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"
30 #include "../librpc/gen_ndr/xattr.h"
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
34 static char *store_file_unix_basic(connection_struct *conn,
37 const SMB_STRUCT_STAT *psbuf);
39 static char *store_file_unix_basic_info2(connection_struct *conn,
42 const SMB_STRUCT_STAT *psbuf);
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
49 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type = get_remote_arch();
55 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
56 val = SMB_ROUNDUP(val,rval);
61 /****************************************************************************
62 Utility functions for dealing with extended attributes.
63 ****************************************************************************/
65 /****************************************************************************
66 Refuse to allow clients to overwrite our private xattrs.
67 ****************************************************************************/
69 static bool samba_private_attr_name(const char *unix_ea_name)
71 static const char * const prohibited_ea_names[] = {
72 SAMBA_POSIX_INHERITANCE_EA_NAME,
73 SAMBA_XATTR_DOS_ATTRIB,
81 for (i = 0; prohibited_ea_names[i]; i++) {
82 if (strequal( prohibited_ea_names[i], unix_ea_name))
85 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
86 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
92 /****************************************************************************
93 Get one EA value. Fill in a struct ea_struct.
94 ****************************************************************************/
96 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
97 files_struct *fsp, const char *fname,
98 const char *ea_name, struct ea_struct *pea)
100 /* Get the value of this xattr. Max size is 64k. */
101 size_t attr_size = 256;
107 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
109 return NT_STATUS_NO_MEMORY;
112 if (fsp && fsp->fh->fd != -1) {
113 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
115 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
118 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
124 return map_nt_error_from_unix(errno);
127 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
128 dump_data(10, (uint8 *)val, sizeret);
131 if (strnequal(ea_name, "user.", 5)) {
132 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
134 pea->name = talloc_strdup(mem_ctx, ea_name);
136 if (pea->name == NULL) {
138 return NT_STATUS_NO_MEMORY;
140 pea->value.data = (unsigned char *)val;
141 pea->value.length = (size_t)sizeret;
145 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
146 files_struct *fsp, const char *fname,
147 char ***pnames, size_t *pnum_names)
149 /* Get a list of all xattrs. Max namesize is 64k. */
150 size_t ea_namelist_size = 1024;
151 char *ea_namelist = NULL;
156 ssize_t sizeret = -1;
158 if (!lp_ea_support(SNUM(conn))) {
167 * TALLOC the result early to get the talloc hierarchy right.
170 names = TALLOC_ARRAY(mem_ctx, char *, 1);
172 DEBUG(0, ("talloc failed\n"));
173 return NT_STATUS_NO_MEMORY;
176 while (ea_namelist_size <= 65536) {
178 ea_namelist = TALLOC_REALLOC_ARRAY(
179 names, ea_namelist, char, ea_namelist_size);
180 if (ea_namelist == NULL) {
181 DEBUG(0, ("talloc failed\n"));
183 return NT_STATUS_NO_MEMORY;
186 if (fsp && fsp->fh->fd != -1) {
187 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
190 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
194 if ((sizeret == -1) && (errno == ERANGE)) {
195 ea_namelist_size *= 2;
204 return map_nt_error_from_unix(errno);
207 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
208 (unsigned int)sizeret));
220 * Ensure the result is 0-terminated
223 if (ea_namelist[sizeret-1] != '\0') {
225 return NT_STATUS_INTERNAL_ERROR;
233 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
237 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
239 DEBUG(0, ("talloc failed\n"));
241 return NT_STATUS_NO_MEMORY;
247 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
248 names[num_names++] = p;
256 *pnum_names = num_names;
260 /****************************************************************************
261 Return a linked list of the total EA's. Plus the total size
262 ****************************************************************************/
264 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
265 const char *fname, size_t *pea_total_len)
267 /* Get a list of all xattrs. Max namesize is 64k. */
270 struct ea_list *ea_list_head = NULL;
275 if (!lp_ea_support(SNUM(conn))) {
279 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
282 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
286 for (i=0; i<num_names; i++) {
287 struct ea_list *listp;
290 if (strnequal(names[i], "system.", 7)
291 || samba_private_attr_name(names[i]))
294 listp = TALLOC_P(mem_ctx, struct ea_list);
299 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
305 push_ascii_fstring(dos_ea_name, listp->ea.name);
308 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
310 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
311 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
312 (unsigned int)listp->ea.value.length));
314 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
318 /* Add on 4 for total length. */
319 if (*pea_total_len) {
323 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
324 (unsigned int)*pea_total_len));
329 /****************************************************************************
330 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
332 ****************************************************************************/
334 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
335 connection_struct *conn, struct ea_list *ea_list)
337 unsigned int ret_data_size = 4;
340 SMB_ASSERT(total_data_size >= 4);
342 if (!lp_ea_support(SNUM(conn))) {
347 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
350 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
351 dos_namelen = strlen(dos_ea_name);
352 if (dos_namelen > 255 || dos_namelen == 0) {
355 if (ea_list->ea.value.length > 65535) {
358 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
362 /* We know we have room. */
363 SCVAL(p,0,ea_list->ea.flags);
364 SCVAL(p,1,dos_namelen);
365 SSVAL(p,2,ea_list->ea.value.length);
366 fstrcpy(p+4, dos_ea_name);
367 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
369 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
370 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
373 ret_data_size = PTR_DIFF(p, pdata);
374 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
375 SIVAL(pdata,0,ret_data_size);
376 return ret_data_size;
379 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
381 unsigned int total_data_size,
382 unsigned int *ret_data_size,
383 connection_struct *conn,
384 struct ea_list *ea_list)
386 uint8_t *p = (uint8_t *)pdata;
387 uint8_t *last_start = NULL;
391 if (!lp_ea_support(SNUM(conn))) {
392 return NT_STATUS_NO_EAS_ON_FILE;
395 for (; ea_list; ea_list = ea_list->next) {
401 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
405 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
406 dos_namelen = strlen(dos_ea_name);
407 if (dos_namelen > 255 || dos_namelen == 0) {
408 return NT_STATUS_INTERNAL_ERROR;
410 if (ea_list->ea.value.length > 65535) {
411 return NT_STATUS_INTERNAL_ERROR;
414 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
417 size_t pad = 4 - (this_size % 4);
421 if (this_size > total_data_size) {
422 return NT_STATUS_INFO_LENGTH_MISMATCH;
425 /* We know we have room. */
426 SIVAL(p, 0x00, 0); /* next offset */
427 SCVAL(p, 0x04, ea_list->ea.flags);
428 SCVAL(p, 0x05, dos_namelen);
429 SSVAL(p, 0x06, ea_list->ea.value.length);
430 fstrcpy((char *)(p+0x08), dos_ea_name);
431 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
433 total_data_size -= this_size;
437 *ret_data_size = PTR_DIFF(p, pdata);
438 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
442 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
444 size_t total_ea_len = 0;
445 TALLOC_CTX *mem_ctx = NULL;
447 if (!lp_ea_support(SNUM(conn))) {
450 mem_ctx = talloc_tos();
451 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
455 /****************************************************************************
456 Ensure the EA name is case insensitive by matching any existing EA name.
457 ****************************************************************************/
459 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
462 TALLOC_CTX *mem_ctx = talloc_tos();
463 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
465 for (; ea_list; ea_list = ea_list->next) {
466 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
467 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
468 &unix_ea_name[5], ea_list->ea.name));
469 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
475 /****************************************************************************
476 Set or delete an extended attribute.
477 ****************************************************************************/
479 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
480 const struct smb_filename *smb_fname, struct ea_list *ea_list)
484 if (!lp_ea_support(SNUM(conn))) {
485 return NT_STATUS_EAS_NOT_SUPPORTED;
488 /* For now setting EAs on streams isn't supported. */
489 fname = smb_fname->base_name;
491 for (;ea_list; ea_list = ea_list->next) {
493 fstring unix_ea_name;
495 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
496 fstrcat(unix_ea_name, ea_list->ea.name);
498 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
500 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
502 if (samba_private_attr_name(unix_ea_name)) {
503 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
504 return NT_STATUS_ACCESS_DENIED;
507 if (ea_list->ea.value.length == 0) {
508 /* Remove the attribute. */
509 if (fsp && (fsp->fh->fd != -1)) {
510 DEBUG(10,("set_ea: deleting ea name %s on "
511 "file %s by file descriptor.\n",
512 unix_ea_name, fsp_str_dbg(fsp)));
513 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
515 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
516 unix_ea_name, fname));
517 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
520 /* Removing a non existent attribute always succeeds. */
521 if (ret == -1 && errno == ENOATTR) {
522 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
528 if (fsp && (fsp->fh->fd != -1)) {
529 DEBUG(10,("set_ea: setting ea name %s on file "
530 "%s by file descriptor.\n",
531 unix_ea_name, fsp_str_dbg(fsp)));
532 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
533 ea_list->ea.value.data, ea_list->ea.value.length, 0);
535 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
536 unix_ea_name, fname));
537 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
538 ea_list->ea.value.data, ea_list->ea.value.length, 0);
544 if (errno == ENOTSUP) {
545 return NT_STATUS_EAS_NOT_SUPPORTED;
548 return map_nt_error_from_unix(errno);
554 /****************************************************************************
555 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
556 ****************************************************************************/
558 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
560 struct ea_list *ea_list_head = NULL;
561 size_t converted_size, offset = 0;
563 while (offset + 2 < data_size) {
564 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
565 unsigned int namelen = CVAL(pdata,offset);
567 offset++; /* Go past the namelen byte. */
569 /* integer wrap paranioa. */
570 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
571 (offset > data_size) || (namelen > data_size) ||
572 (offset + namelen >= data_size)) {
575 /* Ensure the name is null terminated. */
576 if (pdata[offset + namelen] != '\0') {
579 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
581 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
582 "failed: %s", strerror(errno)));
588 offset += (namelen + 1); /* Go past the name + terminating zero. */
589 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
590 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
596 /****************************************************************************
597 Read one EA list entry from the buffer.
598 ****************************************************************************/
600 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
602 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
604 unsigned int namelen;
605 size_t converted_size;
615 eal->ea.flags = CVAL(pdata,0);
616 namelen = CVAL(pdata,1);
617 val_len = SVAL(pdata,2);
619 if (4 + namelen + 1 + val_len > data_size) {
623 /* Ensure the name is null terminated. */
624 if (pdata[namelen + 4] != '\0') {
627 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
628 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
635 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
636 if (!eal->ea.value.data) {
640 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
642 /* Ensure we're null terminated just in case we print the value. */
643 eal->ea.value.data[val_len] = '\0';
644 /* But don't count the null. */
645 eal->ea.value.length--;
648 *pbytes_used = 4 + namelen + 1 + val_len;
651 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
652 dump_data(10, eal->ea.value.data, eal->ea.value.length);
657 /****************************************************************************
658 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
659 ****************************************************************************/
661 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
663 struct ea_list *ea_list_head = NULL;
665 size_t bytes_used = 0;
667 while (offset < data_size) {
668 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
674 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
675 offset += bytes_used;
681 /****************************************************************************
682 Count the total EA size needed.
683 ****************************************************************************/
685 static size_t ea_list_size(struct ea_list *ealist)
688 struct ea_list *listp;
691 for (listp = ealist; listp; listp = listp->next) {
692 push_ascii_fstring(dos_ea_name, listp->ea.name);
693 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
695 /* Add on 4 for total length. */
703 /****************************************************************************
704 Return a union of EA's from a file list and a list of names.
705 The TALLOC context for the two lists *MUST* be identical as we steal
706 memory from one list to add to another. JRA.
707 ****************************************************************************/
709 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
711 struct ea_list *nlistp, *flistp;
713 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
714 for (flistp = file_list; flistp; flistp = flistp->next) {
715 if (strequal(nlistp->ea.name, flistp->ea.name)) {
721 /* Copy the data from this entry. */
722 nlistp->ea.flags = flistp->ea.flags;
723 nlistp->ea.value = flistp->ea.value;
726 nlistp->ea.flags = 0;
727 ZERO_STRUCT(nlistp->ea.value);
731 *total_ea_len = ea_list_size(name_list);
735 /****************************************************************************
736 Send the required number of replies back.
737 We assume all fields other than the data fields are
738 set correctly for the type of call.
739 HACK ! Always assumes smb_setup field is zero.
740 ****************************************************************************/
742 void send_trans2_replies(connection_struct *conn,
743 struct smb_request *req,
750 /* As we are using a protocol > LANMAN1 then the max_send
751 variable must have been set in the sessetupX call.
752 This takes precedence over the max_xmit field in the
753 global struct. These different max_xmit variables should
754 be merged as this is now too confusing */
756 int data_to_send = datasize;
757 int params_to_send = paramsize;
759 const char *pp = params;
760 const char *pd = pdata;
761 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
762 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
763 int data_alignment_offset = 0;
764 bool overflow = False;
765 struct smbd_server_connection *sconn = smbd_server_conn;
766 int max_send = sconn->smb1.sessions.max_send;
768 /* Modify the data_to_send and datasize and set the error if
769 we're trying to send more than max_data_bytes. We still send
770 the part of the packet(s) that fit. Strange, but needed
773 if (max_data_bytes > 0 && datasize > max_data_bytes) {
774 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
775 max_data_bytes, datasize ));
776 datasize = data_to_send = max_data_bytes;
780 /* If there genuinely are no parameters or data to send just send the empty packet */
782 if(params_to_send == 0 && data_to_send == 0) {
783 reply_outbuf(req, 10, 0);
784 show_msg((char *)req->outbuf);
785 if (!srv_send_smb(smbd_server_fd(),
788 IS_CONN_ENCRYPTED(conn),
790 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
792 TALLOC_FREE(req->outbuf);
796 /* When sending params and data ensure that both are nicely aligned */
797 /* Only do this alignment when there is also data to send - else
798 can cause NT redirector problems. */
800 if (((params_to_send % 4) != 0) && (data_to_send != 0))
801 data_alignment_offset = 4 - (params_to_send % 4);
803 /* Space is bufsize minus Netbios over TCP header minus SMB header */
804 /* The alignment_offset is to align the param bytes on an even byte
805 boundary. NT 4.0 Beta needs this to work correctly. */
807 useable_space = max_send - (smb_size
810 + data_alignment_offset);
812 if (useable_space < 0) {
813 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
814 "= %d!!!", useable_space));
815 exit_server_cleanly("send_trans2_replies: Not enough space");
818 while (params_to_send || data_to_send) {
819 /* Calculate whether we will totally or partially fill this packet */
821 total_sent_thistime = params_to_send + data_to_send;
823 /* We can never send more than useable_space */
825 * Note that 'useable_space' does not include the alignment offsets,
826 * but we must include the alignment offsets in the calculation of
827 * the length of the data we send over the wire, as the alignment offsets
828 * are sent here. Fix from Marc_Jacobsen@hp.com.
831 total_sent_thistime = MIN(total_sent_thistime, useable_space);
833 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
834 + data_alignment_offset);
837 * We might have SMBtrans2s in req which was transferred to
838 * the outbuf, fix that.
840 SCVAL(req->outbuf, smb_com, SMBtrans2);
842 /* Set total params and data to be sent */
843 SSVAL(req->outbuf,smb_tprcnt,paramsize);
844 SSVAL(req->outbuf,smb_tdrcnt,datasize);
846 /* Calculate how many parameters and data we can fit into
847 * this packet. Parameters get precedence
850 params_sent_thistime = MIN(params_to_send,useable_space);
851 data_sent_thistime = useable_space - params_sent_thistime;
852 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
854 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
856 /* smb_proff is the offset from the start of the SMB header to the
857 parameter bytes, however the first 4 bytes of outbuf are
858 the Netbios over TCP header. Thus use smb_base() to subtract
859 them from the calculation */
861 SSVAL(req->outbuf,smb_proff,
862 ((smb_buf(req->outbuf)+alignment_offset)
863 - smb_base(req->outbuf)));
865 if(params_sent_thistime == 0)
866 SSVAL(req->outbuf,smb_prdisp,0);
868 /* Absolute displacement of param bytes sent in this packet */
869 SSVAL(req->outbuf,smb_prdisp,pp - params);
871 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
872 if(data_sent_thistime == 0) {
873 SSVAL(req->outbuf,smb_droff,0);
874 SSVAL(req->outbuf,smb_drdisp, 0);
876 /* The offset of the data bytes is the offset of the
877 parameter bytes plus the number of parameters being sent this time */
878 SSVAL(req->outbuf, smb_droff,
879 ((smb_buf(req->outbuf)+alignment_offset)
880 - smb_base(req->outbuf))
881 + params_sent_thistime + data_alignment_offset);
882 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
885 /* Initialize the padding for alignment */
887 if (alignment_offset != 0) {
888 memset(smb_buf(req->outbuf), 0, alignment_offset);
891 /* Copy the param bytes into the packet */
893 if(params_sent_thistime) {
894 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
895 params_sent_thistime);
898 /* Copy in the data bytes */
899 if(data_sent_thistime) {
900 if (data_alignment_offset != 0) {
901 memset((smb_buf(req->outbuf)+alignment_offset+
902 params_sent_thistime), 0,
903 data_alignment_offset);
905 memcpy(smb_buf(req->outbuf)+alignment_offset
906 +params_sent_thistime+data_alignment_offset,
907 pd,data_sent_thistime);
910 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
911 params_sent_thistime, data_sent_thistime, useable_space));
912 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
913 params_to_send, data_to_send, paramsize, datasize));
916 error_packet_set((char *)req->outbuf,
917 ERRDOS,ERRbufferoverflow,
918 STATUS_BUFFER_OVERFLOW,
922 /* Send the packet */
923 show_msg((char *)req->outbuf);
924 if (!srv_send_smb(smbd_server_fd(),
927 IS_CONN_ENCRYPTED(conn),
929 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
931 TALLOC_FREE(req->outbuf);
933 pp += params_sent_thistime;
934 pd += data_sent_thistime;
936 params_to_send -= params_sent_thistime;
937 data_to_send -= data_sent_thistime;
940 if(params_to_send < 0 || data_to_send < 0) {
941 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
942 params_to_send, data_to_send));
950 /****************************************************************************
951 Reply to a TRANSACT2_OPEN.
952 ****************************************************************************/
954 static void call_trans2open(connection_struct *conn,
955 struct smb_request *req,
956 char **pparams, int total_params,
957 char **ppdata, int total_data,
958 unsigned int max_data_bytes)
960 struct smb_filename *smb_fname = NULL;
961 char *params = *pparams;
962 char *pdata = *ppdata;
967 bool return_additional_info;
980 struct ea_list *ea_list = NULL;
985 uint32 create_disposition;
986 uint32 create_options = 0;
987 uint32_t private_flags = 0;
988 TALLOC_CTX *ctx = talloc_tos();
991 * Ensure we have enough parameters to perform the operation.
994 if (total_params < 29) {
995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
999 flags = SVAL(params, 0);
1000 deny_mode = SVAL(params, 2);
1001 open_attr = SVAL(params,6);
1002 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1003 if (oplock_request) {
1004 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1008 return_additional_info = BITSETW(params,0);
1009 open_sattr = SVAL(params, 4);
1010 open_time = make_unix_date3(params+8);
1012 open_ofun = SVAL(params,12);
1013 open_size = IVAL(params,14);
1014 pname = ¶ms[28];
1017 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1021 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1022 total_params - 28, STR_TERMINATE,
1024 if (!NT_STATUS_IS_OK(status)) {
1025 reply_nterror(req, status);
1029 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1030 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1031 (unsigned int)open_ofun, open_size));
1033 status = filename_convert(ctx,
1035 req->flags2 & FLAGS2_DFS_PATHNAMES,
1040 if (!NT_STATUS_IS_OK(status)) {
1041 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1042 reply_botherror(req,
1043 NT_STATUS_PATH_NOT_COVERED,
1044 ERRSRV, ERRbadpath);
1047 reply_nterror(req, status);
1051 if (open_ofun == 0) {
1052 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1056 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1057 &access_mask, &share_mode,
1058 &create_disposition,
1061 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1065 /* Any data in this call is an EA list. */
1066 if (total_data && (total_data != 4)) {
1067 if (total_data < 10) {
1068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1072 if (IVAL(pdata,0) > total_data) {
1073 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1074 IVAL(pdata,0), (unsigned int)total_data));
1075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1079 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1086 if (!lp_ea_support(SNUM(conn))) {
1087 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1092 status = SMB_VFS_CREATE_FILE(
1095 0, /* root_dir_fid */
1096 smb_fname, /* fname */
1097 access_mask, /* access_mask */
1098 share_mode, /* share_access */
1099 create_disposition, /* create_disposition*/
1100 create_options, /* create_options */
1101 open_attr, /* file_attributes */
1102 oplock_request, /* oplock_request */
1103 open_size, /* allocation_size */
1106 ea_list, /* ea_list */
1108 &smb_action); /* psbuf */
1110 if (!NT_STATUS_IS_OK(status)) {
1111 if (open_was_deferred(req->mid)) {
1112 /* We have re-scheduled this call. */
1115 reply_openerror(req, status);
1119 size = get_file_size_stat(&smb_fname->st);
1120 fattr = dos_mode(conn, smb_fname);
1121 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1122 inode = smb_fname->st.st_ex_ino;
1124 close_file(req, fsp, ERROR_CLOSE);
1125 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1129 /* Realloc the size of parameters and data we will return */
1130 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1131 if(*pparams == NULL ) {
1132 reply_nterror(req, NT_STATUS_NO_MEMORY);
1137 SSVAL(params,0,fsp->fnum);
1138 SSVAL(params,2,fattr);
1139 srv_put_dos_date2(params,4, mtime);
1140 SIVAL(params,8, (uint32)size);
1141 SSVAL(params,12,deny_mode);
1142 SSVAL(params,14,0); /* open_type - file or directory. */
1143 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1145 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1146 smb_action |= EXTENDED_OPLOCK_GRANTED;
1149 SSVAL(params,18,smb_action);
1152 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1154 SIVAL(params,20,inode);
1155 SSVAL(params,24,0); /* Padding. */
1157 uint32 ea_size = estimate_ea_size(conn, fsp,
1158 fsp->fsp_name->base_name);
1159 SIVAL(params, 26, ea_size);
1161 SIVAL(params, 26, 0);
1164 /* Send the required number of replies */
1165 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1167 TALLOC_FREE(smb_fname);
1170 /*********************************************************
1171 Routine to check if a given string matches exactly.
1172 as a special case a mask of "." does NOT match. That
1173 is required for correct wildcard semantics
1174 Case can be significant or not.
1175 **********************************************************/
1177 static bool exact_match(bool has_wild,
1178 bool case_sensitive,
1182 if (mask[0] == '.' && mask[1] == 0) {
1190 if (case_sensitive) {
1191 return strcmp(str,mask)==0;
1193 return StrCaseCmp(str,mask) == 0;
1197 /****************************************************************************
1198 Return the filetype for UNIX extensions.
1199 ****************************************************************************/
1201 static uint32 unix_filetype(mode_t mode)
1204 return UNIX_TYPE_FILE;
1205 else if(S_ISDIR(mode))
1206 return UNIX_TYPE_DIR;
1208 else if(S_ISLNK(mode))
1209 return UNIX_TYPE_SYMLINK;
1212 else if(S_ISCHR(mode))
1213 return UNIX_TYPE_CHARDEV;
1216 else if(S_ISBLK(mode))
1217 return UNIX_TYPE_BLKDEV;
1220 else if(S_ISFIFO(mode))
1221 return UNIX_TYPE_FIFO;
1224 else if(S_ISSOCK(mode))
1225 return UNIX_TYPE_SOCKET;
1228 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1229 return UNIX_TYPE_UNKNOWN;
1232 /****************************************************************************
1233 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1234 ****************************************************************************/
1236 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1238 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1239 const SMB_STRUCT_STAT *psbuf,
1241 enum perm_type ptype,
1246 if (perms == SMB_MODE_NO_CHANGE) {
1247 if (!VALID_STAT(*psbuf)) {
1248 return NT_STATUS_INVALID_PARAMETER;
1250 *ret_perms = psbuf->st_ex_mode;
1251 return NT_STATUS_OK;
1255 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1256 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1257 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1258 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1259 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1260 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1261 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1262 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1263 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1265 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1268 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1271 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1276 /* Apply mode mask */
1277 ret &= lp_create_mask(SNUM(conn));
1278 /* Add in force bits */
1279 ret |= lp_force_create_mode(SNUM(conn));
1282 ret &= lp_dir_mask(SNUM(conn));
1283 /* Add in force bits */
1284 ret |= lp_force_dir_mode(SNUM(conn));
1286 case PERM_EXISTING_FILE:
1287 /* Apply mode mask */
1288 ret &= lp_security_mask(SNUM(conn));
1289 /* Add in force bits */
1290 ret |= lp_force_security_mode(SNUM(conn));
1292 case PERM_EXISTING_DIR:
1293 /* Apply mode mask */
1294 ret &= lp_dir_security_mask(SNUM(conn));
1295 /* Add in force bits */
1296 ret |= lp_force_dir_security_mode(SNUM(conn));
1301 return NT_STATUS_OK;
1304 /****************************************************************************
1305 Needed to show the msdfs symlinks as directories. Modifies psbuf
1306 to be a directory if it's a msdfs link.
1307 ****************************************************************************/
1309 static bool check_msdfs_link(connection_struct *conn,
1310 const char *pathname,
1311 SMB_STRUCT_STAT *psbuf)
1313 int saved_errno = errno;
1314 if(lp_host_msdfs() &&
1315 lp_msdfs_root(SNUM(conn)) &&
1316 is_msdfs_link(conn, pathname, psbuf)) {
1318 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1321 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1322 errno = saved_errno;
1325 errno = saved_errno;
1330 /****************************************************************************
1331 Get a level dependent lanman2 dir entry.
1332 ****************************************************************************/
1334 struct smbd_dirptr_lanman2_state {
1335 connection_struct *conn;
1336 uint32_t info_level;
1337 bool check_mangled_names;
1339 bool got_exact_match;
1342 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1348 struct smbd_dirptr_lanman2_state *state =
1349 (struct smbd_dirptr_lanman2_state *)private_data;
1351 char mangled_name[13]; /* mangled 8.3 name. */
1355 /* Mangle fname if it's an illegal name. */
1356 if (mangle_must_mangle(dname, state->conn->params)) {
1357 ok = name_to_8_3(dname, mangled_name,
1358 true, state->conn->params);
1362 fname = mangled_name;
1367 got_match = exact_match(state->has_wild,
1368 state->conn->case_sensitive,
1370 state->got_exact_match = got_match;
1372 got_match = mask_match(fname, mask,
1373 state->conn->case_sensitive);
1376 if(!got_match && state->check_mangled_names &&
1377 !mangle_is_8_3(fname, false, state->conn->params)) {
1379 * It turns out that NT matches wildcards against
1380 * both long *and* short names. This may explain some
1381 * of the wildcard wierdness from old DOS clients
1382 * that some people have been seeing.... JRA.
1384 /* Force the mangling into 8.3. */
1385 ok = name_to_8_3(fname, mangled_name,
1386 false, state->conn->params);
1391 got_match = exact_match(state->has_wild,
1392 state->conn->case_sensitive,
1393 mangled_name, mask);
1394 state->got_exact_match = got_match;
1396 got_match = mask_match(mangled_name, mask,
1397 state->conn->case_sensitive);
1405 *_fname = talloc_strdup(ctx, fname);
1406 if (*_fname == NULL) {
1413 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1415 struct smb_filename *smb_fname,
1418 struct smbd_dirptr_lanman2_state *state =
1419 (struct smbd_dirptr_lanman2_state *)private_data;
1420 bool ms_dfs_link = false;
1423 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1424 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1425 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1426 "Couldn't lstat [%s] (%s)\n",
1427 smb_fname_str_dbg(smb_fname),
1431 } else if (!VALID_STAT(smb_fname->st) &&
1432 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1433 /* Needed to show the msdfs symlinks as
1436 ms_dfs_link = check_msdfs_link(state->conn,
1437 smb_fname->base_name,
1440 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1441 "Couldn't stat [%s] (%s)\n",
1442 smb_fname_str_dbg(smb_fname),
1449 mode = dos_mode_msdfs(state->conn, smb_fname);
1451 mode = dos_mode(state->conn, smb_fname);
1458 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1459 connection_struct *conn,
1461 uint32_t info_level,
1462 struct ea_list *name_list,
1463 bool check_mangled_names,
1464 bool requires_resume_key,
1467 const struct smb_filename *smb_fname,
1468 int space_remaining,
1475 uint64_t *last_entry_off)
1477 char *p, *q, *pdata = *ppdata;
1479 uint64_t file_size = 0;
1480 uint64_t allocation_size = 0;
1482 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1483 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1484 time_t c_date = (time_t)0;
1486 char *last_entry_ptr;
1491 *out_of_space = false;
1493 ZERO_STRUCT(mdate_ts);
1494 ZERO_STRUCT(adate_ts);
1495 ZERO_STRUCT(create_date_ts);
1496 ZERO_STRUCT(cdate_ts);
1498 if (!(mode & aDIR)) {
1499 file_size = get_file_size_stat(&smb_fname->st);
1501 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1503 mdate_ts = smb_fname->st.st_ex_mtime;
1504 adate_ts = smb_fname->st.st_ex_atime;
1505 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1506 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1508 if (lp_dos_filetime_resolution(SNUM(conn))) {
1509 dos_filetime_timespec(&create_date_ts);
1510 dos_filetime_timespec(&mdate_ts);
1511 dos_filetime_timespec(&adate_ts);
1512 dos_filetime_timespec(&cdate_ts);
1515 create_date = convert_timespec_to_time_t(create_date_ts);
1516 mdate = convert_timespec_to_time_t(mdate_ts);
1517 adate = convert_timespec_to_time_t(adate_ts);
1518 c_date = convert_timespec_to_time_t(cdate_ts);
1520 /* align the record */
1521 SMB_ASSERT(align >= 1);
1523 off = (int)PTR_DIFF(pdata, base_data);
1524 pad = (off + (align-1)) & ~(align-1);
1527 if (pad && pad > space_remaining) {
1528 *out_of_space = true;
1529 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1530 "for padding (wanted %u, had %d)\n",
1533 return false; /* Not finished - just out of space */
1537 /* initialize padding to 0 */
1539 memset(pdata, 0, pad);
1541 space_remaining -= pad;
1543 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1553 switch (info_level) {
1554 case SMB_FIND_INFO_STANDARD:
1555 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1556 if(requires_resume_key) {
1560 srv_put_dos_date2(p,0,create_date);
1561 srv_put_dos_date2(p,4,adate);
1562 srv_put_dos_date2(p,8,mdate);
1563 SIVAL(p,12,(uint32)file_size);
1564 SIVAL(p,16,(uint32)allocation_size);
1568 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1569 p += ucs2_align(base_data, p, 0);
1571 len = srvstr_push(base_data, flags2, p,
1572 fname, PTR_DIFF(end_data, p),
1574 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1576 SCVAL(nameptr, -1, len - 2);
1578 SCVAL(nameptr, -1, 0);
1582 SCVAL(nameptr, -1, len - 1);
1584 SCVAL(nameptr, -1, 0);
1590 case SMB_FIND_EA_SIZE:
1591 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1592 if (requires_resume_key) {
1596 srv_put_dos_date2(p,0,create_date);
1597 srv_put_dos_date2(p,4,adate);
1598 srv_put_dos_date2(p,8,mdate);
1599 SIVAL(p,12,(uint32)file_size);
1600 SIVAL(p,16,(uint32)allocation_size);
1603 unsigned int ea_size = estimate_ea_size(conn, NULL,
1604 smb_fname->base_name);
1605 SIVAL(p,22,ea_size); /* Extended attributes */
1609 len = srvstr_push(base_data, flags2,
1610 p, fname, PTR_DIFF(end_data, p),
1611 STR_TERMINATE | STR_NOALIGN);
1612 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1625 SCVAL(nameptr,0,len);
1627 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1630 case SMB_FIND_EA_LIST:
1632 struct ea_list *file_list = NULL;
1635 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1639 if (requires_resume_key) {
1643 srv_put_dos_date2(p,0,create_date);
1644 srv_put_dos_date2(p,4,adate);
1645 srv_put_dos_date2(p,8,mdate);
1646 SIVAL(p,12,(uint32)file_size);
1647 SIVAL(p,16,(uint32)allocation_size);
1649 p += 22; /* p now points to the EA area. */
1651 file_list = get_ea_list_from_file(ctx, conn, NULL,
1652 smb_fname->base_name,
1654 name_list = ea_list_union(name_list, file_list, &ea_len);
1656 /* We need to determine if this entry will fit in the space available. */
1657 /* Max string size is 255 bytes. */
1658 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1659 *out_of_space = true;
1660 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1661 "(wanted %u, had %d)\n",
1662 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1664 return False; /* Not finished - just out of space */
1667 /* Push the ea_data followed by the name. */
1668 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1670 len = srvstr_push(base_data, flags2,
1671 p + 1, fname, PTR_DIFF(end_data, p+1),
1672 STR_TERMINATE | STR_NOALIGN);
1673 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1686 SCVAL(nameptr,0,len);
1688 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1692 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1693 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1694 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1696 SIVAL(p,0,reskey); p += 4;
1697 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1698 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1699 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1700 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1701 SOFF_T(p,0,file_size); p += 8;
1702 SOFF_T(p,0,allocation_size); p += 8;
1703 SIVAL(p,0,mode); p += 4;
1704 q = p; p += 4; /* q is placeholder for name length. */
1706 unsigned int ea_size = estimate_ea_size(conn, NULL,
1707 smb_fname->base_name);
1708 SIVAL(p,0,ea_size); /* Extended attributes */
1711 /* Clear the short name buffer. This is
1712 * IMPORTANT as not doing so will trigger
1713 * a Win2k client bug. JRA.
1715 if (!was_8_3 && check_mangled_names) {
1716 char mangled_name[13]; /* mangled 8.3 name. */
1717 if (!name_to_8_3(fname,mangled_name,True,
1719 /* Error - mangle failed ! */
1720 memset(mangled_name,'\0',12);
1722 mangled_name[12] = 0;
1723 len = srvstr_push(base_data, flags2,
1724 p+2, mangled_name, 24,
1725 STR_UPPER|STR_UNICODE);
1727 memset(p + 2 + len,'\0',24 - len);
1734 len = srvstr_push(base_data, flags2, p,
1735 fname, PTR_DIFF(end_data, p),
1736 STR_TERMINATE_ASCII);
1740 len = PTR_DIFF(p, pdata);
1741 pad = (len + (align-1)) & ~(align-1);
1743 * offset to the next entry, the caller
1744 * will overwrite it for the last entry
1745 * that's why we always include the padding
1749 * set padding to zero
1752 memset(p, 0, pad - len);
1759 case SMB_FIND_FILE_DIRECTORY_INFO:
1760 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1762 SIVAL(p,0,reskey); p += 4;
1763 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1764 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1765 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1766 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1767 SOFF_T(p,0,file_size); p += 8;
1768 SOFF_T(p,0,allocation_size); p += 8;
1769 SIVAL(p,0,mode); p += 4;
1770 len = srvstr_push(base_data, flags2,
1771 p + 4, fname, PTR_DIFF(end_data, p+4),
1772 STR_TERMINATE_ASCII);
1776 len = PTR_DIFF(p, pdata);
1777 pad = (len + (align-1)) & ~(align-1);
1779 * offset to the next entry, the caller
1780 * will overwrite it for the last entry
1781 * that's why we always include the padding
1785 * set padding to zero
1788 memset(p, 0, pad - len);
1795 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1796 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1798 SIVAL(p,0,reskey); p += 4;
1799 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1800 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1801 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1802 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1803 SOFF_T(p,0,file_size); p += 8;
1804 SOFF_T(p,0,allocation_size); p += 8;
1805 SIVAL(p,0,mode); p += 4;
1806 q = p; p += 4; /* q is placeholder for name length. */
1808 unsigned int ea_size = estimate_ea_size(conn, NULL,
1809 smb_fname->base_name);
1810 SIVAL(p,0,ea_size); /* Extended attributes */
1813 len = srvstr_push(base_data, flags2, p,
1814 fname, PTR_DIFF(end_data, p),
1815 STR_TERMINATE_ASCII);
1819 len = PTR_DIFF(p, pdata);
1820 pad = (len + (align-1)) & ~(align-1);
1822 * offset to the next entry, the caller
1823 * will overwrite it for the last entry
1824 * that's why we always include the padding
1828 * set padding to zero
1831 memset(p, 0, pad - len);
1838 case SMB_FIND_FILE_NAMES_INFO:
1839 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1841 SIVAL(p,0,reskey); p += 4;
1843 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1844 acl on a dir (tridge) */
1845 len = srvstr_push(base_data, flags2, p,
1846 fname, PTR_DIFF(end_data, p),
1847 STR_TERMINATE_ASCII);
1851 len = PTR_DIFF(p, pdata);
1852 pad = (len + (align-1)) & ~(align-1);
1854 * offset to the next entry, the caller
1855 * will overwrite it for the last entry
1856 * that's why we always include the padding
1860 * set padding to zero
1863 memset(p, 0, pad - len);
1870 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1871 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1873 SIVAL(p,0,reskey); p += 4;
1874 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1876 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1877 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1878 SOFF_T(p,0,file_size); p += 8;
1879 SOFF_T(p,0,allocation_size); p += 8;
1880 SIVAL(p,0,mode); p += 4;
1881 q = p; p += 4; /* q is placeholder for name length. */
1883 unsigned int ea_size = estimate_ea_size(conn, NULL,
1884 smb_fname->base_name);
1885 SIVAL(p,0,ea_size); /* Extended attributes */
1888 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1889 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1890 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1891 len = srvstr_push(base_data, flags2, p,
1892 fname, PTR_DIFF(end_data, p),
1893 STR_TERMINATE_ASCII);
1897 len = PTR_DIFF(p, pdata);
1898 pad = (len + (align-1)) & ~(align-1);
1900 * offset to the next entry, the caller
1901 * will overwrite it for the last entry
1902 * that's why we always include the padding
1906 * set padding to zero
1909 memset(p, 0, pad - len);
1916 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1917 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1918 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1920 SIVAL(p,0,reskey); p += 4;
1921 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1923 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1924 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1925 SOFF_T(p,0,file_size); p += 8;
1926 SOFF_T(p,0,allocation_size); p += 8;
1927 SIVAL(p,0,mode); p += 4;
1928 q = p; p += 4; /* q is placeholder for name length */
1930 unsigned int ea_size = estimate_ea_size(conn, NULL,
1931 smb_fname->base_name);
1932 SIVAL(p,0,ea_size); /* Extended attributes */
1935 /* Clear the short name buffer. This is
1936 * IMPORTANT as not doing so will trigger
1937 * a Win2k client bug. JRA.
1939 if (!was_8_3 && check_mangled_names) {
1940 char mangled_name[13]; /* mangled 8.3 name. */
1941 if (!name_to_8_3(fname,mangled_name,True,
1943 /* Error - mangle failed ! */
1944 memset(mangled_name,'\0',12);
1946 mangled_name[12] = 0;
1947 len = srvstr_push(base_data, flags2,
1948 p+2, mangled_name, 24,
1949 STR_UPPER|STR_UNICODE);
1952 memset(p + 2 + len,'\0',24 - len);
1959 SSVAL(p,0,0); p += 2; /* Reserved ? */
1960 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1961 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1962 len = srvstr_push(base_data, flags2, p,
1963 fname, PTR_DIFF(end_data, p),
1964 STR_TERMINATE_ASCII);
1968 len = PTR_DIFF(p, pdata);
1969 pad = (len + (align-1)) & ~(align-1);
1971 * offset to the next entry, the caller
1972 * will overwrite it for the last entry
1973 * that's why we always include the padding
1977 * set padding to zero
1980 memset(p, 0, pad - len);
1987 /* CIFS UNIX Extension. */
1989 case SMB_FIND_FILE_UNIX:
1990 case SMB_FIND_FILE_UNIX_INFO2:
1992 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1994 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1996 if (info_level == SMB_FIND_FILE_UNIX) {
1997 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1998 p = store_file_unix_basic(conn, p,
1999 NULL, &smb_fname->st);
2000 len = srvstr_push(base_data, flags2, p,
2001 fname, PTR_DIFF(end_data, p),
2004 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2005 p = store_file_unix_basic_info2(conn, p,
2006 NULL, &smb_fname->st);
2009 len = srvstr_push(base_data, flags2, p, fname,
2010 PTR_DIFF(end_data, p), 0);
2011 SIVAL(nameptr, 0, len);
2016 len = PTR_DIFF(p, pdata);
2017 pad = (len + (align-1)) & ~(align-1);
2019 * offset to the next entry, the caller
2020 * will overwrite it for the last entry
2021 * that's why we always include the padding
2025 * set padding to zero
2028 memset(p, 0, pad - len);
2033 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2041 if (PTR_DIFF(p,pdata) > space_remaining) {
2042 *out_of_space = true;
2043 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2044 "(wanted %u, had %d)\n",
2045 (unsigned int)PTR_DIFF(p,pdata),
2047 return false; /* Not finished - just out of space */
2050 /* Setup the last entry pointer, as an offset from base_data */
2051 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2052 /* Advance the data pointer to the next slot */
2058 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2059 connection_struct *conn,
2060 struct dptr_struct *dirptr,
2062 const char *path_mask,
2065 int requires_resume_key,
2073 int space_remaining,
2075 bool *got_exact_match,
2076 int *_last_entry_off,
2077 struct ea_list *name_list)
2080 const char *mask = NULL;
2081 long prev_dirpos = 0;
2084 struct smb_filename *smb_fname = NULL;
2085 struct smbd_dirptr_lanman2_state state;
2087 uint64_t last_entry_off = 0;
2091 state.info_level = info_level;
2092 state.check_mangled_names = lp_manglednames(conn->params);
2093 state.has_wild = dptr_has_wild(dirptr);
2094 state.got_exact_match = false;
2096 *out_of_space = false;
2097 *got_exact_match = false;
2099 p = strrchr_m(path_mask,'/');
2110 ok = smbd_dirptr_get_entry(ctx,
2116 smbd_dirptr_lanman2_match_fn,
2117 smbd_dirptr_lanman2_mode_fn,
2127 *got_exact_match = state.got_exact_match;
2129 ok = smbd_marshall_dir_entry(ctx,
2134 state.check_mangled_names,
2135 requires_resume_key,
2148 TALLOC_FREE(smb_fname);
2149 if (*out_of_space) {
2150 dptr_SeekDir(dirptr, prev_dirpos);
2157 *_last_entry_off = last_entry_off;
2161 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2162 connection_struct *conn,
2163 struct dptr_struct *dirptr,
2165 const char *path_mask,
2168 bool requires_resume_key,
2174 int space_remaining,
2176 bool *got_exact_match,
2177 int *last_entry_off,
2178 struct ea_list *name_list)
2181 const bool do_pad = true;
2183 if (info_level >= 1 && info_level <= 3) {
2184 /* No alignment on earlier info levels. */
2188 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2189 path_mask, dirtype, info_level,
2190 requires_resume_key, dont_descend, ask_sharemode,
2192 ppdata, base_data, end_data,
2194 out_of_space, got_exact_match,
2195 last_entry_off, name_list);
2198 /****************************************************************************
2199 Reply to a TRANS2_FINDFIRST.
2200 ****************************************************************************/
2202 static void call_trans2findfirst(connection_struct *conn,
2203 struct smb_request *req,
2204 char **pparams, int total_params,
2205 char **ppdata, int total_data,
2206 unsigned int max_data_bytes)
2208 /* We must be careful here that we don't return more than the
2209 allowed number of data bytes. If this means returning fewer than
2210 maxentries then so be it. We assume that the redirector has
2211 enough room for the fixed number of parameter bytes it has
2213 struct smb_filename *smb_dname = NULL;
2214 char *params = *pparams;
2215 char *pdata = *ppdata;
2219 uint16 findfirst_flags;
2220 bool close_after_first;
2222 bool requires_resume_key;
2224 char *directory = NULL;
2227 int last_entry_off=0;
2231 bool finished = False;
2232 bool dont_descend = False;
2233 bool out_of_space = False;
2234 int space_remaining;
2235 bool mask_contains_wcard = False;
2236 struct ea_list *ea_list = NULL;
2237 NTSTATUS ntstatus = NT_STATUS_OK;
2238 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2239 TALLOC_CTX *ctx = talloc_tos();
2240 struct dptr_struct *dirptr = NULL;
2241 struct smbd_server_connection *sconn = smbd_server_conn;
2243 if (total_params < 13) {
2244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2248 dirtype = SVAL(params,0);
2249 maxentries = SVAL(params,2);
2250 findfirst_flags = SVAL(params,4);
2251 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2252 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2253 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2254 info_level = SVAL(params,6);
2256 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2257 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2258 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2259 info_level, max_data_bytes));
2262 /* W2K3 seems to treat zero as 1. */
2266 switch (info_level) {
2267 case SMB_FIND_INFO_STANDARD:
2268 case SMB_FIND_EA_SIZE:
2269 case SMB_FIND_EA_LIST:
2270 case SMB_FIND_FILE_DIRECTORY_INFO:
2271 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2272 case SMB_FIND_FILE_NAMES_INFO:
2273 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2274 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2275 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2277 case SMB_FIND_FILE_UNIX:
2278 case SMB_FIND_FILE_UNIX_INFO2:
2279 /* Always use filesystem for UNIX mtime query. */
2280 ask_sharemode = false;
2281 if (!lp_unix_extensions()) {
2282 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2287 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2291 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2292 params+12, total_params - 12,
2293 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2294 if (!NT_STATUS_IS_OK(ntstatus)) {
2295 reply_nterror(req, ntstatus);
2299 ntstatus = filename_convert(ctx, conn,
2300 req->flags2 & FLAGS2_DFS_PATHNAMES,
2303 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2304 &mask_contains_wcard,
2306 if (!NT_STATUS_IS_OK(ntstatus)) {
2307 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2308 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2309 ERRSRV, ERRbadpath);
2312 reply_nterror(req, ntstatus);
2316 mask = smb_dname->original_lcomp;
2318 directory = smb_dname->base_name;
2320 p = strrchr_m(directory,'/');
2322 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2323 if((directory[0] == '.') && (directory[1] == '\0')) {
2324 mask = talloc_strdup(ctx,"*");
2326 reply_nterror(req, NT_STATUS_NO_MEMORY);
2329 mask_contains_wcard = True;
2331 directory = talloc_strdup(talloc_tos(), "./");
2333 reply_nterror(req, NT_STATUS_NO_MEMORY);
2340 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2342 if (info_level == SMB_FIND_EA_LIST) {
2345 if (total_data < 4) {
2346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2350 ea_size = IVAL(pdata,0);
2351 if (ea_size != total_data) {
2352 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2353 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2358 if (!lp_ea_support(SNUM(conn))) {
2359 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2363 /* Pull out the list of names. */
2364 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2366 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2371 *ppdata = (char *)SMB_REALLOC(
2372 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2373 if(*ppdata == NULL ) {
2374 reply_nterror(req, NT_STATUS_NO_MEMORY);
2378 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2380 /* Realloc the params space */
2381 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2382 if (*pparams == NULL) {
2383 reply_nterror(req, NT_STATUS_NO_MEMORY);
2388 /* Save the wildcard match and attribs we are using on this directory -
2389 needed as lanman2 assumes these are being saved between calls */
2391 ntstatus = dptr_create(conn,
2397 mask_contains_wcard,
2401 if (!NT_STATUS_IS_OK(ntstatus)) {
2402 reply_nterror(req, ntstatus);
2406 dptr_num = dptr_dnum(dirptr);
2407 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2409 /* Initialize per TRANS2_FIND_FIRST operation data */
2410 dptr_init_search_op(dirptr);
2412 /* We don't need to check for VOL here as this is returned by
2413 a different TRANS2 call. */
2415 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2416 directory,lp_dontdescend(SNUM(conn))));
2417 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2418 dont_descend = True;
2421 space_remaining = max_data_bytes;
2422 out_of_space = False;
2424 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2425 bool got_exact_match = False;
2427 /* this is a heuristic to avoid seeking the dirptr except when
2428 absolutely necessary. It allows for a filename of about 40 chars */
2429 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2430 out_of_space = True;
2433 finished = !get_lanman2_dir_entry(ctx,
2437 mask,dirtype,info_level,
2438 requires_resume_key,dont_descend,
2441 space_remaining, &out_of_space,
2443 &last_entry_off, ea_list);
2446 if (finished && out_of_space)
2449 if (!finished && !out_of_space)
2453 * As an optimisation if we know we aren't looking
2454 * for a wildcard name (ie. the name matches the wildcard exactly)
2455 * then we can finish on any (first) match.
2456 * This speeds up large directory searches. JRA.
2462 /* Ensure space_remaining never goes -ve. */
2463 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2464 space_remaining = 0;
2465 out_of_space = true;
2467 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2471 /* Check if we can close the dirptr */
2472 if(close_after_first || (finished && close_if_end)) {
2473 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2474 dptr_close(sconn, &dptr_num);
2478 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2479 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2480 * the protocol level is less than NT1. Tested with smbclient. JRA.
2481 * This should fix the OS/2 client bug #2335.
2484 if(numentries == 0) {
2485 dptr_close(sconn, &dptr_num);
2486 if (get_Protocol() < PROTOCOL_NT1) {
2487 reply_force_doserror(req, ERRDOS, ERRnofiles);
2490 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2491 ERRDOS, ERRbadfile);
2496 /* At this point pdata points to numentries directory entries. */
2498 /* Set up the return parameter block */
2499 SSVAL(params,0,dptr_num);
2500 SSVAL(params,2,numentries);
2501 SSVAL(params,4,finished);
2502 SSVAL(params,6,0); /* Never an EA error */
2503 SSVAL(params,8,last_entry_off);
2505 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2508 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2509 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2511 reply_nterror(req, NT_STATUS_NO_MEMORY);
2515 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2516 smb_fn_name(req->cmd),
2517 mask, directory, dirtype, numentries ) );
2520 * Force a name mangle here to ensure that the
2521 * mask as an 8.3 name is top of the mangled cache.
2522 * The reasons for this are subtle. Don't remove
2523 * this code unless you know what you are doing
2524 * (see PR#13758). JRA.
2527 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2528 char mangled_name[13];
2529 name_to_8_3(mask, mangled_name, True, conn->params);
2532 TALLOC_FREE(smb_dname);
2536 /****************************************************************************
2537 Reply to a TRANS2_FINDNEXT.
2538 ****************************************************************************/
2540 static void call_trans2findnext(connection_struct *conn,
2541 struct smb_request *req,
2542 char **pparams, int total_params,
2543 char **ppdata, int total_data,
2544 unsigned int max_data_bytes)
2546 /* We must be careful here that we don't return more than the
2547 allowed number of data bytes. If this means returning fewer than
2548 maxentries then so be it. We assume that the redirector has
2549 enough room for the fixed number of parameter bytes it has
2551 char *params = *pparams;
2552 char *pdata = *ppdata;
2558 uint16 findnext_flags;
2559 bool close_after_request;
2561 bool requires_resume_key;
2563 bool mask_contains_wcard = False;
2564 char *resume_name = NULL;
2565 const char *mask = NULL;
2566 const char *directory = NULL;
2570 int i, last_entry_off=0;
2571 bool finished = False;
2572 bool dont_descend = False;
2573 bool out_of_space = False;
2574 int space_remaining;
2575 struct ea_list *ea_list = NULL;
2576 NTSTATUS ntstatus = NT_STATUS_OK;
2577 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2578 TALLOC_CTX *ctx = talloc_tos();
2579 struct dptr_struct *dirptr;
2580 struct smbd_server_connection *sconn = smbd_server_conn;
2582 if (total_params < 13) {
2583 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2587 dptr_num = SVAL(params,0);
2588 maxentries = SVAL(params,2);
2589 info_level = SVAL(params,4);
2590 resume_key = IVAL(params,6);
2591 findnext_flags = SVAL(params,10);
2592 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2593 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2594 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2595 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2597 if (!continue_bit) {
2598 /* We only need resume_name if continue_bit is zero. */
2599 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2601 total_params - 12, STR_TERMINATE, &ntstatus,
2602 &mask_contains_wcard);
2603 if (!NT_STATUS_IS_OK(ntstatus)) {
2604 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2605 complain (it thinks we're asking for the directory above the shared
2606 path or an invalid name). Catch this as the resume name is only compared, never used in
2607 a file access. JRA. */
2608 srvstr_pull_talloc(ctx, params, req->flags2,
2609 &resume_name, params+12,
2613 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2614 reply_nterror(req, ntstatus);
2620 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2621 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2622 resume_key = %d resume name = %s continue=%d level = %d\n",
2623 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2624 requires_resume_key, resume_key,
2625 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2628 /* W2K3 seems to treat zero as 1. */
2632 switch (info_level) {
2633 case SMB_FIND_INFO_STANDARD:
2634 case SMB_FIND_EA_SIZE:
2635 case SMB_FIND_EA_LIST:
2636 case SMB_FIND_FILE_DIRECTORY_INFO:
2637 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2638 case SMB_FIND_FILE_NAMES_INFO:
2639 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2640 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2641 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2643 case SMB_FIND_FILE_UNIX:
2644 case SMB_FIND_FILE_UNIX_INFO2:
2645 /* Always use filesystem for UNIX mtime query. */
2646 ask_sharemode = false;
2647 if (!lp_unix_extensions()) {
2648 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2653 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2657 if (info_level == SMB_FIND_EA_LIST) {
2660 if (total_data < 4) {
2661 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2665 ea_size = IVAL(pdata,0);
2666 if (ea_size != total_data) {
2667 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2668 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2669 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2673 if (!lp_ea_support(SNUM(conn))) {
2674 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2678 /* Pull out the list of names. */
2679 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2686 *ppdata = (char *)SMB_REALLOC(
2687 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2688 if(*ppdata == NULL) {
2689 reply_nterror(req, NT_STATUS_NO_MEMORY);
2694 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2696 /* Realloc the params space */
2697 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2698 if(*pparams == NULL ) {
2699 reply_nterror(req, NT_STATUS_NO_MEMORY);
2705 /* Check that the dptr is valid */
2706 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2707 reply_nterror(req, STATUS_NO_MORE_FILES);
2711 directory = dptr_path(sconn, dptr_num);
2713 /* Get the wildcard mask from the dptr */
2714 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2715 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2716 reply_nterror(req, STATUS_NO_MORE_FILES);
2722 /* Get the attr mask from the dptr */
2723 dirtype = dptr_attr(sconn, dptr_num);
2725 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2726 dptr_num, mask, dirtype,
2728 dptr_TellDir(dirptr)));
2730 /* Initialize per TRANS2_FIND_NEXT operation data */
2731 dptr_init_search_op(dirptr);
2733 /* We don't need to check for VOL here as this is returned by
2734 a different TRANS2 call. */
2736 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2737 directory,lp_dontdescend(SNUM(conn))));
2738 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2739 dont_descend = True;
2742 space_remaining = max_data_bytes;
2743 out_of_space = False;
2746 * Seek to the correct position. We no longer use the resume key but
2747 * depend on the last file name instead.
2750 if(!continue_bit && resume_name && *resume_name) {
2753 long current_pos = 0;
2755 * Remember, name_to_8_3 is called by
2756 * get_lanman2_dir_entry(), so the resume name
2757 * could be mangled. Ensure we check the unmangled name.
2760 if (mangle_is_mangled(resume_name, conn->params)) {
2761 char *new_resume_name = NULL;
2762 mangle_lookup_name_from_8_3(ctx,
2766 if (new_resume_name) {
2767 resume_name = new_resume_name;
2772 * Fix for NT redirector problem triggered by resume key indexes
2773 * changing between directory scans. We now return a resume key of 0
2774 * and instead look for the filename to continue from (also given
2775 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2776 * findfirst/findnext (as is usual) then the directory pointer
2777 * should already be at the correct place.
2780 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2781 } /* end if resume_name && !continue_bit */
2783 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2784 bool got_exact_match = False;
2786 /* this is a heuristic to avoid seeking the dirptr except when
2787 absolutely necessary. It allows for a filename of about 40 chars */
2788 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2789 out_of_space = True;
2792 finished = !get_lanman2_dir_entry(ctx,
2796 mask,dirtype,info_level,
2797 requires_resume_key,dont_descend,
2800 space_remaining, &out_of_space,
2802 &last_entry_off, ea_list);
2805 if (finished && out_of_space)
2808 if (!finished && !out_of_space)
2812 * As an optimisation if we know we aren't looking
2813 * for a wildcard name (ie. the name matches the wildcard exactly)
2814 * then we can finish on any (first) match.
2815 * This speeds up large directory searches. JRA.
2821 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2824 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2825 smb_fn_name(req->cmd),
2826 mask, directory, dirtype, numentries ) );
2828 /* Check if we can close the dirptr */
2829 if(close_after_request || (finished && close_if_end)) {
2830 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2831 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2834 /* Set up the return parameter block */
2835 SSVAL(params,0,numentries);
2836 SSVAL(params,2,finished);
2837 SSVAL(params,4,0); /* Never an EA error */
2838 SSVAL(params,6,last_entry_off);
2840 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2846 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2848 E_md4hash(lp_servicename(SNUM(conn)),objid);
2852 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2854 SMB_ASSERT(extended_info != NULL);
2856 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2857 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2858 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2859 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2860 #ifdef SAMBA_VERSION_REVISION
2861 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2863 extended_info->samba_subversion = 0;
2864 #ifdef SAMBA_VERSION_RC_RELEASE
2865 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2867 #ifdef SAMBA_VERSION_PRE_RELEASE
2868 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2871 #ifdef SAMBA_VERSION_VENDOR_PATCH
2872 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2874 extended_info->samba_gitcommitdate = 0;
2875 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2876 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2879 memset(extended_info->samba_version_string, 0,
2880 sizeof(extended_info->samba_version_string));
2882 snprintf (extended_info->samba_version_string,
2883 sizeof(extended_info->samba_version_string),
2884 "%s", samba_version_string());
2887 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2888 TALLOC_CTX *mem_ctx,
2889 uint16_t info_level,
2891 unsigned int max_data_bytes,
2895 char *pdata, *end_data;
2896 int data_len = 0, len;
2897 const char *vname = volume_label(SNUM(conn));
2898 int snum = SNUM(conn);
2899 char *fstype = lp_fstype(SNUM(conn));
2900 uint32 additional_flags = 0;
2901 struct smb_filename smb_fname_dot;
2905 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2906 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2907 "info level (0x%x) on IPC$.\n",
2908 (unsigned int)info_level));
2909 return NT_STATUS_ACCESS_DENIED;
2913 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2915 ZERO_STRUCT(smb_fname_dot);
2916 smb_fname_dot.base_name = discard_const_p(char, ".");
2918 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2919 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2920 return map_nt_error_from_unix(errno);
2923 st = smb_fname_dot.st;
2925 *ppdata = (char *)SMB_REALLOC(
2926 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2927 if (*ppdata == NULL) {
2928 return NT_STATUS_NO_MEMORY;
2932 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2933 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2935 switch (info_level) {
2936 case SMB_INFO_ALLOCATION:
2938 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2940 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2941 return map_nt_error_from_unix(errno);
2944 block_size = lp_block_size(snum);
2945 if (bsize < block_size) {
2946 uint64_t factor = block_size/bsize;
2951 if (bsize > block_size) {
2952 uint64_t factor = bsize/block_size;
2957 bytes_per_sector = 512;
2958 sectors_per_unit = bsize/bytes_per_sector;
2960 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2961 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2962 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2964 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2965 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2966 SIVAL(pdata,l1_cUnit,dsize);
2967 SIVAL(pdata,l1_cUnitAvail,dfree);
2968 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2972 case SMB_INFO_VOLUME:
2973 /* Return volume name */
2975 * Add volume serial number - hash of a combination of
2976 * the called hostname and the service name.
2978 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2980 * Win2k3 and previous mess this up by sending a name length
2981 * one byte short. I believe only older clients (OS/2 Win9x) use
2982 * this call so try fixing this by adding a terminating null to
2983 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2987 pdata+l2_vol_szVolLabel, vname,
2988 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2989 STR_NOALIGN|STR_TERMINATE);
2990 SCVAL(pdata,l2_vol_cch,len);
2991 data_len = l2_vol_szVolLabel + len;
2992 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2993 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2997 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2998 case SMB_FS_ATTRIBUTE_INFORMATION:
3000 additional_flags = 0;
3001 #if defined(HAVE_SYS_QUOTAS)
3002 additional_flags |= FILE_VOLUME_QUOTAS;
3005 if(lp_nt_acl_support(SNUM(conn))) {
3006 additional_flags |= FILE_PERSISTENT_ACLS;
3009 /* Capabilities are filled in at connection time through STATVFS call */
3010 additional_flags |= conn->fs_capabilities;
3011 additional_flags |= lp_parm_int(conn->params->service,
3012 "share", "fake_fscaps",
3015 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3016 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3017 additional_flags); /* FS ATTRIBUTES */
3019 SIVAL(pdata,4,255); /* Max filename component length */
3020 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3021 and will think we can't do long filenames */
3022 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3023 PTR_DIFF(end_data, pdata+12),
3026 data_len = 12 + len;
3029 case SMB_QUERY_FS_LABEL_INFO:
3030 case SMB_FS_LABEL_INFORMATION:
3031 len = srvstr_push(pdata, flags2, pdata+4, vname,
3032 PTR_DIFF(end_data, pdata+4), 0);
3037 case SMB_QUERY_FS_VOLUME_INFO:
3038 case SMB_FS_VOLUME_INFORMATION:
3041 * Add volume serial number - hash of a combination of
3042 * the called hostname and the service name.
3044 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3045 (str_checksum(get_local_machine_name())<<16));
3047 /* Max label len is 32 characters. */
3048 len = srvstr_push(pdata, flags2, pdata+18, vname,
3049 PTR_DIFF(end_data, pdata+18),
3051 SIVAL(pdata,12,len);
3054 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3055 (int)strlen(vname),vname, lp_servicename(snum)));
3058 case SMB_QUERY_FS_SIZE_INFO:
3059 case SMB_FS_SIZE_INFORMATION:
3061 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3063 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3064 return map_nt_error_from_unix(errno);
3066 block_size = lp_block_size(snum);
3067 if (bsize < block_size) {
3068 uint64_t factor = block_size/bsize;
3073 if (bsize > block_size) {
3074 uint64_t factor = bsize/block_size;
3079 bytes_per_sector = 512;
3080 sectors_per_unit = bsize/bytes_per_sector;
3081 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3082 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3083 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3084 SBIG_UINT(pdata,0,dsize);
3085 SBIG_UINT(pdata,8,dfree);
3086 SIVAL(pdata,16,sectors_per_unit);
3087 SIVAL(pdata,20,bytes_per_sector);
3091 case SMB_FS_FULL_SIZE_INFORMATION:
3093 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3095 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3096 return map_nt_error_from_unix(errno);
3098 block_size = lp_block_size(snum);
3099 if (bsize < block_size) {
3100 uint64_t factor = block_size/bsize;
3105 if (bsize > block_size) {
3106 uint64_t factor = bsize/block_size;
3111 bytes_per_sector = 512;
3112 sectors_per_unit = bsize/bytes_per_sector;
3113 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3114 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3115 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3116 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3117 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3118 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3119 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3120 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3124 case SMB_QUERY_FS_DEVICE_INFO:
3125 case SMB_FS_DEVICE_INFORMATION:
3127 SIVAL(pdata,0,0); /* dev type */
3128 SIVAL(pdata,4,0); /* characteristics */
3131 #ifdef HAVE_SYS_QUOTAS
3132 case SMB_FS_QUOTA_INFORMATION:
3134 * what we have to send --metze:
3136 * Unknown1: 24 NULL bytes
3137 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3138 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3139 * Quota Flags: 2 byte :
3140 * Unknown3: 6 NULL bytes
3144 * details for Quota Flags:
3146 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3147 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3148 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3149 * 0x0001 Enable Quotas: enable quota for this fs
3153 /* we need to fake up a fsp here,
3154 * because its not send in this call
3157 SMB_NTQUOTA_STRUCT quotas;
3160 ZERO_STRUCT(quotas);
3166 if (conn->server_info->utok.uid != sec_initial_uid()) {
3167 DEBUG(0,("set_user_quota: access_denied "
3168 "service [%s] user [%s]\n",
3169 lp_servicename(SNUM(conn)),
3170 conn->server_info->unix_name));
3171 return NT_STATUS_ACCESS_DENIED;
3174 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3175 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3176 return map_nt_error_from_unix(errno);
3181 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3182 lp_servicename(SNUM(conn))));
3184 /* Unknown1 24 NULL bytes*/
3185 SBIG_UINT(pdata,0,(uint64_t)0);
3186 SBIG_UINT(pdata,8,(uint64_t)0);
3187 SBIG_UINT(pdata,16,(uint64_t)0);
3189 /* Default Soft Quota 8 bytes */
3190 SBIG_UINT(pdata,24,quotas.softlim);
3192 /* Default Hard Quota 8 bytes */
3193 SBIG_UINT(pdata,32,quotas.hardlim);
3195 /* Quota flag 2 bytes */
3196 SSVAL(pdata,40,quotas.qflags);
3198 /* Unknown3 6 NULL bytes */
3204 #endif /* HAVE_SYS_QUOTAS */
3205 case SMB_FS_OBJECTID_INFORMATION:
3207 unsigned char objid[16];
3208 struct smb_extended_info extended_info;
3209 memcpy(pdata,create_volume_objectid(conn, objid),16);
3210 samba_extended_info_version (&extended_info);
3211 SIVAL(pdata,16,extended_info.samba_magic);
3212 SIVAL(pdata,20,extended_info.samba_version);
3213 SIVAL(pdata,24,extended_info.samba_subversion);
3214 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3215 memcpy(pdata+36,extended_info.samba_version_string,28);
3221 * Query the version and capabilities of the CIFS UNIX extensions
3225 case SMB_QUERY_CIFS_UNIX_INFO:
3227 bool large_write = lp_min_receive_file_size() &&
3228 !srv_is_signing_active(smbd_server_conn);
3229 bool large_read = !srv_is_signing_active(smbd_server_conn);
3230 int encrypt_caps = 0;
3232 if (!lp_unix_extensions()) {
3233 return NT_STATUS_INVALID_LEVEL;
3236 switch (conn->encrypt_level) {
3242 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3245 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3246 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3247 large_write = false;
3253 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3254 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3256 /* We have POSIX ACLs, pathname, encryption,
3257 * large read/write, and locking capability. */
3259 SBIG_UINT(pdata,4,((uint64_t)(
3260 CIFS_UNIX_POSIX_ACLS_CAP|
3261 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3262 CIFS_UNIX_FCNTL_LOCKS_CAP|
3263 CIFS_UNIX_EXTATTR_CAP|
3264 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3266 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3268 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3272 case SMB_QUERY_POSIX_FS_INFO:
3275 vfs_statvfs_struct svfs;
3277 if (!lp_unix_extensions()) {
3278 return NT_STATUS_INVALID_LEVEL;
3281 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3285 SIVAL(pdata,0,svfs.OptimalTransferSize);
3286 SIVAL(pdata,4,svfs.BlockSize);
3287 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3288 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3289 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3290 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3291 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3292 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3293 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3295 } else if (rc == EOPNOTSUPP) {
3296 return NT_STATUS_INVALID_LEVEL;
3297 #endif /* EOPNOTSUPP */
3299 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3300 return NT_STATUS_DOS(ERRSRV, ERRerror);
3305 case SMB_QUERY_POSIX_WHOAMI:
3311 if (!lp_unix_extensions()) {
3312 return NT_STATUS_INVALID_LEVEL;
3315 if (max_data_bytes < 40) {
3316 return NT_STATUS_BUFFER_TOO_SMALL;
3319 /* We ARE guest if global_sid_Builtin_Guests is
3320 * in our list of SIDs.
3322 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3323 conn->server_info->ptok)) {
3324 flags |= SMB_WHOAMI_GUEST;
3327 /* We are NOT guest if global_sid_Authenticated_Users
3328 * is in our list of SIDs.
3330 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3331 conn->server_info->ptok)) {
3332 flags &= ~SMB_WHOAMI_GUEST;
3335 /* NOTE: 8 bytes for UID/GID, irrespective of native
3336 * platform size. This matches
3337 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3339 data_len = 4 /* flags */
3346 + 4 /* pad/reserved */
3347 + (conn->server_info->utok.ngroups * 8)
3349 + (conn->server_info->ptok->num_sids *
3353 SIVAL(pdata, 0, flags);
3354 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3356 (uint64_t)conn->server_info->utok.uid);
3357 SBIG_UINT(pdata, 16,
3358 (uint64_t)conn->server_info->utok.gid);
3361 if (data_len >= max_data_bytes) {
3362 /* Potential overflow, skip the GIDs and SIDs. */
3364 SIVAL(pdata, 24, 0); /* num_groups */
3365 SIVAL(pdata, 28, 0); /* num_sids */
3366 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3367 SIVAL(pdata, 36, 0); /* reserved */
3373 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3374 SIVAL(pdata, 28, conn->server_info->num_sids);
3376 /* We walk the SID list twice, but this call is fairly
3377 * infrequent, and I don't expect that it's performance
3378 * sensitive -- jpeach
3380 for (i = 0, sid_bytes = 0;
3381 i < conn->server_info->ptok->num_sids; ++i) {
3382 sid_bytes += ndr_size_dom_sid(
3383 &conn->server_info->ptok->user_sids[i],
3388 /* SID list byte count */
3389 SIVAL(pdata, 32, sid_bytes);
3391 /* 4 bytes pad/reserved - must be zero */
3392 SIVAL(pdata, 36, 0);
3396 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3397 SBIG_UINT(pdata, data_len,
3398 (uint64_t)conn->server_info->utok.groups[i]);
3404 i < conn->server_info->ptok->num_sids; ++i) {
3405 int sid_len = ndr_size_dom_sid(
3406 &conn->server_info->ptok->user_sids[i],
3410 sid_linearize(pdata + data_len, sid_len,
3411 &conn->server_info->ptok->user_sids[i]);
3412 data_len += sid_len;
3418 case SMB_MAC_QUERY_FS_INFO:
3420 * Thursby MAC extension... ONLY on NTFS filesystems
3421 * once we do streams then we don't need this
3423 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3425 SIVAL(pdata,84,0x100); /* Don't support mac... */
3430 return NT_STATUS_INVALID_LEVEL;
3433 *ret_data_len = data_len;
3434 return NT_STATUS_OK;
3437 /****************************************************************************
3438 Reply to a TRANS2_QFSINFO (query filesystem info).
3439 ****************************************************************************/
3441 static void call_trans2qfsinfo(connection_struct *conn,
3442 struct smb_request *req,
3443 char **pparams, int total_params,
3444 char **ppdata, int total_data,
3445 unsigned int max_data_bytes)
3447 char *params = *pparams;
3448 uint16_t info_level;
3452 if (total_params < 2) {
3453 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3457 info_level = SVAL(params,0);
3459 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3460 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3461 DEBUG(0,("call_trans2qfsinfo: encryption required "
3462 "and info level 0x%x sent.\n",
3463 (unsigned int)info_level));
3464 exit_server_cleanly("encryption required "
3470 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3472 status = smbd_do_qfsinfo(conn, req,
3477 if (!NT_STATUS_IS_OK(status)) {
3478 reply_nterror(req, status);
3482 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3485 DEBUG( 4, ( "%s info_level = %d\n",
3486 smb_fn_name(req->cmd), info_level) );
3491 /****************************************************************************
3492 Reply to a TRANS2_SETFSINFO (set filesystem info).
3493 ****************************************************************************/
3495 static void call_trans2setfsinfo(connection_struct *conn,
3496 struct smb_request *req,
3497 char **pparams, int total_params,
3498 char **ppdata, int total_data,
3499 unsigned int max_data_bytes)
3501 char *pdata = *ppdata;
3502 char *params = *pparams;
3505 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3508 if (total_params < 4) {
3509 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3515 info_level = SVAL(params,2);
3518 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3519 info_level != SMB_SET_CIFS_UNIX_INFO) {
3520 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3521 "info level (0x%x) on IPC$.\n",
3522 (unsigned int)info_level));
3523 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3528 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3529 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3530 DEBUG(0,("call_trans2setfsinfo: encryption required "
3531 "and info level 0x%x sent.\n",
3532 (unsigned int)info_level));
3533 exit_server_cleanly("encryption required "
3539 switch(info_level) {
3540 case SMB_SET_CIFS_UNIX_INFO:
3542 uint16 client_unix_major;
3543 uint16 client_unix_minor;
3544 uint32 client_unix_cap_low;
3545 uint32 client_unix_cap_high;
3547 if (!lp_unix_extensions()) {
3549 NT_STATUS_INVALID_LEVEL);
3553 /* There should be 12 bytes of capabilities set. */
3554 if (total_data < 8) {
3557 NT_STATUS_INVALID_PARAMETER);
3560 client_unix_major = SVAL(pdata,0);
3561 client_unix_minor = SVAL(pdata,2);
3562 client_unix_cap_low = IVAL(pdata,4);
3563 client_unix_cap_high = IVAL(pdata,8);
3564 /* Just print these values for now. */
3565 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3566 cap_low = 0x%x, cap_high = 0x%x\n",
3567 (unsigned int)client_unix_major,
3568 (unsigned int)client_unix_minor,
3569 (unsigned int)client_unix_cap_low,
3570 (unsigned int)client_unix_cap_high ));
3572 /* Here is where we must switch to posix pathname processing... */
3573 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3574 lp_set_posix_pathnames();
3575 mangle_change_to_posix();
3578 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3579 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3580 /* Client that knows how to do posix locks,
3581 * but not posix open/mkdir operations. Set a
3582 * default type for read/write checks. */
3584 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3590 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3593 size_t param_len = 0;
3594 size_t data_len = total_data;
3596 if (!lp_unix_extensions()) {
3599 NT_STATUS_INVALID_LEVEL);
3603 if (lp_smb_encrypt(SNUM(conn)) == false) {
3606 NT_STATUS_NOT_SUPPORTED);
3610 if (smbd_server_conn->smb1.echo_handler.trusted_fde) {
3611 DEBUG( 2,("call_trans2setfsinfo: "
3612 "request transport encryption disabled"
3613 "with 'fork echo handler = yes'\n"));
3616 NT_STATUS_NOT_SUPPORTED);
3620 DEBUG( 4,("call_trans2setfsinfo: "
3621 "request transport encryption.\n"));
3623 status = srv_request_encryption_setup(conn,
3624 (unsigned char **)ppdata,
3626 (unsigned char **)pparams,
3629 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3630 !NT_STATUS_IS_OK(status)) {
3631 reply_nterror(req, status);
3635 send_trans2_replies(conn, req,
3642 if (NT_STATUS_IS_OK(status)) {
3643 /* Server-side transport
3644 * encryption is now *on*. */
3645 status = srv_encryption_start(conn);
3646 if (!NT_STATUS_IS_OK(status)) {
3647 exit_server_cleanly(
3648 "Failure in setting "
3649 "up encrypted transport");
3655 case SMB_FS_QUOTA_INFORMATION:
3657 files_struct *fsp = NULL;
3658 SMB_NTQUOTA_STRUCT quotas;
3660 ZERO_STRUCT(quotas);
3663 if ((conn->server_info->utok.uid != sec_initial_uid())
3664 ||!CAN_WRITE(conn)) {
3665 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3666 lp_servicename(SNUM(conn)),
3667 conn->server_info->unix_name));
3668 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3672 /* note: normaly there're 48 bytes,
3673 * but we didn't use the last 6 bytes for now
3676 fsp = file_fsp(req, SVAL(params,0));
3678 if (!check_fsp_ntquota_handle(conn, req,
3680 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3682 req, NT_STATUS_INVALID_HANDLE);
3686 if (total_data < 42) {
3687 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3691 NT_STATUS_INVALID_PARAMETER);
3695 /* unknown_1 24 NULL bytes in pdata*/
3697 /* the soft quotas 8 bytes (uint64_t)*/
3698 quotas.softlim = (uint64_t)IVAL(pdata,24);
3699 #ifdef LARGE_SMB_OFF_T
3700 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3701 #else /* LARGE_SMB_OFF_T */
3702 if ((IVAL(pdata,28) != 0)&&
3703 ((quotas.softlim != 0xFFFFFFFF)||
3704 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3705 /* more than 32 bits? */
3708 NT_STATUS_INVALID_PARAMETER);
3711 #endif /* LARGE_SMB_OFF_T */
3713 /* the hard quotas 8 bytes (uint64_t)*/
3714 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3715 #ifdef LARGE_SMB_OFF_T
3716 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3717 #else /* LARGE_SMB_OFF_T */
3718 if ((IVAL(pdata,36) != 0)&&
3719 ((quotas.hardlim != 0xFFFFFFFF)||
3720 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3721 /* more than 32 bits? */
3724 NT_STATUS_INVALID_PARAMETER);
3727 #endif /* LARGE_SMB_OFF_T */
3729 /* quota_flags 2 bytes **/
3730 quotas.qflags = SVAL(pdata,40);
3732 /* unknown_2 6 NULL bytes follow*/
3734 /* now set the quotas */
3735 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3736 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3737 reply_nterror(req, map_nt_error_from_unix(errno));
3744 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3746 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3752 * sending this reply works fine,
3753 * but I'm not sure it's the same
3754 * like windows do...
3757 reply_outbuf(req, 10, 0);
3760 #if defined(HAVE_POSIX_ACLS)
3761 /****************************************************************************
3762 Utility function to count the number of entries in a POSIX acl.
3763 ****************************************************************************/
3765 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3767 unsigned int ace_count = 0;
3768 int entry_id = SMB_ACL_FIRST_ENTRY;
3769 SMB_ACL_ENTRY_T entry;
3771 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3773 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3774 entry_id = SMB_ACL_NEXT_ENTRY;
3781 /****************************************************************************
3782 Utility function to marshall a POSIX acl into wire format.
3783 ****************************************************************************/
3785 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3787 int entry_id = SMB_ACL_FIRST_ENTRY;
3788 SMB_ACL_ENTRY_T entry;
3790 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3791 SMB_ACL_TAG_T tagtype;
3792 SMB_ACL_PERMSET_T permset;
3793 unsigned char perms = 0;
3794 unsigned int own_grp;
3797 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3798 entry_id = SMB_ACL_NEXT_ENTRY;
3801 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3802 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3806 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3807 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3811 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3812 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3813 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3815 SCVAL(pdata,1,perms);
3818 case SMB_ACL_USER_OBJ:
3819 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3820 own_grp = (unsigned int)pst->st_ex_uid;
3821 SIVAL(pdata,2,own_grp);
3826 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3828 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3831 own_grp = (unsigned int)*puid;
3832 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3833 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3834 SIVAL(pdata,2,own_grp);
3838 case SMB_ACL_GROUP_OBJ:
3839 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3840 own_grp = (unsigned int)pst->st_ex_gid;
3841 SIVAL(pdata,2,own_grp);
3846 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3848 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3851 own_grp = (unsigned int)*pgid;
3852 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3853 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3854 SIVAL(pdata,2,own_grp);
3859 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3860 SIVAL(pdata,2,0xFFFFFFFF);
3861 SIVAL(pdata,6,0xFFFFFFFF);
3864 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3865 SIVAL(pdata,2,0xFFFFFFFF);
3866 SIVAL(pdata,6,0xFFFFFFFF);
3869 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3872 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3879 /****************************************************************************
3880 Store the FILE_UNIX_BASIC info.
3881 ****************************************************************************/
3883 static char *store_file_unix_basic(connection_struct *conn,
3886 const SMB_STRUCT_STAT *psbuf)
3888 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3889 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3891 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3894 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3897 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3898 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3899 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3902 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3906 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3910 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3913 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3917 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3921 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3924 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3928 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3935 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3936 * the chflags(2) (or equivalent) flags.
3938 * XXX: this really should be behind the VFS interface. To do this, we would
3939 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3940 * Each VFS module could then implement its own mapping as appropriate for the
3941 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3943 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3947 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3951 { UF_IMMUTABLE, EXT_IMMUTABLE },
3955 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3959 { UF_HIDDEN, EXT_HIDDEN },
3962 /* Do not remove. We need to guarantee that this array has at least one
3963 * entry to build on HP-UX.
3969 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3970 uint32 *smb_fflags, uint32 *smb_fmask)
3974 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3975 *smb_fmask |= info2_flags_map[i].smb_fflag;
3976 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3977 *smb_fflags |= info2_flags_map[i].smb_fflag;
3982 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3983 const uint32 smb_fflags,
3984 const uint32 smb_fmask,
3987 uint32 max_fmask = 0;
3990 *stat_fflags = psbuf->st_ex_flags;
3992 /* For each flags requested in smb_fmask, check the state of the
3993 * corresponding flag in smb_fflags and set or clear the matching
3997 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3998 max_fmask |= info2_flags_map[i].smb_fflag;
3999 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4000 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4001 *stat_fflags |= info2_flags_map[i].stat_fflag;
4003 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4008 /* If smb_fmask is asking to set any bits that are not supported by
4009 * our flag mappings, we should fail.
4011 if ((smb_fmask & max_fmask) != smb_fmask) {
4019 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4020 * of file flags and birth (create) time.
4022 static char *store_file_unix_basic_info2(connection_struct *conn,
4025 const SMB_STRUCT_STAT *psbuf)
4027 uint32 file_flags = 0;
4028 uint32 flags_mask = 0;
4030 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4032 /* Create (birth) time 64 bit */
4033 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4036 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4037 SIVAL(pdata, 0, file_flags); /* flags */
4038 SIVAL(pdata, 4, flags_mask); /* mask */
4044 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4045 const struct stream_struct *streams,
4047 unsigned int max_data_bytes,
4048 unsigned int *data_size)
4051 unsigned int ofs = 0;
4053 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4054 unsigned int next_offset;
4056 smb_ucs2_t *namebuf;
4058 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4059 streams[i].name, &namelen) ||
4062 return NT_STATUS_INVALID_PARAMETER;
4066 * name_buf is now null-terminated, we need to marshall as not
4072 SIVAL(data, ofs+4, namelen);
4073 SOFF_T(data, ofs+8, streams[i].size);
4074 SOFF_T(data, ofs+16, streams[i].alloc_size);
4075 memcpy(data+ofs+24, namebuf, namelen);
4076 TALLOC_FREE(namebuf);
4078 next_offset = ofs + 24 + namelen;
4080 if (i == num_streams-1) {
4081 SIVAL(data, ofs, 0);
4084 unsigned int align = ndr_align_size(next_offset, 8);
4086 memset(data+next_offset, 0, align);
4087 next_offset += align;
4089 SIVAL(data, ofs, next_offset - ofs);
4098 return NT_STATUS_OK;
4101 /****************************************************************************
4102 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4103 ****************************************************************************/
4105 static void call_trans2qpipeinfo(connection_struct *conn,
4106 struct smb_request *req,
4107 unsigned int tran_call,
4108 char **pparams, int total_params,
4109 char **ppdata, int total_data,
4110 unsigned int max_data_bytes)
4112 char *params = *pparams;
4113 char *pdata = *ppdata;
4114 unsigned int data_size = 0;
4115 unsigned int param_size = 2;
4120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4124 if (total_params < 4) {
4125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4129 fsp = file_fsp(req, SVAL(params,0));
4130 if (!fsp_is_np(fsp)) {
4131 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4135 info_level = SVAL(params,2);
4137 *pparams = (char *)SMB_REALLOC(*pparams,2);
4138 if (*pparams == NULL) {
4139 reply_nterror(req, NT_STATUS_NO_MEMORY);
4144 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4145 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4146 if (*ppdata == NULL ) {
4147 reply_nterror(req, NT_STATUS_NO_MEMORY);
4152 switch (info_level) {
4153 case SMB_FILE_STANDARD_INFORMATION:
4155 SOFF_T(pdata,0,4096LL);
4162 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4166 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4172 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4173 TALLOC_CTX *mem_ctx,
4174 uint16_t info_level,
4176 struct smb_filename *smb_fname,
4177 bool delete_pending,
4178 struct timespec write_time_ts,
4179 struct ea_list *ea_list,
4180 int lock_data_count,
4183 unsigned int max_data_bytes,
4185 unsigned int *pdata_size)
4187 char *pdata = *ppdata;
4188 char *dstart, *dend;
4189 unsigned int data_size;
4190 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4191 time_t create_time, mtime, atime, c_time;
4192 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4199 uint64_t file_size = 0;
4201 uint64_t allocation_size = 0;
4202 uint64_t file_index = 0;
4203 uint32_t access_mask = 0;
4205 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4206 return NT_STATUS_INVALID_LEVEL;
4209 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4210 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4211 info_level, max_data_bytes));
4213 mode = dos_mode(conn, smb_fname);
4214 nlink = psbuf->st_ex_nlink;
4216 if (nlink && (mode&aDIR)) {
4220 if ((nlink > 0) && delete_pending) {
4224 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4225 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4226 if (*ppdata == NULL) {
4227 return NT_STATUS_NO_MEMORY;
4231 dend = dstart + data_size - 1;
4233 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4234 update_stat_ex_mtime(psbuf, write_time_ts);
4237 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4238 mtime_ts = psbuf->st_ex_mtime;
4239 atime_ts = psbuf->st_ex_atime;
4240 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4242 if (lp_dos_filetime_resolution(SNUM(conn))) {
4243 dos_filetime_timespec(&create_time_ts);
4244 dos_filetime_timespec(&mtime_ts);
4245 dos_filetime_timespec(&atime_ts);
4246 dos_filetime_timespec(&ctime_ts);
4249 create_time = convert_timespec_to_time_t(create_time_ts);
4250 mtime = convert_timespec_to_time_t(mtime_ts);
4251 atime = convert_timespec_to_time_t(atime_ts);
4252 c_time = convert_timespec_to_time_t(ctime_ts);
4254 p = strrchr_m(smb_fname->base_name,'/');
4256 base_name = smb_fname->base_name;
4260 /* NT expects the name to be in an exact form of the *full*
4261 filename. See the trans2 torture test */
4262 if (ISDOT(base_name)) {
4263 dos_fname = talloc_strdup(mem_ctx, "\\");
4265 return NT_STATUS_NO_MEMORY;
4268 dos_fname = talloc_asprintf(mem_ctx,
4270 smb_fname->base_name);
4272 return NT_STATUS_NO_MEMORY;
4274 if (is_ntfs_stream_smb_fname(smb_fname)) {
4275 dos_fname = talloc_asprintf(dos_fname, "%s",
4276 smb_fname->stream_name);
4278 return NT_STATUS_NO_MEMORY;
4282 string_replace(dos_fname, '/', '\\');
4285 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4288 /* Do we have this path open ? */
4290 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4291 fsp1 = file_find_di_first(fileid);
4292 if (fsp1 && fsp1->initial_allocation_size) {
4293 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4297 if (!(mode & aDIR)) {
4298 file_size = get_file_size_stat(psbuf);
4302 pos = fsp->fh->position_information;
4306 access_mask = fsp->access_mask;
4308 /* GENERIC_EXECUTE mapping from Windows */
4309 access_mask = 0x12019F;
4312 /* This should be an index number - looks like
4315 I think this causes us to fail the IFSKIT
4316 BasicFileInformationTest. -tpot */
4317 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4318 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4320 switch (info_level) {
4321 case SMB_INFO_STANDARD:
4322 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4324 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4325 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4326 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4327 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4328 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4329 SSVAL(pdata,l1_attrFile,mode);
4332 case SMB_INFO_QUERY_EA_SIZE:
4334 unsigned int ea_size =
4335 estimate_ea_size(conn, fsp,
4336 smb_fname->base_name);
4337 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4339 srv_put_dos_date2(pdata,0,create_time);
4340 srv_put_dos_date2(pdata,4,atime);
4341 srv_put_dos_date2(pdata,8,mtime); /* write time */
4342 SIVAL(pdata,12,(uint32)file_size);
4343 SIVAL(pdata,16,(uint32)allocation_size);
4344 SSVAL(pdata,20,mode);
4345 SIVAL(pdata,22,ea_size);
4349 case SMB_INFO_IS_NAME_VALID:
4350 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4352 /* os/2 needs this ? really ?*/
4353 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4355 /* This is only reached for qpathinfo */
4359 case SMB_INFO_QUERY_EAS_FROM_LIST:
4361 size_t total_ea_len = 0;
4362 struct ea_list *ea_file_list = NULL;
4364 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4367 get_ea_list_from_file(mem_ctx, conn, fsp,
4368 smb_fname->base_name,
4370 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4372 if (!ea_list || (total_ea_len > data_size)) {
4374 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4378 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4382 case SMB_INFO_QUERY_ALL_EAS:
4384 /* We have data_size bytes to put EA's into. */
4385 size_t total_ea_len = 0;
4387 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4389 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4390 smb_fname->base_name,
4392 if (!ea_list || (total_ea_len > data_size)) {
4394 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4398 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4402 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4404 /* This is FileFullEaInformation - 0xF which maps to
4405 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4407 /* We have data_size bytes to put EA's into. */
4408 size_t total_ea_len = 0;
4409 struct ea_list *ea_file_list = NULL;
4411 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4413 /*TODO: add filtering and index handling */
4416 get_ea_list_from_file(mem_ctx, conn, fsp,
4417 smb_fname->base_name,
4419 if (!ea_file_list) {
4420 return NT_STATUS_NO_EAS_ON_FILE;
4423 status = fill_ea_chained_buffer(mem_ctx,
4427 conn, ea_file_list);
4428 if (!NT_STATUS_IS_OK(status)) {
4434 case SMB_FILE_BASIC_INFORMATION:
4435 case SMB_QUERY_FILE_BASIC_INFO:
4437 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4438 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4439 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4445 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4446 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4447 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4448 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4449 SIVAL(pdata,32,mode);
4451 DEBUG(5,("SMB_QFBI - "));
4452 DEBUG(5,("create: %s ", ctime(&create_time)));
4453 DEBUG(5,("access: %s ", ctime(&atime)));
4454 DEBUG(5,("write: %s ", ctime(&mtime)));
4455 DEBUG(5,("change: %s ", ctime(&c_time)));
4456 DEBUG(5,("mode: %x\n", mode));
4459 case SMB_FILE_STANDARD_INFORMATION:
4460 case SMB_QUERY_FILE_STANDARD_INFO:
4462 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4464 SOFF_T(pdata,0,allocation_size);
4465 SOFF_T(pdata,8,file_size);
4466 SIVAL(pdata,16,nlink);
4467 SCVAL(pdata,20,delete_pending?1:0);
4468 SCVAL(pdata,21,(mode&aDIR)?1:0);
4469 SSVAL(pdata,22,0); /* Padding. */
4472 case SMB_FILE_EA_INFORMATION:
4473 case SMB_QUERY_FILE_EA_INFO:
4475 unsigned int ea_size =
4476 estimate_ea_size(conn, fsp, smb_fname->base_name);
4477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4479 SIVAL(pdata,0,ea_size);
4483 /* Get the 8.3 name - used if NT SMB was negotiated. */
4484 case SMB_QUERY_FILE_ALT_NAME_INFO:
4485 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4488 char mangled_name[13];
4489 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4490 if (!name_to_8_3(base_name,mangled_name,
4491 True,conn->params)) {
4492 return NT_STATUS_NO_MEMORY;
4494 len = srvstr_push(dstart, flags2,
4495 pdata+4, mangled_name,
4496 PTR_DIFF(dend, pdata+4),
4498 data_size = 4 + len;
4503 case SMB_QUERY_FILE_NAME_INFO:
4507 this must be *exactly* right for ACLs on mapped drives to work
4509 len = srvstr_push(dstart, flags2,
4511 PTR_DIFF(dend, pdata+4),
4513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4514 data_size = 4 + len;
4519 case SMB_FILE_ALLOCATION_INFORMATION:
4520 case SMB_QUERY_FILE_ALLOCATION_INFO:
4521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4523 SOFF_T(pdata,0,allocation_size);
4526 case SMB_FILE_END_OF_FILE_INFORMATION:
4527 case SMB_QUERY_FILE_END_OF_FILEINFO:
4528 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4530 SOFF_T(pdata,0,file_size);
4533 case SMB_QUERY_FILE_ALL_INFO:
4534 case SMB_FILE_ALL_INFORMATION:
4537 unsigned int ea_size =
4538 estimate_ea_size(conn, fsp, smb_fname->base_name);
4539 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4540 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4541 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4542 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4543 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4544 SIVAL(pdata,32,mode);
4545 SIVAL(pdata,36,0); /* padding. */
4547 SOFF_T(pdata,0,allocation_size);
4548 SOFF_T(pdata,8,file_size);
4549 SIVAL(pdata,16,nlink);
4550 SCVAL(pdata,20,delete_pending);
4551 SCVAL(pdata,21,(mode&aDIR)?1:0);
4554 SIVAL(pdata,0,ea_size);
4555 pdata += 4; /* EA info */
4556 len = srvstr_push(dstart, flags2,
4558 PTR_DIFF(dend, pdata+4),
4562 data_size = PTR_DIFF(pdata,(*ppdata));
4566 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4569 unsigned int ea_size =
4570 estimate_ea_size(conn, fsp, smb_fname->base_name);
4571 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4572 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4573 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4574 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4575 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4576 SIVAL(pdata, 0x20, mode);
4577 SIVAL(pdata, 0x24, 0); /* padding. */
4578 SBVAL(pdata, 0x28, allocation_size);
4579 SBVAL(pdata, 0x30, file_size);
4580 SIVAL(pdata, 0x38, nlink);
4581 SCVAL(pdata, 0x3C, delete_pending);
4582 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4583 SSVAL(pdata, 0x3E, 0); /* padding */
4584 SBVAL(pdata, 0x40, file_index);
4585 SIVAL(pdata, 0x48, ea_size);
4586 SIVAL(pdata, 0x4C, access_mask);
4587 SBVAL(pdata, 0x50, pos);
4588 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4589 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4593 len = srvstr_push(dstart, flags2,
4595 PTR_DIFF(dend, pdata+4),
4599 data_size = PTR_DIFF(pdata,(*ppdata));
4602 case SMB_FILE_INTERNAL_INFORMATION:
4604 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4605 SBVAL(pdata, 0, file_index);
4609 case SMB_FILE_ACCESS_INFORMATION:
4610 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4611 SIVAL(pdata, 0, access_mask);
4615 case SMB_FILE_NAME_INFORMATION:
4616 /* Pathname with leading '\'. */
4619 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4621 SIVAL(pdata,0,byte_len);
4622 data_size = 4 + byte_len;
4626 case SMB_FILE_DISPOSITION_INFORMATION:
4627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4629 SCVAL(pdata,0,delete_pending);
4632 case SMB_FILE_POSITION_INFORMATION:
4633 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4635 SOFF_T(pdata,0,pos);
4638 case SMB_FILE_MODE_INFORMATION:
4639 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4640 SIVAL(pdata,0,mode);
4644 case SMB_FILE_ALIGNMENT_INFORMATION:
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4646 SIVAL(pdata,0,0); /* No alignment needed. */
4651 * NT4 server just returns "invalid query" to this - if we try
4652 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4655 /* The first statement above is false - verified using Thursby
4656 * client against NT4 -- gcolley.
4658 case SMB_QUERY_FILE_STREAM_INFO:
4659 case SMB_FILE_STREAM_INFORMATION: {
4660 unsigned int num_streams;
4661 struct stream_struct *streams;
4663 DEBUG(10,("smbd_do_qfilepathinfo: "
4664 "SMB_FILE_STREAM_INFORMATION\n"));
4666 if (is_ntfs_stream_smb_fname(smb_fname)) {
4667 return NT_STATUS_INVALID_PARAMETER;
4670 status = SMB_VFS_STREAMINFO(
4671 conn, fsp, smb_fname->base_name, talloc_tos(),
4672 &num_streams, &streams);
4674 if (!NT_STATUS_IS_OK(status)) {
4675 DEBUG(10, ("could not get stream info: %s\n",
4676 nt_errstr(status)));
4680 status = marshall_stream_info(num_streams, streams,
4681 pdata, max_data_bytes,
4684 if (!NT_STATUS_IS_OK(status)) {
4685 DEBUG(10, ("marshall_stream_info failed: %s\n",
4686 nt_errstr(status)));
4690 TALLOC_FREE(streams);
4694 case SMB_QUERY_COMPRESSION_INFO:
4695 case SMB_FILE_COMPRESSION_INFORMATION:
4696 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4697 SOFF_T(pdata,0,file_size);
4698 SIVAL(pdata,8,0); /* ??? */
4699 SIVAL(pdata,12,0); /* ??? */
4703 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4704 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4705 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4706 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4707 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4708 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4709 SOFF_T(pdata,32,allocation_size);
4710 SOFF_T(pdata,40,file_size);
4711 SIVAL(pdata,48,mode);
4712 SIVAL(pdata,52,0); /* ??? */
4716 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4717 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4718 SIVAL(pdata,0,mode);
4724 * CIFS UNIX Extensions.
4727 case SMB_QUERY_FILE_UNIX_BASIC:
4729 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4730 data_size = PTR_DIFF(pdata,(*ppdata));
4734 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4736 for (i=0; i<100; i++)
4737 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4743 case SMB_QUERY_FILE_UNIX_INFO2:
4745 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4746 data_size = PTR_DIFF(pdata,(*ppdata));
4750 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4752 for (i=0; i<100; i++)
4753 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4759 case SMB_QUERY_FILE_UNIX_LINK:
4762 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4765 return NT_STATUS_NO_MEMORY;
4768 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4770 if(!S_ISLNK(psbuf->st_ex_mode)) {
4771 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4774 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4776 len = SMB_VFS_READLINK(conn,
4777 smb_fname->base_name,
4780 return map_nt_error_from_unix(errno);
4783 len = srvstr_push(dstart, flags2,
4785 PTR_DIFF(dend, pdata),
4788 data_size = PTR_DIFF(pdata,(*ppdata));
4793 #if defined(HAVE_POSIX_ACLS)
4794 case SMB_QUERY_POSIX_ACL:
4796 SMB_ACL_T file_acl = NULL;
4797 SMB_ACL_T def_acl = NULL;
4798 uint16 num_file_acls = 0;
4799 uint16 num_def_acls = 0;
4801 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4802 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4805 SMB_VFS_SYS_ACL_GET_FILE(conn,
4806 smb_fname->base_name,
4807 SMB_ACL_TYPE_ACCESS);
4810 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4811 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4812 "not implemented on "
4813 "filesystem containing %s\n",
4814 smb_fname->base_name));
4815 return NT_STATUS_NOT_IMPLEMENTED;
4818 if (S_ISDIR(psbuf->st_ex_mode)) {
4819 if (fsp && fsp->is_directory) {
4821 SMB_VFS_SYS_ACL_GET_FILE(
4823 fsp->fsp_name->base_name,
4824 SMB_ACL_TYPE_DEFAULT);
4827 SMB_VFS_SYS_ACL_GET_FILE(
4829 smb_fname->base_name,
4830 SMB_ACL_TYPE_DEFAULT);
4832 def_acl = free_empty_sys_acl(conn, def_acl);
4835 num_file_acls = count_acl_entries(conn, file_acl);
4836 num_def_acls = count_acl_entries(conn, def_acl);
4838 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4839 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4841 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4842 SMB_POSIX_ACL_HEADER_SIZE) ));
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4847 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4849 return NT_STATUS_BUFFER_TOO_SMALL;
4852 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4853 SSVAL(pdata,2,num_file_acls);
4854 SSVAL(pdata,4,num_def_acls);
4855 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4857 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4860 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4862 return NT_STATUS_INTERNAL_ERROR;
4864 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4866 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4871 return NT_STATUS_INTERNAL_ERROR;
4875 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4878 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4880 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4886 case SMB_QUERY_POSIX_LOCK:
4891 enum brl_type lock_type;
4893 /* We need an open file with a real fd for this. */
4894 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4895 return NT_STATUS_INVALID_LEVEL;
4898 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4899 return NT_STATUS_INVALID_PARAMETER;
4902 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4903 case POSIX_LOCK_TYPE_READ:
4904 lock_type = READ_LOCK;
4906 case POSIX_LOCK_TYPE_WRITE:
4907 lock_type = WRITE_LOCK;
4909 case POSIX_LOCK_TYPE_UNLOCK:
4911 /* There's no point in asking for an unlock... */
4912 return NT_STATUS_INVALID_PARAMETER;
4915 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4916 #if defined(HAVE_LONGLONG)
4917 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4918 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4919 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4920 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4921 #else /* HAVE_LONGLONG */
4922 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4923 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4924 #endif /* HAVE_LONGLONG */
4926 status = query_lock(fsp,
4933 if (ERROR_WAS_LOCK_DENIED(status)) {
4934 /* Here we need to report who has it locked... */
4935 data_size = POSIX_LOCK_DATA_SIZE;
4937 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4938 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4939 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4940 #if defined(HAVE_LONGLONG)
4941 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4942 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4943 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4944 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4945 #else /* HAVE_LONGLONG */
4946 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4947 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4948 #endif /* HAVE_LONGLONG */
4950 } else if (NT_STATUS_IS_OK(status)) {
4951 /* For success we just return a copy of what we sent
4952 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4953 data_size = POSIX_LOCK_DATA_SIZE;
4954 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4955 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4963 return NT_STATUS_INVALID_LEVEL;
4966 *pdata_size = data_size;
4967 return NT_STATUS_OK;
4970 /****************************************************************************
4971 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4972 file name or file id).
4973 ****************************************************************************/
4975 static void call_trans2qfilepathinfo(connection_struct *conn,
4976 struct smb_request *req,
4977 unsigned int tran_call,
4978 char **pparams, int total_params,
4979 char **ppdata, int total_data,
4980 unsigned int max_data_bytes)
4982 char *params = *pparams;
4983 char *pdata = *ppdata;
4985 unsigned int data_size = 0;
4986 unsigned int param_size = 2;
4987 struct smb_filename *smb_fname = NULL;
4988 bool delete_pending = False;
4989 struct timespec write_time_ts;
4990 files_struct *fsp = NULL;
4991 struct file_id fileid;
4992 struct ea_list *ea_list = NULL;
4993 int lock_data_count = 0;
4994 char *lock_data = NULL;
4995 NTSTATUS status = NT_STATUS_OK;
4998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5002 ZERO_STRUCT(write_time_ts);
5004 if (tran_call == TRANSACT2_QFILEINFO) {
5005 if (total_params < 4) {
5006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5011 call_trans2qpipeinfo(conn, req, tran_call,
5012 pparams, total_params,
5018 fsp = file_fsp(req, SVAL(params,0));
5019 info_level = SVAL(params,2);
5021 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5023 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5024 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5028 /* Initial check for valid fsp ptr. */
5029 if (!check_fsp_open(conn, req, fsp)) {
5033 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5035 if (!NT_STATUS_IS_OK(status)) {
5036 reply_nterror(req, status);
5040 if(fsp->fake_file_handle) {
5042 * This is actually for the QUOTA_FAKE_FILE --metze
5045 /* We know this name is ok, it's already passed the checks. */
5047 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5049 * This is actually a QFILEINFO on a directory
5050 * handle (returned from an NT SMB). NT5.0 seems
5051 * to do this call. JRA.
5054 if (INFO_LEVEL_IS_UNIX(info_level)) {
5055 /* Always do lstat for UNIX calls. */
5056 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5057 DEBUG(3,("call_trans2qfilepathinfo: "
5058 "SMB_VFS_LSTAT of %s failed "
5060 smb_fname_str_dbg(smb_fname),
5063 map_nt_error_from_unix(errno));
5066 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5067 DEBUG(3,("call_trans2qfilepathinfo: "
5068 "SMB_VFS_STAT of %s failed (%s)\n",
5069 smb_fname_str_dbg(smb_fname),
5072 map_nt_error_from_unix(errno));
5076 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5077 get_file_infos(fileid, &delete_pending, &write_time_ts);
5080 * Original code - this is an open file.
5082 if (!check_fsp(conn, req, fsp)) {
5086 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5087 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5088 fsp->fnum, strerror(errno)));
5090 map_nt_error_from_unix(errno));
5093 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5094 get_file_infos(fileid, &delete_pending, &write_time_ts);
5101 if (total_params < 7) {
5102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5106 info_level = SVAL(params,0);
5108 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5110 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5111 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5115 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5117 STR_TERMINATE, &status);
5118 if (!NT_STATUS_IS_OK(status)) {
5119 reply_nterror(req, status);
5123 status = filename_convert(req,
5125 req->flags2 & FLAGS2_DFS_PATHNAMES,
5130 if (!NT_STATUS_IS_OK(status)) {
5131 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5132 reply_botherror(req,
5133 NT_STATUS_PATH_NOT_COVERED,
5134 ERRSRV, ERRbadpath);
5137 reply_nterror(req, status);
5141 /* If this is a stream, check if there is a delete_pending. */
5142 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5143 && is_ntfs_stream_smb_fname(smb_fname)) {
5144 struct smb_filename *smb_fname_base = NULL;
5146 /* Create an smb_filename with stream_name == NULL. */
5148 create_synthetic_smb_fname(talloc_tos(),
5149 smb_fname->base_name,
5152 if (!NT_STATUS_IS_OK(status)) {
5153 reply_nterror(req, status);
5157 if (INFO_LEVEL_IS_UNIX(info_level)) {
5158 /* Always do lstat for UNIX calls. */
5159 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5160 DEBUG(3,("call_trans2qfilepathinfo: "
5161 "SMB_VFS_LSTAT of %s failed "
5163 smb_fname_str_dbg(smb_fname_base),
5165 TALLOC_FREE(smb_fname_base);
5167 map_nt_error_from_unix(errno));
5171 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5172 DEBUG(3,("call_trans2qfilepathinfo: "
5173 "fileinfo of %s failed "
5175 smb_fname_str_dbg(smb_fname_base),
5177 TALLOC_FREE(smb_fname_base);
5179 map_nt_error_from_unix(errno));
5184 fileid = vfs_file_id_from_sbuf(conn,
5185 &smb_fname_base->st);
5186 TALLOC_FREE(smb_fname_base);
5187 get_file_infos(fileid, &delete_pending, NULL);
5188 if (delete_pending) {
5189 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5194 if (INFO_LEVEL_IS_UNIX(info_level)) {
5195 /* Always do lstat for UNIX calls. */
5196 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5197 DEBUG(3,("call_trans2qfilepathinfo: "
5198 "SMB_VFS_LSTAT of %s failed (%s)\n",
5199 smb_fname_str_dbg(smb_fname),
5202 map_nt_error_from_unix(errno));
5207 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5208 DEBUG(3,("call_trans2qfilepathinfo: "
5209 "SMB_VFS_STAT of %s failed (%s)\n",
5210 smb_fname_str_dbg(smb_fname),
5213 map_nt_error_from_unix(errno));
5218 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5219 get_file_infos(fileid, &delete_pending, &write_time_ts);
5220 if (delete_pending) {
5221 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5226 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5227 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5228 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5230 /* Pull out any data sent here before we realloc. */
5231 switch (info_level) {
5232 case SMB_INFO_QUERY_EAS_FROM_LIST:
5234 /* Pull any EA list from the data portion. */
5237 if (total_data < 4) {
5239 req, NT_STATUS_INVALID_PARAMETER);
5242 ea_size = IVAL(pdata,0);
5244 if (total_data > 0 && ea_size != total_data) {
5245 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5246 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5248 req, NT_STATUS_INVALID_PARAMETER);
5252 if (!lp_ea_support(SNUM(conn))) {
5253 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5257 /* Pull out the list of names. */
5258 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5261 req, NT_STATUS_INVALID_PARAMETER);
5267 case SMB_QUERY_POSIX_LOCK:
5269 if (fsp == NULL || fsp->fh->fd == -1) {
5270 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5274 if (total_data != POSIX_LOCK_DATA_SIZE) {
5276 req, NT_STATUS_INVALID_PARAMETER);
5280 /* Copy the lock range data. */
5281 lock_data = (char *)TALLOC_MEMDUP(
5282 req, pdata, total_data);
5284 reply_nterror(req, NT_STATUS_NO_MEMORY);
5287 lock_data_count = total_data;
5293 *pparams = (char *)SMB_REALLOC(*pparams,2);
5294 if (*pparams == NULL) {
5295 reply_nterror(req, NT_STATUS_NO_MEMORY);
5302 * draft-leach-cifs-v1-spec-02.txt
5303 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5306 * The requested information is placed in the Data portion of the
5307 * transaction response. For the information levels greater than 0x100,
5308 * the transaction response has 1 parameter word which should be
5309 * ignored by the client.
5311 * However Windows only follows this rule for the IS_NAME_VALID call.
5313 switch (info_level) {
5314 case SMB_INFO_IS_NAME_VALID:
5319 if ((info_level & 0xFF00) == 0xFF00) {
5321 * We use levels that start with 0xFF00
5322 * internally to represent SMB2 specific levels
5324 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5328 status = smbd_do_qfilepathinfo(conn, req, info_level,
5330 delete_pending, write_time_ts,
5332 lock_data_count, lock_data,
5333 req->flags2, max_data_bytes,
5334 ppdata, &data_size);
5335 if (!NT_STATUS_IS_OK(status)) {
5336 reply_nterror(req, status);
5340 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5346 /****************************************************************************
5347 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5349 ****************************************************************************/
5351 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5352 connection_struct *conn,
5353 const struct smb_filename *smb_fname_old,
5354 const struct smb_filename *smb_fname_new)
5356 NTSTATUS status = NT_STATUS_OK;
5358 /* source must already exist. */
5359 if (!VALID_STAT(smb_fname_old->st)) {
5360 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5363 /* Disallow if newname already exists. */
5364 if (VALID_STAT(smb_fname_new->st)) {
5365 return NT_STATUS_OBJECT_NAME_COLLISION;
5368 /* No links from a directory. */
5369 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5370 return NT_STATUS_FILE_IS_A_DIRECTORY;
5373 /* Setting a hardlink to/from a stream isn't currently supported. */
5374 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5375 is_ntfs_stream_smb_fname(smb_fname_new)) {
5376 return NT_STATUS_INVALID_PARAMETER;
5379 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5380 smb_fname_old->base_name, smb_fname_new->base_name));
5382 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5383 smb_fname_new->base_name) != 0) {
5384 status = map_nt_error_from_unix(errno);
5385 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5386 nt_errstr(status), smb_fname_old->base_name,
5387 smb_fname_new->base_name));
5392 /****************************************************************************
5393 Deal with setting the time from any of the setfilepathinfo functions.
5394 ****************************************************************************/
5396 NTSTATUS smb_set_file_time(connection_struct *conn,
5398 const struct smb_filename *smb_fname,
5399 struct smb_file_time *ft,
5400 bool setting_write_time)
5402 struct smb_filename smb_fname_base;
5404 FILE_NOTIFY_CHANGE_LAST_ACCESS
5405 |FILE_NOTIFY_CHANGE_LAST_WRITE
5406 |FILE_NOTIFY_CHANGE_CREATION;
5408 if (!VALID_STAT(smb_fname->st)) {
5409 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5412 /* get some defaults (no modifications) if any info is zero or -1. */
5413 if (null_timespec(ft->create_time)) {
5414 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5417 if (null_timespec(ft->atime)) {
5418 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5421 if (null_timespec(ft->mtime)) {
5422 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5425 if (!setting_write_time) {
5426 /* ft->mtime comes from change time, not write time. */
5427 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5430 /* Ensure the resolution is the correct for
5431 * what we can store on this filesystem. */
5433 round_timespec(conn->ts_res, &ft->create_time);
5434 round_timespec(conn->ts_res, &ft->ctime);
5435 round_timespec(conn->ts_res, &ft->atime);
5436 round_timespec(conn->ts_res, &ft->mtime);
5438 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5439 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5440 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5441 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5442 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5443 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5444 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5445 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5447 if (setting_write_time) {
5449 * This was a Windows setfileinfo on an open file.
5450 * NT does this a lot. We also need to
5451 * set the time here, as it can be read by
5452 * FindFirst/FindNext and with the patch for bug #2045
5453 * in smbd/fileio.c it ensures that this timestamp is
5454 * kept sticky even after a write. We save the request
5455 * away and will set it on file close and after a write. JRA.
5458 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5459 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5462 if (fsp->base_fsp) {
5463 set_sticky_write_time_fsp(fsp->base_fsp,
5466 set_sticky_write_time_fsp(fsp, ft->mtime);
5469 set_sticky_write_time_path(
5470 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5475 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5477 /* Always call ntimes on the base, even if a stream was passed in. */
5478 smb_fname_base = *smb_fname;
5479 smb_fname_base.stream_name = NULL;
5481 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5482 return map_nt_error_from_unix(errno);
5485 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5486 smb_fname->base_name);
5487 return NT_STATUS_OK;
5490 /****************************************************************************
5491 Deal with setting the dosmode from any of the setfilepathinfo functions.
5492 ****************************************************************************/
5494 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5495 const struct smb_filename *smb_fname,
5498 struct smb_filename *smb_fname_base = NULL;
5501 if (!VALID_STAT(smb_fname->st)) {
5502 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5505 /* Always operate on the base_name, even if a stream was passed in. */
5506 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5507 NULL, &smb_fname->st,
5509 if (!NT_STATUS_IS_OK(status)) {
5514 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5521 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5523 /* check the mode isn't different, before changing it */
5524 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5525 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5526 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5527 (unsigned int)dosmode));
5529 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5531 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5533 smb_fname_str_dbg(smb_fname_base),
5535 status = map_nt_error_from_unix(errno);
5539 status = NT_STATUS_OK;
5541 TALLOC_FREE(smb_fname_base);
5545 /****************************************************************************
5546 Deal with setting the size from any of the setfilepathinfo functions.
5547 ****************************************************************************/
5549 static NTSTATUS smb_set_file_size(connection_struct *conn,
5550 struct smb_request *req,
5552 const struct smb_filename *smb_fname,
5553 const SMB_STRUCT_STAT *psbuf,
5555 bool fail_after_createfile)
5557 NTSTATUS status = NT_STATUS_OK;
5558 struct smb_filename *smb_fname_tmp = NULL;
5559 files_struct *new_fsp = NULL;
5561 if (!VALID_STAT(*psbuf)) {
5562 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5565 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5567 if (size == get_file_size_stat(psbuf)) {
5568 return NT_STATUS_OK;
5571 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5572 smb_fname_str_dbg(smb_fname), (double)size));
5574 if (fsp && fsp->fh->fd != -1) {
5575 /* Handle based call. */
5576 if (vfs_set_filelen(fsp, size) == -1) {
5577 return map_nt_error_from_unix(errno);
5579 trigger_write_time_update_immediate(fsp);
5580 return NT_STATUS_OK;
5583 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5584 if (!NT_STATUS_IS_OK(status)) {
5588 smb_fname_tmp->st = *psbuf;
5590 status = SMB_VFS_CREATE_FILE(
5593 0, /* root_dir_fid */
5594 smb_fname_tmp, /* fname */
5595 FILE_WRITE_DATA, /* access_mask */
5596 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5598 FILE_OPEN, /* create_disposition*/
5599 0, /* create_options */
5600 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5601 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5602 0, /* allocation_size */
5603 0, /* private_flags */
5606 &new_fsp, /* result */
5609 TALLOC_FREE(smb_fname_tmp);
5611 if (!NT_STATUS_IS_OK(status)) {
5612 /* NB. We check for open_was_deferred in the caller. */
5616 /* See RAW-SFILEINFO-END-OF-FILE */
5617 if (fail_after_createfile) {
5618 close_file(req, new_fsp,NORMAL_CLOSE);
5619 return NT_STATUS_INVALID_LEVEL;
5622 if (vfs_set_filelen(new_fsp, size) == -1) {
5623 status = map_nt_error_from_unix(errno);
5624 close_file(req, new_fsp,NORMAL_CLOSE);
5628 trigger_write_time_update_immediate(new_fsp);
5629 close_file(req, new_fsp,NORMAL_CLOSE);
5630 return NT_STATUS_OK;
5633 /****************************************************************************
5634 Deal with SMB_INFO_SET_EA.
5635 ****************************************************************************/
5637 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5641 const struct smb_filename *smb_fname)
5643 struct ea_list *ea_list = NULL;
5644 TALLOC_CTX *ctx = NULL;
5645 NTSTATUS status = NT_STATUS_OK;
5647 if (total_data < 10) {
5649 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5650 length. They seem to have no effect. Bug #3212. JRA */
5652 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5653 /* We're done. We only get EA info in this call. */
5654 return NT_STATUS_OK;
5657 return NT_STATUS_INVALID_PARAMETER;
5660 if (IVAL(pdata,0) > total_data) {
5661 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5662 IVAL(pdata,0), (unsigned int)total_data));
5663 return NT_STATUS_INVALID_PARAMETER;
5667 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5669 return NT_STATUS_INVALID_PARAMETER;
5671 status = set_ea(conn, fsp, smb_fname, ea_list);
5676 /****************************************************************************
5677 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5678 ****************************************************************************/
5680 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5685 struct ea_list *ea_list = NULL;
5689 return NT_STATUS_INVALID_HANDLE;
5692 if (!lp_ea_support(SNUM(conn))) {
5693 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5694 "EA's not supported.\n",
5695 (unsigned int)total_data));
5696 return NT_STATUS_EAS_NOT_SUPPORTED;
5699 if (total_data < 10) {
5700 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5702 (unsigned int)total_data));
5703 return NT_STATUS_INVALID_PARAMETER;
5706 ea_list = read_nttrans_ea_list(talloc_tos(),
5711 return NT_STATUS_INVALID_PARAMETER;
5713 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5715 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5716 smb_fname_str_dbg(fsp->fsp_name),
5717 nt_errstr(status) ));
5723 /****************************************************************************
5724 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5725 ****************************************************************************/
5727 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5731 struct smb_filename *smb_fname)
5733 NTSTATUS status = NT_STATUS_OK;
5734 bool delete_on_close;
5737 if (total_data < 1) {
5738 return NT_STATUS_INVALID_PARAMETER;
5742 return NT_STATUS_INVALID_HANDLE;
5745 delete_on_close = (CVAL(pdata,0) ? True : False);
5746 dosmode = dos_mode(conn, smb_fname);
5748 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5749 "delete_on_close = %u\n",
5750 smb_fname_str_dbg(smb_fname),
5751 (unsigned int)dosmode,
5752 (unsigned int)delete_on_close ));
5754 if (delete_on_close) {
5755 status = can_set_delete_on_close(fsp, dosmode);
5756 if (!NT_STATUS_IS_OK(status)) {
5761 /* The set is across all open files on this dev/inode pair. */
5762 if (!set_delete_on_close(fsp, delete_on_close,
5763 &conn->server_info->utok)) {
5764 return NT_STATUS_ACCESS_DENIED;
5766 return NT_STATUS_OK;
5769 /****************************************************************************
5770 Deal with SMB_FILE_POSITION_INFORMATION.
5771 ****************************************************************************/
5773 static NTSTATUS smb_file_position_information(connection_struct *conn,
5778 uint64_t position_information;
5780 if (total_data < 8) {
5781 return NT_STATUS_INVALID_PARAMETER;
5785 /* Ignore on pathname based set. */
5786 return NT_STATUS_OK;
5789 position_information = (uint64_t)IVAL(pdata,0);
5790 #ifdef LARGE_SMB_OFF_T
5791 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5792 #else /* LARGE_SMB_OFF_T */
5793 if (IVAL(pdata,4) != 0) {
5794 /* more than 32 bits? */
5795 return NT_STATUS_INVALID_PARAMETER;
5797 #endif /* LARGE_SMB_OFF_T */
5799 DEBUG(10,("smb_file_position_information: Set file position "
5800 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5801 (double)position_information));
5802 fsp->fh->position_information = position_information;
5803 return NT_STATUS_OK;
5806 /****************************************************************************
5807 Deal with SMB_FILE_MODE_INFORMATION.
5808 ****************************************************************************/
5810 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5816 if (total_data < 4) {
5817 return NT_STATUS_INVALID_PARAMETER;
5819 mode = IVAL(pdata,0);
5820 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5821 return NT_STATUS_INVALID_PARAMETER;
5823 return NT_STATUS_OK;
5826 /****************************************************************************
5827 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5828 ****************************************************************************/
5830 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5831 struct smb_request *req,
5834 const struct smb_filename *smb_fname)
5836 char *link_target = NULL;
5837 const char *newname = smb_fname->base_name;
5838 TALLOC_CTX *ctx = talloc_tos();
5840 /* Set a symbolic link. */
5841 /* Don't allow this if follow links is false. */
5843 if (total_data == 0) {
5844 return NT_STATUS_INVALID_PARAMETER;
5847 if (!lp_symlinks(SNUM(conn))) {
5848 return NT_STATUS_ACCESS_DENIED;
5851 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5852 total_data, STR_TERMINATE);
5855 return NT_STATUS_INVALID_PARAMETER;
5858 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5859 newname, link_target ));
5861 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5862 return map_nt_error_from_unix(errno);
5865 return NT_STATUS_OK;
5868 /****************************************************************************
5869 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5870 ****************************************************************************/
5872 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5873 struct smb_request *req,
5874 const char *pdata, int total_data,
5875 const struct smb_filename *smb_fname_new)
5877 char *oldname = NULL;
5878 struct smb_filename *smb_fname_old = NULL;
5879 TALLOC_CTX *ctx = talloc_tos();
5880 NTSTATUS status = NT_STATUS_OK;
5882 /* Set a hard link. */
5883 if (total_data == 0) {
5884 return NT_STATUS_INVALID_PARAMETER;
5887 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5888 total_data, STR_TERMINATE, &status);
5889 if (!NT_STATUS_IS_OK(status)) {
5893 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5894 smb_fname_str_dbg(smb_fname_new), oldname));
5896 status = filename_convert(ctx,
5898 req->flags2 & FLAGS2_DFS_PATHNAMES,
5903 if (!NT_STATUS_IS_OK(status)) {
5907 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5910 /****************************************************************************
5911 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5912 ****************************************************************************/
5914 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5915 struct smb_request *req,
5919 struct smb_filename *smb_fname_src)
5923 char *newname = NULL;
5924 struct smb_filename *smb_fname_dst = NULL;
5925 NTSTATUS status = NT_STATUS_OK;
5926 TALLOC_CTX *ctx = talloc_tos();
5929 return NT_STATUS_INVALID_HANDLE;
5932 if (total_data < 20) {
5933 return NT_STATUS_INVALID_PARAMETER;
5936 overwrite = (CVAL(pdata,0) ? True : False);
5937 len = IVAL(pdata,16);
5939 if (len > (total_data - 20) || (len == 0)) {
5940 return NT_STATUS_INVALID_PARAMETER;
5943 srvstr_get_path(ctx, pdata, req->flags2, &newname,
5944 &pdata[20], len, STR_TERMINATE,
5946 if (!NT_STATUS_IS_OK(status)) {
5950 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5953 status = filename_convert(ctx,
5955 req->flags2 & FLAGS2_DFS_PATHNAMES,
5960 if (!NT_STATUS_IS_OK(status)) {
5964 /* Ok, this looks wrong to me, but appears to
5965 * be how SMB2 renames work. CHECK WITH Microsoft !
5968 if (fsp->oplock_type != NO_OPLOCK) {
5969 return NT_STATUS_SHARING_VIOLATION;
5972 if (fsp->base_fsp) {
5973 /* newname must be a stream name. */
5974 if (newname[0] != ':') {
5975 return NT_STATUS_NOT_SUPPORTED;
5978 /* Create an smb_fname to call rename_internals_fsp() with. */
5979 status = create_synthetic_smb_fname(talloc_tos(),
5980 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5982 if (!NT_STATUS_IS_OK(status)) {
5987 * Set the original last component, since
5988 * rename_internals_fsp() requires it.
5990 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5992 if (smb_fname_dst->original_lcomp == NULL) {
5993 status = NT_STATUS_NO_MEMORY;
5999 DEBUG(10,("smb2_file_rename_information: "
6000 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6001 fsp->fnum, fsp_str_dbg(fsp),
6002 smb_fname_str_dbg(smb_fname_dst)));
6003 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6007 TALLOC_FREE(smb_fname_dst);
6012 /****************************************************************************
6013 Deal with SMB_FILE_RENAME_INFORMATION.
6014 ****************************************************************************/
6016 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6017 struct smb_request *req,
6021 struct smb_filename *smb_fname_src)
6026 char *newname = NULL;
6027 struct smb_filename *smb_fname_dst = NULL;
6028 bool dest_has_wcard = False;
6029 NTSTATUS status = NT_STATUS_OK;
6031 TALLOC_CTX *ctx = talloc_tos();
6033 if (total_data < 13) {
6034 return NT_STATUS_INVALID_PARAMETER;
6037 overwrite = (CVAL(pdata,0) ? True : False);
6038 root_fid = IVAL(pdata,4);
6039 len = IVAL(pdata,8);
6041 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6042 return NT_STATUS_INVALID_PARAMETER;
6045 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6048 if (!NT_STATUS_IS_OK(status)) {
6052 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6055 status = resolve_dfspath_wcard(ctx, conn,
6056 req->flags2 & FLAGS2_DFS_PATHNAMES,
6061 if (!NT_STATUS_IS_OK(status)) {
6065 /* Check the new name has no '/' characters. */
6066 if (strchr_m(newname, '/')) {
6067 return NT_STATUS_NOT_SUPPORTED;
6070 if (fsp && fsp->base_fsp) {
6071 /* newname must be a stream name. */
6072 if (newname[0] != ':') {
6073 return NT_STATUS_NOT_SUPPORTED;
6076 /* Create an smb_fname to call rename_internals_fsp() with. */
6077 status = create_synthetic_smb_fname(talloc_tos(),
6078 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6080 if (!NT_STATUS_IS_OK(status)) {
6085 * Set the original last component, since
6086 * rename_internals_fsp() requires it.
6088 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6090 if (smb_fname_dst->original_lcomp == NULL) {
6091 status = NT_STATUS_NO_MEMORY;
6097 * Build up an smb_fname_dst based on the filename passed in.
6098 * We basically just strip off the last component, and put on
6099 * the newname instead.
6101 char *base_name = NULL;
6103 /* newname must *not* be a stream name. */
6104 if (newname[0] == ':') {
6105 return NT_STATUS_NOT_SUPPORTED;
6109 * Strip off the last component (filename) of the path passed
6112 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6114 return NT_STATUS_NO_MEMORY;
6116 p = strrchr_m(base_name, '/');
6120 base_name = talloc_strdup(ctx, "./");
6122 return NT_STATUS_NO_MEMORY;
6125 /* Append the new name. */
6126 base_name = talloc_asprintf_append(base_name,
6130 return NT_STATUS_NO_MEMORY;
6133 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6136 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6139 /* If an error we expect this to be
6140 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6142 if (!NT_STATUS_IS_OK(status)) {
6143 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6147 /* Create an smb_fname to call rename_internals_fsp() */
6148 status = create_synthetic_smb_fname(ctx,
6152 if (!NT_STATUS_IS_OK(status)) {
6159 DEBUG(10,("smb_file_rename_information: "
6160 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6161 fsp->fnum, fsp_str_dbg(fsp),
6162 smb_fname_str_dbg(smb_fname_dst)));
6163 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6166 DEBUG(10,("smb_file_rename_information: "
6167 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6168 smb_fname_str_dbg(smb_fname_src),
6169 smb_fname_str_dbg(smb_fname_dst)));
6170 status = rename_internals(ctx, conn, req, smb_fname_src,
6171 smb_fname_dst, 0, overwrite, false,
6173 FILE_WRITE_ATTRIBUTES);
6176 TALLOC_FREE(smb_fname_dst);
6180 /****************************************************************************
6181 Deal with SMB_SET_POSIX_ACL.
6182 ****************************************************************************/
6184 #if defined(HAVE_POSIX_ACLS)
6185 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6189 const struct smb_filename *smb_fname)
6191 uint16 posix_acl_version;
6192 uint16 num_file_acls;
6193 uint16 num_def_acls;
6194 bool valid_file_acls = True;
6195 bool valid_def_acls = True;
6197 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6198 return NT_STATUS_INVALID_PARAMETER;
6200 posix_acl_version = SVAL(pdata,0);
6201 num_file_acls = SVAL(pdata,2);
6202 num_def_acls = SVAL(pdata,4);
6204 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6205 valid_file_acls = False;
6209 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6210 valid_def_acls = False;
6214 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6215 return NT_STATUS_INVALID_PARAMETER;
6218 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6219 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6220 return NT_STATUS_INVALID_PARAMETER;
6223 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6224 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6225 (unsigned int)num_file_acls,
6226 (unsigned int)num_def_acls));
6228 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6229 smb_fname->base_name, num_file_acls,
6230 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6231 return map_nt_error_from_unix(errno);
6234 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6235 smb_fname->base_name, &smb_fname->st, num_def_acls,
6236 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6237 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6238 return map_nt_error_from_unix(errno);
6240 return NT_STATUS_OK;
6244 /****************************************************************************
6245 Deal with SMB_SET_POSIX_LOCK.
6246 ****************************************************************************/
6248 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6249 struct smb_request *req,
6257 bool blocking_lock = False;
6258 enum brl_type lock_type;
6260 NTSTATUS status = NT_STATUS_OK;
6262 if (fsp == NULL || fsp->fh->fd == -1) {
6263 return NT_STATUS_INVALID_HANDLE;
6266 if (total_data != POSIX_LOCK_DATA_SIZE) {
6267 return NT_STATUS_INVALID_PARAMETER;
6270 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6271 case POSIX_LOCK_TYPE_READ:
6272 lock_type = READ_LOCK;
6274 case POSIX_LOCK_TYPE_WRITE:
6275 /* Return the right POSIX-mappable error code for files opened read-only. */
6276 if (!fsp->can_write) {
6277 return NT_STATUS_INVALID_HANDLE;
6279 lock_type = WRITE_LOCK;
6281 case POSIX_LOCK_TYPE_UNLOCK:
6282 lock_type = UNLOCK_LOCK;
6285 return NT_STATUS_INVALID_PARAMETER;
6288 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6289 blocking_lock = False;
6290 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6291 blocking_lock = True;
6293 return NT_STATUS_INVALID_PARAMETER;
6296 if (!lp_blocking_locks(SNUM(conn))) {
6297 blocking_lock = False;
6300 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6301 #if defined(HAVE_LONGLONG)
6302 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6303 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6304 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6305 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6306 #else /* HAVE_LONGLONG */
6307 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6308 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6309 #endif /* HAVE_LONGLONG */
6311 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6312 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6314 (unsigned int)lock_type,
6315 (unsigned long long)smblctx,
6319 if (lock_type == UNLOCK_LOCK) {
6320 status = do_unlock(smbd_messaging_context(),
6327 uint64_t block_smblctx;
6329 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6341 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6343 * A blocking lock was requested. Package up
6344 * this smb into a queued request and push it
6345 * onto the blocking lock queue.
6347 if(push_blocking_lock_request(br_lck,
6350 -1, /* infinite timeout. */
6358 TALLOC_FREE(br_lck);
6362 TALLOC_FREE(br_lck);
6368 /****************************************************************************
6369 Deal with SMB_SET_FILE_BASIC_INFO.
6370 ****************************************************************************/
6372 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6376 const struct smb_filename *smb_fname)
6378 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6379 struct smb_file_time ft;
6381 NTSTATUS status = NT_STATUS_OK;
6385 if (total_data < 36) {
6386 return NT_STATUS_INVALID_PARAMETER;
6389 /* Set the attributes */
6390 dosmode = IVAL(pdata,32);
6391 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6392 if (!NT_STATUS_IS_OK(status)) {
6397 ft.create_time = interpret_long_date(pdata);
6400 ft.atime = interpret_long_date(pdata+8);
6403 ft.mtime = interpret_long_date(pdata+16);
6406 ft.ctime = interpret_long_date(pdata+24);
6408 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6409 smb_fname_str_dbg(smb_fname)));
6411 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6415 /****************************************************************************
6416 Deal with SMB_INFO_STANDARD.
6417 ****************************************************************************/
6419 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6423 const struct smb_filename *smb_fname)
6425 struct smb_file_time ft;
6429 if (total_data < 12) {
6430 return NT_STATUS_INVALID_PARAMETER;
6434 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6436 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6438 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6440 DEBUG(10,("smb_set_info_standard: file %s\n",
6441 smb_fname_str_dbg(smb_fname)));
6443 return smb_set_file_time(conn,
6450 /****************************************************************************
6451 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6452 ****************************************************************************/
6454 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6455 struct smb_request *req,
6459 struct smb_filename *smb_fname)
6461 uint64_t allocation_size = 0;
6462 NTSTATUS status = NT_STATUS_OK;
6463 files_struct *new_fsp = NULL;
6465 if (!VALID_STAT(smb_fname->st)) {
6466 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6469 if (total_data < 8) {
6470 return NT_STATUS_INVALID_PARAMETER;
6473 allocation_size = (uint64_t)IVAL(pdata,0);
6474 #ifdef LARGE_SMB_OFF_T
6475 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6476 #else /* LARGE_SMB_OFF_T */
6477 if (IVAL(pdata,4) != 0) {
6478 /* more than 32 bits? */
6479 return NT_STATUS_INVALID_PARAMETER;
6481 #endif /* LARGE_SMB_OFF_T */
6483 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6484 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6485 (double)allocation_size));
6487 if (allocation_size) {
6488 allocation_size = smb_roundup(conn, allocation_size);
6491 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6492 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6493 (double)allocation_size));
6495 if (fsp && fsp->fh->fd != -1) {
6496 /* Open file handle. */
6497 /* Only change if needed. */
6498 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6499 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6500 return map_nt_error_from_unix(errno);
6503 /* But always update the time. */
6505 * This is equivalent to a write. Ensure it's seen immediately
6506 * if there are no pending writes.
6508 trigger_write_time_update_immediate(fsp);
6509 return NT_STATUS_OK;
6512 /* Pathname or stat or directory file. */
6513 status = SMB_VFS_CREATE_FILE(
6516 0, /* root_dir_fid */
6517 smb_fname, /* fname */
6518 FILE_WRITE_DATA, /* access_mask */
6519 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6521 FILE_OPEN, /* create_disposition*/
6522 0, /* create_options */
6523 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6524 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6525 0, /* allocation_size */
6526 0, /* private_flags */
6529 &new_fsp, /* result */
6532 if (!NT_STATUS_IS_OK(status)) {
6533 /* NB. We check for open_was_deferred in the caller. */
6537 /* Only change if needed. */
6538 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6539 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6540 status = map_nt_error_from_unix(errno);
6541 close_file(req, new_fsp, NORMAL_CLOSE);
6546 /* Changing the allocation size should set the last mod time. */
6548 * This is equivalent to a write. Ensure it's seen immediately
6549 * if there are no pending writes.
6551 trigger_write_time_update_immediate(new_fsp);
6553 close_file(req, new_fsp, NORMAL_CLOSE);
6554 return NT_STATUS_OK;
6557 /****************************************************************************
6558 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6559 ****************************************************************************/
6561 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6562 struct smb_request *req,
6566 const struct smb_filename *smb_fname,
6567 bool fail_after_createfile)
6571 if (total_data < 8) {
6572 return NT_STATUS_INVALID_PARAMETER;
6575 size = IVAL(pdata,0);
6576 #ifdef LARGE_SMB_OFF_T
6577 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6578 #else /* LARGE_SMB_OFF_T */
6579 if (IVAL(pdata,4) != 0) {
6580 /* more than 32 bits? */
6581 return NT_STATUS_INVALID_PARAMETER;
6583 #endif /* LARGE_SMB_OFF_T */
6584 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6585 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6588 return smb_set_file_size(conn, req,
6593 fail_after_createfile);
6596 /****************************************************************************
6597 Allow a UNIX info mknod.
6598 ****************************************************************************/
6600 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6603 const struct smb_filename *smb_fname)
6605 uint32 file_type = IVAL(pdata,56);
6606 #if defined(HAVE_MAKEDEV)
6607 uint32 dev_major = IVAL(pdata,60);
6608 uint32 dev_minor = IVAL(pdata,68);
6610 SMB_DEV_T dev = (SMB_DEV_T)0;
6611 uint32 raw_unixmode = IVAL(pdata,84);
6615 if (total_data < 100) {
6616 return NT_STATUS_INVALID_PARAMETER;
6619 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6620 PERM_NEW_FILE, &unixmode);
6621 if (!NT_STATUS_IS_OK(status)) {
6625 #if defined(HAVE_MAKEDEV)
6626 dev = makedev(dev_major, dev_minor);
6629 switch (file_type) {
6630 #if defined(S_IFIFO)
6631 case UNIX_TYPE_FIFO:
6632 unixmode |= S_IFIFO;
6635 #if defined(S_IFSOCK)
6636 case UNIX_TYPE_SOCKET:
6637 unixmode |= S_IFSOCK;
6640 #if defined(S_IFCHR)
6641 case UNIX_TYPE_CHARDEV:
6642 unixmode |= S_IFCHR;
6645 #if defined(S_IFBLK)
6646 case UNIX_TYPE_BLKDEV:
6647 unixmode |= S_IFBLK;
6651 return NT_STATUS_INVALID_PARAMETER;
6654 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6655 "%.0f mode 0%o for file %s\n", (double)dev,
6656 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6658 /* Ok - do the mknod. */
6659 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6660 return map_nt_error_from_unix(errno);
6663 /* If any of the other "set" calls fail we
6664 * don't want to end up with a half-constructed mknod.
6667 if (lp_inherit_perms(SNUM(conn))) {
6669 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6671 return NT_STATUS_NO_MEMORY;
6673 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6675 TALLOC_FREE(parent);
6678 return NT_STATUS_OK;
6681 /****************************************************************************
6682 Deal with SMB_SET_FILE_UNIX_BASIC.
6683 ****************************************************************************/
6685 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6686 struct smb_request *req,
6690 const struct smb_filename *smb_fname)
6692 struct smb_file_time ft;
6693 uint32 raw_unixmode;
6696 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6697 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6698 NTSTATUS status = NT_STATUS_OK;
6699 bool delete_on_fail = False;
6700 enum perm_type ptype;
6701 files_struct *all_fsps = NULL;
6702 bool modify_mtime = true;
6704 SMB_STRUCT_STAT sbuf;
6708 if (total_data < 100) {
6709 return NT_STATUS_INVALID_PARAMETER;
6712 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6713 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6714 size=IVAL(pdata,0); /* first 8 Bytes are size */
6715 #ifdef LARGE_SMB_OFF_T
6716 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6717 #else /* LARGE_SMB_OFF_T */
6718 if (IVAL(pdata,4) != 0) {
6719 /* more than 32 bits? */
6720 return NT_STATUS_INVALID_PARAMETER;
6722 #endif /* LARGE_SMB_OFF_T */
6725 ft.atime = interpret_long_date(pdata+24); /* access_time */
6726 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6727 set_owner = (uid_t)IVAL(pdata,40);
6728 set_grp = (gid_t)IVAL(pdata,48);
6729 raw_unixmode = IVAL(pdata,84);
6731 if (VALID_STAT(smb_fname->st)) {
6732 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6733 ptype = PERM_EXISTING_DIR;
6735 ptype = PERM_EXISTING_FILE;
6738 ptype = PERM_NEW_FILE;
6741 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6743 if (!NT_STATUS_IS_OK(status)) {
6747 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6748 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6749 smb_fname_str_dbg(smb_fname), (double)size,
6750 (unsigned int)set_owner, (unsigned int)set_grp,
6751 (int)raw_unixmode));
6753 sbuf = smb_fname->st;
6755 if (!VALID_STAT(sbuf)) {
6756 struct smb_filename *smb_fname_tmp = NULL;
6758 * The only valid use of this is to create character and block
6759 * devices, and named pipes. This is deprecated (IMHO) and
6760 * a new info level should be used for mknod. JRA.
6763 status = smb_unix_mknod(conn,
6767 if (!NT_STATUS_IS_OK(status)) {
6771 status = copy_smb_filename(talloc_tos(), smb_fname,
6773 if (!NT_STATUS_IS_OK(status)) {
6777 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6778 status = map_nt_error_from_unix(errno);
6779 TALLOC_FREE(smb_fname_tmp);
6780 SMB_VFS_UNLINK(conn, smb_fname);
6784 sbuf = smb_fname_tmp->st;
6785 TALLOC_FREE(smb_fname_tmp);
6787 /* Ensure we don't try and change anything else. */
6788 raw_unixmode = SMB_MODE_NO_CHANGE;
6789 size = get_file_size_stat(&sbuf);
6790 ft.atime = sbuf.st_ex_atime;
6791 ft.mtime = sbuf.st_ex_mtime;
6793 * We continue here as we might want to change the
6796 delete_on_fail = True;
6800 /* Horrible backwards compatibility hack as an old server bug
6801 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6805 size = get_file_size_stat(&sbuf);
6810 * Deal with the UNIX specific mode set.
6813 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6814 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6815 "setting mode 0%o for file %s\n",
6816 (unsigned int)unixmode,
6817 smb_fname_str_dbg(smb_fname)));
6818 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6819 return map_nt_error_from_unix(errno);
6824 * Deal with the UNIX specific uid set.
6827 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6828 (sbuf.st_ex_uid != set_owner)) {
6831 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6832 "changing owner %u for path %s\n",
6833 (unsigned int)set_owner,
6834 smb_fname_str_dbg(smb_fname)));
6836 if (S_ISLNK(sbuf.st_ex_mode)) {
6837 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6838 set_owner, (gid_t)-1);
6840 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6841 set_owner, (gid_t)-1);
6845 status = map_nt_error_from_unix(errno);
6846 if (delete_on_fail) {
6847 SMB_VFS_UNLINK(conn, smb_fname);
6854 * Deal with the UNIX specific gid set.
6857 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6858 (sbuf.st_ex_gid != set_grp)) {
6859 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6860 "changing group %u for file %s\n",
6861 (unsigned int)set_owner,
6862 smb_fname_str_dbg(smb_fname)));
6863 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6865 status = map_nt_error_from_unix(errno);
6866 if (delete_on_fail) {
6867 SMB_VFS_UNLINK(conn, smb_fname);
6873 /* Deal with any size changes. */
6875 status = smb_set_file_size(conn, req,
6881 if (!NT_STATUS_IS_OK(status)) {
6885 /* Deal with any time changes. */
6886 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6887 /* No change, don't cancel anything. */
6891 id = vfs_file_id_from_sbuf(conn, &sbuf);
6892 for(all_fsps = file_find_di_first(id); all_fsps;
6893 all_fsps = file_find_di_next(all_fsps)) {
6895 * We're setting the time explicitly for UNIX.
6896 * Cancel any pending changes over all handles.
6898 all_fsps->update_write_time_on_close = false;
6899 TALLOC_FREE(all_fsps->update_write_time_event);
6903 * Override the "setting_write_time"
6904 * parameter here as it almost does what
6905 * we need. Just remember if we modified
6906 * mtime and send the notify ourselves.
6908 if (null_timespec(ft.mtime)) {
6909 modify_mtime = false;
6912 status = smb_set_file_time(conn,
6918 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6919 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6924 /****************************************************************************
6925 Deal with SMB_SET_FILE_UNIX_INFO2.
6926 ****************************************************************************/
6928 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6929 struct smb_request *req,
6933 const struct smb_filename *smb_fname)
6939 if (total_data < 116) {
6940 return NT_STATUS_INVALID_PARAMETER;
6943 /* Start by setting all the fields that are common between UNIX_BASIC
6946 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6948 if (!NT_STATUS_IS_OK(status)) {
6952 smb_fflags = IVAL(pdata, 108);
6953 smb_fmask = IVAL(pdata, 112);
6955 /* NB: We should only attempt to alter the file flags if the client
6956 * sends a non-zero mask.
6958 if (smb_fmask != 0) {
6959 int stat_fflags = 0;
6961 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6962 smb_fmask, &stat_fflags)) {
6963 /* Client asked to alter a flag we don't understand. */
6964 return NT_STATUS_INVALID_PARAMETER;
6967 if (fsp && fsp->fh->fd != -1) {
6968 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6969 return NT_STATUS_NOT_SUPPORTED;
6971 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6972 stat_fflags) != 0) {
6973 return map_nt_error_from_unix(errno);
6978 /* XXX: need to add support for changing the create_time here. You
6979 * can do this for paths on Darwin with setattrlist(2). The right way
6980 * to hook this up is probably by extending the VFS utimes interface.
6983 return NT_STATUS_OK;
6986 /****************************************************************************
6987 Create a directory with POSIX semantics.
6988 ****************************************************************************/
6990 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6991 struct smb_request *req,
6994 struct smb_filename *smb_fname,
6995 int *pdata_return_size)
6997 NTSTATUS status = NT_STATUS_OK;
6998 uint32 raw_unixmode = 0;
6999 uint32 mod_unixmode = 0;
7000 mode_t unixmode = (mode_t)0;
7001 files_struct *fsp = NULL;
7002 uint16 info_level_return = 0;
7004 char *pdata = *ppdata;
7006 if (total_data < 18) {
7007 return NT_STATUS_INVALID_PARAMETER;
7010 raw_unixmode = IVAL(pdata,8);
7011 /* Next 4 bytes are not yet defined. */
7013 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7014 PERM_NEW_DIR, &unixmode);
7015 if (!NT_STATUS_IS_OK(status)) {
7019 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7021 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7022 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7024 status = SMB_VFS_CREATE_FILE(
7027 0, /* root_dir_fid */
7028 smb_fname, /* fname */
7029 FILE_READ_ATTRIBUTES, /* access_mask */
7030 FILE_SHARE_NONE, /* share_access */
7031 FILE_CREATE, /* create_disposition*/
7032 FILE_DIRECTORY_FILE, /* create_options */
7033 mod_unixmode, /* file_attributes */
7034 0, /* oplock_request */
7035 0, /* allocation_size */
7036 0, /* private_flags */
7042 if (NT_STATUS_IS_OK(status)) {
7043 close_file(req, fsp, NORMAL_CLOSE);
7046 info_level_return = SVAL(pdata,16);
7048 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7049 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7050 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7051 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7053 *pdata_return_size = 12;
7056 /* Realloc the data size */
7057 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7058 if (*ppdata == NULL) {
7059 *pdata_return_size = 0;
7060 return NT_STATUS_NO_MEMORY;
7064 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7065 SSVAL(pdata,2,0); /* No fnum. */
7066 SIVAL(pdata,4,info); /* Was directory created. */
7068 switch (info_level_return) {
7069 case SMB_QUERY_FILE_UNIX_BASIC:
7070 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7071 SSVAL(pdata,10,0); /* Padding. */
7072 store_file_unix_basic(conn, pdata + 12, fsp,
7075 case SMB_QUERY_FILE_UNIX_INFO2:
7076 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7077 SSVAL(pdata,10,0); /* Padding. */
7078 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7082 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7083 SSVAL(pdata,10,0); /* Padding. */
7090 /****************************************************************************
7091 Open/Create a file with POSIX semantics.
7092 ****************************************************************************/
7094 static NTSTATUS smb_posix_open(connection_struct *conn,
7095 struct smb_request *req,
7098 struct smb_filename *smb_fname,
7099 int *pdata_return_size)
7101 bool extended_oplock_granted = False;
7102 char *pdata = *ppdata;
7104 uint32 wire_open_mode = 0;
7105 uint32 raw_unixmode = 0;
7106 uint32 mod_unixmode = 0;
7107 uint32 create_disp = 0;
7108 uint32 access_mask = 0;
7109 uint32 create_options = 0;
7110 NTSTATUS status = NT_STATUS_OK;
7111 mode_t unixmode = (mode_t)0;
7112 files_struct *fsp = NULL;
7113 int oplock_request = 0;
7115 uint16 info_level_return = 0;
7117 if (total_data < 18) {
7118 return NT_STATUS_INVALID_PARAMETER;
7121 flags = IVAL(pdata,0);
7122 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7123 if (oplock_request) {
7124 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7127 wire_open_mode = IVAL(pdata,4);
7129 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7130 return smb_posix_mkdir(conn, req,
7137 switch (wire_open_mode & SMB_ACCMODE) {
7139 access_mask = FILE_READ_DATA;
7142 access_mask = FILE_WRITE_DATA;
7145 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7148 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7149 (unsigned int)wire_open_mode ));
7150 return NT_STATUS_INVALID_PARAMETER;
7153 wire_open_mode &= ~SMB_ACCMODE;
7155 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7156 create_disp = FILE_CREATE;
7157 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7158 create_disp = FILE_OVERWRITE_IF;
7159 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7160 create_disp = FILE_OPEN_IF;
7161 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7162 create_disp = FILE_OPEN;
7164 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7165 (unsigned int)wire_open_mode ));
7166 return NT_STATUS_INVALID_PARAMETER;
7169 raw_unixmode = IVAL(pdata,8);
7170 /* Next 4 bytes are not yet defined. */
7172 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7173 (VALID_STAT(smb_fname->st) ?
7174 PERM_EXISTING_FILE : PERM_NEW_FILE),
7177 if (!NT_STATUS_IS_OK(status)) {
7181 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7183 if (wire_open_mode & SMB_O_SYNC) {
7184 create_options |= FILE_WRITE_THROUGH;
7186 if (wire_open_mode & SMB_O_APPEND) {
7187 access_mask |= FILE_APPEND_DATA;
7189 if (wire_open_mode & SMB_O_DIRECT) {
7190 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7193 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7194 smb_fname_str_dbg(smb_fname),
7195 (unsigned int)wire_open_mode,
7196 (unsigned int)unixmode ));
7198 status = SMB_VFS_CREATE_FILE(
7201 0, /* root_dir_fid */
7202 smb_fname, /* fname */
7203 access_mask, /* access_mask */
7204 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7206 create_disp, /* create_disposition*/
7207 FILE_NON_DIRECTORY_FILE, /* create_options */
7208 mod_unixmode, /* file_attributes */
7209 oplock_request, /* oplock_request */
7210 0, /* allocation_size */
7211 0, /* private_flags */
7217 if (!NT_STATUS_IS_OK(status)) {
7221 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7222 extended_oplock_granted = True;
7225 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7226 extended_oplock_granted = True;
7229 info_level_return = SVAL(pdata,16);
7231 /* Allocate the correct return size. */
7233 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7234 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7235 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7236 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7238 *pdata_return_size = 12;
7241 /* Realloc the data size */
7242 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7243 if (*ppdata == NULL) {
7244 close_file(req, fsp, ERROR_CLOSE);
7245 *pdata_return_size = 0;
7246 return NT_STATUS_NO_MEMORY;
7250 if (extended_oplock_granted) {
7251 if (flags & REQUEST_BATCH_OPLOCK) {
7252 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7254 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7256 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7257 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7259 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7262 SSVAL(pdata,2,fsp->fnum);
7263 SIVAL(pdata,4,info); /* Was file created etc. */
7265 switch (info_level_return) {
7266 case SMB_QUERY_FILE_UNIX_BASIC:
7267 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7268 SSVAL(pdata,10,0); /* padding. */
7269 store_file_unix_basic(conn, pdata + 12, fsp,
7272 case SMB_QUERY_FILE_UNIX_INFO2:
7273 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7274 SSVAL(pdata,10,0); /* padding. */
7275 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7279 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7280 SSVAL(pdata,10,0); /* padding. */
7283 return NT_STATUS_OK;
7286 /****************************************************************************
7287 Delete a file with POSIX semantics.
7288 ****************************************************************************/
7290 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7291 struct smb_request *req,
7294 struct smb_filename *smb_fname)
7296 NTSTATUS status = NT_STATUS_OK;
7297 files_struct *fsp = NULL;
7301 int create_options = 0;
7303 struct share_mode_lock *lck = NULL;
7305 if (total_data < 2) {
7306 return NT_STATUS_INVALID_PARAMETER;
7309 flags = SVAL(pdata,0);
7311 if (!VALID_STAT(smb_fname->st)) {
7312 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7315 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7316 !VALID_STAT_OF_DIR(smb_fname->st)) {
7317 return NT_STATUS_NOT_A_DIRECTORY;
7320 DEBUG(10,("smb_posix_unlink: %s %s\n",
7321 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7322 smb_fname_str_dbg(smb_fname)));
7324 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7325 create_options |= FILE_DIRECTORY_FILE;
7328 status = SMB_VFS_CREATE_FILE(
7331 0, /* root_dir_fid */
7332 smb_fname, /* fname */
7333 DELETE_ACCESS, /* access_mask */
7334 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7336 FILE_OPEN, /* create_disposition*/
7337 create_options, /* create_options */
7338 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7339 0, /* oplock_request */
7340 0, /* allocation_size */
7341 0, /* private_flags */
7347 if (!NT_STATUS_IS_OK(status)) {
7352 * Don't lie to client. If we can't really delete due to
7353 * non-POSIX opens return SHARING_VIOLATION.
7356 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7359 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7360 "lock for file %s\n", fsp_str_dbg(fsp)));
7361 close_file(req, fsp, NORMAL_CLOSE);
7362 return NT_STATUS_INVALID_PARAMETER;
7366 * See if others still have the file open. If this is the case, then
7367 * don't delete. If all opens are POSIX delete we can set the delete
7368 * on close disposition.
7370 for (i=0; i<lck->num_share_modes; i++) {
7371 struct share_mode_entry *e = &lck->share_modes[i];
7372 if (is_valid_share_mode_entry(e)) {
7373 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7376 /* Fail with sharing violation. */
7377 close_file(req, fsp, NORMAL_CLOSE);
7379 return NT_STATUS_SHARING_VIOLATION;
7384 * Set the delete on close.
7386 status = smb_set_file_disposition_info(conn,
7392 if (!NT_STATUS_IS_OK(status)) {
7393 close_file(req, fsp, NORMAL_CLOSE);
7398 return close_file(req, fsp, NORMAL_CLOSE);
7401 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7402 struct smb_request *req,
7403 TALLOC_CTX *mem_ctx,
7404 uint16_t info_level,
7406 struct smb_filename *smb_fname,
7407 char **ppdata, int total_data,
7410 char *pdata = *ppdata;
7411 NTSTATUS status = NT_STATUS_OK;
7412 int data_return_size = 0;
7416 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7417 return NT_STATUS_INVALID_LEVEL;
7420 if (!CAN_WRITE(conn)) {
7421 /* Allow POSIX opens. The open path will deny
7422 * any non-readonly opens. */
7423 if (info_level != SMB_POSIX_PATH_OPEN) {
7424 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7428 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7429 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7430 fsp ? fsp->fnum : -1, info_level, total_data));
7432 switch (info_level) {
7434 case SMB_INFO_STANDARD:
7436 status = smb_set_info_standard(conn,
7444 case SMB_INFO_SET_EA:
7446 status = smb_info_set_ea(conn,
7454 case SMB_SET_FILE_BASIC_INFO:
7455 case SMB_FILE_BASIC_INFORMATION:
7457 status = smb_set_file_basic_info(conn,
7465 case SMB_FILE_ALLOCATION_INFORMATION:
7466 case SMB_SET_FILE_ALLOCATION_INFO:
7468 status = smb_set_file_allocation_info(conn, req,
7476 case SMB_FILE_END_OF_FILE_INFORMATION:
7477 case SMB_SET_FILE_END_OF_FILE_INFO:
7480 * XP/Win7 both fail after the createfile with
7481 * SMB_SET_FILE_END_OF_FILE_INFO but not
7482 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7483 * The level is known here, so pass it down
7487 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7489 status = smb_set_file_end_of_file_info(conn, req,
7498 case SMB_FILE_DISPOSITION_INFORMATION:
7499 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7502 /* JRA - We used to just ignore this on a path ?
7503 * Shouldn't this be invalid level on a pathname
7506 if (tran_call != TRANSACT2_SETFILEINFO) {
7507 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7510 status = smb_set_file_disposition_info(conn,
7518 case SMB_FILE_POSITION_INFORMATION:
7520 status = smb_file_position_information(conn,
7527 case SMB_FILE_FULL_EA_INFORMATION:
7529 status = smb_set_file_full_ea_info(conn,
7536 /* From tridge Samba4 :
7537 * MODE_INFORMATION in setfileinfo (I have no
7538 * idea what "mode information" on a file is - it takes a value of 0,
7539 * 2, 4 or 6. What could it be?).
7542 case SMB_FILE_MODE_INFORMATION:
7544 status = smb_file_mode_information(conn,
7551 * CIFS UNIX extensions.
7554 case SMB_SET_FILE_UNIX_BASIC:
7556 status = smb_set_file_unix_basic(conn, req,
7564 case SMB_SET_FILE_UNIX_INFO2:
7566 status = smb_set_file_unix_info2(conn, req,
7574 case SMB_SET_FILE_UNIX_LINK:
7577 /* We must have a pathname for this. */
7578 return NT_STATUS_INVALID_LEVEL;
7580 status = smb_set_file_unix_link(conn, req, pdata,
7581 total_data, smb_fname);
7585 case SMB_SET_FILE_UNIX_HLINK:
7588 /* We must have a pathname for this. */
7589 return NT_STATUS_INVALID_LEVEL;
7591 status = smb_set_file_unix_hlink(conn, req,
7597 case SMB_FILE_RENAME_INFORMATION:
7599 status = smb_file_rename_information(conn, req,
7605 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7607 /* SMB2 rename information. */
7608 status = smb2_file_rename_information(conn, req,
7614 #if defined(HAVE_POSIX_ACLS)
7615 case SMB_SET_POSIX_ACL:
7617 status = smb_set_posix_acl(conn,
7626 case SMB_SET_POSIX_LOCK:
7629 return NT_STATUS_INVALID_LEVEL;
7631 status = smb_set_posix_lock(conn, req,
7632 pdata, total_data, fsp);
7636 case SMB_POSIX_PATH_OPEN:
7639 /* We must have a pathname for this. */
7640 return NT_STATUS_INVALID_LEVEL;
7643 status = smb_posix_open(conn, req,
7651 case SMB_POSIX_PATH_UNLINK:
7654 /* We must have a pathname for this. */
7655 return NT_STATUS_INVALID_LEVEL;
7658 status = smb_posix_unlink(conn, req,
7666 return NT_STATUS_INVALID_LEVEL;
7669 if (!NT_STATUS_IS_OK(status)) {
7673 *ret_data_size = data_return_size;
7674 return NT_STATUS_OK;
7677 /****************************************************************************
7678 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7679 ****************************************************************************/
7681 static void call_trans2setfilepathinfo(connection_struct *conn,
7682 struct smb_request *req,
7683 unsigned int tran_call,
7684 char **pparams, int total_params,
7685 char **ppdata, int total_data,
7686 unsigned int max_data_bytes)
7688 char *params = *pparams;
7689 char *pdata = *ppdata;
7691 struct smb_filename *smb_fname = NULL;
7692 files_struct *fsp = NULL;
7693 NTSTATUS status = NT_STATUS_OK;
7694 int data_return_size = 0;
7697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7701 if (tran_call == TRANSACT2_SETFILEINFO) {
7702 if (total_params < 4) {
7703 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7707 fsp = file_fsp(req, SVAL(params,0));
7708 /* Basic check for non-null fsp. */
7709 if (!check_fsp_open(conn, req, fsp)) {
7712 info_level = SVAL(params,2);
7714 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7716 if (!NT_STATUS_IS_OK(status)) {
7717 reply_nterror(req, status);
7721 if(fsp->is_directory || fsp->fh->fd == -1) {
7723 * This is actually a SETFILEINFO on a directory
7724 * handle (returned from an NT SMB). NT5.0 seems
7725 * to do this call. JRA.
7727 if (INFO_LEVEL_IS_UNIX(info_level)) {
7728 /* Always do lstat for UNIX calls. */
7729 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7730 DEBUG(3,("call_trans2setfilepathinfo: "
7731 "SMB_VFS_LSTAT of %s failed "
7733 smb_fname_str_dbg(smb_fname),
7735 reply_nterror(req, map_nt_error_from_unix(errno));
7739 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7740 DEBUG(3,("call_trans2setfilepathinfo: "
7741 "fileinfo of %s failed (%s)\n",
7742 smb_fname_str_dbg(smb_fname),
7744 reply_nterror(req, map_nt_error_from_unix(errno));
7748 } else if (fsp->print_file) {
7750 * Doing a DELETE_ON_CLOSE should cancel a print job.
7752 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7753 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7755 DEBUG(3,("call_trans2setfilepathinfo: "
7756 "Cancelling print job (%s)\n",
7760 send_trans2_replies(conn, req, params, 2,
7766 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7771 * Original code - this is an open file.
7773 if (!check_fsp(conn, req, fsp)) {
7777 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7778 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7779 "of fnum %d failed (%s)\n", fsp->fnum,
7781 reply_nterror(req, map_nt_error_from_unix(errno));
7789 if (total_params < 7) {
7790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7794 info_level = SVAL(params,0);
7795 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7796 total_params - 6, STR_TERMINATE,
7798 if (!NT_STATUS_IS_OK(status)) {
7799 reply_nterror(req, status);
7803 status = filename_convert(req, conn,
7804 req->flags2 & FLAGS2_DFS_PATHNAMES,
7809 if (!NT_STATUS_IS_OK(status)) {
7810 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7811 reply_botherror(req,
7812 NT_STATUS_PATH_NOT_COVERED,
7813 ERRSRV, ERRbadpath);
7816 reply_nterror(req, status);
7820 if (INFO_LEVEL_IS_UNIX(info_level)) {
7822 * For CIFS UNIX extensions the target name may not exist.
7825 /* Always do lstat for UNIX calls. */
7826 SMB_VFS_LSTAT(conn, smb_fname);
7828 } else if (!VALID_STAT(smb_fname->st) &&
7829 SMB_VFS_STAT(conn, smb_fname)) {
7830 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7832 smb_fname_str_dbg(smb_fname),
7834 reply_nterror(req, map_nt_error_from_unix(errno));
7839 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7840 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7841 fsp ? fsp->fnum : -1, info_level,total_data));
7843 /* Realloc the parameter size */
7844 *pparams = (char *)SMB_REALLOC(*pparams,2);
7845 if (*pparams == NULL) {
7846 reply_nterror(req, NT_STATUS_NO_MEMORY);
7853 status = smbd_do_setfilepathinfo(conn, req, req,
7859 if (!NT_STATUS_IS_OK(status)) {
7860 if (open_was_deferred(req->mid)) {
7861 /* We have re-scheduled this call. */
7864 if (blocking_lock_was_deferred_smb1(req->mid)) {
7865 /* We have re-scheduled this call. */
7868 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7869 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7870 ERRSRV, ERRbadpath);
7873 if (info_level == SMB_POSIX_PATH_OPEN) {
7874 reply_openerror(req, status);
7878 reply_nterror(req, status);
7882 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7888 /****************************************************************************
7889 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7890 ****************************************************************************/
7892 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7893 char **pparams, int total_params,
7894 char **ppdata, int total_data,
7895 unsigned int max_data_bytes)
7897 struct smb_filename *smb_dname = NULL;
7898 char *params = *pparams;
7899 char *pdata = *ppdata;
7900 char *directory = NULL;
7901 NTSTATUS status = NT_STATUS_OK;
7902 struct ea_list *ea_list = NULL;
7903 TALLOC_CTX *ctx = talloc_tos();
7905 if (!CAN_WRITE(conn)) {
7906 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7910 if (total_params < 5) {
7911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7915 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7916 total_params - 4, STR_TERMINATE,
7918 if (!NT_STATUS_IS_OK(status)) {
7919 reply_nterror(req, status);
7923 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7925 status = filename_convert(ctx,
7927 req->flags2 & FLAGS2_DFS_PATHNAMES,
7933 if (!NT_STATUS_IS_OK(status)) {
7934 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7935 reply_botherror(req,
7936 NT_STATUS_PATH_NOT_COVERED,
7937 ERRSRV, ERRbadpath);
7940 reply_nterror(req, status);
7945 * OS/2 workplace shell seems to send SET_EA requests of "null"
7946 * length (4 bytes containing IVAL 4).
7947 * They seem to have no effect. Bug #3212. JRA.
7950 if (total_data && (total_data != 4)) {
7951 /* Any data in this call is an EA list. */
7952 if (total_data < 10) {
7953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7957 if (IVAL(pdata,0) > total_data) {
7958 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7959 IVAL(pdata,0), (unsigned int)total_data));
7960 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7964 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7971 if (!lp_ea_support(SNUM(conn))) {
7972 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7976 /* If total_data == 4 Windows doesn't care what values
7977 * are placed in that field, it just ignores them.
7978 * The System i QNTC IBM SMB client puts bad values here,
7979 * so ignore them. */
7981 status = create_directory(conn, req, smb_dname);
7983 if (!NT_STATUS_IS_OK(status)) {
7984 reply_nterror(req, status);
7988 /* Try and set any given EA. */
7990 status = set_ea(conn, NULL, smb_dname, ea_list);
7991 if (!NT_STATUS_IS_OK(status)) {
7992 reply_nterror(req, status);
7997 /* Realloc the parameter and data sizes */
7998 *pparams = (char *)SMB_REALLOC(*pparams,2);
7999 if(*pparams == NULL) {
8000 reply_nterror(req, NT_STATUS_NO_MEMORY);
8007 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8010 TALLOC_FREE(smb_dname);
8014 /****************************************************************************
8015 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8016 We don't actually do this - we just send a null response.
8017 ****************************************************************************/
8019 static void call_trans2findnotifyfirst(connection_struct *conn,
8020 struct smb_request *req,
8021 char **pparams, int total_params,
8022 char **ppdata, int total_data,
8023 unsigned int max_data_bytes)
8025 char *params = *pparams;
8028 if (total_params < 6) {
8029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8033 info_level = SVAL(params,4);
8034 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8036 switch (info_level) {
8041 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8045 /* Realloc the parameter and data sizes */
8046 *pparams = (char *)SMB_REALLOC(*pparams,6);
8047 if (*pparams == NULL) {
8048 reply_nterror(req, NT_STATUS_NO_MEMORY);
8053 SSVAL(params,0,fnf_handle);
8054 SSVAL(params,2,0); /* No changes */
8055 SSVAL(params,4,0); /* No EA errors */
8062 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8067 /****************************************************************************
8068 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8069 changes). Currently this does nothing.
8070 ****************************************************************************/
8072 static void call_trans2findnotifynext(connection_struct *conn,
8073 struct smb_request *req,
8074 char **pparams, int total_params,
8075 char **ppdata, int total_data,
8076 unsigned int max_data_bytes)
8078 char *params = *pparams;
8080 DEBUG(3,("call_trans2findnotifynext\n"));
8082 /* Realloc the parameter and data sizes */
8083 *pparams = (char *)SMB_REALLOC(*pparams,4);
8084 if (*pparams == NULL) {
8085 reply_nterror(req, NT_STATUS_NO_MEMORY);
8090 SSVAL(params,0,0); /* No changes */
8091 SSVAL(params,2,0); /* No EA errors */
8093 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8098 /****************************************************************************
8099 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8100 ****************************************************************************/
8102 static void call_trans2getdfsreferral(connection_struct *conn,
8103 struct smb_request *req,
8104 char **pparams, int total_params,
8105 char **ppdata, int total_data,
8106 unsigned int max_data_bytes)
8108 char *params = *pparams;
8109 char *pathname = NULL;
8111 int max_referral_level;
8112 NTSTATUS status = NT_STATUS_OK;
8113 TALLOC_CTX *ctx = talloc_tos();
8115 DEBUG(10,("call_trans2getdfsreferral\n"));
8117 if (total_params < 3) {
8118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8122 max_referral_level = SVAL(params,0);
8124 if(!lp_host_msdfs()) {
8125 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8129 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8130 total_params - 2, STR_TERMINATE);
8132 reply_nterror(req, NT_STATUS_NOT_FOUND);
8135 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8136 ppdata,&status)) < 0) {
8137 reply_nterror(req, status);
8141 SSVAL(req->inbuf, smb_flg2,
8142 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8143 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8148 #define LMCAT_SPL 0x53
8149 #define LMFUNC_GETJOBID 0x60
8151 /****************************************************************************
8152 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8153 ****************************************************************************/
8155 static void call_trans2ioctl(connection_struct *conn,
8156 struct smb_request *req,
8157 char **pparams, int total_params,
8158 char **ppdata, int total_data,
8159 unsigned int max_data_bytes)
8161 char *pdata = *ppdata;
8162 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8164 /* check for an invalid fid before proceeding */
8167 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8171 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8172 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8173 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8174 if (*ppdata == NULL) {
8175 reply_nterror(req, NT_STATUS_NO_MEMORY);
8180 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8181 CAN ACCEPT THIS IN UNICODE. JRA. */
8184 if (fsp->print_file) {
8185 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8189 srvstr_push(pdata, req->flags2, pdata + 2,
8190 global_myname(), 15,
8191 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8192 srvstr_push(pdata, req->flags2, pdata+18,
8193 lp_servicename(SNUM(conn)), 13,
8194 STR_ASCII|STR_TERMINATE); /* Service name */
8195 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8200 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8201 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8204 /****************************************************************************
8205 Reply to a SMBfindclose (stop trans2 directory search).
8206 ****************************************************************************/
8208 void reply_findclose(struct smb_request *req)
8211 struct smbd_server_connection *sconn = smbd_server_conn;
8213 START_PROFILE(SMBfindclose);
8216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8217 END_PROFILE(SMBfindclose);
8221 dptr_num = SVALS(req->vwv+0, 0);
8223 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8225 dptr_close(sconn, &dptr_num);
8227 reply_outbuf(req, 0, 0);
8229 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8231 END_PROFILE(SMBfindclose);
8235 /****************************************************************************
8236 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8237 ****************************************************************************/
8239 void reply_findnclose(struct smb_request *req)
8243 START_PROFILE(SMBfindnclose);
8246 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8247 END_PROFILE(SMBfindnclose);
8251 dptr_num = SVAL(req->vwv+0, 0);
8253 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8255 /* We never give out valid handles for a
8256 findnotifyfirst - so any dptr_num is ok here.
8259 reply_outbuf(req, 0, 0);
8261 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8263 END_PROFILE(SMBfindnclose);
8267 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8268 struct trans_state *state)
8270 if (get_Protocol() >= PROTOCOL_NT1) {
8271 req->flags2 |= 0x40; /* IS_LONG_NAME */
8272 SSVAL(req->inbuf,smb_flg2,req->flags2);
8275 if (conn->encrypt_level == Required && !req->encrypted) {
8276 if (state->call != TRANSACT2_QFSINFO &&
8277 state->call != TRANSACT2_SETFSINFO) {
8278 DEBUG(0,("handle_trans2: encryption required "
8280 (unsigned int)state->call));
8281 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8286 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8288 /* Now we must call the relevant TRANS2 function */
8289 switch(state->call) {
8290 case TRANSACT2_OPEN:
8292 START_PROFILE(Trans2_open);
8293 call_trans2open(conn, req,
8294 &state->param, state->total_param,
8295 &state->data, state->total_data,
8296 state->max_data_return);
8297 END_PROFILE(Trans2_open);
8301 case TRANSACT2_FINDFIRST:
8303 START_PROFILE(Trans2_findfirst);
8304 call_trans2findfirst(conn, req,
8305 &state->param, state->total_param,
8306 &state->data, state->total_data,
8307 state->max_data_return);
8308 END_PROFILE(Trans2_findfirst);
8312 case TRANSACT2_FINDNEXT:
8314 START_PROFILE(Trans2_findnext);
8315 call_trans2findnext(conn, req,
8316 &state->param, state->total_param,
8317 &state->data, state->total_data,
8318 state->max_data_return);
8319 END_PROFILE(Trans2_findnext);
8323 case TRANSACT2_QFSINFO:
8325 START_PROFILE(Trans2_qfsinfo);
8326 call_trans2qfsinfo(conn, req,
8327 &state->param, state->total_param,
8328 &state->data, state->total_data,
8329 state->max_data_return);
8330 END_PROFILE(Trans2_qfsinfo);
8334 case TRANSACT2_SETFSINFO:
8336 START_PROFILE(Trans2_setfsinfo);
8337 call_trans2setfsinfo(conn, req,
8338 &state->param, state->total_param,
8339 &state->data, state->total_data,
8340 state->max_data_return);
8341 END_PROFILE(Trans2_setfsinfo);
8345 case TRANSACT2_QPATHINFO:
8346 case TRANSACT2_QFILEINFO:
8348 START_PROFILE(Trans2_qpathinfo);
8349 call_trans2qfilepathinfo(conn, req, state->call,
8350 &state->param, state->total_param,
8351 &state->data, state->total_data,
8352 state->max_data_return);
8353 END_PROFILE(Trans2_qpathinfo);
8357 case TRANSACT2_SETPATHINFO:
8358 case TRANSACT2_SETFILEINFO:
8360 START_PROFILE(Trans2_setpathinfo);
8361 call_trans2setfilepathinfo(conn, req, state->call,
8362 &state->param, state->total_param,
8363 &state->data, state->total_data,
8364 state->max_data_return);
8365 END_PROFILE(Trans2_setpathinfo);
8369 case TRANSACT2_FINDNOTIFYFIRST:
8371 START_PROFILE(Trans2_findnotifyfirst);
8372 call_trans2findnotifyfirst(conn, req,
8373 &state->param, state->total_param,
8374 &state->data, state->total_data,
8375 state->max_data_return);
8376 END_PROFILE(Trans2_findnotifyfirst);
8380 case TRANSACT2_FINDNOTIFYNEXT:
8382 START_PROFILE(Trans2_findnotifynext);
8383 call_trans2findnotifynext(conn, req,
8384 &state->param, state->total_param,
8385 &state->data, state->total_data,
8386 state->max_data_return);
8387 END_PROFILE(Trans2_findnotifynext);
8391 case TRANSACT2_MKDIR:
8393 START_PROFILE(Trans2_mkdir);
8394 call_trans2mkdir(conn, req,
8395 &state->param, state->total_param,
8396 &state->data, state->total_data,
8397 state->max_data_return);
8398 END_PROFILE(Trans2_mkdir);
8402 case TRANSACT2_GET_DFS_REFERRAL:
8404 START_PROFILE(Trans2_get_dfs_referral);
8405 call_trans2getdfsreferral(conn, req,
8406 &state->param, state->total_param,
8407 &state->data, state->total_data,
8408 state->max_data_return);
8409 END_PROFILE(Trans2_get_dfs_referral);
8413 case TRANSACT2_IOCTL:
8415 START_PROFILE(Trans2_ioctl);
8416 call_trans2ioctl(conn, req,
8417 &state->param, state->total_param,
8418 &state->data, state->total_data,
8419 state->max_data_return);
8420 END_PROFILE(Trans2_ioctl);
8425 /* Error in request */
8426 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8427 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8431 /****************************************************************************
8432 Reply to a SMBtrans2.
8433 ****************************************************************************/
8435 void reply_trans2(struct smb_request *req)
8437 connection_struct *conn = req->conn;
8442 unsigned int tran_call;
8443 struct trans_state *state;
8446 START_PROFILE(SMBtrans2);
8448 if (req->wct < 14) {
8449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8450 END_PROFILE(SMBtrans2);
8454 dsoff = SVAL(req->vwv+12, 0);
8455 dscnt = SVAL(req->vwv+11, 0);
8456 psoff = SVAL(req->vwv+10, 0);
8457 pscnt = SVAL(req->vwv+9, 0);
8458 tran_call = SVAL(req->vwv+14, 0);
8460 result = allow_new_trans(conn->pending_trans, req->mid);
8461 if (!NT_STATUS_IS_OK(result)) {
8462 DEBUG(2, ("Got invalid trans2 request: %s\n",
8463 nt_errstr(result)));
8464 reply_nterror(req, result);
8465 END_PROFILE(SMBtrans2);
8470 switch (tran_call) {
8471 /* List the allowed trans2 calls on IPC$ */
8472 case TRANSACT2_OPEN:
8473 case TRANSACT2_GET_DFS_REFERRAL:
8474 case TRANSACT2_QFILEINFO:
8475 case TRANSACT2_QFSINFO:
8476 case TRANSACT2_SETFSINFO:
8479 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8480 END_PROFILE(SMBtrans2);
8485 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8486 DEBUG(0, ("talloc failed\n"));
8487 reply_nterror(req, NT_STATUS_NO_MEMORY);
8488 END_PROFILE(SMBtrans2);
8492 state->cmd = SMBtrans2;
8494 state->mid = req->mid;
8495 state->vuid = req->vuid;
8496 state->setup_count = SVAL(req->vwv+13, 0);
8497 state->setup = NULL;
8498 state->total_param = SVAL(req->vwv+0, 0);
8499 state->param = NULL;
8500 state->total_data = SVAL(req->vwv+1, 0);
8502 state->max_param_return = SVAL(req->vwv+2, 0);
8503 state->max_data_return = SVAL(req->vwv+3, 0);
8504 state->max_setup_return = SVAL(req->vwv+4, 0);
8505 state->close_on_completion = BITSETW(req->vwv+5, 0);
8506 state->one_way = BITSETW(req->vwv+5, 1);
8508 state->call = tran_call;
8510 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8511 is so as a sanity check */
8512 if (state->setup_count != 1) {
8514 * Need to have rc=0 for ioctl to get job id for OS/2.
8515 * Network printing will fail if function is not successful.
8516 * Similar function in reply.c will be used if protocol
8517 * is LANMAN1.0 instead of LM1.2X002.
8518 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8519 * outbuf doesn't have to be set(only job id is used).
8521 if ( (state->setup_count == 4)
8522 && (tran_call == TRANSACT2_IOCTL)
8523 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8524 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8525 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8527 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8528 DEBUG(2,("Transaction is %d\n",tran_call));
8530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8531 END_PROFILE(SMBtrans2);
8536 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8539 if (state->total_data) {
8541 if (trans_oob(state->total_data, 0, dscnt)
8542 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8546 /* Can't use talloc here, the core routines do realloc on the
8547 * params and data. */
8548 state->data = (char *)SMB_MALLOC(state->total_data);
8549 if (state->data == NULL) {
8550 DEBUG(0,("reply_trans2: data malloc fail for %u "
8551 "bytes !\n", (unsigned int)state->total_data));
8553 reply_nterror(req, NT_STATUS_NO_MEMORY);
8554 END_PROFILE(SMBtrans2);
8558 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8561 if (state->total_param) {
8563 if (trans_oob(state->total_param, 0, pscnt)
8564 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8568 /* Can't use talloc here, the core routines do realloc on the
8569 * params and data. */
8570 state->param = (char *)SMB_MALLOC(state->total_param);
8571 if (state->param == NULL) {
8572 DEBUG(0,("reply_trans: param malloc fail for %u "
8573 "bytes !\n", (unsigned int)state->total_param));
8574 SAFE_FREE(state->data);
8576 reply_nterror(req, NT_STATUS_NO_MEMORY);
8577 END_PROFILE(SMBtrans2);
8581 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8584 state->received_data = dscnt;
8585 state->received_param = pscnt;
8587 if ((state->received_param == state->total_param) &&
8588 (state->received_data == state->total_data)) {
8590 handle_trans2(conn, req, state);
8592 SAFE_FREE(state->data);
8593 SAFE_FREE(state->param);
8595 END_PROFILE(SMBtrans2);
8599 DLIST_ADD(conn->pending_trans, state);
8601 /* We need to send an interim response then receive the rest
8602 of the parameter/data bytes */
8603 reply_outbuf(req, 0, 0);
8604 show_msg((char *)req->outbuf);
8605 END_PROFILE(SMBtrans2);
8610 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8611 SAFE_FREE(state->data);
8612 SAFE_FREE(state->param);
8614 END_PROFILE(SMBtrans2);
8615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8619 /****************************************************************************
8620 Reply to a SMBtranss2
8621 ****************************************************************************/
8623 void reply_transs2(struct smb_request *req)
8625 connection_struct *conn = req->conn;
8626 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8627 struct trans_state *state;
8629 START_PROFILE(SMBtranss2);
8631 show_msg((char *)req->inbuf);
8634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8635 END_PROFILE(SMBtranss2);
8639 for (state = conn->pending_trans; state != NULL;
8640 state = state->next) {
8641 if (state->mid == req->mid) {
8646 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8648 END_PROFILE(SMBtranss2);
8652 /* Revise state->total_param and state->total_data in case they have
8653 changed downwards */
8655 if (SVAL(req->vwv+0, 0) < state->total_param)
8656 state->total_param = SVAL(req->vwv+0, 0);
8657 if (SVAL(req->vwv+1, 0) < state->total_data)
8658 state->total_data = SVAL(req->vwv+1, 0);
8660 pcnt = SVAL(req->vwv+2, 0);
8661 poff = SVAL(req->vwv+3, 0);
8662 pdisp = SVAL(req->vwv+4, 0);
8664 dcnt = SVAL(req->vwv+5, 0);
8665 doff = SVAL(req->vwv+6, 0);
8666 ddisp = SVAL(req->vwv+7, 0);
8668 state->received_param += pcnt;
8669 state->received_data += dcnt;
8671 if ((state->received_data > state->total_data) ||
8672 (state->received_param > state->total_param))
8676 if (trans_oob(state->total_param, pdisp, pcnt)
8677 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8680 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8684 if (trans_oob(state->total_data, ddisp, dcnt)
8685 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8688 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8691 if ((state->received_param < state->total_param) ||
8692 (state->received_data < state->total_data)) {
8693 END_PROFILE(SMBtranss2);
8697 handle_trans2(conn, req, state);
8699 DLIST_REMOVE(conn->pending_trans, state);
8700 SAFE_FREE(state->data);
8701 SAFE_FREE(state->param);
8704 END_PROFILE(SMBtranss2);
8709 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8710 DLIST_REMOVE(conn->pending_trans, state);
8711 SAFE_FREE(state->data);
8712 SAFE_FREE(state->param);
8714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8715 END_PROFILE(SMBtranss2);