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 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct *conn,
36 const SMB_STRUCT_STAT *psbuf);
38 static char *store_file_unix_basic_info2(connection_struct *conn,
41 const SMB_STRUCT_STAT *psbuf);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
50 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type = get_remote_arch();
54 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
55 val = SMB_ROUNDUP(val,rval);
60 /********************************************************************
61 Create a 64 bit FileIndex. If the file is on the same device as
62 the root of the share, just return the 64-bit inode. If it isn't,
63 mangle as we used to do.
64 ********************************************************************/
66 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
69 if (conn->base_share_dev == psbuf->st_ex_dev) {
70 return (uint64_t)psbuf->st_ex_ino;
72 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
73 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
77 /****************************************************************************
78 Utility functions for dealing with extended attributes.
79 ****************************************************************************/
81 /****************************************************************************
82 Refuse to allow clients to overwrite our private xattrs.
83 ****************************************************************************/
85 static bool samba_private_attr_name(const char *unix_ea_name)
87 static const char * const prohibited_ea_names[] = {
88 SAMBA_POSIX_INHERITANCE_EA_NAME,
89 SAMBA_XATTR_DOS_ATTRIB,
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
101 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
102 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
108 /****************************************************************************
109 Get one EA value. Fill in a struct ea_struct.
110 ****************************************************************************/
112 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
113 files_struct *fsp, const char *fname,
114 const char *ea_name, struct ea_struct *pea)
116 /* Get the value of this xattr. Max size is 64k. */
117 size_t attr_size = 256;
123 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
125 return NT_STATUS_NO_MEMORY;
128 if (fsp && fsp->fh->fd != -1) {
129 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
131 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
134 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
140 return map_nt_error_from_unix(errno);
143 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
144 dump_data(10, (uint8 *)val, sizeret);
147 if (strnequal(ea_name, "user.", 5)) {
148 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
150 pea->name = talloc_strdup(mem_ctx, ea_name);
152 if (pea->name == NULL) {
154 return NT_STATUS_NO_MEMORY;
156 pea->value.data = (unsigned char *)val;
157 pea->value.length = (size_t)sizeret;
161 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
162 files_struct *fsp, const char *fname,
163 char ***pnames, size_t *pnum_names)
165 /* Get a list of all xattrs. Max namesize is 64k. */
166 size_t ea_namelist_size = 1024;
167 char *ea_namelist = NULL;
172 ssize_t sizeret = -1;
174 if (!lp_ea_support(SNUM(conn))) {
183 * TALLOC the result early to get the talloc hierarchy right.
186 names = TALLOC_ARRAY(mem_ctx, char *, 1);
188 DEBUG(0, ("talloc failed\n"));
189 return NT_STATUS_NO_MEMORY;
192 while (ea_namelist_size <= 65536) {
194 ea_namelist = TALLOC_REALLOC_ARRAY(
195 names, ea_namelist, char, ea_namelist_size);
196 if (ea_namelist == NULL) {
197 DEBUG(0, ("talloc failed\n"));
199 return NT_STATUS_NO_MEMORY;
202 if (fsp && fsp->fh->fd != -1) {
203 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
206 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
210 if ((sizeret == -1) && (errno == ERANGE)) {
211 ea_namelist_size *= 2;
220 return map_nt_error_from_unix(errno);
223 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
224 (unsigned int)sizeret));
236 * Ensure the result is 0-terminated
239 if (ea_namelist[sizeret-1] != '\0') {
241 return NT_STATUS_INTERNAL_ERROR;
249 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
253 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
255 DEBUG(0, ("talloc failed\n"));
257 return NT_STATUS_NO_MEMORY;
263 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
264 names[num_names++] = p;
272 *pnum_names = num_names;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
286 struct ea_list *ea_list_head = NULL;
291 if (!lp_ea_support(SNUM(conn))) {
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
310 listp = TALLOC_P(mem_ctx, struct ea_list);
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
371 if (ea_list->ea.value.length > 65535) {
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
397 unsigned int total_data_size,
398 unsigned int *ret_data_size,
399 connection_struct *conn,
400 struct ea_list *ea_list)
402 uint8_t *p = (uint8_t *)pdata;
403 uint8_t *last_start = NULL;
407 if (!lp_ea_support(SNUM(conn))) {
408 return NT_STATUS_NO_EAS_ON_FILE;
411 for (; ea_list; ea_list = ea_list->next) {
417 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
421 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
422 dos_namelen = strlen(dos_ea_name);
423 if (dos_namelen > 255 || dos_namelen == 0) {
424 return NT_STATUS_INTERNAL_ERROR;
426 if (ea_list->ea.value.length > 65535) {
427 return NT_STATUS_INTERNAL_ERROR;
430 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
433 size_t pad = 4 - (this_size % 4);
437 if (this_size > total_data_size) {
438 return NT_STATUS_INFO_LENGTH_MISMATCH;
441 /* We know we have room. */
442 SIVAL(p, 0x00, 0); /* next offset */
443 SCVAL(p, 0x04, ea_list->ea.flags);
444 SCVAL(p, 0x05, dos_namelen);
445 SSVAL(p, 0x06, ea_list->ea.value.length);
446 fstrcpy((char *)(p+0x08), dos_ea_name);
447 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
449 total_data_size -= this_size;
453 *ret_data_size = PTR_DIFF(p, pdata);
454 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
458 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
460 size_t total_ea_len = 0;
461 TALLOC_CTX *mem_ctx = NULL;
463 if (!lp_ea_support(SNUM(conn))) {
466 mem_ctx = talloc_tos();
467 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
471 /****************************************************************************
472 Ensure the EA name is case insensitive by matching any existing EA name.
473 ****************************************************************************/
475 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
478 TALLOC_CTX *mem_ctx = talloc_tos();
479 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
481 for (; ea_list; ea_list = ea_list->next) {
482 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
483 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
484 &unix_ea_name[5], ea_list->ea.name));
485 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
491 /****************************************************************************
492 Set or delete an extended attribute.
493 ****************************************************************************/
495 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
496 const struct smb_filename *smb_fname, struct ea_list *ea_list)
500 if (!lp_ea_support(SNUM(conn))) {
501 return NT_STATUS_EAS_NOT_SUPPORTED;
504 /* For now setting EAs on streams isn't supported. */
505 fname = smb_fname->base_name;
507 for (;ea_list; ea_list = ea_list->next) {
509 fstring unix_ea_name;
511 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
512 fstrcat(unix_ea_name, ea_list->ea.name);
514 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
516 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
518 if (samba_private_attr_name(unix_ea_name)) {
519 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
520 return NT_STATUS_ACCESS_DENIED;
523 if (ea_list->ea.value.length == 0) {
524 /* Remove the attribute. */
525 if (fsp && (fsp->fh->fd != -1)) {
526 DEBUG(10,("set_ea: deleting ea name %s on "
527 "file %s by file descriptor.\n",
528 unix_ea_name, fsp_str_dbg(fsp)));
529 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
531 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
532 unix_ea_name, fname));
533 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
536 /* Removing a non existent attribute always succeeds. */
537 if (ret == -1 && errno == ENOATTR) {
538 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
544 if (fsp && (fsp->fh->fd != -1)) {
545 DEBUG(10,("set_ea: setting ea name %s on file "
546 "%s by file descriptor.\n",
547 unix_ea_name, fsp_str_dbg(fsp)));
548 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
549 ea_list->ea.value.data, ea_list->ea.value.length, 0);
551 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
552 unix_ea_name, fname));
553 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
554 ea_list->ea.value.data, ea_list->ea.value.length, 0);
560 if (errno == ENOTSUP) {
561 return NT_STATUS_EAS_NOT_SUPPORTED;
564 return map_nt_error_from_unix(errno);
570 /****************************************************************************
571 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
572 ****************************************************************************/
574 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
576 struct ea_list *ea_list_head = NULL;
577 size_t converted_size, offset = 0;
579 while (offset + 2 < data_size) {
580 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
581 unsigned int namelen = CVAL(pdata,offset);
583 offset++; /* Go past the namelen byte. */
585 /* integer wrap paranioa. */
586 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
587 (offset > data_size) || (namelen > data_size) ||
588 (offset + namelen >= data_size)) {
591 /* Ensure the name is null terminated. */
592 if (pdata[offset + namelen] != '\0') {
595 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
597 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
598 "failed: %s", strerror(errno)));
604 offset += (namelen + 1); /* Go past the name + terminating zero. */
605 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
606 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
612 /****************************************************************************
613 Read one EA list entry from the buffer.
614 ****************************************************************************/
616 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
618 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
620 unsigned int namelen;
621 size_t converted_size;
631 eal->ea.flags = CVAL(pdata,0);
632 namelen = CVAL(pdata,1);
633 val_len = SVAL(pdata,2);
635 if (4 + namelen + 1 + val_len > data_size) {
639 /* Ensure the name is null terminated. */
640 if (pdata[namelen + 4] != '\0') {
643 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
644 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
651 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
652 if (!eal->ea.value.data) {
656 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
658 /* Ensure we're null terminated just in case we print the value. */
659 eal->ea.value.data[val_len] = '\0';
660 /* But don't count the null. */
661 eal->ea.value.length--;
664 *pbytes_used = 4 + namelen + 1 + val_len;
667 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
668 dump_data(10, eal->ea.value.data, eal->ea.value.length);
673 /****************************************************************************
674 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
675 ****************************************************************************/
677 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
679 struct ea_list *ea_list_head = NULL;
681 size_t bytes_used = 0;
683 while (offset < data_size) {
684 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
690 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
691 offset += bytes_used;
697 /****************************************************************************
698 Count the total EA size needed.
699 ****************************************************************************/
701 static size_t ea_list_size(struct ea_list *ealist)
704 struct ea_list *listp;
707 for (listp = ealist; listp; listp = listp->next) {
708 push_ascii_fstring(dos_ea_name, listp->ea.name);
709 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
711 /* Add on 4 for total length. */
719 /****************************************************************************
720 Return a union of EA's from a file list and a list of names.
721 The TALLOC context for the two lists *MUST* be identical as we steal
722 memory from one list to add to another. JRA.
723 ****************************************************************************/
725 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
727 struct ea_list *nlistp, *flistp;
729 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
730 for (flistp = file_list; flistp; flistp = flistp->next) {
731 if (strequal(nlistp->ea.name, flistp->ea.name)) {
737 /* Copy the data from this entry. */
738 nlistp->ea.flags = flistp->ea.flags;
739 nlistp->ea.value = flistp->ea.value;
742 nlistp->ea.flags = 0;
743 ZERO_STRUCT(nlistp->ea.value);
747 *total_ea_len = ea_list_size(name_list);
751 /****************************************************************************
752 Send the required number of replies back.
753 We assume all fields other than the data fields are
754 set correctly for the type of call.
755 HACK ! Always assumes smb_setup field is zero.
756 ****************************************************************************/
758 void send_trans2_replies(connection_struct *conn,
759 struct smb_request *req,
766 /* As we are using a protocol > LANMAN1 then the max_send
767 variable must have been set in the sessetupX call.
768 This takes precedence over the max_xmit field in the
769 global struct. These different max_xmit variables should
770 be merged as this is now too confusing */
772 int data_to_send = datasize;
773 int params_to_send = paramsize;
775 const char *pp = params;
776 const char *pd = pdata;
777 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
778 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
779 int data_alignment_offset = 0;
780 bool overflow = False;
781 struct smbd_server_connection *sconn = smbd_server_conn;
782 int max_send = sconn->smb1.sessions.max_send;
784 /* Modify the data_to_send and datasize and set the error if
785 we're trying to send more than max_data_bytes. We still send
786 the part of the packet(s) that fit. Strange, but needed
789 if (max_data_bytes > 0 && datasize > max_data_bytes) {
790 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
791 max_data_bytes, datasize ));
792 datasize = data_to_send = max_data_bytes;
796 /* If there genuinely are no parameters or data to send just send the empty packet */
798 if(params_to_send == 0 && data_to_send == 0) {
799 reply_outbuf(req, 10, 0);
800 show_msg((char *)req->outbuf);
801 if (!srv_send_smb(smbd_server_fd(),
804 IS_CONN_ENCRYPTED(conn),
806 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
808 TALLOC_FREE(req->outbuf);
812 /* When sending params and data ensure that both are nicely aligned */
813 /* Only do this alignment when there is also data to send - else
814 can cause NT redirector problems. */
816 if (((params_to_send % 4) != 0) && (data_to_send != 0))
817 data_alignment_offset = 4 - (params_to_send % 4);
819 /* Space is bufsize minus Netbios over TCP header minus SMB header */
820 /* The alignment_offset is to align the param bytes on an even byte
821 boundary. NT 4.0 Beta needs this to work correctly. */
823 useable_space = max_send - (smb_size
826 + data_alignment_offset);
828 if (useable_space < 0) {
829 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
830 "= %d!!!", useable_space));
831 exit_server_cleanly("send_trans2_replies: Not enough space");
834 while (params_to_send || data_to_send) {
835 /* Calculate whether we will totally or partially fill this packet */
837 total_sent_thistime = params_to_send + data_to_send;
839 /* We can never send more than useable_space */
841 * Note that 'useable_space' does not include the alignment offsets,
842 * but we must include the alignment offsets in the calculation of
843 * the length of the data we send over the wire, as the alignment offsets
844 * are sent here. Fix from Marc_Jacobsen@hp.com.
847 total_sent_thistime = MIN(total_sent_thistime, useable_space);
849 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
850 + data_alignment_offset);
853 * We might have SMBtrans2s in req which was transferred to
854 * the outbuf, fix that.
856 SCVAL(req->outbuf, smb_com, SMBtrans2);
858 /* Set total params and data to be sent */
859 SSVAL(req->outbuf,smb_tprcnt,paramsize);
860 SSVAL(req->outbuf,smb_tdrcnt,datasize);
862 /* Calculate how many parameters and data we can fit into
863 * this packet. Parameters get precedence
866 params_sent_thistime = MIN(params_to_send,useable_space);
867 data_sent_thistime = useable_space - params_sent_thistime;
868 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
870 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
872 /* smb_proff is the offset from the start of the SMB header to the
873 parameter bytes, however the first 4 bytes of outbuf are
874 the Netbios over TCP header. Thus use smb_base() to subtract
875 them from the calculation */
877 SSVAL(req->outbuf,smb_proff,
878 ((smb_buf(req->outbuf)+alignment_offset)
879 - smb_base(req->outbuf)));
881 if(params_sent_thistime == 0)
882 SSVAL(req->outbuf,smb_prdisp,0);
884 /* Absolute displacement of param bytes sent in this packet */
885 SSVAL(req->outbuf,smb_prdisp,pp - params);
887 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
888 if(data_sent_thistime == 0) {
889 SSVAL(req->outbuf,smb_droff,0);
890 SSVAL(req->outbuf,smb_drdisp, 0);
892 /* The offset of the data bytes is the offset of the
893 parameter bytes plus the number of parameters being sent this time */
894 SSVAL(req->outbuf, smb_droff,
895 ((smb_buf(req->outbuf)+alignment_offset)
896 - smb_base(req->outbuf))
897 + params_sent_thistime + data_alignment_offset);
898 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
901 /* Initialize the padding for alignment */
903 if (alignment_offset != 0) {
904 memset(smb_buf(req->outbuf), 0, alignment_offset);
907 /* Copy the param bytes into the packet */
909 if(params_sent_thistime) {
910 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
911 params_sent_thistime);
914 /* Copy in the data bytes */
915 if(data_sent_thistime) {
916 if (data_alignment_offset != 0) {
917 memset((smb_buf(req->outbuf)+alignment_offset+
918 params_sent_thistime), 0,
919 data_alignment_offset);
921 memcpy(smb_buf(req->outbuf)+alignment_offset
922 +params_sent_thistime+data_alignment_offset,
923 pd,data_sent_thistime);
926 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
927 params_sent_thistime, data_sent_thistime, useable_space));
928 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
929 params_to_send, data_to_send, paramsize, datasize));
932 error_packet_set((char *)req->outbuf,
933 ERRDOS,ERRbufferoverflow,
934 STATUS_BUFFER_OVERFLOW,
938 /* Send the packet */
939 show_msg((char *)req->outbuf);
940 if (!srv_send_smb(smbd_server_fd(),
943 IS_CONN_ENCRYPTED(conn),
945 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
947 TALLOC_FREE(req->outbuf);
949 pp += params_sent_thistime;
950 pd += data_sent_thistime;
952 params_to_send -= params_sent_thistime;
953 data_to_send -= data_sent_thistime;
956 if(params_to_send < 0 || data_to_send < 0) {
957 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
958 params_to_send, data_to_send));
966 /****************************************************************************
967 Reply to a TRANSACT2_OPEN.
968 ****************************************************************************/
970 static void call_trans2open(connection_struct *conn,
971 struct smb_request *req,
972 char **pparams, int total_params,
973 char **ppdata, int total_data,
974 unsigned int max_data_bytes)
976 struct smb_filename *smb_fname = NULL;
977 char *params = *pparams;
978 char *pdata = *ppdata;
983 bool return_additional_info;
996 struct ea_list *ea_list = NULL;
1001 uint32 create_disposition;
1002 uint32 create_options = 0;
1003 TALLOC_CTX *ctx = talloc_tos();
1006 * Ensure we have enough parameters to perform the operation.
1009 if (total_params < 29) {
1010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1014 flags = SVAL(params, 0);
1015 deny_mode = SVAL(params, 2);
1016 open_attr = SVAL(params,6);
1017 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1018 if (oplock_request) {
1019 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1023 return_additional_info = BITSETW(params,0);
1024 open_sattr = SVAL(params, 4);
1025 open_time = make_unix_date3(params+8);
1027 open_ofun = SVAL(params,12);
1028 open_size = IVAL(params,14);
1029 pname = ¶ms[28];
1032 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1036 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1037 total_params - 28, STR_TERMINATE,
1039 if (!NT_STATUS_IS_OK(status)) {
1040 reply_nterror(req, status);
1044 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1045 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1046 (unsigned int)open_ofun, open_size));
1048 status = filename_convert(ctx,
1050 req->flags2 & FLAGS2_DFS_PATHNAMES,
1055 if (!NT_STATUS_IS_OK(status)) {
1056 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1057 reply_botherror(req,
1058 NT_STATUS_PATH_NOT_COVERED,
1059 ERRSRV, ERRbadpath);
1062 reply_nterror(req, status);
1066 if (open_ofun == 0) {
1067 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1071 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1073 &access_mask, &share_mode,
1074 &create_disposition,
1076 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1080 /* Any data in this call is an EA list. */
1081 if (total_data && (total_data != 4)) {
1082 if (total_data < 10) {
1083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1087 if (IVAL(pdata,0) > total_data) {
1088 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1089 IVAL(pdata,0), (unsigned int)total_data));
1090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1094 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1101 if (!lp_ea_support(SNUM(conn))) {
1102 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1107 status = SMB_VFS_CREATE_FILE(
1110 0, /* root_dir_fid */
1111 smb_fname, /* fname */
1112 access_mask, /* access_mask */
1113 share_mode, /* share_access */
1114 create_disposition, /* create_disposition*/
1115 create_options, /* create_options */
1116 open_attr, /* file_attributes */
1117 oplock_request, /* oplock_request */
1118 open_size, /* allocation_size */
1120 ea_list, /* ea_list */
1122 &smb_action); /* psbuf */
1124 if (!NT_STATUS_IS_OK(status)) {
1125 if (open_was_deferred(req->mid)) {
1126 /* We have re-scheduled this call. */
1129 reply_openerror(req, status);
1133 size = get_file_size_stat(&smb_fname->st);
1134 fattr = dos_mode(conn, smb_fname);
1135 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1136 inode = smb_fname->st.st_ex_ino;
1138 close_file(req, fsp, ERROR_CLOSE);
1139 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1143 /* Realloc the size of parameters and data we will return */
1144 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1145 if(*pparams == NULL ) {
1146 reply_nterror(req, NT_STATUS_NO_MEMORY);
1151 SSVAL(params,0,fsp->fnum);
1152 SSVAL(params,2,fattr);
1153 srv_put_dos_date2(params,4, mtime);
1154 SIVAL(params,8, (uint32)size);
1155 SSVAL(params,12,deny_mode);
1156 SSVAL(params,14,0); /* open_type - file or directory. */
1157 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1159 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1160 smb_action |= EXTENDED_OPLOCK_GRANTED;
1163 SSVAL(params,18,smb_action);
1166 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1168 SIVAL(params,20,inode);
1169 SSVAL(params,24,0); /* Padding. */
1171 uint32 ea_size = estimate_ea_size(conn, fsp,
1172 fsp->fsp_name->base_name);
1173 SIVAL(params, 26, ea_size);
1175 SIVAL(params, 26, 0);
1178 /* Send the required number of replies */
1179 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1181 TALLOC_FREE(smb_fname);
1184 /*********************************************************
1185 Routine to check if a given string matches exactly.
1186 as a special case a mask of "." does NOT match. That
1187 is required for correct wildcard semantics
1188 Case can be significant or not.
1189 **********************************************************/
1191 static bool exact_match(bool has_wild,
1192 bool case_sensitive,
1196 if (mask[0] == '.' && mask[1] == 0) {
1204 if (case_sensitive) {
1205 return strcmp(str,mask)==0;
1207 return StrCaseCmp(str,mask) == 0;
1211 /****************************************************************************
1212 Return the filetype for UNIX extensions.
1213 ****************************************************************************/
1215 static uint32 unix_filetype(mode_t mode)
1218 return UNIX_TYPE_FILE;
1219 else if(S_ISDIR(mode))
1220 return UNIX_TYPE_DIR;
1222 else if(S_ISLNK(mode))
1223 return UNIX_TYPE_SYMLINK;
1226 else if(S_ISCHR(mode))
1227 return UNIX_TYPE_CHARDEV;
1230 else if(S_ISBLK(mode))
1231 return UNIX_TYPE_BLKDEV;
1234 else if(S_ISFIFO(mode))
1235 return UNIX_TYPE_FIFO;
1238 else if(S_ISSOCK(mode))
1239 return UNIX_TYPE_SOCKET;
1242 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1243 return UNIX_TYPE_UNKNOWN;
1246 /****************************************************************************
1247 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1248 ****************************************************************************/
1250 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1252 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1253 const SMB_STRUCT_STAT *psbuf,
1255 enum perm_type ptype,
1260 if (perms == SMB_MODE_NO_CHANGE) {
1261 if (!VALID_STAT(*psbuf)) {
1262 return NT_STATUS_INVALID_PARAMETER;
1264 *ret_perms = psbuf->st_ex_mode;
1265 return NT_STATUS_OK;
1269 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1270 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1271 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1272 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1273 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1274 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1275 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1276 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1277 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1279 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1282 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1285 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1290 /* Apply mode mask */
1291 ret &= lp_create_mask(SNUM(conn));
1292 /* Add in force bits */
1293 ret |= lp_force_create_mode(SNUM(conn));
1296 ret &= lp_dir_mask(SNUM(conn));
1297 /* Add in force bits */
1298 ret |= lp_force_dir_mode(SNUM(conn));
1300 case PERM_EXISTING_FILE:
1301 /* Apply mode mask */
1302 ret &= lp_security_mask(SNUM(conn));
1303 /* Add in force bits */
1304 ret |= lp_force_security_mode(SNUM(conn));
1306 case PERM_EXISTING_DIR:
1307 /* Apply mode mask */
1308 ret &= lp_dir_security_mask(SNUM(conn));
1309 /* Add in force bits */
1310 ret |= lp_force_dir_security_mode(SNUM(conn));
1315 return NT_STATUS_OK;
1318 /****************************************************************************
1319 Needed to show the msdfs symlinks as directories. Modifies psbuf
1320 to be a directory if it's a msdfs link.
1321 ****************************************************************************/
1323 static bool check_msdfs_link(connection_struct *conn,
1324 const char *pathname,
1325 SMB_STRUCT_STAT *psbuf)
1327 int saved_errno = errno;
1328 if(lp_host_msdfs() &&
1329 lp_msdfs_root(SNUM(conn)) &&
1330 is_msdfs_link(conn, pathname, psbuf)) {
1332 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1335 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1336 errno = saved_errno;
1339 errno = saved_errno;
1344 /****************************************************************************
1345 Get a level dependent lanman2 dir entry.
1346 ****************************************************************************/
1348 struct smbd_dirptr_lanman2_state {
1349 connection_struct *conn;
1350 uint32_t info_level;
1351 bool check_mangled_names;
1353 bool got_exact_match;
1356 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1362 struct smbd_dirptr_lanman2_state *state =
1363 (struct smbd_dirptr_lanman2_state *)private_data;
1365 char mangled_name[13]; /* mangled 8.3 name. */
1369 /* Mangle fname if it's an illegal name. */
1370 if (mangle_must_mangle(dname, state->conn->params)) {
1371 ok = name_to_8_3(dname, mangled_name,
1372 true, state->conn->params);
1376 fname = mangled_name;
1381 got_match = exact_match(state->has_wild,
1382 state->conn->case_sensitive,
1384 state->got_exact_match = got_match;
1386 got_match = mask_match(fname, mask,
1387 state->conn->case_sensitive);
1390 if(!got_match && state->check_mangled_names &&
1391 !mangle_is_8_3(fname, false, state->conn->params)) {
1393 * It turns out that NT matches wildcards against
1394 * both long *and* short names. This may explain some
1395 * of the wildcard wierdness from old DOS clients
1396 * that some people have been seeing.... JRA.
1398 /* Force the mangling into 8.3. */
1399 ok = name_to_8_3(fname, mangled_name,
1400 false, state->conn->params);
1405 got_match = exact_match(state->has_wild,
1406 state->conn->case_sensitive,
1407 mangled_name, mask);
1408 state->got_exact_match = got_match;
1410 got_match = mask_match(mangled_name, mask,
1411 state->conn->case_sensitive);
1419 *_fname = talloc_strdup(ctx, fname);
1420 if (*_fname == NULL) {
1427 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1429 struct smb_filename *smb_fname,
1432 struct smbd_dirptr_lanman2_state *state =
1433 (struct smbd_dirptr_lanman2_state *)private_data;
1434 bool ms_dfs_link = false;
1437 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1438 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1439 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1440 "Couldn't lstat [%s] (%s)\n",
1441 smb_fname_str_dbg(smb_fname),
1445 } else if (!VALID_STAT(smb_fname->st) &&
1446 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1447 /* Needed to show the msdfs symlinks as
1450 ms_dfs_link = check_msdfs_link(state->conn,
1451 smb_fname->base_name,
1454 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1455 "Couldn't stat [%s] (%s)\n",
1456 smb_fname_str_dbg(smb_fname),
1463 mode = dos_mode_msdfs(state->conn, smb_fname);
1465 mode = dos_mode(state->conn, smb_fname);
1472 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1473 connection_struct *conn,
1475 uint32_t info_level,
1476 struct ea_list *name_list,
1477 bool check_mangled_names,
1478 bool requires_resume_key,
1481 const struct smb_filename *smb_fname,
1482 uint64_t space_remaining,
1489 uint64_t *last_entry_off)
1491 char *p, *q, *pdata = *ppdata;
1493 uint64_t file_size = 0;
1494 uint64_t allocation_size = 0;
1495 uint64_t file_index = 0;
1497 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1498 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1499 time_t c_date = (time_t)0;
1501 char *last_entry_ptr;
1506 *out_of_space = false;
1508 ZERO_STRUCT(mdate_ts);
1509 ZERO_STRUCT(adate_ts);
1510 ZERO_STRUCT(create_date_ts);
1511 ZERO_STRUCT(cdate_ts);
1513 if (!(mode & aDIR)) {
1514 file_size = get_file_size_stat(&smb_fname->st);
1516 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1518 file_index = get_FileIndex(conn, &smb_fname->st);
1520 mdate_ts = smb_fname->st.st_ex_mtime;
1521 adate_ts = smb_fname->st.st_ex_atime;
1522 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1523 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1525 if (lp_dos_filetime_resolution(SNUM(conn))) {
1526 dos_filetime_timespec(&create_date_ts);
1527 dos_filetime_timespec(&mdate_ts);
1528 dos_filetime_timespec(&adate_ts);
1529 dos_filetime_timespec(&cdate_ts);
1532 create_date = convert_timespec_to_time_t(create_date_ts);
1533 mdate = convert_timespec_to_time_t(mdate_ts);
1534 adate = convert_timespec_to_time_t(adate_ts);
1535 c_date = convert_timespec_to_time_t(cdate_ts);
1537 /* align the record */
1538 off = PTR_DIFF(pdata, base_data);
1539 pad = (off + (align-1)) & ~(align-1);
1542 /* initialize padding to 0 */
1544 memset(pdata, 0, pad);
1546 space_remaining -= pad;
1555 switch (info_level) {
1556 case SMB_FIND_INFO_STANDARD:
1557 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1558 if(requires_resume_key) {
1562 srv_put_dos_date2(p,0,create_date);
1563 srv_put_dos_date2(p,4,adate);
1564 srv_put_dos_date2(p,8,mdate);
1565 SIVAL(p,12,(uint32)file_size);
1566 SIVAL(p,16,(uint32)allocation_size);
1570 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1571 p += ucs2_align(base_data, p, 0);
1573 len = srvstr_push(base_data, flags2, p,
1574 fname, PTR_DIFF(end_data, p),
1576 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 SCVAL(nameptr, -1, len - 2);
1580 SCVAL(nameptr, -1, 0);
1584 SCVAL(nameptr, -1, len - 1);
1586 SCVAL(nameptr, -1, 0);
1592 case SMB_FIND_EA_SIZE:
1593 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1594 if (requires_resume_key) {
1598 srv_put_dos_date2(p,0,create_date);
1599 srv_put_dos_date2(p,4,adate);
1600 srv_put_dos_date2(p,8,mdate);
1601 SIVAL(p,12,(uint32)file_size);
1602 SIVAL(p,16,(uint32)allocation_size);
1605 unsigned int ea_size = estimate_ea_size(conn, NULL,
1606 smb_fname->base_name);
1607 SIVAL(p,22,ea_size); /* Extended attributes */
1611 len = srvstr_push(base_data, flags2,
1612 p, fname, PTR_DIFF(end_data, p),
1613 STR_TERMINATE | STR_NOALIGN);
1614 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1627 SCVAL(nameptr,0,len);
1629 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1632 case SMB_FIND_EA_LIST:
1634 struct ea_list *file_list = NULL;
1637 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1641 if (requires_resume_key) {
1645 srv_put_dos_date2(p,0,create_date);
1646 srv_put_dos_date2(p,4,adate);
1647 srv_put_dos_date2(p,8,mdate);
1648 SIVAL(p,12,(uint32)file_size);
1649 SIVAL(p,16,(uint32)allocation_size);
1651 p += 22; /* p now points to the EA area. */
1653 file_list = get_ea_list_from_file(ctx, conn, NULL,
1654 smb_fname->base_name,
1656 name_list = ea_list_union(name_list, file_list, &ea_len);
1658 /* We need to determine if this entry will fit in the space available. */
1659 /* Max string size is 255 bytes. */
1660 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1661 *out_of_space = true;
1662 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1663 return False; /* Not finished - just out of space */
1666 /* Push the ea_data followed by the name. */
1667 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1669 len = srvstr_push(base_data, flags2,
1670 p + 1, fname, PTR_DIFF(end_data, p+1),
1671 STR_TERMINATE | STR_NOALIGN);
1672 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1685 SCVAL(nameptr,0,len);
1687 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1691 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1692 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1693 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1695 SIVAL(p,0,reskey); p += 4;
1696 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1697 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1698 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1699 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1700 SOFF_T(p,0,file_size); p += 8;
1701 SOFF_T(p,0,allocation_size); p += 8;
1702 SIVAL(p,0,mode); p += 4;
1703 q = p; p += 4; /* q is placeholder for name length. */
1705 unsigned int ea_size = estimate_ea_size(conn, NULL,
1706 smb_fname->base_name);
1707 SIVAL(p,0,ea_size); /* Extended attributes */
1710 /* Clear the short name buffer. This is
1711 * IMPORTANT as not doing so will trigger
1712 * a Win2k client bug. JRA.
1714 if (!was_8_3 && check_mangled_names) {
1715 char mangled_name[13]; /* mangled 8.3 name. */
1716 if (!name_to_8_3(fname,mangled_name,True,
1718 /* Error - mangle failed ! */
1719 memset(mangled_name,'\0',12);
1721 mangled_name[12] = 0;
1722 len = srvstr_push(base_data, flags2,
1723 p+2, mangled_name, 24,
1724 STR_UPPER|STR_UNICODE);
1726 memset(p + 2 + len,'\0',24 - len);
1733 len = srvstr_push(base_data, flags2, p,
1734 fname, PTR_DIFF(end_data, p),
1735 STR_TERMINATE_ASCII);
1739 len = PTR_DIFF(p, pdata);
1740 pad = (len + (align-1)) & ~(align-1);
1742 * offset to the next entry, the caller
1743 * will overwrite it for the last entry
1744 * that's why we always include the padding
1748 * set padding to zero
1751 memset(p, 0, pad - len);
1758 case SMB_FIND_FILE_DIRECTORY_INFO:
1759 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1761 SIVAL(p,0,reskey); p += 4;
1762 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1763 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1764 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1765 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1766 SOFF_T(p,0,file_size); p += 8;
1767 SOFF_T(p,0,allocation_size); p += 8;
1768 SIVAL(p,0,mode); p += 4;
1769 len = srvstr_push(base_data, flags2,
1770 p + 4, fname, PTR_DIFF(end_data, p+4),
1771 STR_TERMINATE_ASCII);
1775 len = PTR_DIFF(p, pdata);
1776 pad = (len + (align-1)) & ~(align-1);
1778 * offset to the next entry, the caller
1779 * will overwrite it for the last entry
1780 * that's why we always include the padding
1784 * set padding to zero
1787 memset(p, 0, pad - len);
1794 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1795 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1797 SIVAL(p,0,reskey); p += 4;
1798 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1799 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1800 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1801 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1802 SOFF_T(p,0,file_size); p += 8;
1803 SOFF_T(p,0,allocation_size); p += 8;
1804 SIVAL(p,0,mode); p += 4;
1805 q = p; p += 4; /* q is placeholder for name length. */
1807 unsigned int ea_size = estimate_ea_size(conn, NULL,
1808 smb_fname->base_name);
1809 SIVAL(p,0,ea_size); /* Extended attributes */
1812 len = srvstr_push(base_data, flags2, p,
1813 fname, PTR_DIFF(end_data, p),
1814 STR_TERMINATE_ASCII);
1818 len = PTR_DIFF(p, pdata);
1819 pad = (len + (align-1)) & ~(align-1);
1821 * offset to the next entry, the caller
1822 * will overwrite it for the last entry
1823 * that's why we always include the padding
1827 * set padding to zero
1830 memset(p, 0, pad - len);
1837 case SMB_FIND_FILE_NAMES_INFO:
1838 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1840 SIVAL(p,0,reskey); p += 4;
1842 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1843 acl on a dir (tridge) */
1844 len = srvstr_push(base_data, flags2, p,
1845 fname, PTR_DIFF(end_data, p),
1846 STR_TERMINATE_ASCII);
1850 len = PTR_DIFF(p, pdata);
1851 pad = (len + (align-1)) & ~(align-1);
1853 * offset to the next entry, the caller
1854 * will overwrite it for the last entry
1855 * that's why we always include the padding
1859 * set padding to zero
1862 memset(p, 0, pad - len);
1869 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1870 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1872 SIVAL(p,0,reskey); p += 4;
1873 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1874 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1876 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1877 SOFF_T(p,0,file_size); p += 8;
1878 SOFF_T(p,0,allocation_size); p += 8;
1879 SIVAL(p,0,mode); p += 4;
1880 q = p; p += 4; /* q is placeholder for name length. */
1882 unsigned int ea_size = estimate_ea_size(conn, NULL,
1883 smb_fname->base_name);
1884 SIVAL(p,0,ea_size); /* Extended attributes */
1887 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1888 SBVAL(p,0,file_index); p += 8;
1889 len = srvstr_push(base_data, flags2, p,
1890 fname, PTR_DIFF(end_data, p),
1891 STR_TERMINATE_ASCII);
1895 len = PTR_DIFF(p, pdata);
1896 pad = (len + (align-1)) & ~(align-1);
1898 * offset to the next entry, the caller
1899 * will overwrite it for the last entry
1900 * that's why we always include the padding
1904 * set padding to zero
1907 memset(p, 0, pad - len);
1914 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1915 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1916 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1918 SIVAL(p,0,reskey); p += 4;
1919 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1923 SOFF_T(p,0,file_size); p += 8;
1924 SOFF_T(p,0,allocation_size); p += 8;
1925 SIVAL(p,0,mode); p += 4;
1926 q = p; p += 4; /* q is placeholder for name length */
1928 unsigned int ea_size = estimate_ea_size(conn, NULL,
1929 smb_fname->base_name);
1930 SIVAL(p,0,ea_size); /* Extended attributes */
1933 /* Clear the short name buffer. This is
1934 * IMPORTANT as not doing so will trigger
1935 * a Win2k client bug. JRA.
1937 if (!was_8_3 && check_mangled_names) {
1938 char mangled_name[13]; /* mangled 8.3 name. */
1939 if (!name_to_8_3(fname,mangled_name,True,
1941 /* Error - mangle failed ! */
1942 memset(mangled_name,'\0',12);
1944 mangled_name[12] = 0;
1945 len = srvstr_push(base_data, flags2,
1946 p+2, mangled_name, 24,
1947 STR_UPPER|STR_UNICODE);
1950 memset(p + 2 + len,'\0',24 - len);
1957 SSVAL(p,0,0); p += 2; /* Reserved ? */
1958 SBVAL(p,0,file_index); p += 8;
1959 len = srvstr_push(base_data, flags2, p,
1960 fname, PTR_DIFF(end_data, p),
1961 STR_TERMINATE_ASCII);
1965 len = PTR_DIFF(p, pdata);
1966 pad = (len + (align-1)) & ~(align-1);
1968 * offset to the next entry, the caller
1969 * will overwrite it for the last entry
1970 * that's why we always include the padding
1974 * set padding to zero
1977 memset(p, 0, pad - len);
1984 /* CIFS UNIX Extension. */
1986 case SMB_FIND_FILE_UNIX:
1987 case SMB_FIND_FILE_UNIX_INFO2:
1989 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1991 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1993 if (info_level == SMB_FIND_FILE_UNIX) {
1994 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1995 p = store_file_unix_basic(conn, p,
1996 NULL, &smb_fname->st);
1997 len = srvstr_push(base_data, flags2, p,
1998 fname, PTR_DIFF(end_data, p),
2001 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2002 p = store_file_unix_basic_info2(conn, p,
2003 NULL, &smb_fname->st);
2006 len = srvstr_push(base_data, flags2, p, fname,
2007 PTR_DIFF(end_data, p), 0);
2008 SIVAL(nameptr, 0, len);
2013 len = PTR_DIFF(p, pdata);
2014 pad = (len + (align-1)) & ~(align-1);
2016 * offset to the next entry, the caller
2017 * will overwrite it for the last entry
2018 * that's why we always include the padding
2022 * set padding to zero
2025 memset(p, 0, pad - len);
2030 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2038 if (PTR_DIFF(p,pdata) > space_remaining) {
2039 *out_of_space = true;
2040 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2041 return false; /* Not finished - just out of space */
2044 /* Setup the last entry pointer, as an offset from base_data */
2045 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2046 /* Advance the data pointer to the next slot */
2052 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2053 connection_struct *conn,
2054 struct dptr_struct *dirptr,
2056 const char *path_mask,
2059 int requires_resume_key,
2067 int space_remaining,
2069 bool *got_exact_match,
2070 int *_last_entry_off,
2071 struct ea_list *name_list)
2074 const char *mask = NULL;
2075 long prev_dirpos = 0;
2078 struct smb_filename *smb_fname = NULL;
2079 struct smbd_dirptr_lanman2_state state;
2081 uint64_t last_entry_off = 0;
2085 state.info_level = info_level;
2086 state.check_mangled_names = lp_manglednames(conn->params);
2087 state.has_wild = dptr_has_wild(dirptr);
2088 state.got_exact_match = false;
2090 *out_of_space = false;
2091 *got_exact_match = false;
2093 p = strrchr_m(path_mask,'/');
2104 ok = smbd_dirptr_get_entry(ctx,
2110 smbd_dirptr_lanman2_match_fn,
2111 smbd_dirptr_lanman2_mode_fn,
2121 *got_exact_match = state.got_exact_match;
2123 ok = smbd_marshall_dir_entry(ctx,
2128 state.check_mangled_names,
2129 requires_resume_key,
2142 TALLOC_FREE(smb_fname);
2143 if (*out_of_space) {
2144 dptr_SeekDir(dirptr, prev_dirpos);
2151 *_last_entry_off = last_entry_off;
2155 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2156 connection_struct *conn,
2157 struct dptr_struct *dirptr,
2159 const char *path_mask,
2162 bool requires_resume_key,
2168 int space_remaining,
2170 bool *got_exact_match,
2171 int *last_entry_off,
2172 struct ea_list *name_list)
2175 const bool do_pad = true;
2177 if (info_level >= 1 && info_level <= 3) {
2178 /* No alignment on earlier info levels. */
2182 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2183 path_mask, dirtype, info_level,
2184 requires_resume_key, dont_descend, ask_sharemode,
2186 ppdata, base_data, end_data,
2188 out_of_space, got_exact_match,
2189 last_entry_off, name_list);
2192 /****************************************************************************
2193 Reply to a TRANS2_FINDFIRST.
2194 ****************************************************************************/
2196 static void call_trans2findfirst(connection_struct *conn,
2197 struct smb_request *req,
2198 char **pparams, int total_params,
2199 char **ppdata, int total_data,
2200 unsigned int max_data_bytes)
2202 /* We must be careful here that we don't return more than the
2203 allowed number of data bytes. If this means returning fewer than
2204 maxentries then so be it. We assume that the redirector has
2205 enough room for the fixed number of parameter bytes it has
2207 struct smb_filename *smb_dname = NULL;
2208 char *params = *pparams;
2209 char *pdata = *ppdata;
2213 uint16 findfirst_flags;
2214 bool close_after_first;
2216 bool requires_resume_key;
2218 char *directory = NULL;
2221 int last_entry_off=0;
2225 bool finished = False;
2226 bool dont_descend = False;
2227 bool out_of_space = False;
2228 int space_remaining;
2229 bool mask_contains_wcard = False;
2230 struct ea_list *ea_list = NULL;
2231 NTSTATUS ntstatus = NT_STATUS_OK;
2232 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2233 TALLOC_CTX *ctx = talloc_tos();
2234 struct dptr_struct *dirptr = NULL;
2235 struct smbd_server_connection *sconn = smbd_server_conn;
2236 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2238 if (total_params < 13) {
2239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2243 dirtype = SVAL(params,0);
2244 maxentries = SVAL(params,2);
2245 findfirst_flags = SVAL(params,4);
2246 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2247 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2248 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2249 info_level = SVAL(params,6);
2251 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2252 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2253 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2254 info_level, max_data_bytes));
2257 /* W2K3 seems to treat zero as 1. */
2261 switch (info_level) {
2262 case SMB_FIND_INFO_STANDARD:
2263 case SMB_FIND_EA_SIZE:
2264 case SMB_FIND_EA_LIST:
2265 case SMB_FIND_FILE_DIRECTORY_INFO:
2266 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2267 case SMB_FIND_FILE_NAMES_INFO:
2268 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2269 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2270 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2272 case SMB_FIND_FILE_UNIX:
2273 case SMB_FIND_FILE_UNIX_INFO2:
2274 /* Always use filesystem for UNIX mtime query. */
2275 ask_sharemode = false;
2276 if (!lp_unix_extensions()) {
2277 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2280 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2283 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2287 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2288 params+12, total_params - 12,
2289 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2290 if (!NT_STATUS_IS_OK(ntstatus)) {
2291 reply_nterror(req, ntstatus);
2295 ntstatus = filename_convert(ctx, conn,
2296 req->flags2 & FLAGS2_DFS_PATHNAMES,
2299 &mask_contains_wcard,
2301 if (!NT_STATUS_IS_OK(ntstatus)) {
2302 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2303 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2304 ERRSRV, ERRbadpath);
2307 reply_nterror(req, ntstatus);
2311 mask = smb_dname->original_lcomp;
2313 directory = smb_dname->base_name;
2315 p = strrchr_m(directory,'/');
2317 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2318 if((directory[0] == '.') && (directory[1] == '\0')) {
2319 mask = talloc_strdup(ctx,"*");
2321 reply_nterror(req, NT_STATUS_NO_MEMORY);
2324 mask_contains_wcard = True;
2326 directory = talloc_strdup(talloc_tos(), "./");
2328 reply_nterror(req, NT_STATUS_NO_MEMORY);
2335 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2337 if (info_level == SMB_FIND_EA_LIST) {
2340 if (total_data < 4) {
2341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2345 ea_size = IVAL(pdata,0);
2346 if (ea_size != total_data) {
2347 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2348 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2353 if (!lp_ea_support(SNUM(conn))) {
2354 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2358 /* Pull out the list of names. */
2359 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2366 *ppdata = (char *)SMB_REALLOC(
2367 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2368 if(*ppdata == NULL ) {
2369 reply_nterror(req, NT_STATUS_NO_MEMORY);
2373 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2375 /* Realloc the params space */
2376 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2377 if (*pparams == NULL) {
2378 reply_nterror(req, NT_STATUS_NO_MEMORY);
2383 /* Save the wildcard match and attribs we are using on this directory -
2384 needed as lanman2 assumes these are being saved between calls */
2386 ntstatus = dptr_create(conn,
2392 mask_contains_wcard,
2396 if (!NT_STATUS_IS_OK(ntstatus)) {
2397 reply_nterror(req, ntstatus);
2401 dptr_num = dptr_dnum(dirptr);
2402 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2404 /* Initialize per TRANS2_FIND_FIRST operation data */
2405 dptr_init_search_op(dirptr);
2407 /* We don't need to check for VOL here as this is returned by
2408 a different TRANS2 call. */
2410 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2411 directory,lp_dontdescend(SNUM(conn))));
2412 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2413 dont_descend = True;
2416 space_remaining = max_data_bytes;
2417 out_of_space = False;
2419 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2420 bool got_exact_match = False;
2422 /* this is a heuristic to avoid seeking the dirptr except when
2423 absolutely necessary. It allows for a filename of about 40 chars */
2424 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2425 out_of_space = True;
2428 finished = !get_lanman2_dir_entry(ctx,
2432 mask,dirtype,info_level,
2433 requires_resume_key,dont_descend,
2436 space_remaining, &out_of_space,
2438 &last_entry_off, ea_list);
2441 if (finished && out_of_space)
2444 if (!finished && !out_of_space)
2448 * As an optimisation if we know we aren't looking
2449 * for a wildcard name (ie. the name matches the wildcard exactly)
2450 * then we can finish on any (first) match.
2451 * This speeds up large directory searches. JRA.
2457 /* Ensure space_remaining never goes -ve. */
2458 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2459 space_remaining = 0;
2460 out_of_space = true;
2462 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2466 /* Check if we can close the dirptr */
2467 if(close_after_first || (finished && close_if_end)) {
2468 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2469 dptr_close(sconn, &dptr_num);
2473 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2474 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2475 * the protocol level is less than NT1. Tested with smbclient. JRA.
2476 * This should fix the OS/2 client bug #2335.
2479 if(numentries == 0) {
2480 dptr_close(sconn, &dptr_num);
2481 if (get_Protocol() < PROTOCOL_NT1) {
2482 reply_force_doserror(req, ERRDOS, ERRnofiles);
2485 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2486 ERRDOS, ERRbadfile);
2491 /* At this point pdata points to numentries directory entries. */
2493 /* Set up the return parameter block */
2494 SSVAL(params,0,dptr_num);
2495 SSVAL(params,2,numentries);
2496 SSVAL(params,4,finished);
2497 SSVAL(params,6,0); /* Never an EA error */
2498 SSVAL(params,8,last_entry_off);
2500 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2503 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2504 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2506 reply_nterror(req, NT_STATUS_NO_MEMORY);
2510 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2511 smb_fn_name(req->cmd),
2512 mask, directory, dirtype, numentries ) );
2515 * Force a name mangle here to ensure that the
2516 * mask as an 8.3 name is top of the mangled cache.
2517 * The reasons for this are subtle. Don't remove
2518 * this code unless you know what you are doing
2519 * (see PR#13758). JRA.
2522 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2523 char mangled_name[13];
2524 name_to_8_3(mask, mangled_name, True, conn->params);
2527 TALLOC_FREE(smb_dname);
2531 /****************************************************************************
2532 Reply to a TRANS2_FINDNEXT.
2533 ****************************************************************************/
2535 static void call_trans2findnext(connection_struct *conn,
2536 struct smb_request *req,
2537 char **pparams, int total_params,
2538 char **ppdata, int total_data,
2539 unsigned int max_data_bytes)
2541 /* We must be careful here that we don't return more than the
2542 allowed number of data bytes. If this means returning fewer than
2543 maxentries then so be it. We assume that the redirector has
2544 enough room for the fixed number of parameter bytes it has
2546 char *params = *pparams;
2547 char *pdata = *ppdata;
2553 uint16 findnext_flags;
2554 bool close_after_request;
2556 bool requires_resume_key;
2558 bool mask_contains_wcard = False;
2559 char *resume_name = NULL;
2560 const char *mask = NULL;
2561 const char *directory = NULL;
2565 int i, last_entry_off=0;
2566 bool finished = False;
2567 bool dont_descend = False;
2568 bool out_of_space = False;
2569 int space_remaining;
2570 struct ea_list *ea_list = NULL;
2571 NTSTATUS ntstatus = NT_STATUS_OK;
2572 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2573 TALLOC_CTX *ctx = talloc_tos();
2574 struct dptr_struct *dirptr;
2575 struct smbd_server_connection *sconn = smbd_server_conn;
2577 if (total_params < 13) {
2578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2582 dptr_num = SVAL(params,0);
2583 maxentries = SVAL(params,2);
2584 info_level = SVAL(params,4);
2585 resume_key = IVAL(params,6);
2586 findnext_flags = SVAL(params,10);
2587 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2588 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2589 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2590 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2592 if (!continue_bit) {
2593 /* We only need resume_name if continue_bit is zero. */
2594 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2596 total_params - 12, STR_TERMINATE, &ntstatus,
2597 &mask_contains_wcard);
2598 if (!NT_STATUS_IS_OK(ntstatus)) {
2599 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2600 complain (it thinks we're asking for the directory above the shared
2601 path or an invalid name). Catch this as the resume name is only compared, never used in
2602 a file access. JRA. */
2603 srvstr_pull_talloc(ctx, params, req->flags2,
2604 &resume_name, params+12,
2608 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2609 reply_nterror(req, ntstatus);
2615 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2616 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2617 resume_key = %d resume name = %s continue=%d level = %d\n",
2618 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2619 requires_resume_key, resume_key,
2620 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2623 /* W2K3 seems to treat zero as 1. */
2627 switch (info_level) {
2628 case SMB_FIND_INFO_STANDARD:
2629 case SMB_FIND_EA_SIZE:
2630 case SMB_FIND_EA_LIST:
2631 case SMB_FIND_FILE_DIRECTORY_INFO:
2632 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2633 case SMB_FIND_FILE_NAMES_INFO:
2634 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2635 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2636 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2638 case SMB_FIND_FILE_UNIX:
2639 case SMB_FIND_FILE_UNIX_INFO2:
2640 /* Always use filesystem for UNIX mtime query. */
2641 ask_sharemode = false;
2642 if (!lp_unix_extensions()) {
2643 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2648 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2652 if (info_level == SMB_FIND_EA_LIST) {
2655 if (total_data < 4) {
2656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2660 ea_size = IVAL(pdata,0);
2661 if (ea_size != total_data) {
2662 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2663 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2668 if (!lp_ea_support(SNUM(conn))) {
2669 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2673 /* Pull out the list of names. */
2674 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2681 *ppdata = (char *)SMB_REALLOC(
2682 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2683 if(*ppdata == NULL) {
2684 reply_nterror(req, NT_STATUS_NO_MEMORY);
2689 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2691 /* Realloc the params space */
2692 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2693 if(*pparams == NULL ) {
2694 reply_nterror(req, NT_STATUS_NO_MEMORY);
2700 /* Check that the dptr is valid */
2701 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2702 reply_nterror(req, STATUS_NO_MORE_FILES);
2706 directory = dptr_path(sconn, dptr_num);
2708 /* Get the wildcard mask from the dptr */
2709 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2710 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2711 reply_nterror(req, STATUS_NO_MORE_FILES);
2717 /* Get the attr mask from the dptr */
2718 dirtype = dptr_attr(sconn, dptr_num);
2720 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2721 dptr_num, mask, dirtype,
2723 dptr_TellDir(dirptr)));
2725 /* Initialize per TRANS2_FIND_NEXT operation data */
2726 dptr_init_search_op(dirptr);
2728 /* We don't need to check for VOL here as this is returned by
2729 a different TRANS2 call. */
2731 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2732 directory,lp_dontdescend(SNUM(conn))));
2733 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2734 dont_descend = True;
2737 space_remaining = max_data_bytes;
2738 out_of_space = False;
2741 * Seek to the correct position. We no longer use the resume key but
2742 * depend on the last file name instead.
2745 if(!continue_bit && resume_name && *resume_name) {
2748 long current_pos = 0;
2750 * Remember, name_to_8_3 is called by
2751 * get_lanman2_dir_entry(), so the resume name
2752 * could be mangled. Ensure we check the unmangled name.
2755 if (mangle_is_mangled(resume_name, conn->params)) {
2756 char *new_resume_name = NULL;
2757 mangle_lookup_name_from_8_3(ctx,
2761 if (new_resume_name) {
2762 resume_name = new_resume_name;
2767 * Fix for NT redirector problem triggered by resume key indexes
2768 * changing between directory scans. We now return a resume key of 0
2769 * and instead look for the filename to continue from (also given
2770 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2771 * findfirst/findnext (as is usual) then the directory pointer
2772 * should already be at the correct place.
2775 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2776 } /* end if resume_name && !continue_bit */
2778 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2779 bool got_exact_match = False;
2781 /* this is a heuristic to avoid seeking the dirptr except when
2782 absolutely necessary. It allows for a filename of about 40 chars */
2783 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2784 out_of_space = True;
2787 finished = !get_lanman2_dir_entry(ctx,
2791 mask,dirtype,info_level,
2792 requires_resume_key,dont_descend,
2795 space_remaining, &out_of_space,
2797 &last_entry_off, ea_list);
2800 if (finished && out_of_space)
2803 if (!finished && !out_of_space)
2807 * As an optimisation if we know we aren't looking
2808 * for a wildcard name (ie. the name matches the wildcard exactly)
2809 * then we can finish on any (first) match.
2810 * This speeds up large directory searches. JRA.
2816 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2819 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2820 smb_fn_name(req->cmd),
2821 mask, directory, dirtype, numentries ) );
2823 /* Check if we can close the dirptr */
2824 if(close_after_request || (finished && close_if_end)) {
2825 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2826 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2829 /* Set up the return parameter block */
2830 SSVAL(params,0,numentries);
2831 SSVAL(params,2,finished);
2832 SSVAL(params,4,0); /* Never an EA error */
2833 SSVAL(params,6,last_entry_off);
2835 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2841 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2843 E_md4hash(lp_servicename(SNUM(conn)),objid);
2847 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2849 SMB_ASSERT(extended_info != NULL);
2851 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2852 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2853 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2854 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2855 #ifdef SAMBA_VERSION_REVISION
2856 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2858 extended_info->samba_subversion = 0;
2859 #ifdef SAMBA_VERSION_RC_RELEASE
2860 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2862 #ifdef SAMBA_VERSION_PRE_RELEASE
2863 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2866 #ifdef SAMBA_VERSION_VENDOR_PATCH
2867 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2869 extended_info->samba_gitcommitdate = 0;
2870 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2871 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2874 memset(extended_info->samba_version_string, 0,
2875 sizeof(extended_info->samba_version_string));
2877 snprintf (extended_info->samba_version_string,
2878 sizeof(extended_info->samba_version_string),
2879 "%s", samba_version_string());
2882 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2883 TALLOC_CTX *mem_ctx,
2884 uint16_t info_level,
2886 unsigned int max_data_bytes,
2890 char *pdata, *end_data;
2891 int data_len = 0, len;
2892 const char *vname = volume_label(SNUM(conn));
2893 int snum = SNUM(conn);
2894 char *fstype = lp_fstype(SNUM(conn));
2895 uint32 additional_flags = 0;
2896 struct smb_filename smb_fname_dot;
2900 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2901 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2902 "info level (0x%x) on IPC$.\n",
2903 (unsigned int)info_level));
2904 return NT_STATUS_ACCESS_DENIED;
2908 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2910 ZERO_STRUCT(smb_fname_dot);
2911 smb_fname_dot.base_name = discard_const_p(char, ".");
2913 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2914 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2915 return map_nt_error_from_unix(errno);
2918 st = smb_fname_dot.st;
2920 *ppdata = (char *)SMB_REALLOC(
2921 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2922 if (*ppdata == NULL) {
2923 return NT_STATUS_NO_MEMORY;
2927 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2928 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2930 switch (info_level) {
2931 case SMB_INFO_ALLOCATION:
2933 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2935 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2936 return map_nt_error_from_unix(errno);
2939 block_size = lp_block_size(snum);
2940 if (bsize < block_size) {
2941 uint64_t factor = block_size/bsize;
2946 if (bsize > block_size) {
2947 uint64_t factor = bsize/block_size;
2952 bytes_per_sector = 512;
2953 sectors_per_unit = bsize/bytes_per_sector;
2955 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2956 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2957 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2959 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2960 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2961 SIVAL(pdata,l1_cUnit,dsize);
2962 SIVAL(pdata,l1_cUnitAvail,dfree);
2963 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2967 case SMB_INFO_VOLUME:
2968 /* Return volume name */
2970 * Add volume serial number - hash of a combination of
2971 * the called hostname and the service name.
2973 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2975 * Win2k3 and previous mess this up by sending a name length
2976 * one byte short. I believe only older clients (OS/2 Win9x) use
2977 * this call so try fixing this by adding a terminating null to
2978 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2982 pdata+l2_vol_szVolLabel, vname,
2983 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2984 STR_NOALIGN|STR_TERMINATE);
2985 SCVAL(pdata,l2_vol_cch,len);
2986 data_len = l2_vol_szVolLabel + len;
2987 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2988 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2992 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2993 case SMB_FS_ATTRIBUTE_INFORMATION:
2995 additional_flags = 0;
2996 #if defined(HAVE_SYS_QUOTAS)
2997 additional_flags |= FILE_VOLUME_QUOTAS;
3000 if(lp_nt_acl_support(SNUM(conn))) {
3001 additional_flags |= FILE_PERSISTENT_ACLS;
3004 /* Capabilities are filled in at connection time through STATVFS call */
3005 additional_flags |= conn->fs_capabilities;
3006 additional_flags |= lp_parm_int(conn->params->service,
3007 "share", "fake_fscaps",
3010 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3011 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3012 additional_flags); /* FS ATTRIBUTES */
3014 SIVAL(pdata,4,255); /* Max filename component length */
3015 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3016 and will think we can't do long filenames */
3017 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3018 PTR_DIFF(end_data, pdata+12),
3021 data_len = 12 + len;
3024 case SMB_QUERY_FS_LABEL_INFO:
3025 case SMB_FS_LABEL_INFORMATION:
3026 len = srvstr_push(pdata, flags2, pdata+4, vname,
3027 PTR_DIFF(end_data, pdata+4), 0);
3032 case SMB_QUERY_FS_VOLUME_INFO:
3033 case SMB_FS_VOLUME_INFORMATION:
3036 * Add volume serial number - hash of a combination of
3037 * the called hostname and the service name.
3039 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3040 (str_checksum(get_local_machine_name())<<16));
3042 /* Max label len is 32 characters. */
3043 len = srvstr_push(pdata, flags2, pdata+18, vname,
3044 PTR_DIFF(end_data, pdata+18),
3046 SIVAL(pdata,12,len);
3049 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3050 (int)strlen(vname),vname, lp_servicename(snum)));
3053 case SMB_QUERY_FS_SIZE_INFO:
3054 case SMB_FS_SIZE_INFORMATION:
3056 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3058 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3059 return map_nt_error_from_unix(errno);
3061 block_size = lp_block_size(snum);
3062 if (bsize < block_size) {
3063 uint64_t factor = block_size/bsize;
3068 if (bsize > block_size) {
3069 uint64_t factor = bsize/block_size;
3074 bytes_per_sector = 512;
3075 sectors_per_unit = bsize/bytes_per_sector;
3076 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3077 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3078 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3079 SBIG_UINT(pdata,0,dsize);
3080 SBIG_UINT(pdata,8,dfree);
3081 SIVAL(pdata,16,sectors_per_unit);
3082 SIVAL(pdata,20,bytes_per_sector);
3086 case SMB_FS_FULL_SIZE_INFORMATION:
3088 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3090 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3091 return map_nt_error_from_unix(errno);
3093 block_size = lp_block_size(snum);
3094 if (bsize < block_size) {
3095 uint64_t factor = block_size/bsize;
3100 if (bsize > block_size) {
3101 uint64_t factor = bsize/block_size;
3106 bytes_per_sector = 512;
3107 sectors_per_unit = bsize/bytes_per_sector;
3108 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3109 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3110 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3111 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3112 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3113 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3114 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3115 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3119 case SMB_QUERY_FS_DEVICE_INFO:
3120 case SMB_FS_DEVICE_INFORMATION:
3122 SIVAL(pdata,0,0); /* dev type */
3123 SIVAL(pdata,4,0); /* characteristics */
3126 #ifdef HAVE_SYS_QUOTAS
3127 case SMB_FS_QUOTA_INFORMATION:
3129 * what we have to send --metze:
3131 * Unknown1: 24 NULL bytes
3132 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3133 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3134 * Quota Flags: 2 byte :
3135 * Unknown3: 6 NULL bytes
3139 * details for Quota Flags:
3141 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3142 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3143 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3144 * 0x0001 Enable Quotas: enable quota for this fs
3148 /* we need to fake up a fsp here,
3149 * because its not send in this call
3152 SMB_NTQUOTA_STRUCT quotas;
3155 ZERO_STRUCT(quotas);
3161 if (conn->server_info->utok.uid != sec_initial_uid() &&
3162 !conn->admin_user) {
3163 DEBUG(0,("set_user_quota: access_denied "
3164 "service [%s] user [%s]\n",
3165 lp_servicename(SNUM(conn)),
3166 conn->server_info->unix_name));
3167 return NT_STATUS_ACCESS_DENIED;
3170 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3171 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3172 return map_nt_error_from_unix(errno);
3177 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3178 lp_servicename(SNUM(conn))));
3180 /* Unknown1 24 NULL bytes*/
3181 SBIG_UINT(pdata,0,(uint64_t)0);
3182 SBIG_UINT(pdata,8,(uint64_t)0);
3183 SBIG_UINT(pdata,16,(uint64_t)0);
3185 /* Default Soft Quota 8 bytes */
3186 SBIG_UINT(pdata,24,quotas.softlim);
3188 /* Default Hard Quota 8 bytes */
3189 SBIG_UINT(pdata,32,quotas.hardlim);
3191 /* Quota flag 2 bytes */
3192 SSVAL(pdata,40,quotas.qflags);
3194 /* Unknown3 6 NULL bytes */
3200 #endif /* HAVE_SYS_QUOTAS */
3201 case SMB_FS_OBJECTID_INFORMATION:
3203 unsigned char objid[16];
3204 struct smb_extended_info extended_info;
3205 memcpy(pdata,create_volume_objectid(conn, objid),16);
3206 samba_extended_info_version (&extended_info);
3207 SIVAL(pdata,16,extended_info.samba_magic);
3208 SIVAL(pdata,20,extended_info.samba_version);
3209 SIVAL(pdata,24,extended_info.samba_subversion);
3210 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3211 memcpy(pdata+36,extended_info.samba_version_string,28);
3217 * Query the version and capabilities of the CIFS UNIX extensions
3221 case SMB_QUERY_CIFS_UNIX_INFO:
3223 bool large_write = lp_min_receive_file_size() &&
3224 !srv_is_signing_active(smbd_server_conn);
3225 bool large_read = !srv_is_signing_active(smbd_server_conn);
3226 int encrypt_caps = 0;
3228 if (!lp_unix_extensions()) {
3229 return NT_STATUS_INVALID_LEVEL;
3232 switch (conn->encrypt_level) {
3238 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3241 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3242 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3243 large_write = false;
3249 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3250 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3252 /* We have POSIX ACLs, pathname, encryption,
3253 * large read/write, and locking capability. */
3255 SBIG_UINT(pdata,4,((uint64_t)(
3256 CIFS_UNIX_POSIX_ACLS_CAP|
3257 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3258 CIFS_UNIX_FCNTL_LOCKS_CAP|
3259 CIFS_UNIX_EXTATTR_CAP|
3260 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3262 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3264 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3268 case SMB_QUERY_POSIX_FS_INFO:
3271 vfs_statvfs_struct svfs;
3273 if (!lp_unix_extensions()) {
3274 return NT_STATUS_INVALID_LEVEL;
3277 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3281 SIVAL(pdata,0,svfs.OptimalTransferSize);
3282 SIVAL(pdata,4,svfs.BlockSize);
3283 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3284 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3285 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3286 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3287 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3288 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3289 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3291 } else if (rc == EOPNOTSUPP) {
3292 return NT_STATUS_INVALID_LEVEL;
3293 #endif /* EOPNOTSUPP */
3295 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3296 return NT_STATUS_DOS(ERRSRV, ERRerror);
3301 case SMB_QUERY_POSIX_WHOAMI:
3307 if (!lp_unix_extensions()) {
3308 return NT_STATUS_INVALID_LEVEL;
3311 if (max_data_bytes < 40) {
3312 return NT_STATUS_BUFFER_TOO_SMALL;
3315 /* We ARE guest if global_sid_Builtin_Guests is
3316 * in our list of SIDs.
3318 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3319 conn->server_info->ptok)) {
3320 flags |= SMB_WHOAMI_GUEST;
3323 /* We are NOT guest if global_sid_Authenticated_Users
3324 * is in our list of SIDs.
3326 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3327 conn->server_info->ptok)) {
3328 flags &= ~SMB_WHOAMI_GUEST;
3331 /* NOTE: 8 bytes for UID/GID, irrespective of native
3332 * platform size. This matches
3333 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3335 data_len = 4 /* flags */
3342 + 4 /* pad/reserved */
3343 + (conn->server_info->utok.ngroups * 8)
3345 + (conn->server_info->ptok->num_sids *
3349 SIVAL(pdata, 0, flags);
3350 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3352 (uint64_t)conn->server_info->utok.uid);
3353 SBIG_UINT(pdata, 16,
3354 (uint64_t)conn->server_info->utok.gid);
3357 if (data_len >= max_data_bytes) {
3358 /* Potential overflow, skip the GIDs and SIDs. */
3360 SIVAL(pdata, 24, 0); /* num_groups */
3361 SIVAL(pdata, 28, 0); /* num_sids */
3362 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3363 SIVAL(pdata, 36, 0); /* reserved */
3369 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3370 SIVAL(pdata, 28, conn->server_info->num_sids);
3372 /* We walk the SID list twice, but this call is fairly
3373 * infrequent, and I don't expect that it's performance
3374 * sensitive -- jpeach
3376 for (i = 0, sid_bytes = 0;
3377 i < conn->server_info->ptok->num_sids; ++i) {
3378 sid_bytes += ndr_size_dom_sid(
3379 &conn->server_info->ptok->user_sids[i],
3384 /* SID list byte count */
3385 SIVAL(pdata, 32, sid_bytes);
3387 /* 4 bytes pad/reserved - must be zero */
3388 SIVAL(pdata, 36, 0);
3392 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3393 SBIG_UINT(pdata, data_len,
3394 (uint64_t)conn->server_info->utok.groups[i]);
3400 i < conn->server_info->ptok->num_sids; ++i) {
3401 int sid_len = ndr_size_dom_sid(
3402 &conn->server_info->ptok->user_sids[i],
3406 sid_linearize(pdata + data_len, sid_len,
3407 &conn->server_info->ptok->user_sids[i]);
3408 data_len += sid_len;
3414 case SMB_MAC_QUERY_FS_INFO:
3416 * Thursby MAC extension... ONLY on NTFS filesystems
3417 * once we do streams then we don't need this
3419 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3421 SIVAL(pdata,84,0x100); /* Don't support mac... */
3426 return NT_STATUS_INVALID_LEVEL;
3429 *ret_data_len = data_len;
3430 return NT_STATUS_OK;
3433 /****************************************************************************
3434 Reply to a TRANS2_QFSINFO (query filesystem info).
3435 ****************************************************************************/
3437 static void call_trans2qfsinfo(connection_struct *conn,
3438 struct smb_request *req,
3439 char **pparams, int total_params,
3440 char **ppdata, int total_data,
3441 unsigned int max_data_bytes)
3443 char *params = *pparams;
3444 uint16_t info_level;
3448 if (total_params < 2) {
3449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3453 info_level = SVAL(params,0);
3455 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3456 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3457 DEBUG(0,("call_trans2qfsinfo: encryption required "
3458 "and info level 0x%x sent.\n",
3459 (unsigned int)info_level));
3460 exit_server_cleanly("encryption required "
3466 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3468 status = smbd_do_qfsinfo(conn, req,
3473 if (!NT_STATUS_IS_OK(status)) {
3474 reply_nterror(req, status);
3478 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3481 DEBUG( 4, ( "%s info_level = %d\n",
3482 smb_fn_name(req->cmd), info_level) );
3487 /****************************************************************************
3488 Reply to a TRANS2_SETFSINFO (set filesystem info).
3489 ****************************************************************************/
3491 static void call_trans2setfsinfo(connection_struct *conn,
3492 struct smb_request *req,
3493 char **pparams, int total_params,
3494 char **ppdata, int total_data,
3495 unsigned int max_data_bytes)
3497 char *pdata = *ppdata;
3498 char *params = *pparams;
3501 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3504 if (total_params < 4) {
3505 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3511 info_level = SVAL(params,2);
3514 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3515 info_level != SMB_SET_CIFS_UNIX_INFO) {
3516 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3517 "info level (0x%x) on IPC$.\n",
3518 (unsigned int)info_level));
3519 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3524 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3525 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3526 DEBUG(0,("call_trans2setfsinfo: encryption required "
3527 "and info level 0x%x sent.\n",
3528 (unsigned int)info_level));
3529 exit_server_cleanly("encryption required "
3535 switch(info_level) {
3536 case SMB_SET_CIFS_UNIX_INFO:
3538 uint16 client_unix_major;
3539 uint16 client_unix_minor;
3540 uint32 client_unix_cap_low;
3541 uint32 client_unix_cap_high;
3543 if (!lp_unix_extensions()) {
3545 NT_STATUS_INVALID_LEVEL);
3549 /* There should be 12 bytes of capabilities set. */
3550 if (total_data < 8) {
3553 NT_STATUS_INVALID_PARAMETER);
3556 client_unix_major = SVAL(pdata,0);
3557 client_unix_minor = SVAL(pdata,2);
3558 client_unix_cap_low = IVAL(pdata,4);
3559 client_unix_cap_high = IVAL(pdata,8);
3560 /* Just print these values for now. */
3561 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3562 cap_low = 0x%x, cap_high = 0x%x\n",
3563 (unsigned int)client_unix_major,
3564 (unsigned int)client_unix_minor,
3565 (unsigned int)client_unix_cap_low,
3566 (unsigned int)client_unix_cap_high ));
3568 /* Here is where we must switch to posix pathname processing... */
3569 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3570 lp_set_posix_pathnames();
3571 mangle_change_to_posix();
3574 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3575 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3576 /* Client that knows how to do posix locks,
3577 * but not posix open/mkdir operations. Set a
3578 * default type for read/write checks. */
3580 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3586 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3589 size_t param_len = 0;
3590 size_t data_len = total_data;
3592 if (!lp_unix_extensions()) {
3595 NT_STATUS_INVALID_LEVEL);
3599 if (lp_smb_encrypt(SNUM(conn)) == false) {
3602 NT_STATUS_NOT_SUPPORTED);
3606 DEBUG( 4,("call_trans2setfsinfo: "
3607 "request transport encryption.\n"));
3609 status = srv_request_encryption_setup(conn,
3610 (unsigned char **)ppdata,
3612 (unsigned char **)pparams,
3615 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3616 !NT_STATUS_IS_OK(status)) {
3617 reply_nterror(req, status);
3621 send_trans2_replies(conn, req,
3628 if (NT_STATUS_IS_OK(status)) {
3629 /* Server-side transport
3630 * encryption is now *on*. */
3631 status = srv_encryption_start(conn);
3632 if (!NT_STATUS_IS_OK(status)) {
3633 exit_server_cleanly(
3634 "Failure in setting "
3635 "up encrypted transport");
3641 case SMB_FS_QUOTA_INFORMATION:
3643 files_struct *fsp = NULL;
3644 SMB_NTQUOTA_STRUCT quotas;
3646 ZERO_STRUCT(quotas);
3649 if (((conn->server_info->utok.uid != sec_initial_uid()) && !conn->admin_user)
3650 ||!CAN_WRITE(conn)) {
3651 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3652 lp_servicename(SNUM(conn)),
3653 conn->server_info->unix_name));
3654 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3658 /* note: normaly there're 48 bytes,
3659 * but we didn't use the last 6 bytes for now
3662 fsp = file_fsp(req, SVAL(params,0));
3664 if (!check_fsp_ntquota_handle(conn, req,
3666 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3668 req, NT_STATUS_INVALID_HANDLE);
3672 if (total_data < 42) {
3673 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3677 NT_STATUS_INVALID_PARAMETER);
3681 /* unknown_1 24 NULL bytes in pdata*/
3683 /* the soft quotas 8 bytes (uint64_t)*/
3684 quotas.softlim = (uint64_t)IVAL(pdata,24);
3685 #ifdef LARGE_SMB_OFF_T
3686 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3687 #else /* LARGE_SMB_OFF_T */
3688 if ((IVAL(pdata,28) != 0)&&
3689 ((quotas.softlim != 0xFFFFFFFF)||
3690 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3691 /* more than 32 bits? */
3694 NT_STATUS_INVALID_PARAMETER);
3697 #endif /* LARGE_SMB_OFF_T */
3699 /* the hard quotas 8 bytes (uint64_t)*/
3700 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3701 #ifdef LARGE_SMB_OFF_T
3702 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3703 #else /* LARGE_SMB_OFF_T */
3704 if ((IVAL(pdata,36) != 0)&&
3705 ((quotas.hardlim != 0xFFFFFFFF)||
3706 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3707 /* more than 32 bits? */
3710 NT_STATUS_INVALID_PARAMETER);
3713 #endif /* LARGE_SMB_OFF_T */
3715 /* quota_flags 2 bytes **/
3716 quotas.qflags = SVAL(pdata,40);
3718 /* unknown_2 6 NULL bytes follow*/
3720 /* now set the quotas */
3721 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3722 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3723 reply_nterror(req, map_nt_error_from_unix(errno));
3730 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3732 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3738 * sending this reply works fine,
3739 * but I'm not sure it's the same
3740 * like windows do...
3743 reply_outbuf(req, 10, 0);
3746 #if defined(HAVE_POSIX_ACLS)
3747 /****************************************************************************
3748 Utility function to count the number of entries in a POSIX acl.
3749 ****************************************************************************/
3751 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3753 unsigned int ace_count = 0;
3754 int entry_id = SMB_ACL_FIRST_ENTRY;
3755 SMB_ACL_ENTRY_T entry;
3757 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3759 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3760 entry_id = SMB_ACL_NEXT_ENTRY;
3767 /****************************************************************************
3768 Utility function to marshall a POSIX acl into wire format.
3769 ****************************************************************************/
3771 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3773 int entry_id = SMB_ACL_FIRST_ENTRY;
3774 SMB_ACL_ENTRY_T entry;
3776 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3777 SMB_ACL_TAG_T tagtype;
3778 SMB_ACL_PERMSET_T permset;
3779 unsigned char perms = 0;
3780 unsigned int own_grp;
3783 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3784 entry_id = SMB_ACL_NEXT_ENTRY;
3787 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3788 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3792 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3793 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3797 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3798 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3799 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3801 SCVAL(pdata,1,perms);
3804 case SMB_ACL_USER_OBJ:
3805 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3806 own_grp = (unsigned int)pst->st_ex_uid;
3807 SIVAL(pdata,2,own_grp);
3812 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3814 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3817 own_grp = (unsigned int)*puid;
3818 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3819 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3820 SIVAL(pdata,2,own_grp);
3824 case SMB_ACL_GROUP_OBJ:
3825 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3826 own_grp = (unsigned int)pst->st_ex_gid;
3827 SIVAL(pdata,2,own_grp);
3832 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3834 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3837 own_grp = (unsigned int)*pgid;
3838 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3839 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3840 SIVAL(pdata,2,own_grp);
3845 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3846 SIVAL(pdata,2,0xFFFFFFFF);
3847 SIVAL(pdata,6,0xFFFFFFFF);
3850 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3851 SIVAL(pdata,2,0xFFFFFFFF);
3852 SIVAL(pdata,6,0xFFFFFFFF);
3855 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3858 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3865 /****************************************************************************
3866 Store the FILE_UNIX_BASIC info.
3867 ****************************************************************************/
3869 static char *store_file_unix_basic(connection_struct *conn,
3872 const SMB_STRUCT_STAT *psbuf)
3874 uint64_t file_index = get_FileIndex(conn, psbuf);
3876 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3877 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3879 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3882 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3885 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3886 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3887 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3890 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3894 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3898 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3901 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3905 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3909 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3912 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3916 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3923 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3924 * the chflags(2) (or equivalent) flags.
3926 * XXX: this really should be behind the VFS interface. To do this, we would
3927 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3928 * Each VFS module could then implement its own mapping as appropriate for the
3929 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3931 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3935 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3939 { UF_IMMUTABLE, EXT_IMMUTABLE },
3943 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3947 { UF_HIDDEN, EXT_HIDDEN },
3950 /* Do not remove. We need to guarantee that this array has at least one
3951 * entry to build on HP-UX.
3957 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3958 uint32 *smb_fflags, uint32 *smb_fmask)
3962 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3963 *smb_fmask |= info2_flags_map[i].smb_fflag;
3964 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3965 *smb_fflags |= info2_flags_map[i].smb_fflag;
3970 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3971 const uint32 smb_fflags,
3972 const uint32 smb_fmask,
3975 uint32 max_fmask = 0;
3978 *stat_fflags = psbuf->st_ex_flags;
3980 /* For each flags requested in smb_fmask, check the state of the
3981 * corresponding flag in smb_fflags and set or clear the matching
3985 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3986 max_fmask |= info2_flags_map[i].smb_fflag;
3987 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3988 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3989 *stat_fflags |= info2_flags_map[i].stat_fflag;
3991 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3996 /* If smb_fmask is asking to set any bits that are not supported by
3997 * our flag mappings, we should fail.
3999 if ((smb_fmask & max_fmask) != smb_fmask) {
4007 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4008 * of file flags and birth (create) time.
4010 static char *store_file_unix_basic_info2(connection_struct *conn,
4013 const SMB_STRUCT_STAT *psbuf)
4015 uint32 file_flags = 0;
4016 uint32 flags_mask = 0;
4018 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4020 /* Create (birth) time 64 bit */
4021 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4024 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4025 SIVAL(pdata, 0, file_flags); /* flags */
4026 SIVAL(pdata, 4, flags_mask); /* mask */
4032 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4033 const struct stream_struct *streams,
4035 unsigned int max_data_bytes,
4036 unsigned int *data_size)
4039 unsigned int ofs = 0;
4041 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4042 unsigned int next_offset;
4044 smb_ucs2_t *namebuf;
4046 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4047 streams[i].name, &namelen) ||
4050 return NT_STATUS_INVALID_PARAMETER;
4054 * name_buf is now null-terminated, we need to marshall as not
4060 SIVAL(data, ofs+4, namelen);
4061 SOFF_T(data, ofs+8, streams[i].size);
4062 SOFF_T(data, ofs+16, streams[i].alloc_size);
4063 memcpy(data+ofs+24, namebuf, namelen);
4064 TALLOC_FREE(namebuf);
4066 next_offset = ofs + 24 + namelen;
4068 if (i == num_streams-1) {
4069 SIVAL(data, ofs, 0);
4072 unsigned int align = ndr_align_size(next_offset, 8);
4074 memset(data+next_offset, 0, align);
4075 next_offset += align;
4077 SIVAL(data, ofs, next_offset - ofs);
4086 return NT_STATUS_OK;
4089 /****************************************************************************
4090 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4091 ****************************************************************************/
4093 static void call_trans2qpipeinfo(connection_struct *conn,
4094 struct smb_request *req,
4095 unsigned int tran_call,
4096 char **pparams, int total_params,
4097 char **ppdata, int total_data,
4098 unsigned int max_data_bytes)
4100 char *params = *pparams;
4101 char *pdata = *ppdata;
4102 unsigned int data_size = 0;
4103 unsigned int param_size = 2;
4108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4112 if (total_params < 4) {
4113 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4117 fsp = file_fsp(req, SVAL(params,0));
4118 if (!fsp_is_np(fsp)) {
4119 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4123 info_level = SVAL(params,2);
4125 *pparams = (char *)SMB_REALLOC(*pparams,2);
4126 if (*pparams == NULL) {
4127 reply_nterror(req, NT_STATUS_NO_MEMORY);
4132 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4133 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4134 if (*ppdata == NULL ) {
4135 reply_nterror(req, NT_STATUS_NO_MEMORY);
4140 switch (info_level) {
4141 case SMB_FILE_STANDARD_INFORMATION:
4143 SOFF_T(pdata,0,4096LL);
4150 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4154 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4160 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4161 TALLOC_CTX *mem_ctx,
4162 uint16_t info_level,
4164 struct smb_filename *smb_fname,
4165 bool delete_pending,
4166 struct timespec write_time_ts,
4168 struct ea_list *ea_list,
4169 int lock_data_count,
4172 unsigned int max_data_bytes,
4174 unsigned int *pdata_size)
4176 char *pdata = *ppdata;
4177 char *dstart, *dend;
4178 unsigned int data_size;
4179 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4180 time_t create_time, mtime, atime, c_time;
4181 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4188 uint64_t file_size = 0;
4190 uint64_t allocation_size = 0;
4191 uint64_t file_index = 0;
4192 uint32_t access_mask = 0;
4194 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4195 return NT_STATUS_INVALID_LEVEL;
4198 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4199 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4200 info_level, max_data_bytes));
4203 mode = dos_mode_msdfs(conn, smb_fname);
4205 mode = dos_mode(conn, smb_fname);
4208 nlink = psbuf->st_ex_nlink;
4210 if (nlink && (mode&aDIR)) {
4214 if ((nlink > 0) && delete_pending) {
4218 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4219 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4220 if (*ppdata == NULL) {
4221 return NT_STATUS_NO_MEMORY;
4225 dend = dstart + data_size - 1;
4227 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4228 update_stat_ex_mtime(psbuf, write_time_ts);
4231 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4232 mtime_ts = psbuf->st_ex_mtime;
4233 atime_ts = psbuf->st_ex_atime;
4234 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4236 if (lp_dos_filetime_resolution(SNUM(conn))) {
4237 dos_filetime_timespec(&create_time_ts);
4238 dos_filetime_timespec(&mtime_ts);
4239 dos_filetime_timespec(&atime_ts);
4240 dos_filetime_timespec(&ctime_ts);
4243 create_time = convert_timespec_to_time_t(create_time_ts);
4244 mtime = convert_timespec_to_time_t(mtime_ts);
4245 atime = convert_timespec_to_time_t(atime_ts);
4246 c_time = convert_timespec_to_time_t(ctime_ts);
4248 p = strrchr_m(smb_fname->base_name,'/');
4250 base_name = smb_fname->base_name;
4254 /* NT expects the name to be in an exact form of the *full*
4255 filename. See the trans2 torture test */
4256 if (ISDOT(base_name)) {
4257 dos_fname = talloc_strdup(mem_ctx, "\\");
4259 return NT_STATUS_NO_MEMORY;
4262 dos_fname = talloc_asprintf(mem_ctx,
4264 smb_fname->base_name);
4266 return NT_STATUS_NO_MEMORY;
4268 if (is_ntfs_stream_smb_fname(smb_fname)) {
4269 dos_fname = talloc_asprintf(dos_fname, "%s",
4270 smb_fname->stream_name);
4272 return NT_STATUS_NO_MEMORY;
4276 string_replace(dos_fname, '/', '\\');
4279 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4282 /* Do we have this path open ? */
4284 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4285 fsp1 = file_find_di_first(fileid);
4286 if (fsp1 && fsp1->initial_allocation_size) {
4287 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4291 if (!(mode & aDIR)) {
4292 file_size = get_file_size_stat(psbuf);
4296 pos = fsp->fh->position_information;
4300 access_mask = fsp->access_mask;
4302 /* GENERIC_EXECUTE mapping from Windows */
4303 access_mask = 0x12019F;
4306 /* This should be an index number - looks like
4309 I think this causes us to fail the IFSKIT
4310 BasicFileInformationTest. -tpot */
4311 file_index = get_FileIndex(conn, psbuf);
4313 switch (info_level) {
4314 case SMB_INFO_STANDARD:
4315 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4317 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4318 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4319 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4320 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4321 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4322 SSVAL(pdata,l1_attrFile,mode);
4325 case SMB_INFO_QUERY_EA_SIZE:
4327 unsigned int ea_size =
4328 estimate_ea_size(conn, fsp,
4329 smb_fname->base_name);
4330 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4332 srv_put_dos_date2(pdata,0,create_time);
4333 srv_put_dos_date2(pdata,4,atime);
4334 srv_put_dos_date2(pdata,8,mtime); /* write time */
4335 SIVAL(pdata,12,(uint32)file_size);
4336 SIVAL(pdata,16,(uint32)allocation_size);
4337 SSVAL(pdata,20,mode);
4338 SIVAL(pdata,22,ea_size);
4342 case SMB_INFO_IS_NAME_VALID:
4343 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4345 /* os/2 needs this ? really ?*/
4346 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4348 /* This is only reached for qpathinfo */
4352 case SMB_INFO_QUERY_EAS_FROM_LIST:
4354 size_t total_ea_len = 0;
4355 struct ea_list *ea_file_list = NULL;
4357 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4360 get_ea_list_from_file(mem_ctx, conn, fsp,
4361 smb_fname->base_name,
4363 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4365 if (!ea_list || (total_ea_len > data_size)) {
4367 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4371 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4375 case SMB_INFO_QUERY_ALL_EAS:
4377 /* We have data_size bytes to put EA's into. */
4378 size_t total_ea_len = 0;
4380 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4382 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4383 smb_fname->base_name,
4385 if (!ea_list || (total_ea_len > data_size)) {
4387 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4391 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4395 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4397 /* This is FileFullEaInformation - 0xF which maps to
4398 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4400 /* We have data_size bytes to put EA's into. */
4401 size_t total_ea_len = 0;
4402 struct ea_list *ea_file_list = NULL;
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4406 /*TODO: add filtering and index handling */
4409 get_ea_list_from_file(mem_ctx, conn, fsp,
4410 smb_fname->base_name,
4412 if (!ea_file_list) {
4413 return NT_STATUS_NO_EAS_ON_FILE;
4416 status = fill_ea_chained_buffer(mem_ctx,
4420 conn, ea_file_list);
4421 if (!NT_STATUS_IS_OK(status)) {
4427 case SMB_FILE_BASIC_INFORMATION:
4428 case SMB_QUERY_FILE_BASIC_INFO:
4430 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4431 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4432 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4434 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4438 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4439 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4440 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4441 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4442 SIVAL(pdata,32,mode);
4444 DEBUG(5,("SMB_QFBI - "));
4445 DEBUG(5,("create: %s ", ctime(&create_time)));
4446 DEBUG(5,("access: %s ", ctime(&atime)));
4447 DEBUG(5,("write: %s ", ctime(&mtime)));
4448 DEBUG(5,("change: %s ", ctime(&c_time)));
4449 DEBUG(5,("mode: %x\n", mode));
4452 case SMB_FILE_STANDARD_INFORMATION:
4453 case SMB_QUERY_FILE_STANDARD_INFO:
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4457 SOFF_T(pdata,0,allocation_size);
4458 SOFF_T(pdata,8,file_size);
4459 SIVAL(pdata,16,nlink);
4460 SCVAL(pdata,20,delete_pending?1:0);
4461 SCVAL(pdata,21,(mode&aDIR)?1:0);
4462 SSVAL(pdata,22,0); /* Padding. */
4465 case SMB_FILE_EA_INFORMATION:
4466 case SMB_QUERY_FILE_EA_INFO:
4468 unsigned int ea_size =
4469 estimate_ea_size(conn, fsp, smb_fname->base_name);
4470 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4472 SIVAL(pdata,0,ea_size);
4476 /* Get the 8.3 name - used if NT SMB was negotiated. */
4477 case SMB_QUERY_FILE_ALT_NAME_INFO:
4478 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4481 char mangled_name[13];
4482 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4483 if (!name_to_8_3(base_name,mangled_name,
4484 True,conn->params)) {
4485 return NT_STATUS_NO_MEMORY;
4487 len = srvstr_push(dstart, flags2,
4488 pdata+4, mangled_name,
4489 PTR_DIFF(dend, pdata+4),
4491 data_size = 4 + len;
4496 case SMB_QUERY_FILE_NAME_INFO:
4500 this must be *exactly* right for ACLs on mapped drives to work
4502 len = srvstr_push(dstart, flags2,
4504 PTR_DIFF(dend, pdata+4),
4506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4507 data_size = 4 + len;
4512 case SMB_FILE_ALLOCATION_INFORMATION:
4513 case SMB_QUERY_FILE_ALLOCATION_INFO:
4514 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4516 SOFF_T(pdata,0,allocation_size);
4519 case SMB_FILE_END_OF_FILE_INFORMATION:
4520 case SMB_QUERY_FILE_END_OF_FILEINFO:
4521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4523 SOFF_T(pdata,0,file_size);
4526 case SMB_QUERY_FILE_ALL_INFO:
4527 case SMB_FILE_ALL_INFORMATION:
4530 unsigned int ea_size =
4531 estimate_ea_size(conn, fsp, smb_fname->base_name);
4532 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4533 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4534 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4535 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4536 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4537 SIVAL(pdata,32,mode);
4538 SIVAL(pdata,36,0); /* padding. */
4540 SOFF_T(pdata,0,allocation_size);
4541 SOFF_T(pdata,8,file_size);
4542 SIVAL(pdata,16,nlink);
4543 SCVAL(pdata,20,delete_pending);
4544 SCVAL(pdata,21,(mode&aDIR)?1:0);
4547 SIVAL(pdata,0,ea_size);
4548 pdata += 4; /* EA info */
4549 len = srvstr_push(dstart, flags2,
4551 PTR_DIFF(dend, pdata+4),
4555 data_size = PTR_DIFF(pdata,(*ppdata));
4559 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4562 unsigned int ea_size =
4563 estimate_ea_size(conn, fsp, smb_fname->base_name);
4564 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4565 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4566 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4567 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4568 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4569 SIVAL(pdata, 0x20, mode);
4570 SIVAL(pdata, 0x24, 0); /* padding. */
4571 SBVAL(pdata, 0x28, allocation_size);
4572 SBVAL(pdata, 0x30, file_size);
4573 SIVAL(pdata, 0x38, nlink);
4574 SCVAL(pdata, 0x3C, delete_pending);
4575 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4576 SSVAL(pdata, 0x3E, 0); /* padding */
4577 SBVAL(pdata, 0x40, file_index);
4578 SIVAL(pdata, 0x48, ea_size);
4579 SIVAL(pdata, 0x4C, access_mask);
4580 SBVAL(pdata, 0x50, pos);
4581 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4582 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4586 len = srvstr_push(dstart, flags2,
4588 PTR_DIFF(dend, pdata+4),
4592 data_size = PTR_DIFF(pdata,(*ppdata));
4595 case SMB_FILE_INTERNAL_INFORMATION:
4597 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4598 SBVAL(pdata, 0, file_index);
4602 case SMB_FILE_ACCESS_INFORMATION:
4603 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4604 SIVAL(pdata, 0, access_mask);
4608 case SMB_FILE_NAME_INFORMATION:
4609 /* Pathname with leading '\'. */
4612 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4614 SIVAL(pdata,0,byte_len);
4615 data_size = 4 + byte_len;
4619 case SMB_FILE_DISPOSITION_INFORMATION:
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4622 SCVAL(pdata,0,delete_pending);
4625 case SMB_FILE_POSITION_INFORMATION:
4626 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4628 SOFF_T(pdata,0,pos);
4631 case SMB_FILE_MODE_INFORMATION:
4632 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4633 SIVAL(pdata,0,mode);
4637 case SMB_FILE_ALIGNMENT_INFORMATION:
4638 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4639 SIVAL(pdata,0,0); /* No alignment needed. */
4644 * NT4 server just returns "invalid query" to this - if we try
4645 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4648 /* The first statement above is false - verified using Thursby
4649 * client against NT4 -- gcolley.
4651 case SMB_QUERY_FILE_STREAM_INFO:
4652 case SMB_FILE_STREAM_INFORMATION: {
4653 unsigned int num_streams;
4654 struct stream_struct *streams;
4656 DEBUG(10,("smbd_do_qfilepathinfo: "
4657 "SMB_FILE_STREAM_INFORMATION\n"));
4659 if (is_ntfs_stream_smb_fname(smb_fname)) {
4660 return NT_STATUS_INVALID_PARAMETER;
4663 status = SMB_VFS_STREAMINFO(
4664 conn, fsp, smb_fname->base_name, talloc_tos(),
4665 &num_streams, &streams);
4667 if (!NT_STATUS_IS_OK(status)) {
4668 DEBUG(10, ("could not get stream info: %s\n",
4669 nt_errstr(status)));
4673 status = marshall_stream_info(num_streams, streams,
4674 pdata, max_data_bytes,
4677 if (!NT_STATUS_IS_OK(status)) {
4678 DEBUG(10, ("marshall_stream_info failed: %s\n",
4679 nt_errstr(status)));
4683 TALLOC_FREE(streams);
4687 case SMB_QUERY_COMPRESSION_INFO:
4688 case SMB_FILE_COMPRESSION_INFORMATION:
4689 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4690 SOFF_T(pdata,0,file_size);
4691 SIVAL(pdata,8,0); /* ??? */
4692 SIVAL(pdata,12,0); /* ??? */
4696 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4697 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4698 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4699 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4700 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4701 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4702 SOFF_T(pdata,32,allocation_size);
4703 SOFF_T(pdata,40,file_size);
4704 SIVAL(pdata,48,mode);
4705 SIVAL(pdata,52,0); /* ??? */
4709 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4710 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4711 SIVAL(pdata,0,mode);
4717 * CIFS UNIX Extensions.
4720 case SMB_QUERY_FILE_UNIX_BASIC:
4722 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4723 data_size = PTR_DIFF(pdata,(*ppdata));
4727 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4729 for (i=0; i<100; i++)
4730 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4736 case SMB_QUERY_FILE_UNIX_INFO2:
4738 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4739 data_size = PTR_DIFF(pdata,(*ppdata));
4743 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4745 for (i=0; i<100; i++)
4746 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4752 case SMB_QUERY_FILE_UNIX_LINK:
4755 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4758 return NT_STATUS_NO_MEMORY;
4761 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4763 if(!S_ISLNK(psbuf->st_ex_mode)) {
4764 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4767 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4769 len = SMB_VFS_READLINK(conn,
4770 smb_fname->base_name,
4773 return map_nt_error_from_unix(errno);
4776 len = srvstr_push(dstart, flags2,
4778 PTR_DIFF(dend, pdata),
4781 data_size = PTR_DIFF(pdata,(*ppdata));
4786 #if defined(HAVE_POSIX_ACLS)
4787 case SMB_QUERY_POSIX_ACL:
4789 SMB_ACL_T file_acl = NULL;
4790 SMB_ACL_T def_acl = NULL;
4791 uint16 num_file_acls = 0;
4792 uint16 num_def_acls = 0;
4794 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4795 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4798 SMB_VFS_SYS_ACL_GET_FILE(conn,
4799 smb_fname->base_name,
4800 SMB_ACL_TYPE_ACCESS);
4803 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4804 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4805 "not implemented on "
4806 "filesystem containing %s\n",
4807 smb_fname->base_name));
4808 return NT_STATUS_NOT_IMPLEMENTED;
4811 if (S_ISDIR(psbuf->st_ex_mode)) {
4812 if (fsp && fsp->is_directory) {
4814 SMB_VFS_SYS_ACL_GET_FILE(
4816 fsp->fsp_name->base_name,
4817 SMB_ACL_TYPE_DEFAULT);
4820 SMB_VFS_SYS_ACL_GET_FILE(
4822 smb_fname->base_name,
4823 SMB_ACL_TYPE_DEFAULT);
4825 def_acl = free_empty_sys_acl(conn, def_acl);
4828 num_file_acls = count_acl_entries(conn, file_acl);
4829 num_def_acls = count_acl_entries(conn, def_acl);
4831 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4832 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4834 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4835 SMB_POSIX_ACL_HEADER_SIZE) ));
4837 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4840 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4842 return NT_STATUS_BUFFER_TOO_SMALL;
4845 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4846 SSVAL(pdata,2,num_file_acls);
4847 SSVAL(pdata,4,num_def_acls);
4848 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4850 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4855 return NT_STATUS_INTERNAL_ERROR;
4857 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4859 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4862 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4864 return NT_STATUS_INTERNAL_ERROR;
4868 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4871 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4873 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4879 case SMB_QUERY_POSIX_LOCK:
4884 enum brl_type lock_type;
4886 /* We need an open file with a real fd for this. */
4887 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4888 return NT_STATUS_INVALID_LEVEL;
4891 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4892 return NT_STATUS_INVALID_PARAMETER;
4895 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4896 case POSIX_LOCK_TYPE_READ:
4897 lock_type = READ_LOCK;
4899 case POSIX_LOCK_TYPE_WRITE:
4900 lock_type = WRITE_LOCK;
4902 case POSIX_LOCK_TYPE_UNLOCK:
4904 /* There's no point in asking for an unlock... */
4905 return NT_STATUS_INVALID_PARAMETER;
4908 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4909 #if defined(HAVE_LONGLONG)
4910 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4911 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4912 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4913 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4914 #else /* HAVE_LONGLONG */
4915 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4916 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4917 #endif /* HAVE_LONGLONG */
4919 status = query_lock(fsp,
4926 if (ERROR_WAS_LOCK_DENIED(status)) {
4927 /* Here we need to report who has it locked... */
4928 data_size = POSIX_LOCK_DATA_SIZE;
4930 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4931 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4932 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4933 #if defined(HAVE_LONGLONG)
4934 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4935 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4936 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4937 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4938 #else /* HAVE_LONGLONG */
4939 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4940 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4941 #endif /* HAVE_LONGLONG */
4943 } else if (NT_STATUS_IS_OK(status)) {
4944 /* For success we just return a copy of what we sent
4945 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4946 data_size = POSIX_LOCK_DATA_SIZE;
4947 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4948 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4956 return NT_STATUS_INVALID_LEVEL;
4959 *pdata_size = data_size;
4960 return NT_STATUS_OK;
4963 /****************************************************************************
4964 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4965 file name or file id).
4966 ****************************************************************************/
4968 static void call_trans2qfilepathinfo(connection_struct *conn,
4969 struct smb_request *req,
4970 unsigned int tran_call,
4971 char **pparams, int total_params,
4972 char **ppdata, int total_data,
4973 unsigned int max_data_bytes)
4975 char *params = *pparams;
4976 char *pdata = *ppdata;
4978 unsigned int data_size = 0;
4979 unsigned int param_size = 2;
4980 struct smb_filename *smb_fname = NULL;
4981 bool delete_pending = False;
4982 struct timespec write_time_ts;
4983 files_struct *fsp = NULL;
4984 struct file_id fileid;
4985 struct ea_list *ea_list = NULL;
4986 int lock_data_count = 0;
4987 char *lock_data = NULL;
4988 bool ms_dfs_link = false;
4989 NTSTATUS status = NT_STATUS_OK;
4992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4996 ZERO_STRUCT(write_time_ts);
4998 if (tran_call == TRANSACT2_QFILEINFO) {
4999 if (total_params < 4) {
5000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5005 call_trans2qpipeinfo(conn, req, tran_call,
5006 pparams, total_params,
5012 fsp = file_fsp(req, SVAL(params,0));
5013 info_level = SVAL(params,2);
5015 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5017 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5018 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5022 /* Initial check for valid fsp ptr. */
5023 if (!check_fsp_open(conn, req, fsp)) {
5027 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5029 if (!NT_STATUS_IS_OK(status)) {
5030 reply_nterror(req, status);
5034 if(fsp->fake_file_handle) {
5036 * This is actually for the QUOTA_FAKE_FILE --metze
5039 /* We know this name is ok, it's already passed the checks. */
5041 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5043 * This is actually a QFILEINFO on a directory
5044 * handle (returned from an NT SMB). NT5.0 seems
5045 * to do this call. JRA.
5048 if (INFO_LEVEL_IS_UNIX(info_level)) {
5049 /* Always do lstat for UNIX calls. */
5050 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5051 DEBUG(3,("call_trans2qfilepathinfo: "
5052 "SMB_VFS_LSTAT of %s failed "
5054 smb_fname_str_dbg(smb_fname),
5057 map_nt_error_from_unix(errno));
5060 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5061 DEBUG(3,("call_trans2qfilepathinfo: "
5062 "SMB_VFS_STAT of %s failed (%s)\n",
5063 smb_fname_str_dbg(smb_fname),
5066 map_nt_error_from_unix(errno));
5070 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5071 get_file_infos(fileid, &delete_pending, &write_time_ts);
5074 * Original code - this is an open file.
5076 if (!check_fsp(conn, req, fsp)) {
5080 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5081 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5082 fsp->fnum, strerror(errno)));
5084 map_nt_error_from_unix(errno));
5087 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5088 get_file_infos(fileid, &delete_pending, &write_time_ts);
5093 uint32_t ucf_flags = 0;
5096 if (total_params < 7) {
5097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5101 info_level = SVAL(params,0);
5103 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5105 if (INFO_LEVEL_IS_UNIX(info_level)) {
5106 if (!lp_unix_extensions()) {
5107 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5110 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5111 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5112 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5113 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5117 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5119 STR_TERMINATE, &status);
5120 if (!NT_STATUS_IS_OK(status)) {
5121 reply_nterror(req, status);
5125 status = filename_convert(req,
5127 req->flags2 & FLAGS2_DFS_PATHNAMES,
5132 if (!NT_STATUS_IS_OK(status)) {
5133 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5134 reply_botherror(req,
5135 NT_STATUS_PATH_NOT_COVERED,
5136 ERRSRV, ERRbadpath);
5139 reply_nterror(req, status);
5143 /* If this is a stream, check if there is a delete_pending. */
5144 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5145 && is_ntfs_stream_smb_fname(smb_fname)) {
5146 struct smb_filename *smb_fname_base = NULL;
5148 /* Create an smb_filename with stream_name == NULL. */
5150 create_synthetic_smb_fname(talloc_tos(),
5151 smb_fname->base_name,
5154 if (!NT_STATUS_IS_OK(status)) {
5155 reply_nterror(req, status);
5159 if (INFO_LEVEL_IS_UNIX(info_level)) {
5160 /* Always do lstat for UNIX calls. */
5161 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5162 DEBUG(3,("call_trans2qfilepathinfo: "
5163 "SMB_VFS_LSTAT of %s failed "
5165 smb_fname_str_dbg(smb_fname_base),
5167 TALLOC_FREE(smb_fname_base);
5169 map_nt_error_from_unix(errno));
5173 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5174 DEBUG(3,("call_trans2qfilepathinfo: "
5175 "fileinfo of %s failed "
5177 smb_fname_str_dbg(smb_fname_base),
5179 TALLOC_FREE(smb_fname_base);
5181 map_nt_error_from_unix(errno));
5186 fileid = vfs_file_id_from_sbuf(conn,
5187 &smb_fname_base->st);
5188 TALLOC_FREE(smb_fname_base);
5189 get_file_infos(fileid, &delete_pending, NULL);
5190 if (delete_pending) {
5191 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5196 if (INFO_LEVEL_IS_UNIX(info_level)) {
5197 /* Always do lstat for UNIX calls. */
5198 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5199 DEBUG(3,("call_trans2qfilepathinfo: "
5200 "SMB_VFS_LSTAT of %s failed (%s)\n",
5201 smb_fname_str_dbg(smb_fname),
5204 map_nt_error_from_unix(errno));
5208 } else if (!VALID_STAT(smb_fname->st) &&
5209 SMB_VFS_STAT(conn, smb_fname) &&
5210 (info_level != SMB_INFO_IS_NAME_VALID)) {
5211 ms_dfs_link = check_msdfs_link(conn,
5212 smb_fname->base_name,
5216 DEBUG(3,("call_trans2qfilepathinfo: "
5217 "SMB_VFS_STAT of %s failed (%s)\n",
5218 smb_fname_str_dbg(smb_fname),
5221 map_nt_error_from_unix(errno));
5226 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5227 get_file_infos(fileid, &delete_pending, &write_time_ts);
5228 if (delete_pending) {
5229 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5234 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5235 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5236 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5238 /* Pull out any data sent here before we realloc. */
5239 switch (info_level) {
5240 case SMB_INFO_QUERY_EAS_FROM_LIST:
5242 /* Pull any EA list from the data portion. */
5245 if (total_data < 4) {
5247 req, NT_STATUS_INVALID_PARAMETER);
5250 ea_size = IVAL(pdata,0);
5252 if (total_data > 0 && ea_size != total_data) {
5253 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5254 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5256 req, NT_STATUS_INVALID_PARAMETER);
5260 if (!lp_ea_support(SNUM(conn))) {
5261 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5265 /* Pull out the list of names. */
5266 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5269 req, NT_STATUS_INVALID_PARAMETER);
5275 case SMB_QUERY_POSIX_LOCK:
5277 if (fsp == NULL || fsp->fh->fd == -1) {
5278 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5282 if (total_data != POSIX_LOCK_DATA_SIZE) {
5284 req, NT_STATUS_INVALID_PARAMETER);
5288 /* Copy the lock range data. */
5289 lock_data = (char *)TALLOC_MEMDUP(
5290 req, pdata, total_data);
5292 reply_nterror(req, NT_STATUS_NO_MEMORY);
5295 lock_data_count = total_data;
5301 *pparams = (char *)SMB_REALLOC(*pparams,2);
5302 if (*pparams == NULL) {
5303 reply_nterror(req, NT_STATUS_NO_MEMORY);
5310 * draft-leach-cifs-v1-spec-02.txt
5311 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5314 * The requested information is placed in the Data portion of the
5315 * transaction response. For the information levels greater than 0x100,
5316 * the transaction response has 1 parameter word which should be
5317 * ignored by the client.
5319 * However Windows only follows this rule for the IS_NAME_VALID call.
5321 switch (info_level) {
5322 case SMB_INFO_IS_NAME_VALID:
5327 if ((info_level & 0xFF00) == 0xFF00) {
5329 * We use levels that start with 0xFF00
5330 * internally to represent SMB2 specific levels
5332 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5336 status = smbd_do_qfilepathinfo(conn, req, info_level,
5338 delete_pending, write_time_ts,
5339 ms_dfs_link, ea_list,
5340 lock_data_count, lock_data,
5341 req->flags2, max_data_bytes,
5342 ppdata, &data_size);
5343 if (!NT_STATUS_IS_OK(status)) {
5344 reply_nterror(req, status);
5348 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5354 /****************************************************************************
5355 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5357 ****************************************************************************/
5359 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5360 connection_struct *conn,
5361 const struct smb_filename *smb_fname_old,
5362 const struct smb_filename *smb_fname_new)
5364 NTSTATUS status = NT_STATUS_OK;
5366 /* source must already exist. */
5367 if (!VALID_STAT(smb_fname_old->st)) {
5368 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5371 /* Disallow if newname already exists. */
5372 if (VALID_STAT(smb_fname_new->st)) {
5373 return NT_STATUS_OBJECT_NAME_COLLISION;
5376 /* No links from a directory. */
5377 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5378 return NT_STATUS_FILE_IS_A_DIRECTORY;
5381 /* Setting a hardlink to/from a stream isn't currently supported. */
5382 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5383 is_ntfs_stream_smb_fname(smb_fname_new)) {
5384 return NT_STATUS_INVALID_PARAMETER;
5387 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5388 smb_fname_old->base_name, smb_fname_new->base_name));
5390 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5391 smb_fname_new->base_name) != 0) {
5392 status = map_nt_error_from_unix(errno);
5393 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5394 nt_errstr(status), smb_fname_old->base_name,
5395 smb_fname_new->base_name));
5400 /****************************************************************************
5401 Deal with setting the time from any of the setfilepathinfo functions.
5402 ****************************************************************************/
5404 NTSTATUS smb_set_file_time(connection_struct *conn,
5406 const struct smb_filename *smb_fname,
5407 struct smb_file_time *ft,
5408 bool setting_write_time)
5410 struct smb_filename smb_fname_base;
5412 FILE_NOTIFY_CHANGE_LAST_ACCESS
5413 |FILE_NOTIFY_CHANGE_LAST_WRITE
5414 |FILE_NOTIFY_CHANGE_CREATION;
5416 if (!VALID_STAT(smb_fname->st)) {
5417 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5420 /* get some defaults (no modifications) if any info is zero or -1. */
5421 if (null_timespec(ft->create_time)) {
5422 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5425 if (null_timespec(ft->atime)) {
5426 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5429 if (null_timespec(ft->mtime)) {
5430 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5433 if (!setting_write_time) {
5434 /* ft->mtime comes from change time, not write time. */
5435 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5438 /* Ensure the resolution is the correct for
5439 * what we can store on this filesystem. */
5441 round_timespec(conn->ts_res, &ft->create_time);
5442 round_timespec(conn->ts_res, &ft->ctime);
5443 round_timespec(conn->ts_res, &ft->atime);
5444 round_timespec(conn->ts_res, &ft->mtime);
5446 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5447 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5448 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5449 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5450 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5451 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5452 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5453 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5455 if (setting_write_time) {
5457 * This was a Windows setfileinfo on an open file.
5458 * NT does this a lot. We also need to
5459 * set the time here, as it can be read by
5460 * FindFirst/FindNext and with the patch for bug #2045
5461 * in smbd/fileio.c it ensures that this timestamp is
5462 * kept sticky even after a write. We save the request
5463 * away and will set it on file close and after a write. JRA.
5466 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5467 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5470 if (fsp->base_fsp) {
5471 set_sticky_write_time_fsp(fsp->base_fsp,
5474 set_sticky_write_time_fsp(fsp, ft->mtime);
5477 set_sticky_write_time_path(
5478 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5483 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5485 /* Always call ntimes on the base, even if a stream was passed in. */
5486 smb_fname_base = *smb_fname;
5487 smb_fname_base.stream_name = NULL;
5489 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5490 return map_nt_error_from_unix(errno);
5493 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5494 smb_fname->base_name);
5495 return NT_STATUS_OK;
5498 /****************************************************************************
5499 Deal with setting the dosmode from any of the setfilepathinfo functions.
5500 ****************************************************************************/
5502 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5503 const struct smb_filename *smb_fname,
5506 struct smb_filename *smb_fname_base = NULL;
5509 if (!VALID_STAT(smb_fname->st)) {
5510 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5513 /* Always operate on the base_name, even if a stream was passed in. */
5514 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5515 NULL, &smb_fname->st,
5517 if (!NT_STATUS_IS_OK(status)) {
5522 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5529 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5531 /* check the mode isn't different, before changing it */
5532 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5533 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5534 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5535 (unsigned int)dosmode));
5537 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5539 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5541 smb_fname_str_dbg(smb_fname_base),
5543 status = map_nt_error_from_unix(errno);
5547 status = NT_STATUS_OK;
5549 TALLOC_FREE(smb_fname_base);
5553 /****************************************************************************
5554 Deal with setting the size from any of the setfilepathinfo functions.
5555 ****************************************************************************/
5557 static NTSTATUS smb_set_file_size(connection_struct *conn,
5558 struct smb_request *req,
5560 const struct smb_filename *smb_fname,
5561 const SMB_STRUCT_STAT *psbuf,
5563 bool fail_after_createfile)
5565 NTSTATUS status = NT_STATUS_OK;
5566 struct smb_filename *smb_fname_tmp = NULL;
5567 files_struct *new_fsp = NULL;
5569 if (!VALID_STAT(*psbuf)) {
5570 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5573 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5575 if (size == get_file_size_stat(psbuf)) {
5576 return NT_STATUS_OK;
5579 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5580 smb_fname_str_dbg(smb_fname), (double)size));
5582 if (fsp && fsp->fh->fd != -1) {
5583 /* Handle based call. */
5584 if (vfs_set_filelen(fsp, size) == -1) {
5585 return map_nt_error_from_unix(errno);
5587 trigger_write_time_update_immediate(fsp);
5588 return NT_STATUS_OK;
5591 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5592 if (!NT_STATUS_IS_OK(status)) {
5596 smb_fname_tmp->st = *psbuf;
5598 status = SMB_VFS_CREATE_FILE(
5601 0, /* root_dir_fid */
5602 smb_fname_tmp, /* fname */
5603 FILE_WRITE_ATTRIBUTES, /* access_mask */
5604 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5606 FILE_OPEN, /* create_disposition*/
5607 0, /* create_options */
5608 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5609 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5610 0, /* allocation_size */
5613 &new_fsp, /* result */
5616 TALLOC_FREE(smb_fname_tmp);
5618 if (!NT_STATUS_IS_OK(status)) {
5619 /* NB. We check for open_was_deferred in the caller. */
5623 /* See RAW-SFILEINFO-END-OF-FILE */
5624 if (fail_after_createfile) {
5625 close_file(req, new_fsp,NORMAL_CLOSE);
5626 return NT_STATUS_INVALID_LEVEL;
5629 if (vfs_set_filelen(new_fsp, size) == -1) {
5630 status = map_nt_error_from_unix(errno);
5631 close_file(req, new_fsp,NORMAL_CLOSE);
5635 trigger_write_time_update_immediate(new_fsp);
5636 close_file(req, new_fsp,NORMAL_CLOSE);
5637 return NT_STATUS_OK;
5640 /****************************************************************************
5641 Deal with SMB_INFO_SET_EA.
5642 ****************************************************************************/
5644 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5648 const struct smb_filename *smb_fname)
5650 struct ea_list *ea_list = NULL;
5651 TALLOC_CTX *ctx = NULL;
5652 NTSTATUS status = NT_STATUS_OK;
5654 if (total_data < 10) {
5656 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5657 length. They seem to have no effect. Bug #3212. JRA */
5659 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5660 /* We're done. We only get EA info in this call. */
5661 return NT_STATUS_OK;
5664 return NT_STATUS_INVALID_PARAMETER;
5667 if (IVAL(pdata,0) > total_data) {
5668 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5669 IVAL(pdata,0), (unsigned int)total_data));
5670 return NT_STATUS_INVALID_PARAMETER;
5674 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5676 return NT_STATUS_INVALID_PARAMETER;
5678 status = set_ea(conn, fsp, smb_fname, ea_list);
5683 /****************************************************************************
5684 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5685 ****************************************************************************/
5687 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5692 struct ea_list *ea_list = NULL;
5696 return NT_STATUS_INVALID_HANDLE;
5699 if (!lp_ea_support(SNUM(conn))) {
5700 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5701 "EA's not supported.\n",
5702 (unsigned int)total_data));
5703 return NT_STATUS_EAS_NOT_SUPPORTED;
5706 if (total_data < 10) {
5707 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5709 (unsigned int)total_data));
5710 return NT_STATUS_INVALID_PARAMETER;
5713 ea_list = read_nttrans_ea_list(talloc_tos(),
5718 return NT_STATUS_INVALID_PARAMETER;
5720 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5722 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5723 smb_fname_str_dbg(fsp->fsp_name),
5724 nt_errstr(status) ));
5730 /****************************************************************************
5731 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5732 ****************************************************************************/
5734 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5738 struct smb_filename *smb_fname)
5740 NTSTATUS status = NT_STATUS_OK;
5741 bool delete_on_close;
5744 if (total_data < 1) {
5745 return NT_STATUS_INVALID_PARAMETER;
5749 return NT_STATUS_INVALID_HANDLE;
5752 delete_on_close = (CVAL(pdata,0) ? True : False);
5753 dosmode = dos_mode(conn, smb_fname);
5755 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5756 "delete_on_close = %u\n",
5757 smb_fname_str_dbg(smb_fname),
5758 (unsigned int)dosmode,
5759 (unsigned int)delete_on_close ));
5761 if (delete_on_close) {
5762 status = can_set_delete_on_close(fsp, dosmode);
5763 if (!NT_STATUS_IS_OK(status)) {
5768 /* The set is across all open files on this dev/inode pair. */
5769 if (!set_delete_on_close(fsp, delete_on_close,
5770 &conn->server_info->utok)) {
5771 return NT_STATUS_ACCESS_DENIED;
5773 return NT_STATUS_OK;
5776 /****************************************************************************
5777 Deal with SMB_FILE_POSITION_INFORMATION.
5778 ****************************************************************************/
5780 static NTSTATUS smb_file_position_information(connection_struct *conn,
5785 uint64_t position_information;
5787 if (total_data < 8) {
5788 return NT_STATUS_INVALID_PARAMETER;
5792 /* Ignore on pathname based set. */
5793 return NT_STATUS_OK;
5796 position_information = (uint64_t)IVAL(pdata,0);
5797 #ifdef LARGE_SMB_OFF_T
5798 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5799 #else /* LARGE_SMB_OFF_T */
5800 if (IVAL(pdata,4) != 0) {
5801 /* more than 32 bits? */
5802 return NT_STATUS_INVALID_PARAMETER;
5804 #endif /* LARGE_SMB_OFF_T */
5806 DEBUG(10,("smb_file_position_information: Set file position "
5807 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5808 (double)position_information));
5809 fsp->fh->position_information = position_information;
5810 return NT_STATUS_OK;
5813 /****************************************************************************
5814 Deal with SMB_FILE_MODE_INFORMATION.
5815 ****************************************************************************/
5817 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5823 if (total_data < 4) {
5824 return NT_STATUS_INVALID_PARAMETER;
5826 mode = IVAL(pdata,0);
5827 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5828 return NT_STATUS_INVALID_PARAMETER;
5830 return NT_STATUS_OK;
5833 /****************************************************************************
5834 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5835 ****************************************************************************/
5837 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5838 struct smb_request *req,
5841 const struct smb_filename *smb_fname)
5843 char *link_target = NULL;
5844 const char *newname = smb_fname->base_name;
5845 TALLOC_CTX *ctx = talloc_tos();
5847 /* Set a symbolic link. */
5848 /* Don't allow this if follow links is false. */
5850 if (total_data == 0) {
5851 return NT_STATUS_INVALID_PARAMETER;
5854 if (!lp_symlinks(SNUM(conn))) {
5855 return NT_STATUS_ACCESS_DENIED;
5858 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5859 total_data, STR_TERMINATE);
5862 return NT_STATUS_INVALID_PARAMETER;
5865 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5866 newname, link_target ));
5868 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5869 return map_nt_error_from_unix(errno);
5872 return NT_STATUS_OK;
5875 /****************************************************************************
5876 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5877 ****************************************************************************/
5879 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5880 struct smb_request *req,
5881 const char *pdata, int total_data,
5882 const struct smb_filename *smb_fname_new)
5884 char *oldname = NULL;
5885 struct smb_filename *smb_fname_old = NULL;
5886 TALLOC_CTX *ctx = talloc_tos();
5887 NTSTATUS status = NT_STATUS_OK;
5889 /* Set a hard link. */
5890 if (total_data == 0) {
5891 return NT_STATUS_INVALID_PARAMETER;
5894 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5895 total_data, STR_TERMINATE, &status);
5896 if (!NT_STATUS_IS_OK(status)) {
5900 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5901 smb_fname_str_dbg(smb_fname_new), oldname));
5903 status = filename_convert(ctx,
5905 req->flags2 & FLAGS2_DFS_PATHNAMES,
5910 if (!NT_STATUS_IS_OK(status)) {
5914 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5917 /****************************************************************************
5918 Deal with SMB_FILE_RENAME_INFORMATION.
5919 ****************************************************************************/
5921 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5922 struct smb_request *req,
5926 struct smb_filename *smb_fname_src)
5931 char *newname = NULL;
5932 struct smb_filename *smb_fname_dst = NULL;
5933 bool dest_has_wcard = False;
5934 NTSTATUS status = NT_STATUS_OK;
5936 TALLOC_CTX *ctx = talloc_tos();
5938 if (total_data < 13) {
5939 return NT_STATUS_INVALID_PARAMETER;
5942 overwrite = (CVAL(pdata,0) ? True : False);
5943 root_fid = IVAL(pdata,4);
5944 len = IVAL(pdata,8);
5946 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5947 return NT_STATUS_INVALID_PARAMETER;
5950 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5953 if (!NT_STATUS_IS_OK(status)) {
5957 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5960 status = resolve_dfspath_wcard(ctx, conn,
5961 req->flags2 & FLAGS2_DFS_PATHNAMES,
5966 if (!NT_STATUS_IS_OK(status)) {
5970 /* Check the new name has no '/' characters. */
5971 if (strchr_m(newname, '/')) {
5972 return NT_STATUS_NOT_SUPPORTED;
5975 if (fsp && fsp->base_fsp) {
5976 /* newname must be a stream name. */
5977 if (newname[0] != ':') {
5978 return NT_STATUS_NOT_SUPPORTED;
5981 /* Create an smb_fname to call rename_internals_fsp() with. */
5982 status = create_synthetic_smb_fname(talloc_tos(),
5983 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5985 if (!NT_STATUS_IS_OK(status)) {
5990 * Set the original last component, since
5991 * rename_internals_fsp() requires it.
5993 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5995 if (smb_fname_dst->original_lcomp == NULL) {
5996 status = NT_STATUS_NO_MEMORY;
6002 * Build up an smb_fname_dst based on the filename passed in.
6003 * We basically just strip off the last component, and put on
6004 * the newname instead.
6006 char *base_name = NULL;
6008 /* newname must *not* be a stream name. */
6009 if (newname[0] == ':') {
6010 return NT_STATUS_NOT_SUPPORTED;
6014 * Strip off the last component (filename) of the path passed
6017 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6019 return NT_STATUS_NO_MEMORY;
6021 p = strrchr_m(base_name, '/');
6025 base_name = talloc_strdup(ctx, "./");
6027 return NT_STATUS_NO_MEMORY;
6030 /* Append the new name. */
6031 base_name = talloc_asprintf_append(base_name,
6035 return NT_STATUS_NO_MEMORY;
6038 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6041 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6044 /* If an error we expect this to be
6045 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6047 if (!NT_STATUS_IS_OK(status)) {
6048 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6052 /* Create an smb_fname to call rename_internals_fsp() */
6053 status = create_synthetic_smb_fname(ctx,
6057 if (!NT_STATUS_IS_OK(status)) {
6064 DEBUG(10,("smb_file_rename_information: "
6065 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6066 fsp->fnum, fsp_str_dbg(fsp),
6067 smb_fname_str_dbg(smb_fname_dst)));
6068 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6071 DEBUG(10,("smb_file_rename_information: "
6072 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6073 smb_fname_str_dbg(smb_fname_src),
6074 smb_fname_str_dbg(smb_fname_dst)));
6075 status = rename_internals(ctx, conn, req, smb_fname_src,
6076 smb_fname_dst, 0, overwrite, false,
6078 FILE_WRITE_ATTRIBUTES);
6081 TALLOC_FREE(smb_fname_dst);
6085 /****************************************************************************
6086 Deal with SMB_SET_POSIX_ACL.
6087 ****************************************************************************/
6089 #if defined(HAVE_POSIX_ACLS)
6090 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6094 const struct smb_filename *smb_fname)
6096 uint16 posix_acl_version;
6097 uint16 num_file_acls;
6098 uint16 num_def_acls;
6099 bool valid_file_acls = True;
6100 bool valid_def_acls = True;
6102 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6103 return NT_STATUS_INVALID_PARAMETER;
6105 posix_acl_version = SVAL(pdata,0);
6106 num_file_acls = SVAL(pdata,2);
6107 num_def_acls = SVAL(pdata,4);
6109 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6110 valid_file_acls = False;
6114 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6115 valid_def_acls = False;
6119 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6120 return NT_STATUS_INVALID_PARAMETER;
6123 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6124 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6125 return NT_STATUS_INVALID_PARAMETER;
6128 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6129 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6130 (unsigned int)num_file_acls,
6131 (unsigned int)num_def_acls));
6133 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6134 smb_fname->base_name, num_file_acls,
6135 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6136 return map_nt_error_from_unix(errno);
6139 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6140 smb_fname->base_name, &smb_fname->st, num_def_acls,
6141 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6142 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6143 return map_nt_error_from_unix(errno);
6145 return NT_STATUS_OK;
6149 /****************************************************************************
6150 Deal with SMB_SET_POSIX_LOCK.
6151 ****************************************************************************/
6153 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6154 struct smb_request *req,
6162 bool blocking_lock = False;
6163 enum brl_type lock_type;
6165 NTSTATUS status = NT_STATUS_OK;
6167 if (fsp == NULL || fsp->fh->fd == -1) {
6168 return NT_STATUS_INVALID_HANDLE;
6171 if (total_data != POSIX_LOCK_DATA_SIZE) {
6172 return NT_STATUS_INVALID_PARAMETER;
6175 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6176 case POSIX_LOCK_TYPE_READ:
6177 lock_type = READ_LOCK;
6179 case POSIX_LOCK_TYPE_WRITE:
6180 /* Return the right POSIX-mappable error code for files opened read-only. */
6181 if (!fsp->can_write) {
6182 return NT_STATUS_INVALID_HANDLE;
6184 lock_type = WRITE_LOCK;
6186 case POSIX_LOCK_TYPE_UNLOCK:
6187 lock_type = UNLOCK_LOCK;
6190 return NT_STATUS_INVALID_PARAMETER;
6193 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6194 blocking_lock = False;
6195 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6196 blocking_lock = True;
6198 return NT_STATUS_INVALID_PARAMETER;
6201 if (!lp_blocking_locks(SNUM(conn))) {
6202 blocking_lock = False;
6205 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6206 #if defined(HAVE_LONGLONG)
6207 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6208 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6209 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6210 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6211 #else /* HAVE_LONGLONG */
6212 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6213 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6214 #endif /* HAVE_LONGLONG */
6216 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6217 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6219 (unsigned int)lock_type,
6220 (unsigned int)lock_pid,
6224 if (lock_type == UNLOCK_LOCK) {
6225 status = do_unlock(smbd_messaging_context(),
6232 uint32 block_smbpid;
6234 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6246 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6248 * A blocking lock was requested. Package up
6249 * this smb into a queued request and push it
6250 * onto the blocking lock queue.
6252 if(push_blocking_lock_request(br_lck,
6255 -1, /* infinite timeout. */
6263 TALLOC_FREE(br_lck);
6267 TALLOC_FREE(br_lck);
6273 /****************************************************************************
6274 Deal with SMB_SET_FILE_BASIC_INFO.
6275 ****************************************************************************/
6277 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6281 const struct smb_filename *smb_fname)
6283 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6284 struct smb_file_time ft;
6286 NTSTATUS status = NT_STATUS_OK;
6290 if (total_data < 36) {
6291 return NT_STATUS_INVALID_PARAMETER;
6294 /* Set the attributes */
6295 dosmode = IVAL(pdata,32);
6296 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6297 if (!NT_STATUS_IS_OK(status)) {
6302 ft.create_time = interpret_long_date(pdata);
6305 ft.atime = interpret_long_date(pdata+8);
6308 ft.mtime = interpret_long_date(pdata+16);
6311 ft.ctime = interpret_long_date(pdata+24);
6313 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6314 smb_fname_str_dbg(smb_fname)));
6316 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6320 /****************************************************************************
6321 Deal with SMB_INFO_STANDARD.
6322 ****************************************************************************/
6324 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6328 const struct smb_filename *smb_fname)
6330 struct smb_file_time ft;
6334 if (total_data < 12) {
6335 return NT_STATUS_INVALID_PARAMETER;
6339 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6341 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6343 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6345 DEBUG(10,("smb_set_info_standard: file %s\n",
6346 smb_fname_str_dbg(smb_fname)));
6348 return smb_set_file_time(conn,
6355 /****************************************************************************
6356 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6357 ****************************************************************************/
6359 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6360 struct smb_request *req,
6364 struct smb_filename *smb_fname)
6366 uint64_t allocation_size = 0;
6367 NTSTATUS status = NT_STATUS_OK;
6368 files_struct *new_fsp = NULL;
6370 if (!VALID_STAT(smb_fname->st)) {
6371 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6374 if (total_data < 8) {
6375 return NT_STATUS_INVALID_PARAMETER;
6378 allocation_size = (uint64_t)IVAL(pdata,0);
6379 #ifdef LARGE_SMB_OFF_T
6380 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6381 #else /* LARGE_SMB_OFF_T */
6382 if (IVAL(pdata,4) != 0) {
6383 /* more than 32 bits? */
6384 return NT_STATUS_INVALID_PARAMETER;
6386 #endif /* LARGE_SMB_OFF_T */
6388 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6389 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6390 (double)allocation_size));
6392 if (allocation_size) {
6393 allocation_size = smb_roundup(conn, allocation_size);
6396 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6397 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6398 (double)allocation_size));
6400 if (fsp && fsp->fh->fd != -1) {
6401 /* Open file handle. */
6402 /* Only change if needed. */
6403 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6404 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6405 return map_nt_error_from_unix(errno);
6408 /* But always update the time. */
6410 * This is equivalent to a write. Ensure it's seen immediately
6411 * if there are no pending writes.
6413 trigger_write_time_update_immediate(fsp);
6414 return NT_STATUS_OK;
6417 /* Pathname or stat or directory file. */
6418 status = SMB_VFS_CREATE_FILE(
6421 0, /* root_dir_fid */
6422 smb_fname, /* fname */
6423 FILE_WRITE_DATA, /* access_mask */
6424 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6426 FILE_OPEN, /* create_disposition*/
6427 0, /* create_options */
6428 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6429 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6430 0, /* allocation_size */
6433 &new_fsp, /* result */
6436 if (!NT_STATUS_IS_OK(status)) {
6437 /* NB. We check for open_was_deferred in the caller. */
6441 /* Only change if needed. */
6442 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6443 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6444 status = map_nt_error_from_unix(errno);
6445 close_file(req, new_fsp, NORMAL_CLOSE);
6450 /* Changing the allocation size should set the last mod time. */
6452 * This is equivalent to a write. Ensure it's seen immediately
6453 * if there are no pending writes.
6455 trigger_write_time_update_immediate(new_fsp);
6457 close_file(req, new_fsp, NORMAL_CLOSE);
6458 return NT_STATUS_OK;
6461 /****************************************************************************
6462 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6463 ****************************************************************************/
6465 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6466 struct smb_request *req,
6470 const struct smb_filename *smb_fname,
6471 bool fail_after_createfile)
6475 if (total_data < 8) {
6476 return NT_STATUS_INVALID_PARAMETER;
6479 size = IVAL(pdata,0);
6480 #ifdef LARGE_SMB_OFF_T
6481 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6482 #else /* LARGE_SMB_OFF_T */
6483 if (IVAL(pdata,4) != 0) {
6484 /* more than 32 bits? */
6485 return NT_STATUS_INVALID_PARAMETER;
6487 #endif /* LARGE_SMB_OFF_T */
6488 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6489 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6492 return smb_set_file_size(conn, req,
6497 fail_after_createfile);
6500 /****************************************************************************
6501 Allow a UNIX info mknod.
6502 ****************************************************************************/
6504 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6507 const struct smb_filename *smb_fname)
6509 uint32 file_type = IVAL(pdata,56);
6510 #if defined(HAVE_MAKEDEV)
6511 uint32 dev_major = IVAL(pdata,60);
6512 uint32 dev_minor = IVAL(pdata,68);
6514 SMB_DEV_T dev = (SMB_DEV_T)0;
6515 uint32 raw_unixmode = IVAL(pdata,84);
6519 if (total_data < 100) {
6520 return NT_STATUS_INVALID_PARAMETER;
6523 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6524 PERM_NEW_FILE, &unixmode);
6525 if (!NT_STATUS_IS_OK(status)) {
6529 #if defined(HAVE_MAKEDEV)
6530 dev = makedev(dev_major, dev_minor);
6533 switch (file_type) {
6534 #if defined(S_IFIFO)
6535 case UNIX_TYPE_FIFO:
6536 unixmode |= S_IFIFO;
6539 #if defined(S_IFSOCK)
6540 case UNIX_TYPE_SOCKET:
6541 unixmode |= S_IFSOCK;
6544 #if defined(S_IFCHR)
6545 case UNIX_TYPE_CHARDEV:
6546 unixmode |= S_IFCHR;
6549 #if defined(S_IFBLK)
6550 case UNIX_TYPE_BLKDEV:
6551 unixmode |= S_IFBLK;
6555 return NT_STATUS_INVALID_PARAMETER;
6558 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6559 "%.0f mode 0%o for file %s\n", (double)dev,
6560 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6562 /* Ok - do the mknod. */
6563 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6564 return map_nt_error_from_unix(errno);
6567 /* If any of the other "set" calls fail we
6568 * don't want to end up with a half-constructed mknod.
6571 if (lp_inherit_perms(SNUM(conn))) {
6573 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6575 return NT_STATUS_NO_MEMORY;
6577 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6579 TALLOC_FREE(parent);
6582 return NT_STATUS_OK;
6585 /****************************************************************************
6586 Deal with SMB_SET_FILE_UNIX_BASIC.
6587 ****************************************************************************/
6589 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6590 struct smb_request *req,
6594 const struct smb_filename *smb_fname)
6596 struct smb_file_time ft;
6597 uint32 raw_unixmode;
6600 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6601 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6602 NTSTATUS status = NT_STATUS_OK;
6603 bool delete_on_fail = False;
6604 enum perm_type ptype;
6605 files_struct *all_fsps = NULL;
6606 bool modify_mtime = true;
6608 struct smb_filename *smb_fname_tmp = NULL;
6609 SMB_STRUCT_STAT sbuf;
6613 if (total_data < 100) {
6614 return NT_STATUS_INVALID_PARAMETER;
6617 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6618 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6619 size=IVAL(pdata,0); /* first 8 Bytes are size */
6620 #ifdef LARGE_SMB_OFF_T
6621 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6622 #else /* LARGE_SMB_OFF_T */
6623 if (IVAL(pdata,4) != 0) {
6624 /* more than 32 bits? */
6625 return NT_STATUS_INVALID_PARAMETER;
6627 #endif /* LARGE_SMB_OFF_T */
6630 ft.atime = interpret_long_date(pdata+24); /* access_time */
6631 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6632 set_owner = (uid_t)IVAL(pdata,40);
6633 set_grp = (gid_t)IVAL(pdata,48);
6634 raw_unixmode = IVAL(pdata,84);
6636 if (VALID_STAT(smb_fname->st)) {
6637 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6638 ptype = PERM_EXISTING_DIR;
6640 ptype = PERM_EXISTING_FILE;
6643 ptype = PERM_NEW_FILE;
6646 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6648 if (!NT_STATUS_IS_OK(status)) {
6652 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6653 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6654 smb_fname_str_dbg(smb_fname), (double)size,
6655 (unsigned int)set_owner, (unsigned int)set_grp,
6656 (int)raw_unixmode));
6658 sbuf = smb_fname->st;
6660 if (!VALID_STAT(sbuf)) {
6662 * The only valid use of this is to create character and block
6663 * devices, and named pipes. This is deprecated (IMHO) and
6664 * a new info level should be used for mknod. JRA.
6667 status = smb_unix_mknod(conn,
6671 if (!NT_STATUS_IS_OK(status)) {
6675 status = copy_smb_filename(talloc_tos(), smb_fname,
6677 if (!NT_STATUS_IS_OK(status)) {
6681 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6682 status = map_nt_error_from_unix(errno);
6683 TALLOC_FREE(smb_fname_tmp);
6684 SMB_VFS_UNLINK(conn, smb_fname);
6688 sbuf = smb_fname_tmp->st;
6689 smb_fname = smb_fname_tmp;
6691 /* Ensure we don't try and change anything else. */
6692 raw_unixmode = SMB_MODE_NO_CHANGE;
6693 size = get_file_size_stat(&sbuf);
6694 ft.atime = sbuf.st_ex_atime;
6695 ft.mtime = sbuf.st_ex_mtime;
6697 * We continue here as we might want to change the
6700 delete_on_fail = True;
6704 /* Horrible backwards compatibility hack as an old server bug
6705 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6709 size = get_file_size_stat(&sbuf);
6714 * Deal with the UNIX specific mode set.
6717 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6718 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6719 "setting mode 0%o for file %s\n",
6720 (unsigned int)unixmode,
6721 smb_fname_str_dbg(smb_fname)));
6722 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6723 return map_nt_error_from_unix(errno);
6728 * Deal with the UNIX specific uid set.
6731 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6732 (sbuf.st_ex_uid != set_owner)) {
6735 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6736 "changing owner %u for path %s\n",
6737 (unsigned int)set_owner,
6738 smb_fname_str_dbg(smb_fname)));
6740 if (S_ISLNK(sbuf.st_ex_mode)) {
6741 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6742 set_owner, (gid_t)-1);
6744 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6745 set_owner, (gid_t)-1);
6749 status = map_nt_error_from_unix(errno);
6750 if (delete_on_fail) {
6751 SMB_VFS_UNLINK(conn, smb_fname);
6758 * Deal with the UNIX specific gid set.
6761 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6762 (sbuf.st_ex_gid != set_grp)) {
6763 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6764 "changing group %u for file %s\n",
6765 (unsigned int)set_owner,
6766 smb_fname_str_dbg(smb_fname)));
6767 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6769 status = map_nt_error_from_unix(errno);
6770 if (delete_on_fail) {
6771 SMB_VFS_UNLINK(conn, smb_fname);
6777 /* Deal with any size changes. */
6779 status = smb_set_file_size(conn, req,
6785 if (!NT_STATUS_IS_OK(status)) {
6789 /* Deal with any time changes. */
6790 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6791 /* No change, don't cancel anything. */
6795 id = vfs_file_id_from_sbuf(conn, &sbuf);
6796 for(all_fsps = file_find_di_first(id); all_fsps;
6797 all_fsps = file_find_di_next(all_fsps)) {
6799 * We're setting the time explicitly for UNIX.
6800 * Cancel any pending changes over all handles.
6802 all_fsps->update_write_time_on_close = false;
6803 TALLOC_FREE(all_fsps->update_write_time_event);
6807 * Override the "setting_write_time"
6808 * parameter here as it almost does what
6809 * we need. Just remember if we modified
6810 * mtime and send the notify ourselves.
6812 if (null_timespec(ft.mtime)) {
6813 modify_mtime = false;
6816 status = smb_set_file_time(conn,
6822 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6823 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6828 /****************************************************************************
6829 Deal with SMB_SET_FILE_UNIX_INFO2.
6830 ****************************************************************************/
6832 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6833 struct smb_request *req,
6837 const struct smb_filename *smb_fname)
6843 if (total_data < 116) {
6844 return NT_STATUS_INVALID_PARAMETER;
6847 /* Start by setting all the fields that are common between UNIX_BASIC
6850 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6852 if (!NT_STATUS_IS_OK(status)) {
6856 smb_fflags = IVAL(pdata, 108);
6857 smb_fmask = IVAL(pdata, 112);
6859 /* NB: We should only attempt to alter the file flags if the client
6860 * sends a non-zero mask.
6862 if (smb_fmask != 0) {
6863 int stat_fflags = 0;
6865 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6866 smb_fmask, &stat_fflags)) {
6867 /* Client asked to alter a flag we don't understand. */
6868 return NT_STATUS_INVALID_PARAMETER;
6871 if (fsp && fsp->fh->fd != -1) {
6872 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6873 return NT_STATUS_NOT_SUPPORTED;
6875 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6876 stat_fflags) != 0) {
6877 return map_nt_error_from_unix(errno);
6882 /* XXX: need to add support for changing the create_time here. You
6883 * can do this for paths on Darwin with setattrlist(2). The right way
6884 * to hook this up is probably by extending the VFS utimes interface.
6887 return NT_STATUS_OK;
6890 /****************************************************************************
6891 Create a directory with POSIX semantics.
6892 ****************************************************************************/
6894 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6895 struct smb_request *req,
6898 struct smb_filename *smb_fname,
6899 int *pdata_return_size)
6901 NTSTATUS status = NT_STATUS_OK;
6902 uint32 raw_unixmode = 0;
6903 uint32 mod_unixmode = 0;
6904 mode_t unixmode = (mode_t)0;
6905 files_struct *fsp = NULL;
6906 uint16 info_level_return = 0;
6908 char *pdata = *ppdata;
6910 if (total_data < 18) {
6911 return NT_STATUS_INVALID_PARAMETER;
6914 raw_unixmode = IVAL(pdata,8);
6915 /* Next 4 bytes are not yet defined. */
6917 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6918 PERM_NEW_DIR, &unixmode);
6919 if (!NT_STATUS_IS_OK(status)) {
6923 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6925 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6926 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6928 status = SMB_VFS_CREATE_FILE(
6931 0, /* root_dir_fid */
6932 smb_fname, /* fname */
6933 FILE_READ_ATTRIBUTES, /* access_mask */
6934 FILE_SHARE_NONE, /* share_access */
6935 FILE_CREATE, /* create_disposition*/
6936 FILE_DIRECTORY_FILE, /* create_options */
6937 mod_unixmode, /* file_attributes */
6938 0, /* oplock_request */
6939 0, /* allocation_size */
6945 if (NT_STATUS_IS_OK(status)) {
6946 close_file(req, fsp, NORMAL_CLOSE);
6949 info_level_return = SVAL(pdata,16);
6951 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6952 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6953 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6954 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6956 *pdata_return_size = 12;
6959 /* Realloc the data size */
6960 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6961 if (*ppdata == NULL) {
6962 *pdata_return_size = 0;
6963 return NT_STATUS_NO_MEMORY;
6967 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6968 SSVAL(pdata,2,0); /* No fnum. */
6969 SIVAL(pdata,4,info); /* Was directory created. */
6971 switch (info_level_return) {
6972 case SMB_QUERY_FILE_UNIX_BASIC:
6973 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6974 SSVAL(pdata,10,0); /* Padding. */
6975 store_file_unix_basic(conn, pdata + 12, fsp,
6978 case SMB_QUERY_FILE_UNIX_INFO2:
6979 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6980 SSVAL(pdata,10,0); /* Padding. */
6981 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6985 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6986 SSVAL(pdata,10,0); /* Padding. */
6993 /****************************************************************************
6994 Open/Create a file with POSIX semantics.
6995 ****************************************************************************/
6997 static NTSTATUS smb_posix_open(connection_struct *conn,
6998 struct smb_request *req,
7001 struct smb_filename *smb_fname,
7002 int *pdata_return_size)
7004 bool extended_oplock_granted = False;
7005 char *pdata = *ppdata;
7007 uint32 wire_open_mode = 0;
7008 uint32 raw_unixmode = 0;
7009 uint32 mod_unixmode = 0;
7010 uint32 create_disp = 0;
7011 uint32 access_mask = 0;
7012 uint32 create_options = 0;
7013 NTSTATUS status = NT_STATUS_OK;
7014 mode_t unixmode = (mode_t)0;
7015 files_struct *fsp = NULL;
7016 int oplock_request = 0;
7018 uint16 info_level_return = 0;
7020 if (total_data < 18) {
7021 return NT_STATUS_INVALID_PARAMETER;
7024 flags = IVAL(pdata,0);
7025 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7026 if (oplock_request) {
7027 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7030 wire_open_mode = IVAL(pdata,4);
7032 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7033 return smb_posix_mkdir(conn, req,
7040 switch (wire_open_mode & SMB_ACCMODE) {
7042 access_mask = FILE_READ_DATA;
7045 access_mask = FILE_WRITE_DATA;
7048 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7051 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7052 (unsigned int)wire_open_mode ));
7053 return NT_STATUS_INVALID_PARAMETER;
7056 wire_open_mode &= ~SMB_ACCMODE;
7058 /* First take care of O_CREAT|O_EXCL interactions. */
7059 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7060 case (SMB_O_CREAT | SMB_O_EXCL):
7061 /* File exists fail. File not exist create. */
7062 create_disp = FILE_CREATE;
7065 /* File exists open. File not exist create. */
7066 create_disp = FILE_OPEN_IF;
7069 /* File exists open. File not exist fail. */
7070 create_disp = FILE_OPEN;
7073 /* O_EXCL on its own without O_CREAT is undefined. */
7075 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7076 (unsigned int)wire_open_mode ));
7077 return NT_STATUS_INVALID_PARAMETER;
7080 /* Next factor in the effects of O_TRUNC. */
7081 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7083 if (wire_open_mode & SMB_O_TRUNC) {
7084 switch (create_disp) {
7086 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7087 /* Leave create_disp alone as
7088 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7090 /* File exists fail. File not exist create. */
7093 /* SMB_O_CREAT | SMB_O_TRUNC */
7094 /* File exists overwrite. File not exist create. */
7095 create_disp = FILE_OVERWRITE_IF;
7099 /* File exists overwrite. File not exist fail. */
7100 create_disp = FILE_OVERWRITE;
7103 /* Cannot get here. */
7104 smb_panic("smb_posix_open: logic error");
7105 return NT_STATUS_INVALID_PARAMETER;
7109 raw_unixmode = IVAL(pdata,8);
7110 /* Next 4 bytes are not yet defined. */
7112 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7113 (VALID_STAT(smb_fname->st) ?
7114 PERM_EXISTING_FILE : PERM_NEW_FILE),
7117 if (!NT_STATUS_IS_OK(status)) {
7121 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7123 if (wire_open_mode & SMB_O_SYNC) {
7124 create_options |= FILE_WRITE_THROUGH;
7126 if (wire_open_mode & SMB_O_APPEND) {
7127 access_mask |= FILE_APPEND_DATA;
7129 if (wire_open_mode & SMB_O_DIRECT) {
7130 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7133 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7134 smb_fname_str_dbg(smb_fname),
7135 (unsigned int)wire_open_mode,
7136 (unsigned int)unixmode ));
7138 status = SMB_VFS_CREATE_FILE(
7141 0, /* root_dir_fid */
7142 smb_fname, /* fname */
7143 access_mask, /* access_mask */
7144 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7146 create_disp, /* create_disposition*/
7147 FILE_NON_DIRECTORY_FILE, /* create_options */
7148 mod_unixmode, /* file_attributes */
7149 oplock_request, /* oplock_request */
7150 0, /* allocation_size */
7156 if (!NT_STATUS_IS_OK(status)) {
7160 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7161 extended_oplock_granted = True;
7164 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7165 extended_oplock_granted = True;
7168 info_level_return = SVAL(pdata,16);
7170 /* Allocate the correct return size. */
7172 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7173 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7174 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7175 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7177 *pdata_return_size = 12;
7180 /* Realloc the data size */
7181 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7182 if (*ppdata == NULL) {
7183 close_file(req, fsp, ERROR_CLOSE);
7184 *pdata_return_size = 0;
7185 return NT_STATUS_NO_MEMORY;
7189 if (extended_oplock_granted) {
7190 if (flags & REQUEST_BATCH_OPLOCK) {
7191 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7193 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7195 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7196 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7198 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7201 SSVAL(pdata,2,fsp->fnum);
7202 SIVAL(pdata,4,info); /* Was file created etc. */
7204 switch (info_level_return) {
7205 case SMB_QUERY_FILE_UNIX_BASIC:
7206 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7207 SSVAL(pdata,10,0); /* padding. */
7208 store_file_unix_basic(conn, pdata + 12, fsp,
7211 case SMB_QUERY_FILE_UNIX_INFO2:
7212 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7213 SSVAL(pdata,10,0); /* padding. */
7214 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7218 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7219 SSVAL(pdata,10,0); /* padding. */
7222 return NT_STATUS_OK;
7225 /****************************************************************************
7226 Delete a file with POSIX semantics.
7227 ****************************************************************************/
7229 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7230 struct smb_request *req,
7233 struct smb_filename *smb_fname)
7235 NTSTATUS status = NT_STATUS_OK;
7236 files_struct *fsp = NULL;
7240 int create_options = 0;
7242 struct share_mode_lock *lck = NULL;
7244 if (total_data < 2) {
7245 return NT_STATUS_INVALID_PARAMETER;
7248 flags = SVAL(pdata,0);
7250 if (!VALID_STAT(smb_fname->st)) {
7251 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7254 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7255 !VALID_STAT_OF_DIR(smb_fname->st)) {
7256 return NT_STATUS_NOT_A_DIRECTORY;
7259 DEBUG(10,("smb_posix_unlink: %s %s\n",
7260 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7261 smb_fname_str_dbg(smb_fname)));
7263 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7264 create_options |= FILE_DIRECTORY_FILE;
7267 status = SMB_VFS_CREATE_FILE(
7270 0, /* root_dir_fid */
7271 smb_fname, /* fname */
7272 DELETE_ACCESS, /* access_mask */
7273 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7275 FILE_OPEN, /* create_disposition*/
7276 create_options, /* create_options */
7277 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7278 0, /* oplock_request */
7279 0, /* allocation_size */
7285 if (!NT_STATUS_IS_OK(status)) {
7290 * Don't lie to client. If we can't really delete due to
7291 * non-POSIX opens return SHARING_VIOLATION.
7294 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7297 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7298 "lock for file %s\n", fsp_str_dbg(fsp)));
7299 close_file(req, fsp, NORMAL_CLOSE);
7300 return NT_STATUS_INVALID_PARAMETER;
7304 * See if others still have the file open. If this is the case, then
7305 * don't delete. If all opens are POSIX delete we can set the delete
7306 * on close disposition.
7308 for (i=0; i<lck->num_share_modes; i++) {
7309 struct share_mode_entry *e = &lck->share_modes[i];
7310 if (is_valid_share_mode_entry(e)) {
7311 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7314 /* Fail with sharing violation. */
7315 close_file(req, fsp, NORMAL_CLOSE);
7317 return NT_STATUS_SHARING_VIOLATION;
7322 * Set the delete on close.
7324 status = smb_set_file_disposition_info(conn,
7330 if (!NT_STATUS_IS_OK(status)) {
7331 close_file(req, fsp, NORMAL_CLOSE);
7336 return close_file(req, fsp, NORMAL_CLOSE);
7339 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7340 struct smb_request *req,
7341 TALLOC_CTX *mem_ctx,
7342 uint16_t info_level,
7344 struct smb_filename *smb_fname,
7345 char **ppdata, int total_data,
7348 char *pdata = *ppdata;
7349 NTSTATUS status = NT_STATUS_OK;
7350 int data_return_size = 0;
7354 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7355 return NT_STATUS_INVALID_LEVEL;
7358 if (!CAN_WRITE(conn)) {
7359 /* Allow POSIX opens. The open path will deny
7360 * any non-readonly opens. */
7361 if (info_level != SMB_POSIX_PATH_OPEN) {
7362 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7366 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7367 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7368 fsp ? fsp->fnum : -1, info_level, total_data));
7370 switch (info_level) {
7372 case SMB_INFO_STANDARD:
7374 status = smb_set_info_standard(conn,
7382 case SMB_INFO_SET_EA:
7384 status = smb_info_set_ea(conn,
7392 case SMB_SET_FILE_BASIC_INFO:
7393 case SMB_FILE_BASIC_INFORMATION:
7395 status = smb_set_file_basic_info(conn,
7403 case SMB_FILE_ALLOCATION_INFORMATION:
7404 case SMB_SET_FILE_ALLOCATION_INFO:
7406 status = smb_set_file_allocation_info(conn, req,
7414 case SMB_FILE_END_OF_FILE_INFORMATION:
7415 case SMB_SET_FILE_END_OF_FILE_INFO:
7418 * XP/Win7 both fail after the createfile with
7419 * SMB_SET_FILE_END_OF_FILE_INFO but not
7420 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7421 * The level is known here, so pass it down
7425 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7427 status = smb_set_file_end_of_file_info(conn, req,
7436 case SMB_FILE_DISPOSITION_INFORMATION:
7437 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7440 /* JRA - We used to just ignore this on a path ?
7441 * Shouldn't this be invalid level on a pathname
7444 if (tran_call != TRANSACT2_SETFILEINFO) {
7445 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7448 status = smb_set_file_disposition_info(conn,
7456 case SMB_FILE_POSITION_INFORMATION:
7458 status = smb_file_position_information(conn,
7465 case SMB_FILE_FULL_EA_INFORMATION:
7467 status = smb_set_file_full_ea_info(conn,
7474 /* From tridge Samba4 :
7475 * MODE_INFORMATION in setfileinfo (I have no
7476 * idea what "mode information" on a file is - it takes a value of 0,
7477 * 2, 4 or 6. What could it be?).
7480 case SMB_FILE_MODE_INFORMATION:
7482 status = smb_file_mode_information(conn,
7489 * CIFS UNIX extensions.
7492 case SMB_SET_FILE_UNIX_BASIC:
7494 status = smb_set_file_unix_basic(conn, req,
7502 case SMB_SET_FILE_UNIX_INFO2:
7504 status = smb_set_file_unix_info2(conn, req,
7512 case SMB_SET_FILE_UNIX_LINK:
7515 /* We must have a pathname for this. */
7516 return NT_STATUS_INVALID_LEVEL;
7518 status = smb_set_file_unix_link(conn, req, pdata,
7519 total_data, smb_fname);
7523 case SMB_SET_FILE_UNIX_HLINK:
7526 /* We must have a pathname for this. */
7527 return NT_STATUS_INVALID_LEVEL;
7529 status = smb_set_file_unix_hlink(conn, req,
7535 case SMB_FILE_RENAME_INFORMATION:
7537 status = smb_file_rename_information(conn, req,
7543 #if defined(HAVE_POSIX_ACLS)
7544 case SMB_SET_POSIX_ACL:
7546 status = smb_set_posix_acl(conn,
7555 case SMB_SET_POSIX_LOCK:
7558 return NT_STATUS_INVALID_LEVEL;
7560 status = smb_set_posix_lock(conn, req,
7561 pdata, total_data, fsp);
7565 case SMB_POSIX_PATH_OPEN:
7568 /* We must have a pathname for this. */
7569 return NT_STATUS_INVALID_LEVEL;
7572 status = smb_posix_open(conn, req,
7580 case SMB_POSIX_PATH_UNLINK:
7583 /* We must have a pathname for this. */
7584 return NT_STATUS_INVALID_LEVEL;
7587 status = smb_posix_unlink(conn, req,
7595 return NT_STATUS_INVALID_LEVEL;
7598 if (!NT_STATUS_IS_OK(status)) {
7602 *ret_data_size = data_return_size;
7603 return NT_STATUS_OK;
7606 /****************************************************************************
7607 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7608 ****************************************************************************/
7610 static void call_trans2setfilepathinfo(connection_struct *conn,
7611 struct smb_request *req,
7612 unsigned int tran_call,
7613 char **pparams, int total_params,
7614 char **ppdata, int total_data,
7615 unsigned int max_data_bytes)
7617 char *params = *pparams;
7618 char *pdata = *ppdata;
7620 struct smb_filename *smb_fname = NULL;
7621 files_struct *fsp = NULL;
7622 NTSTATUS status = NT_STATUS_OK;
7623 int data_return_size = 0;
7626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7630 if (tran_call == TRANSACT2_SETFILEINFO) {
7631 if (total_params < 4) {
7632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7636 fsp = file_fsp(req, SVAL(params,0));
7637 /* Basic check for non-null fsp. */
7638 if (!check_fsp_open(conn, req, fsp)) {
7641 info_level = SVAL(params,2);
7643 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7645 if (!NT_STATUS_IS_OK(status)) {
7646 reply_nterror(req, status);
7650 if(fsp->is_directory || fsp->fh->fd == -1) {
7652 * This is actually a SETFILEINFO on a directory
7653 * handle (returned from an NT SMB). NT5.0 seems
7654 * to do this call. JRA.
7656 if (INFO_LEVEL_IS_UNIX(info_level)) {
7657 /* Always do lstat for UNIX calls. */
7658 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7659 DEBUG(3,("call_trans2setfilepathinfo: "
7660 "SMB_VFS_LSTAT of %s failed "
7662 smb_fname_str_dbg(smb_fname),
7664 reply_nterror(req, map_nt_error_from_unix(errno));
7668 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7669 DEBUG(3,("call_trans2setfilepathinfo: "
7670 "fileinfo of %s failed (%s)\n",
7671 smb_fname_str_dbg(smb_fname),
7673 reply_nterror(req, map_nt_error_from_unix(errno));
7677 } else if (fsp->print_file) {
7679 * Doing a DELETE_ON_CLOSE should cancel a print job.
7681 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7682 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7684 DEBUG(3,("call_trans2setfilepathinfo: "
7685 "Cancelling print job (%s)\n",
7689 send_trans2_replies(conn, req, params, 2,
7695 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7700 * Original code - this is an open file.
7702 if (!check_fsp(conn, req, fsp)) {
7706 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7707 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7708 "of fnum %d failed (%s)\n", fsp->fnum,
7710 reply_nterror(req, map_nt_error_from_unix(errno));
7718 if (total_params < 7) {
7719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7723 info_level = SVAL(params,0);
7724 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7725 total_params - 6, STR_TERMINATE,
7727 if (!NT_STATUS_IS_OK(status)) {
7728 reply_nterror(req, status);
7732 status = filename_convert(req, conn,
7733 req->flags2 & FLAGS2_DFS_PATHNAMES,
7738 if (!NT_STATUS_IS_OK(status)) {
7739 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7740 reply_botherror(req,
7741 NT_STATUS_PATH_NOT_COVERED,
7742 ERRSRV, ERRbadpath);
7745 reply_nterror(req, status);
7749 if (INFO_LEVEL_IS_UNIX(info_level)) {
7751 * For CIFS UNIX extensions the target name may not exist.
7754 /* Always do lstat for UNIX calls. */
7755 SMB_VFS_LSTAT(conn, smb_fname);
7757 } else if (!VALID_STAT(smb_fname->st) &&
7758 SMB_VFS_STAT(conn, smb_fname)) {
7759 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7761 smb_fname_str_dbg(smb_fname),
7763 reply_nterror(req, map_nt_error_from_unix(errno));
7768 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7769 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7770 fsp ? fsp->fnum : -1, info_level,total_data));
7772 /* Realloc the parameter size */
7773 *pparams = (char *)SMB_REALLOC(*pparams,2);
7774 if (*pparams == NULL) {
7775 reply_nterror(req, NT_STATUS_NO_MEMORY);
7782 status = smbd_do_setfilepathinfo(conn, req, req,
7788 if (!NT_STATUS_IS_OK(status)) {
7789 if (open_was_deferred(req->mid)) {
7790 /* We have re-scheduled this call. */
7793 if (blocking_lock_was_deferred(req->mid)) {
7794 /* We have re-scheduled this call. */
7797 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7798 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7799 ERRSRV, ERRbadpath);
7802 if (info_level == SMB_POSIX_PATH_OPEN) {
7803 reply_openerror(req, status);
7807 reply_nterror(req, status);
7811 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7817 /****************************************************************************
7818 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7819 ****************************************************************************/
7821 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7822 char **pparams, int total_params,
7823 char **ppdata, int total_data,
7824 unsigned int max_data_bytes)
7826 struct smb_filename *smb_dname = NULL;
7827 char *params = *pparams;
7828 char *pdata = *ppdata;
7829 char *directory = NULL;
7830 NTSTATUS status = NT_STATUS_OK;
7831 struct ea_list *ea_list = NULL;
7832 TALLOC_CTX *ctx = talloc_tos();
7834 if (!CAN_WRITE(conn)) {
7835 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7839 if (total_params < 5) {
7840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7844 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7845 total_params - 4, STR_TERMINATE,
7847 if (!NT_STATUS_IS_OK(status)) {
7848 reply_nterror(req, status);
7852 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7854 status = filename_convert(ctx,
7856 req->flags2 & FLAGS2_DFS_PATHNAMES,
7862 if (!NT_STATUS_IS_OK(status)) {
7863 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7864 reply_botherror(req,
7865 NT_STATUS_PATH_NOT_COVERED,
7866 ERRSRV, ERRbadpath);
7869 reply_nterror(req, status);
7874 * OS/2 workplace shell seems to send SET_EA requests of "null"
7875 * length (4 bytes containing IVAL 4).
7876 * They seem to have no effect. Bug #3212. JRA.
7879 if (total_data && (total_data != 4)) {
7880 /* Any data in this call is an EA list. */
7881 if (total_data < 10) {
7882 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7886 if (IVAL(pdata,0) > total_data) {
7887 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7888 IVAL(pdata,0), (unsigned int)total_data));
7889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7893 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7900 if (!lp_ea_support(SNUM(conn))) {
7901 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7905 /* If total_data == 4 Windows doesn't care what values
7906 * are placed in that field, it just ignores them.
7907 * The System i QNTC IBM SMB client puts bad values here,
7908 * so ignore them. */
7910 status = create_directory(conn, req, smb_dname);
7912 if (!NT_STATUS_IS_OK(status)) {
7913 reply_nterror(req, status);
7917 /* Try and set any given EA. */
7919 status = set_ea(conn, NULL, smb_dname, ea_list);
7920 if (!NT_STATUS_IS_OK(status)) {
7921 reply_nterror(req, status);
7926 /* Realloc the parameter and data sizes */
7927 *pparams = (char *)SMB_REALLOC(*pparams,2);
7928 if(*pparams == NULL) {
7929 reply_nterror(req, NT_STATUS_NO_MEMORY);
7936 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7939 TALLOC_FREE(smb_dname);
7943 /****************************************************************************
7944 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7945 We don't actually do this - we just send a null response.
7946 ****************************************************************************/
7948 static void call_trans2findnotifyfirst(connection_struct *conn,
7949 struct smb_request *req,
7950 char **pparams, int total_params,
7951 char **ppdata, int total_data,
7952 unsigned int max_data_bytes)
7954 char *params = *pparams;
7957 if (total_params < 6) {
7958 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7962 info_level = SVAL(params,4);
7963 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7965 switch (info_level) {
7970 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7974 /* Realloc the parameter and data sizes */
7975 *pparams = (char *)SMB_REALLOC(*pparams,6);
7976 if (*pparams == NULL) {
7977 reply_nterror(req, NT_STATUS_NO_MEMORY);
7982 SSVAL(params,0,fnf_handle);
7983 SSVAL(params,2,0); /* No changes */
7984 SSVAL(params,4,0); /* No EA errors */
7991 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7996 /****************************************************************************
7997 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7998 changes). Currently this does nothing.
7999 ****************************************************************************/
8001 static void call_trans2findnotifynext(connection_struct *conn,
8002 struct smb_request *req,
8003 char **pparams, int total_params,
8004 char **ppdata, int total_data,
8005 unsigned int max_data_bytes)
8007 char *params = *pparams;
8009 DEBUG(3,("call_trans2findnotifynext\n"));
8011 /* Realloc the parameter and data sizes */
8012 *pparams = (char *)SMB_REALLOC(*pparams,4);
8013 if (*pparams == NULL) {
8014 reply_nterror(req, NT_STATUS_NO_MEMORY);
8019 SSVAL(params,0,0); /* No changes */
8020 SSVAL(params,2,0); /* No EA errors */
8022 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8027 /****************************************************************************
8028 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8029 ****************************************************************************/
8031 static void call_trans2getdfsreferral(connection_struct *conn,
8032 struct smb_request *req,
8033 char **pparams, int total_params,
8034 char **ppdata, int total_data,
8035 unsigned int max_data_bytes)
8037 char *params = *pparams;
8038 char *pathname = NULL;
8040 int max_referral_level;
8041 NTSTATUS status = NT_STATUS_OK;
8042 TALLOC_CTX *ctx = talloc_tos();
8044 DEBUG(10,("call_trans2getdfsreferral\n"));
8046 if (total_params < 3) {
8047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8051 max_referral_level = SVAL(params,0);
8053 if(!lp_host_msdfs()) {
8054 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8058 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8059 total_params - 2, STR_TERMINATE);
8061 reply_nterror(req, NT_STATUS_NOT_FOUND);
8064 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8065 ppdata,&status)) < 0) {
8066 reply_nterror(req, status);
8070 SSVAL(req->inbuf, smb_flg2,
8071 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8072 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8077 #define LMCAT_SPL 0x53
8078 #define LMFUNC_GETJOBID 0x60
8080 /****************************************************************************
8081 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8082 ****************************************************************************/
8084 static void call_trans2ioctl(connection_struct *conn,
8085 struct smb_request *req,
8086 char **pparams, int total_params,
8087 char **ppdata, int total_data,
8088 unsigned int max_data_bytes)
8090 char *pdata = *ppdata;
8091 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8093 /* check for an invalid fid before proceeding */
8096 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8100 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8101 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8102 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8103 if (*ppdata == NULL) {
8104 reply_nterror(req, NT_STATUS_NO_MEMORY);
8109 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8110 CAN ACCEPT THIS IN UNICODE. JRA. */
8112 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8113 srvstr_push(pdata, req->flags2, pdata + 2,
8114 global_myname(), 15,
8115 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8116 srvstr_push(pdata, req->flags2, pdata+18,
8117 lp_servicename(SNUM(conn)), 13,
8118 STR_ASCII|STR_TERMINATE); /* Service name */
8119 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8124 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8125 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8128 /****************************************************************************
8129 Reply to a SMBfindclose (stop trans2 directory search).
8130 ****************************************************************************/
8132 void reply_findclose(struct smb_request *req)
8135 struct smbd_server_connection *sconn = smbd_server_conn;
8137 START_PROFILE(SMBfindclose);
8140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8141 END_PROFILE(SMBfindclose);
8145 dptr_num = SVALS(req->vwv+0, 0);
8147 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8149 dptr_close(sconn, &dptr_num);
8151 reply_outbuf(req, 0, 0);
8153 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8155 END_PROFILE(SMBfindclose);
8159 /****************************************************************************
8160 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8161 ****************************************************************************/
8163 void reply_findnclose(struct smb_request *req)
8167 START_PROFILE(SMBfindnclose);
8170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8171 END_PROFILE(SMBfindnclose);
8175 dptr_num = SVAL(req->vwv+0, 0);
8177 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8179 /* We never give out valid handles for a
8180 findnotifyfirst - so any dptr_num is ok here.
8183 reply_outbuf(req, 0, 0);
8185 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8187 END_PROFILE(SMBfindnclose);
8191 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8192 struct trans_state *state)
8194 if (get_Protocol() >= PROTOCOL_NT1) {
8195 req->flags2 |= 0x40; /* IS_LONG_NAME */
8196 SSVAL(req->inbuf,smb_flg2,req->flags2);
8199 if (conn->encrypt_level == Required && !req->encrypted) {
8200 if (state->call != TRANSACT2_QFSINFO &&
8201 state->call != TRANSACT2_SETFSINFO) {
8202 DEBUG(0,("handle_trans2: encryption required "
8204 (unsigned int)state->call));
8205 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8210 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8212 /* Now we must call the relevant TRANS2 function */
8213 switch(state->call) {
8214 case TRANSACT2_OPEN:
8216 START_PROFILE(Trans2_open);
8217 call_trans2open(conn, req,
8218 &state->param, state->total_param,
8219 &state->data, state->total_data,
8220 state->max_data_return);
8221 END_PROFILE(Trans2_open);
8225 case TRANSACT2_FINDFIRST:
8227 START_PROFILE(Trans2_findfirst);
8228 call_trans2findfirst(conn, req,
8229 &state->param, state->total_param,
8230 &state->data, state->total_data,
8231 state->max_data_return);
8232 END_PROFILE(Trans2_findfirst);
8236 case TRANSACT2_FINDNEXT:
8238 START_PROFILE(Trans2_findnext);
8239 call_trans2findnext(conn, req,
8240 &state->param, state->total_param,
8241 &state->data, state->total_data,
8242 state->max_data_return);
8243 END_PROFILE(Trans2_findnext);
8247 case TRANSACT2_QFSINFO:
8249 START_PROFILE(Trans2_qfsinfo);
8250 call_trans2qfsinfo(conn, req,
8251 &state->param, state->total_param,
8252 &state->data, state->total_data,
8253 state->max_data_return);
8254 END_PROFILE(Trans2_qfsinfo);
8258 case TRANSACT2_SETFSINFO:
8260 START_PROFILE(Trans2_setfsinfo);
8261 call_trans2setfsinfo(conn, req,
8262 &state->param, state->total_param,
8263 &state->data, state->total_data,
8264 state->max_data_return);
8265 END_PROFILE(Trans2_setfsinfo);
8269 case TRANSACT2_QPATHINFO:
8270 case TRANSACT2_QFILEINFO:
8272 START_PROFILE(Trans2_qpathinfo);
8273 call_trans2qfilepathinfo(conn, req, state->call,
8274 &state->param, state->total_param,
8275 &state->data, state->total_data,
8276 state->max_data_return);
8277 END_PROFILE(Trans2_qpathinfo);
8281 case TRANSACT2_SETPATHINFO:
8282 case TRANSACT2_SETFILEINFO:
8284 START_PROFILE(Trans2_setpathinfo);
8285 call_trans2setfilepathinfo(conn, req, state->call,
8286 &state->param, state->total_param,
8287 &state->data, state->total_data,
8288 state->max_data_return);
8289 END_PROFILE(Trans2_setpathinfo);
8293 case TRANSACT2_FINDNOTIFYFIRST:
8295 START_PROFILE(Trans2_findnotifyfirst);
8296 call_trans2findnotifyfirst(conn, req,
8297 &state->param, state->total_param,
8298 &state->data, state->total_data,
8299 state->max_data_return);
8300 END_PROFILE(Trans2_findnotifyfirst);
8304 case TRANSACT2_FINDNOTIFYNEXT:
8306 START_PROFILE(Trans2_findnotifynext);
8307 call_trans2findnotifynext(conn, req,
8308 &state->param, state->total_param,
8309 &state->data, state->total_data,
8310 state->max_data_return);
8311 END_PROFILE(Trans2_findnotifynext);
8315 case TRANSACT2_MKDIR:
8317 START_PROFILE(Trans2_mkdir);
8318 call_trans2mkdir(conn, req,
8319 &state->param, state->total_param,
8320 &state->data, state->total_data,
8321 state->max_data_return);
8322 END_PROFILE(Trans2_mkdir);
8326 case TRANSACT2_GET_DFS_REFERRAL:
8328 START_PROFILE(Trans2_get_dfs_referral);
8329 call_trans2getdfsreferral(conn, req,
8330 &state->param, state->total_param,
8331 &state->data, state->total_data,
8332 state->max_data_return);
8333 END_PROFILE(Trans2_get_dfs_referral);
8337 case TRANSACT2_IOCTL:
8339 START_PROFILE(Trans2_ioctl);
8340 call_trans2ioctl(conn, req,
8341 &state->param, state->total_param,
8342 &state->data, state->total_data,
8343 state->max_data_return);
8344 END_PROFILE(Trans2_ioctl);
8349 /* Error in request */
8350 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8351 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8355 /****************************************************************************
8356 Reply to a SMBtrans2.
8357 ****************************************************************************/
8359 void reply_trans2(struct smb_request *req)
8361 connection_struct *conn = req->conn;
8366 unsigned int tran_call;
8367 struct trans_state *state;
8370 START_PROFILE(SMBtrans2);
8372 if (req->wct < 14) {
8373 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8374 END_PROFILE(SMBtrans2);
8378 dsoff = SVAL(req->vwv+12, 0);
8379 dscnt = SVAL(req->vwv+11, 0);
8380 psoff = SVAL(req->vwv+10, 0);
8381 pscnt = SVAL(req->vwv+9, 0);
8382 tran_call = SVAL(req->vwv+14, 0);
8384 result = allow_new_trans(conn->pending_trans, req->mid);
8385 if (!NT_STATUS_IS_OK(result)) {
8386 DEBUG(2, ("Got invalid trans2 request: %s\n",
8387 nt_errstr(result)));
8388 reply_nterror(req, result);
8389 END_PROFILE(SMBtrans2);
8394 switch (tran_call) {
8395 /* List the allowed trans2 calls on IPC$ */
8396 case TRANSACT2_OPEN:
8397 case TRANSACT2_GET_DFS_REFERRAL:
8398 case TRANSACT2_QFILEINFO:
8399 case TRANSACT2_QFSINFO:
8400 case TRANSACT2_SETFSINFO:
8403 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8404 END_PROFILE(SMBtrans2);
8409 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8410 DEBUG(0, ("talloc failed\n"));
8411 reply_nterror(req, NT_STATUS_NO_MEMORY);
8412 END_PROFILE(SMBtrans2);
8416 state->cmd = SMBtrans2;
8418 state->mid = req->mid;
8419 state->vuid = req->vuid;
8420 state->setup_count = SVAL(req->vwv+13, 0);
8421 state->setup = NULL;
8422 state->total_param = SVAL(req->vwv+0, 0);
8423 state->param = NULL;
8424 state->total_data = SVAL(req->vwv+1, 0);
8426 state->max_param_return = SVAL(req->vwv+2, 0);
8427 state->max_data_return = SVAL(req->vwv+3, 0);
8428 state->max_setup_return = SVAL(req->vwv+4, 0);
8429 state->close_on_completion = BITSETW(req->vwv+5, 0);
8430 state->one_way = BITSETW(req->vwv+5, 1);
8432 state->call = tran_call;
8434 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8435 is so as a sanity check */
8436 if (state->setup_count != 1) {
8438 * Need to have rc=0 for ioctl to get job id for OS/2.
8439 * Network printing will fail if function is not successful.
8440 * Similar function in reply.c will be used if protocol
8441 * is LANMAN1.0 instead of LM1.2X002.
8442 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8443 * outbuf doesn't have to be set(only job id is used).
8445 if ( (state->setup_count == 4)
8446 && (tran_call == TRANSACT2_IOCTL)
8447 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8448 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8449 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8451 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8452 DEBUG(2,("Transaction is %d\n",tran_call));
8454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8455 END_PROFILE(SMBtrans2);
8460 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8463 if (state->total_data) {
8465 if (trans_oob(state->total_data, 0, dscnt)
8466 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8470 /* Can't use talloc here, the core routines do realloc on the
8471 * params and data. */
8472 state->data = (char *)SMB_MALLOC(state->total_data);
8473 if (state->data == NULL) {
8474 DEBUG(0,("reply_trans2: data malloc fail for %u "
8475 "bytes !\n", (unsigned int)state->total_data));
8477 reply_nterror(req, NT_STATUS_NO_MEMORY);
8478 END_PROFILE(SMBtrans2);
8482 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8485 if (state->total_param) {
8487 if (trans_oob(state->total_param, 0, pscnt)
8488 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8492 /* Can't use talloc here, the core routines do realloc on the
8493 * params and data. */
8494 state->param = (char *)SMB_MALLOC(state->total_param);
8495 if (state->param == NULL) {
8496 DEBUG(0,("reply_trans: param malloc fail for %u "
8497 "bytes !\n", (unsigned int)state->total_param));
8498 SAFE_FREE(state->data);
8500 reply_nterror(req, NT_STATUS_NO_MEMORY);
8501 END_PROFILE(SMBtrans2);
8505 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8508 state->received_data = dscnt;
8509 state->received_param = pscnt;
8511 if ((state->received_param == state->total_param) &&
8512 (state->received_data == state->total_data)) {
8514 handle_trans2(conn, req, state);
8516 SAFE_FREE(state->data);
8517 SAFE_FREE(state->param);
8519 END_PROFILE(SMBtrans2);
8523 DLIST_ADD(conn->pending_trans, state);
8525 /* We need to send an interim response then receive the rest
8526 of the parameter/data bytes */
8527 reply_outbuf(req, 0, 0);
8528 show_msg((char *)req->outbuf);
8529 END_PROFILE(SMBtrans2);
8534 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8535 SAFE_FREE(state->data);
8536 SAFE_FREE(state->param);
8538 END_PROFILE(SMBtrans2);
8539 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8543 /****************************************************************************
8544 Reply to a SMBtranss2
8545 ****************************************************************************/
8547 void reply_transs2(struct smb_request *req)
8549 connection_struct *conn = req->conn;
8550 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8551 struct trans_state *state;
8553 START_PROFILE(SMBtranss2);
8555 show_msg((char *)req->inbuf);
8558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8559 END_PROFILE(SMBtranss2);
8563 for (state = conn->pending_trans; state != NULL;
8564 state = state->next) {
8565 if (state->mid == req->mid) {
8570 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8572 END_PROFILE(SMBtranss2);
8576 /* Revise state->total_param and state->total_data in case they have
8577 changed downwards */
8579 if (SVAL(req->vwv+0, 0) < state->total_param)
8580 state->total_param = SVAL(req->vwv+0, 0);
8581 if (SVAL(req->vwv+1, 0) < state->total_data)
8582 state->total_data = SVAL(req->vwv+1, 0);
8584 pcnt = SVAL(req->vwv+2, 0);
8585 poff = SVAL(req->vwv+3, 0);
8586 pdisp = SVAL(req->vwv+4, 0);
8588 dcnt = SVAL(req->vwv+5, 0);
8589 doff = SVAL(req->vwv+6, 0);
8590 ddisp = SVAL(req->vwv+7, 0);
8592 state->received_param += pcnt;
8593 state->received_data += dcnt;
8595 if ((state->received_data > state->total_data) ||
8596 (state->received_param > state->total_param))
8600 if (trans_oob(state->total_param, pdisp, pcnt)
8601 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8604 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8608 if (trans_oob(state->total_data, ddisp, dcnt)
8609 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8612 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8615 if ((state->received_param < state->total_param) ||
8616 (state->received_data < state->total_data)) {
8617 END_PROFILE(SMBtranss2);
8621 handle_trans2(conn, req, state);
8623 DLIST_REMOVE(conn->pending_trans, state);
8624 SAFE_FREE(state->data);
8625 SAFE_FREE(state->param);
8628 END_PROFILE(SMBtranss2);
8633 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8634 DLIST_REMOVE(conn->pending_trans, state);
8635 SAFE_FREE(state->data);
8636 SAFE_FREE(state->param);
8638 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8639 END_PROFILE(SMBtranss2);