2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
75 SAMBA_XATTR_DOSTIMESTAMPS,
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))) {
165 * TALLOC the result early to get the talloc hierarchy right.
168 names = TALLOC_ARRAY(mem_ctx, char *, 1);
170 DEBUG(0, ("talloc failed\n"));
171 return NT_STATUS_NO_MEMORY;
174 while (ea_namelist_size <= 65536) {
176 ea_namelist = TALLOC_REALLOC_ARRAY(
177 names, ea_namelist, char, ea_namelist_size);
178 if (ea_namelist == NULL) {
179 DEBUG(0, ("talloc failed\n"));
181 return NT_STATUS_NO_MEMORY;
184 if (fsp && fsp->fh->fd != -1) {
185 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
188 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
192 if ((sizeret == -1) && (errno == ERANGE)) {
193 ea_namelist_size *= 2;
202 return map_nt_error_from_unix(errno);
205 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
206 (unsigned int)sizeret));
216 * Ensure the result is 0-terminated
219 if (ea_namelist[sizeret-1] != '\0') {
221 return NT_STATUS_INTERNAL_ERROR;
229 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
233 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
235 DEBUG(0, ("talloc failed\n"));
237 return NT_STATUS_NO_MEMORY;
243 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
244 names[num_names++] = p;
248 *pnum_names = num_names;
252 /****************************************************************************
253 Return a linked list of the total EA's. Plus the total size
254 ****************************************************************************/
256 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
257 const char *fname, size_t *pea_total_len)
259 /* Get a list of all xattrs. Max namesize is 64k. */
262 struct ea_list *ea_list_head = NULL;
267 if (!lp_ea_support(SNUM(conn))) {
271 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
274 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
278 for (i=0; i<num_names; i++) {
279 struct ea_list *listp;
282 if (strnequal(names[i], "system.", 7)
283 || samba_private_attr_name(names[i]))
286 listp = TALLOC_P(mem_ctx, struct ea_list);
291 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
297 push_ascii_fstring(dos_ea_name, listp->ea.name);
300 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
302 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
303 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
304 (unsigned int)listp->ea.value.length));
306 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
310 /* Add on 4 for total length. */
311 if (*pea_total_len) {
315 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
316 (unsigned int)*pea_total_len));
321 /****************************************************************************
322 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
324 ****************************************************************************/
326 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
327 connection_struct *conn, struct ea_list *ea_list)
329 unsigned int ret_data_size = 4;
332 SMB_ASSERT(total_data_size >= 4);
334 if (!lp_ea_support(SNUM(conn))) {
339 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
342 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
343 dos_namelen = strlen(dos_ea_name);
344 if (dos_namelen > 255 || dos_namelen == 0) {
347 if (ea_list->ea.value.length > 65535) {
350 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
354 /* We know we have room. */
355 SCVAL(p,0,ea_list->ea.flags);
356 SCVAL(p,1,dos_namelen);
357 SSVAL(p,2,ea_list->ea.value.length);
358 fstrcpy(p+4, dos_ea_name);
359 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
361 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
362 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
365 ret_data_size = PTR_DIFF(p, pdata);
366 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
367 SIVAL(pdata,0,ret_data_size);
368 return ret_data_size;
371 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
373 unsigned int total_data_size,
374 unsigned int *ret_data_size,
375 connection_struct *conn,
376 struct ea_list *ea_list)
378 uint8_t *p = (uint8_t *)pdata;
379 uint8_t *last_start = NULL;
383 if (!lp_ea_support(SNUM(conn))) {
384 return NT_STATUS_NO_EAS_ON_FILE;
387 for (; ea_list; ea_list = ea_list->next) {
393 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
397 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
398 dos_namelen = strlen(dos_ea_name);
399 if (dos_namelen > 255 || dos_namelen == 0) {
400 return NT_STATUS_INTERNAL_ERROR;
402 if (ea_list->ea.value.length > 65535) {
403 return NT_STATUS_INTERNAL_ERROR;
406 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
409 size_t pad = 4 - (this_size % 4);
413 if (this_size > total_data_size) {
414 return NT_STATUS_INFO_LENGTH_MISMATCH;
417 /* We know we have room. */
418 SIVAL(p, 0x00, 0); /* next offset */
419 SCVAL(p, 0x04, ea_list->ea.flags);
420 SCVAL(p, 0x05, dos_namelen);
421 SSVAL(p, 0x06, ea_list->ea.value.length);
422 fstrcpy((char *)(p+0x08), dos_ea_name);
423 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
425 total_data_size -= this_size;
429 *ret_data_size = PTR_DIFF(p, pdata);
430 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
434 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
436 size_t total_ea_len = 0;
437 TALLOC_CTX *mem_ctx = NULL;
439 if (!lp_ea_support(SNUM(conn))) {
442 mem_ctx = talloc_tos();
443 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
447 /****************************************************************************
448 Ensure the EA name is case insensitive by matching any existing EA name.
449 ****************************************************************************/
451 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
454 TALLOC_CTX *mem_ctx = talloc_tos();
455 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
457 for (; ea_list; ea_list = ea_list->next) {
458 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
459 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
460 &unix_ea_name[5], ea_list->ea.name));
461 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
467 /****************************************************************************
468 Set or delete an extended attribute.
469 ****************************************************************************/
471 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
472 const struct smb_filename *smb_fname, struct ea_list *ea_list)
476 if (!lp_ea_support(SNUM(conn))) {
477 return NT_STATUS_EAS_NOT_SUPPORTED;
480 /* For now setting EAs on streams isn't supported. */
481 fname = smb_fname->base_name;
483 for (;ea_list; ea_list = ea_list->next) {
485 fstring unix_ea_name;
487 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
488 fstrcat(unix_ea_name, ea_list->ea.name);
490 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
492 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
494 if (samba_private_attr_name(unix_ea_name)) {
495 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
496 return NT_STATUS_ACCESS_DENIED;
499 if (ea_list->ea.value.length == 0) {
500 /* Remove the attribute. */
501 if (fsp && (fsp->fh->fd != -1)) {
502 DEBUG(10,("set_ea: deleting ea name %s on "
503 "file %s by file descriptor.\n",
504 unix_ea_name, fsp_str_dbg(fsp)));
505 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
507 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
508 unix_ea_name, fname));
509 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
512 /* Removing a non existent attribute always succeeds. */
513 if (ret == -1 && errno == ENOATTR) {
514 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
520 if (fsp && (fsp->fh->fd != -1)) {
521 DEBUG(10,("set_ea: setting ea name %s on file "
522 "%s by file descriptor.\n",
523 unix_ea_name, fsp_str_dbg(fsp)));
524 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
525 ea_list->ea.value.data, ea_list->ea.value.length, 0);
527 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
528 unix_ea_name, fname));
529 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
530 ea_list->ea.value.data, ea_list->ea.value.length, 0);
536 if (errno == ENOTSUP) {
537 return NT_STATUS_EAS_NOT_SUPPORTED;
540 return map_nt_error_from_unix(errno);
546 /****************************************************************************
547 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
548 ****************************************************************************/
550 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
552 struct ea_list *ea_list_head = NULL;
553 size_t converted_size, offset = 0;
555 while (offset + 2 < data_size) {
556 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
557 unsigned int namelen = CVAL(pdata,offset);
559 offset++; /* Go past the namelen byte. */
561 /* integer wrap paranioa. */
562 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
563 (offset > data_size) || (namelen > data_size) ||
564 (offset + namelen >= data_size)) {
567 /* Ensure the name is null terminated. */
568 if (pdata[offset + namelen] != '\0') {
571 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
573 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
574 "failed: %s", strerror(errno)));
580 offset += (namelen + 1); /* Go past the name + terminating zero. */
581 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
582 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
588 /****************************************************************************
589 Read one EA list entry from the buffer.
590 ****************************************************************************/
592 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
594 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
596 unsigned int namelen;
597 size_t converted_size;
607 eal->ea.flags = CVAL(pdata,0);
608 namelen = CVAL(pdata,1);
609 val_len = SVAL(pdata,2);
611 if (4 + namelen + 1 + val_len > data_size) {
615 /* Ensure the name is null terminated. */
616 if (pdata[namelen + 4] != '\0') {
619 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
620 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
627 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
628 if (!eal->ea.value.data) {
632 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
634 /* Ensure we're null terminated just in case we print the value. */
635 eal->ea.value.data[val_len] = '\0';
636 /* But don't count the null. */
637 eal->ea.value.length--;
640 *pbytes_used = 4 + namelen + 1 + val_len;
643 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
644 dump_data(10, eal->ea.value.data, eal->ea.value.length);
649 /****************************************************************************
650 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
651 ****************************************************************************/
653 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
655 struct ea_list *ea_list_head = NULL;
657 size_t bytes_used = 0;
659 while (offset < data_size) {
660 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
666 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
667 offset += bytes_used;
673 /****************************************************************************
674 Count the total EA size needed.
675 ****************************************************************************/
677 static size_t ea_list_size(struct ea_list *ealist)
680 struct ea_list *listp;
683 for (listp = ealist; listp; listp = listp->next) {
684 push_ascii_fstring(dos_ea_name, listp->ea.name);
685 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
687 /* Add on 4 for total length. */
695 /****************************************************************************
696 Return a union of EA's from a file list and a list of names.
697 The TALLOC context for the two lists *MUST* be identical as we steal
698 memory from one list to add to another. JRA.
699 ****************************************************************************/
701 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
703 struct ea_list *nlistp, *flistp;
705 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
706 for (flistp = file_list; flistp; flistp = flistp->next) {
707 if (strequal(nlistp->ea.name, flistp->ea.name)) {
713 /* Copy the data from this entry. */
714 nlistp->ea.flags = flistp->ea.flags;
715 nlistp->ea.value = flistp->ea.value;
718 nlistp->ea.flags = 0;
719 ZERO_STRUCT(nlistp->ea.value);
723 *total_ea_len = ea_list_size(name_list);
727 /****************************************************************************
728 Send the required number of replies back.
729 We assume all fields other than the data fields are
730 set correctly for the type of call.
731 HACK ! Always assumes smb_setup field is zero.
732 ****************************************************************************/
734 void send_trans2_replies(connection_struct *conn,
735 struct smb_request *req,
742 /* As we are using a protocol > LANMAN1 then the max_send
743 variable must have been set in the sessetupX call.
744 This takes precedence over the max_xmit field in the
745 global struct. These different max_xmit variables should
746 be merged as this is now too confusing */
748 int data_to_send = datasize;
749 int params_to_send = paramsize;
751 const char *pp = params;
752 const char *pd = pdata;
753 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
754 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
755 int data_alignment_offset = 0;
756 bool overflow = False;
757 struct smbd_server_connection *sconn = smbd_server_conn;
758 int max_send = sconn->smb1.sessions.max_send;
760 /* Modify the data_to_send and datasize and set the error if
761 we're trying to send more than max_data_bytes. We still send
762 the part of the packet(s) that fit. Strange, but needed
765 if (max_data_bytes > 0 && datasize > max_data_bytes) {
766 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
767 max_data_bytes, datasize ));
768 datasize = data_to_send = max_data_bytes;
772 /* If there genuinely are no parameters or data to send just send the empty packet */
774 if(params_to_send == 0 && data_to_send == 0) {
775 reply_outbuf(req, 10, 0);
776 show_msg((char *)req->outbuf);
777 if (!srv_send_smb(smbd_server_fd(),
780 IS_CONN_ENCRYPTED(conn),
782 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
784 TALLOC_FREE(req->outbuf);
788 /* When sending params and data ensure that both are nicely aligned */
789 /* Only do this alignment when there is also data to send - else
790 can cause NT redirector problems. */
792 if (((params_to_send % 4) != 0) && (data_to_send != 0))
793 data_alignment_offset = 4 - (params_to_send % 4);
795 /* Space is bufsize minus Netbios over TCP header minus SMB header */
796 /* The alignment_offset is to align the param bytes on an even byte
797 boundary. NT 4.0 Beta needs this to work correctly. */
799 useable_space = max_send - (smb_size
802 + data_alignment_offset);
804 if (useable_space < 0) {
805 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
806 "= %d!!!", useable_space));
807 exit_server_cleanly("send_trans2_replies: Not enough space");
810 while (params_to_send || data_to_send) {
811 /* Calculate whether we will totally or partially fill this packet */
813 total_sent_thistime = params_to_send + data_to_send;
815 /* We can never send more than useable_space */
817 * Note that 'useable_space' does not include the alignment offsets,
818 * but we must include the alignment offsets in the calculation of
819 * the length of the data we send over the wire, as the alignment offsets
820 * are sent here. Fix from Marc_Jacobsen@hp.com.
823 total_sent_thistime = MIN(total_sent_thistime, useable_space);
825 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
826 + data_alignment_offset);
829 * We might have SMBtrans2s in req which was transferred to
830 * the outbuf, fix that.
832 SCVAL(req->outbuf, smb_com, SMBtrans2);
834 /* Set total params and data to be sent */
835 SSVAL(req->outbuf,smb_tprcnt,paramsize);
836 SSVAL(req->outbuf,smb_tdrcnt,datasize);
838 /* Calculate how many parameters and data we can fit into
839 * this packet. Parameters get precedence
842 params_sent_thistime = MIN(params_to_send,useable_space);
843 data_sent_thistime = useable_space - params_sent_thistime;
844 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
846 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
848 /* smb_proff is the offset from the start of the SMB header to the
849 parameter bytes, however the first 4 bytes of outbuf are
850 the Netbios over TCP header. Thus use smb_base() to subtract
851 them from the calculation */
853 SSVAL(req->outbuf,smb_proff,
854 ((smb_buf(req->outbuf)+alignment_offset)
855 - smb_base(req->outbuf)));
857 if(params_sent_thistime == 0)
858 SSVAL(req->outbuf,smb_prdisp,0);
860 /* Absolute displacement of param bytes sent in this packet */
861 SSVAL(req->outbuf,smb_prdisp,pp - params);
863 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
864 if(data_sent_thistime == 0) {
865 SSVAL(req->outbuf,smb_droff,0);
866 SSVAL(req->outbuf,smb_drdisp, 0);
868 /* The offset of the data bytes is the offset of the
869 parameter bytes plus the number of parameters being sent this time */
870 SSVAL(req->outbuf, smb_droff,
871 ((smb_buf(req->outbuf)+alignment_offset)
872 - smb_base(req->outbuf))
873 + params_sent_thistime + data_alignment_offset);
874 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
877 /* Initialize the padding for alignment */
879 if (alignment_offset != 0) {
880 memset(smb_buf(req->outbuf), 0, alignment_offset);
883 /* Copy the param bytes into the packet */
885 if(params_sent_thistime) {
886 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
887 params_sent_thistime);
890 /* Copy in the data bytes */
891 if(data_sent_thistime) {
892 if (data_alignment_offset != 0) {
893 memset((smb_buf(req->outbuf)+alignment_offset+
894 params_sent_thistime), 0,
895 data_alignment_offset);
897 memcpy(smb_buf(req->outbuf)+alignment_offset
898 +params_sent_thistime+data_alignment_offset,
899 pd,data_sent_thistime);
902 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
903 params_sent_thistime, data_sent_thistime, useable_space));
904 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
905 params_to_send, data_to_send, paramsize, datasize));
908 error_packet_set((char *)req->outbuf,
909 ERRDOS,ERRbufferoverflow,
910 STATUS_BUFFER_OVERFLOW,
914 /* Send the packet */
915 show_msg((char *)req->outbuf);
916 if (!srv_send_smb(smbd_server_fd(),
919 IS_CONN_ENCRYPTED(conn),
921 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
923 TALLOC_FREE(req->outbuf);
925 pp += params_sent_thistime;
926 pd += data_sent_thistime;
928 params_to_send -= params_sent_thistime;
929 data_to_send -= data_sent_thistime;
932 if(params_to_send < 0 || data_to_send < 0) {
933 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
934 params_to_send, data_to_send));
942 /****************************************************************************
943 Reply to a TRANSACT2_OPEN.
944 ****************************************************************************/
946 static void call_trans2open(connection_struct *conn,
947 struct smb_request *req,
948 char **pparams, int total_params,
949 char **ppdata, int total_data,
950 unsigned int max_data_bytes)
952 struct smb_filename *smb_fname = NULL;
953 char *params = *pparams;
954 char *pdata = *ppdata;
959 bool return_additional_info;
972 struct ea_list *ea_list = NULL;
977 uint32 create_disposition;
978 uint32 create_options = 0;
979 TALLOC_CTX *ctx = talloc_tos();
982 * Ensure we have enough parameters to perform the operation.
985 if (total_params < 29) {
986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
990 flags = SVAL(params, 0);
991 deny_mode = SVAL(params, 2);
992 open_attr = SVAL(params,6);
993 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
994 if (oplock_request) {
995 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
999 return_additional_info = BITSETW(params,0);
1000 open_sattr = SVAL(params, 4);
1001 open_time = make_unix_date3(params+8);
1003 open_ofun = SVAL(params,12);
1004 open_size = IVAL(params,14);
1005 pname = ¶ms[28];
1008 reply_doserror(req, ERRSRV, ERRaccess);
1012 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1013 total_params - 28, STR_TERMINATE,
1015 if (!NT_STATUS_IS_OK(status)) {
1016 reply_nterror(req, status);
1020 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1021 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1022 (unsigned int)open_ofun, open_size));
1024 status = filename_convert(ctx,
1026 req->flags2 & FLAGS2_DFS_PATHNAMES,
1031 if (!NT_STATUS_IS_OK(status)) {
1032 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1033 reply_botherror(req,
1034 NT_STATUS_PATH_NOT_COVERED,
1035 ERRSRV, ERRbadpath);
1038 reply_nterror(req, status);
1042 if (open_ofun == 0) {
1043 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1047 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1048 &access_mask, &share_mode,
1049 &create_disposition,
1051 reply_doserror(req, ERRDOS, ERRbadaccess);
1055 /* Any data in this call is an EA list. */
1056 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1057 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1061 if (total_data != 4) {
1062 if (total_data < 10) {
1063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1067 if (IVAL(pdata,0) > total_data) {
1068 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1069 IVAL(pdata,0), (unsigned int)total_data));
1070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1074 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1080 } else if (IVAL(pdata,0) != 4) {
1081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1085 status = SMB_VFS_CREATE_FILE(
1088 0, /* root_dir_fid */
1089 smb_fname, /* fname */
1090 access_mask, /* access_mask */
1091 share_mode, /* share_access */
1092 create_disposition, /* create_disposition*/
1093 create_options, /* create_options */
1094 open_attr, /* file_attributes */
1095 oplock_request, /* oplock_request */
1096 open_size, /* allocation_size */
1098 ea_list, /* ea_list */
1100 &smb_action); /* psbuf */
1102 if (!NT_STATUS_IS_OK(status)) {
1103 if (open_was_deferred(req->mid)) {
1104 /* We have re-scheduled this call. */
1107 reply_openerror(req, status);
1111 size = get_file_size_stat(&smb_fname->st);
1112 fattr = dos_mode(conn, smb_fname);
1113 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1114 inode = smb_fname->st.st_ex_ino;
1116 close_file(req, fsp, ERROR_CLOSE);
1117 reply_doserror(req, ERRDOS,ERRnoaccess);
1121 /* Realloc the size of parameters and data we will return */
1122 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1123 if(*pparams == NULL ) {
1124 reply_nterror(req, NT_STATUS_NO_MEMORY);
1129 SSVAL(params,0,fsp->fnum);
1130 SSVAL(params,2,fattr);
1131 srv_put_dos_date2(params,4, mtime);
1132 SIVAL(params,8, (uint32)size);
1133 SSVAL(params,12,deny_mode);
1134 SSVAL(params,14,0); /* open_type - file or directory. */
1135 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1137 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1138 smb_action |= EXTENDED_OPLOCK_GRANTED;
1141 SSVAL(params,18,smb_action);
1144 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1146 SIVAL(params,20,inode);
1147 SSVAL(params,24,0); /* Padding. */
1149 uint32 ea_size = estimate_ea_size(conn, fsp,
1150 fsp->fsp_name->base_name);
1151 SIVAL(params, 26, ea_size);
1153 SIVAL(params, 26, 0);
1156 /* Send the required number of replies */
1157 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1159 TALLOC_FREE(smb_fname);
1162 /*********************************************************
1163 Routine to check if a given string matches exactly.
1164 as a special case a mask of "." does NOT match. That
1165 is required for correct wildcard semantics
1166 Case can be significant or not.
1167 **********************************************************/
1169 static bool exact_match(bool has_wild,
1170 bool case_sensitive,
1174 if (mask[0] == '.' && mask[1] == 0) {
1182 if (case_sensitive) {
1183 return strcmp(str,mask)==0;
1185 return StrCaseCmp(str,mask) == 0;
1189 /****************************************************************************
1190 Return the filetype for UNIX extensions.
1191 ****************************************************************************/
1193 static uint32 unix_filetype(mode_t mode)
1196 return UNIX_TYPE_FILE;
1197 else if(S_ISDIR(mode))
1198 return UNIX_TYPE_DIR;
1200 else if(S_ISLNK(mode))
1201 return UNIX_TYPE_SYMLINK;
1204 else if(S_ISCHR(mode))
1205 return UNIX_TYPE_CHARDEV;
1208 else if(S_ISBLK(mode))
1209 return UNIX_TYPE_BLKDEV;
1212 else if(S_ISFIFO(mode))
1213 return UNIX_TYPE_FIFO;
1216 else if(S_ISSOCK(mode))
1217 return UNIX_TYPE_SOCKET;
1220 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1221 return UNIX_TYPE_UNKNOWN;
1224 /****************************************************************************
1225 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1226 ****************************************************************************/
1228 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1230 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1231 const SMB_STRUCT_STAT *psbuf,
1233 enum perm_type ptype,
1238 if (perms == SMB_MODE_NO_CHANGE) {
1239 if (!VALID_STAT(*psbuf)) {
1240 return NT_STATUS_INVALID_PARAMETER;
1242 *ret_perms = psbuf->st_ex_mode;
1243 return NT_STATUS_OK;
1247 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1248 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1249 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1250 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1251 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1252 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1253 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1254 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1255 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1257 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1260 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1263 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1268 /* Apply mode mask */
1269 ret &= lp_create_mask(SNUM(conn));
1270 /* Add in force bits */
1271 ret |= lp_force_create_mode(SNUM(conn));
1274 ret &= lp_dir_mask(SNUM(conn));
1275 /* Add in force bits */
1276 ret |= lp_force_dir_mode(SNUM(conn));
1278 case PERM_EXISTING_FILE:
1279 /* Apply mode mask */
1280 ret &= lp_security_mask(SNUM(conn));
1281 /* Add in force bits */
1282 ret |= lp_force_security_mode(SNUM(conn));
1284 case PERM_EXISTING_DIR:
1285 /* Apply mode mask */
1286 ret &= lp_dir_security_mask(SNUM(conn));
1287 /* Add in force bits */
1288 ret |= lp_force_dir_security_mode(SNUM(conn));
1293 return NT_STATUS_OK;
1296 /****************************************************************************
1297 Needed to show the msdfs symlinks as directories. Modifies psbuf
1298 to be a directory if it's a msdfs link.
1299 ****************************************************************************/
1301 static bool check_msdfs_link(connection_struct *conn,
1302 const char *pathname,
1303 SMB_STRUCT_STAT *psbuf)
1305 int saved_errno = errno;
1306 if(lp_host_msdfs() &&
1307 lp_msdfs_root(SNUM(conn)) &&
1308 is_msdfs_link(conn, pathname, psbuf)) {
1310 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1313 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1314 errno = saved_errno;
1317 errno = saved_errno;
1322 /****************************************************************************
1323 Get a level dependent lanman2 dir entry.
1324 ****************************************************************************/
1326 struct smbd_dirptr_lanman2_state {
1327 connection_struct *conn;
1328 uint32_t info_level;
1329 bool check_mangled_names;
1331 bool got_exact_match;
1334 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1340 struct smbd_dirptr_lanman2_state *state =
1341 (struct smbd_dirptr_lanman2_state *)private_data;
1343 char mangled_name[13]; /* mangled 8.3 name. */
1347 /* Mangle fname if it's an illegal name. */
1348 if (mangle_must_mangle(dname, state->conn->params)) {
1349 ok = name_to_8_3(dname, mangled_name,
1350 true, state->conn->params);
1354 fname = mangled_name;
1359 got_match = exact_match(state->has_wild,
1360 state->conn->case_sensitive,
1362 state->got_exact_match = got_match;
1364 got_match = mask_match(fname, mask,
1365 state->conn->case_sensitive);
1368 if(!got_match && state->check_mangled_names &&
1369 !mangle_is_8_3(fname, false, state->conn->params)) {
1371 * It turns out that NT matches wildcards against
1372 * both long *and* short names. This may explain some
1373 * of the wildcard wierdness from old DOS clients
1374 * that some people have been seeing.... JRA.
1376 /* Force the mangling into 8.3. */
1377 ok = name_to_8_3(fname, mangled_name,
1378 false, state->conn->params);
1383 got_match = exact_match(state->has_wild,
1384 state->conn->case_sensitive,
1385 mangled_name, mask);
1386 state->got_exact_match = got_match;
1388 got_match = mask_match(mangled_name, mask,
1389 state->conn->case_sensitive);
1397 *_fname = talloc_strdup(ctx, fname);
1398 if (*_fname == NULL) {
1405 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1407 struct smb_filename *smb_fname,
1410 struct smbd_dirptr_lanman2_state *state =
1411 (struct smbd_dirptr_lanman2_state *)private_data;
1412 bool ms_dfs_link = false;
1415 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1416 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1417 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1418 "Couldn't lstat [%s] (%s)\n",
1419 smb_fname_str_dbg(smb_fname),
1423 } else if (!VALID_STAT(smb_fname->st) &&
1424 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1425 /* Needed to show the msdfs symlinks as
1428 ms_dfs_link = check_msdfs_link(state->conn,
1429 smb_fname->base_name,
1432 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1433 "Couldn't stat [%s] (%s)\n",
1434 smb_fname_str_dbg(smb_fname),
1441 mode = dos_mode_msdfs(state->conn, smb_fname);
1443 mode = dos_mode(state->conn, smb_fname);
1450 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1451 connection_struct *conn,
1453 uint32_t info_level,
1454 struct ea_list *name_list,
1455 bool check_mangled_names,
1456 bool requires_resume_key,
1459 const struct smb_filename *smb_fname,
1460 uint64_t space_remaining,
1465 uint64_t *last_entry_off)
1467 char *p, *q, *pdata = *ppdata;
1469 uint64_t file_size = 0;
1470 uint64_t allocation_size = 0;
1472 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1473 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1474 time_t c_date = (time_t)0;
1476 char *last_entry_ptr;
1478 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1480 *out_of_space = false;
1482 ZERO_STRUCT(mdate_ts);
1483 ZERO_STRUCT(adate_ts);
1484 ZERO_STRUCT(create_date_ts);
1485 ZERO_STRUCT(cdate_ts);
1487 if (!(mode & aDIR)) {
1488 file_size = get_file_size_stat(&smb_fname->st);
1490 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1492 mdate_ts = smb_fname->st.st_ex_mtime;
1493 adate_ts = smb_fname->st.st_ex_atime;
1494 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1495 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1497 if (lp_dos_filetime_resolution(SNUM(conn))) {
1498 dos_filetime_timespec(&create_date_ts);
1499 dos_filetime_timespec(&mdate_ts);
1500 dos_filetime_timespec(&adate_ts);
1501 dos_filetime_timespec(&cdate_ts);
1504 create_date = convert_timespec_to_time_t(create_date_ts);
1505 mdate = convert_timespec_to_time_t(mdate_ts);
1506 adate = convert_timespec_to_time_t(adate_ts);
1507 c_date = convert_timespec_to_time_t(cdate_ts);
1512 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1514 switch (info_level) {
1515 case SMB_FIND_INFO_STANDARD:
1516 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1517 if(requires_resume_key) {
1521 srv_put_dos_date2(p,0,create_date);
1522 srv_put_dos_date2(p,4,adate);
1523 srv_put_dos_date2(p,8,mdate);
1524 SIVAL(p,12,(uint32)file_size);
1525 SIVAL(p,16,(uint32)allocation_size);
1529 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1530 p += ucs2_align(base_data, p, 0);
1532 len = srvstr_push(base_data, flags2, p,
1533 fname, PTR_DIFF(end_data, p),
1535 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1537 SCVAL(nameptr, -1, len - 2);
1539 SCVAL(nameptr, -1, 0);
1543 SCVAL(nameptr, -1, len - 1);
1545 SCVAL(nameptr, -1, 0);
1551 case SMB_FIND_EA_SIZE:
1552 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1553 if (requires_resume_key) {
1557 srv_put_dos_date2(p,0,create_date);
1558 srv_put_dos_date2(p,4,adate);
1559 srv_put_dos_date2(p,8,mdate);
1560 SIVAL(p,12,(uint32)file_size);
1561 SIVAL(p,16,(uint32)allocation_size);
1564 unsigned int ea_size = estimate_ea_size(conn, NULL,
1565 smb_fname->base_name);
1566 SIVAL(p,22,ea_size); /* Extended attributes */
1570 len = srvstr_push(base_data, flags2,
1571 p, fname, PTR_DIFF(end_data, p),
1572 STR_TERMINATE | STR_NOALIGN);
1573 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1586 SCVAL(nameptr,0,len);
1588 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1591 case SMB_FIND_EA_LIST:
1593 struct ea_list *file_list = NULL;
1596 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1600 if (requires_resume_key) {
1604 srv_put_dos_date2(p,0,create_date);
1605 srv_put_dos_date2(p,4,adate);
1606 srv_put_dos_date2(p,8,mdate);
1607 SIVAL(p,12,(uint32)file_size);
1608 SIVAL(p,16,(uint32)allocation_size);
1610 p += 22; /* p now points to the EA area. */
1612 file_list = get_ea_list_from_file(ctx, conn, NULL,
1613 smb_fname->base_name,
1615 name_list = ea_list_union(name_list, file_list, &ea_len);
1617 /* We need to determine if this entry will fit in the space available. */
1618 /* Max string size is 255 bytes. */
1619 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1620 *out_of_space = true;
1621 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1622 return False; /* Not finished - just out of space */
1625 /* Push the ea_data followed by the name. */
1626 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1628 len = srvstr_push(base_data, flags2,
1629 p + 1, fname, PTR_DIFF(end_data, p+1),
1630 STR_TERMINATE | STR_NOALIGN);
1631 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1644 SCVAL(nameptr,0,len);
1646 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1650 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1651 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1652 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1654 SIVAL(p,0,reskey); p += 4;
1655 put_long_date_timespec(p,create_date_ts); p += 8;
1656 put_long_date_timespec(p,adate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 put_long_date_timespec(p,cdate_ts); p += 8;
1659 SOFF_T(p,0,file_size); p += 8;
1660 SOFF_T(p,0,allocation_size); p += 8;
1661 SIVAL(p,0,nt_extmode); p += 4;
1662 q = p; p += 4; /* q is placeholder for name length. */
1664 unsigned int ea_size = estimate_ea_size(conn, NULL,
1665 smb_fname->base_name);
1666 SIVAL(p,0,ea_size); /* Extended attributes */
1669 /* Clear the short name buffer. This is
1670 * IMPORTANT as not doing so will trigger
1671 * a Win2k client bug. JRA.
1673 if (!was_8_3 && check_mangled_names) {
1674 char mangled_name[13]; /* mangled 8.3 name. */
1675 if (!name_to_8_3(fname,mangled_name,True,
1677 /* Error - mangle failed ! */
1678 memset(mangled_name,'\0',12);
1680 mangled_name[12] = 0;
1681 len = srvstr_push(base_data, flags2,
1682 p+2, mangled_name, 24,
1683 STR_UPPER|STR_UNICODE);
1685 memset(p + 2 + len,'\0',24 - len);
1692 len = srvstr_push(base_data, flags2, p,
1693 fname, PTR_DIFF(end_data, p),
1694 STR_TERMINATE_ASCII);
1697 SIVAL(p,0,0); /* Ensure any padding is null. */
1698 len = PTR_DIFF(p, pdata);
1699 len = (len + 3) & ~3;
1704 case SMB_FIND_FILE_DIRECTORY_INFO:
1705 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1707 SIVAL(p,0,reskey); p += 4;
1708 put_long_date_timespec(p,create_date_ts); p += 8;
1709 put_long_date_timespec(p,adate_ts); p += 8;
1710 put_long_date_timespec(p,mdate_ts); p += 8;
1711 put_long_date_timespec(p,cdate_ts); p += 8;
1712 SOFF_T(p,0,file_size); p += 8;
1713 SOFF_T(p,0,allocation_size); p += 8;
1714 SIVAL(p,0,nt_extmode); p += 4;
1715 len = srvstr_push(base_data, flags2,
1716 p + 4, fname, PTR_DIFF(end_data, p+4),
1717 STR_TERMINATE_ASCII);
1720 SIVAL(p,0,0); /* Ensure any padding is null. */
1721 len = PTR_DIFF(p, pdata);
1722 len = (len + 3) & ~3;
1727 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1728 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1730 SIVAL(p,0,reskey); p += 4;
1731 put_long_date_timespec(p,create_date_ts); p += 8;
1732 put_long_date_timespec(p,adate_ts); p += 8;
1733 put_long_date_timespec(p,mdate_ts); p += 8;
1734 put_long_date_timespec(p,cdate_ts); p += 8;
1735 SOFF_T(p,0,file_size); p += 8;
1736 SOFF_T(p,0,allocation_size); p += 8;
1737 SIVAL(p,0,nt_extmode); p += 4;
1738 q = p; p += 4; /* q is placeholder for name length. */
1740 unsigned int ea_size = estimate_ea_size(conn, NULL,
1741 smb_fname->base_name);
1742 SIVAL(p,0,ea_size); /* Extended attributes */
1745 len = srvstr_push(base_data, flags2, p,
1746 fname, PTR_DIFF(end_data, p),
1747 STR_TERMINATE_ASCII);
1751 SIVAL(p,0,0); /* Ensure any padding is null. */
1752 len = PTR_DIFF(p, pdata);
1753 len = (len + 3) & ~3;
1758 case SMB_FIND_FILE_NAMES_INFO:
1759 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1761 SIVAL(p,0,reskey); p += 4;
1763 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1764 acl on a dir (tridge) */
1765 len = srvstr_push(base_data, flags2, p,
1766 fname, PTR_DIFF(end_data, p),
1767 STR_TERMINATE_ASCII);
1770 SIVAL(p,0,0); /* Ensure any padding is null. */
1771 len = PTR_DIFF(p, pdata);
1772 len = (len + 3) & ~3;
1777 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1778 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1780 SIVAL(p,0,reskey); p += 4;
1781 put_long_date_timespec(p,create_date_ts); p += 8;
1782 put_long_date_timespec(p,adate_ts); p += 8;
1783 put_long_date_timespec(p,mdate_ts); p += 8;
1784 put_long_date_timespec(p,cdate_ts); p += 8;
1785 SOFF_T(p,0,file_size); p += 8;
1786 SOFF_T(p,0,allocation_size); p += 8;
1787 SIVAL(p,0,nt_extmode); p += 4;
1788 q = p; p += 4; /* q is placeholder for name length. */
1790 unsigned int ea_size = estimate_ea_size(conn, NULL,
1791 smb_fname->base_name);
1792 SIVAL(p,0,ea_size); /* Extended attributes */
1795 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1796 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1797 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1798 len = srvstr_push(base_data, flags2, p,
1799 fname, PTR_DIFF(end_data, p),
1800 STR_TERMINATE_ASCII);
1803 SIVAL(p,0,0); /* Ensure any padding is null. */
1804 len = PTR_DIFF(p, pdata);
1805 len = (len + 3) & ~3;
1810 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1811 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1812 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1814 SIVAL(p,0,reskey); p += 4;
1815 put_long_date_timespec(p,create_date_ts); p += 8;
1816 put_long_date_timespec(p,adate_ts); p += 8;
1817 put_long_date_timespec(p,mdate_ts); p += 8;
1818 put_long_date_timespec(p,cdate_ts); p += 8;
1819 SOFF_T(p,0,file_size); p += 8;
1820 SOFF_T(p,0,allocation_size); p += 8;
1821 SIVAL(p,0,nt_extmode); p += 4;
1822 q = p; p += 4; /* q is placeholder for name length */
1824 unsigned int ea_size = estimate_ea_size(conn, NULL,
1825 smb_fname->base_name);
1826 SIVAL(p,0,ea_size); /* Extended attributes */
1829 /* Clear the short name buffer. This is
1830 * IMPORTANT as not doing so will trigger
1831 * a Win2k client bug. JRA.
1833 if (!was_8_3 && check_mangled_names) {
1834 char mangled_name[13]; /* mangled 8.3 name. */
1835 if (!name_to_8_3(fname,mangled_name,True,
1837 /* Error - mangle failed ! */
1838 memset(mangled_name,'\0',12);
1840 mangled_name[12] = 0;
1841 len = srvstr_push(base_data, flags2,
1842 p+2, mangled_name, 24,
1843 STR_UPPER|STR_UNICODE);
1846 memset(p + 2 + len,'\0',24 - len);
1853 SSVAL(p,0,0); p += 2; /* Reserved ? */
1854 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1855 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1856 len = srvstr_push(base_data, flags2, p,
1857 fname, PTR_DIFF(end_data, p),
1858 STR_TERMINATE_ASCII);
1861 SIVAL(p,0,0); /* Ensure any padding is null. */
1862 len = PTR_DIFF(p, pdata);
1863 len = (len + 3) & ~3;
1868 /* CIFS UNIX Extension. */
1870 case SMB_FIND_FILE_UNIX:
1871 case SMB_FIND_FILE_UNIX_INFO2:
1873 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1875 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1877 if (info_level == SMB_FIND_FILE_UNIX) {
1878 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1879 p = store_file_unix_basic(conn, p,
1880 NULL, &smb_fname->st);
1881 len = srvstr_push(base_data, flags2, p,
1882 fname, PTR_DIFF(end_data, p),
1885 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1886 p = store_file_unix_basic_info2(conn, p,
1887 NULL, &smb_fname->st);
1890 len = srvstr_push(base_data, flags2, p, fname,
1891 PTR_DIFF(end_data, p), 0);
1892 SIVAL(nameptr, 0, len);
1896 SIVAL(p,0,0); /* Ensure any padding is null. */
1898 len = PTR_DIFF(p, pdata);
1899 len = (len + 3) & ~3;
1900 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1902 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1910 if (PTR_DIFF(p,pdata) > space_remaining) {
1911 *out_of_space = true;
1912 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1913 return false; /* Not finished - just out of space */
1916 /* Setup the last entry pointer, as an offset from base_data */
1917 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1918 /* Advance the data pointer to the next slot */
1924 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1925 connection_struct *conn,
1926 struct dptr_struct *dirptr,
1928 const char *path_mask,
1931 int requires_resume_key,
1937 int space_remaining,
1939 bool *got_exact_match,
1940 int *_last_entry_off,
1941 struct ea_list *name_list)
1944 const char *mask = NULL;
1945 long prev_dirpos = 0;
1948 struct smb_filename *smb_fname = NULL;
1949 struct smbd_dirptr_lanman2_state state;
1951 uint64_t last_entry_off = 0;
1955 state.info_level = info_level;
1956 state.check_mangled_names = lp_manglednames(conn->params);
1957 state.has_wild = dptr_has_wild(dirptr);
1958 state.got_exact_match = false;
1960 *out_of_space = false;
1961 *got_exact_match = false;
1963 p = strrchr_m(path_mask,'/');
1974 ok = smbd_dirptr_get_entry(ctx,
1980 smbd_dirptr_lanman2_match_fn,
1981 smbd_dirptr_lanman2_mode_fn,
1991 *got_exact_match = state.got_exact_match;
1993 ok = smbd_marshall_dir_entry(ctx,
1998 state.check_mangled_names,
1999 requires_resume_key,
2010 TALLOC_FREE(smb_fname);
2011 if (*out_of_space) {
2012 dptr_SeekDir(dirptr, prev_dirpos);
2019 *_last_entry_off = last_entry_off;
2023 /****************************************************************************
2024 Reply to a TRANS2_FINDFIRST.
2025 ****************************************************************************/
2027 static void call_trans2findfirst(connection_struct *conn,
2028 struct smb_request *req,
2029 char **pparams, int total_params,
2030 char **ppdata, int total_data,
2031 unsigned int max_data_bytes)
2033 /* We must be careful here that we don't return more than the
2034 allowed number of data bytes. If this means returning fewer than
2035 maxentries then so be it. We assume that the redirector has
2036 enough room for the fixed number of parameter bytes it has
2038 struct smb_filename *smb_dname = NULL;
2039 char *params = *pparams;
2040 char *pdata = *ppdata;
2044 uint16 findfirst_flags;
2045 bool close_after_first;
2047 bool requires_resume_key;
2049 char *directory = NULL;
2052 int last_entry_off=0;
2056 bool finished = False;
2057 bool dont_descend = False;
2058 bool out_of_space = False;
2059 int space_remaining;
2060 bool mask_contains_wcard = False;
2061 struct ea_list *ea_list = NULL;
2062 NTSTATUS ntstatus = NT_STATUS_OK;
2063 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2064 TALLOC_CTX *ctx = talloc_tos();
2065 struct dptr_struct *dirptr = NULL;
2066 struct smbd_server_connection *sconn = smbd_server_conn;
2068 if (total_params < 13) {
2069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2073 dirtype = SVAL(params,0);
2074 maxentries = SVAL(params,2);
2075 findfirst_flags = SVAL(params,4);
2076 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2077 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2078 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2079 info_level = SVAL(params,6);
2081 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2082 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2083 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2084 info_level, max_data_bytes));
2087 /* W2K3 seems to treat zero as 1. */
2091 switch (info_level) {
2092 case SMB_FIND_INFO_STANDARD:
2093 case SMB_FIND_EA_SIZE:
2094 case SMB_FIND_EA_LIST:
2095 case SMB_FIND_FILE_DIRECTORY_INFO:
2096 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2097 case SMB_FIND_FILE_NAMES_INFO:
2098 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2099 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2100 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2102 case SMB_FIND_FILE_UNIX:
2103 case SMB_FIND_FILE_UNIX_INFO2:
2104 /* Always use filesystem for UNIX mtime query. */
2105 ask_sharemode = false;
2106 if (!lp_unix_extensions()) {
2107 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2112 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2116 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2117 params+12, total_params - 12,
2118 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2119 if (!NT_STATUS_IS_OK(ntstatus)) {
2120 reply_nterror(req, ntstatus);
2124 ntstatus = filename_convert(ctx, conn,
2125 req->flags2 & FLAGS2_DFS_PATHNAMES,
2128 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2129 &mask_contains_wcard,
2131 if (!NT_STATUS_IS_OK(ntstatus)) {
2132 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2133 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2134 ERRSRV, ERRbadpath);
2137 reply_nterror(req, ntstatus);
2141 mask = smb_dname->original_lcomp;
2143 directory = smb_dname->base_name;
2145 p = strrchr_m(directory,'/');
2147 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2148 if((directory[0] == '.') && (directory[1] == '\0')) {
2149 mask = talloc_strdup(ctx,"*");
2151 reply_nterror(req, NT_STATUS_NO_MEMORY);
2154 mask_contains_wcard = True;
2156 directory = talloc_strdup(talloc_tos(), "./");
2158 reply_nterror(req, NT_STATUS_NO_MEMORY);
2165 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2167 if (info_level == SMB_FIND_EA_LIST) {
2170 if (total_data < 4) {
2171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2175 ea_size = IVAL(pdata,0);
2176 if (ea_size != total_data) {
2177 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2178 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2183 if (!lp_ea_support(SNUM(conn))) {
2184 reply_doserror(req, ERRDOS, ERReasnotsupported);
2188 /* Pull out the list of names. */
2189 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2196 *ppdata = (char *)SMB_REALLOC(
2197 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2198 if(*ppdata == NULL ) {
2199 reply_nterror(req, NT_STATUS_NO_MEMORY);
2203 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2205 /* Realloc the params space */
2206 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2207 if (*pparams == NULL) {
2208 reply_nterror(req, NT_STATUS_NO_MEMORY);
2213 /* Save the wildcard match and attribs we are using on this directory -
2214 needed as lanman2 assumes these are being saved between calls */
2216 ntstatus = dptr_create(conn,
2222 mask_contains_wcard,
2226 if (!NT_STATUS_IS_OK(ntstatus)) {
2227 reply_nterror(req, ntstatus);
2231 dptr_num = dptr_dnum(dirptr);
2232 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2234 /* Initialize per TRANS2_FIND_FIRST operation data */
2235 dptr_init_search_op(dirptr);
2237 /* We don't need to check for VOL here as this is returned by
2238 a different TRANS2 call. */
2240 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2241 directory,lp_dontdescend(SNUM(conn))));
2242 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2243 dont_descend = True;
2246 space_remaining = max_data_bytes;
2247 out_of_space = False;
2249 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2250 bool got_exact_match = False;
2252 /* this is a heuristic to avoid seeking the dirptr except when
2253 absolutely necessary. It allows for a filename of about 40 chars */
2254 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2255 out_of_space = True;
2258 finished = !get_lanman2_dir_entry(ctx,
2262 mask,dirtype,info_level,
2263 requires_resume_key,dont_descend,
2266 space_remaining, &out_of_space,
2268 &last_entry_off, ea_list);
2271 if (finished && out_of_space)
2274 if (!finished && !out_of_space)
2278 * As an optimisation if we know we aren't looking
2279 * for a wildcard name (ie. the name matches the wildcard exactly)
2280 * then we can finish on any (first) match.
2281 * This speeds up large directory searches. JRA.
2287 /* Ensure space_remaining never goes -ve. */
2288 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2289 space_remaining = 0;
2290 out_of_space = true;
2292 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2296 /* Check if we can close the dirptr */
2297 if(close_after_first || (finished && close_if_end)) {
2298 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2299 dptr_close(sconn, &dptr_num);
2303 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2304 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2305 * the protocol level is less than NT1. Tested with smbclient. JRA.
2306 * This should fix the OS/2 client bug #2335.
2309 if(numentries == 0) {
2310 dptr_close(sconn, &dptr_num);
2311 if (Protocol < PROTOCOL_NT1) {
2312 reply_doserror(req, ERRDOS, ERRnofiles);
2315 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2316 ERRDOS, ERRbadfile);
2321 /* At this point pdata points to numentries directory entries. */
2323 /* Set up the return parameter block */
2324 SSVAL(params,0,dptr_num);
2325 SSVAL(params,2,numentries);
2326 SSVAL(params,4,finished);
2327 SSVAL(params,6,0); /* Never an EA error */
2328 SSVAL(params,8,last_entry_off);
2330 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2333 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2334 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2336 reply_nterror(req, NT_STATUS_NO_MEMORY);
2340 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2341 smb_fn_name(req->cmd),
2342 mask, directory, dirtype, numentries ) );
2345 * Force a name mangle here to ensure that the
2346 * mask as an 8.3 name is top of the mangled cache.
2347 * The reasons for this are subtle. Don't remove
2348 * this code unless you know what you are doing
2349 * (see PR#13758). JRA.
2352 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2353 char mangled_name[13];
2354 name_to_8_3(mask, mangled_name, True, conn->params);
2357 TALLOC_FREE(smb_dname);
2361 /****************************************************************************
2362 Reply to a TRANS2_FINDNEXT.
2363 ****************************************************************************/
2365 static void call_trans2findnext(connection_struct *conn,
2366 struct smb_request *req,
2367 char **pparams, int total_params,
2368 char **ppdata, int total_data,
2369 unsigned int max_data_bytes)
2371 /* We must be careful here that we don't return more than the
2372 allowed number of data bytes. If this means returning fewer than
2373 maxentries then so be it. We assume that the redirector has
2374 enough room for the fixed number of parameter bytes it has
2376 char *params = *pparams;
2377 char *pdata = *ppdata;
2383 uint16 findnext_flags;
2384 bool close_after_request;
2386 bool requires_resume_key;
2388 bool mask_contains_wcard = False;
2389 char *resume_name = NULL;
2390 const char *mask = NULL;
2391 const char *directory = NULL;
2395 int i, last_entry_off=0;
2396 bool finished = False;
2397 bool dont_descend = False;
2398 bool out_of_space = False;
2399 int space_remaining;
2400 struct ea_list *ea_list = NULL;
2401 NTSTATUS ntstatus = NT_STATUS_OK;
2402 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2403 TALLOC_CTX *ctx = talloc_tos();
2404 struct dptr_struct *dirptr;
2405 struct smbd_server_connection *sconn = smbd_server_conn;
2407 if (total_params < 13) {
2408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2412 dptr_num = SVAL(params,0);
2413 maxentries = SVAL(params,2);
2414 info_level = SVAL(params,4);
2415 resume_key = IVAL(params,6);
2416 findnext_flags = SVAL(params,10);
2417 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2418 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2419 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2420 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2422 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2424 total_params - 12, STR_TERMINATE, &ntstatus,
2425 &mask_contains_wcard);
2426 if (!NT_STATUS_IS_OK(ntstatus)) {
2427 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2428 complain (it thinks we're asking for the directory above the shared
2429 path or an invalid name). Catch this as the resume name is only compared, never used in
2430 a file access. JRA. */
2431 srvstr_pull_talloc(ctx, params, req->flags2,
2432 &resume_name, params+12,
2436 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2437 reply_nterror(req, ntstatus);
2442 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2443 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2444 resume_key = %d resume name = %s continue=%d level = %d\n",
2445 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2446 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2449 /* W2K3 seems to treat zero as 1. */
2453 switch (info_level) {
2454 case SMB_FIND_INFO_STANDARD:
2455 case SMB_FIND_EA_SIZE:
2456 case SMB_FIND_EA_LIST:
2457 case SMB_FIND_FILE_DIRECTORY_INFO:
2458 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2459 case SMB_FIND_FILE_NAMES_INFO:
2460 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2461 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2462 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2464 case SMB_FIND_FILE_UNIX:
2465 case SMB_FIND_FILE_UNIX_INFO2:
2466 /* Always use filesystem for UNIX mtime query. */
2467 ask_sharemode = false;
2468 if (!lp_unix_extensions()) {
2469 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2474 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2478 if (info_level == SMB_FIND_EA_LIST) {
2481 if (total_data < 4) {
2482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2486 ea_size = IVAL(pdata,0);
2487 if (ea_size != total_data) {
2488 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2489 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2494 if (!lp_ea_support(SNUM(conn))) {
2495 reply_doserror(req, ERRDOS, ERReasnotsupported);
2499 /* Pull out the list of names. */
2500 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2507 *ppdata = (char *)SMB_REALLOC(
2508 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2509 if(*ppdata == NULL) {
2510 reply_nterror(req, NT_STATUS_NO_MEMORY);
2515 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2517 /* Realloc the params space */
2518 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2519 if(*pparams == NULL ) {
2520 reply_nterror(req, NT_STATUS_NO_MEMORY);
2526 /* Check that the dptr is valid */
2527 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2528 reply_doserror(req, ERRDOS, ERRnofiles);
2532 directory = dptr_path(sconn, dptr_num);
2534 /* Get the wildcard mask from the dptr */
2535 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2536 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2537 reply_doserror(req, ERRDOS, ERRnofiles);
2543 /* Get the attr mask from the dptr */
2544 dirtype = dptr_attr(sconn, dptr_num);
2546 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2547 dptr_num, mask, dirtype,
2549 dptr_TellDir(dirptr)));
2551 /* Initialize per TRANS2_FIND_NEXT operation data */
2552 dptr_init_search_op(dirptr);
2554 /* We don't need to check for VOL here as this is returned by
2555 a different TRANS2 call. */
2557 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2558 directory,lp_dontdescend(SNUM(conn))));
2559 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2560 dont_descend = True;
2563 space_remaining = max_data_bytes;
2564 out_of_space = False;
2567 * Seek to the correct position. We no longer use the resume key but
2568 * depend on the last file name instead.
2571 if(*resume_name && !continue_bit) {
2574 long current_pos = 0;
2576 * Remember, name_to_8_3 is called by
2577 * get_lanman2_dir_entry(), so the resume name
2578 * could be mangled. Ensure we check the unmangled name.
2581 if (mangle_is_mangled(resume_name, conn->params)) {
2582 char *new_resume_name = NULL;
2583 mangle_lookup_name_from_8_3(ctx,
2587 if (new_resume_name) {
2588 resume_name = new_resume_name;
2593 * Fix for NT redirector problem triggered by resume key indexes
2594 * changing between directory scans. We now return a resume key of 0
2595 * and instead look for the filename to continue from (also given
2596 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2597 * findfirst/findnext (as is usual) then the directory pointer
2598 * should already be at the correct place.
2601 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2602 } /* end if resume_name && !continue_bit */
2604 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2605 bool got_exact_match = False;
2607 /* this is a heuristic to avoid seeking the dirptr except when
2608 absolutely necessary. It allows for a filename of about 40 chars */
2609 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2610 out_of_space = True;
2613 finished = !get_lanman2_dir_entry(ctx,
2617 mask,dirtype,info_level,
2618 requires_resume_key,dont_descend,
2621 space_remaining, &out_of_space,
2623 &last_entry_off, ea_list);
2626 if (finished && out_of_space)
2629 if (!finished && !out_of_space)
2633 * As an optimisation if we know we aren't looking
2634 * for a wildcard name (ie. the name matches the wildcard exactly)
2635 * then we can finish on any (first) match.
2636 * This speeds up large directory searches. JRA.
2642 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2645 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2646 smb_fn_name(req->cmd),
2647 mask, directory, dirtype, numentries ) );
2649 /* Check if we can close the dirptr */
2650 if(close_after_request || (finished && close_if_end)) {
2651 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2652 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2655 /* Set up the return parameter block */
2656 SSVAL(params,0,numentries);
2657 SSVAL(params,2,finished);
2658 SSVAL(params,4,0); /* Never an EA error */
2659 SSVAL(params,6,last_entry_off);
2661 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2667 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2669 E_md4hash(lp_servicename(SNUM(conn)),objid);
2673 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2675 SMB_ASSERT(extended_info != NULL);
2677 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2678 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2679 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2680 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2681 #ifdef SAMBA_VERSION_REVISION
2682 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2684 extended_info->samba_subversion = 0;
2685 #ifdef SAMBA_VERSION_RC_RELEASE
2686 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2688 #ifdef SAMBA_VERSION_PRE_RELEASE
2689 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2692 #ifdef SAMBA_VERSION_VENDOR_PATCH
2693 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2695 extended_info->samba_gitcommitdate = 0;
2696 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2697 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2700 memset(extended_info->samba_version_string, 0,
2701 sizeof(extended_info->samba_version_string));
2703 snprintf (extended_info->samba_version_string,
2704 sizeof(extended_info->samba_version_string),
2705 "%s", samba_version_string());
2708 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2709 TALLOC_CTX *mem_ctx,
2710 uint16_t info_level,
2712 unsigned int max_data_bytes,
2716 char *pdata, *end_data;
2717 int data_len = 0, len;
2718 const char *vname = volume_label(SNUM(conn));
2719 int snum = SNUM(conn);
2720 char *fstype = lp_fstype(SNUM(conn));
2721 uint32 additional_flags = 0;
2722 struct smb_filename *smb_fname_dot = NULL;
2727 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2728 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2729 "info level (0x%x) on IPC$.\n",
2730 (unsigned int)info_level));
2731 return NT_STATUS_ACCESS_DENIED;
2735 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2737 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2739 if (!NT_STATUS_IS_OK(status)) {
2743 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2744 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2745 TALLOC_FREE(smb_fname_dot);
2746 return map_nt_error_from_unix(errno);
2749 st = smb_fname_dot->st;
2750 TALLOC_FREE(smb_fname_dot);
2752 *ppdata = (char *)SMB_REALLOC(
2753 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2754 if (*ppdata == NULL) {
2755 return NT_STATUS_NO_MEMORY;
2759 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2760 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2762 switch (info_level) {
2763 case SMB_INFO_ALLOCATION:
2765 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2767 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2768 return map_nt_error_from_unix(errno);
2771 block_size = lp_block_size(snum);
2772 if (bsize < block_size) {
2773 uint64_t factor = block_size/bsize;
2778 if (bsize > block_size) {
2779 uint64_t factor = bsize/block_size;
2784 bytes_per_sector = 512;
2785 sectors_per_unit = bsize/bytes_per_sector;
2787 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2788 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2789 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2791 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2792 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2793 SIVAL(pdata,l1_cUnit,dsize);
2794 SIVAL(pdata,l1_cUnitAvail,dfree);
2795 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2799 case SMB_INFO_VOLUME:
2800 /* Return volume name */
2802 * Add volume serial number - hash of a combination of
2803 * the called hostname and the service name.
2805 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2807 * Win2k3 and previous mess this up by sending a name length
2808 * one byte short. I believe only older clients (OS/2 Win9x) use
2809 * this call so try fixing this by adding a terminating null to
2810 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2814 pdata+l2_vol_szVolLabel, vname,
2815 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2816 STR_NOALIGN|STR_TERMINATE);
2817 SCVAL(pdata,l2_vol_cch,len);
2818 data_len = l2_vol_szVolLabel + len;
2819 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2820 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2824 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2825 case SMB_FS_ATTRIBUTE_INFORMATION:
2827 additional_flags = 0;
2828 #if defined(HAVE_SYS_QUOTAS)
2829 additional_flags |= FILE_VOLUME_QUOTAS;
2832 if(lp_nt_acl_support(SNUM(conn))) {
2833 additional_flags |= FILE_PERSISTENT_ACLS;
2836 /* Capabilities are filled in at connection time through STATVFS call */
2837 additional_flags |= conn->fs_capabilities;
2839 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2840 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2841 additional_flags); /* FS ATTRIBUTES */
2843 SIVAL(pdata,4,255); /* Max filename component length */
2844 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2845 and will think we can't do long filenames */
2846 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2847 PTR_DIFF(end_data, pdata+12),
2850 data_len = 12 + len;
2853 case SMB_QUERY_FS_LABEL_INFO:
2854 case SMB_FS_LABEL_INFORMATION:
2855 len = srvstr_push(pdata, flags2, pdata+4, vname,
2856 PTR_DIFF(end_data, pdata+4), 0);
2861 case SMB_QUERY_FS_VOLUME_INFO:
2862 case SMB_FS_VOLUME_INFORMATION:
2865 * Add volume serial number - hash of a combination of
2866 * the called hostname and the service name.
2868 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2869 (str_checksum(get_local_machine_name())<<16));
2871 /* Max label len is 32 characters. */
2872 len = srvstr_push(pdata, flags2, pdata+18, vname,
2873 PTR_DIFF(end_data, pdata+18),
2875 SIVAL(pdata,12,len);
2878 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2879 (int)strlen(vname),vname, lp_servicename(snum)));
2882 case SMB_QUERY_FS_SIZE_INFO:
2883 case SMB_FS_SIZE_INFORMATION:
2885 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2887 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2888 return map_nt_error_from_unix(errno);
2890 block_size = lp_block_size(snum);
2891 if (bsize < block_size) {
2892 uint64_t factor = block_size/bsize;
2897 if (bsize > block_size) {
2898 uint64_t factor = bsize/block_size;
2903 bytes_per_sector = 512;
2904 sectors_per_unit = bsize/bytes_per_sector;
2905 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2906 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2907 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2908 SBIG_UINT(pdata,0,dsize);
2909 SBIG_UINT(pdata,8,dfree);
2910 SIVAL(pdata,16,sectors_per_unit);
2911 SIVAL(pdata,20,bytes_per_sector);
2915 case SMB_FS_FULL_SIZE_INFORMATION:
2917 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2919 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2920 return map_nt_error_from_unix(errno);
2922 block_size = lp_block_size(snum);
2923 if (bsize < block_size) {
2924 uint64_t factor = block_size/bsize;
2929 if (bsize > block_size) {
2930 uint64_t factor = bsize/block_size;
2935 bytes_per_sector = 512;
2936 sectors_per_unit = bsize/bytes_per_sector;
2937 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2938 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2939 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2940 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2941 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2942 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2943 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2944 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2948 case SMB_QUERY_FS_DEVICE_INFO:
2949 case SMB_FS_DEVICE_INFORMATION:
2951 SIVAL(pdata,0,0); /* dev type */
2952 SIVAL(pdata,4,0); /* characteristics */
2955 #ifdef HAVE_SYS_QUOTAS
2956 case SMB_FS_QUOTA_INFORMATION:
2958 * what we have to send --metze:
2960 * Unknown1: 24 NULL bytes
2961 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2962 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2963 * Quota Flags: 2 byte :
2964 * Unknown3: 6 NULL bytes
2968 * details for Quota Flags:
2970 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2971 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2972 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2973 * 0x0001 Enable Quotas: enable quota for this fs
2977 /* we need to fake up a fsp here,
2978 * because its not send in this call
2981 SMB_NTQUOTA_STRUCT quotas;
2984 ZERO_STRUCT(quotas);
2990 if (conn->server_info->utok.uid != sec_initial_uid()) {
2991 DEBUG(0,("set_user_quota: access_denied "
2992 "service [%s] user [%s]\n",
2993 lp_servicename(SNUM(conn)),
2994 conn->server_info->unix_name));
2995 return NT_STATUS_ACCESS_DENIED;
2998 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2999 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3000 return map_nt_error_from_unix(errno);
3005 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3006 lp_servicename(SNUM(conn))));
3008 /* Unknown1 24 NULL bytes*/
3009 SBIG_UINT(pdata,0,(uint64_t)0);
3010 SBIG_UINT(pdata,8,(uint64_t)0);
3011 SBIG_UINT(pdata,16,(uint64_t)0);
3013 /* Default Soft Quota 8 bytes */
3014 SBIG_UINT(pdata,24,quotas.softlim);
3016 /* Default Hard Quota 8 bytes */
3017 SBIG_UINT(pdata,32,quotas.hardlim);
3019 /* Quota flag 2 bytes */
3020 SSVAL(pdata,40,quotas.qflags);
3022 /* Unknown3 6 NULL bytes */
3028 #endif /* HAVE_SYS_QUOTAS */
3029 case SMB_FS_OBJECTID_INFORMATION:
3031 unsigned char objid[16];
3032 struct smb_extended_info extended_info;
3033 memcpy(pdata,create_volume_objectid(conn, objid),16);
3034 samba_extended_info_version (&extended_info);
3035 SIVAL(pdata,16,extended_info.samba_magic);
3036 SIVAL(pdata,20,extended_info.samba_version);
3037 SIVAL(pdata,24,extended_info.samba_subversion);
3038 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3039 memcpy(pdata+36,extended_info.samba_version_string,28);
3045 * Query the version and capabilities of the CIFS UNIX extensions
3049 case SMB_QUERY_CIFS_UNIX_INFO:
3051 bool large_write = lp_min_receive_file_size() &&
3052 !srv_is_signing_active(smbd_server_conn);
3053 bool large_read = !srv_is_signing_active(smbd_server_conn);
3054 int encrypt_caps = 0;
3056 if (!lp_unix_extensions()) {
3057 return NT_STATUS_INVALID_LEVEL;
3060 switch (conn->encrypt_level) {
3066 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3069 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3070 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3071 large_write = false;
3077 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3078 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3080 /* We have POSIX ACLs, pathname, encryption,
3081 * large read/write, and locking capability. */
3083 SBIG_UINT(pdata,4,((uint64_t)(
3084 CIFS_UNIX_POSIX_ACLS_CAP|
3085 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3086 CIFS_UNIX_FCNTL_LOCKS_CAP|
3087 CIFS_UNIX_EXTATTR_CAP|
3088 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3090 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3092 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3096 case SMB_QUERY_POSIX_FS_INFO:
3099 vfs_statvfs_struct svfs;
3101 if (!lp_unix_extensions()) {
3102 return NT_STATUS_INVALID_LEVEL;
3105 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3109 SIVAL(pdata,0,svfs.OptimalTransferSize);
3110 SIVAL(pdata,4,svfs.BlockSize);
3111 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3112 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3113 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3114 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3115 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3116 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3117 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3119 } else if (rc == EOPNOTSUPP) {
3120 return NT_STATUS_INVALID_LEVEL;
3121 #endif /* EOPNOTSUPP */
3123 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3124 return NT_STATUS_DOS(ERRSRV, ERRerror);
3129 case SMB_QUERY_POSIX_WHOAMI:
3135 if (!lp_unix_extensions()) {
3136 return NT_STATUS_INVALID_LEVEL;
3139 if (max_data_bytes < 40) {
3140 return NT_STATUS_BUFFER_TOO_SMALL;
3143 /* We ARE guest if global_sid_Builtin_Guests is
3144 * in our list of SIDs.
3146 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3147 conn->server_info->ptok)) {
3148 flags |= SMB_WHOAMI_GUEST;
3151 /* We are NOT guest if global_sid_Authenticated_Users
3152 * is in our list of SIDs.
3154 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3155 conn->server_info->ptok)) {
3156 flags &= ~SMB_WHOAMI_GUEST;
3159 /* NOTE: 8 bytes for UID/GID, irrespective of native
3160 * platform size. This matches
3161 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3163 data_len = 4 /* flags */
3170 + 4 /* pad/reserved */
3171 + (conn->server_info->utok.ngroups * 8)
3173 + (conn->server_info->ptok->num_sids *
3177 SIVAL(pdata, 0, flags);
3178 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3180 (uint64_t)conn->server_info->utok.uid);
3181 SBIG_UINT(pdata, 16,
3182 (uint64_t)conn->server_info->utok.gid);
3185 if (data_len >= max_data_bytes) {
3186 /* Potential overflow, skip the GIDs and SIDs. */
3188 SIVAL(pdata, 24, 0); /* num_groups */
3189 SIVAL(pdata, 28, 0); /* num_sids */
3190 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3191 SIVAL(pdata, 36, 0); /* reserved */
3197 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3198 SIVAL(pdata, 28, conn->server_info->num_sids);
3200 /* We walk the SID list twice, but this call is fairly
3201 * infrequent, and I don't expect that it's performance
3202 * sensitive -- jpeach
3204 for (i = 0, sid_bytes = 0;
3205 i < conn->server_info->ptok->num_sids; ++i) {
3206 sid_bytes += ndr_size_dom_sid(
3207 &conn->server_info->ptok->user_sids[i],
3212 /* SID list byte count */
3213 SIVAL(pdata, 32, sid_bytes);
3215 /* 4 bytes pad/reserved - must be zero */
3216 SIVAL(pdata, 36, 0);
3220 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3221 SBIG_UINT(pdata, data_len,
3222 (uint64_t)conn->server_info->utok.groups[i]);
3228 i < conn->server_info->ptok->num_sids; ++i) {
3229 int sid_len = ndr_size_dom_sid(
3230 &conn->server_info->ptok->user_sids[i],
3234 sid_linearize(pdata + data_len, sid_len,
3235 &conn->server_info->ptok->user_sids[i]);
3236 data_len += sid_len;
3242 case SMB_MAC_QUERY_FS_INFO:
3244 * Thursby MAC extension... ONLY on NTFS filesystems
3245 * once we do streams then we don't need this
3247 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3249 SIVAL(pdata,84,0x100); /* Don't support mac... */
3254 return NT_STATUS_INVALID_LEVEL;
3257 *ret_data_len = data_len;
3258 return NT_STATUS_OK;
3261 /****************************************************************************
3262 Reply to a TRANS2_QFSINFO (query filesystem info).
3263 ****************************************************************************/
3265 static void call_trans2qfsinfo(connection_struct *conn,
3266 struct smb_request *req,
3267 char **pparams, int total_params,
3268 char **ppdata, int total_data,
3269 unsigned int max_data_bytes)
3271 char *params = *pparams;
3272 uint16_t info_level;
3276 if (total_params < 2) {
3277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3281 info_level = SVAL(params,0);
3283 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3284 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3285 DEBUG(0,("call_trans2qfsinfo: encryption required "
3286 "and info level 0x%x sent.\n",
3287 (unsigned int)info_level));
3288 exit_server_cleanly("encryption required "
3294 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3296 status = smbd_do_qfsinfo(conn, req,
3301 if (!NT_STATUS_IS_OK(status)) {
3302 reply_nterror(req, status);
3306 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3309 DEBUG( 4, ( "%s info_level = %d\n",
3310 smb_fn_name(req->cmd), info_level) );
3315 /****************************************************************************
3316 Reply to a TRANS2_SETFSINFO (set filesystem info).
3317 ****************************************************************************/
3319 static void call_trans2setfsinfo(connection_struct *conn,
3320 struct smb_request *req,
3321 char **pparams, int total_params,
3322 char **ppdata, int total_data,
3323 unsigned int max_data_bytes)
3325 char *pdata = *ppdata;
3326 char *params = *pparams;
3329 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3332 if (total_params < 4) {
3333 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3339 info_level = SVAL(params,2);
3342 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3343 info_level != SMB_SET_CIFS_UNIX_INFO) {
3344 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3345 "info level (0x%x) on IPC$.\n",
3346 (unsigned int)info_level));
3347 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3352 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3353 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3354 DEBUG(0,("call_trans2setfsinfo: encryption required "
3355 "and info level 0x%x sent.\n",
3356 (unsigned int)info_level));
3357 exit_server_cleanly("encryption required "
3363 switch(info_level) {
3364 case SMB_SET_CIFS_UNIX_INFO:
3366 uint16 client_unix_major;
3367 uint16 client_unix_minor;
3368 uint32 client_unix_cap_low;
3369 uint32 client_unix_cap_high;
3371 if (!lp_unix_extensions()) {
3373 NT_STATUS_INVALID_LEVEL);
3377 /* There should be 12 bytes of capabilities set. */
3378 if (total_data < 8) {
3381 NT_STATUS_INVALID_PARAMETER);
3384 client_unix_major = SVAL(pdata,0);
3385 client_unix_minor = SVAL(pdata,2);
3386 client_unix_cap_low = IVAL(pdata,4);
3387 client_unix_cap_high = IVAL(pdata,8);
3388 /* Just print these values for now. */
3389 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3390 cap_low = 0x%x, cap_high = 0x%x\n",
3391 (unsigned int)client_unix_major,
3392 (unsigned int)client_unix_minor,
3393 (unsigned int)client_unix_cap_low,
3394 (unsigned int)client_unix_cap_high ));
3396 /* Here is where we must switch to posix pathname processing... */
3397 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3398 lp_set_posix_pathnames();
3399 mangle_change_to_posix();
3402 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3403 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3404 /* Client that knows how to do posix locks,
3405 * but not posix open/mkdir operations. Set a
3406 * default type for read/write checks. */
3408 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3414 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3417 size_t param_len = 0;
3418 size_t data_len = total_data;
3420 if (!lp_unix_extensions()) {
3423 NT_STATUS_INVALID_LEVEL);
3427 if (lp_smb_encrypt(SNUM(conn)) == false) {
3430 NT_STATUS_NOT_SUPPORTED);
3434 DEBUG( 4,("call_trans2setfsinfo: "
3435 "request transport encryption.\n"));
3437 status = srv_request_encryption_setup(conn,
3438 (unsigned char **)ppdata,
3440 (unsigned char **)pparams,
3443 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3444 !NT_STATUS_IS_OK(status)) {
3445 reply_nterror(req, status);
3449 send_trans2_replies(conn, req,
3456 if (NT_STATUS_IS_OK(status)) {
3457 /* Server-side transport
3458 * encryption is now *on*. */
3459 status = srv_encryption_start(conn);
3460 if (!NT_STATUS_IS_OK(status)) {
3461 exit_server_cleanly(
3462 "Failure in setting "
3463 "up encrypted transport");
3469 case SMB_FS_QUOTA_INFORMATION:
3471 files_struct *fsp = NULL;
3472 SMB_NTQUOTA_STRUCT quotas;
3474 ZERO_STRUCT(quotas);
3477 if ((conn->server_info->utok.uid != sec_initial_uid())
3478 ||!CAN_WRITE(conn)) {
3479 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3480 lp_servicename(SNUM(conn)),
3481 conn->server_info->unix_name));
3482 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3486 /* note: normaly there're 48 bytes,
3487 * but we didn't use the last 6 bytes for now
3490 fsp = file_fsp(req, SVAL(params,0));
3492 if (!check_fsp_ntquota_handle(conn, req,
3494 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3496 req, NT_STATUS_INVALID_HANDLE);
3500 if (total_data < 42) {
3501 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3505 NT_STATUS_INVALID_PARAMETER);
3509 /* unknown_1 24 NULL bytes in pdata*/
3511 /* the soft quotas 8 bytes (uint64_t)*/
3512 quotas.softlim = (uint64_t)IVAL(pdata,24);
3513 #ifdef LARGE_SMB_OFF_T
3514 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3515 #else /* LARGE_SMB_OFF_T */
3516 if ((IVAL(pdata,28) != 0)&&
3517 ((quotas.softlim != 0xFFFFFFFF)||
3518 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3519 /* more than 32 bits? */
3522 NT_STATUS_INVALID_PARAMETER);
3525 #endif /* LARGE_SMB_OFF_T */
3527 /* the hard quotas 8 bytes (uint64_t)*/
3528 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3529 #ifdef LARGE_SMB_OFF_T
3530 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3531 #else /* LARGE_SMB_OFF_T */
3532 if ((IVAL(pdata,36) != 0)&&
3533 ((quotas.hardlim != 0xFFFFFFFF)||
3534 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3535 /* more than 32 bits? */
3538 NT_STATUS_INVALID_PARAMETER);
3541 #endif /* LARGE_SMB_OFF_T */
3543 /* quota_flags 2 bytes **/
3544 quotas.qflags = SVAL(pdata,40);
3546 /* unknown_2 6 NULL bytes follow*/
3548 /* now set the quotas */
3549 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3550 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3551 reply_nterror(req, map_nt_error_from_unix(errno));
3558 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3560 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3566 * sending this reply works fine,
3567 * but I'm not sure it's the same
3568 * like windows do...
3571 reply_outbuf(req, 10, 0);
3574 #if defined(HAVE_POSIX_ACLS)
3575 /****************************************************************************
3576 Utility function to count the number of entries in a POSIX acl.
3577 ****************************************************************************/
3579 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3581 unsigned int ace_count = 0;
3582 int entry_id = SMB_ACL_FIRST_ENTRY;
3583 SMB_ACL_ENTRY_T entry;
3585 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3587 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3588 entry_id = SMB_ACL_NEXT_ENTRY;
3595 /****************************************************************************
3596 Utility function to marshall a POSIX acl into wire format.
3597 ****************************************************************************/
3599 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3601 int entry_id = SMB_ACL_FIRST_ENTRY;
3602 SMB_ACL_ENTRY_T entry;
3604 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3605 SMB_ACL_TAG_T tagtype;
3606 SMB_ACL_PERMSET_T permset;
3607 unsigned char perms = 0;
3608 unsigned int own_grp;
3611 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3612 entry_id = SMB_ACL_NEXT_ENTRY;
3615 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3616 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3620 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3621 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3625 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3626 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3627 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3629 SCVAL(pdata,1,perms);
3632 case SMB_ACL_USER_OBJ:
3633 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3634 own_grp = (unsigned int)pst->st_ex_uid;
3635 SIVAL(pdata,2,own_grp);
3640 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3642 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3645 own_grp = (unsigned int)*puid;
3646 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3647 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3648 SIVAL(pdata,2,own_grp);
3652 case SMB_ACL_GROUP_OBJ:
3653 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3654 own_grp = (unsigned int)pst->st_ex_gid;
3655 SIVAL(pdata,2,own_grp);
3660 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3662 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3665 own_grp = (unsigned int)*pgid;
3666 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3667 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3668 SIVAL(pdata,2,own_grp);
3673 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3674 SIVAL(pdata,2,0xFFFFFFFF);
3675 SIVAL(pdata,6,0xFFFFFFFF);
3678 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3679 SIVAL(pdata,2,0xFFFFFFFF);
3680 SIVAL(pdata,6,0xFFFFFFFF);
3683 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3686 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3693 /****************************************************************************
3694 Store the FILE_UNIX_BASIC info.
3695 ****************************************************************************/
3697 static char *store_file_unix_basic(connection_struct *conn,
3700 const SMB_STRUCT_STAT *psbuf)
3702 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3703 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3705 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3708 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3711 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3712 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3713 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3716 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3720 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3724 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3727 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3731 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3735 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3738 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3742 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3749 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3750 * the chflags(2) (or equivalent) flags.
3752 * XXX: this really should be behind the VFS interface. To do this, we would
3753 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3754 * Each VFS module could then implement its own mapping as appropriate for the
3755 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3757 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3761 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3765 { UF_IMMUTABLE, EXT_IMMUTABLE },
3769 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3773 { UF_HIDDEN, EXT_HIDDEN },
3776 /* Do not remove. We need to guarantee that this array has at least one
3777 * entry to build on HP-UX.
3783 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3784 uint32 *smb_fflags, uint32 *smb_fmask)
3788 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3789 *smb_fmask |= info2_flags_map[i].smb_fflag;
3790 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3791 *smb_fflags |= info2_flags_map[i].smb_fflag;
3796 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3797 const uint32 smb_fflags,
3798 const uint32 smb_fmask,
3801 uint32 max_fmask = 0;
3804 *stat_fflags = psbuf->st_ex_flags;
3806 /* For each flags requested in smb_fmask, check the state of the
3807 * corresponding flag in smb_fflags and set or clear the matching
3811 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3812 max_fmask |= info2_flags_map[i].smb_fflag;
3813 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3814 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3815 *stat_fflags |= info2_flags_map[i].stat_fflag;
3817 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3822 /* If smb_fmask is asking to set any bits that are not supported by
3823 * our flag mappings, we should fail.
3825 if ((smb_fmask & max_fmask) != smb_fmask) {
3833 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3834 * of file flags and birth (create) time.
3836 static char *store_file_unix_basic_info2(connection_struct *conn,
3839 const SMB_STRUCT_STAT *psbuf)
3841 uint32 file_flags = 0;
3842 uint32 flags_mask = 0;
3844 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3846 /* Create (birth) time 64 bit */
3847 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3850 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3851 SIVAL(pdata, 0, file_flags); /* flags */
3852 SIVAL(pdata, 4, flags_mask); /* mask */
3858 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3859 const struct stream_struct *streams,
3861 unsigned int max_data_bytes,
3862 unsigned int *data_size)
3865 unsigned int ofs = 0;
3867 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3868 unsigned int next_offset;
3870 smb_ucs2_t *namebuf;
3872 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3873 streams[i].name, &namelen) ||
3876 return NT_STATUS_INVALID_PARAMETER;
3880 * name_buf is now null-terminated, we need to marshall as not
3886 SIVAL(data, ofs+4, namelen);
3887 SOFF_T(data, ofs+8, streams[i].size);
3888 SOFF_T(data, ofs+16, streams[i].alloc_size);
3889 memcpy(data+ofs+24, namebuf, namelen);
3890 TALLOC_FREE(namebuf);
3892 next_offset = ofs + 24 + namelen;
3894 if (i == num_streams-1) {
3895 SIVAL(data, ofs, 0);
3898 unsigned int align = ndr_align_size(next_offset, 8);
3900 memset(data+next_offset, 0, align);
3901 next_offset += align;
3903 SIVAL(data, ofs, next_offset - ofs);
3912 return NT_STATUS_OK;
3915 /****************************************************************************
3916 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3917 ****************************************************************************/
3919 static void call_trans2qpipeinfo(connection_struct *conn,
3920 struct smb_request *req,
3921 unsigned int tran_call,
3922 char **pparams, int total_params,
3923 char **ppdata, int total_data,
3924 unsigned int max_data_bytes)
3926 char *params = *pparams;
3927 char *pdata = *ppdata;
3928 unsigned int data_size = 0;
3929 unsigned int param_size = 2;
3934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3938 if (total_params < 4) {
3939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3943 fsp = file_fsp(req, SVAL(params,0));
3944 if (!fsp_is_np(fsp)) {
3945 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3949 info_level = SVAL(params,2);
3951 *pparams = (char *)SMB_REALLOC(*pparams,2);
3952 if (*pparams == NULL) {
3953 reply_nterror(req, NT_STATUS_NO_MEMORY);
3958 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3959 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3960 if (*ppdata == NULL ) {
3961 reply_nterror(req, NT_STATUS_NO_MEMORY);
3966 switch (info_level) {
3967 case SMB_FILE_STANDARD_INFORMATION:
3969 SOFF_T(pdata,0,4096LL);
3976 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3980 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3986 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3987 TALLOC_CTX *mem_ctx,
3988 uint16_t info_level,
3990 struct smb_filename *smb_fname,
3991 bool delete_pending,
3992 struct timespec write_time_ts,
3994 struct ea_list *ea_list,
3995 int lock_data_count,
3998 unsigned int max_data_bytes,
4000 unsigned int *pdata_size)
4002 char *pdata = *ppdata;
4003 char *dstart, *dend;
4004 unsigned int data_size;
4005 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4006 time_t create_time, mtime, atime, c_time;
4007 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4014 uint64_t file_size = 0;
4016 uint64_t allocation_size = 0;
4017 uint64_t file_index = 0;
4018 uint32_t access_mask = 0;
4020 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4021 return NT_STATUS_INVALID_LEVEL;
4024 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4025 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4026 info_level, max_data_bytes));
4029 mode = dos_mode_msdfs(conn, smb_fname);
4031 mode = dos_mode(conn, smb_fname);
4034 mode = FILE_ATTRIBUTE_NORMAL;
4036 nlink = psbuf->st_ex_nlink;
4038 if (nlink && (mode&aDIR)) {
4042 if ((nlink > 0) && delete_pending) {
4046 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4047 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4048 if (*ppdata == NULL) {
4049 return NT_STATUS_NO_MEMORY;
4053 dend = dstart + data_size - 1;
4055 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4056 update_stat_ex_mtime(psbuf, write_time_ts);
4059 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4060 mtime_ts = psbuf->st_ex_mtime;
4061 atime_ts = psbuf->st_ex_atime;
4062 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4064 if (lp_dos_filetime_resolution(SNUM(conn))) {
4065 dos_filetime_timespec(&create_time_ts);
4066 dos_filetime_timespec(&mtime_ts);
4067 dos_filetime_timespec(&atime_ts);
4068 dos_filetime_timespec(&ctime_ts);
4071 create_time = convert_timespec_to_time_t(create_time_ts);
4072 mtime = convert_timespec_to_time_t(mtime_ts);
4073 atime = convert_timespec_to_time_t(atime_ts);
4074 c_time = convert_timespec_to_time_t(ctime_ts);
4076 p = strrchr_m(smb_fname->base_name,'/');
4078 base_name = smb_fname->base_name;
4082 /* NT expects the name to be in an exact form of the *full*
4083 filename. See the trans2 torture test */
4084 if (ISDOT(base_name)) {
4085 dos_fname = talloc_strdup(mem_ctx, "\\");
4087 return NT_STATUS_NO_MEMORY;
4090 dos_fname = talloc_asprintf(mem_ctx,
4092 smb_fname->base_name);
4094 return NT_STATUS_NO_MEMORY;
4096 if (is_ntfs_stream_smb_fname(smb_fname)) {
4097 dos_fname = talloc_asprintf(dos_fname, "%s",
4098 smb_fname->stream_name);
4100 return NT_STATUS_NO_MEMORY;
4104 string_replace(dos_fname, '/', '\\');
4107 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4110 /* Do we have this path open ? */
4112 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4113 fsp1 = file_find_di_first(fileid);
4114 if (fsp1 && fsp1->initial_allocation_size) {
4115 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4119 if (!(mode & aDIR)) {
4120 file_size = get_file_size_stat(psbuf);
4124 pos = fsp->fh->position_information;
4128 access_mask = fsp->access_mask;
4130 /* GENERIC_EXECUTE mapping from Windows */
4131 access_mask = 0x12019F;
4134 /* This should be an index number - looks like
4137 I think this causes us to fail the IFSKIT
4138 BasicFileInformationTest. -tpot */
4139 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4140 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4142 switch (info_level) {
4143 case SMB_INFO_STANDARD:
4144 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4146 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4147 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4148 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4149 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4150 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4151 SSVAL(pdata,l1_attrFile,mode);
4154 case SMB_INFO_QUERY_EA_SIZE:
4156 unsigned int ea_size =
4157 estimate_ea_size(conn, fsp,
4158 smb_fname->base_name);
4159 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4161 srv_put_dos_date2(pdata,0,create_time);
4162 srv_put_dos_date2(pdata,4,atime);
4163 srv_put_dos_date2(pdata,8,mtime); /* write time */
4164 SIVAL(pdata,12,(uint32)file_size);
4165 SIVAL(pdata,16,(uint32)allocation_size);
4166 SSVAL(pdata,20,mode);
4167 SIVAL(pdata,22,ea_size);
4171 case SMB_INFO_IS_NAME_VALID:
4172 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4174 /* os/2 needs this ? really ?*/
4175 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4177 /* This is only reached for qpathinfo */
4181 case SMB_INFO_QUERY_EAS_FROM_LIST:
4183 size_t total_ea_len = 0;
4184 struct ea_list *ea_file_list = NULL;
4186 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4189 get_ea_list_from_file(mem_ctx, conn, fsp,
4190 smb_fname->base_name,
4192 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4194 if (!ea_list || (total_ea_len > data_size)) {
4196 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4200 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4204 case SMB_INFO_QUERY_ALL_EAS:
4206 /* We have data_size bytes to put EA's into. */
4207 size_t total_ea_len = 0;
4209 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4211 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4212 smb_fname->base_name,
4214 if (!ea_list || (total_ea_len > data_size)) {
4216 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4220 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4224 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4226 /* We have data_size bytes to put EA's into. */
4227 size_t total_ea_len = 0;
4228 struct ea_list *ea_file_list = NULL;
4230 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4232 /*TODO: add filtering and index handling */
4235 get_ea_list_from_file(mem_ctx, conn, fsp,
4236 smb_fname->base_name,
4238 if (!ea_file_list) {
4239 return NT_STATUS_NO_EAS_ON_FILE;
4242 status = fill_ea_chained_buffer(mem_ctx,
4246 conn, ea_file_list);
4247 if (!NT_STATUS_IS_OK(status)) {
4253 case SMB_FILE_BASIC_INFORMATION:
4254 case SMB_QUERY_FILE_BASIC_INFO:
4256 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4257 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4258 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4260 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4264 put_long_date_timespec(pdata,create_time_ts);
4265 put_long_date_timespec(pdata+8,atime_ts);
4266 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4267 put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4268 SIVAL(pdata,32,mode);
4270 DEBUG(5,("SMB_QFBI - "));
4271 DEBUG(5,("create: %s ", ctime(&create_time)));
4272 DEBUG(5,("access: %s ", ctime(&atime)));
4273 DEBUG(5,("write: %s ", ctime(&mtime)));
4274 DEBUG(5,("change: %s ", ctime(&c_time)));
4275 DEBUG(5,("mode: %x\n", mode));
4278 case SMB_FILE_STANDARD_INFORMATION:
4279 case SMB_QUERY_FILE_STANDARD_INFO:
4281 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4283 SOFF_T(pdata,0,allocation_size);
4284 SOFF_T(pdata,8,file_size);
4285 SIVAL(pdata,16,nlink);
4286 SCVAL(pdata,20,delete_pending?1:0);
4287 SCVAL(pdata,21,(mode&aDIR)?1:0);
4288 SSVAL(pdata,22,0); /* Padding. */
4291 case SMB_FILE_EA_INFORMATION:
4292 case SMB_QUERY_FILE_EA_INFO:
4294 unsigned int ea_size =
4295 estimate_ea_size(conn, fsp, smb_fname->base_name);
4296 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4298 SIVAL(pdata,0,ea_size);
4302 /* Get the 8.3 name - used if NT SMB was negotiated. */
4303 case SMB_QUERY_FILE_ALT_NAME_INFO:
4304 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4307 char mangled_name[13];
4308 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4309 if (!name_to_8_3(base_name,mangled_name,
4310 True,conn->params)) {
4311 return NT_STATUS_NO_MEMORY;
4313 len = srvstr_push(dstart, flags2,
4314 pdata+4, mangled_name,
4315 PTR_DIFF(dend, pdata+4),
4317 data_size = 4 + len;
4322 case SMB_QUERY_FILE_NAME_INFO:
4326 this must be *exactly* right for ACLs on mapped drives to work
4328 len = srvstr_push(dstart, flags2,
4330 PTR_DIFF(dend, pdata+4),
4332 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4333 data_size = 4 + len;
4338 case SMB_FILE_ALLOCATION_INFORMATION:
4339 case SMB_QUERY_FILE_ALLOCATION_INFO:
4340 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4342 SOFF_T(pdata,0,allocation_size);
4345 case SMB_FILE_END_OF_FILE_INFORMATION:
4346 case SMB_QUERY_FILE_END_OF_FILEINFO:
4347 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4349 SOFF_T(pdata,0,file_size);
4352 case SMB_QUERY_FILE_ALL_INFO:
4353 case SMB_FILE_ALL_INFORMATION:
4356 unsigned int ea_size =
4357 estimate_ea_size(conn, fsp, smb_fname->base_name);
4358 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4359 put_long_date_timespec(pdata,create_time_ts);
4360 put_long_date_timespec(pdata+8,atime_ts);
4361 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4362 put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4363 SIVAL(pdata,32,mode);
4364 SIVAL(pdata,36,0); /* padding. */
4366 SOFF_T(pdata,0,allocation_size);
4367 SOFF_T(pdata,8,file_size);
4368 SIVAL(pdata,16,nlink);
4369 SCVAL(pdata,20,delete_pending);
4370 SCVAL(pdata,21,(mode&aDIR)?1:0);
4373 SIVAL(pdata,0,ea_size);
4374 pdata += 4; /* EA info */
4375 len = srvstr_push(dstart, flags2,
4377 PTR_DIFF(dend, pdata+4),
4381 data_size = PTR_DIFF(pdata,(*ppdata));
4385 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4388 unsigned int ea_size =
4389 estimate_ea_size(conn, fsp, smb_fname->base_name);
4390 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4391 put_long_date_timespec(pdata+0x00,create_time_ts);
4392 put_long_date_timespec(pdata+0x08,atime_ts);
4393 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4394 put_long_date_timespec(pdata+0x18,ctime_ts); /* change time */
4395 SIVAL(pdata, 0x20, mode);
4396 SIVAL(pdata, 0x24, 0); /* padding. */
4397 SBVAL(pdata, 0x28, allocation_size);
4398 SBVAL(pdata, 0x30, file_size);
4399 SIVAL(pdata, 0x38, nlink);
4400 SCVAL(pdata, 0x3C, delete_pending);
4401 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4402 SSVAL(pdata, 0x3E, 0); /* padding */
4403 SBVAL(pdata, 0x40, file_index);
4404 SIVAL(pdata, 0x48, ea_size);
4405 SIVAL(pdata, 0x4C, access_mask);
4406 SBVAL(pdata, 0x50, pos);
4407 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4408 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4412 len = srvstr_push(dstart, flags2,
4414 PTR_DIFF(dend, pdata+4),
4418 data_size = PTR_DIFF(pdata,(*ppdata));
4421 case SMB_FILE_INTERNAL_INFORMATION:
4423 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4424 SBVAL(pdata, 0, file_index);
4428 case SMB_FILE_ACCESS_INFORMATION:
4429 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4430 SIVAL(pdata, 0, access_mask);
4434 case SMB_FILE_NAME_INFORMATION:
4435 /* Pathname with leading '\'. */
4438 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4439 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4440 SIVAL(pdata,0,byte_len);
4441 data_size = 4 + byte_len;
4445 case SMB_FILE_DISPOSITION_INFORMATION:
4446 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4448 SCVAL(pdata,0,delete_pending);
4451 case SMB_FILE_POSITION_INFORMATION:
4452 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4454 SOFF_T(pdata,0,pos);
4457 case SMB_FILE_MODE_INFORMATION:
4458 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4459 SIVAL(pdata,0,mode);
4463 case SMB_FILE_ALIGNMENT_INFORMATION:
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4465 SIVAL(pdata,0,0); /* No alignment needed. */
4470 * NT4 server just returns "invalid query" to this - if we try
4471 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4474 /* The first statement above is false - verified using Thursby
4475 * client against NT4 -- gcolley.
4477 case SMB_QUERY_FILE_STREAM_INFO:
4478 case SMB_FILE_STREAM_INFORMATION: {
4479 unsigned int num_streams;
4480 struct stream_struct *streams;
4482 DEBUG(10,("smbd_do_qfilepathinfo: "
4483 "SMB_FILE_STREAM_INFORMATION\n"));
4485 if (is_ntfs_stream_smb_fname(smb_fname)) {
4486 return NT_STATUS_INVALID_PARAMETER;
4489 status = SMB_VFS_STREAMINFO(
4490 conn, fsp, smb_fname->base_name, talloc_tos(),
4491 &num_streams, &streams);
4493 if (!NT_STATUS_IS_OK(status)) {
4494 DEBUG(10, ("could not get stream info: %s\n",
4495 nt_errstr(status)));
4499 status = marshall_stream_info(num_streams, streams,
4500 pdata, max_data_bytes,
4503 if (!NT_STATUS_IS_OK(status)) {
4504 DEBUG(10, ("marshall_stream_info failed: %s\n",
4505 nt_errstr(status)));
4509 TALLOC_FREE(streams);
4513 case SMB_QUERY_COMPRESSION_INFO:
4514 case SMB_FILE_COMPRESSION_INFORMATION:
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4516 SOFF_T(pdata,0,file_size);
4517 SIVAL(pdata,8,0); /* ??? */
4518 SIVAL(pdata,12,0); /* ??? */
4522 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4523 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4524 put_long_date_timespec(pdata,create_time_ts);
4525 put_long_date_timespec(pdata+8,atime_ts);
4526 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4527 put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4528 SOFF_T(pdata,32,allocation_size);
4529 SOFF_T(pdata,40,file_size);
4530 SIVAL(pdata,48,mode);
4531 SIVAL(pdata,52,0); /* ??? */
4535 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4536 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4537 SIVAL(pdata,0,mode);
4543 * CIFS UNIX Extensions.
4546 case SMB_QUERY_FILE_UNIX_BASIC:
4548 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4549 data_size = PTR_DIFF(pdata,(*ppdata));
4553 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4555 for (i=0; i<100; i++)
4556 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4562 case SMB_QUERY_FILE_UNIX_INFO2:
4564 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4565 data_size = PTR_DIFF(pdata,(*ppdata));
4569 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4571 for (i=0; i<100; i++)
4572 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4578 case SMB_QUERY_FILE_UNIX_LINK:
4581 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4584 return NT_STATUS_NO_MEMORY;
4587 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4589 if(!S_ISLNK(psbuf->st_ex_mode)) {
4590 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4593 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4595 len = SMB_VFS_READLINK(conn,
4596 smb_fname->base_name,
4599 return map_nt_error_from_unix(errno);
4602 len = srvstr_push(dstart, flags2,
4604 PTR_DIFF(dend, pdata),
4607 data_size = PTR_DIFF(pdata,(*ppdata));
4612 #if defined(HAVE_POSIX_ACLS)
4613 case SMB_QUERY_POSIX_ACL:
4615 SMB_ACL_T file_acl = NULL;
4616 SMB_ACL_T def_acl = NULL;
4617 uint16 num_file_acls = 0;
4618 uint16 num_def_acls = 0;
4620 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4621 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4624 SMB_VFS_SYS_ACL_GET_FILE(conn,
4625 smb_fname->base_name,
4626 SMB_ACL_TYPE_ACCESS);
4629 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4630 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4631 "not implemented on "
4632 "filesystem containing %s\n",
4633 smb_fname->base_name));
4634 return NT_STATUS_NOT_IMPLEMENTED;
4637 if (S_ISDIR(psbuf->st_ex_mode)) {
4638 if (fsp && fsp->is_directory) {
4640 SMB_VFS_SYS_ACL_GET_FILE(
4642 fsp->fsp_name->base_name,
4643 SMB_ACL_TYPE_DEFAULT);
4646 SMB_VFS_SYS_ACL_GET_FILE(
4648 smb_fname->base_name,
4649 SMB_ACL_TYPE_DEFAULT);
4651 def_acl = free_empty_sys_acl(conn, def_acl);
4654 num_file_acls = count_acl_entries(conn, file_acl);
4655 num_def_acls = count_acl_entries(conn, def_acl);
4657 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4658 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4660 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4661 SMB_POSIX_ACL_HEADER_SIZE) ));
4663 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4666 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4668 return NT_STATUS_BUFFER_TOO_SMALL;
4671 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4672 SSVAL(pdata,2,num_file_acls);
4673 SSVAL(pdata,4,num_def_acls);
4674 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4676 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4679 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4681 return NT_STATUS_INTERNAL_ERROR;
4683 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4685 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4688 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4690 return NT_STATUS_INTERNAL_ERROR;
4694 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4697 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4699 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4705 case SMB_QUERY_POSIX_LOCK:
4710 enum brl_type lock_type;
4712 /* We need an open file with a real fd for this. */
4713 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4714 return NT_STATUS_INVALID_LEVEL;
4717 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4718 return NT_STATUS_INVALID_PARAMETER;
4721 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4722 case POSIX_LOCK_TYPE_READ:
4723 lock_type = READ_LOCK;
4725 case POSIX_LOCK_TYPE_WRITE:
4726 lock_type = WRITE_LOCK;
4728 case POSIX_LOCK_TYPE_UNLOCK:
4730 /* There's no point in asking for an unlock... */
4731 return NT_STATUS_INVALID_PARAMETER;
4734 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4735 #if defined(HAVE_LONGLONG)
4736 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4737 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4738 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4739 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4740 #else /* HAVE_LONGLONG */
4741 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4742 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4743 #endif /* HAVE_LONGLONG */
4745 status = query_lock(fsp,
4752 if (ERROR_WAS_LOCK_DENIED(status)) {
4753 /* Here we need to report who has it locked... */
4754 data_size = POSIX_LOCK_DATA_SIZE;
4756 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4757 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4758 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4759 #if defined(HAVE_LONGLONG)
4760 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4761 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4762 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4763 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4764 #else /* HAVE_LONGLONG */
4765 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4766 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4767 #endif /* HAVE_LONGLONG */
4769 } else if (NT_STATUS_IS_OK(status)) {
4770 /* For success we just return a copy of what we sent
4771 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4772 data_size = POSIX_LOCK_DATA_SIZE;
4773 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4774 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4782 return NT_STATUS_INVALID_LEVEL;
4785 *pdata_size = data_size;
4786 return NT_STATUS_OK;
4789 /****************************************************************************
4790 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4791 file name or file id).
4792 ****************************************************************************/
4794 static void call_trans2qfilepathinfo(connection_struct *conn,
4795 struct smb_request *req,
4796 unsigned int tran_call,
4797 char **pparams, int total_params,
4798 char **ppdata, int total_data,
4799 unsigned int max_data_bytes)
4801 char *params = *pparams;
4802 char *pdata = *ppdata;
4804 unsigned int data_size = 0;
4805 unsigned int param_size = 2;
4806 struct smb_filename *smb_fname = NULL;
4807 bool delete_pending = False;
4808 struct timespec write_time_ts;
4809 files_struct *fsp = NULL;
4810 struct file_id fileid;
4811 struct ea_list *ea_list = NULL;
4812 int lock_data_count = 0;
4813 char *lock_data = NULL;
4814 bool ms_dfs_link = false;
4815 NTSTATUS status = NT_STATUS_OK;
4818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4822 ZERO_STRUCT(write_time_ts);
4824 if (tran_call == TRANSACT2_QFILEINFO) {
4825 if (total_params < 4) {
4826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4831 call_trans2qpipeinfo(conn, req, tran_call,
4832 pparams, total_params,
4838 fsp = file_fsp(req, SVAL(params,0));
4839 info_level = SVAL(params,2);
4841 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4843 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4844 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4848 /* Initial check for valid fsp ptr. */
4849 if (!check_fsp_open(conn, req, fsp)) {
4853 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4855 if (!NT_STATUS_IS_OK(status)) {
4856 reply_nterror(req, status);
4860 if(fsp->fake_file_handle) {
4862 * This is actually for the QUOTA_FAKE_FILE --metze
4865 /* We know this name is ok, it's already passed the checks. */
4867 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4869 * This is actually a QFILEINFO on a directory
4870 * handle (returned from an NT SMB). NT5.0 seems
4871 * to do this call. JRA.
4874 if (INFO_LEVEL_IS_UNIX(info_level)) {
4875 /* Always do lstat for UNIX calls. */
4876 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4877 DEBUG(3,("call_trans2qfilepathinfo: "
4878 "SMB_VFS_LSTAT of %s failed "
4880 smb_fname_str_dbg(smb_fname),
4883 map_nt_error_from_unix(errno));
4886 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4887 DEBUG(3,("call_trans2qfilepathinfo: "
4888 "SMB_VFS_STAT of %s failed (%s)\n",
4889 smb_fname_str_dbg(smb_fname),
4892 map_nt_error_from_unix(errno));
4896 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4897 get_file_infos(fileid, &delete_pending, &write_time_ts);
4900 * Original code - this is an open file.
4902 if (!check_fsp(conn, req, fsp)) {
4906 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4907 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4908 fsp->fnum, strerror(errno)));
4910 map_nt_error_from_unix(errno));
4913 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4914 get_file_infos(fileid, &delete_pending, &write_time_ts);
4921 if (total_params < 7) {
4922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4926 info_level = SVAL(params,0);
4928 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4930 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4931 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4935 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4937 STR_TERMINATE, &status);
4938 if (!NT_STATUS_IS_OK(status)) {
4939 reply_nterror(req, status);
4943 status = filename_convert(req,
4945 req->flags2 & FLAGS2_DFS_PATHNAMES,
4950 if (!NT_STATUS_IS_OK(status)) {
4951 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4952 reply_botherror(req,
4953 NT_STATUS_PATH_NOT_COVERED,
4954 ERRSRV, ERRbadpath);
4957 reply_nterror(req, status);
4961 /* If this is a stream, check if there is a delete_pending. */
4962 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4963 && is_ntfs_stream_smb_fname(smb_fname)) {
4964 struct smb_filename *smb_fname_base = NULL;
4966 /* Create an smb_filename with stream_name == NULL. */
4968 create_synthetic_smb_fname(talloc_tos(),
4969 smb_fname->base_name,
4972 if (!NT_STATUS_IS_OK(status)) {
4973 reply_nterror(req, status);
4977 if (INFO_LEVEL_IS_UNIX(info_level)) {
4978 /* Always do lstat for UNIX calls. */
4979 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4980 DEBUG(3,("call_trans2qfilepathinfo: "
4981 "SMB_VFS_LSTAT of %s failed "
4983 smb_fname_str_dbg(smb_fname_base),
4985 TALLOC_FREE(smb_fname_base);
4987 map_nt_error_from_unix(errno));
4991 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4992 DEBUG(3,("call_trans2qfilepathinfo: "
4993 "fileinfo of %s failed "
4995 smb_fname_str_dbg(smb_fname_base),
4997 TALLOC_FREE(smb_fname_base);
4999 map_nt_error_from_unix(errno));
5004 fileid = vfs_file_id_from_sbuf(conn,
5005 &smb_fname_base->st);
5006 TALLOC_FREE(smb_fname_base);
5007 get_file_infos(fileid, &delete_pending, NULL);
5008 if (delete_pending) {
5009 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5014 if (INFO_LEVEL_IS_UNIX(info_level)) {
5015 /* Always do lstat for UNIX calls. */
5016 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5017 DEBUG(3,("call_trans2qfilepathinfo: "
5018 "SMB_VFS_LSTAT of %s failed (%s)\n",
5019 smb_fname_str_dbg(smb_fname),
5022 map_nt_error_from_unix(errno));
5026 } else if (!VALID_STAT(smb_fname->st) &&
5027 SMB_VFS_STAT(conn, smb_fname) &&
5028 (info_level != SMB_INFO_IS_NAME_VALID)) {
5029 ms_dfs_link = check_msdfs_link(conn,
5030 smb_fname->base_name,
5034 DEBUG(3,("call_trans2qfilepathinfo: "
5035 "SMB_VFS_STAT of %s failed (%s)\n",
5036 smb_fname_str_dbg(smb_fname),
5039 map_nt_error_from_unix(errno));
5044 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5045 get_file_infos(fileid, &delete_pending, &write_time_ts);
5046 if (delete_pending) {
5047 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5052 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5053 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5054 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5056 /* Pull out any data sent here before we realloc. */
5057 switch (info_level) {
5058 case SMB_INFO_QUERY_EAS_FROM_LIST:
5060 /* Pull any EA list from the data portion. */
5063 if (total_data < 4) {
5065 req, NT_STATUS_INVALID_PARAMETER);
5068 ea_size = IVAL(pdata,0);
5070 if (total_data > 0 && ea_size != total_data) {
5071 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5072 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5074 req, NT_STATUS_INVALID_PARAMETER);
5078 if (!lp_ea_support(SNUM(conn))) {
5079 reply_doserror(req, ERRDOS,
5080 ERReasnotsupported);
5084 /* Pull out the list of names. */
5085 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5088 req, NT_STATUS_INVALID_PARAMETER);
5094 case SMB_QUERY_POSIX_LOCK:
5096 if (fsp == NULL || fsp->fh->fd == -1) {
5097 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5101 if (total_data != POSIX_LOCK_DATA_SIZE) {
5103 req, NT_STATUS_INVALID_PARAMETER);
5107 /* Copy the lock range data. */
5108 lock_data = (char *)TALLOC_MEMDUP(
5109 req, pdata, total_data);
5111 reply_nterror(req, NT_STATUS_NO_MEMORY);
5114 lock_data_count = total_data;
5120 *pparams = (char *)SMB_REALLOC(*pparams,2);
5121 if (*pparams == NULL) {
5122 reply_nterror(req, NT_STATUS_NO_MEMORY);
5129 * draft-leach-cifs-v1-spec-02.txt
5130 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5133 * The requested information is placed in the Data portion of the
5134 * transaction response. For the information levels greater than 0x100,
5135 * the transaction response has 1 parameter word which should be
5136 * ignored by the client.
5138 * However Windows only follows this rule for the IS_NAME_VALID call.
5140 switch (info_level) {
5141 case SMB_INFO_IS_NAME_VALID:
5146 if ((info_level & 0xFF00) == 0xFF00) {
5148 * We use levels that start with 0xFF00
5149 * internally to represent SMB2 specific levels
5151 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5155 status = smbd_do_qfilepathinfo(conn, req, info_level,
5157 delete_pending, write_time_ts,
5158 ms_dfs_link, ea_list,
5159 lock_data_count, lock_data,
5160 req->flags2, max_data_bytes,
5161 ppdata, &data_size);
5162 if (!NT_STATUS_IS_OK(status)) {
5163 reply_nterror(req, status);
5167 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5173 /****************************************************************************
5174 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5176 ****************************************************************************/
5178 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5179 connection_struct *conn,
5180 const struct smb_filename *smb_fname_old,
5181 const struct smb_filename *smb_fname_new)
5183 NTSTATUS status = NT_STATUS_OK;
5185 /* source must already exist. */
5186 if (!VALID_STAT(smb_fname_old->st)) {
5187 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5190 /* Disallow if newname already exists. */
5191 if (VALID_STAT(smb_fname_new->st)) {
5192 return NT_STATUS_OBJECT_NAME_COLLISION;
5195 /* No links from a directory. */
5196 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5197 return NT_STATUS_FILE_IS_A_DIRECTORY;
5200 /* Setting a hardlink to/from a stream isn't currently supported. */
5201 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5202 is_ntfs_stream_smb_fname(smb_fname_new)) {
5203 return NT_STATUS_INVALID_PARAMETER;
5206 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5207 smb_fname_old->base_name, smb_fname_new->base_name));
5209 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5210 smb_fname_new->base_name) != 0) {
5211 status = map_nt_error_from_unix(errno);
5212 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5213 nt_errstr(status), smb_fname_old->base_name,
5214 smb_fname_new->base_name));
5219 /****************************************************************************
5220 Deal with setting the time from any of the setfilepathinfo functions.
5221 ****************************************************************************/
5223 NTSTATUS smb_set_file_time(connection_struct *conn,
5225 const struct smb_filename *smb_fname,
5226 struct smb_file_time *ft,
5227 bool setting_write_time)
5229 struct smb_filename *smb_fname_base = NULL;
5231 FILE_NOTIFY_CHANGE_LAST_ACCESS
5232 |FILE_NOTIFY_CHANGE_LAST_WRITE
5233 |FILE_NOTIFY_CHANGE_CREATION;
5236 if (!VALID_STAT(smb_fname->st)) {
5237 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5240 /* get some defaults (no modifications) if any info is zero or -1. */
5241 if (null_timespec(ft->create_time)) {
5242 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5245 if (null_timespec(ft->atime)) {
5246 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5249 if (null_timespec(ft->mtime)) {
5250 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5253 if (!setting_write_time) {
5254 /* ft->mtime comes from change time, not write time. */
5255 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5258 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5259 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5260 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5261 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5262 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5263 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5264 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5265 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5267 if (setting_write_time) {
5269 * This was a Windows setfileinfo on an open file.
5270 * NT does this a lot. We also need to
5271 * set the time here, as it can be read by
5272 * FindFirst/FindNext and with the patch for bug #2045
5273 * in smbd/fileio.c it ensures that this timestamp is
5274 * kept sticky even after a write. We save the request
5275 * away and will set it on file close and after a write. JRA.
5278 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5279 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5282 if (fsp->base_fsp) {
5283 set_sticky_write_time_fsp(fsp->base_fsp,
5286 set_sticky_write_time_fsp(fsp, ft->mtime);
5289 set_sticky_write_time_path(
5290 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5295 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5297 /* Always call ntimes on the base, even if a stream was passed in. */
5298 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5299 NULL, &smb_fname->st,
5301 if (!NT_STATUS_IS_OK(status)) {
5305 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5306 TALLOC_FREE(smb_fname_base);
5307 return map_nt_error_from_unix(errno);
5309 TALLOC_FREE(smb_fname_base);
5311 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5312 smb_fname->base_name);
5313 return NT_STATUS_OK;
5316 /****************************************************************************
5317 Deal with setting the dosmode from any of the setfilepathinfo functions.
5318 ****************************************************************************/
5320 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5321 const struct smb_filename *smb_fname,
5324 struct smb_filename *smb_fname_base = NULL;
5327 if (!VALID_STAT(smb_fname->st)) {
5328 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5331 /* Always operate on the base_name, even if a stream was passed in. */
5332 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5333 NULL, &smb_fname->st,
5335 if (!NT_STATUS_IS_OK(status)) {
5340 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5347 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5349 /* check the mode isn't different, before changing it */
5350 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5351 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5352 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5353 (unsigned int)dosmode));
5355 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5357 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5359 smb_fname_str_dbg(smb_fname_base),
5361 status = map_nt_error_from_unix(errno);
5365 status = NT_STATUS_OK;
5367 TALLOC_FREE(smb_fname_base);
5371 /****************************************************************************
5372 Deal with setting the size from any of the setfilepathinfo functions.
5373 ****************************************************************************/
5375 static NTSTATUS smb_set_file_size(connection_struct *conn,
5376 struct smb_request *req,
5378 const struct smb_filename *smb_fname,
5379 const SMB_STRUCT_STAT *psbuf,
5382 NTSTATUS status = NT_STATUS_OK;
5383 struct smb_filename *smb_fname_tmp = NULL;
5384 files_struct *new_fsp = NULL;
5386 if (!VALID_STAT(*psbuf)) {
5387 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5390 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5392 if (size == get_file_size_stat(psbuf)) {
5393 return NT_STATUS_OK;
5396 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5397 smb_fname_str_dbg(smb_fname), (double)size));
5399 if (fsp && fsp->fh->fd != -1) {
5400 /* Handle based call. */
5401 if (vfs_set_filelen(fsp, size) == -1) {
5402 return map_nt_error_from_unix(errno);
5404 trigger_write_time_update_immediate(fsp);
5405 return NT_STATUS_OK;
5408 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5409 if (!NT_STATUS_IS_OK(status)) {
5413 smb_fname_tmp->st = *psbuf;
5415 status = SMB_VFS_CREATE_FILE(
5418 0, /* root_dir_fid */
5419 smb_fname_tmp, /* fname */
5420 FILE_WRITE_ATTRIBUTES, /* access_mask */
5421 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5423 FILE_OPEN, /* create_disposition*/
5424 0, /* create_options */
5425 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5426 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5427 0, /* allocation_size */
5430 &new_fsp, /* result */
5433 TALLOC_FREE(smb_fname_tmp);
5435 if (!NT_STATUS_IS_OK(status)) {
5436 /* NB. We check for open_was_deferred in the caller. */
5440 if (vfs_set_filelen(new_fsp, size) == -1) {
5441 status = map_nt_error_from_unix(errno);
5442 close_file(req, new_fsp,NORMAL_CLOSE);
5446 trigger_write_time_update_immediate(new_fsp);
5447 close_file(req, new_fsp,NORMAL_CLOSE);
5448 return NT_STATUS_OK;
5451 /****************************************************************************
5452 Deal with SMB_INFO_SET_EA.
5453 ****************************************************************************/
5455 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5459 const struct smb_filename *smb_fname)
5461 struct ea_list *ea_list = NULL;
5462 TALLOC_CTX *ctx = NULL;
5463 NTSTATUS status = NT_STATUS_OK;
5465 if (total_data < 10) {
5467 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5468 length. They seem to have no effect. Bug #3212. JRA */
5470 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5471 /* We're done. We only get EA info in this call. */
5472 return NT_STATUS_OK;
5475 return NT_STATUS_INVALID_PARAMETER;
5478 if (IVAL(pdata,0) > total_data) {
5479 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5480 IVAL(pdata,0), (unsigned int)total_data));
5481 return NT_STATUS_INVALID_PARAMETER;
5485 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5487 return NT_STATUS_INVALID_PARAMETER;
5489 status = set_ea(conn, fsp, smb_fname, ea_list);
5494 /****************************************************************************
5495 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5496 ****************************************************************************/
5498 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5502 const struct smb_filename *smb_fname)
5504 NTSTATUS status = NT_STATUS_OK;
5505 bool delete_on_close;
5508 if (total_data < 1) {
5509 return NT_STATUS_INVALID_PARAMETER;
5513 return NT_STATUS_INVALID_HANDLE;
5516 delete_on_close = (CVAL(pdata,0) ? True : False);
5517 dosmode = dos_mode(conn, smb_fname);
5519 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5520 "delete_on_close = %u\n",
5521 smb_fname_str_dbg(smb_fname),
5522 (unsigned int)dosmode,
5523 (unsigned int)delete_on_close ));
5525 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5527 if (!NT_STATUS_IS_OK(status)) {
5531 /* The set is across all open files on this dev/inode pair. */
5532 if (!set_delete_on_close(fsp, delete_on_close,
5533 &conn->server_info->utok)) {
5534 return NT_STATUS_ACCESS_DENIED;
5536 return NT_STATUS_OK;
5539 /****************************************************************************
5540 Deal with SMB_FILE_POSITION_INFORMATION.
5541 ****************************************************************************/
5543 static NTSTATUS smb_file_position_information(connection_struct *conn,
5548 uint64_t position_information;
5550 if (total_data < 8) {
5551 return NT_STATUS_INVALID_PARAMETER;
5555 /* Ignore on pathname based set. */
5556 return NT_STATUS_OK;
5559 position_information = (uint64_t)IVAL(pdata,0);
5560 #ifdef LARGE_SMB_OFF_T
5561 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5562 #else /* LARGE_SMB_OFF_T */
5563 if (IVAL(pdata,4) != 0) {
5564 /* more than 32 bits? */
5565 return NT_STATUS_INVALID_PARAMETER;
5567 #endif /* LARGE_SMB_OFF_T */
5569 DEBUG(10,("smb_file_position_information: Set file position "
5570 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5571 (double)position_information));
5572 fsp->fh->position_information = position_information;
5573 return NT_STATUS_OK;
5576 /****************************************************************************
5577 Deal with SMB_FILE_MODE_INFORMATION.
5578 ****************************************************************************/
5580 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5586 if (total_data < 4) {
5587 return NT_STATUS_INVALID_PARAMETER;
5589 mode = IVAL(pdata,0);
5590 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5591 return NT_STATUS_INVALID_PARAMETER;
5593 return NT_STATUS_OK;
5596 /****************************************************************************
5597 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5598 ****************************************************************************/
5600 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5601 struct smb_request *req,
5604 const struct smb_filename *smb_fname)
5606 char *link_target = NULL;
5607 const char *newname = smb_fname->base_name;
5608 NTSTATUS status = NT_STATUS_OK;
5609 TALLOC_CTX *ctx = talloc_tos();
5611 /* Set a symbolic link. */
5612 /* Don't allow this if follow links is false. */
5614 if (total_data == 0) {
5615 return NT_STATUS_INVALID_PARAMETER;
5618 if (!lp_symlinks(SNUM(conn))) {
5619 return NT_STATUS_ACCESS_DENIED;
5622 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5623 total_data, STR_TERMINATE);
5626 return NT_STATUS_INVALID_PARAMETER;
5629 /* !widelinks forces the target path to be within the share. */
5630 /* This means we can interpret the target as a pathname. */
5631 if (!lp_widelinks(SNUM(conn))) {
5632 char *rel_name = NULL;
5633 char *last_dirp = NULL;
5635 if (*link_target == '/') {
5636 /* No absolute paths allowed. */
5637 return NT_STATUS_ACCESS_DENIED;
5639 rel_name = talloc_strdup(ctx,newname);
5641 return NT_STATUS_NO_MEMORY;
5643 last_dirp = strrchr_m(rel_name, '/');
5645 last_dirp[1] = '\0';
5647 rel_name = talloc_strdup(ctx,"./");
5649 return NT_STATUS_NO_MEMORY;
5652 rel_name = talloc_asprintf_append(rel_name,
5656 return NT_STATUS_NO_MEMORY;
5659 status = check_name(conn, rel_name);
5660 if (!NT_STATUS_IS_OK(status)) {
5665 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5666 newname, link_target ));
5668 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5669 return map_nt_error_from_unix(errno);
5672 return NT_STATUS_OK;
5675 /****************************************************************************
5676 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5677 ****************************************************************************/
5679 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5680 struct smb_request *req,
5681 const char *pdata, int total_data,
5682 const struct smb_filename *smb_fname_new)
5684 char *oldname = NULL;
5685 struct smb_filename *smb_fname_old = NULL;
5686 TALLOC_CTX *ctx = talloc_tos();
5687 NTSTATUS status = NT_STATUS_OK;
5689 /* Set a hard link. */
5690 if (total_data == 0) {
5691 return NT_STATUS_INVALID_PARAMETER;
5694 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5695 total_data, STR_TERMINATE, &status);
5696 if (!NT_STATUS_IS_OK(status)) {
5700 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5701 smb_fname_str_dbg(smb_fname_new), oldname));
5703 status = filename_convert(ctx,
5705 req->flags2 & FLAGS2_DFS_PATHNAMES,
5710 if (!NT_STATUS_IS_OK(status)) {
5714 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5717 /****************************************************************************
5718 Deal with SMB_FILE_RENAME_INFORMATION.
5719 ****************************************************************************/
5721 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5722 struct smb_request *req,
5726 struct smb_filename *smb_fname_src)
5731 char *newname = NULL;
5732 struct smb_filename *smb_fname_dst = NULL;
5733 bool dest_has_wcard = False;
5734 NTSTATUS status = NT_STATUS_OK;
5736 TALLOC_CTX *ctx = talloc_tos();
5738 if (total_data < 13) {
5739 return NT_STATUS_INVALID_PARAMETER;
5742 overwrite = (CVAL(pdata,0) ? True : False);
5743 root_fid = IVAL(pdata,4);
5744 len = IVAL(pdata,8);
5746 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5747 return NT_STATUS_INVALID_PARAMETER;
5750 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5753 if (!NT_STATUS_IS_OK(status)) {
5757 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5760 status = resolve_dfspath_wcard(ctx, conn,
5761 req->flags2 & FLAGS2_DFS_PATHNAMES,
5765 if (!NT_STATUS_IS_OK(status)) {
5769 /* Check the new name has no '/' characters. */
5770 if (strchr_m(newname, '/')) {
5771 return NT_STATUS_NOT_SUPPORTED;
5774 if (fsp && fsp->base_fsp) {
5775 /* newname must be a stream name. */
5776 if (newname[0] != ':') {
5777 return NT_STATUS_NOT_SUPPORTED;
5780 /* Create an smb_fname to call rename_internals_fsp() with. */
5781 status = create_synthetic_smb_fname(talloc_tos(),
5782 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5784 if (!NT_STATUS_IS_OK(status)) {
5789 * Set the original last component, since
5790 * rename_internals_fsp() requires it.
5792 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5794 if (smb_fname_dst->original_lcomp == NULL) {
5795 status = NT_STATUS_NO_MEMORY;
5801 * Build up an smb_fname_dst based on the filename passed in.
5802 * We basically just strip off the last component, and put on
5803 * the newname instead.
5805 char *base_name = NULL;
5807 /* newname must *not* be a stream name. */
5808 if (newname[0] == ':') {
5809 return NT_STATUS_NOT_SUPPORTED;
5813 * Strip off the last component (filename) of the path passed
5816 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5818 return NT_STATUS_NO_MEMORY;
5820 p = strrchr_m(base_name, '/');
5824 base_name = talloc_strdup(ctx, "./");
5826 return NT_STATUS_NO_MEMORY;
5829 /* Append the new name. */
5830 base_name = talloc_asprintf_append(base_name,
5834 return NT_STATUS_NO_MEMORY;
5837 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5840 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
5843 /* If an error we expect this to be
5844 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5846 if (!NT_STATUS_IS_OK(status)) {
5847 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5851 /* Create an smb_fname to call rename_internals_fsp() */
5852 status = create_synthetic_smb_fname(ctx,
5856 if (!NT_STATUS_IS_OK(status)) {
5863 DEBUG(10,("smb_file_rename_information: "
5864 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5865 fsp->fnum, fsp_str_dbg(fsp),
5866 smb_fname_str_dbg(smb_fname_dst)));
5867 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5870 DEBUG(10,("smb_file_rename_information: "
5871 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5872 smb_fname_str_dbg(smb_fname_src),
5873 smb_fname_str_dbg(smb_fname_dst)));
5874 status = rename_internals(ctx, conn, req, smb_fname_src,
5875 smb_fname_dst, 0, overwrite, false,
5877 FILE_WRITE_ATTRIBUTES);
5880 TALLOC_FREE(smb_fname_dst);
5884 /****************************************************************************
5885 Deal with SMB_SET_POSIX_ACL.
5886 ****************************************************************************/
5888 #if defined(HAVE_POSIX_ACLS)
5889 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5893 const struct smb_filename *smb_fname)
5895 uint16 posix_acl_version;
5896 uint16 num_file_acls;
5897 uint16 num_def_acls;
5898 bool valid_file_acls = True;
5899 bool valid_def_acls = True;
5901 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5902 return NT_STATUS_INVALID_PARAMETER;
5904 posix_acl_version = SVAL(pdata,0);
5905 num_file_acls = SVAL(pdata,2);
5906 num_def_acls = SVAL(pdata,4);
5908 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5909 valid_file_acls = False;
5913 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5914 valid_def_acls = False;
5918 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5919 return NT_STATUS_INVALID_PARAMETER;
5922 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5923 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5924 return NT_STATUS_INVALID_PARAMETER;
5927 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5928 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5929 (unsigned int)num_file_acls,
5930 (unsigned int)num_def_acls));
5932 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5933 smb_fname->base_name, num_file_acls,
5934 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5935 return map_nt_error_from_unix(errno);
5938 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5939 smb_fname->base_name, &smb_fname->st, num_def_acls,
5940 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5941 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5942 return map_nt_error_from_unix(errno);
5944 return NT_STATUS_OK;
5948 /****************************************************************************
5949 Deal with SMB_SET_POSIX_LOCK.
5950 ****************************************************************************/
5952 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5953 struct smb_request *req,
5961 bool blocking_lock = False;
5962 enum brl_type lock_type;
5964 NTSTATUS status = NT_STATUS_OK;
5966 if (fsp == NULL || fsp->fh->fd == -1) {
5967 return NT_STATUS_INVALID_HANDLE;
5970 if (total_data != POSIX_LOCK_DATA_SIZE) {
5971 return NT_STATUS_INVALID_PARAMETER;
5974 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5975 case POSIX_LOCK_TYPE_READ:
5976 lock_type = READ_LOCK;
5978 case POSIX_LOCK_TYPE_WRITE:
5979 /* Return the right POSIX-mappable error code for files opened read-only. */
5980 if (!fsp->can_write) {
5981 return NT_STATUS_INVALID_HANDLE;
5983 lock_type = WRITE_LOCK;
5985 case POSIX_LOCK_TYPE_UNLOCK:
5986 lock_type = UNLOCK_LOCK;
5989 return NT_STATUS_INVALID_PARAMETER;
5992 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5993 blocking_lock = False;
5994 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5995 blocking_lock = True;
5997 return NT_STATUS_INVALID_PARAMETER;
6000 if (!lp_blocking_locks(SNUM(conn))) {
6001 blocking_lock = False;
6004 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6005 #if defined(HAVE_LONGLONG)
6006 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6007 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6008 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6009 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6010 #else /* HAVE_LONGLONG */
6011 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6012 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6013 #endif /* HAVE_LONGLONG */
6015 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6016 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6018 (unsigned int)lock_type,
6019 (unsigned int)lock_pid,
6023 if (lock_type == UNLOCK_LOCK) {
6024 status = do_unlock(smbd_messaging_context(),
6031 uint32 block_smbpid;
6033 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6045 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6047 * A blocking lock was requested. Package up
6048 * this smb into a queued request and push it
6049 * onto the blocking lock queue.
6051 if(push_blocking_lock_request(br_lck,
6054 -1, /* infinite timeout. */
6062 TALLOC_FREE(br_lck);
6066 TALLOC_FREE(br_lck);
6072 /****************************************************************************
6073 Deal with SMB_SET_FILE_BASIC_INFO.
6074 ****************************************************************************/
6076 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6080 const struct smb_filename *smb_fname)
6082 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6083 struct smb_file_time ft;
6085 NTSTATUS status = NT_STATUS_OK;
6089 if (total_data < 36) {
6090 return NT_STATUS_INVALID_PARAMETER;
6093 /* Set the attributes */
6094 dosmode = IVAL(pdata,32);
6095 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6096 if (!NT_STATUS_IS_OK(status)) {
6101 ft.create_time = interpret_long_date(pdata);
6104 ft.atime = interpret_long_date(pdata+8);
6107 ft.mtime = interpret_long_date(pdata+16);
6110 ft.ctime = interpret_long_date(pdata+24);
6112 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6113 smb_fname_str_dbg(smb_fname)));
6115 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6119 /****************************************************************************
6120 Deal with SMB_INFO_STANDARD.
6121 ****************************************************************************/
6123 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6127 const struct smb_filename *smb_fname)
6129 struct smb_file_time ft;
6133 if (total_data < 12) {
6134 return NT_STATUS_INVALID_PARAMETER;
6138 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6140 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6142 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6144 DEBUG(10,("smb_set_info_standard: file %s\n",
6145 smb_fname_str_dbg(smb_fname)));
6147 return smb_set_file_time(conn,
6154 /****************************************************************************
6155 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6156 ****************************************************************************/
6158 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6159 struct smb_request *req,
6163 struct smb_filename *smb_fname)
6165 uint64_t allocation_size = 0;
6166 NTSTATUS status = NT_STATUS_OK;
6167 files_struct *new_fsp = NULL;
6169 if (!VALID_STAT(smb_fname->st)) {
6170 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6173 if (total_data < 8) {
6174 return NT_STATUS_INVALID_PARAMETER;
6177 allocation_size = (uint64_t)IVAL(pdata,0);
6178 #ifdef LARGE_SMB_OFF_T
6179 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6180 #else /* LARGE_SMB_OFF_T */
6181 if (IVAL(pdata,4) != 0) {
6182 /* more than 32 bits? */
6183 return NT_STATUS_INVALID_PARAMETER;
6185 #endif /* LARGE_SMB_OFF_T */
6187 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6188 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6189 (double)allocation_size));
6191 if (allocation_size) {
6192 allocation_size = smb_roundup(conn, allocation_size);
6195 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6196 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6197 (double)allocation_size));
6199 if (fsp && fsp->fh->fd != -1) {
6200 /* Open file handle. */
6201 /* Only change if needed. */
6202 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6203 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6204 return map_nt_error_from_unix(errno);
6207 /* But always update the time. */
6209 * This is equivalent to a write. Ensure it's seen immediately
6210 * if there are no pending writes.
6212 trigger_write_time_update_immediate(fsp);
6213 return NT_STATUS_OK;
6216 /* Pathname or stat or directory file. */
6217 status = SMB_VFS_CREATE_FILE(
6220 0, /* root_dir_fid */
6221 smb_fname, /* fname */
6222 FILE_WRITE_DATA, /* access_mask */
6223 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6225 FILE_OPEN, /* create_disposition*/
6226 0, /* create_options */
6227 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6228 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6229 0, /* allocation_size */
6232 &new_fsp, /* result */
6235 if (!NT_STATUS_IS_OK(status)) {
6236 /* NB. We check for open_was_deferred in the caller. */
6240 /* Only change if needed. */
6241 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6242 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6243 status = map_nt_error_from_unix(errno);
6244 close_file(req, new_fsp, NORMAL_CLOSE);
6249 /* Changing the allocation size should set the last mod time. */
6251 * This is equivalent to a write. Ensure it's seen immediately
6252 * if there are no pending writes.
6254 trigger_write_time_update_immediate(new_fsp);
6256 close_file(req, new_fsp, NORMAL_CLOSE);
6257 return NT_STATUS_OK;
6260 /****************************************************************************
6261 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6262 ****************************************************************************/
6264 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6265 struct smb_request *req,
6269 const struct smb_filename *smb_fname)
6273 if (total_data < 8) {
6274 return NT_STATUS_INVALID_PARAMETER;
6277 size = IVAL(pdata,0);
6278 #ifdef LARGE_SMB_OFF_T
6279 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6280 #else /* LARGE_SMB_OFF_T */
6281 if (IVAL(pdata,4) != 0) {
6282 /* more than 32 bits? */
6283 return NT_STATUS_INVALID_PARAMETER;
6285 #endif /* LARGE_SMB_OFF_T */
6286 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6287 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6290 return smb_set_file_size(conn, req,
6297 /****************************************************************************
6298 Allow a UNIX info mknod.
6299 ****************************************************************************/
6301 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6304 const struct smb_filename *smb_fname)
6306 uint32 file_type = IVAL(pdata,56);
6307 #if defined(HAVE_MAKEDEV)
6308 uint32 dev_major = IVAL(pdata,60);
6309 uint32 dev_minor = IVAL(pdata,68);
6311 SMB_DEV_T dev = (SMB_DEV_T)0;
6312 uint32 raw_unixmode = IVAL(pdata,84);
6316 if (total_data < 100) {
6317 return NT_STATUS_INVALID_PARAMETER;
6320 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6321 PERM_NEW_FILE, &unixmode);
6322 if (!NT_STATUS_IS_OK(status)) {
6326 #if defined(HAVE_MAKEDEV)
6327 dev = makedev(dev_major, dev_minor);
6330 switch (file_type) {
6331 #if defined(S_IFIFO)
6332 case UNIX_TYPE_FIFO:
6333 unixmode |= S_IFIFO;
6336 #if defined(S_IFSOCK)
6337 case UNIX_TYPE_SOCKET:
6338 unixmode |= S_IFSOCK;
6341 #if defined(S_IFCHR)
6342 case UNIX_TYPE_CHARDEV:
6343 unixmode |= S_IFCHR;
6346 #if defined(S_IFBLK)
6347 case UNIX_TYPE_BLKDEV:
6348 unixmode |= S_IFBLK;
6352 return NT_STATUS_INVALID_PARAMETER;
6355 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6356 "%.0f mode 0%o for file %s\n", (double)dev,
6357 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6359 /* Ok - do the mknod. */
6360 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6361 return map_nt_error_from_unix(errno);
6364 /* If any of the other "set" calls fail we
6365 * don't want to end up with a half-constructed mknod.
6368 if (lp_inherit_perms(SNUM(conn))) {
6370 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6372 return NT_STATUS_NO_MEMORY;
6374 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6376 TALLOC_FREE(parent);
6379 return NT_STATUS_OK;
6382 /****************************************************************************
6383 Deal with SMB_SET_FILE_UNIX_BASIC.
6384 ****************************************************************************/
6386 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6387 struct smb_request *req,
6391 const struct smb_filename *smb_fname)
6393 struct smb_file_time ft;
6394 uint32 raw_unixmode;
6397 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6398 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6399 NTSTATUS status = NT_STATUS_OK;
6400 bool delete_on_fail = False;
6401 enum perm_type ptype;
6402 files_struct *all_fsps = NULL;
6403 bool modify_mtime = true;
6405 SMB_STRUCT_STAT sbuf;
6409 if (total_data < 100) {
6410 return NT_STATUS_INVALID_PARAMETER;
6413 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6414 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6415 size=IVAL(pdata,0); /* first 8 Bytes are size */
6416 #ifdef LARGE_SMB_OFF_T
6417 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6418 #else /* LARGE_SMB_OFF_T */
6419 if (IVAL(pdata,4) != 0) {
6420 /* more than 32 bits? */
6421 return NT_STATUS_INVALID_PARAMETER;
6423 #endif /* LARGE_SMB_OFF_T */
6426 ft.atime = interpret_long_date(pdata+24); /* access_time */
6427 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6428 set_owner = (uid_t)IVAL(pdata,40);
6429 set_grp = (gid_t)IVAL(pdata,48);
6430 raw_unixmode = IVAL(pdata,84);
6432 if (VALID_STAT(smb_fname->st)) {
6433 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6434 ptype = PERM_EXISTING_DIR;
6436 ptype = PERM_EXISTING_FILE;
6439 ptype = PERM_NEW_FILE;
6442 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6444 if (!NT_STATUS_IS_OK(status)) {
6448 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6449 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6450 smb_fname_str_dbg(smb_fname), (double)size,
6451 (unsigned int)set_owner, (unsigned int)set_grp,
6452 (int)raw_unixmode));
6454 sbuf = smb_fname->st;
6456 if (!VALID_STAT(sbuf)) {
6457 struct smb_filename *smb_fname_tmp = NULL;
6459 * The only valid use of this is to create character and block
6460 * devices, and named pipes. This is deprecated (IMHO) and
6461 * a new info level should be used for mknod. JRA.
6464 status = smb_unix_mknod(conn,
6468 if (!NT_STATUS_IS_OK(status)) {
6472 status = copy_smb_filename(talloc_tos(), smb_fname,
6474 if (!NT_STATUS_IS_OK(status)) {
6478 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6479 status = map_nt_error_from_unix(errno);
6480 TALLOC_FREE(smb_fname_tmp);
6481 SMB_VFS_UNLINK(conn, smb_fname);
6485 sbuf = smb_fname_tmp->st;
6486 TALLOC_FREE(smb_fname_tmp);
6488 /* Ensure we don't try and change anything else. */
6489 raw_unixmode = SMB_MODE_NO_CHANGE;
6490 size = get_file_size_stat(&sbuf);
6491 ft.atime = sbuf.st_ex_atime;
6492 ft.mtime = sbuf.st_ex_mtime;
6494 * We continue here as we might want to change the
6497 delete_on_fail = True;
6501 /* Horrible backwards compatibility hack as an old server bug
6502 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6506 size = get_file_size_stat(&sbuf);
6511 * Deal with the UNIX specific mode set.
6514 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6515 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6516 "setting mode 0%o for file %s\n",
6517 (unsigned int)unixmode,
6518 smb_fname_str_dbg(smb_fname)));
6519 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6520 return map_nt_error_from_unix(errno);
6525 * Deal with the UNIX specific uid set.
6528 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6529 (sbuf.st_ex_uid != set_owner)) {
6532 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6533 "changing owner %u for path %s\n",
6534 (unsigned int)set_owner,
6535 smb_fname_str_dbg(smb_fname)));
6537 if (S_ISLNK(sbuf.st_ex_mode)) {
6538 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6539 set_owner, (gid_t)-1);
6541 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6542 set_owner, (gid_t)-1);
6546 status = map_nt_error_from_unix(errno);
6547 if (delete_on_fail) {
6548 SMB_VFS_UNLINK(conn, smb_fname);
6555 * Deal with the UNIX specific gid set.
6558 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6559 (sbuf.st_ex_gid != set_grp)) {
6560 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6561 "changing group %u for file %s\n",
6562 (unsigned int)set_owner,
6563 smb_fname_str_dbg(smb_fname)));
6564 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6566 status = map_nt_error_from_unix(errno);
6567 if (delete_on_fail) {
6568 SMB_VFS_UNLINK(conn, smb_fname);
6574 /* Deal with any size changes. */
6576 status = smb_set_file_size(conn, req,
6581 if (!NT_STATUS_IS_OK(status)) {
6585 /* Deal with any time changes. */
6586 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6587 /* No change, don't cancel anything. */
6591 id = vfs_file_id_from_sbuf(conn, &sbuf);
6592 for(all_fsps = file_find_di_first(id); all_fsps;
6593 all_fsps = file_find_di_next(all_fsps)) {
6595 * We're setting the time explicitly for UNIX.
6596 * Cancel any pending changes over all handles.
6598 all_fsps->update_write_time_on_close = false;
6599 TALLOC_FREE(all_fsps->update_write_time_event);
6603 * Override the "setting_write_time"
6604 * parameter here as it almost does what
6605 * we need. Just remember if we modified
6606 * mtime and send the notify ourselves.
6608 if (null_timespec(ft.mtime)) {
6609 modify_mtime = false;
6612 status = smb_set_file_time(conn,
6618 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6619 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6624 /****************************************************************************
6625 Deal with SMB_SET_FILE_UNIX_INFO2.
6626 ****************************************************************************/
6628 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6629 struct smb_request *req,
6633 const struct smb_filename *smb_fname)
6639 if (total_data < 116) {
6640 return NT_STATUS_INVALID_PARAMETER;
6643 /* Start by setting all the fields that are common between UNIX_BASIC
6646 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6648 if (!NT_STATUS_IS_OK(status)) {
6652 smb_fflags = IVAL(pdata, 108);
6653 smb_fmask = IVAL(pdata, 112);
6655 /* NB: We should only attempt to alter the file flags if the client
6656 * sends a non-zero mask.
6658 if (smb_fmask != 0) {
6659 int stat_fflags = 0;
6661 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6662 smb_fmask, &stat_fflags)) {
6663 /* Client asked to alter a flag we don't understand. */
6664 return NT_STATUS_INVALID_PARAMETER;
6667 if (fsp && fsp->fh->fd != -1) {
6668 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6669 return NT_STATUS_NOT_SUPPORTED;
6671 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6672 stat_fflags) != 0) {
6673 return map_nt_error_from_unix(errno);
6678 /* XXX: need to add support for changing the create_time here. You
6679 * can do this for paths on Darwin with setattrlist(2). The right way
6680 * to hook this up is probably by extending the VFS utimes interface.
6683 return NT_STATUS_OK;
6686 /****************************************************************************
6687 Create a directory with POSIX semantics.
6688 ****************************************************************************/
6690 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6691 struct smb_request *req,
6694 struct smb_filename *smb_fname,
6695 int *pdata_return_size)
6697 NTSTATUS status = NT_STATUS_OK;
6698 uint32 raw_unixmode = 0;
6699 uint32 mod_unixmode = 0;
6700 mode_t unixmode = (mode_t)0;
6701 files_struct *fsp = NULL;
6702 uint16 info_level_return = 0;
6704 char *pdata = *ppdata;
6706 if (total_data < 18) {
6707 return NT_STATUS_INVALID_PARAMETER;
6710 raw_unixmode = IVAL(pdata,8);
6711 /* Next 4 bytes are not yet defined. */
6713 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6714 PERM_NEW_DIR, &unixmode);
6715 if (!NT_STATUS_IS_OK(status)) {
6719 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6721 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6722 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6724 status = SMB_VFS_CREATE_FILE(
6727 0, /* root_dir_fid */
6728 smb_fname, /* fname */
6729 FILE_READ_ATTRIBUTES, /* access_mask */
6730 FILE_SHARE_NONE, /* share_access */
6731 FILE_CREATE, /* create_disposition*/
6732 FILE_DIRECTORY_FILE, /* create_options */
6733 mod_unixmode, /* file_attributes */
6734 0, /* oplock_request */
6735 0, /* allocation_size */
6741 if (NT_STATUS_IS_OK(status)) {
6742 close_file(req, fsp, NORMAL_CLOSE);
6745 info_level_return = SVAL(pdata,16);
6747 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6748 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6749 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6750 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6752 *pdata_return_size = 12;
6755 /* Realloc the data size */
6756 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6757 if (*ppdata == NULL) {
6758 *pdata_return_size = 0;
6759 return NT_STATUS_NO_MEMORY;
6763 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6764 SSVAL(pdata,2,0); /* No fnum. */
6765 SIVAL(pdata,4,info); /* Was directory created. */
6767 switch (info_level_return) {
6768 case SMB_QUERY_FILE_UNIX_BASIC:
6769 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6770 SSVAL(pdata,10,0); /* Padding. */
6771 store_file_unix_basic(conn, pdata + 12, fsp,
6774 case SMB_QUERY_FILE_UNIX_INFO2:
6775 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6776 SSVAL(pdata,10,0); /* Padding. */
6777 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6781 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6782 SSVAL(pdata,10,0); /* Padding. */
6789 /****************************************************************************
6790 Open/Create a file with POSIX semantics.
6791 ****************************************************************************/
6793 static NTSTATUS smb_posix_open(connection_struct *conn,
6794 struct smb_request *req,
6797 struct smb_filename *smb_fname,
6798 int *pdata_return_size)
6800 bool extended_oplock_granted = False;
6801 char *pdata = *ppdata;
6803 uint32 wire_open_mode = 0;
6804 uint32 raw_unixmode = 0;
6805 uint32 mod_unixmode = 0;
6806 uint32 create_disp = 0;
6807 uint32 access_mask = 0;
6808 uint32 create_options = 0;
6809 NTSTATUS status = NT_STATUS_OK;
6810 mode_t unixmode = (mode_t)0;
6811 files_struct *fsp = NULL;
6812 int oplock_request = 0;
6814 uint16 info_level_return = 0;
6816 if (total_data < 18) {
6817 return NT_STATUS_INVALID_PARAMETER;
6820 flags = IVAL(pdata,0);
6821 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6822 if (oplock_request) {
6823 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6826 wire_open_mode = IVAL(pdata,4);
6828 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6829 return smb_posix_mkdir(conn, req,
6836 switch (wire_open_mode & SMB_ACCMODE) {
6838 access_mask = FILE_READ_DATA;
6841 access_mask = FILE_WRITE_DATA;
6844 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6847 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6848 (unsigned int)wire_open_mode ));
6849 return NT_STATUS_INVALID_PARAMETER;
6852 wire_open_mode &= ~SMB_ACCMODE;
6854 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6855 create_disp = FILE_CREATE;
6856 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6857 create_disp = FILE_OVERWRITE_IF;
6858 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6859 create_disp = FILE_OPEN_IF;
6860 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6861 create_disp = FILE_OPEN;
6863 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6864 (unsigned int)wire_open_mode ));
6865 return NT_STATUS_INVALID_PARAMETER;
6868 raw_unixmode = IVAL(pdata,8);
6869 /* Next 4 bytes are not yet defined. */
6871 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6872 (VALID_STAT(smb_fname->st) ?
6873 PERM_EXISTING_FILE : PERM_NEW_FILE),
6876 if (!NT_STATUS_IS_OK(status)) {
6880 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6882 if (wire_open_mode & SMB_O_SYNC) {
6883 create_options |= FILE_WRITE_THROUGH;
6885 if (wire_open_mode & SMB_O_APPEND) {
6886 access_mask |= FILE_APPEND_DATA;
6888 if (wire_open_mode & SMB_O_DIRECT) {
6889 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6892 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6893 smb_fname_str_dbg(smb_fname),
6894 (unsigned int)wire_open_mode,
6895 (unsigned int)unixmode ));
6897 status = SMB_VFS_CREATE_FILE(
6900 0, /* root_dir_fid */
6901 smb_fname, /* fname */
6902 access_mask, /* access_mask */
6903 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6905 create_disp, /* create_disposition*/
6906 FILE_NON_DIRECTORY_FILE, /* create_options */
6907 mod_unixmode, /* file_attributes */
6908 oplock_request, /* oplock_request */
6909 0, /* allocation_size */
6915 if (!NT_STATUS_IS_OK(status)) {
6919 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6920 extended_oplock_granted = True;
6923 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6924 extended_oplock_granted = True;
6927 info_level_return = SVAL(pdata,16);
6929 /* Allocate the correct return size. */
6931 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6932 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6933 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6934 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6936 *pdata_return_size = 12;
6939 /* Realloc the data size */
6940 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6941 if (*ppdata == NULL) {
6942 close_file(req, fsp, ERROR_CLOSE);
6943 *pdata_return_size = 0;
6944 return NT_STATUS_NO_MEMORY;
6948 if (extended_oplock_granted) {
6949 if (flags & REQUEST_BATCH_OPLOCK) {
6950 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6952 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6954 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6955 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6957 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6960 SSVAL(pdata,2,fsp->fnum);
6961 SIVAL(pdata,4,info); /* Was file created etc. */
6963 switch (info_level_return) {
6964 case SMB_QUERY_FILE_UNIX_BASIC:
6965 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6966 SSVAL(pdata,10,0); /* padding. */
6967 store_file_unix_basic(conn, pdata + 12, fsp,
6970 case SMB_QUERY_FILE_UNIX_INFO2:
6971 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6972 SSVAL(pdata,10,0); /* padding. */
6973 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6977 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6978 SSVAL(pdata,10,0); /* padding. */
6981 return NT_STATUS_OK;
6984 /****************************************************************************
6985 Delete a file with POSIX semantics.
6986 ****************************************************************************/
6988 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6989 struct smb_request *req,
6992 struct smb_filename *smb_fname)
6994 NTSTATUS status = NT_STATUS_OK;
6995 files_struct *fsp = NULL;
6999 int create_options = 0;
7001 struct share_mode_lock *lck = NULL;
7003 if (total_data < 2) {
7004 return NT_STATUS_INVALID_PARAMETER;
7007 flags = SVAL(pdata,0);
7009 if (!VALID_STAT(smb_fname->st)) {
7010 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7013 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7014 !VALID_STAT_OF_DIR(smb_fname->st)) {
7015 return NT_STATUS_NOT_A_DIRECTORY;
7018 DEBUG(10,("smb_posix_unlink: %s %s\n",
7019 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7020 smb_fname_str_dbg(smb_fname)));
7022 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7023 create_options |= FILE_DIRECTORY_FILE;
7026 status = SMB_VFS_CREATE_FILE(
7029 0, /* root_dir_fid */
7030 smb_fname, /* fname */
7031 DELETE_ACCESS, /* access_mask */
7032 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7034 FILE_OPEN, /* create_disposition*/
7035 create_options, /* create_options */
7036 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7037 0, /* oplock_request */
7038 0, /* allocation_size */
7044 if (!NT_STATUS_IS_OK(status)) {
7049 * Don't lie to client. If we can't really delete due to
7050 * non-POSIX opens return SHARING_VIOLATION.
7053 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7056 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7057 "lock for file %s\n", fsp_str_dbg(fsp)));
7058 close_file(req, fsp, NORMAL_CLOSE);
7059 return NT_STATUS_INVALID_PARAMETER;
7063 * See if others still have the file open. If this is the case, then
7064 * don't delete. If all opens are POSIX delete we can set the delete
7065 * on close disposition.
7067 for (i=0; i<lck->num_share_modes; i++) {
7068 struct share_mode_entry *e = &lck->share_modes[i];
7069 if (is_valid_share_mode_entry(e)) {
7070 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7073 /* Fail with sharing violation. */
7074 close_file(req, fsp, NORMAL_CLOSE);
7076 return NT_STATUS_SHARING_VIOLATION;
7081 * Set the delete on close.
7083 status = smb_set_file_disposition_info(conn,
7089 if (!NT_STATUS_IS_OK(status)) {
7090 close_file(req, fsp, NORMAL_CLOSE);
7095 return close_file(req, fsp, NORMAL_CLOSE);
7098 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7099 struct smb_request *req,
7100 TALLOC_CTX *mem_ctx,
7101 uint16_t info_level,
7103 struct smb_filename *smb_fname,
7104 char **ppdata, int total_data,
7107 char *pdata = *ppdata;
7108 NTSTATUS status = NT_STATUS_OK;
7109 int data_return_size = 0;
7113 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7114 return NT_STATUS_INVALID_LEVEL;
7117 if (!CAN_WRITE(conn)) {
7118 /* Allow POSIX opens. The open path will deny
7119 * any non-readonly opens. */
7120 if (info_level != SMB_POSIX_PATH_OPEN) {
7121 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7125 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7126 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7127 fsp ? fsp->fnum : -1, info_level, total_data));
7129 switch (info_level) {
7131 case SMB_INFO_STANDARD:
7133 status = smb_set_info_standard(conn,
7141 case SMB_INFO_SET_EA:
7143 status = smb_info_set_ea(conn,
7151 case SMB_SET_FILE_BASIC_INFO:
7152 case SMB_FILE_BASIC_INFORMATION:
7154 status = smb_set_file_basic_info(conn,
7162 case SMB_FILE_ALLOCATION_INFORMATION:
7163 case SMB_SET_FILE_ALLOCATION_INFO:
7165 status = smb_set_file_allocation_info(conn, req,
7173 case SMB_FILE_END_OF_FILE_INFORMATION:
7174 case SMB_SET_FILE_END_OF_FILE_INFO:
7176 status = smb_set_file_end_of_file_info(conn, req,
7184 case SMB_FILE_DISPOSITION_INFORMATION:
7185 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7188 /* JRA - We used to just ignore this on a path ?
7189 * Shouldn't this be invalid level on a pathname
7192 if (tran_call != TRANSACT2_SETFILEINFO) {
7193 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7196 status = smb_set_file_disposition_info(conn,
7204 case SMB_FILE_POSITION_INFORMATION:
7206 status = smb_file_position_information(conn,
7213 /* From tridge Samba4 :
7214 * MODE_INFORMATION in setfileinfo (I have no
7215 * idea what "mode information" on a file is - it takes a value of 0,
7216 * 2, 4 or 6. What could it be?).
7219 case SMB_FILE_MODE_INFORMATION:
7221 status = smb_file_mode_information(conn,
7228 * CIFS UNIX extensions.
7231 case SMB_SET_FILE_UNIX_BASIC:
7233 status = smb_set_file_unix_basic(conn, req,
7241 case SMB_SET_FILE_UNIX_INFO2:
7243 status = smb_set_file_unix_info2(conn, req,
7251 case SMB_SET_FILE_UNIX_LINK:
7254 /* We must have a pathname for this. */
7255 return NT_STATUS_INVALID_LEVEL;
7257 status = smb_set_file_unix_link(conn, req, pdata,
7258 total_data, smb_fname);
7262 case SMB_SET_FILE_UNIX_HLINK:
7265 /* We must have a pathname for this. */
7266 return NT_STATUS_INVALID_LEVEL;
7268 status = smb_set_file_unix_hlink(conn, req,
7274 case SMB_FILE_RENAME_INFORMATION:
7276 status = smb_file_rename_information(conn, req,
7282 #if defined(HAVE_POSIX_ACLS)
7283 case SMB_SET_POSIX_ACL:
7285 status = smb_set_posix_acl(conn,
7294 case SMB_SET_POSIX_LOCK:
7297 return NT_STATUS_INVALID_LEVEL;
7299 status = smb_set_posix_lock(conn, req,
7300 pdata, total_data, fsp);
7304 case SMB_POSIX_PATH_OPEN:
7307 /* We must have a pathname for this. */
7308 return NT_STATUS_INVALID_LEVEL;
7311 status = smb_posix_open(conn, req,
7319 case SMB_POSIX_PATH_UNLINK:
7322 /* We must have a pathname for this. */
7323 return NT_STATUS_INVALID_LEVEL;
7326 status = smb_posix_unlink(conn, req,
7334 return NT_STATUS_INVALID_LEVEL;
7337 if (!NT_STATUS_IS_OK(status)) {
7341 *ret_data_size = data_return_size;
7342 return NT_STATUS_OK;
7345 /****************************************************************************
7346 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7347 ****************************************************************************/
7349 static void call_trans2setfilepathinfo(connection_struct *conn,
7350 struct smb_request *req,
7351 unsigned int tran_call,
7352 char **pparams, int total_params,
7353 char **ppdata, int total_data,
7354 unsigned int max_data_bytes)
7356 char *params = *pparams;
7357 char *pdata = *ppdata;
7359 struct smb_filename *smb_fname = NULL;
7360 files_struct *fsp = NULL;
7361 NTSTATUS status = NT_STATUS_OK;
7362 int data_return_size = 0;
7365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7369 if (tran_call == TRANSACT2_SETFILEINFO) {
7370 if (total_params < 4) {
7371 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7375 fsp = file_fsp(req, SVAL(params,0));
7376 /* Basic check for non-null fsp. */
7377 if (!check_fsp_open(conn, req, fsp)) {
7380 info_level = SVAL(params,2);
7382 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7384 if (!NT_STATUS_IS_OK(status)) {
7385 reply_nterror(req, status);
7389 if(fsp->is_directory || fsp->fh->fd == -1) {
7391 * This is actually a SETFILEINFO on a directory
7392 * handle (returned from an NT SMB). NT5.0 seems
7393 * to do this call. JRA.
7395 if (INFO_LEVEL_IS_UNIX(info_level)) {
7396 /* Always do lstat for UNIX calls. */
7397 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7398 DEBUG(3,("call_trans2setfilepathinfo: "
7399 "SMB_VFS_LSTAT of %s failed "
7401 smb_fname_str_dbg(smb_fname),
7403 reply_nterror(req, map_nt_error_from_unix(errno));
7407 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7408 DEBUG(3,("call_trans2setfilepathinfo: "
7409 "fileinfo of %s failed (%s)\n",
7410 smb_fname_str_dbg(smb_fname),
7412 reply_nterror(req, map_nt_error_from_unix(errno));
7416 } else if (fsp->print_file) {
7418 * Doing a DELETE_ON_CLOSE should cancel a print job.
7420 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7421 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7423 DEBUG(3,("call_trans2setfilepathinfo: "
7424 "Cancelling print job (%s)\n",
7428 send_trans2_replies(conn, req, params, 2,
7433 reply_doserror(req, ERRDOS, ERRbadpath);
7438 * Original code - this is an open file.
7440 if (!check_fsp(conn, req, fsp)) {
7444 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7445 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7446 "of fnum %d failed (%s)\n", fsp->fnum,
7448 reply_nterror(req, map_nt_error_from_unix(errno));
7456 if (total_params < 7) {
7457 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7461 info_level = SVAL(params,0);
7462 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7463 total_params - 6, STR_TERMINATE,
7465 if (!NT_STATUS_IS_OK(status)) {
7466 reply_nterror(req, status);
7470 status = filename_convert(req, conn,
7471 req->flags2 & FLAGS2_DFS_PATHNAMES,
7476 if (!NT_STATUS_IS_OK(status)) {
7477 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7478 reply_botherror(req,
7479 NT_STATUS_PATH_NOT_COVERED,
7480 ERRSRV, ERRbadpath);
7483 reply_nterror(req, status);
7487 if (INFO_LEVEL_IS_UNIX(info_level)) {
7489 * For CIFS UNIX extensions the target name may not exist.
7492 /* Always do lstat for UNIX calls. */
7493 SMB_VFS_LSTAT(conn, smb_fname);
7495 } else if (!VALID_STAT(smb_fname->st) &&
7496 SMB_VFS_STAT(conn, smb_fname)) {
7497 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7499 smb_fname_str_dbg(smb_fname),
7501 reply_nterror(req, map_nt_error_from_unix(errno));
7506 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7507 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7508 fsp ? fsp->fnum : -1, info_level,total_data));
7510 /* Realloc the parameter size */
7511 *pparams = (char *)SMB_REALLOC(*pparams,2);
7512 if (*pparams == NULL) {
7513 reply_nterror(req, NT_STATUS_NO_MEMORY);
7520 status = smbd_do_setfilepathinfo(conn, req, req,
7526 if (!NT_STATUS_IS_OK(status)) {
7527 if (open_was_deferred(req->mid)) {
7528 /* We have re-scheduled this call. */
7531 if (blocking_lock_was_deferred(req->mid)) {
7532 /* We have re-scheduled this call. */
7535 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7536 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7537 ERRSRV, ERRbadpath);
7540 if (info_level == SMB_POSIX_PATH_OPEN) {
7541 reply_openerror(req, status);
7545 reply_nterror(req, status);
7549 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7555 /****************************************************************************
7556 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7557 ****************************************************************************/
7559 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7560 char **pparams, int total_params,
7561 char **ppdata, int total_data,
7562 unsigned int max_data_bytes)
7564 struct smb_filename *smb_dname = NULL;
7565 char *params = *pparams;
7566 char *pdata = *ppdata;
7567 char *directory = NULL;
7568 NTSTATUS status = NT_STATUS_OK;
7569 struct ea_list *ea_list = NULL;
7570 TALLOC_CTX *ctx = talloc_tos();
7572 if (!CAN_WRITE(conn)) {
7573 reply_doserror(req, ERRSRV, ERRaccess);
7577 if (total_params < 5) {
7578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7582 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7583 total_params - 4, STR_TERMINATE,
7585 if (!NT_STATUS_IS_OK(status)) {
7586 reply_nterror(req, status);
7590 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7592 status = filename_convert(ctx,
7594 req->flags2 & FLAGS2_DFS_PATHNAMES,
7600 if (!NT_STATUS_IS_OK(status)) {
7601 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7602 reply_botherror(req,
7603 NT_STATUS_PATH_NOT_COVERED,
7604 ERRSRV, ERRbadpath);
7607 reply_nterror(req, status);
7611 /* Any data in this call is an EA list. */
7612 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7613 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7618 * OS/2 workplace shell seems to send SET_EA requests of "null"
7619 * length (4 bytes containing IVAL 4).
7620 * They seem to have no effect. Bug #3212. JRA.
7623 if (total_data != 4) {
7624 if (total_data < 10) {
7625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7629 if (IVAL(pdata,0) > total_data) {
7630 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7631 IVAL(pdata,0), (unsigned int)total_data));
7632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7636 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7643 /* If total_data == 4 Windows doesn't care what values
7644 * are placed in that field, it just ignores them.
7645 * The System i QNTC IBM SMB client puts bad values here,
7646 * so ignore them. */
7648 status = create_directory(conn, req, smb_dname);
7650 if (!NT_STATUS_IS_OK(status)) {
7651 reply_nterror(req, status);
7655 /* Try and set any given EA. */
7657 status = set_ea(conn, NULL, smb_dname, ea_list);
7658 if (!NT_STATUS_IS_OK(status)) {
7659 reply_nterror(req, status);
7664 /* Realloc the parameter and data sizes */
7665 *pparams = (char *)SMB_REALLOC(*pparams,2);
7666 if(*pparams == NULL) {
7667 reply_nterror(req, NT_STATUS_NO_MEMORY);
7674 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7677 TALLOC_FREE(smb_dname);
7681 /****************************************************************************
7682 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7683 We don't actually do this - we just send a null response.
7684 ****************************************************************************/
7686 static void call_trans2findnotifyfirst(connection_struct *conn,
7687 struct smb_request *req,
7688 char **pparams, int total_params,
7689 char **ppdata, int total_data,
7690 unsigned int max_data_bytes)
7692 char *params = *pparams;
7695 if (total_params < 6) {
7696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7700 info_level = SVAL(params,4);
7701 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7703 switch (info_level) {
7708 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7712 /* Realloc the parameter and data sizes */
7713 *pparams = (char *)SMB_REALLOC(*pparams,6);
7714 if (*pparams == NULL) {
7715 reply_nterror(req, NT_STATUS_NO_MEMORY);
7720 SSVAL(params,0,fnf_handle);
7721 SSVAL(params,2,0); /* No changes */
7722 SSVAL(params,4,0); /* No EA errors */
7729 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7734 /****************************************************************************
7735 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7736 changes). Currently this does nothing.
7737 ****************************************************************************/
7739 static void call_trans2findnotifynext(connection_struct *conn,
7740 struct smb_request *req,
7741 char **pparams, int total_params,
7742 char **ppdata, int total_data,
7743 unsigned int max_data_bytes)
7745 char *params = *pparams;
7747 DEBUG(3,("call_trans2findnotifynext\n"));
7749 /* Realloc the parameter and data sizes */
7750 *pparams = (char *)SMB_REALLOC(*pparams,4);
7751 if (*pparams == NULL) {
7752 reply_nterror(req, NT_STATUS_NO_MEMORY);
7757 SSVAL(params,0,0); /* No changes */
7758 SSVAL(params,2,0); /* No EA errors */
7760 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7765 /****************************************************************************
7766 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7767 ****************************************************************************/
7769 static void call_trans2getdfsreferral(connection_struct *conn,
7770 struct smb_request *req,
7771 char **pparams, int total_params,
7772 char **ppdata, int total_data,
7773 unsigned int max_data_bytes)
7775 char *params = *pparams;
7776 char *pathname = NULL;
7778 int max_referral_level;
7779 NTSTATUS status = NT_STATUS_OK;
7780 TALLOC_CTX *ctx = talloc_tos();
7782 DEBUG(10,("call_trans2getdfsreferral\n"));
7784 if (total_params < 3) {
7785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7789 max_referral_level = SVAL(params,0);
7791 if(!lp_host_msdfs()) {
7792 reply_doserror(req, ERRDOS, ERRbadfunc);
7796 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7797 total_params - 2, STR_TERMINATE);
7799 reply_nterror(req, NT_STATUS_NOT_FOUND);
7802 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7803 ppdata,&status)) < 0) {
7804 reply_nterror(req, status);
7808 SSVAL(req->inbuf, smb_flg2,
7809 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7810 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7815 #define LMCAT_SPL 0x53
7816 #define LMFUNC_GETJOBID 0x60
7818 /****************************************************************************
7819 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7820 ****************************************************************************/
7822 static void call_trans2ioctl(connection_struct *conn,
7823 struct smb_request *req,
7824 char **pparams, int total_params,
7825 char **ppdata, int total_data,
7826 unsigned int max_data_bytes)
7828 char *pdata = *ppdata;
7829 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7831 /* check for an invalid fid before proceeding */
7834 reply_doserror(req, ERRDOS, ERRbadfid);
7838 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7839 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7840 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7841 if (*ppdata == NULL) {
7842 reply_nterror(req, NT_STATUS_NO_MEMORY);
7847 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7848 CAN ACCEPT THIS IN UNICODE. JRA. */
7850 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7851 srvstr_push(pdata, req->flags2, pdata + 2,
7852 global_myname(), 15,
7853 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7854 srvstr_push(pdata, req->flags2, pdata+18,
7855 lp_servicename(SNUM(conn)), 13,
7856 STR_ASCII|STR_TERMINATE); /* Service name */
7857 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7862 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7863 reply_doserror(req, ERRSRV, ERRerror);
7866 /****************************************************************************
7867 Reply to a SMBfindclose (stop trans2 directory search).
7868 ****************************************************************************/
7870 void reply_findclose(struct smb_request *req)
7873 struct smbd_server_connection *sconn = smbd_server_conn;
7875 START_PROFILE(SMBfindclose);
7878 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7879 END_PROFILE(SMBfindclose);
7883 dptr_num = SVALS(req->vwv+0, 0);
7885 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7887 dptr_close(sconn, &dptr_num);
7889 reply_outbuf(req, 0, 0);
7891 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7893 END_PROFILE(SMBfindclose);
7897 /****************************************************************************
7898 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7899 ****************************************************************************/
7901 void reply_findnclose(struct smb_request *req)
7905 START_PROFILE(SMBfindnclose);
7908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7909 END_PROFILE(SMBfindnclose);
7913 dptr_num = SVAL(req->vwv+0, 0);
7915 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7917 /* We never give out valid handles for a
7918 findnotifyfirst - so any dptr_num is ok here.
7921 reply_outbuf(req, 0, 0);
7923 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7925 END_PROFILE(SMBfindnclose);
7929 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7930 struct trans_state *state)
7932 if (Protocol >= PROTOCOL_NT1) {
7933 req->flags2 |= 0x40; /* IS_LONG_NAME */
7934 SSVAL(req->inbuf,smb_flg2,req->flags2);
7937 if (conn->encrypt_level == Required && !req->encrypted) {
7938 if (state->call != TRANSACT2_QFSINFO &&
7939 state->call != TRANSACT2_SETFSINFO) {
7940 DEBUG(0,("handle_trans2: encryption required "
7942 (unsigned int)state->call));
7943 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7948 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7950 /* Now we must call the relevant TRANS2 function */
7951 switch(state->call) {
7952 case TRANSACT2_OPEN:
7954 START_PROFILE(Trans2_open);
7955 call_trans2open(conn, req,
7956 &state->param, state->total_param,
7957 &state->data, state->total_data,
7958 state->max_data_return);
7959 END_PROFILE(Trans2_open);
7963 case TRANSACT2_FINDFIRST:
7965 START_PROFILE(Trans2_findfirst);
7966 call_trans2findfirst(conn, req,
7967 &state->param, state->total_param,
7968 &state->data, state->total_data,
7969 state->max_data_return);
7970 END_PROFILE(Trans2_findfirst);
7974 case TRANSACT2_FINDNEXT:
7976 START_PROFILE(Trans2_findnext);
7977 call_trans2findnext(conn, req,
7978 &state->param, state->total_param,
7979 &state->data, state->total_data,
7980 state->max_data_return);
7981 END_PROFILE(Trans2_findnext);
7985 case TRANSACT2_QFSINFO:
7987 START_PROFILE(Trans2_qfsinfo);
7988 call_trans2qfsinfo(conn, req,
7989 &state->param, state->total_param,
7990 &state->data, state->total_data,
7991 state->max_data_return);
7992 END_PROFILE(Trans2_qfsinfo);
7996 case TRANSACT2_SETFSINFO:
7998 START_PROFILE(Trans2_setfsinfo);
7999 call_trans2setfsinfo(conn, req,
8000 &state->param, state->total_param,
8001 &state->data, state->total_data,
8002 state->max_data_return);
8003 END_PROFILE(Trans2_setfsinfo);
8007 case TRANSACT2_QPATHINFO:
8008 case TRANSACT2_QFILEINFO:
8010 START_PROFILE(Trans2_qpathinfo);
8011 call_trans2qfilepathinfo(conn, req, state->call,
8012 &state->param, state->total_param,
8013 &state->data, state->total_data,
8014 state->max_data_return);
8015 END_PROFILE(Trans2_qpathinfo);
8019 case TRANSACT2_SETPATHINFO:
8020 case TRANSACT2_SETFILEINFO:
8022 START_PROFILE(Trans2_setpathinfo);
8023 call_trans2setfilepathinfo(conn, req, state->call,
8024 &state->param, state->total_param,
8025 &state->data, state->total_data,
8026 state->max_data_return);
8027 END_PROFILE(Trans2_setpathinfo);
8031 case TRANSACT2_FINDNOTIFYFIRST:
8033 START_PROFILE(Trans2_findnotifyfirst);
8034 call_trans2findnotifyfirst(conn, req,
8035 &state->param, state->total_param,
8036 &state->data, state->total_data,
8037 state->max_data_return);
8038 END_PROFILE(Trans2_findnotifyfirst);
8042 case TRANSACT2_FINDNOTIFYNEXT:
8044 START_PROFILE(Trans2_findnotifynext);
8045 call_trans2findnotifynext(conn, req,
8046 &state->param, state->total_param,
8047 &state->data, state->total_data,
8048 state->max_data_return);
8049 END_PROFILE(Trans2_findnotifynext);
8053 case TRANSACT2_MKDIR:
8055 START_PROFILE(Trans2_mkdir);
8056 call_trans2mkdir(conn, req,
8057 &state->param, state->total_param,
8058 &state->data, state->total_data,
8059 state->max_data_return);
8060 END_PROFILE(Trans2_mkdir);
8064 case TRANSACT2_GET_DFS_REFERRAL:
8066 START_PROFILE(Trans2_get_dfs_referral);
8067 call_trans2getdfsreferral(conn, req,
8068 &state->param, state->total_param,
8069 &state->data, state->total_data,
8070 state->max_data_return);
8071 END_PROFILE(Trans2_get_dfs_referral);
8075 case TRANSACT2_IOCTL:
8077 START_PROFILE(Trans2_ioctl);
8078 call_trans2ioctl(conn, req,
8079 &state->param, state->total_param,
8080 &state->data, state->total_data,
8081 state->max_data_return);
8082 END_PROFILE(Trans2_ioctl);
8087 /* Error in request */
8088 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8089 reply_doserror(req, ERRSRV,ERRerror);
8093 /****************************************************************************
8094 Reply to a SMBtrans2.
8095 ****************************************************************************/
8097 void reply_trans2(struct smb_request *req)
8099 connection_struct *conn = req->conn;
8104 unsigned int tran_call;
8105 struct trans_state *state;
8108 START_PROFILE(SMBtrans2);
8110 if (req->wct < 14) {
8111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8112 END_PROFILE(SMBtrans2);
8116 dsoff = SVAL(req->vwv+12, 0);
8117 dscnt = SVAL(req->vwv+11, 0);
8118 psoff = SVAL(req->vwv+10, 0);
8119 pscnt = SVAL(req->vwv+9, 0);
8120 tran_call = SVAL(req->vwv+14, 0);
8122 result = allow_new_trans(conn->pending_trans, req->mid);
8123 if (!NT_STATUS_IS_OK(result)) {
8124 DEBUG(2, ("Got invalid trans2 request: %s\n",
8125 nt_errstr(result)));
8126 reply_nterror(req, result);
8127 END_PROFILE(SMBtrans2);
8132 switch (tran_call) {
8133 /* List the allowed trans2 calls on IPC$ */
8134 case TRANSACT2_OPEN:
8135 case TRANSACT2_GET_DFS_REFERRAL:
8136 case TRANSACT2_QFILEINFO:
8137 case TRANSACT2_QFSINFO:
8138 case TRANSACT2_SETFSINFO:
8141 reply_doserror(req, ERRSRV, ERRaccess);
8142 END_PROFILE(SMBtrans2);
8147 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8148 DEBUG(0, ("talloc failed\n"));
8149 reply_nterror(req, NT_STATUS_NO_MEMORY);
8150 END_PROFILE(SMBtrans2);
8154 state->cmd = SMBtrans2;
8156 state->mid = req->mid;
8157 state->vuid = req->vuid;
8158 state->setup_count = SVAL(req->vwv+13, 0);
8159 state->setup = NULL;
8160 state->total_param = SVAL(req->vwv+0, 0);
8161 state->param = NULL;
8162 state->total_data = SVAL(req->vwv+1, 0);
8164 state->max_param_return = SVAL(req->vwv+2, 0);
8165 state->max_data_return = SVAL(req->vwv+3, 0);
8166 state->max_setup_return = SVAL(req->vwv+4, 0);
8167 state->close_on_completion = BITSETW(req->vwv+5, 0);
8168 state->one_way = BITSETW(req->vwv+5, 1);
8170 state->call = tran_call;
8172 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8173 is so as a sanity check */
8174 if (state->setup_count != 1) {
8176 * Need to have rc=0 for ioctl to get job id for OS/2.
8177 * Network printing will fail if function is not successful.
8178 * Similar function in reply.c will be used if protocol
8179 * is LANMAN1.0 instead of LM1.2X002.
8180 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8181 * outbuf doesn't have to be set(only job id is used).
8183 if ( (state->setup_count == 4)
8184 && (tran_call == TRANSACT2_IOCTL)
8185 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8186 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8187 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8189 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8190 DEBUG(2,("Transaction is %d\n",tran_call));
8192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8193 END_PROFILE(SMBtrans2);
8198 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8201 if (state->total_data) {
8203 if (trans_oob(state->total_data, 0, dscnt)
8204 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8208 /* Can't use talloc here, the core routines do realloc on the
8209 * params and data. */
8210 state->data = (char *)SMB_MALLOC(state->total_data);
8211 if (state->data == NULL) {
8212 DEBUG(0,("reply_trans2: data malloc fail for %u "
8213 "bytes !\n", (unsigned int)state->total_data));
8215 reply_nterror(req, NT_STATUS_NO_MEMORY);
8216 END_PROFILE(SMBtrans2);
8220 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8223 if (state->total_param) {
8225 if (trans_oob(state->total_param, 0, pscnt)
8226 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8230 /* Can't use talloc here, the core routines do realloc on the
8231 * params and data. */
8232 state->param = (char *)SMB_MALLOC(state->total_param);
8233 if (state->param == NULL) {
8234 DEBUG(0,("reply_trans: param malloc fail for %u "
8235 "bytes !\n", (unsigned int)state->total_param));
8236 SAFE_FREE(state->data);
8238 reply_nterror(req, NT_STATUS_NO_MEMORY);
8239 END_PROFILE(SMBtrans2);
8243 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8246 state->received_data = dscnt;
8247 state->received_param = pscnt;
8249 if ((state->received_param == state->total_param) &&
8250 (state->received_data == state->total_data)) {
8252 handle_trans2(conn, req, state);
8254 SAFE_FREE(state->data);
8255 SAFE_FREE(state->param);
8257 END_PROFILE(SMBtrans2);
8261 DLIST_ADD(conn->pending_trans, state);
8263 /* We need to send an interim response then receive the rest
8264 of the parameter/data bytes */
8265 reply_outbuf(req, 0, 0);
8266 show_msg((char *)req->outbuf);
8267 END_PROFILE(SMBtrans2);
8272 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8273 SAFE_FREE(state->data);
8274 SAFE_FREE(state->param);
8276 END_PROFILE(SMBtrans2);
8277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8281 /****************************************************************************
8282 Reply to a SMBtranss2
8283 ****************************************************************************/
8285 void reply_transs2(struct smb_request *req)
8287 connection_struct *conn = req->conn;
8288 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8289 struct trans_state *state;
8291 START_PROFILE(SMBtranss2);
8293 show_msg((char *)req->inbuf);
8296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8297 END_PROFILE(SMBtranss2);
8301 for (state = conn->pending_trans; state != NULL;
8302 state = state->next) {
8303 if (state->mid == req->mid) {
8308 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8310 END_PROFILE(SMBtranss2);
8314 /* Revise state->total_param and state->total_data in case they have
8315 changed downwards */
8317 if (SVAL(req->vwv+0, 0) < state->total_param)
8318 state->total_param = SVAL(req->vwv+0, 0);
8319 if (SVAL(req->vwv+1, 0) < state->total_data)
8320 state->total_data = SVAL(req->vwv+1, 0);
8322 pcnt = SVAL(req->vwv+2, 0);
8323 poff = SVAL(req->vwv+3, 0);
8324 pdisp = SVAL(req->vwv+4, 0);
8326 dcnt = SVAL(req->vwv+5, 0);
8327 doff = SVAL(req->vwv+6, 0);
8328 ddisp = SVAL(req->vwv+7, 0);
8330 state->received_param += pcnt;
8331 state->received_data += dcnt;
8333 if ((state->received_data > state->total_data) ||
8334 (state->received_param > state->total_param))
8338 if (trans_oob(state->total_param, pdisp, pcnt)
8339 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8342 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8346 if (trans_oob(state->total_data, ddisp, dcnt)
8347 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8350 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8353 if ((state->received_param < state->total_param) ||
8354 (state->received_data < state->total_data)) {
8355 END_PROFILE(SMBtranss2);
8359 handle_trans2(conn, req, state);
8361 DLIST_REMOVE(conn->pending_trans, state);
8362 SAFE_FREE(state->data);
8363 SAFE_FREE(state->param);
8366 END_PROFILE(SMBtranss2);
8371 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8372 DLIST_REMOVE(conn->pending_trans, state);
8373 SAFE_FREE(state->data);
8374 SAFE_FREE(state->param);
8376 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8377 END_PROFILE(SMBtranss2);