2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
247 *pnum_names = num_names;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list *ea_list_head = NULL;
266 if (!lp_ea_support(SNUM(conn))) {
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
285 listp = TALLOC_P(mem_ctx, struct ea_list);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
346 if (ea_list->ea.value.length > 65535) {
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
372 unsigned int total_data_size,
373 unsigned int *ret_data_size,
374 connection_struct *conn,
375 struct ea_list *ea_list)
377 uint8_t *p = (uint8_t *)pdata;
378 uint8_t *last_start = NULL;
382 if (!lp_ea_support(SNUM(conn))) {
383 return NT_STATUS_NO_EAS_ON_FILE;
386 for (; ea_list; ea_list = ea_list->next) {
392 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
396 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
397 dos_namelen = strlen(dos_ea_name);
398 if (dos_namelen > 255 || dos_namelen == 0) {
399 return NT_STATUS_INTERNAL_ERROR;
401 if (ea_list->ea.value.length > 65535) {
402 return NT_STATUS_INTERNAL_ERROR;
405 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
408 size_t pad = 4 - (this_size % 4);
412 if (this_size > total_data_size) {
413 return NT_STATUS_INFO_LENGTH_MISMATCH;
416 /* We know we have room. */
417 SIVAL(p, 0x00, 0); /* next offset */
418 SCVAL(p, 0x04, ea_list->ea.flags);
419 SCVAL(p, 0x05, dos_namelen);
420 SSVAL(p, 0x06, ea_list->ea.value.length);
421 fstrcpy((char *)(p+0x08), dos_ea_name);
422 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
424 total_data_size -= this_size;
428 *ret_data_size = PTR_DIFF(p, pdata);
429 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
433 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
435 size_t total_ea_len = 0;
436 TALLOC_CTX *mem_ctx = NULL;
438 if (!lp_ea_support(SNUM(conn))) {
441 mem_ctx = talloc_tos();
442 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
446 /****************************************************************************
447 Ensure the EA name is case insensitive by matching any existing EA name.
448 ****************************************************************************/
450 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
453 TALLOC_CTX *mem_ctx = talloc_tos();
454 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
456 for (; ea_list; ea_list = ea_list->next) {
457 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
458 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
459 &unix_ea_name[5], ea_list->ea.name));
460 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
466 /****************************************************************************
467 Set or delete an extended attribute.
468 ****************************************************************************/
470 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
471 const struct smb_filename *smb_fname, struct ea_list *ea_list)
475 if (!lp_ea_support(SNUM(conn))) {
476 return NT_STATUS_EAS_NOT_SUPPORTED;
479 /* For now setting EAs on streams isn't supported. */
480 fname = smb_fname->base_name;
482 for (;ea_list; ea_list = ea_list->next) {
484 fstring unix_ea_name;
486 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
487 fstrcat(unix_ea_name, ea_list->ea.name);
489 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
491 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
493 if (samba_private_attr_name(unix_ea_name)) {
494 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
495 return NT_STATUS_ACCESS_DENIED;
498 if (ea_list->ea.value.length == 0) {
499 /* Remove the attribute. */
500 if (fsp && (fsp->fh->fd != -1)) {
501 DEBUG(10,("set_ea: deleting ea name %s on "
502 "file %s by file descriptor.\n",
503 unix_ea_name, fsp_str_dbg(fsp)));
504 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
506 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
507 unix_ea_name, fname));
508 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
511 /* Removing a non existent attribute always succeeds. */
512 if (ret == -1 && errno == ENOATTR) {
513 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
519 if (fsp && (fsp->fh->fd != -1)) {
520 DEBUG(10,("set_ea: setting ea name %s on file "
521 "%s by file descriptor.\n",
522 unix_ea_name, fsp_str_dbg(fsp)));
523 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
524 ea_list->ea.value.data, ea_list->ea.value.length, 0);
526 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
527 unix_ea_name, fname));
528 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
529 ea_list->ea.value.data, ea_list->ea.value.length, 0);
535 if (errno == ENOTSUP) {
536 return NT_STATUS_EAS_NOT_SUPPORTED;
539 return map_nt_error_from_unix(errno);
545 /****************************************************************************
546 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
547 ****************************************************************************/
549 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
551 struct ea_list *ea_list_head = NULL;
552 size_t converted_size, offset = 0;
554 while (offset + 2 < data_size) {
555 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
556 unsigned int namelen = CVAL(pdata,offset);
558 offset++; /* Go past the namelen byte. */
560 /* integer wrap paranioa. */
561 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
562 (offset > data_size) || (namelen > data_size) ||
563 (offset + namelen >= data_size)) {
566 /* Ensure the name is null terminated. */
567 if (pdata[offset + namelen] != '\0') {
570 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
572 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
573 "failed: %s", strerror(errno)));
579 offset += (namelen + 1); /* Go past the name + terminating zero. */
580 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
581 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
587 /****************************************************************************
588 Read one EA list entry from the buffer.
589 ****************************************************************************/
591 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
593 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
595 unsigned int namelen;
596 size_t converted_size;
606 eal->ea.flags = CVAL(pdata,0);
607 namelen = CVAL(pdata,1);
608 val_len = SVAL(pdata,2);
610 if (4 + namelen + 1 + val_len > data_size) {
614 /* Ensure the name is null terminated. */
615 if (pdata[namelen + 4] != '\0') {
618 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
619 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
626 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
627 if (!eal->ea.value.data) {
631 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
633 /* Ensure we're null terminated just in case we print the value. */
634 eal->ea.value.data[val_len] = '\0';
635 /* But don't count the null. */
636 eal->ea.value.length--;
639 *pbytes_used = 4 + namelen + 1 + val_len;
642 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
643 dump_data(10, eal->ea.value.data, eal->ea.value.length);
648 /****************************************************************************
649 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
650 ****************************************************************************/
652 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
654 struct ea_list *ea_list_head = NULL;
656 size_t bytes_used = 0;
658 while (offset < data_size) {
659 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
665 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
666 offset += bytes_used;
672 /****************************************************************************
673 Count the total EA size needed.
674 ****************************************************************************/
676 static size_t ea_list_size(struct ea_list *ealist)
679 struct ea_list *listp;
682 for (listp = ealist; listp; listp = listp->next) {
683 push_ascii_fstring(dos_ea_name, listp->ea.name);
684 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
686 /* Add on 4 for total length. */
694 /****************************************************************************
695 Return a union of EA's from a file list and a list of names.
696 The TALLOC context for the two lists *MUST* be identical as we steal
697 memory from one list to add to another. JRA.
698 ****************************************************************************/
700 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
702 struct ea_list *nlistp, *flistp;
704 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
705 for (flistp = file_list; flistp; flistp = flistp->next) {
706 if (strequal(nlistp->ea.name, flistp->ea.name)) {
712 /* Copy the data from this entry. */
713 nlistp->ea.flags = flistp->ea.flags;
714 nlistp->ea.value = flistp->ea.value;
717 nlistp->ea.flags = 0;
718 ZERO_STRUCT(nlistp->ea.value);
722 *total_ea_len = ea_list_size(name_list);
726 /****************************************************************************
727 Send the required number of replies back.
728 We assume all fields other than the data fields are
729 set correctly for the type of call.
730 HACK ! Always assumes smb_setup field is zero.
731 ****************************************************************************/
733 void send_trans2_replies(connection_struct *conn,
734 struct smb_request *req,
741 /* As we are using a protocol > LANMAN1 then the max_send
742 variable must have been set in the sessetupX call.
743 This takes precedence over the max_xmit field in the
744 global struct. These different max_xmit variables should
745 be merged as this is now too confusing */
747 int data_to_send = datasize;
748 int params_to_send = paramsize;
750 const char *pp = params;
751 const char *pd = pdata;
752 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
753 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
754 int data_alignment_offset = 0;
755 bool overflow = False;
756 struct smbd_server_connection *sconn = smbd_server_conn;
757 int max_send = sconn->smb1.sessions.max_send;
759 /* Modify the data_to_send and datasize and set the error if
760 we're trying to send more than max_data_bytes. We still send
761 the part of the packet(s) that fit. Strange, but needed
764 if (max_data_bytes > 0 && datasize > max_data_bytes) {
765 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
766 max_data_bytes, datasize ));
767 datasize = data_to_send = max_data_bytes;
771 /* If there genuinely are no parameters or data to send just send the empty packet */
773 if(params_to_send == 0 && data_to_send == 0) {
774 reply_outbuf(req, 10, 0);
775 show_msg((char *)req->outbuf);
776 if (!srv_send_smb(smbd_server_fd(),
779 IS_CONN_ENCRYPTED(conn),
781 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
783 TALLOC_FREE(req->outbuf);
787 /* When sending params and data ensure that both are nicely aligned */
788 /* Only do this alignment when there is also data to send - else
789 can cause NT redirector problems. */
791 if (((params_to_send % 4) != 0) && (data_to_send != 0))
792 data_alignment_offset = 4 - (params_to_send % 4);
794 /* Space is bufsize minus Netbios over TCP header minus SMB header */
795 /* The alignment_offset is to align the param bytes on an even byte
796 boundary. NT 4.0 Beta needs this to work correctly. */
798 useable_space = max_send - (smb_size
801 + data_alignment_offset);
803 if (useable_space < 0) {
804 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
805 "= %d!!!", useable_space));
806 exit_server_cleanly("send_trans2_replies: Not enough space");
809 while (params_to_send || data_to_send) {
810 /* Calculate whether we will totally or partially fill this packet */
812 total_sent_thistime = params_to_send + data_to_send;
814 /* We can never send more than useable_space */
816 * Note that 'useable_space' does not include the alignment offsets,
817 * but we must include the alignment offsets in the calculation of
818 * the length of the data we send over the wire, as the alignment offsets
819 * are sent here. Fix from Marc_Jacobsen@hp.com.
822 total_sent_thistime = MIN(total_sent_thistime, useable_space);
824 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
825 + data_alignment_offset);
828 * We might have SMBtrans2s in req which was transferred to
829 * the outbuf, fix that.
831 SCVAL(req->outbuf, smb_com, SMBtrans2);
833 /* Set total params and data to be sent */
834 SSVAL(req->outbuf,smb_tprcnt,paramsize);
835 SSVAL(req->outbuf,smb_tdrcnt,datasize);
837 /* Calculate how many parameters and data we can fit into
838 * this packet. Parameters get precedence
841 params_sent_thistime = MIN(params_to_send,useable_space);
842 data_sent_thistime = useable_space - params_sent_thistime;
843 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
845 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
847 /* smb_proff is the offset from the start of the SMB header to the
848 parameter bytes, however the first 4 bytes of outbuf are
849 the Netbios over TCP header. Thus use smb_base() to subtract
850 them from the calculation */
852 SSVAL(req->outbuf,smb_proff,
853 ((smb_buf(req->outbuf)+alignment_offset)
854 - smb_base(req->outbuf)));
856 if(params_sent_thistime == 0)
857 SSVAL(req->outbuf,smb_prdisp,0);
859 /* Absolute displacement of param bytes sent in this packet */
860 SSVAL(req->outbuf,smb_prdisp,pp - params);
862 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
863 if(data_sent_thistime == 0) {
864 SSVAL(req->outbuf,smb_droff,0);
865 SSVAL(req->outbuf,smb_drdisp, 0);
867 /* The offset of the data bytes is the offset of the
868 parameter bytes plus the number of parameters being sent this time */
869 SSVAL(req->outbuf, smb_droff,
870 ((smb_buf(req->outbuf)+alignment_offset)
871 - smb_base(req->outbuf))
872 + params_sent_thistime + data_alignment_offset);
873 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
876 /* Initialize the padding for alignment */
878 if (alignment_offset != 0) {
879 memset(smb_buf(req->outbuf), 0, alignment_offset);
882 /* Copy the param bytes into the packet */
884 if(params_sent_thistime) {
885 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
886 params_sent_thistime);
889 /* Copy in the data bytes */
890 if(data_sent_thistime) {
891 if (data_alignment_offset != 0) {
892 memset((smb_buf(req->outbuf)+alignment_offset+
893 params_sent_thistime), 0,
894 data_alignment_offset);
896 memcpy(smb_buf(req->outbuf)+alignment_offset
897 +params_sent_thistime+data_alignment_offset,
898 pd,data_sent_thistime);
901 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
902 params_sent_thistime, data_sent_thistime, useable_space));
903 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
904 params_to_send, data_to_send, paramsize, datasize));
907 error_packet_set((char *)req->outbuf,
908 ERRDOS,ERRbufferoverflow,
909 STATUS_BUFFER_OVERFLOW,
913 /* Send the packet */
914 show_msg((char *)req->outbuf);
915 if (!srv_send_smb(smbd_server_fd(),
918 IS_CONN_ENCRYPTED(conn),
920 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
922 TALLOC_FREE(req->outbuf);
924 pp += params_sent_thistime;
925 pd += data_sent_thistime;
927 params_to_send -= params_sent_thistime;
928 data_to_send -= data_sent_thistime;
931 if(params_to_send < 0 || data_to_send < 0) {
932 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
933 params_to_send, data_to_send));
941 /****************************************************************************
942 Reply to a TRANSACT2_OPEN.
943 ****************************************************************************/
945 static void call_trans2open(connection_struct *conn,
946 struct smb_request *req,
947 char **pparams, int total_params,
948 char **ppdata, int total_data,
949 unsigned int max_data_bytes)
951 struct smb_filename *smb_fname = NULL;
952 char *params = *pparams;
953 char *pdata = *ppdata;
958 bool return_additional_info;
971 struct ea_list *ea_list = NULL;
976 uint32 create_disposition;
977 uint32 create_options = 0;
978 TALLOC_CTX *ctx = talloc_tos();
981 * Ensure we have enough parameters to perform the operation.
984 if (total_params < 29) {
985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
989 flags = SVAL(params, 0);
990 deny_mode = SVAL(params, 2);
991 open_attr = SVAL(params,6);
992 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
993 if (oplock_request) {
994 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
998 return_additional_info = BITSETW(params,0);
999 open_sattr = SVAL(params, 4);
1000 open_time = make_unix_date3(params+8);
1002 open_ofun = SVAL(params,12);
1003 open_size = IVAL(params,14);
1004 pname = ¶ms[28];
1007 reply_doserror(req, ERRSRV, ERRaccess);
1011 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1012 total_params - 28, STR_TERMINATE,
1014 if (!NT_STATUS_IS_OK(status)) {
1015 reply_nterror(req, status);
1019 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1020 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1021 (unsigned int)open_ofun, open_size));
1023 status = filename_convert(ctx,
1025 req->flags2 & FLAGS2_DFS_PATHNAMES,
1030 if (!NT_STATUS_IS_OK(status)) {
1031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1032 reply_botherror(req,
1033 NT_STATUS_PATH_NOT_COVERED,
1034 ERRSRV, ERRbadpath);
1037 reply_nterror(req, status);
1041 if (open_ofun == 0) {
1042 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1046 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1047 &access_mask, &share_mode,
1048 &create_disposition,
1050 reply_doserror(req, ERRDOS, ERRbadaccess);
1054 /* Any data in this call is an EA list. */
1055 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1056 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1060 if (total_data != 4) {
1061 if (total_data < 10) {
1062 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1066 if (IVAL(pdata,0) > total_data) {
1067 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1068 IVAL(pdata,0), (unsigned int)total_data));
1069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1073 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1079 } else if (IVAL(pdata,0) != 4) {
1080 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1084 status = SMB_VFS_CREATE_FILE(
1087 0, /* root_dir_fid */
1088 smb_fname, /* fname */
1089 access_mask, /* access_mask */
1090 share_mode, /* share_access */
1091 create_disposition, /* create_disposition*/
1092 create_options, /* create_options */
1093 open_attr, /* file_attributes */
1094 oplock_request, /* oplock_request */
1095 open_size, /* allocation_size */
1097 ea_list, /* ea_list */
1099 &smb_action); /* psbuf */
1101 if (!NT_STATUS_IS_OK(status)) {
1102 if (open_was_deferred(req->mid)) {
1103 /* We have re-scheduled this call. */
1106 reply_openerror(req, status);
1110 size = get_file_size_stat(&smb_fname->st);
1111 fattr = dos_mode(conn, smb_fname);
1112 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1113 inode = smb_fname->st.st_ex_ino;
1115 close_file(req, fsp, ERROR_CLOSE);
1116 reply_doserror(req, ERRDOS,ERRnoaccess);
1120 /* Realloc the size of parameters and data we will return */
1121 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1122 if(*pparams == NULL ) {
1123 reply_nterror(req, NT_STATUS_NO_MEMORY);
1128 SSVAL(params,0,fsp->fnum);
1129 SSVAL(params,2,fattr);
1130 srv_put_dos_date2(params,4, mtime);
1131 SIVAL(params,8, (uint32)size);
1132 SSVAL(params,12,deny_mode);
1133 SSVAL(params,14,0); /* open_type - file or directory. */
1134 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1136 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1137 smb_action |= EXTENDED_OPLOCK_GRANTED;
1140 SSVAL(params,18,smb_action);
1143 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1145 SIVAL(params,20,inode);
1146 SSVAL(params,24,0); /* Padding. */
1148 uint32 ea_size = estimate_ea_size(conn, fsp,
1149 fsp->fsp_name->base_name);
1150 SIVAL(params, 26, ea_size);
1152 SIVAL(params, 26, 0);
1155 /* Send the required number of replies */
1156 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1158 TALLOC_FREE(smb_fname);
1161 /*********************************************************
1162 Routine to check if a given string matches exactly.
1163 as a special case a mask of "." does NOT match. That
1164 is required for correct wildcard semantics
1165 Case can be significant or not.
1166 **********************************************************/
1168 static bool exact_match(bool has_wild,
1169 bool case_sensitive,
1173 if (mask[0] == '.' && mask[1] == 0) {
1181 if (case_sensitive) {
1182 return strcmp(str,mask)==0;
1184 return StrCaseCmp(str,mask) == 0;
1188 /****************************************************************************
1189 Return the filetype for UNIX extensions.
1190 ****************************************************************************/
1192 static uint32 unix_filetype(mode_t mode)
1195 return UNIX_TYPE_FILE;
1196 else if(S_ISDIR(mode))
1197 return UNIX_TYPE_DIR;
1199 else if(S_ISLNK(mode))
1200 return UNIX_TYPE_SYMLINK;
1203 else if(S_ISCHR(mode))
1204 return UNIX_TYPE_CHARDEV;
1207 else if(S_ISBLK(mode))
1208 return UNIX_TYPE_BLKDEV;
1211 else if(S_ISFIFO(mode))
1212 return UNIX_TYPE_FIFO;
1215 else if(S_ISSOCK(mode))
1216 return UNIX_TYPE_SOCKET;
1219 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1220 return UNIX_TYPE_UNKNOWN;
1223 /****************************************************************************
1224 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1225 ****************************************************************************/
1227 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1229 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1230 const SMB_STRUCT_STAT *psbuf,
1232 enum perm_type ptype,
1237 if (perms == SMB_MODE_NO_CHANGE) {
1238 if (!VALID_STAT(*psbuf)) {
1239 return NT_STATUS_INVALID_PARAMETER;
1241 *ret_perms = psbuf->st_ex_mode;
1242 return NT_STATUS_OK;
1246 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1247 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1248 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1249 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1250 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1251 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1252 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1253 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1254 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1256 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1259 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1262 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1267 /* Apply mode mask */
1268 ret &= lp_create_mask(SNUM(conn));
1269 /* Add in force bits */
1270 ret |= lp_force_create_mode(SNUM(conn));
1273 ret &= lp_dir_mask(SNUM(conn));
1274 /* Add in force bits */
1275 ret |= lp_force_dir_mode(SNUM(conn));
1277 case PERM_EXISTING_FILE:
1278 /* Apply mode mask */
1279 ret &= lp_security_mask(SNUM(conn));
1280 /* Add in force bits */
1281 ret |= lp_force_security_mode(SNUM(conn));
1283 case PERM_EXISTING_DIR:
1284 /* Apply mode mask */
1285 ret &= lp_dir_security_mask(SNUM(conn));
1286 /* Add in force bits */
1287 ret |= lp_force_dir_security_mode(SNUM(conn));
1292 return NT_STATUS_OK;
1295 /****************************************************************************
1296 Needed to show the msdfs symlinks as directories. Modifies psbuf
1297 to be a directory if it's a msdfs link.
1298 ****************************************************************************/
1300 static bool check_msdfs_link(connection_struct *conn,
1301 const char *pathname,
1302 SMB_STRUCT_STAT *psbuf)
1304 int saved_errno = errno;
1305 if(lp_host_msdfs() &&
1306 lp_msdfs_root(SNUM(conn)) &&
1307 is_msdfs_link(conn, pathname, psbuf)) {
1309 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1312 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1313 errno = saved_errno;
1316 errno = saved_errno;
1321 /****************************************************************************
1322 Get a level dependent lanman2 dir entry.
1323 ****************************************************************************/
1325 struct smbd_dirptr_lanman2_state {
1326 connection_struct *conn;
1327 uint32_t info_level;
1328 bool check_mangled_names;
1330 bool got_exact_match;
1333 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1339 struct smbd_dirptr_lanman2_state *state =
1340 (struct smbd_dirptr_lanman2_state *)private_data;
1342 char mangled_name[13]; /* mangled 8.3 name. */
1346 /* Mangle fname if it's an illegal name. */
1347 if (mangle_must_mangle(dname, state->conn->params)) {
1348 ok = name_to_8_3(dname, mangled_name,
1349 true, state->conn->params);
1353 fname = mangled_name;
1358 got_match = exact_match(state->has_wild,
1359 state->conn->case_sensitive,
1361 state->got_exact_match = got_match;
1363 got_match = mask_match(fname, mask,
1364 state->conn->case_sensitive);
1367 if(!got_match && state->check_mangled_names &&
1368 !mangle_is_8_3(fname, false, state->conn->params)) {
1370 * It turns out that NT matches wildcards against
1371 * both long *and* short names. This may explain some
1372 * of the wildcard wierdness from old DOS clients
1373 * that some people have been seeing.... JRA.
1375 /* Force the mangling into 8.3. */
1376 ok = name_to_8_3(fname, mangled_name,
1377 false, state->conn->params);
1382 got_match = exact_match(state->has_wild,
1383 state->conn->case_sensitive,
1384 mangled_name, mask);
1385 state->got_exact_match = got_match;
1387 got_match = mask_match(mangled_name, mask,
1388 state->conn->case_sensitive);
1396 *_fname = talloc_strdup(ctx, fname);
1397 if (*_fname == NULL) {
1404 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1406 struct smb_filename *smb_fname,
1409 struct smbd_dirptr_lanman2_state *state =
1410 (struct smbd_dirptr_lanman2_state *)private_data;
1411 bool ms_dfs_link = false;
1414 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1415 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1416 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1417 "Couldn't lstat [%s] (%s)\n",
1418 smb_fname_str_dbg(smb_fname),
1422 } else if (!VALID_STAT(smb_fname->st) &&
1423 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1424 /* Needed to show the msdfs symlinks as
1427 ms_dfs_link = check_msdfs_link(state->conn,
1428 smb_fname->base_name,
1431 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1432 "Couldn't stat [%s] (%s)\n",
1433 smb_fname_str_dbg(smb_fname),
1440 mode = dos_mode_msdfs(state->conn, smb_fname);
1442 mode = dos_mode(state->conn, smb_fname);
1449 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1450 connection_struct *conn,
1452 const char *path_mask,
1455 int requires_resume_key,
1461 int space_remaining,
1463 bool *got_exact_match,
1464 int *last_entry_off,
1465 struct ea_list *name_list)
1467 const char *mask = NULL;
1468 char *p, *q, *pdata = *ppdata;
1472 SMB_OFF_T file_size = 0;
1473 uint64_t allocation_size = 0;
1475 struct timespec mdate_ts, adate_ts, create_date_ts;
1476 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1478 char *last_entry_ptr;
1480 uint32 nt_extmode; /* Used for NT connections instead of mode */
1482 struct smb_filename *smb_fname = NULL;
1483 struct smbd_dirptr_lanman2_state state;
1488 state.info_level = info_level;
1489 state.check_mangled_names = lp_manglednames(conn->params);
1490 state.has_wild = dptr_has_wild(conn->dirptr);
1491 state.got_exact_match = false;
1493 *out_of_space = False;
1494 *got_exact_match = False;
1496 ZERO_STRUCT(mdate_ts);
1497 ZERO_STRUCT(adate_ts);
1498 ZERO_STRUCT(create_date_ts);
1500 if (!conn->dirptr) {
1504 p = strrchr_m(path_mask,'/');
1515 ok = smbd_dirptr_get_entry(ctx,
1521 smbd_dirptr_lanman2_match_fn,
1522 smbd_dirptr_lanman2_mode_fn,
1532 *got_exact_match = state.got_exact_match;
1534 if (!(mode & aDIR)) {
1535 file_size = get_file_size_stat(&smb_fname->st);
1537 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1539 mdate_ts = smb_fname->st.st_ex_mtime;
1540 adate_ts = smb_fname->st.st_ex_atime;
1541 create_date_ts = smb_fname->st.st_ex_btime;
1543 if (lp_dos_filetime_resolution(SNUM(conn))) {
1544 dos_filetime_timespec(&create_date_ts);
1545 dos_filetime_timespec(&mdate_ts);
1546 dos_filetime_timespec(&adate_ts);
1549 create_date = convert_timespec_to_time_t(create_date_ts);
1550 mdate = convert_timespec_to_time_t(mdate_ts);
1551 adate = convert_timespec_to_time_t(adate_ts);
1556 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1558 switch (info_level) {
1559 case SMB_FIND_INFO_STANDARD:
1560 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1561 if(requires_resume_key) {
1565 srv_put_dos_date2(p,0,create_date);
1566 srv_put_dos_date2(p,4,adate);
1567 srv_put_dos_date2(p,8,mdate);
1568 SIVAL(p,12,(uint32)file_size);
1569 SIVAL(p,16,(uint32)allocation_size);
1573 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1574 p += ucs2_align(base_data, p, 0);
1576 len = srvstr_push(base_data, flags2, p,
1577 fname, PTR_DIFF(end_data, p),
1579 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1581 SCVAL(nameptr, -1, len - 2);
1583 SCVAL(nameptr, -1, 0);
1587 SCVAL(nameptr, -1, len - 1);
1589 SCVAL(nameptr, -1, 0);
1595 case SMB_FIND_EA_SIZE:
1596 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1597 if(requires_resume_key) {
1601 srv_put_dos_date2(p,0,create_date);
1602 srv_put_dos_date2(p,4,adate);
1603 srv_put_dos_date2(p,8,mdate);
1604 SIVAL(p,12,(uint32)file_size);
1605 SIVAL(p,16,(uint32)allocation_size);
1608 unsigned int ea_size = estimate_ea_size(conn, NULL,
1609 smb_fname->base_name);
1610 SIVAL(p,22,ea_size); /* Extended attributes */
1614 len = srvstr_push(base_data, flags2,
1615 p, fname, PTR_DIFF(end_data, p),
1616 STR_TERMINATE | STR_NOALIGN);
1617 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1630 SCVAL(nameptr,0,len);
1632 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1635 case SMB_FIND_EA_LIST:
1637 struct ea_list *file_list = NULL;
1640 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1643 TALLOC_FREE(smb_fname);
1646 if(requires_resume_key) {
1650 srv_put_dos_date2(p,0,create_date);
1651 srv_put_dos_date2(p,4,adate);
1652 srv_put_dos_date2(p,8,mdate);
1653 SIVAL(p,12,(uint32)file_size);
1654 SIVAL(p,16,(uint32)allocation_size);
1656 p += 22; /* p now points to the EA area. */
1658 file_list = get_ea_list_from_file(ctx, conn, NULL,
1659 smb_fname->base_name,
1661 name_list = ea_list_union(name_list, file_list, &ea_len);
1663 /* We need to determine if this entry will fit in the space available. */
1664 /* Max string size is 255 bytes. */
1665 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1667 TALLOC_FREE(smb_fname);
1668 /* Move the dirptr back to prev_dirpos */
1669 dptr_SeekDir(conn->dirptr, prev_dirpos);
1670 *out_of_space = True;
1671 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1672 return False; /* Not finished - just out of space */
1675 /* Push the ea_data followed by the name. */
1676 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1678 len = srvstr_push(base_data, flags2,
1679 p + 1, fname, PTR_DIFF(end_data, p+1),
1680 STR_TERMINATE | STR_NOALIGN);
1681 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1694 SCVAL(nameptr,0,len);
1696 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1700 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1701 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1702 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1704 SIVAL(p,0,reskey); p += 4;
1705 put_long_date_timespec(p,create_date_ts); p += 8;
1706 put_long_date_timespec(p,adate_ts); p += 8;
1707 put_long_date_timespec(p,mdate_ts); p += 8;
1708 put_long_date_timespec(p,mdate_ts); p += 8;
1709 SOFF_T(p,0,file_size); p += 8;
1710 SOFF_T(p,0,allocation_size); p += 8;
1711 SIVAL(p,0,nt_extmode); p += 4;
1712 q = p; p += 4; /* q is placeholder for name length. */
1714 unsigned int ea_size = estimate_ea_size(conn, NULL,
1715 smb_fname->base_name);
1716 SIVAL(p,0,ea_size); /* Extended attributes */
1719 /* Clear the short name buffer. This is
1720 * IMPORTANT as not doing so will trigger
1721 * a Win2k client bug. JRA.
1723 if (!was_8_3 && state.check_mangled_names) {
1724 char mangled_name[13]; /* mangled 8.3 name. */
1725 if (!name_to_8_3(fname,mangled_name,True,
1727 /* Error - mangle failed ! */
1728 memset(mangled_name,'\0',12);
1730 mangled_name[12] = 0;
1731 len = srvstr_push(base_data, flags2,
1732 p+2, mangled_name, 24,
1733 STR_UPPER|STR_UNICODE);
1735 memset(p + 2 + len,'\0',24 - len);
1742 len = srvstr_push(base_data, flags2, p,
1743 fname, PTR_DIFF(end_data, p),
1744 STR_TERMINATE_ASCII);
1747 SIVAL(p,0,0); /* Ensure any padding is null. */
1748 len = PTR_DIFF(p, pdata);
1749 len = (len + 3) & ~3;
1754 case SMB_FIND_FILE_DIRECTORY_INFO:
1755 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1757 SIVAL(p,0,reskey); p += 4;
1758 put_long_date_timespec(p,create_date_ts); p += 8;
1759 put_long_date_timespec(p,adate_ts); p += 8;
1760 put_long_date_timespec(p,mdate_ts); p += 8;
1761 put_long_date_timespec(p,mdate_ts); p += 8;
1762 SOFF_T(p,0,file_size); p += 8;
1763 SOFF_T(p,0,allocation_size); p += 8;
1764 SIVAL(p,0,nt_extmode); p += 4;
1765 len = srvstr_push(base_data, flags2,
1766 p + 4, fname, PTR_DIFF(end_data, p+4),
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_FILE_FULL_DIRECTORY_INFO:
1778 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_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,mdate_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 len = srvstr_push(base_data, flags2, p,
1796 fname, PTR_DIFF(end_data, p),
1797 STR_TERMINATE_ASCII);
1801 SIVAL(p,0,0); /* Ensure any padding is null. */
1802 len = PTR_DIFF(p, pdata);
1803 len = (len + 3) & ~3;
1808 case SMB_FIND_FILE_NAMES_INFO:
1809 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1811 SIVAL(p,0,reskey); p += 4;
1813 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1814 acl on a dir (tridge) */
1815 len = srvstr_push(base_data, flags2, p,
1816 fname, PTR_DIFF(end_data, p),
1817 STR_TERMINATE_ASCII);
1820 SIVAL(p,0,0); /* Ensure any padding is null. */
1821 len = PTR_DIFF(p, pdata);
1822 len = (len + 3) & ~3;
1827 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1828 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1830 SIVAL(p,0,reskey); p += 4;
1831 put_long_date_timespec(p,create_date_ts); p += 8;
1832 put_long_date_timespec(p,adate_ts); p += 8;
1833 put_long_date_timespec(p,mdate_ts); p += 8;
1834 put_long_date_timespec(p,mdate_ts); p += 8;
1835 SOFF_T(p,0,file_size); p += 8;
1836 SOFF_T(p,0,allocation_size); p += 8;
1837 SIVAL(p,0,nt_extmode); p += 4;
1838 q = p; p += 4; /* q is placeholder for name length. */
1840 unsigned int ea_size = estimate_ea_size(conn, NULL,
1841 smb_fname->base_name);
1842 SIVAL(p,0,ea_size); /* Extended attributes */
1845 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1846 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1847 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1848 len = srvstr_push(base_data, flags2, p,
1849 fname, PTR_DIFF(end_data, p),
1850 STR_TERMINATE_ASCII);
1853 SIVAL(p,0,0); /* Ensure any padding is null. */
1854 len = PTR_DIFF(p, pdata);
1855 len = (len + 3) & ~3;
1860 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1861 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1862 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1864 SIVAL(p,0,reskey); p += 4;
1865 put_long_date_timespec(p,create_date_ts); p += 8;
1866 put_long_date_timespec(p,adate_ts); p += 8;
1867 put_long_date_timespec(p,mdate_ts); p += 8;
1868 put_long_date_timespec(p,mdate_ts); p += 8;
1869 SOFF_T(p,0,file_size); p += 8;
1870 SOFF_T(p,0,allocation_size); p += 8;
1871 SIVAL(p,0,nt_extmode); p += 4;
1872 q = p; p += 4; /* q is placeholder for name length */
1874 unsigned int ea_size = estimate_ea_size(conn, NULL,
1875 smb_fname->base_name);
1876 SIVAL(p,0,ea_size); /* Extended attributes */
1879 /* Clear the short name buffer. This is
1880 * IMPORTANT as not doing so will trigger
1881 * a Win2k client bug. JRA.
1883 if (!was_8_3 && state.check_mangled_names) {
1884 char mangled_name[13]; /* mangled 8.3 name. */
1885 if (!name_to_8_3(fname,mangled_name,True,
1887 /* Error - mangle failed ! */
1888 memset(mangled_name,'\0',12);
1890 mangled_name[12] = 0;
1891 len = srvstr_push(base_data, flags2,
1892 p+2, mangled_name, 24,
1893 STR_UPPER|STR_UNICODE);
1896 memset(p + 2 + len,'\0',24 - len);
1903 SSVAL(p,0,0); p += 2; /* Reserved ? */
1904 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1905 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1906 len = srvstr_push(base_data, flags2, p,
1907 fname, PTR_DIFF(end_data, p),
1908 STR_TERMINATE_ASCII);
1911 SIVAL(p,0,0); /* Ensure any padding is null. */
1912 len = PTR_DIFF(p, pdata);
1913 len = (len + 3) & ~3;
1918 /* CIFS UNIX Extension. */
1920 case SMB_FIND_FILE_UNIX:
1921 case SMB_FIND_FILE_UNIX_INFO2:
1923 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1925 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1927 if (info_level == SMB_FIND_FILE_UNIX) {
1928 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1929 p = store_file_unix_basic(conn, p,
1930 NULL, &smb_fname->st);
1931 len = srvstr_push(base_data, flags2, p,
1932 fname, PTR_DIFF(end_data, p),
1935 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1936 p = store_file_unix_basic_info2(conn, p,
1937 NULL, &smb_fname->st);
1940 len = srvstr_push(base_data, flags2, p, fname,
1941 PTR_DIFF(end_data, p), 0);
1942 SIVAL(nameptr, 0, len);
1946 SIVAL(p,0,0); /* Ensure any padding is null. */
1948 len = PTR_DIFF(p, pdata);
1949 len = (len + 3) & ~3;
1950 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1952 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1958 TALLOC_FREE(smb_fname);
1963 TALLOC_FREE(smb_fname);
1965 if (PTR_DIFF(p,pdata) > space_remaining) {
1966 /* Move the dirptr back to prev_dirpos */
1967 dptr_SeekDir(conn->dirptr, prev_dirpos);
1968 *out_of_space = True;
1969 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1970 return False; /* Not finished - just out of space */
1973 /* Setup the last entry pointer, as an offset from base_data */
1974 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1975 /* Advance the data pointer to the next slot */
1981 /****************************************************************************
1982 Reply to a TRANS2_FINDFIRST.
1983 ****************************************************************************/
1985 static void call_trans2findfirst(connection_struct *conn,
1986 struct smb_request *req,
1987 char **pparams, int total_params,
1988 char **ppdata, int total_data,
1989 unsigned int max_data_bytes)
1991 /* We must be careful here that we don't return more than the
1992 allowed number of data bytes. If this means returning fewer than
1993 maxentries then so be it. We assume that the redirector has
1994 enough room for the fixed number of parameter bytes it has
1996 struct smb_filename *smb_dname = NULL;
1997 char *params = *pparams;
1998 char *pdata = *ppdata;
2002 uint16 findfirst_flags;
2003 bool close_after_first;
2005 bool requires_resume_key;
2007 char *directory = NULL;
2010 int last_entry_off=0;
2014 bool finished = False;
2015 bool dont_descend = False;
2016 bool out_of_space = False;
2017 int space_remaining;
2018 bool mask_contains_wcard = False;
2019 struct ea_list *ea_list = NULL;
2020 NTSTATUS ntstatus = NT_STATUS_OK;
2021 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2022 TALLOC_CTX *ctx = talloc_tos();
2024 if (total_params < 13) {
2025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2029 dirtype = SVAL(params,0);
2030 maxentries = SVAL(params,2);
2031 findfirst_flags = SVAL(params,4);
2032 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2033 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2034 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2035 info_level = SVAL(params,6);
2037 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2038 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2039 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2040 info_level, max_data_bytes));
2043 /* W2K3 seems to treat zero as 1. */
2047 switch (info_level) {
2048 case SMB_FIND_INFO_STANDARD:
2049 case SMB_FIND_EA_SIZE:
2050 case SMB_FIND_EA_LIST:
2051 case SMB_FIND_FILE_DIRECTORY_INFO:
2052 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2053 case SMB_FIND_FILE_NAMES_INFO:
2054 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2055 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2056 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2058 case SMB_FIND_FILE_UNIX:
2059 case SMB_FIND_FILE_UNIX_INFO2:
2060 /* Always use filesystem for UNIX mtime query. */
2061 ask_sharemode = false;
2062 if (!lp_unix_extensions()) {
2063 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2068 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2072 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2073 params+12, total_params - 12,
2074 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2075 if (!NT_STATUS_IS_OK(ntstatus)) {
2076 reply_nterror(req, ntstatus);
2080 ntstatus = filename_convert(ctx, conn,
2081 req->flags2 & FLAGS2_DFS_PATHNAMES,
2084 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2085 &mask_contains_wcard,
2087 if (!NT_STATUS_IS_OK(ntstatus)) {
2088 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2089 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2090 ERRSRV, ERRbadpath);
2093 reply_nterror(req, ntstatus);
2097 mask = smb_dname->original_lcomp;
2099 directory = smb_dname->base_name;
2101 p = strrchr_m(directory,'/');
2103 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2104 if((directory[0] == '.') && (directory[1] == '\0')) {
2105 mask = talloc_strdup(ctx,"*");
2107 reply_nterror(req, NT_STATUS_NO_MEMORY);
2110 mask_contains_wcard = True;
2112 directory = talloc_strdup(talloc_tos(), "./");
2114 reply_nterror(req, NT_STATUS_NO_MEMORY);
2121 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2123 if (info_level == SMB_FIND_EA_LIST) {
2126 if (total_data < 4) {
2127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2131 ea_size = IVAL(pdata,0);
2132 if (ea_size != total_data) {
2133 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2134 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2139 if (!lp_ea_support(SNUM(conn))) {
2140 reply_doserror(req, ERRDOS, ERReasnotsupported);
2144 /* Pull out the list of names. */
2145 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2147 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2152 *ppdata = (char *)SMB_REALLOC(
2153 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2154 if(*ppdata == NULL ) {
2155 reply_nterror(req, NT_STATUS_NO_MEMORY);
2159 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2161 /* Realloc the params space */
2162 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2163 if (*pparams == NULL) {
2164 reply_nterror(req, NT_STATUS_NO_MEMORY);
2169 /* Save the wildcard match and attribs we are using on this directory -
2170 needed as lanman2 assumes these are being saved between calls */
2172 ntstatus = dptr_create(conn,
2178 mask_contains_wcard,
2182 if (!NT_STATUS_IS_OK(ntstatus)) {
2183 reply_nterror(req, ntstatus);
2187 dptr_num = dptr_dnum(conn->dirptr);
2188 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2190 /* Initialize per TRANS2_FIND_FIRST operation data */
2191 dptr_init_search_op(conn->dirptr);
2193 /* We don't need to check for VOL here as this is returned by
2194 a different TRANS2 call. */
2196 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2197 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2198 dont_descend = True;
2201 space_remaining = max_data_bytes;
2202 out_of_space = False;
2204 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2205 bool got_exact_match = False;
2207 /* this is a heuristic to avoid seeking the dirptr except when
2208 absolutely necessary. It allows for a filename of about 40 chars */
2209 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2210 out_of_space = True;
2213 finished = !get_lanman2_dir_entry(ctx,
2216 mask,dirtype,info_level,
2217 requires_resume_key,dont_descend,
2220 space_remaining, &out_of_space,
2222 &last_entry_off, ea_list);
2225 if (finished && out_of_space)
2228 if (!finished && !out_of_space)
2232 * As an optimisation if we know we aren't looking
2233 * for a wildcard name (ie. the name matches the wildcard exactly)
2234 * then we can finish on any (first) match.
2235 * This speeds up large directory searches. JRA.
2241 /* Ensure space_remaining never goes -ve. */
2242 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2243 space_remaining = 0;
2244 out_of_space = true;
2246 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2250 /* Check if we can close the dirptr */
2251 if(close_after_first || (finished && close_if_end)) {
2252 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2253 dptr_close(&dptr_num);
2257 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2258 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2259 * the protocol level is less than NT1. Tested with smbclient. JRA.
2260 * This should fix the OS/2 client bug #2335.
2263 if(numentries == 0) {
2264 dptr_close(&dptr_num);
2265 if (Protocol < PROTOCOL_NT1) {
2266 reply_doserror(req, ERRDOS, ERRnofiles);
2269 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2270 ERRDOS, ERRbadfile);
2275 /* At this point pdata points to numentries directory entries. */
2277 /* Set up the return parameter block */
2278 SSVAL(params,0,dptr_num);
2279 SSVAL(params,2,numentries);
2280 SSVAL(params,4,finished);
2281 SSVAL(params,6,0); /* Never an EA error */
2282 SSVAL(params,8,last_entry_off);
2284 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2287 if ((! *directory) && dptr_path(dptr_num)) {
2288 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2290 reply_nterror(req, NT_STATUS_NO_MEMORY);
2294 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2295 smb_fn_name(req->cmd),
2296 mask, directory, dirtype, numentries ) );
2299 * Force a name mangle here to ensure that the
2300 * mask as an 8.3 name is top of the mangled cache.
2301 * The reasons for this are subtle. Don't remove
2302 * this code unless you know what you are doing
2303 * (see PR#13758). JRA.
2306 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2307 char mangled_name[13];
2308 name_to_8_3(mask, mangled_name, True, conn->params);
2311 TALLOC_FREE(smb_dname);
2315 /****************************************************************************
2316 Reply to a TRANS2_FINDNEXT.
2317 ****************************************************************************/
2319 static void call_trans2findnext(connection_struct *conn,
2320 struct smb_request *req,
2321 char **pparams, int total_params,
2322 char **ppdata, int total_data,
2323 unsigned int max_data_bytes)
2325 /* We must be careful here that we don't return more than the
2326 allowed number of data bytes. If this means returning fewer than
2327 maxentries then so be it. We assume that the redirector has
2328 enough room for the fixed number of parameter bytes it has
2330 char *params = *pparams;
2331 char *pdata = *ppdata;
2337 uint16 findnext_flags;
2338 bool close_after_request;
2340 bool requires_resume_key;
2342 bool mask_contains_wcard = False;
2343 char *resume_name = NULL;
2344 const char *mask = NULL;
2345 const char *directory = NULL;
2349 int i, last_entry_off=0;
2350 bool finished = False;
2351 bool dont_descend = False;
2352 bool out_of_space = False;
2353 int space_remaining;
2354 struct ea_list *ea_list = NULL;
2355 NTSTATUS ntstatus = NT_STATUS_OK;
2356 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2357 TALLOC_CTX *ctx = talloc_tos();
2359 if (total_params < 13) {
2360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2364 dptr_num = SVAL(params,0);
2365 maxentries = SVAL(params,2);
2366 info_level = SVAL(params,4);
2367 resume_key = IVAL(params,6);
2368 findnext_flags = SVAL(params,10);
2369 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2370 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2371 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2372 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2374 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2376 total_params - 12, STR_TERMINATE, &ntstatus,
2377 &mask_contains_wcard);
2378 if (!NT_STATUS_IS_OK(ntstatus)) {
2379 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2380 complain (it thinks we're asking for the directory above the shared
2381 path or an invalid name). Catch this as the resume name is only compared, never used in
2382 a file access. JRA. */
2383 srvstr_pull_talloc(ctx, params, req->flags2,
2384 &resume_name, params+12,
2388 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2389 reply_nterror(req, ntstatus);
2394 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2395 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2396 resume_key = %d resume name = %s continue=%d level = %d\n",
2397 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2398 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2401 /* W2K3 seems to treat zero as 1. */
2405 switch (info_level) {
2406 case SMB_FIND_INFO_STANDARD:
2407 case SMB_FIND_EA_SIZE:
2408 case SMB_FIND_EA_LIST:
2409 case SMB_FIND_FILE_DIRECTORY_INFO:
2410 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2411 case SMB_FIND_FILE_NAMES_INFO:
2412 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2413 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2414 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2416 case SMB_FIND_FILE_UNIX:
2417 case SMB_FIND_FILE_UNIX_INFO2:
2418 /* Always use filesystem for UNIX mtime query. */
2419 ask_sharemode = false;
2420 if (!lp_unix_extensions()) {
2421 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2426 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2430 if (info_level == SMB_FIND_EA_LIST) {
2433 if (total_data < 4) {
2434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2438 ea_size = IVAL(pdata,0);
2439 if (ea_size != total_data) {
2440 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2441 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2442 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2446 if (!lp_ea_support(SNUM(conn))) {
2447 reply_doserror(req, ERRDOS, ERReasnotsupported);
2451 /* Pull out the list of names. */
2452 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2459 *ppdata = (char *)SMB_REALLOC(
2460 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2461 if(*ppdata == NULL) {
2462 reply_nterror(req, NT_STATUS_NO_MEMORY);
2467 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2469 /* Realloc the params space */
2470 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2471 if(*pparams == NULL ) {
2472 reply_nterror(req, NT_STATUS_NO_MEMORY);
2478 /* Check that the dptr is valid */
2479 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2480 reply_doserror(req, ERRDOS, ERRnofiles);
2484 string_set(&conn->dirpath,dptr_path(dptr_num));
2486 /* Get the wildcard mask from the dptr */
2487 if((p = dptr_wcard(dptr_num))== NULL) {
2488 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2489 reply_doserror(req, ERRDOS, ERRnofiles);
2494 directory = conn->dirpath;
2496 /* Get the attr mask from the dptr */
2497 dirtype = dptr_attr(dptr_num);
2499 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2500 dptr_num, mask, dirtype,
2502 dptr_TellDir(conn->dirptr)));
2504 /* Initialize per TRANS2_FIND_NEXT operation data */
2505 dptr_init_search_op(conn->dirptr);
2507 /* We don't need to check for VOL here as this is returned by
2508 a different TRANS2 call. */
2510 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2511 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2512 dont_descend = True;
2515 space_remaining = max_data_bytes;
2516 out_of_space = False;
2519 * Seek to the correct position. We no longer use the resume key but
2520 * depend on the last file name instead.
2523 if(*resume_name && !continue_bit) {
2526 long current_pos = 0;
2528 * Remember, name_to_8_3 is called by
2529 * get_lanman2_dir_entry(), so the resume name
2530 * could be mangled. Ensure we check the unmangled name.
2533 if (mangle_is_mangled(resume_name, conn->params)) {
2534 char *new_resume_name = NULL;
2535 mangle_lookup_name_from_8_3(ctx,
2539 if (new_resume_name) {
2540 resume_name = new_resume_name;
2545 * Fix for NT redirector problem triggered by resume key indexes
2546 * changing between directory scans. We now return a resume key of 0
2547 * and instead look for the filename to continue from (also given
2548 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2549 * findfirst/findnext (as is usual) then the directory pointer
2550 * should already be at the correct place.
2553 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2554 } /* end if resume_name && !continue_bit */
2556 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2557 bool got_exact_match = False;
2559 /* this is a heuristic to avoid seeking the dirptr except when
2560 absolutely necessary. It allows for a filename of about 40 chars */
2561 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2562 out_of_space = True;
2565 finished = !get_lanman2_dir_entry(ctx,
2568 mask,dirtype,info_level,
2569 requires_resume_key,dont_descend,
2572 space_remaining, &out_of_space,
2574 &last_entry_off, ea_list);
2577 if (finished && out_of_space)
2580 if (!finished && !out_of_space)
2584 * As an optimisation if we know we aren't looking
2585 * for a wildcard name (ie. the name matches the wildcard exactly)
2586 * then we can finish on any (first) match.
2587 * This speeds up large directory searches. JRA.
2593 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2596 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2597 smb_fn_name(req->cmd),
2598 mask, directory, dirtype, numentries ) );
2600 /* Check if we can close the dirptr */
2601 if(close_after_request || (finished && close_if_end)) {
2602 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2603 dptr_close(&dptr_num); /* This frees up the saved mask */
2606 /* Set up the return parameter block */
2607 SSVAL(params,0,numentries);
2608 SSVAL(params,2,finished);
2609 SSVAL(params,4,0); /* Never an EA error */
2610 SSVAL(params,6,last_entry_off);
2612 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2618 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2620 E_md4hash(lp_servicename(SNUM(conn)),objid);
2624 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2626 SMB_ASSERT(extended_info != NULL);
2628 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2629 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2630 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2631 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2632 #ifdef SAMBA_VERSION_REVISION
2633 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2635 extended_info->samba_subversion = 0;
2636 #ifdef SAMBA_VERSION_RC_RELEASE
2637 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2639 #ifdef SAMBA_VERSION_PRE_RELEASE
2640 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2643 #ifdef SAMBA_VERSION_VENDOR_PATCH
2644 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2646 extended_info->samba_gitcommitdate = 0;
2647 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2648 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2651 memset(extended_info->samba_version_string, 0,
2652 sizeof(extended_info->samba_version_string));
2654 snprintf (extended_info->samba_version_string,
2655 sizeof(extended_info->samba_version_string),
2656 "%s", samba_version_string());
2659 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2660 TALLOC_CTX *mem_ctx,
2661 uint16_t info_level,
2663 unsigned int max_data_bytes,
2667 char *pdata, *end_data;
2668 int data_len = 0, len;
2669 const char *vname = volume_label(SNUM(conn));
2670 int snum = SNUM(conn);
2671 char *fstype = lp_fstype(SNUM(conn));
2672 uint32 additional_flags = 0;
2673 struct smb_filename *smb_fname_dot = NULL;
2678 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2679 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2680 "info level (0x%x) on IPC$.\n",
2681 (unsigned int)info_level));
2682 return NT_STATUS_ACCESS_DENIED;
2686 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2688 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2690 if (!NT_STATUS_IS_OK(status)) {
2694 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2695 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2696 TALLOC_FREE(smb_fname_dot);
2697 return map_nt_error_from_unix(errno);
2700 st = smb_fname_dot->st;
2701 TALLOC_FREE(smb_fname_dot);
2703 *ppdata = (char *)SMB_REALLOC(
2704 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2705 if (*ppdata == NULL) {
2706 return NT_STATUS_NO_MEMORY;
2710 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2711 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2713 switch (info_level) {
2714 case SMB_INFO_ALLOCATION:
2716 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2718 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2719 return map_nt_error_from_unix(errno);
2722 block_size = lp_block_size(snum);
2723 if (bsize < block_size) {
2724 uint64_t factor = block_size/bsize;
2729 if (bsize > block_size) {
2730 uint64_t factor = bsize/block_size;
2735 bytes_per_sector = 512;
2736 sectors_per_unit = bsize/bytes_per_sector;
2738 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2739 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2740 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2742 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2743 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2744 SIVAL(pdata,l1_cUnit,dsize);
2745 SIVAL(pdata,l1_cUnitAvail,dfree);
2746 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2750 case SMB_INFO_VOLUME:
2751 /* Return volume name */
2753 * Add volume serial number - hash of a combination of
2754 * the called hostname and the service name.
2756 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2758 * Win2k3 and previous mess this up by sending a name length
2759 * one byte short. I believe only older clients (OS/2 Win9x) use
2760 * this call so try fixing this by adding a terminating null to
2761 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2765 pdata+l2_vol_szVolLabel, vname,
2766 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2767 STR_NOALIGN|STR_TERMINATE);
2768 SCVAL(pdata,l2_vol_cch,len);
2769 data_len = l2_vol_szVolLabel + len;
2770 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2771 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2775 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2776 case SMB_FS_ATTRIBUTE_INFORMATION:
2778 additional_flags = 0;
2779 #if defined(HAVE_SYS_QUOTAS)
2780 additional_flags |= FILE_VOLUME_QUOTAS;
2783 if(lp_nt_acl_support(SNUM(conn))) {
2784 additional_flags |= FILE_PERSISTENT_ACLS;
2787 /* Capabilities are filled in at connection time through STATVFS call */
2788 additional_flags |= conn->fs_capabilities;
2790 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2791 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2792 additional_flags); /* FS ATTRIBUTES */
2794 SIVAL(pdata,4,255); /* Max filename component length */
2795 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2796 and will think we can't do long filenames */
2797 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2798 PTR_DIFF(end_data, pdata+12),
2801 data_len = 12 + len;
2804 case SMB_QUERY_FS_LABEL_INFO:
2805 case SMB_FS_LABEL_INFORMATION:
2806 len = srvstr_push(pdata, flags2, pdata+4, vname,
2807 PTR_DIFF(end_data, pdata+4), 0);
2812 case SMB_QUERY_FS_VOLUME_INFO:
2813 case SMB_FS_VOLUME_INFORMATION:
2816 * Add volume serial number - hash of a combination of
2817 * the called hostname and the service name.
2819 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2820 (str_checksum(get_local_machine_name())<<16));
2822 /* Max label len is 32 characters. */
2823 len = srvstr_push(pdata, flags2, pdata+18, vname,
2824 PTR_DIFF(end_data, pdata+18),
2826 SIVAL(pdata,12,len);
2829 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2830 (int)strlen(vname),vname, lp_servicename(snum)));
2833 case SMB_QUERY_FS_SIZE_INFO:
2834 case SMB_FS_SIZE_INFORMATION:
2836 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2838 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2839 return map_nt_error_from_unix(errno);
2841 block_size = lp_block_size(snum);
2842 if (bsize < block_size) {
2843 uint64_t factor = block_size/bsize;
2848 if (bsize > block_size) {
2849 uint64_t factor = bsize/block_size;
2854 bytes_per_sector = 512;
2855 sectors_per_unit = bsize/bytes_per_sector;
2856 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2857 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2858 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2859 SBIG_UINT(pdata,0,dsize);
2860 SBIG_UINT(pdata,8,dfree);
2861 SIVAL(pdata,16,sectors_per_unit);
2862 SIVAL(pdata,20,bytes_per_sector);
2866 case SMB_FS_FULL_SIZE_INFORMATION:
2868 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2870 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2871 return map_nt_error_from_unix(errno);
2873 block_size = lp_block_size(snum);
2874 if (bsize < block_size) {
2875 uint64_t factor = block_size/bsize;
2880 if (bsize > block_size) {
2881 uint64_t factor = bsize/block_size;
2886 bytes_per_sector = 512;
2887 sectors_per_unit = bsize/bytes_per_sector;
2888 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2889 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2890 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2891 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2892 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2893 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2894 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2895 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2899 case SMB_QUERY_FS_DEVICE_INFO:
2900 case SMB_FS_DEVICE_INFORMATION:
2902 SIVAL(pdata,0,0); /* dev type */
2903 SIVAL(pdata,4,0); /* characteristics */
2906 #ifdef HAVE_SYS_QUOTAS
2907 case SMB_FS_QUOTA_INFORMATION:
2909 * what we have to send --metze:
2911 * Unknown1: 24 NULL bytes
2912 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2913 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2914 * Quota Flags: 2 byte :
2915 * Unknown3: 6 NULL bytes
2919 * details for Quota Flags:
2921 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2922 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2923 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2924 * 0x0001 Enable Quotas: enable quota for this fs
2928 /* we need to fake up a fsp here,
2929 * because its not send in this call
2932 SMB_NTQUOTA_STRUCT quotas;
2935 ZERO_STRUCT(quotas);
2941 if (conn->server_info->utok.uid != sec_initial_uid()) {
2942 DEBUG(0,("set_user_quota: access_denied "
2943 "service [%s] user [%s]\n",
2944 lp_servicename(SNUM(conn)),
2945 conn->server_info->unix_name));
2946 return NT_STATUS_ACCESS_DENIED;
2949 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2950 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2951 return map_nt_error_from_unix(errno);
2956 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2957 lp_servicename(SNUM(conn))));
2959 /* Unknown1 24 NULL bytes*/
2960 SBIG_UINT(pdata,0,(uint64_t)0);
2961 SBIG_UINT(pdata,8,(uint64_t)0);
2962 SBIG_UINT(pdata,16,(uint64_t)0);
2964 /* Default Soft Quota 8 bytes */
2965 SBIG_UINT(pdata,24,quotas.softlim);
2967 /* Default Hard Quota 8 bytes */
2968 SBIG_UINT(pdata,32,quotas.hardlim);
2970 /* Quota flag 2 bytes */
2971 SSVAL(pdata,40,quotas.qflags);
2973 /* Unknown3 6 NULL bytes */
2979 #endif /* HAVE_SYS_QUOTAS */
2980 case SMB_FS_OBJECTID_INFORMATION:
2982 unsigned char objid[16];
2983 struct smb_extended_info extended_info;
2984 memcpy(pdata,create_volume_objectid(conn, objid),16);
2985 samba_extended_info_version (&extended_info);
2986 SIVAL(pdata,16,extended_info.samba_magic);
2987 SIVAL(pdata,20,extended_info.samba_version);
2988 SIVAL(pdata,24,extended_info.samba_subversion);
2989 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2990 memcpy(pdata+36,extended_info.samba_version_string,28);
2996 * Query the version and capabilities of the CIFS UNIX extensions
3000 case SMB_QUERY_CIFS_UNIX_INFO:
3002 bool large_write = lp_min_receive_file_size() &&
3003 !srv_is_signing_active(smbd_server_conn);
3004 bool large_read = !srv_is_signing_active(smbd_server_conn);
3005 int encrypt_caps = 0;
3007 if (!lp_unix_extensions()) {
3008 return NT_STATUS_INVALID_LEVEL;
3011 switch (conn->encrypt_level) {
3017 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3020 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3021 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3022 large_write = false;
3028 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3029 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3031 /* We have POSIX ACLs, pathname, encryption,
3032 * large read/write, and locking capability. */
3034 SBIG_UINT(pdata,4,((uint64_t)(
3035 CIFS_UNIX_POSIX_ACLS_CAP|
3036 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3037 CIFS_UNIX_FCNTL_LOCKS_CAP|
3038 CIFS_UNIX_EXTATTR_CAP|
3039 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3041 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3043 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3047 case SMB_QUERY_POSIX_FS_INFO:
3050 vfs_statvfs_struct svfs;
3052 if (!lp_unix_extensions()) {
3053 return NT_STATUS_INVALID_LEVEL;
3056 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3060 SIVAL(pdata,0,svfs.OptimalTransferSize);
3061 SIVAL(pdata,4,svfs.BlockSize);
3062 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3063 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3064 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3065 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3066 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3067 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3068 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3070 } else if (rc == EOPNOTSUPP) {
3071 return NT_STATUS_INVALID_LEVEL;
3072 #endif /* EOPNOTSUPP */
3074 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3075 return NT_STATUS_DOS(ERRSRV, ERRerror);
3080 case SMB_QUERY_POSIX_WHOAMI:
3086 if (!lp_unix_extensions()) {
3087 return NT_STATUS_INVALID_LEVEL;
3090 if (max_data_bytes < 40) {
3091 return NT_STATUS_BUFFER_TOO_SMALL;
3094 /* We ARE guest if global_sid_Builtin_Guests is
3095 * in our list of SIDs.
3097 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3098 conn->server_info->ptok)) {
3099 flags |= SMB_WHOAMI_GUEST;
3102 /* We are NOT guest if global_sid_Authenticated_Users
3103 * is in our list of SIDs.
3105 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3106 conn->server_info->ptok)) {
3107 flags &= ~SMB_WHOAMI_GUEST;
3110 /* NOTE: 8 bytes for UID/GID, irrespective of native
3111 * platform size. This matches
3112 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3114 data_len = 4 /* flags */
3121 + 4 /* pad/reserved */
3122 + (conn->server_info->utok.ngroups * 8)
3124 + (conn->server_info->ptok->num_sids *
3128 SIVAL(pdata, 0, flags);
3129 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3131 (uint64_t)conn->server_info->utok.uid);
3132 SBIG_UINT(pdata, 16,
3133 (uint64_t)conn->server_info->utok.gid);
3136 if (data_len >= max_data_bytes) {
3137 /* Potential overflow, skip the GIDs and SIDs. */
3139 SIVAL(pdata, 24, 0); /* num_groups */
3140 SIVAL(pdata, 28, 0); /* num_sids */
3141 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3142 SIVAL(pdata, 36, 0); /* reserved */
3148 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3149 SIVAL(pdata, 28, conn->server_info->num_sids);
3151 /* We walk the SID list twice, but this call is fairly
3152 * infrequent, and I don't expect that it's performance
3153 * sensitive -- jpeach
3155 for (i = 0, sid_bytes = 0;
3156 i < conn->server_info->ptok->num_sids; ++i) {
3157 sid_bytes += ndr_size_dom_sid(
3158 &conn->server_info->ptok->user_sids[i],
3163 /* SID list byte count */
3164 SIVAL(pdata, 32, sid_bytes);
3166 /* 4 bytes pad/reserved - must be zero */
3167 SIVAL(pdata, 36, 0);
3171 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3172 SBIG_UINT(pdata, data_len,
3173 (uint64_t)conn->server_info->utok.groups[i]);
3179 i < conn->server_info->ptok->num_sids; ++i) {
3180 int sid_len = ndr_size_dom_sid(
3181 &conn->server_info->ptok->user_sids[i],
3185 sid_linearize(pdata + data_len, sid_len,
3186 &conn->server_info->ptok->user_sids[i]);
3187 data_len += sid_len;
3193 case SMB_MAC_QUERY_FS_INFO:
3195 * Thursby MAC extension... ONLY on NTFS filesystems
3196 * once we do streams then we don't need this
3198 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3200 SIVAL(pdata,84,0x100); /* Don't support mac... */
3205 return NT_STATUS_INVALID_LEVEL;
3208 *ret_data_len = data_len;
3209 return NT_STATUS_OK;
3212 /****************************************************************************
3213 Reply to a TRANS2_QFSINFO (query filesystem info).
3214 ****************************************************************************/
3216 static void call_trans2qfsinfo(connection_struct *conn,
3217 struct smb_request *req,
3218 char **pparams, int total_params,
3219 char **ppdata, int total_data,
3220 unsigned int max_data_bytes)
3222 char *params = *pparams;
3223 uint16_t info_level;
3227 if (total_params < 2) {
3228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3232 info_level = SVAL(params,0);
3234 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3235 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3236 DEBUG(0,("call_trans2qfsinfo: encryption required "
3237 "and info level 0x%x sent.\n",
3238 (unsigned int)info_level));
3239 exit_server_cleanly("encryption required "
3245 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3247 status = smbd_do_qfsinfo(conn, req,
3252 if (!NT_STATUS_IS_OK(status)) {
3253 reply_nterror(req, status);
3257 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3260 DEBUG( 4, ( "%s info_level = %d\n",
3261 smb_fn_name(req->cmd), info_level) );
3266 /****************************************************************************
3267 Reply to a TRANS2_SETFSINFO (set filesystem info).
3268 ****************************************************************************/
3270 static void call_trans2setfsinfo(connection_struct *conn,
3271 struct smb_request *req,
3272 char **pparams, int total_params,
3273 char **ppdata, int total_data,
3274 unsigned int max_data_bytes)
3276 char *pdata = *ppdata;
3277 char *params = *pparams;
3280 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3283 if (total_params < 4) {
3284 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3286 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3290 info_level = SVAL(params,2);
3293 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3294 info_level != SMB_SET_CIFS_UNIX_INFO) {
3295 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3296 "info level (0x%x) on IPC$.\n",
3297 (unsigned int)info_level));
3298 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3303 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3304 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3305 DEBUG(0,("call_trans2setfsinfo: encryption required "
3306 "and info level 0x%x sent.\n",
3307 (unsigned int)info_level));
3308 exit_server_cleanly("encryption required "
3314 switch(info_level) {
3315 case SMB_SET_CIFS_UNIX_INFO:
3317 uint16 client_unix_major;
3318 uint16 client_unix_minor;
3319 uint32 client_unix_cap_low;
3320 uint32 client_unix_cap_high;
3322 if (!lp_unix_extensions()) {
3324 NT_STATUS_INVALID_LEVEL);
3328 /* There should be 12 bytes of capabilities set. */
3329 if (total_data < 8) {
3332 NT_STATUS_INVALID_PARAMETER);
3335 client_unix_major = SVAL(pdata,0);
3336 client_unix_minor = SVAL(pdata,2);
3337 client_unix_cap_low = IVAL(pdata,4);
3338 client_unix_cap_high = IVAL(pdata,8);
3339 /* Just print these values for now. */
3340 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3341 cap_low = 0x%x, cap_high = 0x%x\n",
3342 (unsigned int)client_unix_major,
3343 (unsigned int)client_unix_minor,
3344 (unsigned int)client_unix_cap_low,
3345 (unsigned int)client_unix_cap_high ));
3347 /* Here is where we must switch to posix pathname processing... */
3348 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3349 lp_set_posix_pathnames();
3350 mangle_change_to_posix();
3353 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3354 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3355 /* Client that knows how to do posix locks,
3356 * but not posix open/mkdir operations. Set a
3357 * default type for read/write checks. */
3359 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3365 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3368 size_t param_len = 0;
3369 size_t data_len = total_data;
3371 if (!lp_unix_extensions()) {
3374 NT_STATUS_INVALID_LEVEL);
3378 if (lp_smb_encrypt(SNUM(conn)) == false) {
3381 NT_STATUS_NOT_SUPPORTED);
3385 DEBUG( 4,("call_trans2setfsinfo: "
3386 "request transport encryption.\n"));
3388 status = srv_request_encryption_setup(conn,
3389 (unsigned char **)ppdata,
3391 (unsigned char **)pparams,
3394 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3395 !NT_STATUS_IS_OK(status)) {
3396 reply_nterror(req, status);
3400 send_trans2_replies(conn, req,
3407 if (NT_STATUS_IS_OK(status)) {
3408 /* Server-side transport
3409 * encryption is now *on*. */
3410 status = srv_encryption_start(conn);
3411 if (!NT_STATUS_IS_OK(status)) {
3412 exit_server_cleanly(
3413 "Failure in setting "
3414 "up encrypted transport");
3420 case SMB_FS_QUOTA_INFORMATION:
3422 files_struct *fsp = NULL;
3423 SMB_NTQUOTA_STRUCT quotas;
3425 ZERO_STRUCT(quotas);
3428 if ((conn->server_info->utok.uid != sec_initial_uid())
3429 ||!CAN_WRITE(conn)) {
3430 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3431 lp_servicename(SNUM(conn)),
3432 conn->server_info->unix_name));
3433 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3437 /* note: normaly there're 48 bytes,
3438 * but we didn't use the last 6 bytes for now
3441 fsp = file_fsp(req, SVAL(params,0));
3443 if (!check_fsp_ntquota_handle(conn, req,
3445 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3447 req, NT_STATUS_INVALID_HANDLE);
3451 if (total_data < 42) {
3452 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3456 NT_STATUS_INVALID_PARAMETER);
3460 /* unknown_1 24 NULL bytes in pdata*/
3462 /* the soft quotas 8 bytes (uint64_t)*/
3463 quotas.softlim = (uint64_t)IVAL(pdata,24);
3464 #ifdef LARGE_SMB_OFF_T
3465 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3466 #else /* LARGE_SMB_OFF_T */
3467 if ((IVAL(pdata,28) != 0)&&
3468 ((quotas.softlim != 0xFFFFFFFF)||
3469 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3470 /* more than 32 bits? */
3473 NT_STATUS_INVALID_PARAMETER);
3476 #endif /* LARGE_SMB_OFF_T */
3478 /* the hard quotas 8 bytes (uint64_t)*/
3479 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3480 #ifdef LARGE_SMB_OFF_T
3481 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3482 #else /* LARGE_SMB_OFF_T */
3483 if ((IVAL(pdata,36) != 0)&&
3484 ((quotas.hardlim != 0xFFFFFFFF)||
3485 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3486 /* more than 32 bits? */
3489 NT_STATUS_INVALID_PARAMETER);
3492 #endif /* LARGE_SMB_OFF_T */
3494 /* quota_flags 2 bytes **/
3495 quotas.qflags = SVAL(pdata,40);
3497 /* unknown_2 6 NULL bytes follow*/
3499 /* now set the quotas */
3500 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3501 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3502 reply_nterror(req, map_nt_error_from_unix(errno));
3509 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3511 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3517 * sending this reply works fine,
3518 * but I'm not sure it's the same
3519 * like windows do...
3522 reply_outbuf(req, 10, 0);
3525 #if defined(HAVE_POSIX_ACLS)
3526 /****************************************************************************
3527 Utility function to count the number of entries in a POSIX acl.
3528 ****************************************************************************/
3530 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3532 unsigned int ace_count = 0;
3533 int entry_id = SMB_ACL_FIRST_ENTRY;
3534 SMB_ACL_ENTRY_T entry;
3536 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3538 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3539 entry_id = SMB_ACL_NEXT_ENTRY;
3546 /****************************************************************************
3547 Utility function to marshall a POSIX acl into wire format.
3548 ****************************************************************************/
3550 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3552 int entry_id = SMB_ACL_FIRST_ENTRY;
3553 SMB_ACL_ENTRY_T entry;
3555 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3556 SMB_ACL_TAG_T tagtype;
3557 SMB_ACL_PERMSET_T permset;
3558 unsigned char perms = 0;
3559 unsigned int own_grp;
3562 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3563 entry_id = SMB_ACL_NEXT_ENTRY;
3566 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3567 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3571 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3572 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3576 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3577 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3578 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3580 SCVAL(pdata,1,perms);
3583 case SMB_ACL_USER_OBJ:
3584 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3585 own_grp = (unsigned int)pst->st_ex_uid;
3586 SIVAL(pdata,2,own_grp);
3591 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3593 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3596 own_grp = (unsigned int)*puid;
3597 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3598 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3599 SIVAL(pdata,2,own_grp);
3603 case SMB_ACL_GROUP_OBJ:
3604 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3605 own_grp = (unsigned int)pst->st_ex_gid;
3606 SIVAL(pdata,2,own_grp);
3611 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3613 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3616 own_grp = (unsigned int)*pgid;
3617 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3618 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3619 SIVAL(pdata,2,own_grp);
3624 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3625 SIVAL(pdata,2,0xFFFFFFFF);
3626 SIVAL(pdata,6,0xFFFFFFFF);
3629 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3630 SIVAL(pdata,2,0xFFFFFFFF);
3631 SIVAL(pdata,6,0xFFFFFFFF);
3634 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3637 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3644 /****************************************************************************
3645 Store the FILE_UNIX_BASIC info.
3646 ****************************************************************************/
3648 static char *store_file_unix_basic(connection_struct *conn,
3651 const SMB_STRUCT_STAT *psbuf)
3653 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3654 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3656 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3659 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3662 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3663 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3664 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3667 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3671 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3675 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3678 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3682 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3686 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3689 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3693 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3700 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3701 * the chflags(2) (or equivalent) flags.
3703 * XXX: this really should be behind the VFS interface. To do this, we would
3704 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3705 * Each VFS module could then implement its own mapping as appropriate for the
3706 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3708 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3712 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3716 { UF_IMMUTABLE, EXT_IMMUTABLE },
3720 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3724 { UF_HIDDEN, EXT_HIDDEN },
3727 /* Do not remove. We need to guarantee that this array has at least one
3728 * entry to build on HP-UX.
3734 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3735 uint32 *smb_fflags, uint32 *smb_fmask)
3739 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3740 *smb_fmask |= info2_flags_map[i].smb_fflag;
3741 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3742 *smb_fflags |= info2_flags_map[i].smb_fflag;
3747 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3748 const uint32 smb_fflags,
3749 const uint32 smb_fmask,
3752 uint32 max_fmask = 0;
3755 *stat_fflags = psbuf->st_ex_flags;
3757 /* For each flags requested in smb_fmask, check the state of the
3758 * corresponding flag in smb_fflags and set or clear the matching
3762 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3763 max_fmask |= info2_flags_map[i].smb_fflag;
3764 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3765 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3766 *stat_fflags |= info2_flags_map[i].stat_fflag;
3768 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3773 /* If smb_fmask is asking to set any bits that are not supported by
3774 * our flag mappings, we should fail.
3776 if ((smb_fmask & max_fmask) != smb_fmask) {
3784 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3785 * of file flags and birth (create) time.
3787 static char *store_file_unix_basic_info2(connection_struct *conn,
3790 const SMB_STRUCT_STAT *psbuf)
3792 uint32 file_flags = 0;
3793 uint32 flags_mask = 0;
3795 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3797 /* Create (birth) time 64 bit */
3798 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3801 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3802 SIVAL(pdata, 0, file_flags); /* flags */
3803 SIVAL(pdata, 4, flags_mask); /* mask */
3809 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3810 const struct stream_struct *streams,
3812 unsigned int max_data_bytes,
3813 unsigned int *data_size)
3816 unsigned int ofs = 0;
3818 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3819 unsigned int next_offset;
3821 smb_ucs2_t *namebuf;
3823 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3824 streams[i].name, &namelen) ||
3827 return NT_STATUS_INVALID_PARAMETER;
3831 * name_buf is now null-terminated, we need to marshall as not
3837 SIVAL(data, ofs+4, namelen);
3838 SOFF_T(data, ofs+8, streams[i].size);
3839 SOFF_T(data, ofs+16, streams[i].alloc_size);
3840 memcpy(data+ofs+24, namebuf, namelen);
3841 TALLOC_FREE(namebuf);
3843 next_offset = ofs + 24 + namelen;
3845 if (i == num_streams-1) {
3846 SIVAL(data, ofs, 0);
3849 unsigned int align = ndr_align_size(next_offset, 8);
3851 memset(data+next_offset, 0, align);
3852 next_offset += align;
3854 SIVAL(data, ofs, next_offset - ofs);
3863 return NT_STATUS_OK;
3866 /****************************************************************************
3867 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3868 ****************************************************************************/
3870 static void call_trans2qpipeinfo(connection_struct *conn,
3871 struct smb_request *req,
3872 unsigned int tran_call,
3873 char **pparams, int total_params,
3874 char **ppdata, int total_data,
3875 unsigned int max_data_bytes)
3877 char *params = *pparams;
3878 char *pdata = *ppdata;
3879 unsigned int data_size = 0;
3880 unsigned int param_size = 2;
3885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3889 if (total_params < 4) {
3890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3894 fsp = file_fsp(req, SVAL(params,0));
3895 if (!fsp_is_np(fsp)) {
3896 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3900 info_level = SVAL(params,2);
3902 *pparams = (char *)SMB_REALLOC(*pparams,2);
3903 if (*pparams == NULL) {
3904 reply_nterror(req, NT_STATUS_NO_MEMORY);
3909 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3910 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3911 if (*ppdata == NULL ) {
3912 reply_nterror(req, NT_STATUS_NO_MEMORY);
3917 switch (info_level) {
3918 case SMB_FILE_STANDARD_INFORMATION:
3920 SOFF_T(pdata,0,4096LL);
3927 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3931 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3937 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3938 TALLOC_CTX *mem_ctx,
3939 uint16_t info_level,
3941 const struct smb_filename *smb_fname,
3942 bool delete_pending,
3943 struct timespec write_time_ts,
3945 struct ea_list *ea_list,
3946 int lock_data_count,
3949 unsigned int max_data_bytes,
3951 unsigned int *pdata_size)
3953 char *pdata = *ppdata;
3954 char *dstart, *dend;
3955 unsigned int data_size;
3956 struct timespec create_time_ts, mtime_ts, atime_ts;
3957 time_t create_time, mtime, atime;
3958 SMB_STRUCT_STAT sbuf;
3965 uint64_t file_size = 0;
3967 uint64_t allocation_size = 0;
3968 uint64_t file_index = 0;
3969 uint32_t access_mask = 0;
3971 sbuf = smb_fname->st;
3973 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3974 return NT_STATUS_INVALID_LEVEL;
3977 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
3978 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
3979 info_level, max_data_bytes));
3982 mode = dos_mode_msdfs(conn, smb_fname);
3984 mode = dos_mode(conn, smb_fname);
3987 mode = FILE_ATTRIBUTE_NORMAL;
3989 nlink = sbuf.st_ex_nlink;
3991 if (nlink && (mode&aDIR)) {
3995 if ((nlink > 0) && delete_pending) {
3999 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4000 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4001 if (*ppdata == NULL) {
4002 return NT_STATUS_NO_MEMORY;
4006 dend = dstart + data_size - 1;
4008 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4009 update_stat_ex_mtime(&sbuf, write_time_ts);
4012 create_time_ts = sbuf.st_ex_btime;
4013 mtime_ts = sbuf.st_ex_mtime;
4014 atime_ts = sbuf.st_ex_atime;
4016 if (lp_dos_filetime_resolution(SNUM(conn))) {
4017 dos_filetime_timespec(&create_time_ts);
4018 dos_filetime_timespec(&mtime_ts);
4019 dos_filetime_timespec(&atime_ts);
4022 create_time = convert_timespec_to_time_t(create_time_ts);
4023 mtime = convert_timespec_to_time_t(mtime_ts);
4024 atime = convert_timespec_to_time_t(atime_ts);
4026 p = strrchr_m(smb_fname->base_name,'/');
4028 base_name = smb_fname->base_name;
4032 /* NT expects the name to be in an exact form of the *full*
4033 filename. See the trans2 torture test */
4034 if (ISDOT(base_name)) {
4035 dos_fname = talloc_strdup(mem_ctx, "\\");
4037 return NT_STATUS_NO_MEMORY;
4040 dos_fname = talloc_asprintf(mem_ctx,
4042 smb_fname->base_name);
4044 return NT_STATUS_NO_MEMORY;
4046 if (is_ntfs_stream_smb_fname(smb_fname)) {
4047 dos_fname = talloc_asprintf(dos_fname, "%s",
4048 smb_fname->stream_name);
4050 return NT_STATUS_NO_MEMORY;
4054 string_replace(dos_fname, '/', '\\');
4057 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4060 /* Do we have this path open ? */
4062 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4063 fsp1 = file_find_di_first(fileid);
4064 if (fsp1 && fsp1->initial_allocation_size) {
4065 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4069 if (!(mode & aDIR)) {
4070 file_size = get_file_size_stat(&sbuf);
4074 pos = fsp->fh->position_information;
4078 access_mask = fsp->access_mask;
4080 /* GENERIC_EXECUTE mapping from Windows */
4081 access_mask = 0x12019F;
4084 /* This should be an index number - looks like
4087 I think this causes us to fail the IFSKIT
4088 BasicFileInformationTest. -tpot */
4089 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4090 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4092 switch (info_level) {
4093 case SMB_INFO_STANDARD:
4094 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4096 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4097 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4098 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4099 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4100 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4101 SSVAL(pdata,l1_attrFile,mode);
4104 case SMB_INFO_QUERY_EA_SIZE:
4106 unsigned int ea_size =
4107 estimate_ea_size(conn, fsp,
4108 smb_fname->base_name);
4109 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4111 srv_put_dos_date2(pdata,0,create_time);
4112 srv_put_dos_date2(pdata,4,atime);
4113 srv_put_dos_date2(pdata,8,mtime); /* write time */
4114 SIVAL(pdata,12,(uint32)file_size);
4115 SIVAL(pdata,16,(uint32)allocation_size);
4116 SSVAL(pdata,20,mode);
4117 SIVAL(pdata,22,ea_size);
4121 case SMB_INFO_IS_NAME_VALID:
4122 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4124 /* os/2 needs this ? really ?*/
4125 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4127 /* This is only reached for qpathinfo */
4131 case SMB_INFO_QUERY_EAS_FROM_LIST:
4133 size_t total_ea_len = 0;
4134 struct ea_list *ea_file_list = NULL;
4136 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4139 get_ea_list_from_file(mem_ctx, conn, fsp,
4140 smb_fname->base_name,
4142 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4144 if (!ea_list || (total_ea_len > data_size)) {
4146 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4150 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4154 case SMB_INFO_QUERY_ALL_EAS:
4156 /* We have data_size bytes to put EA's into. */
4157 size_t total_ea_len = 0;
4159 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4161 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4162 smb_fname->base_name,
4164 if (!ea_list || (total_ea_len > data_size)) {
4166 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4170 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4174 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4176 /* We have data_size bytes to put EA's into. */
4177 size_t total_ea_len = 0;
4178 struct ea_list *ea_file_list = NULL;
4180 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4182 /*TODO: add filtering and index handling */
4185 get_ea_list_from_file(mem_ctx, conn, fsp,
4186 smb_fname->base_name,
4188 if (!ea_file_list) {
4189 return NT_STATUS_NO_EAS_ON_FILE;
4192 status = fill_ea_chained_buffer(mem_ctx,
4196 conn, ea_file_list);
4197 if (!NT_STATUS_IS_OK(status)) {
4203 case SMB_FILE_BASIC_INFORMATION:
4204 case SMB_QUERY_FILE_BASIC_INFO:
4206 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4207 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4208 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4210 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4214 put_long_date_timespec(pdata,create_time_ts);
4215 put_long_date_timespec(pdata+8,atime_ts);
4216 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4217 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4218 SIVAL(pdata,32,mode);
4220 DEBUG(5,("SMB_QFBI - "));
4221 DEBUG(5,("create: %s ", ctime(&create_time)));
4222 DEBUG(5,("access: %s ", ctime(&atime)));
4223 DEBUG(5,("write: %s ", ctime(&mtime)));
4224 DEBUG(5,("change: %s ", ctime(&mtime)));
4225 DEBUG(5,("mode: %x\n", mode));
4228 case SMB_FILE_STANDARD_INFORMATION:
4229 case SMB_QUERY_FILE_STANDARD_INFO:
4231 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4233 SOFF_T(pdata,0,allocation_size);
4234 SOFF_T(pdata,8,file_size);
4235 SIVAL(pdata,16,nlink);
4236 SCVAL(pdata,20,delete_pending?1:0);
4237 SCVAL(pdata,21,(mode&aDIR)?1:0);
4238 SSVAL(pdata,22,0); /* Padding. */
4241 case SMB_FILE_EA_INFORMATION:
4242 case SMB_QUERY_FILE_EA_INFO:
4244 unsigned int ea_size =
4245 estimate_ea_size(conn, fsp, smb_fname->base_name);
4246 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4248 SIVAL(pdata,0,ea_size);
4252 /* Get the 8.3 name - used if NT SMB was negotiated. */
4253 case SMB_QUERY_FILE_ALT_NAME_INFO:
4254 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4257 char mangled_name[13];
4258 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4259 if (!name_to_8_3(base_name,mangled_name,
4260 True,conn->params)) {
4261 return NT_STATUS_NO_MEMORY;
4263 len = srvstr_push(dstart, flags2,
4264 pdata+4, mangled_name,
4265 PTR_DIFF(dend, pdata+4),
4267 data_size = 4 + len;
4272 case SMB_QUERY_FILE_NAME_INFO:
4276 this must be *exactly* right for ACLs on mapped drives to work
4278 len = srvstr_push(dstart, flags2,
4280 PTR_DIFF(dend, pdata+4),
4282 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4283 data_size = 4 + len;
4288 case SMB_FILE_ALLOCATION_INFORMATION:
4289 case SMB_QUERY_FILE_ALLOCATION_INFO:
4290 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4292 SOFF_T(pdata,0,allocation_size);
4295 case SMB_FILE_END_OF_FILE_INFORMATION:
4296 case SMB_QUERY_FILE_END_OF_FILEINFO:
4297 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4299 SOFF_T(pdata,0,file_size);
4302 case SMB_QUERY_FILE_ALL_INFO:
4303 case SMB_FILE_ALL_INFORMATION:
4306 unsigned int ea_size =
4307 estimate_ea_size(conn, fsp, smb_fname->base_name);
4308 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4309 put_long_date_timespec(pdata,create_time_ts);
4310 put_long_date_timespec(pdata+8,atime_ts);
4311 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4312 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4313 SIVAL(pdata,32,mode);
4314 SIVAL(pdata,36,0); /* padding. */
4316 SOFF_T(pdata,0,allocation_size);
4317 SOFF_T(pdata,8,file_size);
4318 SIVAL(pdata,16,nlink);
4319 SCVAL(pdata,20,delete_pending);
4320 SCVAL(pdata,21,(mode&aDIR)?1:0);
4323 SIVAL(pdata,0,ea_size);
4324 pdata += 4; /* EA info */
4325 len = srvstr_push(dstart, flags2,
4327 PTR_DIFF(dend, pdata+4),
4331 data_size = PTR_DIFF(pdata,(*ppdata));
4335 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4338 unsigned int ea_size =
4339 estimate_ea_size(conn, fsp, smb_fname->base_name);
4340 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4341 put_long_date_timespec(pdata+0x00,create_time_ts);
4342 put_long_date_timespec(pdata+0x08,atime_ts);
4343 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4344 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4345 SIVAL(pdata, 0x20, mode);
4346 SIVAL(pdata, 0x24, 0); /* padding. */
4347 SBVAL(pdata, 0x28, allocation_size);
4348 SBVAL(pdata, 0x30, file_size);
4349 SIVAL(pdata, 0x38, nlink);
4350 SCVAL(pdata, 0x3C, delete_pending);
4351 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4352 SSVAL(pdata, 0x3E, 0); /* padding */
4353 SBVAL(pdata, 0x40, file_index);
4354 SIVAL(pdata, 0x48, ea_size);
4355 SIVAL(pdata, 0x4C, access_mask);
4356 SBVAL(pdata, 0x50, pos);
4357 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4358 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4362 len = srvstr_push(dstart, flags2,
4364 PTR_DIFF(dend, pdata+4),
4368 data_size = PTR_DIFF(pdata,(*ppdata));
4371 case SMB_FILE_INTERNAL_INFORMATION:
4373 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4374 SBVAL(pdata, 0, file_index);
4378 case SMB_FILE_ACCESS_INFORMATION:
4379 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4380 SIVAL(pdata, 0, access_mask);
4384 case SMB_FILE_NAME_INFORMATION:
4385 /* Pathname with leading '\'. */
4388 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4389 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4390 SIVAL(pdata,0,byte_len);
4391 data_size = 4 + byte_len;
4395 case SMB_FILE_DISPOSITION_INFORMATION:
4396 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4398 SCVAL(pdata,0,delete_pending);
4401 case SMB_FILE_POSITION_INFORMATION:
4402 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4404 SOFF_T(pdata,0,pos);
4407 case SMB_FILE_MODE_INFORMATION:
4408 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4409 SIVAL(pdata,0,mode);
4413 case SMB_FILE_ALIGNMENT_INFORMATION:
4414 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4415 SIVAL(pdata,0,0); /* No alignment needed. */
4420 * NT4 server just returns "invalid query" to this - if we try
4421 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4424 /* The first statement above is false - verified using Thursby
4425 * client against NT4 -- gcolley.
4427 case SMB_QUERY_FILE_STREAM_INFO:
4428 case SMB_FILE_STREAM_INFORMATION: {
4429 unsigned int num_streams;
4430 struct stream_struct *streams;
4432 DEBUG(10,("smbd_do_qfilepathinfo: "
4433 "SMB_FILE_STREAM_INFORMATION\n"));
4435 if (is_ntfs_stream_smb_fname(smb_fname)) {
4436 return NT_STATUS_INVALID_PARAMETER;
4439 status = SMB_VFS_STREAMINFO(
4440 conn, fsp, smb_fname->base_name, talloc_tos(),
4441 &num_streams, &streams);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 DEBUG(10, ("could not get stream info: %s\n",
4445 nt_errstr(status)));
4449 status = marshall_stream_info(num_streams, streams,
4450 pdata, max_data_bytes,
4453 if (!NT_STATUS_IS_OK(status)) {
4454 DEBUG(10, ("marshall_stream_info failed: %s\n",
4455 nt_errstr(status)));
4459 TALLOC_FREE(streams);
4463 case SMB_QUERY_COMPRESSION_INFO:
4464 case SMB_FILE_COMPRESSION_INFORMATION:
4465 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4466 SOFF_T(pdata,0,file_size);
4467 SIVAL(pdata,8,0); /* ??? */
4468 SIVAL(pdata,12,0); /* ??? */
4472 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4473 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4474 put_long_date_timespec(pdata,create_time_ts);
4475 put_long_date_timespec(pdata+8,atime_ts);
4476 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4477 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4478 SOFF_T(pdata,32,allocation_size);
4479 SOFF_T(pdata,40,file_size);
4480 SIVAL(pdata,48,mode);
4481 SIVAL(pdata,52,0); /* ??? */
4485 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4486 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4487 SIVAL(pdata,0,mode);
4493 * CIFS UNIX Extensions.
4496 case SMB_QUERY_FILE_UNIX_BASIC:
4498 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4499 data_size = PTR_DIFF(pdata,(*ppdata));
4503 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4505 for (i=0; i<100; i++)
4506 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4512 case SMB_QUERY_FILE_UNIX_INFO2:
4514 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4515 data_size = PTR_DIFF(pdata,(*ppdata));
4519 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4521 for (i=0; i<100; i++)
4522 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4528 case SMB_QUERY_FILE_UNIX_LINK:
4531 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4534 return NT_STATUS_NO_MEMORY;
4537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4539 if(!S_ISLNK(sbuf.st_ex_mode)) {
4540 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4543 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4545 len = SMB_VFS_READLINK(conn,
4546 smb_fname->base_name,
4549 return map_nt_error_from_unix(errno);
4552 len = srvstr_push(dstart, flags2,
4554 PTR_DIFF(dend, pdata),
4557 data_size = PTR_DIFF(pdata,(*ppdata));
4562 #if defined(HAVE_POSIX_ACLS)
4563 case SMB_QUERY_POSIX_ACL:
4565 SMB_ACL_T file_acl = NULL;
4566 SMB_ACL_T def_acl = NULL;
4567 uint16 num_file_acls = 0;
4568 uint16 num_def_acls = 0;
4570 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4571 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4574 SMB_VFS_SYS_ACL_GET_FILE(conn,
4575 smb_fname->base_name,
4576 SMB_ACL_TYPE_ACCESS);
4579 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4580 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4581 "not implemented on "
4582 "filesystem containing %s\n",
4583 smb_fname->base_name));
4584 return NT_STATUS_NOT_IMPLEMENTED;
4587 if (S_ISDIR(sbuf.st_ex_mode)) {
4588 if (fsp && fsp->is_directory) {
4590 SMB_VFS_SYS_ACL_GET_FILE(
4592 fsp->fsp_name->base_name,
4593 SMB_ACL_TYPE_DEFAULT);
4596 SMB_VFS_SYS_ACL_GET_FILE(
4598 smb_fname->base_name,
4599 SMB_ACL_TYPE_DEFAULT);
4601 def_acl = free_empty_sys_acl(conn, def_acl);
4604 num_file_acls = count_acl_entries(conn, file_acl);
4605 num_def_acls = count_acl_entries(conn, def_acl);
4607 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4608 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4610 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4611 SMB_POSIX_ACL_HEADER_SIZE) ));
4613 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4616 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4618 return NT_STATUS_BUFFER_TOO_SMALL;
4621 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4622 SSVAL(pdata,2,num_file_acls);
4623 SSVAL(pdata,4,num_def_acls);
4624 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4626 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4629 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4631 return NT_STATUS_INTERNAL_ERROR;
4633 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4635 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4638 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4640 return NT_STATUS_INTERNAL_ERROR;
4644 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4647 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4649 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4655 case SMB_QUERY_POSIX_LOCK:
4660 enum brl_type lock_type;
4662 /* We need an open file with a real fd for this. */
4663 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4664 return NT_STATUS_INVALID_LEVEL;
4667 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4668 return NT_STATUS_INVALID_PARAMETER;
4671 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4672 case POSIX_LOCK_TYPE_READ:
4673 lock_type = READ_LOCK;
4675 case POSIX_LOCK_TYPE_WRITE:
4676 lock_type = WRITE_LOCK;
4678 case POSIX_LOCK_TYPE_UNLOCK:
4680 /* There's no point in asking for an unlock... */
4681 return NT_STATUS_INVALID_PARAMETER;
4684 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4685 #if defined(HAVE_LONGLONG)
4686 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4687 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4688 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4689 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4690 #else /* HAVE_LONGLONG */
4691 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4692 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4693 #endif /* HAVE_LONGLONG */
4695 status = query_lock(fsp,
4702 if (ERROR_WAS_LOCK_DENIED(status)) {
4703 /* Here we need to report who has it locked... */
4704 data_size = POSIX_LOCK_DATA_SIZE;
4706 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4707 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4708 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4709 #if defined(HAVE_LONGLONG)
4710 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4711 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4712 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4713 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4714 #else /* HAVE_LONGLONG */
4715 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4716 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4717 #endif /* HAVE_LONGLONG */
4719 } else if (NT_STATUS_IS_OK(status)) {
4720 /* For success we just return a copy of what we sent
4721 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4722 data_size = POSIX_LOCK_DATA_SIZE;
4723 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4724 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4732 return NT_STATUS_INVALID_LEVEL;
4735 *pdata_size = data_size;
4736 return NT_STATUS_OK;
4739 /****************************************************************************
4740 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4741 file name or file id).
4742 ****************************************************************************/
4744 static void call_trans2qfilepathinfo(connection_struct *conn,
4745 struct smb_request *req,
4746 unsigned int tran_call,
4747 char **pparams, int total_params,
4748 char **ppdata, int total_data,
4749 unsigned int max_data_bytes)
4751 char *params = *pparams;
4752 char *pdata = *ppdata;
4754 unsigned int data_size = 0;
4755 unsigned int param_size = 2;
4756 struct smb_filename *smb_fname = NULL;
4757 bool delete_pending = False;
4758 struct timespec write_time_ts;
4759 files_struct *fsp = NULL;
4760 struct file_id fileid;
4761 struct ea_list *ea_list = NULL;
4762 int lock_data_count = 0;
4763 char *lock_data = NULL;
4764 bool ms_dfs_link = false;
4765 NTSTATUS status = NT_STATUS_OK;
4768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4772 ZERO_STRUCT(write_time_ts);
4774 if (tran_call == TRANSACT2_QFILEINFO) {
4775 if (total_params < 4) {
4776 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4781 call_trans2qpipeinfo(conn, req, tran_call,
4782 pparams, total_params,
4788 fsp = file_fsp(req, SVAL(params,0));
4789 info_level = SVAL(params,2);
4791 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4793 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4794 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4798 /* Initial check for valid fsp ptr. */
4799 if (!check_fsp_open(conn, req, fsp)) {
4803 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4805 if (!NT_STATUS_IS_OK(status)) {
4806 reply_nterror(req, status);
4810 if(fsp->fake_file_handle) {
4812 * This is actually for the QUOTA_FAKE_FILE --metze
4815 /* We know this name is ok, it's already passed the checks. */
4817 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4819 * This is actually a QFILEINFO on a directory
4820 * handle (returned from an NT SMB). NT5.0 seems
4821 * to do this call. JRA.
4824 if (INFO_LEVEL_IS_UNIX(info_level)) {
4825 /* Always do lstat for UNIX calls. */
4826 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4827 DEBUG(3,("call_trans2qfilepathinfo: "
4828 "SMB_VFS_LSTAT of %s failed "
4830 smb_fname_str_dbg(smb_fname),
4833 map_nt_error_from_unix(errno));
4836 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4837 DEBUG(3,("call_trans2qfilepathinfo: "
4838 "SMB_VFS_STAT of %s failed (%s)\n",
4839 smb_fname_str_dbg(smb_fname),
4842 map_nt_error_from_unix(errno));
4846 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4847 get_file_infos(fileid, &delete_pending, &write_time_ts);
4850 * Original code - this is an open file.
4852 if (!check_fsp(conn, req, fsp)) {
4856 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4857 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4858 fsp->fnum, strerror(errno)));
4860 map_nt_error_from_unix(errno));
4863 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4864 get_file_infos(fileid, &delete_pending, &write_time_ts);
4871 if (total_params < 7) {
4872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4876 info_level = SVAL(params,0);
4878 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4880 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4881 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4885 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4887 STR_TERMINATE, &status);
4888 if (!NT_STATUS_IS_OK(status)) {
4889 reply_nterror(req, status);
4893 status = filename_convert(req,
4895 req->flags2 & FLAGS2_DFS_PATHNAMES,
4900 if (!NT_STATUS_IS_OK(status)) {
4901 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4902 reply_botherror(req,
4903 NT_STATUS_PATH_NOT_COVERED,
4904 ERRSRV, ERRbadpath);
4907 reply_nterror(req, status);
4911 /* If this is a stream, check if there is a delete_pending. */
4912 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4913 && is_ntfs_stream_smb_fname(smb_fname)) {
4914 struct smb_filename *smb_fname_base = NULL;
4916 /* Create an smb_filename with stream_name == NULL. */
4918 create_synthetic_smb_fname(talloc_tos(),
4919 smb_fname->base_name,
4922 if (!NT_STATUS_IS_OK(status)) {
4923 reply_nterror(req, status);
4927 if (INFO_LEVEL_IS_UNIX(info_level)) {
4928 /* Always do lstat for UNIX calls. */
4929 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4930 DEBUG(3,("call_trans2qfilepathinfo: "
4931 "SMB_VFS_LSTAT of %s failed "
4933 smb_fname_str_dbg(smb_fname_base),
4935 TALLOC_FREE(smb_fname_base);
4937 map_nt_error_from_unix(errno));
4941 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4942 DEBUG(3,("call_trans2qfilepathinfo: "
4943 "fileinfo of %s failed "
4945 smb_fname_str_dbg(smb_fname_base),
4947 TALLOC_FREE(smb_fname_base);
4949 map_nt_error_from_unix(errno));
4954 fileid = vfs_file_id_from_sbuf(conn,
4955 &smb_fname_base->st);
4956 TALLOC_FREE(smb_fname_base);
4957 get_file_infos(fileid, &delete_pending, NULL);
4958 if (delete_pending) {
4959 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4964 if (INFO_LEVEL_IS_UNIX(info_level)) {
4965 /* Always do lstat for UNIX calls. */
4966 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4967 DEBUG(3,("call_trans2qfilepathinfo: "
4968 "SMB_VFS_LSTAT of %s failed (%s)\n",
4969 smb_fname_str_dbg(smb_fname),
4972 map_nt_error_from_unix(errno));
4976 } else if (!VALID_STAT(smb_fname->st) &&
4977 SMB_VFS_STAT(conn, smb_fname) &&
4978 (info_level != SMB_INFO_IS_NAME_VALID)) {
4979 ms_dfs_link = check_msdfs_link(conn,
4980 smb_fname->base_name,
4984 DEBUG(3,("call_trans2qfilepathinfo: "
4985 "SMB_VFS_STAT of %s failed (%s)\n",
4986 smb_fname_str_dbg(smb_fname),
4989 map_nt_error_from_unix(errno));
4994 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4995 get_file_infos(fileid, &delete_pending, &write_time_ts);
4996 if (delete_pending) {
4997 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5002 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5003 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5004 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5006 /* Pull out any data sent here before we realloc. */
5007 switch (info_level) {
5008 case SMB_INFO_QUERY_EAS_FROM_LIST:
5010 /* Pull any EA list from the data portion. */
5013 if (total_data < 4) {
5015 req, NT_STATUS_INVALID_PARAMETER);
5018 ea_size = IVAL(pdata,0);
5020 if (total_data > 0 && ea_size != total_data) {
5021 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5022 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5024 req, NT_STATUS_INVALID_PARAMETER);
5028 if (!lp_ea_support(SNUM(conn))) {
5029 reply_doserror(req, ERRDOS,
5030 ERReasnotsupported);
5034 /* Pull out the list of names. */
5035 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5038 req, NT_STATUS_INVALID_PARAMETER);
5044 case SMB_QUERY_POSIX_LOCK:
5046 if (fsp == NULL || fsp->fh->fd == -1) {
5047 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5051 if (total_data != POSIX_LOCK_DATA_SIZE) {
5053 req, NT_STATUS_INVALID_PARAMETER);
5057 /* Copy the lock range data. */
5058 lock_data = (char *)TALLOC_MEMDUP(
5059 req, pdata, total_data);
5061 reply_nterror(req, NT_STATUS_NO_MEMORY);
5064 lock_data_count = total_data;
5070 *pparams = (char *)SMB_REALLOC(*pparams,2);
5071 if (*pparams == NULL) {
5072 reply_nterror(req, NT_STATUS_NO_MEMORY);
5079 * draft-leach-cifs-v1-spec-02.txt
5080 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5083 * The requested information is placed in the Data portion of the
5084 * transaction response. For the information levels greater than 0x100,
5085 * the transaction response has 1 parameter word which should be
5086 * ignored by the client.
5088 * However Windows only follows this rule for the IS_NAME_VALID call.
5090 switch (info_level) {
5091 case SMB_INFO_IS_NAME_VALID:
5096 if ((info_level & 0xFF00) == 0xFF00) {
5098 * We use levels that start with 0xFF00
5099 * internally to represent SMB2 specific levels
5101 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5105 status = smbd_do_qfilepathinfo(conn, req, info_level,
5107 delete_pending, write_time_ts,
5108 ms_dfs_link, ea_list,
5109 lock_data_count, lock_data,
5110 req->flags2, max_data_bytes,
5111 ppdata, &data_size);
5112 if (!NT_STATUS_IS_OK(status)) {
5113 reply_nterror(req, status);
5117 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5123 /****************************************************************************
5124 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5126 ****************************************************************************/
5128 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5129 connection_struct *conn,
5130 const struct smb_filename *smb_fname_old,
5131 const struct smb_filename *smb_fname_new)
5133 NTSTATUS status = NT_STATUS_OK;
5135 /* source must already exist. */
5136 if (!VALID_STAT(smb_fname_old->st)) {
5137 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5140 /* Disallow if newname already exists. */
5141 if (VALID_STAT(smb_fname_new->st)) {
5142 return NT_STATUS_OBJECT_NAME_COLLISION;
5145 /* No links from a directory. */
5146 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5147 return NT_STATUS_FILE_IS_A_DIRECTORY;
5150 /* Setting a hardlink to/from a stream isn't currently supported. */
5151 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5152 is_ntfs_stream_smb_fname(smb_fname_new)) {
5153 return NT_STATUS_INVALID_PARAMETER;
5156 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5157 smb_fname_old->base_name, smb_fname_new->base_name));
5159 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5160 smb_fname_new->base_name) != 0) {
5161 status = map_nt_error_from_unix(errno);
5162 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5163 nt_errstr(status), smb_fname_old->base_name,
5164 smb_fname_new->base_name));
5169 /****************************************************************************
5170 Deal with setting the time from any of the setfilepathinfo functions.
5171 ****************************************************************************/
5173 NTSTATUS smb_set_file_time(connection_struct *conn,
5175 const struct smb_filename *smb_fname,
5176 struct smb_file_time *ft,
5177 bool setting_write_time)
5179 struct smb_filename *smb_fname_base = NULL;
5181 FILE_NOTIFY_CHANGE_LAST_ACCESS
5182 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5183 bool set_createtime = false;
5184 bool set_ctime = false;
5187 if (!VALID_STAT(smb_fname->st)) {
5188 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5191 /* get some defaults (no modifications) if any info is zero or -1. */
5192 if (null_timespec(ft->create_time)) {
5193 ft->create_time = smb_fname->st.st_ex_btime;
5195 set_createtime = true;
5198 if (null_timespec(ft->ctime)) {
5199 ft->ctime = smb_fname->st.st_ex_ctime;
5204 if (null_timespec(ft->atime)) {
5205 ft->atime= smb_fname->st.st_ex_atime;
5206 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5209 if (null_timespec(ft->mtime)) {
5210 ft->mtime = smb_fname->st.st_ex_mtime;
5211 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5214 if (!setting_write_time) {
5215 /* ft->mtime comes from change time, not write time. */
5216 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5219 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5220 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5221 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5222 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5223 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5224 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5225 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5226 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5229 * Try and set the times of this file if
5230 * they are different from the current values.
5234 struct timespec mts = smb_fname->st.st_ex_mtime;
5235 struct timespec ats = smb_fname->st.st_ex_atime;
5236 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5237 (timespec_compare(&ft->mtime, &mts) == 0)) {
5238 if (set_createtime || set_ctime) {
5239 notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_LAST_WRITE,
5240 smb_fname->base_name);
5242 return NT_STATUS_OK;
5246 if (setting_write_time) {
5248 * This was a Windows setfileinfo on an open file.
5249 * NT does this a lot. We also need to
5250 * set the time here, as it can be read by
5251 * FindFirst/FindNext and with the patch for bug #2045
5252 * in smbd/fileio.c it ensures that this timestamp is
5253 * kept sticky even after a write. We save the request
5254 * away and will set it on file close and after a write. JRA.
5257 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5258 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5261 if (fsp->base_fsp) {
5262 set_sticky_write_time_fsp(fsp->base_fsp,
5265 set_sticky_write_time_fsp(fsp, ft->mtime);
5268 set_sticky_write_time_path(
5269 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5274 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5276 /* Always call ntimes on the base, even if a stream was passed in. */
5277 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5278 NULL, &smb_fname->st,
5280 if (!NT_STATUS_IS_OK(status)) {
5284 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5285 TALLOC_FREE(smb_fname_base);
5286 return map_nt_error_from_unix(errno);
5288 TALLOC_FREE(smb_fname_base);
5290 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5291 smb_fname->base_name);
5292 return NT_STATUS_OK;
5295 /****************************************************************************
5296 Deal with setting the dosmode from any of the setfilepathinfo functions.
5297 ****************************************************************************/
5299 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5300 const struct smb_filename *smb_fname,
5303 struct smb_filename *smb_fname_base = NULL;
5306 if (!VALID_STAT(smb_fname->st)) {
5307 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5310 /* Always operate on the base_name, even if a stream was passed in. */
5311 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5312 NULL, &smb_fname->st,
5314 if (!NT_STATUS_IS_OK(status)) {
5319 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5326 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5328 /* check the mode isn't different, before changing it */
5329 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5330 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5331 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5332 (unsigned int)dosmode));
5334 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5336 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5338 smb_fname_str_dbg(smb_fname_base),
5340 status = map_nt_error_from_unix(errno);
5344 status = NT_STATUS_OK;
5346 TALLOC_FREE(smb_fname_base);
5350 /****************************************************************************
5351 Deal with setting the size from any of the setfilepathinfo functions.
5352 ****************************************************************************/
5354 static NTSTATUS smb_set_file_size(connection_struct *conn,
5355 struct smb_request *req,
5357 const struct smb_filename *smb_fname,
5358 const SMB_STRUCT_STAT *psbuf,
5361 NTSTATUS status = NT_STATUS_OK;
5362 struct smb_filename *smb_fname_tmp = NULL;
5363 files_struct *new_fsp = NULL;
5365 if (!VALID_STAT(*psbuf)) {
5366 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5369 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5371 if (size == get_file_size_stat(psbuf)) {
5372 return NT_STATUS_OK;
5375 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5376 smb_fname_str_dbg(smb_fname), (double)size));
5378 if (fsp && fsp->fh->fd != -1) {
5379 /* Handle based call. */
5380 if (vfs_set_filelen(fsp, size) == -1) {
5381 return map_nt_error_from_unix(errno);
5383 trigger_write_time_update_immediate(fsp);
5384 return NT_STATUS_OK;
5387 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5388 if (!NT_STATUS_IS_OK(status)) {
5392 smb_fname_tmp->st = *psbuf;
5394 status = SMB_VFS_CREATE_FILE(
5397 0, /* root_dir_fid */
5398 smb_fname_tmp, /* fname */
5399 FILE_WRITE_ATTRIBUTES, /* access_mask */
5400 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5402 FILE_OPEN, /* create_disposition*/
5403 0, /* create_options */
5404 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5405 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5406 0, /* allocation_size */
5409 &new_fsp, /* result */
5412 TALLOC_FREE(smb_fname_tmp);
5414 if (!NT_STATUS_IS_OK(status)) {
5415 /* NB. We check for open_was_deferred in the caller. */
5419 if (vfs_set_filelen(new_fsp, size) == -1) {
5420 status = map_nt_error_from_unix(errno);
5421 close_file(req, new_fsp,NORMAL_CLOSE);
5425 trigger_write_time_update_immediate(new_fsp);
5426 close_file(req, new_fsp,NORMAL_CLOSE);
5427 return NT_STATUS_OK;
5430 /****************************************************************************
5431 Deal with SMB_INFO_SET_EA.
5432 ****************************************************************************/
5434 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5438 const struct smb_filename *smb_fname)
5440 struct ea_list *ea_list = NULL;
5441 TALLOC_CTX *ctx = NULL;
5442 NTSTATUS status = NT_STATUS_OK;
5444 if (total_data < 10) {
5446 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5447 length. They seem to have no effect. Bug #3212. JRA */
5449 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5450 /* We're done. We only get EA info in this call. */
5451 return NT_STATUS_OK;
5454 return NT_STATUS_INVALID_PARAMETER;
5457 if (IVAL(pdata,0) > total_data) {
5458 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5459 IVAL(pdata,0), (unsigned int)total_data));
5460 return NT_STATUS_INVALID_PARAMETER;
5464 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5466 return NT_STATUS_INVALID_PARAMETER;
5468 status = set_ea(conn, fsp, smb_fname, ea_list);
5473 /****************************************************************************
5474 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5475 ****************************************************************************/
5477 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5481 const struct smb_filename *smb_fname)
5483 NTSTATUS status = NT_STATUS_OK;
5484 bool delete_on_close;
5487 if (total_data < 1) {
5488 return NT_STATUS_INVALID_PARAMETER;
5492 return NT_STATUS_INVALID_HANDLE;
5495 delete_on_close = (CVAL(pdata,0) ? True : False);
5496 dosmode = dos_mode(conn, smb_fname);
5498 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5499 "delete_on_close = %u\n",
5500 smb_fname_str_dbg(smb_fname),
5501 (unsigned int)dosmode,
5502 (unsigned int)delete_on_close ));
5504 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5506 if (!NT_STATUS_IS_OK(status)) {
5510 /* The set is across all open files on this dev/inode pair. */
5511 if (!set_delete_on_close(fsp, delete_on_close,
5512 &conn->server_info->utok)) {
5513 return NT_STATUS_ACCESS_DENIED;
5515 return NT_STATUS_OK;
5518 /****************************************************************************
5519 Deal with SMB_FILE_POSITION_INFORMATION.
5520 ****************************************************************************/
5522 static NTSTATUS smb_file_position_information(connection_struct *conn,
5527 uint64_t position_information;
5529 if (total_data < 8) {
5530 return NT_STATUS_INVALID_PARAMETER;
5534 /* Ignore on pathname based set. */
5535 return NT_STATUS_OK;
5538 position_information = (uint64_t)IVAL(pdata,0);
5539 #ifdef LARGE_SMB_OFF_T
5540 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5541 #else /* LARGE_SMB_OFF_T */
5542 if (IVAL(pdata,4) != 0) {
5543 /* more than 32 bits? */
5544 return NT_STATUS_INVALID_PARAMETER;
5546 #endif /* LARGE_SMB_OFF_T */
5548 DEBUG(10,("smb_file_position_information: Set file position "
5549 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5550 (double)position_information));
5551 fsp->fh->position_information = position_information;
5552 return NT_STATUS_OK;
5555 /****************************************************************************
5556 Deal with SMB_FILE_MODE_INFORMATION.
5557 ****************************************************************************/
5559 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5565 if (total_data < 4) {
5566 return NT_STATUS_INVALID_PARAMETER;
5568 mode = IVAL(pdata,0);
5569 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5570 return NT_STATUS_INVALID_PARAMETER;
5572 return NT_STATUS_OK;
5575 /****************************************************************************
5576 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5577 ****************************************************************************/
5579 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5580 struct smb_request *req,
5583 const struct smb_filename *smb_fname)
5585 char *link_target = NULL;
5586 const char *newname = smb_fname->base_name;
5587 NTSTATUS status = NT_STATUS_OK;
5588 TALLOC_CTX *ctx = talloc_tos();
5590 /* Set a symbolic link. */
5591 /* Don't allow this if follow links is false. */
5593 if (total_data == 0) {
5594 return NT_STATUS_INVALID_PARAMETER;
5597 if (!lp_symlinks(SNUM(conn))) {
5598 return NT_STATUS_ACCESS_DENIED;
5601 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5602 total_data, STR_TERMINATE);
5605 return NT_STATUS_INVALID_PARAMETER;
5608 /* !widelinks forces the target path to be within the share. */
5609 /* This means we can interpret the target as a pathname. */
5610 if (!lp_widelinks(SNUM(conn))) {
5611 char *rel_name = NULL;
5612 char *last_dirp = NULL;
5614 if (*link_target == '/') {
5615 /* No absolute paths allowed. */
5616 return NT_STATUS_ACCESS_DENIED;
5618 rel_name = talloc_strdup(ctx,newname);
5620 return NT_STATUS_NO_MEMORY;
5622 last_dirp = strrchr_m(rel_name, '/');
5624 last_dirp[1] = '\0';
5626 rel_name = talloc_strdup(ctx,"./");
5628 return NT_STATUS_NO_MEMORY;
5631 rel_name = talloc_asprintf_append(rel_name,
5635 return NT_STATUS_NO_MEMORY;
5638 status = check_name(conn, rel_name);
5639 if (!NT_STATUS_IS_OK(status)) {
5644 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5645 newname, link_target ));
5647 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5648 return map_nt_error_from_unix(errno);
5651 return NT_STATUS_OK;
5654 /****************************************************************************
5655 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5656 ****************************************************************************/
5658 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5659 struct smb_request *req,
5660 const char *pdata, int total_data,
5661 const struct smb_filename *smb_fname_new)
5663 char *oldname = NULL;
5664 struct smb_filename *smb_fname_old = NULL;
5665 TALLOC_CTX *ctx = talloc_tos();
5666 NTSTATUS status = NT_STATUS_OK;
5668 /* Set a hard link. */
5669 if (total_data == 0) {
5670 return NT_STATUS_INVALID_PARAMETER;
5673 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5674 total_data, STR_TERMINATE, &status);
5675 if (!NT_STATUS_IS_OK(status)) {
5679 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5680 smb_fname_str_dbg(smb_fname_new), oldname));
5682 status = filename_convert(ctx,
5684 req->flags2 & FLAGS2_DFS_PATHNAMES,
5689 if (!NT_STATUS_IS_OK(status)) {
5693 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5696 /****************************************************************************
5697 Deal with SMB_FILE_RENAME_INFORMATION.
5698 ****************************************************************************/
5700 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5701 struct smb_request *req,
5705 struct smb_filename *smb_fname_src)
5710 char *newname = NULL;
5711 struct smb_filename *smb_fname_dst = NULL;
5712 bool dest_has_wcard = False;
5713 NTSTATUS status = NT_STATUS_OK;
5715 TALLOC_CTX *ctx = talloc_tos();
5717 if (total_data < 13) {
5718 return NT_STATUS_INVALID_PARAMETER;
5721 overwrite = (CVAL(pdata,0) ? True : False);
5722 root_fid = IVAL(pdata,4);
5723 len = IVAL(pdata,8);
5725 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5726 return NT_STATUS_INVALID_PARAMETER;
5729 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5732 if (!NT_STATUS_IS_OK(status)) {
5736 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5739 status = resolve_dfspath_wcard(ctx, conn,
5740 req->flags2 & FLAGS2_DFS_PATHNAMES,
5744 if (!NT_STATUS_IS_OK(status)) {
5748 /* Check the new name has no '/' characters. */
5749 if (strchr_m(newname, '/')) {
5750 return NT_STATUS_NOT_SUPPORTED;
5753 if (fsp && fsp->base_fsp) {
5754 /* newname must be a stream name. */
5755 if (newname[0] != ':') {
5756 return NT_STATUS_NOT_SUPPORTED;
5759 /* Create an smb_fname to call rename_internals_fsp() with. */
5760 status = create_synthetic_smb_fname(talloc_tos(),
5761 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5763 if (!NT_STATUS_IS_OK(status)) {
5768 * Set the original last component, since
5769 * rename_internals_fsp() requires it.
5771 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5773 if (smb_fname_dst->original_lcomp == NULL) {
5774 status = NT_STATUS_NO_MEMORY;
5780 * Build up an smb_fname_dst based on the filename passed in.
5781 * We basically just strip off the last component, and put on
5782 * the newname instead.
5784 char *base_name = NULL;
5786 /* newname must *not* be a stream name. */
5787 if (newname[0] == ':') {
5788 return NT_STATUS_NOT_SUPPORTED;
5792 * Strip off the last component (filename) of the path passed
5795 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5797 return NT_STATUS_NO_MEMORY;
5799 p = strrchr_m(base_name, '/');
5803 base_name = talloc_strdup(ctx, "./");
5805 return NT_STATUS_NO_MEMORY;
5808 /* Append the new name. */
5809 base_name = talloc_asprintf_append(base_name,
5813 return NT_STATUS_NO_MEMORY;
5816 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5819 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
5822 /* If an error we expect this to be
5823 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5825 if (!NT_STATUS_IS_OK(status)) {
5826 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5830 /* Create an smb_fname to call rename_internals_fsp() */
5831 status = create_synthetic_smb_fname(ctx,
5835 if (!NT_STATUS_IS_OK(status)) {
5842 DEBUG(10,("smb_file_rename_information: "
5843 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5844 fsp->fnum, fsp_str_dbg(fsp),
5845 smb_fname_str_dbg(smb_fname_dst)));
5846 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5849 DEBUG(10,("smb_file_rename_information: "
5850 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5851 smb_fname_str_dbg(smb_fname_src),
5852 smb_fname_str_dbg(smb_fname_dst)));
5853 status = rename_internals(ctx, conn, req, smb_fname_src,
5854 smb_fname_dst, 0, overwrite, false,
5856 FILE_WRITE_ATTRIBUTES);
5859 TALLOC_FREE(smb_fname_dst);
5863 /****************************************************************************
5864 Deal with SMB_SET_POSIX_ACL.
5865 ****************************************************************************/
5867 #if defined(HAVE_POSIX_ACLS)
5868 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5872 const struct smb_filename *smb_fname)
5874 uint16 posix_acl_version;
5875 uint16 num_file_acls;
5876 uint16 num_def_acls;
5877 bool valid_file_acls = True;
5878 bool valid_def_acls = True;
5880 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5881 return NT_STATUS_INVALID_PARAMETER;
5883 posix_acl_version = SVAL(pdata,0);
5884 num_file_acls = SVAL(pdata,2);
5885 num_def_acls = SVAL(pdata,4);
5887 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5888 valid_file_acls = False;
5892 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5893 valid_def_acls = False;
5897 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5898 return NT_STATUS_INVALID_PARAMETER;
5901 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5902 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5903 return NT_STATUS_INVALID_PARAMETER;
5906 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5907 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5908 (unsigned int)num_file_acls,
5909 (unsigned int)num_def_acls));
5911 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5912 smb_fname->base_name, num_file_acls,
5913 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5914 return map_nt_error_from_unix(errno);
5917 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5918 smb_fname->base_name, &smb_fname->st, num_def_acls,
5919 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5920 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5921 return map_nt_error_from_unix(errno);
5923 return NT_STATUS_OK;
5927 /****************************************************************************
5928 Deal with SMB_SET_POSIX_LOCK.
5929 ****************************************************************************/
5931 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5932 struct smb_request *req,
5940 bool blocking_lock = False;
5941 enum brl_type lock_type;
5943 NTSTATUS status = NT_STATUS_OK;
5945 if (fsp == NULL || fsp->fh->fd == -1) {
5946 return NT_STATUS_INVALID_HANDLE;
5949 if (total_data != POSIX_LOCK_DATA_SIZE) {
5950 return NT_STATUS_INVALID_PARAMETER;
5953 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5954 case POSIX_LOCK_TYPE_READ:
5955 lock_type = READ_LOCK;
5957 case POSIX_LOCK_TYPE_WRITE:
5958 /* Return the right POSIX-mappable error code for files opened read-only. */
5959 if (!fsp->can_write) {
5960 return NT_STATUS_INVALID_HANDLE;
5962 lock_type = WRITE_LOCK;
5964 case POSIX_LOCK_TYPE_UNLOCK:
5965 lock_type = UNLOCK_LOCK;
5968 return NT_STATUS_INVALID_PARAMETER;
5971 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5972 blocking_lock = False;
5973 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5974 blocking_lock = True;
5976 return NT_STATUS_INVALID_PARAMETER;
5979 if (!lp_blocking_locks(SNUM(conn))) {
5980 blocking_lock = False;
5983 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5984 #if defined(HAVE_LONGLONG)
5985 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5986 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5987 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5988 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5989 #else /* HAVE_LONGLONG */
5990 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5991 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5992 #endif /* HAVE_LONGLONG */
5994 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5995 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5997 (unsigned int)lock_type,
5998 (unsigned int)lock_pid,
6002 if (lock_type == UNLOCK_LOCK) {
6003 status = do_unlock(smbd_messaging_context(),
6010 uint32 block_smbpid;
6012 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6024 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6026 * A blocking lock was requested. Package up
6027 * this smb into a queued request and push it
6028 * onto the blocking lock queue.
6030 if(push_blocking_lock_request(br_lck,
6033 -1, /* infinite timeout. */
6041 TALLOC_FREE(br_lck);
6045 TALLOC_FREE(br_lck);
6051 /****************************************************************************
6052 Deal with SMB_SET_FILE_BASIC_INFO.
6053 ****************************************************************************/
6055 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6059 const struct smb_filename *smb_fname)
6061 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6062 struct smb_file_time ft;
6064 NTSTATUS status = NT_STATUS_OK;
6068 if (total_data < 36) {
6069 return NT_STATUS_INVALID_PARAMETER;
6072 /* Set the attributes */
6073 dosmode = IVAL(pdata,32);
6074 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6075 if (!NT_STATUS_IS_OK(status)) {
6080 ft.create_time = interpret_long_date(pdata);
6083 ft.atime = interpret_long_date(pdata+8);
6086 ft.mtime = interpret_long_date(pdata+16);
6089 ft.ctime = interpret_long_date(pdata+24);
6091 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6092 smb_fname_str_dbg(smb_fname)));
6094 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6098 /****************************************************************************
6099 Deal with SMB_INFO_STANDARD.
6100 ****************************************************************************/
6102 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6106 const struct smb_filename *smb_fname)
6108 struct smb_file_time ft;
6112 if (total_data < 12) {
6113 return NT_STATUS_INVALID_PARAMETER;
6117 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6119 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6121 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6123 DEBUG(10,("smb_set_info_standard: file %s\n",
6124 smb_fname_str_dbg(smb_fname)));
6126 return smb_set_file_time(conn,
6133 /****************************************************************************
6134 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6135 ****************************************************************************/
6137 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6138 struct smb_request *req,
6142 struct smb_filename *smb_fname)
6144 uint64_t allocation_size = 0;
6145 NTSTATUS status = NT_STATUS_OK;
6146 files_struct *new_fsp = NULL;
6148 if (!VALID_STAT(smb_fname->st)) {
6149 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6152 if (total_data < 8) {
6153 return NT_STATUS_INVALID_PARAMETER;
6156 allocation_size = (uint64_t)IVAL(pdata,0);
6157 #ifdef LARGE_SMB_OFF_T
6158 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6159 #else /* LARGE_SMB_OFF_T */
6160 if (IVAL(pdata,4) != 0) {
6161 /* more than 32 bits? */
6162 return NT_STATUS_INVALID_PARAMETER;
6164 #endif /* LARGE_SMB_OFF_T */
6166 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6167 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6168 (double)allocation_size));
6170 if (allocation_size) {
6171 allocation_size = smb_roundup(conn, allocation_size);
6174 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6175 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6176 (double)allocation_size));
6178 if (fsp && fsp->fh->fd != -1) {
6179 /* Open file handle. */
6180 /* Only change if needed. */
6181 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6182 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6183 return map_nt_error_from_unix(errno);
6186 /* But always update the time. */
6188 * This is equivalent to a write. Ensure it's seen immediately
6189 * if there are no pending writes.
6191 trigger_write_time_update_immediate(fsp);
6192 return NT_STATUS_OK;
6195 /* Pathname or stat or directory file. */
6196 status = SMB_VFS_CREATE_FILE(
6199 0, /* root_dir_fid */
6200 smb_fname, /* fname */
6201 FILE_WRITE_DATA, /* access_mask */
6202 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6204 FILE_OPEN, /* create_disposition*/
6205 0, /* create_options */
6206 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6207 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6208 0, /* allocation_size */
6211 &new_fsp, /* result */
6214 if (!NT_STATUS_IS_OK(status)) {
6215 /* NB. We check for open_was_deferred in the caller. */
6219 /* Only change if needed. */
6220 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6221 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6222 status = map_nt_error_from_unix(errno);
6223 close_file(req, new_fsp, NORMAL_CLOSE);
6228 /* Changing the allocation size should set the last mod time. */
6230 * This is equivalent to a write. Ensure it's seen immediately
6231 * if there are no pending writes.
6233 trigger_write_time_update_immediate(new_fsp);
6235 close_file(req, new_fsp, NORMAL_CLOSE);
6236 return NT_STATUS_OK;
6239 /****************************************************************************
6240 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6241 ****************************************************************************/
6243 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6244 struct smb_request *req,
6248 const struct smb_filename *smb_fname)
6252 if (total_data < 8) {
6253 return NT_STATUS_INVALID_PARAMETER;
6256 size = IVAL(pdata,0);
6257 #ifdef LARGE_SMB_OFF_T
6258 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6259 #else /* LARGE_SMB_OFF_T */
6260 if (IVAL(pdata,4) != 0) {
6261 /* more than 32 bits? */
6262 return NT_STATUS_INVALID_PARAMETER;
6264 #endif /* LARGE_SMB_OFF_T */
6265 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6266 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6269 return smb_set_file_size(conn, req,
6276 /****************************************************************************
6277 Allow a UNIX info mknod.
6278 ****************************************************************************/
6280 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6283 const struct smb_filename *smb_fname)
6285 uint32 file_type = IVAL(pdata,56);
6286 #if defined(HAVE_MAKEDEV)
6287 uint32 dev_major = IVAL(pdata,60);
6288 uint32 dev_minor = IVAL(pdata,68);
6290 SMB_DEV_T dev = (SMB_DEV_T)0;
6291 uint32 raw_unixmode = IVAL(pdata,84);
6295 if (total_data < 100) {
6296 return NT_STATUS_INVALID_PARAMETER;
6299 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6300 PERM_NEW_FILE, &unixmode);
6301 if (!NT_STATUS_IS_OK(status)) {
6305 #if defined(HAVE_MAKEDEV)
6306 dev = makedev(dev_major, dev_minor);
6309 switch (file_type) {
6310 #if defined(S_IFIFO)
6311 case UNIX_TYPE_FIFO:
6312 unixmode |= S_IFIFO;
6315 #if defined(S_IFSOCK)
6316 case UNIX_TYPE_SOCKET:
6317 unixmode |= S_IFSOCK;
6320 #if defined(S_IFCHR)
6321 case UNIX_TYPE_CHARDEV:
6322 unixmode |= S_IFCHR;
6325 #if defined(S_IFBLK)
6326 case UNIX_TYPE_BLKDEV:
6327 unixmode |= S_IFBLK;
6331 return NT_STATUS_INVALID_PARAMETER;
6334 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6335 "%.0f mode 0%o for file %s\n", (double)dev,
6336 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6338 /* Ok - do the mknod. */
6339 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6340 return map_nt_error_from_unix(errno);
6343 /* If any of the other "set" calls fail we
6344 * don't want to end up with a half-constructed mknod.
6347 if (lp_inherit_perms(SNUM(conn))) {
6349 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6351 return NT_STATUS_NO_MEMORY;
6353 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6355 TALLOC_FREE(parent);
6358 return NT_STATUS_OK;
6361 /****************************************************************************
6362 Deal with SMB_SET_FILE_UNIX_BASIC.
6363 ****************************************************************************/
6365 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6366 struct smb_request *req,
6370 const struct smb_filename *smb_fname)
6372 struct smb_file_time ft;
6373 uint32 raw_unixmode;
6376 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6377 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6378 NTSTATUS status = NT_STATUS_OK;
6379 bool delete_on_fail = False;
6380 enum perm_type ptype;
6381 files_struct *all_fsps = NULL;
6382 bool modify_mtime = true;
6384 SMB_STRUCT_STAT sbuf;
6388 if (total_data < 100) {
6389 return NT_STATUS_INVALID_PARAMETER;
6392 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6393 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6394 size=IVAL(pdata,0); /* first 8 Bytes are size */
6395 #ifdef LARGE_SMB_OFF_T
6396 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6397 #else /* LARGE_SMB_OFF_T */
6398 if (IVAL(pdata,4) != 0) {
6399 /* more than 32 bits? */
6400 return NT_STATUS_INVALID_PARAMETER;
6402 #endif /* LARGE_SMB_OFF_T */
6405 ft.atime = interpret_long_date(pdata+24); /* access_time */
6406 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6407 set_owner = (uid_t)IVAL(pdata,40);
6408 set_grp = (gid_t)IVAL(pdata,48);
6409 raw_unixmode = IVAL(pdata,84);
6411 if (VALID_STAT(smb_fname->st)) {
6412 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6413 ptype = PERM_EXISTING_DIR;
6415 ptype = PERM_EXISTING_FILE;
6418 ptype = PERM_NEW_FILE;
6421 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6423 if (!NT_STATUS_IS_OK(status)) {
6427 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6428 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6429 smb_fname_str_dbg(smb_fname), (double)size,
6430 (unsigned int)set_owner, (unsigned int)set_grp,
6431 (int)raw_unixmode));
6433 sbuf = smb_fname->st;
6435 if (!VALID_STAT(sbuf)) {
6436 struct smb_filename *smb_fname_tmp = NULL;
6438 * The only valid use of this is to create character and block
6439 * devices, and named pipes. This is deprecated (IMHO) and
6440 * a new info level should be used for mknod. JRA.
6443 status = smb_unix_mknod(conn,
6447 if (!NT_STATUS_IS_OK(status)) {
6451 status = copy_smb_filename(talloc_tos(), smb_fname,
6453 if (!NT_STATUS_IS_OK(status)) {
6457 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6458 status = map_nt_error_from_unix(errno);
6459 TALLOC_FREE(smb_fname_tmp);
6460 SMB_VFS_UNLINK(conn, smb_fname);
6464 sbuf = smb_fname_tmp->st;
6465 TALLOC_FREE(smb_fname_tmp);
6467 /* Ensure we don't try and change anything else. */
6468 raw_unixmode = SMB_MODE_NO_CHANGE;
6469 size = get_file_size_stat(&sbuf);
6470 ft.atime = sbuf.st_ex_atime;
6471 ft.mtime = sbuf.st_ex_mtime;
6473 * We continue here as we might want to change the
6476 delete_on_fail = True;
6480 /* Horrible backwards compatibility hack as an old server bug
6481 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6485 size = get_file_size_stat(&sbuf);
6490 * Deal with the UNIX specific mode set.
6493 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6494 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6495 "setting mode 0%o for file %s\n",
6496 (unsigned int)unixmode,
6497 smb_fname_str_dbg(smb_fname)));
6498 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6499 return map_nt_error_from_unix(errno);
6504 * Deal with the UNIX specific uid set.
6507 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6508 (sbuf.st_ex_uid != set_owner)) {
6511 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6512 "changing owner %u for path %s\n",
6513 (unsigned int)set_owner,
6514 smb_fname_str_dbg(smb_fname)));
6516 if (S_ISLNK(sbuf.st_ex_mode)) {
6517 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6518 set_owner, (gid_t)-1);
6520 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6521 set_owner, (gid_t)-1);
6525 status = map_nt_error_from_unix(errno);
6526 if (delete_on_fail) {
6527 SMB_VFS_UNLINK(conn, smb_fname);
6534 * Deal with the UNIX specific gid set.
6537 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6538 (sbuf.st_ex_gid != set_grp)) {
6539 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6540 "changing group %u for file %s\n",
6541 (unsigned int)set_owner,
6542 smb_fname_str_dbg(smb_fname)));
6543 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6545 status = map_nt_error_from_unix(errno);
6546 if (delete_on_fail) {
6547 SMB_VFS_UNLINK(conn, smb_fname);
6553 /* Deal with any size changes. */
6555 status = smb_set_file_size(conn, req,
6560 if (!NT_STATUS_IS_OK(status)) {
6564 /* Deal with any time changes. */
6565 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6566 /* No change, don't cancel anything. */
6570 id = vfs_file_id_from_sbuf(conn, &sbuf);
6571 for(all_fsps = file_find_di_first(id); all_fsps;
6572 all_fsps = file_find_di_next(all_fsps)) {
6574 * We're setting the time explicitly for UNIX.
6575 * Cancel any pending changes over all handles.
6577 all_fsps->update_write_time_on_close = false;
6578 TALLOC_FREE(all_fsps->update_write_time_event);
6582 * Override the "setting_write_time"
6583 * parameter here as it almost does what
6584 * we need. Just remember if we modified
6585 * mtime and send the notify ourselves.
6587 if (null_timespec(ft.mtime)) {
6588 modify_mtime = false;
6591 status = smb_set_file_time(conn,
6597 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6598 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6603 /****************************************************************************
6604 Deal with SMB_SET_FILE_UNIX_INFO2.
6605 ****************************************************************************/
6607 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6608 struct smb_request *req,
6612 const struct smb_filename *smb_fname)
6618 if (total_data < 116) {
6619 return NT_STATUS_INVALID_PARAMETER;
6622 /* Start by setting all the fields that are common between UNIX_BASIC
6625 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6627 if (!NT_STATUS_IS_OK(status)) {
6631 smb_fflags = IVAL(pdata, 108);
6632 smb_fmask = IVAL(pdata, 112);
6634 /* NB: We should only attempt to alter the file flags if the client
6635 * sends a non-zero mask.
6637 if (smb_fmask != 0) {
6638 int stat_fflags = 0;
6640 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6641 smb_fmask, &stat_fflags)) {
6642 /* Client asked to alter a flag we don't understand. */
6643 return NT_STATUS_INVALID_PARAMETER;
6646 if (fsp && fsp->fh->fd != -1) {
6647 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6648 return NT_STATUS_NOT_SUPPORTED;
6650 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6651 stat_fflags) != 0) {
6652 return map_nt_error_from_unix(errno);
6657 /* XXX: need to add support for changing the create_time here. You
6658 * can do this for paths on Darwin with setattrlist(2). The right way
6659 * to hook this up is probably by extending the VFS utimes interface.
6662 return NT_STATUS_OK;
6665 /****************************************************************************
6666 Create a directory with POSIX semantics.
6667 ****************************************************************************/
6669 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6670 struct smb_request *req,
6673 struct smb_filename *smb_fname,
6674 int *pdata_return_size)
6676 NTSTATUS status = NT_STATUS_OK;
6677 uint32 raw_unixmode = 0;
6678 uint32 mod_unixmode = 0;
6679 mode_t unixmode = (mode_t)0;
6680 files_struct *fsp = NULL;
6681 uint16 info_level_return = 0;
6683 char *pdata = *ppdata;
6685 if (total_data < 18) {
6686 return NT_STATUS_INVALID_PARAMETER;
6689 raw_unixmode = IVAL(pdata,8);
6690 /* Next 4 bytes are not yet defined. */
6692 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6693 PERM_NEW_DIR, &unixmode);
6694 if (!NT_STATUS_IS_OK(status)) {
6698 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6700 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6701 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6703 status = SMB_VFS_CREATE_FILE(
6706 0, /* root_dir_fid */
6707 smb_fname, /* fname */
6708 FILE_READ_ATTRIBUTES, /* access_mask */
6709 FILE_SHARE_NONE, /* share_access */
6710 FILE_CREATE, /* create_disposition*/
6711 FILE_DIRECTORY_FILE, /* create_options */
6712 mod_unixmode, /* file_attributes */
6713 0, /* oplock_request */
6714 0, /* allocation_size */
6720 if (NT_STATUS_IS_OK(status)) {
6721 close_file(req, fsp, NORMAL_CLOSE);
6724 info_level_return = SVAL(pdata,16);
6726 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6727 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6728 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6729 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6731 *pdata_return_size = 12;
6734 /* Realloc the data size */
6735 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6736 if (*ppdata == NULL) {
6737 *pdata_return_size = 0;
6738 return NT_STATUS_NO_MEMORY;
6742 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6743 SSVAL(pdata,2,0); /* No fnum. */
6744 SIVAL(pdata,4,info); /* Was directory created. */
6746 switch (info_level_return) {
6747 case SMB_QUERY_FILE_UNIX_BASIC:
6748 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6749 SSVAL(pdata,10,0); /* Padding. */
6750 store_file_unix_basic(conn, pdata + 12, fsp,
6753 case SMB_QUERY_FILE_UNIX_INFO2:
6754 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6755 SSVAL(pdata,10,0); /* Padding. */
6756 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6760 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6761 SSVAL(pdata,10,0); /* Padding. */
6768 /****************************************************************************
6769 Open/Create a file with POSIX semantics.
6770 ****************************************************************************/
6772 static NTSTATUS smb_posix_open(connection_struct *conn,
6773 struct smb_request *req,
6776 struct smb_filename *smb_fname,
6777 int *pdata_return_size)
6779 bool extended_oplock_granted = False;
6780 char *pdata = *ppdata;
6782 uint32 wire_open_mode = 0;
6783 uint32 raw_unixmode = 0;
6784 uint32 mod_unixmode = 0;
6785 uint32 create_disp = 0;
6786 uint32 access_mask = 0;
6787 uint32 create_options = 0;
6788 NTSTATUS status = NT_STATUS_OK;
6789 mode_t unixmode = (mode_t)0;
6790 files_struct *fsp = NULL;
6791 int oplock_request = 0;
6793 uint16 info_level_return = 0;
6795 if (total_data < 18) {
6796 return NT_STATUS_INVALID_PARAMETER;
6799 flags = IVAL(pdata,0);
6800 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6801 if (oplock_request) {
6802 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6805 wire_open_mode = IVAL(pdata,4);
6807 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6808 return smb_posix_mkdir(conn, req,
6815 switch (wire_open_mode & SMB_ACCMODE) {
6817 access_mask = FILE_READ_DATA;
6820 access_mask = FILE_WRITE_DATA;
6823 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6826 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6827 (unsigned int)wire_open_mode ));
6828 return NT_STATUS_INVALID_PARAMETER;
6831 wire_open_mode &= ~SMB_ACCMODE;
6833 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6834 create_disp = FILE_CREATE;
6835 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6836 create_disp = FILE_OVERWRITE_IF;
6837 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6838 create_disp = FILE_OPEN_IF;
6839 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6840 create_disp = FILE_OPEN;
6842 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6843 (unsigned int)wire_open_mode ));
6844 return NT_STATUS_INVALID_PARAMETER;
6847 raw_unixmode = IVAL(pdata,8);
6848 /* Next 4 bytes are not yet defined. */
6850 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6851 (VALID_STAT(smb_fname->st) ?
6852 PERM_EXISTING_FILE : PERM_NEW_FILE),
6855 if (!NT_STATUS_IS_OK(status)) {
6859 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6861 if (wire_open_mode & SMB_O_SYNC) {
6862 create_options |= FILE_WRITE_THROUGH;
6864 if (wire_open_mode & SMB_O_APPEND) {
6865 access_mask |= FILE_APPEND_DATA;
6867 if (wire_open_mode & SMB_O_DIRECT) {
6868 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6871 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6872 smb_fname_str_dbg(smb_fname),
6873 (unsigned int)wire_open_mode,
6874 (unsigned int)unixmode ));
6876 status = SMB_VFS_CREATE_FILE(
6879 0, /* root_dir_fid */
6880 smb_fname, /* fname */
6881 access_mask, /* access_mask */
6882 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6884 create_disp, /* create_disposition*/
6885 FILE_NON_DIRECTORY_FILE, /* create_options */
6886 mod_unixmode, /* file_attributes */
6887 oplock_request, /* oplock_request */
6888 0, /* allocation_size */
6894 if (!NT_STATUS_IS_OK(status)) {
6898 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6899 extended_oplock_granted = True;
6902 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6903 extended_oplock_granted = True;
6906 info_level_return = SVAL(pdata,16);
6908 /* Allocate the correct return size. */
6910 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6911 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6912 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6913 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6915 *pdata_return_size = 12;
6918 /* Realloc the data size */
6919 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6920 if (*ppdata == NULL) {
6921 close_file(req, fsp, ERROR_CLOSE);
6922 *pdata_return_size = 0;
6923 return NT_STATUS_NO_MEMORY;
6927 if (extended_oplock_granted) {
6928 if (flags & REQUEST_BATCH_OPLOCK) {
6929 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6931 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6933 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6934 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6936 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6939 SSVAL(pdata,2,fsp->fnum);
6940 SIVAL(pdata,4,info); /* Was file created etc. */
6942 switch (info_level_return) {
6943 case SMB_QUERY_FILE_UNIX_BASIC:
6944 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6945 SSVAL(pdata,10,0); /* padding. */
6946 store_file_unix_basic(conn, pdata + 12, fsp,
6949 case SMB_QUERY_FILE_UNIX_INFO2:
6950 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6951 SSVAL(pdata,10,0); /* padding. */
6952 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6956 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6957 SSVAL(pdata,10,0); /* padding. */
6960 return NT_STATUS_OK;
6963 /****************************************************************************
6964 Delete a file with POSIX semantics.
6965 ****************************************************************************/
6967 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6968 struct smb_request *req,
6971 struct smb_filename *smb_fname)
6973 NTSTATUS status = NT_STATUS_OK;
6974 files_struct *fsp = NULL;
6978 int create_options = 0;
6980 struct share_mode_lock *lck = NULL;
6982 if (total_data < 2) {
6983 return NT_STATUS_INVALID_PARAMETER;
6986 flags = SVAL(pdata,0);
6988 if (!VALID_STAT(smb_fname->st)) {
6989 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6992 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6993 !VALID_STAT_OF_DIR(smb_fname->st)) {
6994 return NT_STATUS_NOT_A_DIRECTORY;
6997 DEBUG(10,("smb_posix_unlink: %s %s\n",
6998 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6999 smb_fname_str_dbg(smb_fname)));
7001 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7002 create_options |= FILE_DIRECTORY_FILE;
7005 status = SMB_VFS_CREATE_FILE(
7008 0, /* root_dir_fid */
7009 smb_fname, /* fname */
7010 DELETE_ACCESS, /* access_mask */
7011 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7013 FILE_OPEN, /* create_disposition*/
7014 create_options, /* create_options */
7015 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7016 0, /* oplock_request */
7017 0, /* allocation_size */
7023 if (!NT_STATUS_IS_OK(status)) {
7028 * Don't lie to client. If we can't really delete due to
7029 * non-POSIX opens return SHARING_VIOLATION.
7032 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7035 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7036 "lock for file %s\n", fsp_str_dbg(fsp)));
7037 close_file(req, fsp, NORMAL_CLOSE);
7038 return NT_STATUS_INVALID_PARAMETER;
7042 * See if others still have the file open. If this is the case, then
7043 * don't delete. If all opens are POSIX delete we can set the delete
7044 * on close disposition.
7046 for (i=0; i<lck->num_share_modes; i++) {
7047 struct share_mode_entry *e = &lck->share_modes[i];
7048 if (is_valid_share_mode_entry(e)) {
7049 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7052 /* Fail with sharing violation. */
7053 close_file(req, fsp, NORMAL_CLOSE);
7055 return NT_STATUS_SHARING_VIOLATION;
7060 * Set the delete on close.
7062 status = smb_set_file_disposition_info(conn,
7068 if (!NT_STATUS_IS_OK(status)) {
7069 close_file(req, fsp, NORMAL_CLOSE);
7074 return close_file(req, fsp, NORMAL_CLOSE);
7077 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7078 struct smb_request *req,
7079 TALLOC_CTX *mem_ctx,
7080 uint16_t info_level,
7082 struct smb_filename *smb_fname,
7083 char **ppdata, int total_data,
7086 char *pdata = *ppdata;
7087 NTSTATUS status = NT_STATUS_OK;
7088 int data_return_size = 0;
7092 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7093 return NT_STATUS_INVALID_LEVEL;
7096 if (!CAN_WRITE(conn)) {
7097 /* Allow POSIX opens. The open path will deny
7098 * any non-readonly opens. */
7099 if (info_level != SMB_POSIX_PATH_OPEN) {
7100 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7104 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7105 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7106 fsp ? fsp->fnum : -1, info_level, total_data));
7108 switch (info_level) {
7110 case SMB_INFO_STANDARD:
7112 status = smb_set_info_standard(conn,
7120 case SMB_INFO_SET_EA:
7122 status = smb_info_set_ea(conn,
7130 case SMB_SET_FILE_BASIC_INFO:
7131 case SMB_FILE_BASIC_INFORMATION:
7133 status = smb_set_file_basic_info(conn,
7141 case SMB_FILE_ALLOCATION_INFORMATION:
7142 case SMB_SET_FILE_ALLOCATION_INFO:
7144 status = smb_set_file_allocation_info(conn, req,
7152 case SMB_FILE_END_OF_FILE_INFORMATION:
7153 case SMB_SET_FILE_END_OF_FILE_INFO:
7155 status = smb_set_file_end_of_file_info(conn, req,
7163 case SMB_FILE_DISPOSITION_INFORMATION:
7164 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7167 /* JRA - We used to just ignore this on a path ?
7168 * Shouldn't this be invalid level on a pathname
7171 if (tran_call != TRANSACT2_SETFILEINFO) {
7172 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7175 status = smb_set_file_disposition_info(conn,
7183 case SMB_FILE_POSITION_INFORMATION:
7185 status = smb_file_position_information(conn,
7192 /* From tridge Samba4 :
7193 * MODE_INFORMATION in setfileinfo (I have no
7194 * idea what "mode information" on a file is - it takes a value of 0,
7195 * 2, 4 or 6. What could it be?).
7198 case SMB_FILE_MODE_INFORMATION:
7200 status = smb_file_mode_information(conn,
7207 * CIFS UNIX extensions.
7210 case SMB_SET_FILE_UNIX_BASIC:
7212 status = smb_set_file_unix_basic(conn, req,
7220 case SMB_SET_FILE_UNIX_INFO2:
7222 status = smb_set_file_unix_info2(conn, req,
7230 case SMB_SET_FILE_UNIX_LINK:
7233 /* We must have a pathname for this. */
7234 return NT_STATUS_INVALID_LEVEL;
7236 status = smb_set_file_unix_link(conn, req, pdata,
7237 total_data, smb_fname);
7241 case SMB_SET_FILE_UNIX_HLINK:
7244 /* We must have a pathname for this. */
7245 return NT_STATUS_INVALID_LEVEL;
7247 status = smb_set_file_unix_hlink(conn, req,
7253 case SMB_FILE_RENAME_INFORMATION:
7255 status = smb_file_rename_information(conn, req,
7261 #if defined(HAVE_POSIX_ACLS)
7262 case SMB_SET_POSIX_ACL:
7264 status = smb_set_posix_acl(conn,
7273 case SMB_SET_POSIX_LOCK:
7276 return NT_STATUS_INVALID_LEVEL;
7278 status = smb_set_posix_lock(conn, req,
7279 pdata, total_data, fsp);
7283 case SMB_POSIX_PATH_OPEN:
7286 /* We must have a pathname for this. */
7287 return NT_STATUS_INVALID_LEVEL;
7290 status = smb_posix_open(conn, req,
7298 case SMB_POSIX_PATH_UNLINK:
7301 /* We must have a pathname for this. */
7302 return NT_STATUS_INVALID_LEVEL;
7305 status = smb_posix_unlink(conn, req,
7313 return NT_STATUS_INVALID_LEVEL;
7316 if (!NT_STATUS_IS_OK(status)) {
7320 *ret_data_size = data_return_size;
7321 return NT_STATUS_OK;
7324 /****************************************************************************
7325 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7326 ****************************************************************************/
7328 static void call_trans2setfilepathinfo(connection_struct *conn,
7329 struct smb_request *req,
7330 unsigned int tran_call,
7331 char **pparams, int total_params,
7332 char **ppdata, int total_data,
7333 unsigned int max_data_bytes)
7335 char *params = *pparams;
7336 char *pdata = *ppdata;
7338 struct smb_filename *smb_fname = NULL;
7339 files_struct *fsp = NULL;
7340 NTSTATUS status = NT_STATUS_OK;
7341 int data_return_size = 0;
7344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7348 if (tran_call == TRANSACT2_SETFILEINFO) {
7349 if (total_params < 4) {
7350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7354 fsp = file_fsp(req, SVAL(params,0));
7355 /* Basic check for non-null fsp. */
7356 if (!check_fsp_open(conn, req, fsp)) {
7359 info_level = SVAL(params,2);
7361 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7363 if (!NT_STATUS_IS_OK(status)) {
7364 reply_nterror(req, status);
7368 if(fsp->is_directory || fsp->fh->fd == -1) {
7370 * This is actually a SETFILEINFO on a directory
7371 * handle (returned from an NT SMB). NT5.0 seems
7372 * to do this call. JRA.
7374 if (INFO_LEVEL_IS_UNIX(info_level)) {
7375 /* Always do lstat for UNIX calls. */
7376 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7377 DEBUG(3,("call_trans2setfilepathinfo: "
7378 "SMB_VFS_LSTAT of %s failed "
7380 smb_fname_str_dbg(smb_fname),
7382 reply_nterror(req, map_nt_error_from_unix(errno));
7386 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7387 DEBUG(3,("call_trans2setfilepathinfo: "
7388 "fileinfo of %s failed (%s)\n",
7389 smb_fname_str_dbg(smb_fname),
7391 reply_nterror(req, map_nt_error_from_unix(errno));
7395 } else if (fsp->print_file) {
7397 * Doing a DELETE_ON_CLOSE should cancel a print job.
7399 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7400 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7402 DEBUG(3,("call_trans2setfilepathinfo: "
7403 "Cancelling print job (%s)\n",
7407 send_trans2_replies(conn, req, params, 2,
7412 reply_doserror(req, ERRDOS, ERRbadpath);
7417 * Original code - this is an open file.
7419 if (!check_fsp(conn, req, fsp)) {
7423 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7424 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7425 "of fnum %d failed (%s)\n", fsp->fnum,
7427 reply_nterror(req, map_nt_error_from_unix(errno));
7435 if (total_params < 7) {
7436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7440 info_level = SVAL(params,0);
7441 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7442 total_params - 6, STR_TERMINATE,
7444 if (!NT_STATUS_IS_OK(status)) {
7445 reply_nterror(req, status);
7449 status = filename_convert(req, conn,
7450 req->flags2 & FLAGS2_DFS_PATHNAMES,
7455 if (!NT_STATUS_IS_OK(status)) {
7456 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7457 reply_botherror(req,
7458 NT_STATUS_PATH_NOT_COVERED,
7459 ERRSRV, ERRbadpath);
7462 reply_nterror(req, status);
7466 if (INFO_LEVEL_IS_UNIX(info_level)) {
7468 * For CIFS UNIX extensions the target name may not exist.
7471 /* Always do lstat for UNIX calls. */
7472 SMB_VFS_LSTAT(conn, smb_fname);
7474 } else if (!VALID_STAT(smb_fname->st) &&
7475 SMB_VFS_STAT(conn, smb_fname)) {
7476 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7478 smb_fname_str_dbg(smb_fname),
7480 reply_nterror(req, map_nt_error_from_unix(errno));
7485 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7486 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7487 fsp ? fsp->fnum : -1, info_level,total_data));
7489 /* Realloc the parameter size */
7490 *pparams = (char *)SMB_REALLOC(*pparams,2);
7491 if (*pparams == NULL) {
7492 reply_nterror(req, NT_STATUS_NO_MEMORY);
7499 status = smbd_do_setfilepathinfo(conn, req, req,
7505 if (!NT_STATUS_IS_OK(status)) {
7506 if (open_was_deferred(req->mid)) {
7507 /* We have re-scheduled this call. */
7510 if (blocking_lock_was_deferred(req->mid)) {
7511 /* We have re-scheduled this call. */
7514 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7515 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7516 ERRSRV, ERRbadpath);
7519 if (info_level == SMB_POSIX_PATH_OPEN) {
7520 reply_openerror(req, status);
7524 reply_nterror(req, status);
7528 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7534 /****************************************************************************
7535 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7536 ****************************************************************************/
7538 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7539 char **pparams, int total_params,
7540 char **ppdata, int total_data,
7541 unsigned int max_data_bytes)
7543 struct smb_filename *smb_dname = NULL;
7544 char *params = *pparams;
7545 char *pdata = *ppdata;
7546 char *directory = NULL;
7547 NTSTATUS status = NT_STATUS_OK;
7548 struct ea_list *ea_list = NULL;
7549 TALLOC_CTX *ctx = talloc_tos();
7551 if (!CAN_WRITE(conn)) {
7552 reply_doserror(req, ERRSRV, ERRaccess);
7556 if (total_params < 5) {
7557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7561 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7562 total_params - 4, STR_TERMINATE,
7564 if (!NT_STATUS_IS_OK(status)) {
7565 reply_nterror(req, status);
7569 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7571 status = filename_convert(ctx,
7573 req->flags2 & FLAGS2_DFS_PATHNAMES,
7579 if (!NT_STATUS_IS_OK(status)) {
7580 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7581 reply_botherror(req,
7582 NT_STATUS_PATH_NOT_COVERED,
7583 ERRSRV, ERRbadpath);
7586 reply_nterror(req, status);
7590 /* Any data in this call is an EA list. */
7591 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7592 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7597 * OS/2 workplace shell seems to send SET_EA requests of "null"
7598 * length (4 bytes containing IVAL 4).
7599 * They seem to have no effect. Bug #3212. JRA.
7602 if (total_data != 4) {
7603 if (total_data < 10) {
7604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7608 if (IVAL(pdata,0) > total_data) {
7609 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7610 IVAL(pdata,0), (unsigned int)total_data));
7611 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7615 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7622 /* If total_data == 4 Windows doesn't care what values
7623 * are placed in that field, it just ignores them.
7624 * The System i QNTC IBM SMB client puts bad values here,
7625 * so ignore them. */
7627 status = create_directory(conn, req, smb_dname);
7629 if (!NT_STATUS_IS_OK(status)) {
7630 reply_nterror(req, status);
7634 /* Try and set any given EA. */
7636 status = set_ea(conn, NULL, smb_dname, ea_list);
7637 if (!NT_STATUS_IS_OK(status)) {
7638 reply_nterror(req, status);
7643 /* Realloc the parameter and data sizes */
7644 *pparams = (char *)SMB_REALLOC(*pparams,2);
7645 if(*pparams == NULL) {
7646 reply_nterror(req, NT_STATUS_NO_MEMORY);
7653 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7656 TALLOC_FREE(smb_dname);
7660 /****************************************************************************
7661 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7662 We don't actually do this - we just send a null response.
7663 ****************************************************************************/
7665 static void call_trans2findnotifyfirst(connection_struct *conn,
7666 struct smb_request *req,
7667 char **pparams, int total_params,
7668 char **ppdata, int total_data,
7669 unsigned int max_data_bytes)
7671 char *params = *pparams;
7674 if (total_params < 6) {
7675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7679 info_level = SVAL(params,4);
7680 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7682 switch (info_level) {
7687 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7691 /* Realloc the parameter and data sizes */
7692 *pparams = (char *)SMB_REALLOC(*pparams,6);
7693 if (*pparams == NULL) {
7694 reply_nterror(req, NT_STATUS_NO_MEMORY);
7699 SSVAL(params,0,fnf_handle);
7700 SSVAL(params,2,0); /* No changes */
7701 SSVAL(params,4,0); /* No EA errors */
7708 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7713 /****************************************************************************
7714 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7715 changes). Currently this does nothing.
7716 ****************************************************************************/
7718 static void call_trans2findnotifynext(connection_struct *conn,
7719 struct smb_request *req,
7720 char **pparams, int total_params,
7721 char **ppdata, int total_data,
7722 unsigned int max_data_bytes)
7724 char *params = *pparams;
7726 DEBUG(3,("call_trans2findnotifynext\n"));
7728 /* Realloc the parameter and data sizes */
7729 *pparams = (char *)SMB_REALLOC(*pparams,4);
7730 if (*pparams == NULL) {
7731 reply_nterror(req, NT_STATUS_NO_MEMORY);
7736 SSVAL(params,0,0); /* No changes */
7737 SSVAL(params,2,0); /* No EA errors */
7739 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7744 /****************************************************************************
7745 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7746 ****************************************************************************/
7748 static void call_trans2getdfsreferral(connection_struct *conn,
7749 struct smb_request *req,
7750 char **pparams, int total_params,
7751 char **ppdata, int total_data,
7752 unsigned int max_data_bytes)
7754 char *params = *pparams;
7755 char *pathname = NULL;
7757 int max_referral_level;
7758 NTSTATUS status = NT_STATUS_OK;
7759 TALLOC_CTX *ctx = talloc_tos();
7761 DEBUG(10,("call_trans2getdfsreferral\n"));
7763 if (total_params < 3) {
7764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7768 max_referral_level = SVAL(params,0);
7770 if(!lp_host_msdfs()) {
7771 reply_doserror(req, ERRDOS, ERRbadfunc);
7775 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7776 total_params - 2, STR_TERMINATE);
7778 reply_nterror(req, NT_STATUS_NOT_FOUND);
7781 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7782 ppdata,&status)) < 0) {
7783 reply_nterror(req, status);
7787 SSVAL(req->inbuf, smb_flg2,
7788 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7789 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7794 #define LMCAT_SPL 0x53
7795 #define LMFUNC_GETJOBID 0x60
7797 /****************************************************************************
7798 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7799 ****************************************************************************/
7801 static void call_trans2ioctl(connection_struct *conn,
7802 struct smb_request *req,
7803 char **pparams, int total_params,
7804 char **ppdata, int total_data,
7805 unsigned int max_data_bytes)
7807 char *pdata = *ppdata;
7808 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7810 /* check for an invalid fid before proceeding */
7813 reply_doserror(req, ERRDOS, ERRbadfid);
7817 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7818 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7819 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7820 if (*ppdata == NULL) {
7821 reply_nterror(req, NT_STATUS_NO_MEMORY);
7826 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7827 CAN ACCEPT THIS IN UNICODE. JRA. */
7829 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7830 srvstr_push(pdata, req->flags2, pdata + 2,
7831 global_myname(), 15,
7832 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7833 srvstr_push(pdata, req->flags2, pdata+18,
7834 lp_servicename(SNUM(conn)), 13,
7835 STR_ASCII|STR_TERMINATE); /* Service name */
7836 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7841 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7842 reply_doserror(req, ERRSRV, ERRerror);
7845 /****************************************************************************
7846 Reply to a SMBfindclose (stop trans2 directory search).
7847 ****************************************************************************/
7849 void reply_findclose(struct smb_request *req)
7853 START_PROFILE(SMBfindclose);
7856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7857 END_PROFILE(SMBfindclose);
7861 dptr_num = SVALS(req->vwv+0, 0);
7863 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7865 dptr_close(&dptr_num);
7867 reply_outbuf(req, 0, 0);
7869 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7871 END_PROFILE(SMBfindclose);
7875 /****************************************************************************
7876 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7877 ****************************************************************************/
7879 void reply_findnclose(struct smb_request *req)
7883 START_PROFILE(SMBfindnclose);
7886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7887 END_PROFILE(SMBfindnclose);
7891 dptr_num = SVAL(req->vwv+0, 0);
7893 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7895 /* We never give out valid handles for a
7896 findnotifyfirst - so any dptr_num is ok here.
7899 reply_outbuf(req, 0, 0);
7901 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7903 END_PROFILE(SMBfindnclose);
7907 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7908 struct trans_state *state)
7910 if (Protocol >= PROTOCOL_NT1) {
7911 req->flags2 |= 0x40; /* IS_LONG_NAME */
7912 SSVAL(req->inbuf,smb_flg2,req->flags2);
7915 if (conn->encrypt_level == Required && !req->encrypted) {
7916 if (state->call != TRANSACT2_QFSINFO &&
7917 state->call != TRANSACT2_SETFSINFO) {
7918 DEBUG(0,("handle_trans2: encryption required "
7920 (unsigned int)state->call));
7921 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7926 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7928 /* Now we must call the relevant TRANS2 function */
7929 switch(state->call) {
7930 case TRANSACT2_OPEN:
7932 START_PROFILE(Trans2_open);
7933 call_trans2open(conn, req,
7934 &state->param, state->total_param,
7935 &state->data, state->total_data,
7936 state->max_data_return);
7937 END_PROFILE(Trans2_open);
7941 case TRANSACT2_FINDFIRST:
7943 START_PROFILE(Trans2_findfirst);
7944 call_trans2findfirst(conn, req,
7945 &state->param, state->total_param,
7946 &state->data, state->total_data,
7947 state->max_data_return);
7948 END_PROFILE(Trans2_findfirst);
7952 case TRANSACT2_FINDNEXT:
7954 START_PROFILE(Trans2_findnext);
7955 call_trans2findnext(conn, req,
7956 &state->param, state->total_param,
7957 &state->data, state->total_data,
7958 state->max_data_return);
7959 END_PROFILE(Trans2_findnext);
7963 case TRANSACT2_QFSINFO:
7965 START_PROFILE(Trans2_qfsinfo);
7966 call_trans2qfsinfo(conn, req,
7967 &state->param, state->total_param,
7968 &state->data, state->total_data,
7969 state->max_data_return);
7970 END_PROFILE(Trans2_qfsinfo);
7974 case TRANSACT2_SETFSINFO:
7976 START_PROFILE(Trans2_setfsinfo);
7977 call_trans2setfsinfo(conn, req,
7978 &state->param, state->total_param,
7979 &state->data, state->total_data,
7980 state->max_data_return);
7981 END_PROFILE(Trans2_setfsinfo);
7985 case TRANSACT2_QPATHINFO:
7986 case TRANSACT2_QFILEINFO:
7988 START_PROFILE(Trans2_qpathinfo);
7989 call_trans2qfilepathinfo(conn, req, state->call,
7990 &state->param, state->total_param,
7991 &state->data, state->total_data,
7992 state->max_data_return);
7993 END_PROFILE(Trans2_qpathinfo);
7997 case TRANSACT2_SETPATHINFO:
7998 case TRANSACT2_SETFILEINFO:
8000 START_PROFILE(Trans2_setpathinfo);
8001 call_trans2setfilepathinfo(conn, req, state->call,
8002 &state->param, state->total_param,
8003 &state->data, state->total_data,
8004 state->max_data_return);
8005 END_PROFILE(Trans2_setpathinfo);
8009 case TRANSACT2_FINDNOTIFYFIRST:
8011 START_PROFILE(Trans2_findnotifyfirst);
8012 call_trans2findnotifyfirst(conn, req,
8013 &state->param, state->total_param,
8014 &state->data, state->total_data,
8015 state->max_data_return);
8016 END_PROFILE(Trans2_findnotifyfirst);
8020 case TRANSACT2_FINDNOTIFYNEXT:
8022 START_PROFILE(Trans2_findnotifynext);
8023 call_trans2findnotifynext(conn, req,
8024 &state->param, state->total_param,
8025 &state->data, state->total_data,
8026 state->max_data_return);
8027 END_PROFILE(Trans2_findnotifynext);
8031 case TRANSACT2_MKDIR:
8033 START_PROFILE(Trans2_mkdir);
8034 call_trans2mkdir(conn, req,
8035 &state->param, state->total_param,
8036 &state->data, state->total_data,
8037 state->max_data_return);
8038 END_PROFILE(Trans2_mkdir);
8042 case TRANSACT2_GET_DFS_REFERRAL:
8044 START_PROFILE(Trans2_get_dfs_referral);
8045 call_trans2getdfsreferral(conn, req,
8046 &state->param, state->total_param,
8047 &state->data, state->total_data,
8048 state->max_data_return);
8049 END_PROFILE(Trans2_get_dfs_referral);
8053 case TRANSACT2_IOCTL:
8055 START_PROFILE(Trans2_ioctl);
8056 call_trans2ioctl(conn, req,
8057 &state->param, state->total_param,
8058 &state->data, state->total_data,
8059 state->max_data_return);
8060 END_PROFILE(Trans2_ioctl);
8065 /* Error in request */
8066 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8067 reply_doserror(req, ERRSRV,ERRerror);
8071 /****************************************************************************
8072 Reply to a SMBtrans2.
8073 ****************************************************************************/
8075 void reply_trans2(struct smb_request *req)
8077 connection_struct *conn = req->conn;
8082 unsigned int tran_call;
8083 struct trans_state *state;
8086 START_PROFILE(SMBtrans2);
8088 if (req->wct < 14) {
8089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8090 END_PROFILE(SMBtrans2);
8094 dsoff = SVAL(req->vwv+12, 0);
8095 dscnt = SVAL(req->vwv+11, 0);
8096 psoff = SVAL(req->vwv+10, 0);
8097 pscnt = SVAL(req->vwv+9, 0);
8098 tran_call = SVAL(req->vwv+14, 0);
8100 result = allow_new_trans(conn->pending_trans, req->mid);
8101 if (!NT_STATUS_IS_OK(result)) {
8102 DEBUG(2, ("Got invalid trans2 request: %s\n",
8103 nt_errstr(result)));
8104 reply_nterror(req, result);
8105 END_PROFILE(SMBtrans2);
8110 switch (tran_call) {
8111 /* List the allowed trans2 calls on IPC$ */
8112 case TRANSACT2_OPEN:
8113 case TRANSACT2_GET_DFS_REFERRAL:
8114 case TRANSACT2_QFILEINFO:
8115 case TRANSACT2_QFSINFO:
8116 case TRANSACT2_SETFSINFO:
8119 reply_doserror(req, ERRSRV, ERRaccess);
8120 END_PROFILE(SMBtrans2);
8125 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8126 DEBUG(0, ("talloc failed\n"));
8127 reply_nterror(req, NT_STATUS_NO_MEMORY);
8128 END_PROFILE(SMBtrans2);
8132 state->cmd = SMBtrans2;
8134 state->mid = req->mid;
8135 state->vuid = req->vuid;
8136 state->setup_count = SVAL(req->vwv+13, 0);
8137 state->setup = NULL;
8138 state->total_param = SVAL(req->vwv+0, 0);
8139 state->param = NULL;
8140 state->total_data = SVAL(req->vwv+1, 0);
8142 state->max_param_return = SVAL(req->vwv+2, 0);
8143 state->max_data_return = SVAL(req->vwv+3, 0);
8144 state->max_setup_return = SVAL(req->vwv+4, 0);
8145 state->close_on_completion = BITSETW(req->vwv+5, 0);
8146 state->one_way = BITSETW(req->vwv+5, 1);
8148 state->call = tran_call;
8150 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8151 is so as a sanity check */
8152 if (state->setup_count != 1) {
8154 * Need to have rc=0 for ioctl to get job id for OS/2.
8155 * Network printing will fail if function is not successful.
8156 * Similar function in reply.c will be used if protocol
8157 * is LANMAN1.0 instead of LM1.2X002.
8158 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8159 * outbuf doesn't have to be set(only job id is used).
8161 if ( (state->setup_count == 4)
8162 && (tran_call == TRANSACT2_IOCTL)
8163 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8164 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8165 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8167 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8168 DEBUG(2,("Transaction is %d\n",tran_call));
8170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8171 END_PROFILE(SMBtrans2);
8176 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8179 if (state->total_data) {
8181 if (trans_oob(state->total_data, 0, dscnt)
8182 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8186 /* Can't use talloc here, the core routines do realloc on the
8187 * params and data. */
8188 state->data = (char *)SMB_MALLOC(state->total_data);
8189 if (state->data == NULL) {
8190 DEBUG(0,("reply_trans2: data malloc fail for %u "
8191 "bytes !\n", (unsigned int)state->total_data));
8193 reply_nterror(req, NT_STATUS_NO_MEMORY);
8194 END_PROFILE(SMBtrans2);
8198 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8201 if (state->total_param) {
8203 if (trans_oob(state->total_param, 0, pscnt)
8204 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8208 /* Can't use talloc here, the core routines do realloc on the
8209 * params and data. */
8210 state->param = (char *)SMB_MALLOC(state->total_param);
8211 if (state->param == NULL) {
8212 DEBUG(0,("reply_trans: param malloc fail for %u "
8213 "bytes !\n", (unsigned int)state->total_param));
8214 SAFE_FREE(state->data);
8216 reply_nterror(req, NT_STATUS_NO_MEMORY);
8217 END_PROFILE(SMBtrans2);
8221 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8224 state->received_data = dscnt;
8225 state->received_param = pscnt;
8227 if ((state->received_param == state->total_param) &&
8228 (state->received_data == state->total_data)) {
8230 handle_trans2(conn, req, state);
8232 SAFE_FREE(state->data);
8233 SAFE_FREE(state->param);
8235 END_PROFILE(SMBtrans2);
8239 DLIST_ADD(conn->pending_trans, state);
8241 /* We need to send an interim response then receive the rest
8242 of the parameter/data bytes */
8243 reply_outbuf(req, 0, 0);
8244 show_msg((char *)req->outbuf);
8245 END_PROFILE(SMBtrans2);
8250 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8251 SAFE_FREE(state->data);
8252 SAFE_FREE(state->param);
8254 END_PROFILE(SMBtrans2);
8255 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8259 /****************************************************************************
8260 Reply to a SMBtranss2
8261 ****************************************************************************/
8263 void reply_transs2(struct smb_request *req)
8265 connection_struct *conn = req->conn;
8266 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8267 struct trans_state *state;
8269 START_PROFILE(SMBtranss2);
8271 show_msg((char *)req->inbuf);
8274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8275 END_PROFILE(SMBtranss2);
8279 for (state = conn->pending_trans; state != NULL;
8280 state = state->next) {
8281 if (state->mid == req->mid) {
8286 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8287 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8288 END_PROFILE(SMBtranss2);
8292 /* Revise state->total_param and state->total_data in case they have
8293 changed downwards */
8295 if (SVAL(req->vwv+0, 0) < state->total_param)
8296 state->total_param = SVAL(req->vwv+0, 0);
8297 if (SVAL(req->vwv+1, 0) < state->total_data)
8298 state->total_data = SVAL(req->vwv+1, 0);
8300 pcnt = SVAL(req->vwv+2, 0);
8301 poff = SVAL(req->vwv+3, 0);
8302 pdisp = SVAL(req->vwv+4, 0);
8304 dcnt = SVAL(req->vwv+5, 0);
8305 doff = SVAL(req->vwv+6, 0);
8306 ddisp = SVAL(req->vwv+7, 0);
8308 state->received_param += pcnt;
8309 state->received_data += dcnt;
8311 if ((state->received_data > state->total_data) ||
8312 (state->received_param > state->total_param))
8316 if (trans_oob(state->total_param, pdisp, pcnt)
8317 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8320 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8324 if (trans_oob(state->total_data, ddisp, dcnt)
8325 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8328 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8331 if ((state->received_param < state->total_param) ||
8332 (state->received_data < state->total_data)) {
8333 END_PROFILE(SMBtranss2);
8337 handle_trans2(conn, req, state);
8339 DLIST_REMOVE(conn->pending_trans, state);
8340 SAFE_FREE(state->data);
8341 SAFE_FREE(state->param);
8344 END_PROFILE(SMBtranss2);
8349 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8350 DLIST_REMOVE(conn->pending_trans, state);
8351 SAFE_FREE(state->data);
8352 SAFE_FREE(state->param);
8354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8355 END_PROFILE(SMBtranss2);