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,
1451 struct dptr_struct *dirptr,
1453 const char *path_mask,
1456 int requires_resume_key,
1462 int space_remaining,
1464 bool *got_exact_match,
1465 int *last_entry_off,
1466 struct ea_list *name_list)
1468 const char *mask = NULL;
1469 char *p, *q, *pdata = *ppdata;
1473 SMB_OFF_T file_size = 0;
1474 uint64_t allocation_size = 0;
1476 struct timespec mdate_ts, adate_ts, create_date_ts;
1477 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1479 char *last_entry_ptr;
1481 uint32 nt_extmode; /* Used for NT connections instead of mode */
1483 struct smb_filename *smb_fname = NULL;
1484 struct smbd_dirptr_lanman2_state state;
1489 state.info_level = info_level;
1490 state.check_mangled_names = lp_manglednames(conn->params);
1491 state.has_wild = dptr_has_wild(dirptr);
1492 state.got_exact_match = false;
1494 *out_of_space = False;
1495 *got_exact_match = False;
1497 ZERO_STRUCT(mdate_ts);
1498 ZERO_STRUCT(adate_ts);
1499 ZERO_STRUCT(create_date_ts);
1501 p = strrchr_m(path_mask,'/');
1512 ok = smbd_dirptr_get_entry(ctx,
1518 smbd_dirptr_lanman2_match_fn,
1519 smbd_dirptr_lanman2_mode_fn,
1529 *got_exact_match = state.got_exact_match;
1531 if (!(mode & aDIR)) {
1532 file_size = get_file_size_stat(&smb_fname->st);
1534 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1536 mdate_ts = smb_fname->st.st_ex_mtime;
1537 adate_ts = smb_fname->st.st_ex_atime;
1538 create_date_ts = smb_fname->st.st_ex_btime;
1540 if (lp_dos_filetime_resolution(SNUM(conn))) {
1541 dos_filetime_timespec(&create_date_ts);
1542 dos_filetime_timespec(&mdate_ts);
1543 dos_filetime_timespec(&adate_ts);
1546 create_date = convert_timespec_to_time_t(create_date_ts);
1547 mdate = convert_timespec_to_time_t(mdate_ts);
1548 adate = convert_timespec_to_time_t(adate_ts);
1553 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1555 switch (info_level) {
1556 case SMB_FIND_INFO_STANDARD:
1557 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1558 if(requires_resume_key) {
1562 srv_put_dos_date2(p,0,create_date);
1563 srv_put_dos_date2(p,4,adate);
1564 srv_put_dos_date2(p,8,mdate);
1565 SIVAL(p,12,(uint32)file_size);
1566 SIVAL(p,16,(uint32)allocation_size);
1570 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1571 p += ucs2_align(base_data, p, 0);
1573 len = srvstr_push(base_data, flags2, p,
1574 fname, PTR_DIFF(end_data, p),
1576 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 SCVAL(nameptr, -1, len - 2);
1580 SCVAL(nameptr, -1, 0);
1584 SCVAL(nameptr, -1, len - 1);
1586 SCVAL(nameptr, -1, 0);
1592 case SMB_FIND_EA_SIZE:
1593 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1594 if(requires_resume_key) {
1598 srv_put_dos_date2(p,0,create_date);
1599 srv_put_dos_date2(p,4,adate);
1600 srv_put_dos_date2(p,8,mdate);
1601 SIVAL(p,12,(uint32)file_size);
1602 SIVAL(p,16,(uint32)allocation_size);
1605 unsigned int ea_size = estimate_ea_size(conn, NULL,
1606 smb_fname->base_name);
1607 SIVAL(p,22,ea_size); /* Extended attributes */
1611 len = srvstr_push(base_data, flags2,
1612 p, fname, PTR_DIFF(end_data, p),
1613 STR_TERMINATE | STR_NOALIGN);
1614 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1627 SCVAL(nameptr,0,len);
1629 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1632 case SMB_FIND_EA_LIST:
1634 struct ea_list *file_list = NULL;
1637 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1640 TALLOC_FREE(smb_fname);
1643 if(requires_resume_key) {
1647 srv_put_dos_date2(p,0,create_date);
1648 srv_put_dos_date2(p,4,adate);
1649 srv_put_dos_date2(p,8,mdate);
1650 SIVAL(p,12,(uint32)file_size);
1651 SIVAL(p,16,(uint32)allocation_size);
1653 p += 22; /* p now points to the EA area. */
1655 file_list = get_ea_list_from_file(ctx, conn, NULL,
1656 smb_fname->base_name,
1658 name_list = ea_list_union(name_list, file_list, &ea_len);
1660 /* We need to determine if this entry will fit in the space available. */
1661 /* Max string size is 255 bytes. */
1662 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1664 TALLOC_FREE(smb_fname);
1665 /* Move the dirptr back to prev_dirpos */
1666 dptr_SeekDir(dirptr, prev_dirpos);
1667 *out_of_space = True;
1668 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1669 return False; /* Not finished - just out of space */
1672 /* Push the ea_data followed by the name. */
1673 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1675 len = srvstr_push(base_data, flags2,
1676 p + 1, fname, PTR_DIFF(end_data, p+1),
1677 STR_TERMINATE | STR_NOALIGN);
1678 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1691 SCVAL(nameptr,0,len);
1693 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1697 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1698 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1699 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1701 SIVAL(p,0,reskey); p += 4;
1702 put_long_date_timespec(p,create_date_ts); p += 8;
1703 put_long_date_timespec(p,adate_ts); p += 8;
1704 put_long_date_timespec(p,mdate_ts); p += 8;
1705 put_long_date_timespec(p,mdate_ts); p += 8;
1706 SOFF_T(p,0,file_size); p += 8;
1707 SOFF_T(p,0,allocation_size); p += 8;
1708 SIVAL(p,0,nt_extmode); p += 4;
1709 q = p; p += 4; /* q is placeholder for name length. */
1711 unsigned int ea_size = estimate_ea_size(conn, NULL,
1712 smb_fname->base_name);
1713 SIVAL(p,0,ea_size); /* Extended attributes */
1716 /* Clear the short name buffer. This is
1717 * IMPORTANT as not doing so will trigger
1718 * a Win2k client bug. JRA.
1720 if (!was_8_3 && state.check_mangled_names) {
1721 char mangled_name[13]; /* mangled 8.3 name. */
1722 if (!name_to_8_3(fname,mangled_name,True,
1724 /* Error - mangle failed ! */
1725 memset(mangled_name,'\0',12);
1727 mangled_name[12] = 0;
1728 len = srvstr_push(base_data, flags2,
1729 p+2, mangled_name, 24,
1730 STR_UPPER|STR_UNICODE);
1732 memset(p + 2 + len,'\0',24 - len);
1739 len = srvstr_push(base_data, flags2, p,
1740 fname, PTR_DIFF(end_data, p),
1741 STR_TERMINATE_ASCII);
1744 SIVAL(p,0,0); /* Ensure any padding is null. */
1745 len = PTR_DIFF(p, pdata);
1746 len = (len + 3) & ~3;
1751 case SMB_FIND_FILE_DIRECTORY_INFO:
1752 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1754 SIVAL(p,0,reskey); p += 4;
1755 put_long_date_timespec(p,create_date_ts); p += 8;
1756 put_long_date_timespec(p,adate_ts); p += 8;
1757 put_long_date_timespec(p,mdate_ts); p += 8;
1758 put_long_date_timespec(p,mdate_ts); p += 8;
1759 SOFF_T(p,0,file_size); p += 8;
1760 SOFF_T(p,0,allocation_size); p += 8;
1761 SIVAL(p,0,nt_extmode); p += 4;
1762 len = srvstr_push(base_data, flags2,
1763 p + 4, fname, PTR_DIFF(end_data, p+4),
1764 STR_TERMINATE_ASCII);
1767 SIVAL(p,0,0); /* Ensure any padding is null. */
1768 len = PTR_DIFF(p, pdata);
1769 len = (len + 3) & ~3;
1774 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1775 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1777 SIVAL(p,0,reskey); p += 4;
1778 put_long_date_timespec(p,create_date_ts); p += 8;
1779 put_long_date_timespec(p,adate_ts); p += 8;
1780 put_long_date_timespec(p,mdate_ts); p += 8;
1781 put_long_date_timespec(p,mdate_ts); p += 8;
1782 SOFF_T(p,0,file_size); p += 8;
1783 SOFF_T(p,0,allocation_size); p += 8;
1784 SIVAL(p,0,nt_extmode); p += 4;
1785 q = p; p += 4; /* q is placeholder for name length. */
1787 unsigned int ea_size = estimate_ea_size(conn, NULL,
1788 smb_fname->base_name);
1789 SIVAL(p,0,ea_size); /* Extended attributes */
1792 len = srvstr_push(base_data, flags2, p,
1793 fname, PTR_DIFF(end_data, p),
1794 STR_TERMINATE_ASCII);
1798 SIVAL(p,0,0); /* Ensure any padding is null. */
1799 len = PTR_DIFF(p, pdata);
1800 len = (len + 3) & ~3;
1805 case SMB_FIND_FILE_NAMES_INFO:
1806 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1808 SIVAL(p,0,reskey); p += 4;
1810 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1811 acl on a dir (tridge) */
1812 len = srvstr_push(base_data, flags2, p,
1813 fname, PTR_DIFF(end_data, p),
1814 STR_TERMINATE_ASCII);
1817 SIVAL(p,0,0); /* Ensure any padding is null. */
1818 len = PTR_DIFF(p, pdata);
1819 len = (len + 3) & ~3;
1824 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1827 SIVAL(p,0,reskey); p += 4;
1828 put_long_date_timespec(p,create_date_ts); p += 8;
1829 put_long_date_timespec(p,adate_ts); p += 8;
1830 put_long_date_timespec(p,mdate_ts); p += 8;
1831 put_long_date_timespec(p,mdate_ts); p += 8;
1832 SOFF_T(p,0,file_size); p += 8;
1833 SOFF_T(p,0,allocation_size); p += 8;
1834 SIVAL(p,0,nt_extmode); p += 4;
1835 q = p; p += 4; /* q is placeholder for name length. */
1837 unsigned int ea_size = estimate_ea_size(conn, NULL,
1838 smb_fname->base_name);
1839 SIVAL(p,0,ea_size); /* Extended attributes */
1842 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1843 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1844 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1845 len = srvstr_push(base_data, flags2, p,
1846 fname, PTR_DIFF(end_data, p),
1847 STR_TERMINATE_ASCII);
1850 SIVAL(p,0,0); /* Ensure any padding is null. */
1851 len = PTR_DIFF(p, pdata);
1852 len = (len + 3) & ~3;
1857 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1858 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1859 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1861 SIVAL(p,0,reskey); p += 4;
1862 put_long_date_timespec(p,create_date_ts); p += 8;
1863 put_long_date_timespec(p,adate_ts); p += 8;
1864 put_long_date_timespec(p,mdate_ts); p += 8;
1865 put_long_date_timespec(p,mdate_ts); p += 8;
1866 SOFF_T(p,0,file_size); p += 8;
1867 SOFF_T(p,0,allocation_size); p += 8;
1868 SIVAL(p,0,nt_extmode); p += 4;
1869 q = p; p += 4; /* q is placeholder for name length */
1871 unsigned int ea_size = estimate_ea_size(conn, NULL,
1872 smb_fname->base_name);
1873 SIVAL(p,0,ea_size); /* Extended attributes */
1876 /* Clear the short name buffer. This is
1877 * IMPORTANT as not doing so will trigger
1878 * a Win2k client bug. JRA.
1880 if (!was_8_3 && state.check_mangled_names) {
1881 char mangled_name[13]; /* mangled 8.3 name. */
1882 if (!name_to_8_3(fname,mangled_name,True,
1884 /* Error - mangle failed ! */
1885 memset(mangled_name,'\0',12);
1887 mangled_name[12] = 0;
1888 len = srvstr_push(base_data, flags2,
1889 p+2, mangled_name, 24,
1890 STR_UPPER|STR_UNICODE);
1893 memset(p + 2 + len,'\0',24 - len);
1900 SSVAL(p,0,0); p += 2; /* Reserved ? */
1901 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1902 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1903 len = srvstr_push(base_data, flags2, p,
1904 fname, PTR_DIFF(end_data, p),
1905 STR_TERMINATE_ASCII);
1908 SIVAL(p,0,0); /* Ensure any padding is null. */
1909 len = PTR_DIFF(p, pdata);
1910 len = (len + 3) & ~3;
1915 /* CIFS UNIX Extension. */
1917 case SMB_FIND_FILE_UNIX:
1918 case SMB_FIND_FILE_UNIX_INFO2:
1920 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1922 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1924 if (info_level == SMB_FIND_FILE_UNIX) {
1925 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1926 p = store_file_unix_basic(conn, p,
1927 NULL, &smb_fname->st);
1928 len = srvstr_push(base_data, flags2, p,
1929 fname, PTR_DIFF(end_data, p),
1932 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1933 p = store_file_unix_basic_info2(conn, p,
1934 NULL, &smb_fname->st);
1937 len = srvstr_push(base_data, flags2, p, fname,
1938 PTR_DIFF(end_data, p), 0);
1939 SIVAL(nameptr, 0, len);
1943 SIVAL(p,0,0); /* Ensure any padding is null. */
1945 len = PTR_DIFF(p, pdata);
1946 len = (len + 3) & ~3;
1947 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1949 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1955 TALLOC_FREE(smb_fname);
1960 TALLOC_FREE(smb_fname);
1962 if (PTR_DIFF(p,pdata) > space_remaining) {
1963 /* Move the dirptr back to prev_dirpos */
1964 dptr_SeekDir(dirptr, prev_dirpos);
1965 *out_of_space = True;
1966 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1967 return False; /* Not finished - just out of space */
1970 /* Setup the last entry pointer, as an offset from base_data */
1971 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1972 /* Advance the data pointer to the next slot */
1978 /****************************************************************************
1979 Reply to a TRANS2_FINDFIRST.
1980 ****************************************************************************/
1982 static void call_trans2findfirst(connection_struct *conn,
1983 struct smb_request *req,
1984 char **pparams, int total_params,
1985 char **ppdata, int total_data,
1986 unsigned int max_data_bytes)
1988 /* We must be careful here that we don't return more than the
1989 allowed number of data bytes. If this means returning fewer than
1990 maxentries then so be it. We assume that the redirector has
1991 enough room for the fixed number of parameter bytes it has
1993 struct smb_filename *smb_dname = NULL;
1994 char *params = *pparams;
1995 char *pdata = *ppdata;
1999 uint16 findfirst_flags;
2000 bool close_after_first;
2002 bool requires_resume_key;
2004 char *directory = NULL;
2007 int last_entry_off=0;
2011 bool finished = False;
2012 bool dont_descend = False;
2013 bool out_of_space = False;
2014 int space_remaining;
2015 bool mask_contains_wcard = False;
2016 struct ea_list *ea_list = NULL;
2017 NTSTATUS ntstatus = NT_STATUS_OK;
2018 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2019 TALLOC_CTX *ctx = talloc_tos();
2020 struct dptr_struct *dirptr = NULL;
2022 if (total_params < 13) {
2023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2027 dirtype = SVAL(params,0);
2028 maxentries = SVAL(params,2);
2029 findfirst_flags = SVAL(params,4);
2030 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2031 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2032 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2033 info_level = SVAL(params,6);
2035 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2036 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2037 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2038 info_level, max_data_bytes));
2041 /* W2K3 seems to treat zero as 1. */
2045 switch (info_level) {
2046 case SMB_FIND_INFO_STANDARD:
2047 case SMB_FIND_EA_SIZE:
2048 case SMB_FIND_EA_LIST:
2049 case SMB_FIND_FILE_DIRECTORY_INFO:
2050 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2051 case SMB_FIND_FILE_NAMES_INFO:
2052 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2053 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2054 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2056 case SMB_FIND_FILE_UNIX:
2057 case SMB_FIND_FILE_UNIX_INFO2:
2058 /* Always use filesystem for UNIX mtime query. */
2059 ask_sharemode = false;
2060 if (!lp_unix_extensions()) {
2061 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2066 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2070 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2071 params+12, total_params - 12,
2072 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2073 if (!NT_STATUS_IS_OK(ntstatus)) {
2074 reply_nterror(req, ntstatus);
2078 ntstatus = filename_convert(ctx, conn,
2079 req->flags2 & FLAGS2_DFS_PATHNAMES,
2082 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2083 &mask_contains_wcard,
2085 if (!NT_STATUS_IS_OK(ntstatus)) {
2086 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2087 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2088 ERRSRV, ERRbadpath);
2091 reply_nterror(req, ntstatus);
2095 mask = smb_dname->original_lcomp;
2097 directory = smb_dname->base_name;
2099 p = strrchr_m(directory,'/');
2101 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2102 if((directory[0] == '.') && (directory[1] == '\0')) {
2103 mask = talloc_strdup(ctx,"*");
2105 reply_nterror(req, NT_STATUS_NO_MEMORY);
2108 mask_contains_wcard = True;
2110 directory = talloc_strdup(talloc_tos(), "./");
2112 reply_nterror(req, NT_STATUS_NO_MEMORY);
2119 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2121 if (info_level == SMB_FIND_EA_LIST) {
2124 if (total_data < 4) {
2125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2129 ea_size = IVAL(pdata,0);
2130 if (ea_size != total_data) {
2131 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2132 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2137 if (!lp_ea_support(SNUM(conn))) {
2138 reply_doserror(req, ERRDOS, ERReasnotsupported);
2142 /* Pull out the list of names. */
2143 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2150 *ppdata = (char *)SMB_REALLOC(
2151 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2152 if(*ppdata == NULL ) {
2153 reply_nterror(req, NT_STATUS_NO_MEMORY);
2157 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2159 /* Realloc the params space */
2160 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2161 if (*pparams == NULL) {
2162 reply_nterror(req, NT_STATUS_NO_MEMORY);
2167 /* Save the wildcard match and attribs we are using on this directory -
2168 needed as lanman2 assumes these are being saved between calls */
2170 ntstatus = dptr_create(conn,
2176 mask_contains_wcard,
2180 if (!NT_STATUS_IS_OK(ntstatus)) {
2181 reply_nterror(req, ntstatus);
2185 dptr_num = dptr_dnum(dirptr);
2186 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2188 /* Initialize per TRANS2_FIND_FIRST operation data */
2189 dptr_init_search_op(dirptr);
2191 /* We don't need to check for VOL here as this is returned by
2192 a different TRANS2 call. */
2194 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2195 directory,lp_dontdescend(SNUM(conn))));
2196 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2197 dont_descend = True;
2200 space_remaining = max_data_bytes;
2201 out_of_space = False;
2203 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2204 bool got_exact_match = False;
2206 /* this is a heuristic to avoid seeking the dirptr except when
2207 absolutely necessary. It allows for a filename of about 40 chars */
2208 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2209 out_of_space = True;
2212 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();
2358 struct dptr_struct *dirptr;
2360 if (total_params < 13) {
2361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2365 dptr_num = SVAL(params,0);
2366 maxentries = SVAL(params,2);
2367 info_level = SVAL(params,4);
2368 resume_key = IVAL(params,6);
2369 findnext_flags = SVAL(params,10);
2370 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2371 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2372 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2373 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2375 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2377 total_params - 12, STR_TERMINATE, &ntstatus,
2378 &mask_contains_wcard);
2379 if (!NT_STATUS_IS_OK(ntstatus)) {
2380 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2381 complain (it thinks we're asking for the directory above the shared
2382 path or an invalid name). Catch this as the resume name is only compared, never used in
2383 a file access. JRA. */
2384 srvstr_pull_talloc(ctx, params, req->flags2,
2385 &resume_name, params+12,
2389 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2390 reply_nterror(req, ntstatus);
2395 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2396 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2397 resume_key = %d resume name = %s continue=%d level = %d\n",
2398 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2399 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2402 /* W2K3 seems to treat zero as 1. */
2406 switch (info_level) {
2407 case SMB_FIND_INFO_STANDARD:
2408 case SMB_FIND_EA_SIZE:
2409 case SMB_FIND_EA_LIST:
2410 case SMB_FIND_FILE_DIRECTORY_INFO:
2411 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2412 case SMB_FIND_FILE_NAMES_INFO:
2413 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2414 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2415 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2417 case SMB_FIND_FILE_UNIX:
2418 case SMB_FIND_FILE_UNIX_INFO2:
2419 /* Always use filesystem for UNIX mtime query. */
2420 ask_sharemode = false;
2421 if (!lp_unix_extensions()) {
2422 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2427 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2431 if (info_level == SMB_FIND_EA_LIST) {
2434 if (total_data < 4) {
2435 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2439 ea_size = IVAL(pdata,0);
2440 if (ea_size != total_data) {
2441 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2442 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2443 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2447 if (!lp_ea_support(SNUM(conn))) {
2448 reply_doserror(req, ERRDOS, ERReasnotsupported);
2452 /* Pull out the list of names. */
2453 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2455 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2460 *ppdata = (char *)SMB_REALLOC(
2461 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2462 if(*ppdata == NULL) {
2463 reply_nterror(req, NT_STATUS_NO_MEMORY);
2468 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2470 /* Realloc the params space */
2471 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2472 if(*pparams == NULL ) {
2473 reply_nterror(req, NT_STATUS_NO_MEMORY);
2479 /* Check that the dptr is valid */
2480 if(!(dirptr = dptr_fetch_lanman2(dptr_num))) {
2481 reply_doserror(req, ERRDOS, ERRnofiles);
2485 directory = dptr_path(dptr_num);
2487 /* Get the wildcard mask from the dptr */
2488 if((p = dptr_wcard(dptr_num))== NULL) {
2489 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2490 reply_doserror(req, ERRDOS, ERRnofiles);
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(dirptr)));
2504 /* Initialize per TRANS2_FIND_NEXT operation data */
2505 dptr_init_search_op(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",
2511 directory,lp_dontdescend(SNUM(conn))));
2512 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2513 dont_descend = True;
2516 space_remaining = max_data_bytes;
2517 out_of_space = False;
2520 * Seek to the correct position. We no longer use the resume key but
2521 * depend on the last file name instead.
2524 if(*resume_name && !continue_bit) {
2527 long current_pos = 0;
2529 * Remember, name_to_8_3 is called by
2530 * get_lanman2_dir_entry(), so the resume name
2531 * could be mangled. Ensure we check the unmangled name.
2534 if (mangle_is_mangled(resume_name, conn->params)) {
2535 char *new_resume_name = NULL;
2536 mangle_lookup_name_from_8_3(ctx,
2540 if (new_resume_name) {
2541 resume_name = new_resume_name;
2546 * Fix for NT redirector problem triggered by resume key indexes
2547 * changing between directory scans. We now return a resume key of 0
2548 * and instead look for the filename to continue from (also given
2549 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2550 * findfirst/findnext (as is usual) then the directory pointer
2551 * should already be at the correct place.
2554 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2555 } /* end if resume_name && !continue_bit */
2557 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2558 bool got_exact_match = False;
2560 /* this is a heuristic to avoid seeking the dirptr except when
2561 absolutely necessary. It allows for a filename of about 40 chars */
2562 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2563 out_of_space = True;
2566 finished = !get_lanman2_dir_entry(ctx,
2570 mask,dirtype,info_level,
2571 requires_resume_key,dont_descend,
2574 space_remaining, &out_of_space,
2576 &last_entry_off, ea_list);
2579 if (finished && out_of_space)
2582 if (!finished && !out_of_space)
2586 * As an optimisation if we know we aren't looking
2587 * for a wildcard name (ie. the name matches the wildcard exactly)
2588 * then we can finish on any (first) match.
2589 * This speeds up large directory searches. JRA.
2595 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2598 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2599 smb_fn_name(req->cmd),
2600 mask, directory, dirtype, numentries ) );
2602 /* Check if we can close the dirptr */
2603 if(close_after_request || (finished && close_if_end)) {
2604 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2605 dptr_close(&dptr_num); /* This frees up the saved mask */
2608 /* Set up the return parameter block */
2609 SSVAL(params,0,numentries);
2610 SSVAL(params,2,finished);
2611 SSVAL(params,4,0); /* Never an EA error */
2612 SSVAL(params,6,last_entry_off);
2614 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2620 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2622 E_md4hash(lp_servicename(SNUM(conn)),objid);
2626 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2628 SMB_ASSERT(extended_info != NULL);
2630 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2631 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2632 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2633 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2634 #ifdef SAMBA_VERSION_REVISION
2635 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2637 extended_info->samba_subversion = 0;
2638 #ifdef SAMBA_VERSION_RC_RELEASE
2639 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2641 #ifdef SAMBA_VERSION_PRE_RELEASE
2642 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2645 #ifdef SAMBA_VERSION_VENDOR_PATCH
2646 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2648 extended_info->samba_gitcommitdate = 0;
2649 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2650 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2653 memset(extended_info->samba_version_string, 0,
2654 sizeof(extended_info->samba_version_string));
2656 snprintf (extended_info->samba_version_string,
2657 sizeof(extended_info->samba_version_string),
2658 "%s", samba_version_string());
2661 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2662 TALLOC_CTX *mem_ctx,
2663 uint16_t info_level,
2665 unsigned int max_data_bytes,
2669 char *pdata, *end_data;
2670 int data_len = 0, len;
2671 const char *vname = volume_label(SNUM(conn));
2672 int snum = SNUM(conn);
2673 char *fstype = lp_fstype(SNUM(conn));
2674 uint32 additional_flags = 0;
2675 struct smb_filename *smb_fname_dot = NULL;
2680 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2681 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2682 "info level (0x%x) on IPC$.\n",
2683 (unsigned int)info_level));
2684 return NT_STATUS_ACCESS_DENIED;
2688 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2690 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2692 if (!NT_STATUS_IS_OK(status)) {
2696 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2697 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2698 TALLOC_FREE(smb_fname_dot);
2699 return map_nt_error_from_unix(errno);
2702 st = smb_fname_dot->st;
2703 TALLOC_FREE(smb_fname_dot);
2705 *ppdata = (char *)SMB_REALLOC(
2706 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2707 if (*ppdata == NULL) {
2708 return NT_STATUS_NO_MEMORY;
2712 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2713 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2715 switch (info_level) {
2716 case SMB_INFO_ALLOCATION:
2718 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2720 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2721 return map_nt_error_from_unix(errno);
2724 block_size = lp_block_size(snum);
2725 if (bsize < block_size) {
2726 uint64_t factor = block_size/bsize;
2731 if (bsize > block_size) {
2732 uint64_t factor = bsize/block_size;
2737 bytes_per_sector = 512;
2738 sectors_per_unit = bsize/bytes_per_sector;
2740 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2741 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2742 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2744 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2745 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2746 SIVAL(pdata,l1_cUnit,dsize);
2747 SIVAL(pdata,l1_cUnitAvail,dfree);
2748 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2752 case SMB_INFO_VOLUME:
2753 /* Return volume name */
2755 * Add volume serial number - hash of a combination of
2756 * the called hostname and the service name.
2758 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2760 * Win2k3 and previous mess this up by sending a name length
2761 * one byte short. I believe only older clients (OS/2 Win9x) use
2762 * this call so try fixing this by adding a terminating null to
2763 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2767 pdata+l2_vol_szVolLabel, vname,
2768 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2769 STR_NOALIGN|STR_TERMINATE);
2770 SCVAL(pdata,l2_vol_cch,len);
2771 data_len = l2_vol_szVolLabel + len;
2772 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2773 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2777 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2778 case SMB_FS_ATTRIBUTE_INFORMATION:
2780 additional_flags = 0;
2781 #if defined(HAVE_SYS_QUOTAS)
2782 additional_flags |= FILE_VOLUME_QUOTAS;
2785 if(lp_nt_acl_support(SNUM(conn))) {
2786 additional_flags |= FILE_PERSISTENT_ACLS;
2789 /* Capabilities are filled in at connection time through STATVFS call */
2790 additional_flags |= conn->fs_capabilities;
2792 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2793 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2794 additional_flags); /* FS ATTRIBUTES */
2796 SIVAL(pdata,4,255); /* Max filename component length */
2797 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2798 and will think we can't do long filenames */
2799 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2800 PTR_DIFF(end_data, pdata+12),
2803 data_len = 12 + len;
2806 case SMB_QUERY_FS_LABEL_INFO:
2807 case SMB_FS_LABEL_INFORMATION:
2808 len = srvstr_push(pdata, flags2, pdata+4, vname,
2809 PTR_DIFF(end_data, pdata+4), 0);
2814 case SMB_QUERY_FS_VOLUME_INFO:
2815 case SMB_FS_VOLUME_INFORMATION:
2818 * Add volume serial number - hash of a combination of
2819 * the called hostname and the service name.
2821 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2822 (str_checksum(get_local_machine_name())<<16));
2824 /* Max label len is 32 characters. */
2825 len = srvstr_push(pdata, flags2, pdata+18, vname,
2826 PTR_DIFF(end_data, pdata+18),
2828 SIVAL(pdata,12,len);
2831 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2832 (int)strlen(vname),vname, lp_servicename(snum)));
2835 case SMB_QUERY_FS_SIZE_INFO:
2836 case SMB_FS_SIZE_INFORMATION:
2838 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2840 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2841 return map_nt_error_from_unix(errno);
2843 block_size = lp_block_size(snum);
2844 if (bsize < block_size) {
2845 uint64_t factor = block_size/bsize;
2850 if (bsize > block_size) {
2851 uint64_t factor = bsize/block_size;
2856 bytes_per_sector = 512;
2857 sectors_per_unit = bsize/bytes_per_sector;
2858 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2859 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2860 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2861 SBIG_UINT(pdata,0,dsize);
2862 SBIG_UINT(pdata,8,dfree);
2863 SIVAL(pdata,16,sectors_per_unit);
2864 SIVAL(pdata,20,bytes_per_sector);
2868 case SMB_FS_FULL_SIZE_INFORMATION:
2870 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2872 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2873 return map_nt_error_from_unix(errno);
2875 block_size = lp_block_size(snum);
2876 if (bsize < block_size) {
2877 uint64_t factor = block_size/bsize;
2882 if (bsize > block_size) {
2883 uint64_t factor = bsize/block_size;
2888 bytes_per_sector = 512;
2889 sectors_per_unit = bsize/bytes_per_sector;
2890 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2891 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2892 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2893 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2894 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2895 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2896 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2897 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2901 case SMB_QUERY_FS_DEVICE_INFO:
2902 case SMB_FS_DEVICE_INFORMATION:
2904 SIVAL(pdata,0,0); /* dev type */
2905 SIVAL(pdata,4,0); /* characteristics */
2908 #ifdef HAVE_SYS_QUOTAS
2909 case SMB_FS_QUOTA_INFORMATION:
2911 * what we have to send --metze:
2913 * Unknown1: 24 NULL bytes
2914 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2915 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2916 * Quota Flags: 2 byte :
2917 * Unknown3: 6 NULL bytes
2921 * details for Quota Flags:
2923 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2924 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2925 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2926 * 0x0001 Enable Quotas: enable quota for this fs
2930 /* we need to fake up a fsp here,
2931 * because its not send in this call
2934 SMB_NTQUOTA_STRUCT quotas;
2937 ZERO_STRUCT(quotas);
2943 if (conn->server_info->utok.uid != sec_initial_uid()) {
2944 DEBUG(0,("set_user_quota: access_denied "
2945 "service [%s] user [%s]\n",
2946 lp_servicename(SNUM(conn)),
2947 conn->server_info->unix_name));
2948 return NT_STATUS_ACCESS_DENIED;
2951 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2952 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2953 return map_nt_error_from_unix(errno);
2958 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2959 lp_servicename(SNUM(conn))));
2961 /* Unknown1 24 NULL bytes*/
2962 SBIG_UINT(pdata,0,(uint64_t)0);
2963 SBIG_UINT(pdata,8,(uint64_t)0);
2964 SBIG_UINT(pdata,16,(uint64_t)0);
2966 /* Default Soft Quota 8 bytes */
2967 SBIG_UINT(pdata,24,quotas.softlim);
2969 /* Default Hard Quota 8 bytes */
2970 SBIG_UINT(pdata,32,quotas.hardlim);
2972 /* Quota flag 2 bytes */
2973 SSVAL(pdata,40,quotas.qflags);
2975 /* Unknown3 6 NULL bytes */
2981 #endif /* HAVE_SYS_QUOTAS */
2982 case SMB_FS_OBJECTID_INFORMATION:
2984 unsigned char objid[16];
2985 struct smb_extended_info extended_info;
2986 memcpy(pdata,create_volume_objectid(conn, objid),16);
2987 samba_extended_info_version (&extended_info);
2988 SIVAL(pdata,16,extended_info.samba_magic);
2989 SIVAL(pdata,20,extended_info.samba_version);
2990 SIVAL(pdata,24,extended_info.samba_subversion);
2991 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2992 memcpy(pdata+36,extended_info.samba_version_string,28);
2998 * Query the version and capabilities of the CIFS UNIX extensions
3002 case SMB_QUERY_CIFS_UNIX_INFO:
3004 bool large_write = lp_min_receive_file_size() &&
3005 !srv_is_signing_active(smbd_server_conn);
3006 bool large_read = !srv_is_signing_active(smbd_server_conn);
3007 int encrypt_caps = 0;
3009 if (!lp_unix_extensions()) {
3010 return NT_STATUS_INVALID_LEVEL;
3013 switch (conn->encrypt_level) {
3019 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3022 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3023 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3024 large_write = false;
3030 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3031 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3033 /* We have POSIX ACLs, pathname, encryption,
3034 * large read/write, and locking capability. */
3036 SBIG_UINT(pdata,4,((uint64_t)(
3037 CIFS_UNIX_POSIX_ACLS_CAP|
3038 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3039 CIFS_UNIX_FCNTL_LOCKS_CAP|
3040 CIFS_UNIX_EXTATTR_CAP|
3041 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3043 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3045 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3049 case SMB_QUERY_POSIX_FS_INFO:
3052 vfs_statvfs_struct svfs;
3054 if (!lp_unix_extensions()) {
3055 return NT_STATUS_INVALID_LEVEL;
3058 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3062 SIVAL(pdata,0,svfs.OptimalTransferSize);
3063 SIVAL(pdata,4,svfs.BlockSize);
3064 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3065 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3066 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3067 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3068 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3069 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3070 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3072 } else if (rc == EOPNOTSUPP) {
3073 return NT_STATUS_INVALID_LEVEL;
3074 #endif /* EOPNOTSUPP */
3076 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3077 return NT_STATUS_DOS(ERRSRV, ERRerror);
3082 case SMB_QUERY_POSIX_WHOAMI:
3088 if (!lp_unix_extensions()) {
3089 return NT_STATUS_INVALID_LEVEL;
3092 if (max_data_bytes < 40) {
3093 return NT_STATUS_BUFFER_TOO_SMALL;
3096 /* We ARE guest if global_sid_Builtin_Guests is
3097 * in our list of SIDs.
3099 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3100 conn->server_info->ptok)) {
3101 flags |= SMB_WHOAMI_GUEST;
3104 /* We are NOT guest if global_sid_Authenticated_Users
3105 * is in our list of SIDs.
3107 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3108 conn->server_info->ptok)) {
3109 flags &= ~SMB_WHOAMI_GUEST;
3112 /* NOTE: 8 bytes for UID/GID, irrespective of native
3113 * platform size. This matches
3114 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3116 data_len = 4 /* flags */
3123 + 4 /* pad/reserved */
3124 + (conn->server_info->utok.ngroups * 8)
3126 + (conn->server_info->ptok->num_sids *
3130 SIVAL(pdata, 0, flags);
3131 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3133 (uint64_t)conn->server_info->utok.uid);
3134 SBIG_UINT(pdata, 16,
3135 (uint64_t)conn->server_info->utok.gid);
3138 if (data_len >= max_data_bytes) {
3139 /* Potential overflow, skip the GIDs and SIDs. */
3141 SIVAL(pdata, 24, 0); /* num_groups */
3142 SIVAL(pdata, 28, 0); /* num_sids */
3143 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3144 SIVAL(pdata, 36, 0); /* reserved */
3150 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3151 SIVAL(pdata, 28, conn->server_info->num_sids);
3153 /* We walk the SID list twice, but this call is fairly
3154 * infrequent, and I don't expect that it's performance
3155 * sensitive -- jpeach
3157 for (i = 0, sid_bytes = 0;
3158 i < conn->server_info->ptok->num_sids; ++i) {
3159 sid_bytes += ndr_size_dom_sid(
3160 &conn->server_info->ptok->user_sids[i],
3165 /* SID list byte count */
3166 SIVAL(pdata, 32, sid_bytes);
3168 /* 4 bytes pad/reserved - must be zero */
3169 SIVAL(pdata, 36, 0);
3173 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3174 SBIG_UINT(pdata, data_len,
3175 (uint64_t)conn->server_info->utok.groups[i]);
3181 i < conn->server_info->ptok->num_sids; ++i) {
3182 int sid_len = ndr_size_dom_sid(
3183 &conn->server_info->ptok->user_sids[i],
3187 sid_linearize(pdata + data_len, sid_len,
3188 &conn->server_info->ptok->user_sids[i]);
3189 data_len += sid_len;
3195 case SMB_MAC_QUERY_FS_INFO:
3197 * Thursby MAC extension... ONLY on NTFS filesystems
3198 * once we do streams then we don't need this
3200 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3202 SIVAL(pdata,84,0x100); /* Don't support mac... */
3207 return NT_STATUS_INVALID_LEVEL;
3210 *ret_data_len = data_len;
3211 return NT_STATUS_OK;
3214 /****************************************************************************
3215 Reply to a TRANS2_QFSINFO (query filesystem info).
3216 ****************************************************************************/
3218 static void call_trans2qfsinfo(connection_struct *conn,
3219 struct smb_request *req,
3220 char **pparams, int total_params,
3221 char **ppdata, int total_data,
3222 unsigned int max_data_bytes)
3224 char *params = *pparams;
3225 uint16_t info_level;
3229 if (total_params < 2) {
3230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3234 info_level = SVAL(params,0);
3236 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3237 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3238 DEBUG(0,("call_trans2qfsinfo: encryption required "
3239 "and info level 0x%x sent.\n",
3240 (unsigned int)info_level));
3241 exit_server_cleanly("encryption required "
3247 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3249 status = smbd_do_qfsinfo(conn, req,
3254 if (!NT_STATUS_IS_OK(status)) {
3255 reply_nterror(req, status);
3259 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3262 DEBUG( 4, ( "%s info_level = %d\n",
3263 smb_fn_name(req->cmd), info_level) );
3268 /****************************************************************************
3269 Reply to a TRANS2_SETFSINFO (set filesystem info).
3270 ****************************************************************************/
3272 static void call_trans2setfsinfo(connection_struct *conn,
3273 struct smb_request *req,
3274 char **pparams, int total_params,
3275 char **ppdata, int total_data,
3276 unsigned int max_data_bytes)
3278 char *pdata = *ppdata;
3279 char *params = *pparams;
3282 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3285 if (total_params < 4) {
3286 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3292 info_level = SVAL(params,2);
3295 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3296 info_level != SMB_SET_CIFS_UNIX_INFO) {
3297 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3298 "info level (0x%x) on IPC$.\n",
3299 (unsigned int)info_level));
3300 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3305 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3306 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3307 DEBUG(0,("call_trans2setfsinfo: encryption required "
3308 "and info level 0x%x sent.\n",
3309 (unsigned int)info_level));
3310 exit_server_cleanly("encryption required "
3316 switch(info_level) {
3317 case SMB_SET_CIFS_UNIX_INFO:
3319 uint16 client_unix_major;
3320 uint16 client_unix_minor;
3321 uint32 client_unix_cap_low;
3322 uint32 client_unix_cap_high;
3324 if (!lp_unix_extensions()) {
3326 NT_STATUS_INVALID_LEVEL);
3330 /* There should be 12 bytes of capabilities set. */
3331 if (total_data < 8) {
3334 NT_STATUS_INVALID_PARAMETER);
3337 client_unix_major = SVAL(pdata,0);
3338 client_unix_minor = SVAL(pdata,2);
3339 client_unix_cap_low = IVAL(pdata,4);
3340 client_unix_cap_high = IVAL(pdata,8);
3341 /* Just print these values for now. */
3342 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3343 cap_low = 0x%x, cap_high = 0x%x\n",
3344 (unsigned int)client_unix_major,
3345 (unsigned int)client_unix_minor,
3346 (unsigned int)client_unix_cap_low,
3347 (unsigned int)client_unix_cap_high ));
3349 /* Here is where we must switch to posix pathname processing... */
3350 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3351 lp_set_posix_pathnames();
3352 mangle_change_to_posix();
3355 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3356 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3357 /* Client that knows how to do posix locks,
3358 * but not posix open/mkdir operations. Set a
3359 * default type for read/write checks. */
3361 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3367 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3370 size_t param_len = 0;
3371 size_t data_len = total_data;
3373 if (!lp_unix_extensions()) {
3376 NT_STATUS_INVALID_LEVEL);
3380 if (lp_smb_encrypt(SNUM(conn)) == false) {
3383 NT_STATUS_NOT_SUPPORTED);
3387 DEBUG( 4,("call_trans2setfsinfo: "
3388 "request transport encryption.\n"));
3390 status = srv_request_encryption_setup(conn,
3391 (unsigned char **)ppdata,
3393 (unsigned char **)pparams,
3396 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3397 !NT_STATUS_IS_OK(status)) {
3398 reply_nterror(req, status);
3402 send_trans2_replies(conn, req,
3409 if (NT_STATUS_IS_OK(status)) {
3410 /* Server-side transport
3411 * encryption is now *on*. */
3412 status = srv_encryption_start(conn);
3413 if (!NT_STATUS_IS_OK(status)) {
3414 exit_server_cleanly(
3415 "Failure in setting "
3416 "up encrypted transport");
3422 case SMB_FS_QUOTA_INFORMATION:
3424 files_struct *fsp = NULL;
3425 SMB_NTQUOTA_STRUCT quotas;
3427 ZERO_STRUCT(quotas);
3430 if ((conn->server_info->utok.uid != sec_initial_uid())
3431 ||!CAN_WRITE(conn)) {
3432 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3433 lp_servicename(SNUM(conn)),
3434 conn->server_info->unix_name));
3435 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3439 /* note: normaly there're 48 bytes,
3440 * but we didn't use the last 6 bytes for now
3443 fsp = file_fsp(req, SVAL(params,0));
3445 if (!check_fsp_ntquota_handle(conn, req,
3447 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3449 req, NT_STATUS_INVALID_HANDLE);
3453 if (total_data < 42) {
3454 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3458 NT_STATUS_INVALID_PARAMETER);
3462 /* unknown_1 24 NULL bytes in pdata*/
3464 /* the soft quotas 8 bytes (uint64_t)*/
3465 quotas.softlim = (uint64_t)IVAL(pdata,24);
3466 #ifdef LARGE_SMB_OFF_T
3467 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3468 #else /* LARGE_SMB_OFF_T */
3469 if ((IVAL(pdata,28) != 0)&&
3470 ((quotas.softlim != 0xFFFFFFFF)||
3471 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3472 /* more than 32 bits? */
3475 NT_STATUS_INVALID_PARAMETER);
3478 #endif /* LARGE_SMB_OFF_T */
3480 /* the hard quotas 8 bytes (uint64_t)*/
3481 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3482 #ifdef LARGE_SMB_OFF_T
3483 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3484 #else /* LARGE_SMB_OFF_T */
3485 if ((IVAL(pdata,36) != 0)&&
3486 ((quotas.hardlim != 0xFFFFFFFF)||
3487 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3488 /* more than 32 bits? */
3491 NT_STATUS_INVALID_PARAMETER);
3494 #endif /* LARGE_SMB_OFF_T */
3496 /* quota_flags 2 bytes **/
3497 quotas.qflags = SVAL(pdata,40);
3499 /* unknown_2 6 NULL bytes follow*/
3501 /* now set the quotas */
3502 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3503 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3504 reply_nterror(req, map_nt_error_from_unix(errno));
3511 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3513 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3519 * sending this reply works fine,
3520 * but I'm not sure it's the same
3521 * like windows do...
3524 reply_outbuf(req, 10, 0);
3527 #if defined(HAVE_POSIX_ACLS)
3528 /****************************************************************************
3529 Utility function to count the number of entries in a POSIX acl.
3530 ****************************************************************************/
3532 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3534 unsigned int ace_count = 0;
3535 int entry_id = SMB_ACL_FIRST_ENTRY;
3536 SMB_ACL_ENTRY_T entry;
3538 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3540 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3541 entry_id = SMB_ACL_NEXT_ENTRY;
3548 /****************************************************************************
3549 Utility function to marshall a POSIX acl into wire format.
3550 ****************************************************************************/
3552 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3554 int entry_id = SMB_ACL_FIRST_ENTRY;
3555 SMB_ACL_ENTRY_T entry;
3557 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3558 SMB_ACL_TAG_T tagtype;
3559 SMB_ACL_PERMSET_T permset;
3560 unsigned char perms = 0;
3561 unsigned int own_grp;
3564 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3565 entry_id = SMB_ACL_NEXT_ENTRY;
3568 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3569 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3573 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3574 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3578 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3579 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3580 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3582 SCVAL(pdata,1,perms);
3585 case SMB_ACL_USER_OBJ:
3586 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3587 own_grp = (unsigned int)pst->st_ex_uid;
3588 SIVAL(pdata,2,own_grp);
3593 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3595 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3598 own_grp = (unsigned int)*puid;
3599 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3600 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3601 SIVAL(pdata,2,own_grp);
3605 case SMB_ACL_GROUP_OBJ:
3606 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3607 own_grp = (unsigned int)pst->st_ex_gid;
3608 SIVAL(pdata,2,own_grp);
3613 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3615 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3618 own_grp = (unsigned int)*pgid;
3619 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3620 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3621 SIVAL(pdata,2,own_grp);
3626 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3627 SIVAL(pdata,2,0xFFFFFFFF);
3628 SIVAL(pdata,6,0xFFFFFFFF);
3631 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3632 SIVAL(pdata,2,0xFFFFFFFF);
3633 SIVAL(pdata,6,0xFFFFFFFF);
3636 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3639 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3646 /****************************************************************************
3647 Store the FILE_UNIX_BASIC info.
3648 ****************************************************************************/
3650 static char *store_file_unix_basic(connection_struct *conn,
3653 const SMB_STRUCT_STAT *psbuf)
3655 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3656 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3658 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3661 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3664 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3665 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3666 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3669 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3673 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3677 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3680 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3684 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3688 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3691 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3695 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3702 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3703 * the chflags(2) (or equivalent) flags.
3705 * XXX: this really should be behind the VFS interface. To do this, we would
3706 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3707 * Each VFS module could then implement its own mapping as appropriate for the
3708 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3710 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3714 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3718 { UF_IMMUTABLE, EXT_IMMUTABLE },
3722 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3726 { UF_HIDDEN, EXT_HIDDEN },
3729 /* Do not remove. We need to guarantee that this array has at least one
3730 * entry to build on HP-UX.
3736 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3737 uint32 *smb_fflags, uint32 *smb_fmask)
3741 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3742 *smb_fmask |= info2_flags_map[i].smb_fflag;
3743 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3744 *smb_fflags |= info2_flags_map[i].smb_fflag;
3749 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3750 const uint32 smb_fflags,
3751 const uint32 smb_fmask,
3754 uint32 max_fmask = 0;
3757 *stat_fflags = psbuf->st_ex_flags;
3759 /* For each flags requested in smb_fmask, check the state of the
3760 * corresponding flag in smb_fflags and set or clear the matching
3764 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3765 max_fmask |= info2_flags_map[i].smb_fflag;
3766 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3767 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3768 *stat_fflags |= info2_flags_map[i].stat_fflag;
3770 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3775 /* If smb_fmask is asking to set any bits that are not supported by
3776 * our flag mappings, we should fail.
3778 if ((smb_fmask & max_fmask) != smb_fmask) {
3786 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3787 * of file flags and birth (create) time.
3789 static char *store_file_unix_basic_info2(connection_struct *conn,
3792 const SMB_STRUCT_STAT *psbuf)
3794 uint32 file_flags = 0;
3795 uint32 flags_mask = 0;
3797 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3799 /* Create (birth) time 64 bit */
3800 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3803 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3804 SIVAL(pdata, 0, file_flags); /* flags */
3805 SIVAL(pdata, 4, flags_mask); /* mask */
3811 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3812 const struct stream_struct *streams,
3814 unsigned int max_data_bytes,
3815 unsigned int *data_size)
3818 unsigned int ofs = 0;
3820 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3821 unsigned int next_offset;
3823 smb_ucs2_t *namebuf;
3825 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3826 streams[i].name, &namelen) ||
3829 return NT_STATUS_INVALID_PARAMETER;
3833 * name_buf is now null-terminated, we need to marshall as not
3839 SIVAL(data, ofs+4, namelen);
3840 SOFF_T(data, ofs+8, streams[i].size);
3841 SOFF_T(data, ofs+16, streams[i].alloc_size);
3842 memcpy(data+ofs+24, namebuf, namelen);
3843 TALLOC_FREE(namebuf);
3845 next_offset = ofs + 24 + namelen;
3847 if (i == num_streams-1) {
3848 SIVAL(data, ofs, 0);
3851 unsigned int align = ndr_align_size(next_offset, 8);
3853 memset(data+next_offset, 0, align);
3854 next_offset += align;
3856 SIVAL(data, ofs, next_offset - ofs);
3865 return NT_STATUS_OK;
3868 /****************************************************************************
3869 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3870 ****************************************************************************/
3872 static void call_trans2qpipeinfo(connection_struct *conn,
3873 struct smb_request *req,
3874 unsigned int tran_call,
3875 char **pparams, int total_params,
3876 char **ppdata, int total_data,
3877 unsigned int max_data_bytes)
3879 char *params = *pparams;
3880 char *pdata = *ppdata;
3881 unsigned int data_size = 0;
3882 unsigned int param_size = 2;
3887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3891 if (total_params < 4) {
3892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3896 fsp = file_fsp(req, SVAL(params,0));
3897 if (!fsp_is_np(fsp)) {
3898 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3902 info_level = SVAL(params,2);
3904 *pparams = (char *)SMB_REALLOC(*pparams,2);
3905 if (*pparams == NULL) {
3906 reply_nterror(req, NT_STATUS_NO_MEMORY);
3911 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3912 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3913 if (*ppdata == NULL ) {
3914 reply_nterror(req, NT_STATUS_NO_MEMORY);
3919 switch (info_level) {
3920 case SMB_FILE_STANDARD_INFORMATION:
3922 SOFF_T(pdata,0,4096LL);
3929 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3933 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3939 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3940 TALLOC_CTX *mem_ctx,
3941 uint16_t info_level,
3943 const struct smb_filename *smb_fname,
3944 bool delete_pending,
3945 struct timespec write_time_ts,
3947 struct ea_list *ea_list,
3948 int lock_data_count,
3951 unsigned int max_data_bytes,
3953 unsigned int *pdata_size)
3955 char *pdata = *ppdata;
3956 char *dstart, *dend;
3957 unsigned int data_size;
3958 struct timespec create_time_ts, mtime_ts, atime_ts;
3959 time_t create_time, mtime, atime;
3960 SMB_STRUCT_STAT sbuf;
3967 uint64_t file_size = 0;
3969 uint64_t allocation_size = 0;
3970 uint64_t file_index = 0;
3971 uint32_t access_mask = 0;
3973 sbuf = smb_fname->st;
3975 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3976 return NT_STATUS_INVALID_LEVEL;
3979 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
3980 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
3981 info_level, max_data_bytes));
3984 mode = dos_mode_msdfs(conn, smb_fname);
3986 mode = dos_mode(conn, smb_fname);
3989 mode = FILE_ATTRIBUTE_NORMAL;
3991 nlink = sbuf.st_ex_nlink;
3993 if (nlink && (mode&aDIR)) {
3997 if ((nlink > 0) && delete_pending) {
4001 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4002 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4003 if (*ppdata == NULL) {
4004 return NT_STATUS_NO_MEMORY;
4008 dend = dstart + data_size - 1;
4010 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4011 update_stat_ex_mtime(&sbuf, write_time_ts);
4014 create_time_ts = sbuf.st_ex_btime;
4015 mtime_ts = sbuf.st_ex_mtime;
4016 atime_ts = sbuf.st_ex_atime;
4018 if (lp_dos_filetime_resolution(SNUM(conn))) {
4019 dos_filetime_timespec(&create_time_ts);
4020 dos_filetime_timespec(&mtime_ts);
4021 dos_filetime_timespec(&atime_ts);
4024 create_time = convert_timespec_to_time_t(create_time_ts);
4025 mtime = convert_timespec_to_time_t(mtime_ts);
4026 atime = convert_timespec_to_time_t(atime_ts);
4028 p = strrchr_m(smb_fname->base_name,'/');
4030 base_name = smb_fname->base_name;
4034 /* NT expects the name to be in an exact form of the *full*
4035 filename. See the trans2 torture test */
4036 if (ISDOT(base_name)) {
4037 dos_fname = talloc_strdup(mem_ctx, "\\");
4039 return NT_STATUS_NO_MEMORY;
4042 dos_fname = talloc_asprintf(mem_ctx,
4044 smb_fname->base_name);
4046 return NT_STATUS_NO_MEMORY;
4048 if (is_ntfs_stream_smb_fname(smb_fname)) {
4049 dos_fname = talloc_asprintf(dos_fname, "%s",
4050 smb_fname->stream_name);
4052 return NT_STATUS_NO_MEMORY;
4056 string_replace(dos_fname, '/', '\\');
4059 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4062 /* Do we have this path open ? */
4064 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4065 fsp1 = file_find_di_first(fileid);
4066 if (fsp1 && fsp1->initial_allocation_size) {
4067 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4071 if (!(mode & aDIR)) {
4072 file_size = get_file_size_stat(&sbuf);
4076 pos = fsp->fh->position_information;
4080 access_mask = fsp->access_mask;
4082 /* GENERIC_EXECUTE mapping from Windows */
4083 access_mask = 0x12019F;
4086 /* This should be an index number - looks like
4089 I think this causes us to fail the IFSKIT
4090 BasicFileInformationTest. -tpot */
4091 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4092 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4094 switch (info_level) {
4095 case SMB_INFO_STANDARD:
4096 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4098 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4099 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4100 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4101 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4102 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4103 SSVAL(pdata,l1_attrFile,mode);
4106 case SMB_INFO_QUERY_EA_SIZE:
4108 unsigned int ea_size =
4109 estimate_ea_size(conn, fsp,
4110 smb_fname->base_name);
4111 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4113 srv_put_dos_date2(pdata,0,create_time);
4114 srv_put_dos_date2(pdata,4,atime);
4115 srv_put_dos_date2(pdata,8,mtime); /* write time */
4116 SIVAL(pdata,12,(uint32)file_size);
4117 SIVAL(pdata,16,(uint32)allocation_size);
4118 SSVAL(pdata,20,mode);
4119 SIVAL(pdata,22,ea_size);
4123 case SMB_INFO_IS_NAME_VALID:
4124 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4126 /* os/2 needs this ? really ?*/
4127 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4129 /* This is only reached for qpathinfo */
4133 case SMB_INFO_QUERY_EAS_FROM_LIST:
4135 size_t total_ea_len = 0;
4136 struct ea_list *ea_file_list = NULL;
4138 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4141 get_ea_list_from_file(mem_ctx, conn, fsp,
4142 smb_fname->base_name,
4144 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4146 if (!ea_list || (total_ea_len > data_size)) {
4148 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4152 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4156 case SMB_INFO_QUERY_ALL_EAS:
4158 /* We have data_size bytes to put EA's into. */
4159 size_t total_ea_len = 0;
4161 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4163 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4164 smb_fname->base_name,
4166 if (!ea_list || (total_ea_len > data_size)) {
4168 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4172 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4176 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4178 /* We have data_size bytes to put EA's into. */
4179 size_t total_ea_len = 0;
4180 struct ea_list *ea_file_list = NULL;
4182 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4184 /*TODO: add filtering and index handling */
4187 get_ea_list_from_file(mem_ctx, conn, fsp,
4188 smb_fname->base_name,
4190 if (!ea_file_list) {
4191 return NT_STATUS_NO_EAS_ON_FILE;
4194 status = fill_ea_chained_buffer(mem_ctx,
4198 conn, ea_file_list);
4199 if (!NT_STATUS_IS_OK(status)) {
4205 case SMB_FILE_BASIC_INFORMATION:
4206 case SMB_QUERY_FILE_BASIC_INFO:
4208 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4209 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4210 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4212 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4216 put_long_date_timespec(pdata,create_time_ts);
4217 put_long_date_timespec(pdata+8,atime_ts);
4218 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4219 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4220 SIVAL(pdata,32,mode);
4222 DEBUG(5,("SMB_QFBI - "));
4223 DEBUG(5,("create: %s ", ctime(&create_time)));
4224 DEBUG(5,("access: %s ", ctime(&atime)));
4225 DEBUG(5,("write: %s ", ctime(&mtime)));
4226 DEBUG(5,("change: %s ", ctime(&mtime)));
4227 DEBUG(5,("mode: %x\n", mode));
4230 case SMB_FILE_STANDARD_INFORMATION:
4231 case SMB_QUERY_FILE_STANDARD_INFO:
4233 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4235 SOFF_T(pdata,0,allocation_size);
4236 SOFF_T(pdata,8,file_size);
4237 SIVAL(pdata,16,nlink);
4238 SCVAL(pdata,20,delete_pending?1:0);
4239 SCVAL(pdata,21,(mode&aDIR)?1:0);
4240 SSVAL(pdata,22,0); /* Padding. */
4243 case SMB_FILE_EA_INFORMATION:
4244 case SMB_QUERY_FILE_EA_INFO:
4246 unsigned int ea_size =
4247 estimate_ea_size(conn, fsp, smb_fname->base_name);
4248 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4250 SIVAL(pdata,0,ea_size);
4254 /* Get the 8.3 name - used if NT SMB was negotiated. */
4255 case SMB_QUERY_FILE_ALT_NAME_INFO:
4256 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4259 char mangled_name[13];
4260 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4261 if (!name_to_8_3(base_name,mangled_name,
4262 True,conn->params)) {
4263 return NT_STATUS_NO_MEMORY;
4265 len = srvstr_push(dstart, flags2,
4266 pdata+4, mangled_name,
4267 PTR_DIFF(dend, pdata+4),
4269 data_size = 4 + len;
4274 case SMB_QUERY_FILE_NAME_INFO:
4278 this must be *exactly* right for ACLs on mapped drives to work
4280 len = srvstr_push(dstart, flags2,
4282 PTR_DIFF(dend, pdata+4),
4284 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4285 data_size = 4 + len;
4290 case SMB_FILE_ALLOCATION_INFORMATION:
4291 case SMB_QUERY_FILE_ALLOCATION_INFO:
4292 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4294 SOFF_T(pdata,0,allocation_size);
4297 case SMB_FILE_END_OF_FILE_INFORMATION:
4298 case SMB_QUERY_FILE_END_OF_FILEINFO:
4299 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4301 SOFF_T(pdata,0,file_size);
4304 case SMB_QUERY_FILE_ALL_INFO:
4305 case SMB_FILE_ALL_INFORMATION:
4308 unsigned int ea_size =
4309 estimate_ea_size(conn, fsp, smb_fname->base_name);
4310 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4311 put_long_date_timespec(pdata,create_time_ts);
4312 put_long_date_timespec(pdata+8,atime_ts);
4313 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4314 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4315 SIVAL(pdata,32,mode);
4316 SIVAL(pdata,36,0); /* padding. */
4318 SOFF_T(pdata,0,allocation_size);
4319 SOFF_T(pdata,8,file_size);
4320 SIVAL(pdata,16,nlink);
4321 SCVAL(pdata,20,delete_pending);
4322 SCVAL(pdata,21,(mode&aDIR)?1:0);
4325 SIVAL(pdata,0,ea_size);
4326 pdata += 4; /* EA info */
4327 len = srvstr_push(dstart, flags2,
4329 PTR_DIFF(dend, pdata+4),
4333 data_size = PTR_DIFF(pdata,(*ppdata));
4337 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4340 unsigned int ea_size =
4341 estimate_ea_size(conn, fsp, smb_fname->base_name);
4342 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4343 put_long_date_timespec(pdata+0x00,create_time_ts);
4344 put_long_date_timespec(pdata+0x08,atime_ts);
4345 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4346 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4347 SIVAL(pdata, 0x20, mode);
4348 SIVAL(pdata, 0x24, 0); /* padding. */
4349 SBVAL(pdata, 0x28, allocation_size);
4350 SBVAL(pdata, 0x30, file_size);
4351 SIVAL(pdata, 0x38, nlink);
4352 SCVAL(pdata, 0x3C, delete_pending);
4353 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4354 SSVAL(pdata, 0x3E, 0); /* padding */
4355 SBVAL(pdata, 0x40, file_index);
4356 SIVAL(pdata, 0x48, ea_size);
4357 SIVAL(pdata, 0x4C, access_mask);
4358 SBVAL(pdata, 0x50, pos);
4359 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4360 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4364 len = srvstr_push(dstart, flags2,
4366 PTR_DIFF(dend, pdata+4),
4370 data_size = PTR_DIFF(pdata,(*ppdata));
4373 case SMB_FILE_INTERNAL_INFORMATION:
4375 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4376 SBVAL(pdata, 0, file_index);
4380 case SMB_FILE_ACCESS_INFORMATION:
4381 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4382 SIVAL(pdata, 0, access_mask);
4386 case SMB_FILE_NAME_INFORMATION:
4387 /* Pathname with leading '\'. */
4390 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4391 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4392 SIVAL(pdata,0,byte_len);
4393 data_size = 4 + byte_len;
4397 case SMB_FILE_DISPOSITION_INFORMATION:
4398 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4400 SCVAL(pdata,0,delete_pending);
4403 case SMB_FILE_POSITION_INFORMATION:
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4406 SOFF_T(pdata,0,pos);
4409 case SMB_FILE_MODE_INFORMATION:
4410 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4411 SIVAL(pdata,0,mode);
4415 case SMB_FILE_ALIGNMENT_INFORMATION:
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4417 SIVAL(pdata,0,0); /* No alignment needed. */
4422 * NT4 server just returns "invalid query" to this - if we try
4423 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4426 /* The first statement above is false - verified using Thursby
4427 * client against NT4 -- gcolley.
4429 case SMB_QUERY_FILE_STREAM_INFO:
4430 case SMB_FILE_STREAM_INFORMATION: {
4431 unsigned int num_streams;
4432 struct stream_struct *streams;
4434 DEBUG(10,("smbd_do_qfilepathinfo: "
4435 "SMB_FILE_STREAM_INFORMATION\n"));
4437 if (is_ntfs_stream_smb_fname(smb_fname)) {
4438 return NT_STATUS_INVALID_PARAMETER;
4441 status = SMB_VFS_STREAMINFO(
4442 conn, fsp, smb_fname->base_name, talloc_tos(),
4443 &num_streams, &streams);
4445 if (!NT_STATUS_IS_OK(status)) {
4446 DEBUG(10, ("could not get stream info: %s\n",
4447 nt_errstr(status)));
4451 status = marshall_stream_info(num_streams, streams,
4452 pdata, max_data_bytes,
4455 if (!NT_STATUS_IS_OK(status)) {
4456 DEBUG(10, ("marshall_stream_info failed: %s\n",
4457 nt_errstr(status)));
4461 TALLOC_FREE(streams);
4465 case SMB_QUERY_COMPRESSION_INFO:
4466 case SMB_FILE_COMPRESSION_INFORMATION:
4467 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4468 SOFF_T(pdata,0,file_size);
4469 SIVAL(pdata,8,0); /* ??? */
4470 SIVAL(pdata,12,0); /* ??? */
4474 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4475 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4476 put_long_date_timespec(pdata,create_time_ts);
4477 put_long_date_timespec(pdata+8,atime_ts);
4478 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4479 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4480 SOFF_T(pdata,32,allocation_size);
4481 SOFF_T(pdata,40,file_size);
4482 SIVAL(pdata,48,mode);
4483 SIVAL(pdata,52,0); /* ??? */
4487 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4488 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4489 SIVAL(pdata,0,mode);
4495 * CIFS UNIX Extensions.
4498 case SMB_QUERY_FILE_UNIX_BASIC:
4500 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4501 data_size = PTR_DIFF(pdata,(*ppdata));
4505 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4507 for (i=0; i<100; i++)
4508 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4514 case SMB_QUERY_FILE_UNIX_INFO2:
4516 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4517 data_size = PTR_DIFF(pdata,(*ppdata));
4521 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4523 for (i=0; i<100; i++)
4524 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4530 case SMB_QUERY_FILE_UNIX_LINK:
4533 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4536 return NT_STATUS_NO_MEMORY;
4539 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4541 if(!S_ISLNK(sbuf.st_ex_mode)) {
4542 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4545 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4547 len = SMB_VFS_READLINK(conn,
4548 smb_fname->base_name,
4551 return map_nt_error_from_unix(errno);
4554 len = srvstr_push(dstart, flags2,
4556 PTR_DIFF(dend, pdata),
4559 data_size = PTR_DIFF(pdata,(*ppdata));
4564 #if defined(HAVE_POSIX_ACLS)
4565 case SMB_QUERY_POSIX_ACL:
4567 SMB_ACL_T file_acl = NULL;
4568 SMB_ACL_T def_acl = NULL;
4569 uint16 num_file_acls = 0;
4570 uint16 num_def_acls = 0;
4572 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4573 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4576 SMB_VFS_SYS_ACL_GET_FILE(conn,
4577 smb_fname->base_name,
4578 SMB_ACL_TYPE_ACCESS);
4581 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4582 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4583 "not implemented on "
4584 "filesystem containing %s\n",
4585 smb_fname->base_name));
4586 return NT_STATUS_NOT_IMPLEMENTED;
4589 if (S_ISDIR(sbuf.st_ex_mode)) {
4590 if (fsp && fsp->is_directory) {
4592 SMB_VFS_SYS_ACL_GET_FILE(
4594 fsp->fsp_name->base_name,
4595 SMB_ACL_TYPE_DEFAULT);
4598 SMB_VFS_SYS_ACL_GET_FILE(
4600 smb_fname->base_name,
4601 SMB_ACL_TYPE_DEFAULT);
4603 def_acl = free_empty_sys_acl(conn, def_acl);
4606 num_file_acls = count_acl_entries(conn, file_acl);
4607 num_def_acls = count_acl_entries(conn, def_acl);
4609 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4610 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4612 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4613 SMB_POSIX_ACL_HEADER_SIZE) ));
4615 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4618 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4620 return NT_STATUS_BUFFER_TOO_SMALL;
4623 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4624 SSVAL(pdata,2,num_file_acls);
4625 SSVAL(pdata,4,num_def_acls);
4626 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4628 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4631 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4633 return NT_STATUS_INTERNAL_ERROR;
4635 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4637 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4640 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4642 return NT_STATUS_INTERNAL_ERROR;
4646 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4649 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4651 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4657 case SMB_QUERY_POSIX_LOCK:
4662 enum brl_type lock_type;
4664 /* We need an open file with a real fd for this. */
4665 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4666 return NT_STATUS_INVALID_LEVEL;
4669 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4670 return NT_STATUS_INVALID_PARAMETER;
4673 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4674 case POSIX_LOCK_TYPE_READ:
4675 lock_type = READ_LOCK;
4677 case POSIX_LOCK_TYPE_WRITE:
4678 lock_type = WRITE_LOCK;
4680 case POSIX_LOCK_TYPE_UNLOCK:
4682 /* There's no point in asking for an unlock... */
4683 return NT_STATUS_INVALID_PARAMETER;
4686 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4687 #if defined(HAVE_LONGLONG)
4688 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4689 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4690 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4691 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4692 #else /* HAVE_LONGLONG */
4693 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4694 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4695 #endif /* HAVE_LONGLONG */
4697 status = query_lock(fsp,
4704 if (ERROR_WAS_LOCK_DENIED(status)) {
4705 /* Here we need to report who has it locked... */
4706 data_size = POSIX_LOCK_DATA_SIZE;
4708 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4709 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4710 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4711 #if defined(HAVE_LONGLONG)
4712 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4713 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4714 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4715 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4716 #else /* HAVE_LONGLONG */
4717 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4718 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4719 #endif /* HAVE_LONGLONG */
4721 } else if (NT_STATUS_IS_OK(status)) {
4722 /* For success we just return a copy of what we sent
4723 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4724 data_size = POSIX_LOCK_DATA_SIZE;
4725 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4726 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4734 return NT_STATUS_INVALID_LEVEL;
4737 *pdata_size = data_size;
4738 return NT_STATUS_OK;
4741 /****************************************************************************
4742 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4743 file name or file id).
4744 ****************************************************************************/
4746 static void call_trans2qfilepathinfo(connection_struct *conn,
4747 struct smb_request *req,
4748 unsigned int tran_call,
4749 char **pparams, int total_params,
4750 char **ppdata, int total_data,
4751 unsigned int max_data_bytes)
4753 char *params = *pparams;
4754 char *pdata = *ppdata;
4756 unsigned int data_size = 0;
4757 unsigned int param_size = 2;
4758 struct smb_filename *smb_fname = NULL;
4759 bool delete_pending = False;
4760 struct timespec write_time_ts;
4761 files_struct *fsp = NULL;
4762 struct file_id fileid;
4763 struct ea_list *ea_list = NULL;
4764 int lock_data_count = 0;
4765 char *lock_data = NULL;
4766 bool ms_dfs_link = false;
4767 NTSTATUS status = NT_STATUS_OK;
4770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4774 ZERO_STRUCT(write_time_ts);
4776 if (tran_call == TRANSACT2_QFILEINFO) {
4777 if (total_params < 4) {
4778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4783 call_trans2qpipeinfo(conn, req, tran_call,
4784 pparams, total_params,
4790 fsp = file_fsp(req, SVAL(params,0));
4791 info_level = SVAL(params,2);
4793 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4795 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4796 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4800 /* Initial check for valid fsp ptr. */
4801 if (!check_fsp_open(conn, req, fsp)) {
4805 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4807 if (!NT_STATUS_IS_OK(status)) {
4808 reply_nterror(req, status);
4812 if(fsp->fake_file_handle) {
4814 * This is actually for the QUOTA_FAKE_FILE --metze
4817 /* We know this name is ok, it's already passed the checks. */
4819 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4821 * This is actually a QFILEINFO on a directory
4822 * handle (returned from an NT SMB). NT5.0 seems
4823 * to do this call. JRA.
4826 if (INFO_LEVEL_IS_UNIX(info_level)) {
4827 /* Always do lstat for UNIX calls. */
4828 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4829 DEBUG(3,("call_trans2qfilepathinfo: "
4830 "SMB_VFS_LSTAT of %s failed "
4832 smb_fname_str_dbg(smb_fname),
4835 map_nt_error_from_unix(errno));
4838 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4839 DEBUG(3,("call_trans2qfilepathinfo: "
4840 "SMB_VFS_STAT of %s failed (%s)\n",
4841 smb_fname_str_dbg(smb_fname),
4844 map_nt_error_from_unix(errno));
4848 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4849 get_file_infos(fileid, &delete_pending, &write_time_ts);
4852 * Original code - this is an open file.
4854 if (!check_fsp(conn, req, fsp)) {
4858 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4859 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4860 fsp->fnum, strerror(errno)));
4862 map_nt_error_from_unix(errno));
4865 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4866 get_file_infos(fileid, &delete_pending, &write_time_ts);
4873 if (total_params < 7) {
4874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4878 info_level = SVAL(params,0);
4880 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4882 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4883 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4887 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
4889 STR_TERMINATE, &status);
4890 if (!NT_STATUS_IS_OK(status)) {
4891 reply_nterror(req, status);
4895 status = filename_convert(req,
4897 req->flags2 & FLAGS2_DFS_PATHNAMES,
4902 if (!NT_STATUS_IS_OK(status)) {
4903 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4904 reply_botherror(req,
4905 NT_STATUS_PATH_NOT_COVERED,
4906 ERRSRV, ERRbadpath);
4909 reply_nterror(req, status);
4913 /* If this is a stream, check if there is a delete_pending. */
4914 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4915 && is_ntfs_stream_smb_fname(smb_fname)) {
4916 struct smb_filename *smb_fname_base = NULL;
4918 /* Create an smb_filename with stream_name == NULL. */
4920 create_synthetic_smb_fname(talloc_tos(),
4921 smb_fname->base_name,
4924 if (!NT_STATUS_IS_OK(status)) {
4925 reply_nterror(req, status);
4929 if (INFO_LEVEL_IS_UNIX(info_level)) {
4930 /* Always do lstat for UNIX calls. */
4931 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4932 DEBUG(3,("call_trans2qfilepathinfo: "
4933 "SMB_VFS_LSTAT of %s failed "
4935 smb_fname_str_dbg(smb_fname_base),
4937 TALLOC_FREE(smb_fname_base);
4939 map_nt_error_from_unix(errno));
4943 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4944 DEBUG(3,("call_trans2qfilepathinfo: "
4945 "fileinfo of %s failed "
4947 smb_fname_str_dbg(smb_fname_base),
4949 TALLOC_FREE(smb_fname_base);
4951 map_nt_error_from_unix(errno));
4956 fileid = vfs_file_id_from_sbuf(conn,
4957 &smb_fname_base->st);
4958 TALLOC_FREE(smb_fname_base);
4959 get_file_infos(fileid, &delete_pending, NULL);
4960 if (delete_pending) {
4961 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4966 if (INFO_LEVEL_IS_UNIX(info_level)) {
4967 /* Always do lstat for UNIX calls. */
4968 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4969 DEBUG(3,("call_trans2qfilepathinfo: "
4970 "SMB_VFS_LSTAT of %s failed (%s)\n",
4971 smb_fname_str_dbg(smb_fname),
4974 map_nt_error_from_unix(errno));
4978 } else if (!VALID_STAT(smb_fname->st) &&
4979 SMB_VFS_STAT(conn, smb_fname) &&
4980 (info_level != SMB_INFO_IS_NAME_VALID)) {
4981 ms_dfs_link = check_msdfs_link(conn,
4982 smb_fname->base_name,
4986 DEBUG(3,("call_trans2qfilepathinfo: "
4987 "SMB_VFS_STAT of %s failed (%s)\n",
4988 smb_fname_str_dbg(smb_fname),
4991 map_nt_error_from_unix(errno));
4996 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4997 get_file_infos(fileid, &delete_pending, &write_time_ts);
4998 if (delete_pending) {
4999 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5004 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5005 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5006 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5008 /* Pull out any data sent here before we realloc. */
5009 switch (info_level) {
5010 case SMB_INFO_QUERY_EAS_FROM_LIST:
5012 /* Pull any EA list from the data portion. */
5015 if (total_data < 4) {
5017 req, NT_STATUS_INVALID_PARAMETER);
5020 ea_size = IVAL(pdata,0);
5022 if (total_data > 0 && ea_size != total_data) {
5023 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5024 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5026 req, NT_STATUS_INVALID_PARAMETER);
5030 if (!lp_ea_support(SNUM(conn))) {
5031 reply_doserror(req, ERRDOS,
5032 ERReasnotsupported);
5036 /* Pull out the list of names. */
5037 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5040 req, NT_STATUS_INVALID_PARAMETER);
5046 case SMB_QUERY_POSIX_LOCK:
5048 if (fsp == NULL || fsp->fh->fd == -1) {
5049 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5053 if (total_data != POSIX_LOCK_DATA_SIZE) {
5055 req, NT_STATUS_INVALID_PARAMETER);
5059 /* Copy the lock range data. */
5060 lock_data = (char *)TALLOC_MEMDUP(
5061 req, pdata, total_data);
5063 reply_nterror(req, NT_STATUS_NO_MEMORY);
5066 lock_data_count = total_data;
5072 *pparams = (char *)SMB_REALLOC(*pparams,2);
5073 if (*pparams == NULL) {
5074 reply_nterror(req, NT_STATUS_NO_MEMORY);
5081 * draft-leach-cifs-v1-spec-02.txt
5082 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5085 * The requested information is placed in the Data portion of the
5086 * transaction response. For the information levels greater than 0x100,
5087 * the transaction response has 1 parameter word which should be
5088 * ignored by the client.
5090 * However Windows only follows this rule for the IS_NAME_VALID call.
5092 switch (info_level) {
5093 case SMB_INFO_IS_NAME_VALID:
5098 if ((info_level & 0xFF00) == 0xFF00) {
5100 * We use levels that start with 0xFF00
5101 * internally to represent SMB2 specific levels
5103 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5107 status = smbd_do_qfilepathinfo(conn, req, info_level,
5109 delete_pending, write_time_ts,
5110 ms_dfs_link, ea_list,
5111 lock_data_count, lock_data,
5112 req->flags2, max_data_bytes,
5113 ppdata, &data_size);
5114 if (!NT_STATUS_IS_OK(status)) {
5115 reply_nterror(req, status);
5119 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5125 /****************************************************************************
5126 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5128 ****************************************************************************/
5130 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5131 connection_struct *conn,
5132 const struct smb_filename *smb_fname_old,
5133 const struct smb_filename *smb_fname_new)
5135 NTSTATUS status = NT_STATUS_OK;
5137 /* source must already exist. */
5138 if (!VALID_STAT(smb_fname_old->st)) {
5139 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5142 /* Disallow if newname already exists. */
5143 if (VALID_STAT(smb_fname_new->st)) {
5144 return NT_STATUS_OBJECT_NAME_COLLISION;
5147 /* No links from a directory. */
5148 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5149 return NT_STATUS_FILE_IS_A_DIRECTORY;
5152 /* Setting a hardlink to/from a stream isn't currently supported. */
5153 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5154 is_ntfs_stream_smb_fname(smb_fname_new)) {
5155 return NT_STATUS_INVALID_PARAMETER;
5158 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5159 smb_fname_old->base_name, smb_fname_new->base_name));
5161 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5162 smb_fname_new->base_name) != 0) {
5163 status = map_nt_error_from_unix(errno);
5164 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5165 nt_errstr(status), smb_fname_old->base_name,
5166 smb_fname_new->base_name));
5171 /****************************************************************************
5172 Deal with setting the time from any of the setfilepathinfo functions.
5173 ****************************************************************************/
5175 NTSTATUS smb_set_file_time(connection_struct *conn,
5177 const struct smb_filename *smb_fname,
5178 struct smb_file_time *ft,
5179 bool setting_write_time)
5181 struct smb_filename *smb_fname_base = NULL;
5183 FILE_NOTIFY_CHANGE_LAST_ACCESS
5184 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5185 bool set_createtime = false;
5186 bool set_ctime = false;
5189 if (!VALID_STAT(smb_fname->st)) {
5190 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5193 /* get some defaults (no modifications) if any info is zero or -1. */
5194 if (null_timespec(ft->create_time)) {
5195 ft->create_time = smb_fname->st.st_ex_btime;
5197 set_createtime = true;
5200 if (null_timespec(ft->ctime)) {
5201 ft->ctime = smb_fname->st.st_ex_ctime;
5206 if (null_timespec(ft->atime)) {
5207 ft->atime= smb_fname->st.st_ex_atime;
5208 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5211 if (null_timespec(ft->mtime)) {
5212 ft->mtime = smb_fname->st.st_ex_mtime;
5213 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5216 if (!setting_write_time) {
5217 /* ft->mtime comes from change time, not write time. */
5218 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5221 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5222 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5223 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5224 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5225 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5226 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5227 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5228 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5231 * Try and set the times of this file if
5232 * they are different from the current values.
5236 struct timespec mts = smb_fname->st.st_ex_mtime;
5237 struct timespec ats = smb_fname->st.st_ex_atime;
5238 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5239 (timespec_compare(&ft->mtime, &mts) == 0)) {
5240 if (set_createtime || set_ctime) {
5241 notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_LAST_WRITE,
5242 smb_fname->base_name);
5244 return NT_STATUS_OK;
5248 if (setting_write_time) {
5250 * This was a Windows setfileinfo on an open file.
5251 * NT does this a lot. We also need to
5252 * set the time here, as it can be read by
5253 * FindFirst/FindNext and with the patch for bug #2045
5254 * in smbd/fileio.c it ensures that this timestamp is
5255 * kept sticky even after a write. We save the request
5256 * away and will set it on file close and after a write. JRA.
5259 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5260 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5263 if (fsp->base_fsp) {
5264 set_sticky_write_time_fsp(fsp->base_fsp,
5267 set_sticky_write_time_fsp(fsp, ft->mtime);
5270 set_sticky_write_time_path(
5271 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5276 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5278 /* Always call ntimes on the base, even if a stream was passed in. */
5279 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5280 NULL, &smb_fname->st,
5282 if (!NT_STATUS_IS_OK(status)) {
5286 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5287 TALLOC_FREE(smb_fname_base);
5288 return map_nt_error_from_unix(errno);
5290 TALLOC_FREE(smb_fname_base);
5292 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5293 smb_fname->base_name);
5294 return NT_STATUS_OK;
5297 /****************************************************************************
5298 Deal with setting the dosmode from any of the setfilepathinfo functions.
5299 ****************************************************************************/
5301 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5302 const struct smb_filename *smb_fname,
5305 struct smb_filename *smb_fname_base = NULL;
5308 if (!VALID_STAT(smb_fname->st)) {
5309 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5312 /* Always operate on the base_name, even if a stream was passed in. */
5313 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5314 NULL, &smb_fname->st,
5316 if (!NT_STATUS_IS_OK(status)) {
5321 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5328 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5330 /* check the mode isn't different, before changing it */
5331 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5332 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5333 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5334 (unsigned int)dosmode));
5336 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5338 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5340 smb_fname_str_dbg(smb_fname_base),
5342 status = map_nt_error_from_unix(errno);
5346 status = NT_STATUS_OK;
5348 TALLOC_FREE(smb_fname_base);
5352 /****************************************************************************
5353 Deal with setting the size from any of the setfilepathinfo functions.
5354 ****************************************************************************/
5356 static NTSTATUS smb_set_file_size(connection_struct *conn,
5357 struct smb_request *req,
5359 const struct smb_filename *smb_fname,
5360 const SMB_STRUCT_STAT *psbuf,
5363 NTSTATUS status = NT_STATUS_OK;
5364 struct smb_filename *smb_fname_tmp = NULL;
5365 files_struct *new_fsp = NULL;
5367 if (!VALID_STAT(*psbuf)) {
5368 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5371 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5373 if (size == get_file_size_stat(psbuf)) {
5374 return NT_STATUS_OK;
5377 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5378 smb_fname_str_dbg(smb_fname), (double)size));
5380 if (fsp && fsp->fh->fd != -1) {
5381 /* Handle based call. */
5382 if (vfs_set_filelen(fsp, size) == -1) {
5383 return map_nt_error_from_unix(errno);
5385 trigger_write_time_update_immediate(fsp);
5386 return NT_STATUS_OK;
5389 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5390 if (!NT_STATUS_IS_OK(status)) {
5394 smb_fname_tmp->st = *psbuf;
5396 status = SMB_VFS_CREATE_FILE(
5399 0, /* root_dir_fid */
5400 smb_fname_tmp, /* fname */
5401 FILE_WRITE_ATTRIBUTES, /* access_mask */
5402 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5404 FILE_OPEN, /* create_disposition*/
5405 0, /* create_options */
5406 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5407 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5408 0, /* allocation_size */
5411 &new_fsp, /* result */
5414 TALLOC_FREE(smb_fname_tmp);
5416 if (!NT_STATUS_IS_OK(status)) {
5417 /* NB. We check for open_was_deferred in the caller. */
5421 if (vfs_set_filelen(new_fsp, size) == -1) {
5422 status = map_nt_error_from_unix(errno);
5423 close_file(req, new_fsp,NORMAL_CLOSE);
5427 trigger_write_time_update_immediate(new_fsp);
5428 close_file(req, new_fsp,NORMAL_CLOSE);
5429 return NT_STATUS_OK;
5432 /****************************************************************************
5433 Deal with SMB_INFO_SET_EA.
5434 ****************************************************************************/
5436 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5440 const struct smb_filename *smb_fname)
5442 struct ea_list *ea_list = NULL;
5443 TALLOC_CTX *ctx = NULL;
5444 NTSTATUS status = NT_STATUS_OK;
5446 if (total_data < 10) {
5448 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5449 length. They seem to have no effect. Bug #3212. JRA */
5451 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5452 /* We're done. We only get EA info in this call. */
5453 return NT_STATUS_OK;
5456 return NT_STATUS_INVALID_PARAMETER;
5459 if (IVAL(pdata,0) > total_data) {
5460 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5461 IVAL(pdata,0), (unsigned int)total_data));
5462 return NT_STATUS_INVALID_PARAMETER;
5466 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5468 return NT_STATUS_INVALID_PARAMETER;
5470 status = set_ea(conn, fsp, smb_fname, ea_list);
5475 /****************************************************************************
5476 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5477 ****************************************************************************/
5479 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5483 const struct smb_filename *smb_fname)
5485 NTSTATUS status = NT_STATUS_OK;
5486 bool delete_on_close;
5489 if (total_data < 1) {
5490 return NT_STATUS_INVALID_PARAMETER;
5494 return NT_STATUS_INVALID_HANDLE;
5497 delete_on_close = (CVAL(pdata,0) ? True : False);
5498 dosmode = dos_mode(conn, smb_fname);
5500 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5501 "delete_on_close = %u\n",
5502 smb_fname_str_dbg(smb_fname),
5503 (unsigned int)dosmode,
5504 (unsigned int)delete_on_close ));
5506 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5508 if (!NT_STATUS_IS_OK(status)) {
5512 /* The set is across all open files on this dev/inode pair. */
5513 if (!set_delete_on_close(fsp, delete_on_close,
5514 &conn->server_info->utok)) {
5515 return NT_STATUS_ACCESS_DENIED;
5517 return NT_STATUS_OK;
5520 /****************************************************************************
5521 Deal with SMB_FILE_POSITION_INFORMATION.
5522 ****************************************************************************/
5524 static NTSTATUS smb_file_position_information(connection_struct *conn,
5529 uint64_t position_information;
5531 if (total_data < 8) {
5532 return NT_STATUS_INVALID_PARAMETER;
5536 /* Ignore on pathname based set. */
5537 return NT_STATUS_OK;
5540 position_information = (uint64_t)IVAL(pdata,0);
5541 #ifdef LARGE_SMB_OFF_T
5542 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5543 #else /* LARGE_SMB_OFF_T */
5544 if (IVAL(pdata,4) != 0) {
5545 /* more than 32 bits? */
5546 return NT_STATUS_INVALID_PARAMETER;
5548 #endif /* LARGE_SMB_OFF_T */
5550 DEBUG(10,("smb_file_position_information: Set file position "
5551 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5552 (double)position_information));
5553 fsp->fh->position_information = position_information;
5554 return NT_STATUS_OK;
5557 /****************************************************************************
5558 Deal with SMB_FILE_MODE_INFORMATION.
5559 ****************************************************************************/
5561 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5567 if (total_data < 4) {
5568 return NT_STATUS_INVALID_PARAMETER;
5570 mode = IVAL(pdata,0);
5571 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5572 return NT_STATUS_INVALID_PARAMETER;
5574 return NT_STATUS_OK;
5577 /****************************************************************************
5578 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5579 ****************************************************************************/
5581 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5582 struct smb_request *req,
5585 const struct smb_filename *smb_fname)
5587 char *link_target = NULL;
5588 const char *newname = smb_fname->base_name;
5589 NTSTATUS status = NT_STATUS_OK;
5590 TALLOC_CTX *ctx = talloc_tos();
5592 /* Set a symbolic link. */
5593 /* Don't allow this if follow links is false. */
5595 if (total_data == 0) {
5596 return NT_STATUS_INVALID_PARAMETER;
5599 if (!lp_symlinks(SNUM(conn))) {
5600 return NT_STATUS_ACCESS_DENIED;
5603 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5604 total_data, STR_TERMINATE);
5607 return NT_STATUS_INVALID_PARAMETER;
5610 /* !widelinks forces the target path to be within the share. */
5611 /* This means we can interpret the target as a pathname. */
5612 if (!lp_widelinks(SNUM(conn))) {
5613 char *rel_name = NULL;
5614 char *last_dirp = NULL;
5616 if (*link_target == '/') {
5617 /* No absolute paths allowed. */
5618 return NT_STATUS_ACCESS_DENIED;
5620 rel_name = talloc_strdup(ctx,newname);
5622 return NT_STATUS_NO_MEMORY;
5624 last_dirp = strrchr_m(rel_name, '/');
5626 last_dirp[1] = '\0';
5628 rel_name = talloc_strdup(ctx,"./");
5630 return NT_STATUS_NO_MEMORY;
5633 rel_name = talloc_asprintf_append(rel_name,
5637 return NT_STATUS_NO_MEMORY;
5640 status = check_name(conn, rel_name);
5641 if (!NT_STATUS_IS_OK(status)) {
5646 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5647 newname, link_target ));
5649 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5650 return map_nt_error_from_unix(errno);
5653 return NT_STATUS_OK;
5656 /****************************************************************************
5657 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5658 ****************************************************************************/
5660 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5661 struct smb_request *req,
5662 const char *pdata, int total_data,
5663 const struct smb_filename *smb_fname_new)
5665 char *oldname = NULL;
5666 struct smb_filename *smb_fname_old = NULL;
5667 TALLOC_CTX *ctx = talloc_tos();
5668 NTSTATUS status = NT_STATUS_OK;
5670 /* Set a hard link. */
5671 if (total_data == 0) {
5672 return NT_STATUS_INVALID_PARAMETER;
5675 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5676 total_data, STR_TERMINATE, &status);
5677 if (!NT_STATUS_IS_OK(status)) {
5681 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5682 smb_fname_str_dbg(smb_fname_new), oldname));
5684 status = filename_convert(ctx,
5686 req->flags2 & FLAGS2_DFS_PATHNAMES,
5691 if (!NT_STATUS_IS_OK(status)) {
5695 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5698 /****************************************************************************
5699 Deal with SMB_FILE_RENAME_INFORMATION.
5700 ****************************************************************************/
5702 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5703 struct smb_request *req,
5707 struct smb_filename *smb_fname_src)
5712 char *newname = NULL;
5713 struct smb_filename *smb_fname_dst = NULL;
5714 bool dest_has_wcard = False;
5715 NTSTATUS status = NT_STATUS_OK;
5717 TALLOC_CTX *ctx = talloc_tos();
5719 if (total_data < 13) {
5720 return NT_STATUS_INVALID_PARAMETER;
5723 overwrite = (CVAL(pdata,0) ? True : False);
5724 root_fid = IVAL(pdata,4);
5725 len = IVAL(pdata,8);
5727 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5728 return NT_STATUS_INVALID_PARAMETER;
5731 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5734 if (!NT_STATUS_IS_OK(status)) {
5738 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5741 status = resolve_dfspath_wcard(ctx, conn,
5742 req->flags2 & FLAGS2_DFS_PATHNAMES,
5746 if (!NT_STATUS_IS_OK(status)) {
5750 /* Check the new name has no '/' characters. */
5751 if (strchr_m(newname, '/')) {
5752 return NT_STATUS_NOT_SUPPORTED;
5755 if (fsp && fsp->base_fsp) {
5756 /* newname must be a stream name. */
5757 if (newname[0] != ':') {
5758 return NT_STATUS_NOT_SUPPORTED;
5761 /* Create an smb_fname to call rename_internals_fsp() with. */
5762 status = create_synthetic_smb_fname(talloc_tos(),
5763 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5765 if (!NT_STATUS_IS_OK(status)) {
5770 * Set the original last component, since
5771 * rename_internals_fsp() requires it.
5773 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5775 if (smb_fname_dst->original_lcomp == NULL) {
5776 status = NT_STATUS_NO_MEMORY;
5782 * Build up an smb_fname_dst based on the filename passed in.
5783 * We basically just strip off the last component, and put on
5784 * the newname instead.
5786 char *base_name = NULL;
5788 /* newname must *not* be a stream name. */
5789 if (newname[0] == ':') {
5790 return NT_STATUS_NOT_SUPPORTED;
5794 * Strip off the last component (filename) of the path passed
5797 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5799 return NT_STATUS_NO_MEMORY;
5801 p = strrchr_m(base_name, '/');
5805 base_name = talloc_strdup(ctx, "./");
5807 return NT_STATUS_NO_MEMORY;
5810 /* Append the new name. */
5811 base_name = talloc_asprintf_append(base_name,
5815 return NT_STATUS_NO_MEMORY;
5818 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5821 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
5824 /* If an error we expect this to be
5825 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5827 if (!NT_STATUS_IS_OK(status)) {
5828 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5832 /* Create an smb_fname to call rename_internals_fsp() */
5833 status = create_synthetic_smb_fname(ctx,
5837 if (!NT_STATUS_IS_OK(status)) {
5844 DEBUG(10,("smb_file_rename_information: "
5845 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5846 fsp->fnum, fsp_str_dbg(fsp),
5847 smb_fname_str_dbg(smb_fname_dst)));
5848 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5851 DEBUG(10,("smb_file_rename_information: "
5852 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5853 smb_fname_str_dbg(smb_fname_src),
5854 smb_fname_str_dbg(smb_fname_dst)));
5855 status = rename_internals(ctx, conn, req, smb_fname_src,
5856 smb_fname_dst, 0, overwrite, false,
5858 FILE_WRITE_ATTRIBUTES);
5861 TALLOC_FREE(smb_fname_dst);
5865 /****************************************************************************
5866 Deal with SMB_SET_POSIX_ACL.
5867 ****************************************************************************/
5869 #if defined(HAVE_POSIX_ACLS)
5870 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5874 const struct smb_filename *smb_fname)
5876 uint16 posix_acl_version;
5877 uint16 num_file_acls;
5878 uint16 num_def_acls;
5879 bool valid_file_acls = True;
5880 bool valid_def_acls = True;
5882 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5883 return NT_STATUS_INVALID_PARAMETER;
5885 posix_acl_version = SVAL(pdata,0);
5886 num_file_acls = SVAL(pdata,2);
5887 num_def_acls = SVAL(pdata,4);
5889 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5890 valid_file_acls = False;
5894 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5895 valid_def_acls = False;
5899 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5900 return NT_STATUS_INVALID_PARAMETER;
5903 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5904 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5905 return NT_STATUS_INVALID_PARAMETER;
5908 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5909 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5910 (unsigned int)num_file_acls,
5911 (unsigned int)num_def_acls));
5913 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5914 smb_fname->base_name, num_file_acls,
5915 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5916 return map_nt_error_from_unix(errno);
5919 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5920 smb_fname->base_name, &smb_fname->st, num_def_acls,
5921 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5922 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5923 return map_nt_error_from_unix(errno);
5925 return NT_STATUS_OK;
5929 /****************************************************************************
5930 Deal with SMB_SET_POSIX_LOCK.
5931 ****************************************************************************/
5933 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5934 struct smb_request *req,
5942 bool blocking_lock = False;
5943 enum brl_type lock_type;
5945 NTSTATUS status = NT_STATUS_OK;
5947 if (fsp == NULL || fsp->fh->fd == -1) {
5948 return NT_STATUS_INVALID_HANDLE;
5951 if (total_data != POSIX_LOCK_DATA_SIZE) {
5952 return NT_STATUS_INVALID_PARAMETER;
5955 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5956 case POSIX_LOCK_TYPE_READ:
5957 lock_type = READ_LOCK;
5959 case POSIX_LOCK_TYPE_WRITE:
5960 /* Return the right POSIX-mappable error code for files opened read-only. */
5961 if (!fsp->can_write) {
5962 return NT_STATUS_INVALID_HANDLE;
5964 lock_type = WRITE_LOCK;
5966 case POSIX_LOCK_TYPE_UNLOCK:
5967 lock_type = UNLOCK_LOCK;
5970 return NT_STATUS_INVALID_PARAMETER;
5973 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5974 blocking_lock = False;
5975 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5976 blocking_lock = True;
5978 return NT_STATUS_INVALID_PARAMETER;
5981 if (!lp_blocking_locks(SNUM(conn))) {
5982 blocking_lock = False;
5985 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5986 #if defined(HAVE_LONGLONG)
5987 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5988 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5989 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5990 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5991 #else /* HAVE_LONGLONG */
5992 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5993 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5994 #endif /* HAVE_LONGLONG */
5996 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5997 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5999 (unsigned int)lock_type,
6000 (unsigned int)lock_pid,
6004 if (lock_type == UNLOCK_LOCK) {
6005 status = do_unlock(smbd_messaging_context(),
6012 uint32 block_smbpid;
6014 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6026 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6028 * A blocking lock was requested. Package up
6029 * this smb into a queued request and push it
6030 * onto the blocking lock queue.
6032 if(push_blocking_lock_request(br_lck,
6035 -1, /* infinite timeout. */
6043 TALLOC_FREE(br_lck);
6047 TALLOC_FREE(br_lck);
6053 /****************************************************************************
6054 Deal with SMB_SET_FILE_BASIC_INFO.
6055 ****************************************************************************/
6057 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6061 const struct smb_filename *smb_fname)
6063 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6064 struct smb_file_time ft;
6066 NTSTATUS status = NT_STATUS_OK;
6070 if (total_data < 36) {
6071 return NT_STATUS_INVALID_PARAMETER;
6074 /* Set the attributes */
6075 dosmode = IVAL(pdata,32);
6076 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6077 if (!NT_STATUS_IS_OK(status)) {
6082 ft.create_time = interpret_long_date(pdata);
6085 ft.atime = interpret_long_date(pdata+8);
6088 ft.mtime = interpret_long_date(pdata+16);
6091 ft.ctime = interpret_long_date(pdata+24);
6093 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6094 smb_fname_str_dbg(smb_fname)));
6096 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6100 /****************************************************************************
6101 Deal with SMB_INFO_STANDARD.
6102 ****************************************************************************/
6104 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6108 const struct smb_filename *smb_fname)
6110 struct smb_file_time ft;
6114 if (total_data < 12) {
6115 return NT_STATUS_INVALID_PARAMETER;
6119 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6121 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6123 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6125 DEBUG(10,("smb_set_info_standard: file %s\n",
6126 smb_fname_str_dbg(smb_fname)));
6128 return smb_set_file_time(conn,
6135 /****************************************************************************
6136 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6137 ****************************************************************************/
6139 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6140 struct smb_request *req,
6144 struct smb_filename *smb_fname)
6146 uint64_t allocation_size = 0;
6147 NTSTATUS status = NT_STATUS_OK;
6148 files_struct *new_fsp = NULL;
6150 if (!VALID_STAT(smb_fname->st)) {
6151 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6154 if (total_data < 8) {
6155 return NT_STATUS_INVALID_PARAMETER;
6158 allocation_size = (uint64_t)IVAL(pdata,0);
6159 #ifdef LARGE_SMB_OFF_T
6160 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6161 #else /* LARGE_SMB_OFF_T */
6162 if (IVAL(pdata,4) != 0) {
6163 /* more than 32 bits? */
6164 return NT_STATUS_INVALID_PARAMETER;
6166 #endif /* LARGE_SMB_OFF_T */
6168 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6169 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6170 (double)allocation_size));
6172 if (allocation_size) {
6173 allocation_size = smb_roundup(conn, allocation_size);
6176 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6177 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6178 (double)allocation_size));
6180 if (fsp && fsp->fh->fd != -1) {
6181 /* Open file handle. */
6182 /* Only change if needed. */
6183 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6184 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6185 return map_nt_error_from_unix(errno);
6188 /* But always update the time. */
6190 * This is equivalent to a write. Ensure it's seen immediately
6191 * if there are no pending writes.
6193 trigger_write_time_update_immediate(fsp);
6194 return NT_STATUS_OK;
6197 /* Pathname or stat or directory file. */
6198 status = SMB_VFS_CREATE_FILE(
6201 0, /* root_dir_fid */
6202 smb_fname, /* fname */
6203 FILE_WRITE_DATA, /* access_mask */
6204 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6206 FILE_OPEN, /* create_disposition*/
6207 0, /* create_options */
6208 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6209 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6210 0, /* allocation_size */
6213 &new_fsp, /* result */
6216 if (!NT_STATUS_IS_OK(status)) {
6217 /* NB. We check for open_was_deferred in the caller. */
6221 /* Only change if needed. */
6222 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6223 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6224 status = map_nt_error_from_unix(errno);
6225 close_file(req, new_fsp, NORMAL_CLOSE);
6230 /* Changing the allocation size should set the last mod time. */
6232 * This is equivalent to a write. Ensure it's seen immediately
6233 * if there are no pending writes.
6235 trigger_write_time_update_immediate(new_fsp);
6237 close_file(req, new_fsp, NORMAL_CLOSE);
6238 return NT_STATUS_OK;
6241 /****************************************************************************
6242 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6243 ****************************************************************************/
6245 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6246 struct smb_request *req,
6250 const struct smb_filename *smb_fname)
6254 if (total_data < 8) {
6255 return NT_STATUS_INVALID_PARAMETER;
6258 size = IVAL(pdata,0);
6259 #ifdef LARGE_SMB_OFF_T
6260 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6261 #else /* LARGE_SMB_OFF_T */
6262 if (IVAL(pdata,4) != 0) {
6263 /* more than 32 bits? */
6264 return NT_STATUS_INVALID_PARAMETER;
6266 #endif /* LARGE_SMB_OFF_T */
6267 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6268 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6271 return smb_set_file_size(conn, req,
6278 /****************************************************************************
6279 Allow a UNIX info mknod.
6280 ****************************************************************************/
6282 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6285 const struct smb_filename *smb_fname)
6287 uint32 file_type = IVAL(pdata,56);
6288 #if defined(HAVE_MAKEDEV)
6289 uint32 dev_major = IVAL(pdata,60);
6290 uint32 dev_minor = IVAL(pdata,68);
6292 SMB_DEV_T dev = (SMB_DEV_T)0;
6293 uint32 raw_unixmode = IVAL(pdata,84);
6297 if (total_data < 100) {
6298 return NT_STATUS_INVALID_PARAMETER;
6301 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6302 PERM_NEW_FILE, &unixmode);
6303 if (!NT_STATUS_IS_OK(status)) {
6307 #if defined(HAVE_MAKEDEV)
6308 dev = makedev(dev_major, dev_minor);
6311 switch (file_type) {
6312 #if defined(S_IFIFO)
6313 case UNIX_TYPE_FIFO:
6314 unixmode |= S_IFIFO;
6317 #if defined(S_IFSOCK)
6318 case UNIX_TYPE_SOCKET:
6319 unixmode |= S_IFSOCK;
6322 #if defined(S_IFCHR)
6323 case UNIX_TYPE_CHARDEV:
6324 unixmode |= S_IFCHR;
6327 #if defined(S_IFBLK)
6328 case UNIX_TYPE_BLKDEV:
6329 unixmode |= S_IFBLK;
6333 return NT_STATUS_INVALID_PARAMETER;
6336 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6337 "%.0f mode 0%o for file %s\n", (double)dev,
6338 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6340 /* Ok - do the mknod. */
6341 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6342 return map_nt_error_from_unix(errno);
6345 /* If any of the other "set" calls fail we
6346 * don't want to end up with a half-constructed mknod.
6349 if (lp_inherit_perms(SNUM(conn))) {
6351 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6353 return NT_STATUS_NO_MEMORY;
6355 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6357 TALLOC_FREE(parent);
6360 return NT_STATUS_OK;
6363 /****************************************************************************
6364 Deal with SMB_SET_FILE_UNIX_BASIC.
6365 ****************************************************************************/
6367 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6368 struct smb_request *req,
6372 const struct smb_filename *smb_fname)
6374 struct smb_file_time ft;
6375 uint32 raw_unixmode;
6378 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6379 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6380 NTSTATUS status = NT_STATUS_OK;
6381 bool delete_on_fail = False;
6382 enum perm_type ptype;
6383 files_struct *all_fsps = NULL;
6384 bool modify_mtime = true;
6386 SMB_STRUCT_STAT sbuf;
6390 if (total_data < 100) {
6391 return NT_STATUS_INVALID_PARAMETER;
6394 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6395 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6396 size=IVAL(pdata,0); /* first 8 Bytes are size */
6397 #ifdef LARGE_SMB_OFF_T
6398 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6399 #else /* LARGE_SMB_OFF_T */
6400 if (IVAL(pdata,4) != 0) {
6401 /* more than 32 bits? */
6402 return NT_STATUS_INVALID_PARAMETER;
6404 #endif /* LARGE_SMB_OFF_T */
6407 ft.atime = interpret_long_date(pdata+24); /* access_time */
6408 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6409 set_owner = (uid_t)IVAL(pdata,40);
6410 set_grp = (gid_t)IVAL(pdata,48);
6411 raw_unixmode = IVAL(pdata,84);
6413 if (VALID_STAT(smb_fname->st)) {
6414 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6415 ptype = PERM_EXISTING_DIR;
6417 ptype = PERM_EXISTING_FILE;
6420 ptype = PERM_NEW_FILE;
6423 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6425 if (!NT_STATUS_IS_OK(status)) {
6429 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6430 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6431 smb_fname_str_dbg(smb_fname), (double)size,
6432 (unsigned int)set_owner, (unsigned int)set_grp,
6433 (int)raw_unixmode));
6435 sbuf = smb_fname->st;
6437 if (!VALID_STAT(sbuf)) {
6438 struct smb_filename *smb_fname_tmp = NULL;
6440 * The only valid use of this is to create character and block
6441 * devices, and named pipes. This is deprecated (IMHO) and
6442 * a new info level should be used for mknod. JRA.
6445 status = smb_unix_mknod(conn,
6449 if (!NT_STATUS_IS_OK(status)) {
6453 status = copy_smb_filename(talloc_tos(), smb_fname,
6455 if (!NT_STATUS_IS_OK(status)) {
6459 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6460 status = map_nt_error_from_unix(errno);
6461 TALLOC_FREE(smb_fname_tmp);
6462 SMB_VFS_UNLINK(conn, smb_fname);
6466 sbuf = smb_fname_tmp->st;
6467 TALLOC_FREE(smb_fname_tmp);
6469 /* Ensure we don't try and change anything else. */
6470 raw_unixmode = SMB_MODE_NO_CHANGE;
6471 size = get_file_size_stat(&sbuf);
6472 ft.atime = sbuf.st_ex_atime;
6473 ft.mtime = sbuf.st_ex_mtime;
6475 * We continue here as we might want to change the
6478 delete_on_fail = True;
6482 /* Horrible backwards compatibility hack as an old server bug
6483 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6487 size = get_file_size_stat(&sbuf);
6492 * Deal with the UNIX specific mode set.
6495 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6496 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6497 "setting mode 0%o for file %s\n",
6498 (unsigned int)unixmode,
6499 smb_fname_str_dbg(smb_fname)));
6500 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6501 return map_nt_error_from_unix(errno);
6506 * Deal with the UNIX specific uid set.
6509 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6510 (sbuf.st_ex_uid != set_owner)) {
6513 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6514 "changing owner %u for path %s\n",
6515 (unsigned int)set_owner,
6516 smb_fname_str_dbg(smb_fname)));
6518 if (S_ISLNK(sbuf.st_ex_mode)) {
6519 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6520 set_owner, (gid_t)-1);
6522 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6523 set_owner, (gid_t)-1);
6527 status = map_nt_error_from_unix(errno);
6528 if (delete_on_fail) {
6529 SMB_VFS_UNLINK(conn, smb_fname);
6536 * Deal with the UNIX specific gid set.
6539 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6540 (sbuf.st_ex_gid != set_grp)) {
6541 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6542 "changing group %u for file %s\n",
6543 (unsigned int)set_owner,
6544 smb_fname_str_dbg(smb_fname)));
6545 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6547 status = map_nt_error_from_unix(errno);
6548 if (delete_on_fail) {
6549 SMB_VFS_UNLINK(conn, smb_fname);
6555 /* Deal with any size changes. */
6557 status = smb_set_file_size(conn, req,
6562 if (!NT_STATUS_IS_OK(status)) {
6566 /* Deal with any time changes. */
6567 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6568 /* No change, don't cancel anything. */
6572 id = vfs_file_id_from_sbuf(conn, &sbuf);
6573 for(all_fsps = file_find_di_first(id); all_fsps;
6574 all_fsps = file_find_di_next(all_fsps)) {
6576 * We're setting the time explicitly for UNIX.
6577 * Cancel any pending changes over all handles.
6579 all_fsps->update_write_time_on_close = false;
6580 TALLOC_FREE(all_fsps->update_write_time_event);
6584 * Override the "setting_write_time"
6585 * parameter here as it almost does what
6586 * we need. Just remember if we modified
6587 * mtime and send the notify ourselves.
6589 if (null_timespec(ft.mtime)) {
6590 modify_mtime = false;
6593 status = smb_set_file_time(conn,
6599 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6600 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6605 /****************************************************************************
6606 Deal with SMB_SET_FILE_UNIX_INFO2.
6607 ****************************************************************************/
6609 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6610 struct smb_request *req,
6614 const struct smb_filename *smb_fname)
6620 if (total_data < 116) {
6621 return NT_STATUS_INVALID_PARAMETER;
6624 /* Start by setting all the fields that are common between UNIX_BASIC
6627 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6629 if (!NT_STATUS_IS_OK(status)) {
6633 smb_fflags = IVAL(pdata, 108);
6634 smb_fmask = IVAL(pdata, 112);
6636 /* NB: We should only attempt to alter the file flags if the client
6637 * sends a non-zero mask.
6639 if (smb_fmask != 0) {
6640 int stat_fflags = 0;
6642 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6643 smb_fmask, &stat_fflags)) {
6644 /* Client asked to alter a flag we don't understand. */
6645 return NT_STATUS_INVALID_PARAMETER;
6648 if (fsp && fsp->fh->fd != -1) {
6649 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6650 return NT_STATUS_NOT_SUPPORTED;
6652 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6653 stat_fflags) != 0) {
6654 return map_nt_error_from_unix(errno);
6659 /* XXX: need to add support for changing the create_time here. You
6660 * can do this for paths on Darwin with setattrlist(2). The right way
6661 * to hook this up is probably by extending the VFS utimes interface.
6664 return NT_STATUS_OK;
6667 /****************************************************************************
6668 Create a directory with POSIX semantics.
6669 ****************************************************************************/
6671 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6672 struct smb_request *req,
6675 struct smb_filename *smb_fname,
6676 int *pdata_return_size)
6678 NTSTATUS status = NT_STATUS_OK;
6679 uint32 raw_unixmode = 0;
6680 uint32 mod_unixmode = 0;
6681 mode_t unixmode = (mode_t)0;
6682 files_struct *fsp = NULL;
6683 uint16 info_level_return = 0;
6685 char *pdata = *ppdata;
6687 if (total_data < 18) {
6688 return NT_STATUS_INVALID_PARAMETER;
6691 raw_unixmode = IVAL(pdata,8);
6692 /* Next 4 bytes are not yet defined. */
6694 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6695 PERM_NEW_DIR, &unixmode);
6696 if (!NT_STATUS_IS_OK(status)) {
6700 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6702 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6703 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6705 status = SMB_VFS_CREATE_FILE(
6708 0, /* root_dir_fid */
6709 smb_fname, /* fname */
6710 FILE_READ_ATTRIBUTES, /* access_mask */
6711 FILE_SHARE_NONE, /* share_access */
6712 FILE_CREATE, /* create_disposition*/
6713 FILE_DIRECTORY_FILE, /* create_options */
6714 mod_unixmode, /* file_attributes */
6715 0, /* oplock_request */
6716 0, /* allocation_size */
6722 if (NT_STATUS_IS_OK(status)) {
6723 close_file(req, fsp, NORMAL_CLOSE);
6726 info_level_return = SVAL(pdata,16);
6728 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6729 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6730 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6731 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6733 *pdata_return_size = 12;
6736 /* Realloc the data size */
6737 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6738 if (*ppdata == NULL) {
6739 *pdata_return_size = 0;
6740 return NT_STATUS_NO_MEMORY;
6744 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6745 SSVAL(pdata,2,0); /* No fnum. */
6746 SIVAL(pdata,4,info); /* Was directory created. */
6748 switch (info_level_return) {
6749 case SMB_QUERY_FILE_UNIX_BASIC:
6750 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6751 SSVAL(pdata,10,0); /* Padding. */
6752 store_file_unix_basic(conn, pdata + 12, fsp,
6755 case SMB_QUERY_FILE_UNIX_INFO2:
6756 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6757 SSVAL(pdata,10,0); /* Padding. */
6758 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6762 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6763 SSVAL(pdata,10,0); /* Padding. */
6770 /****************************************************************************
6771 Open/Create a file with POSIX semantics.
6772 ****************************************************************************/
6774 static NTSTATUS smb_posix_open(connection_struct *conn,
6775 struct smb_request *req,
6778 struct smb_filename *smb_fname,
6779 int *pdata_return_size)
6781 bool extended_oplock_granted = False;
6782 char *pdata = *ppdata;
6784 uint32 wire_open_mode = 0;
6785 uint32 raw_unixmode = 0;
6786 uint32 mod_unixmode = 0;
6787 uint32 create_disp = 0;
6788 uint32 access_mask = 0;
6789 uint32 create_options = 0;
6790 NTSTATUS status = NT_STATUS_OK;
6791 mode_t unixmode = (mode_t)0;
6792 files_struct *fsp = NULL;
6793 int oplock_request = 0;
6795 uint16 info_level_return = 0;
6797 if (total_data < 18) {
6798 return NT_STATUS_INVALID_PARAMETER;
6801 flags = IVAL(pdata,0);
6802 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6803 if (oplock_request) {
6804 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6807 wire_open_mode = IVAL(pdata,4);
6809 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6810 return smb_posix_mkdir(conn, req,
6817 switch (wire_open_mode & SMB_ACCMODE) {
6819 access_mask = FILE_READ_DATA;
6822 access_mask = FILE_WRITE_DATA;
6825 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6828 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6829 (unsigned int)wire_open_mode ));
6830 return NT_STATUS_INVALID_PARAMETER;
6833 wire_open_mode &= ~SMB_ACCMODE;
6835 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6836 create_disp = FILE_CREATE;
6837 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6838 create_disp = FILE_OVERWRITE_IF;
6839 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6840 create_disp = FILE_OPEN_IF;
6841 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6842 create_disp = FILE_OPEN;
6844 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6845 (unsigned int)wire_open_mode ));
6846 return NT_STATUS_INVALID_PARAMETER;
6849 raw_unixmode = IVAL(pdata,8);
6850 /* Next 4 bytes are not yet defined. */
6852 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6853 (VALID_STAT(smb_fname->st) ?
6854 PERM_EXISTING_FILE : PERM_NEW_FILE),
6857 if (!NT_STATUS_IS_OK(status)) {
6861 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6863 if (wire_open_mode & SMB_O_SYNC) {
6864 create_options |= FILE_WRITE_THROUGH;
6866 if (wire_open_mode & SMB_O_APPEND) {
6867 access_mask |= FILE_APPEND_DATA;
6869 if (wire_open_mode & SMB_O_DIRECT) {
6870 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6873 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6874 smb_fname_str_dbg(smb_fname),
6875 (unsigned int)wire_open_mode,
6876 (unsigned int)unixmode ));
6878 status = SMB_VFS_CREATE_FILE(
6881 0, /* root_dir_fid */
6882 smb_fname, /* fname */
6883 access_mask, /* access_mask */
6884 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6886 create_disp, /* create_disposition*/
6887 FILE_NON_DIRECTORY_FILE, /* create_options */
6888 mod_unixmode, /* file_attributes */
6889 oplock_request, /* oplock_request */
6890 0, /* allocation_size */
6896 if (!NT_STATUS_IS_OK(status)) {
6900 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6901 extended_oplock_granted = True;
6904 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6905 extended_oplock_granted = True;
6908 info_level_return = SVAL(pdata,16);
6910 /* Allocate the correct return size. */
6912 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6913 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6914 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6915 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6917 *pdata_return_size = 12;
6920 /* Realloc the data size */
6921 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6922 if (*ppdata == NULL) {
6923 close_file(req, fsp, ERROR_CLOSE);
6924 *pdata_return_size = 0;
6925 return NT_STATUS_NO_MEMORY;
6929 if (extended_oplock_granted) {
6930 if (flags & REQUEST_BATCH_OPLOCK) {
6931 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6933 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6935 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6936 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6938 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6941 SSVAL(pdata,2,fsp->fnum);
6942 SIVAL(pdata,4,info); /* Was file created etc. */
6944 switch (info_level_return) {
6945 case SMB_QUERY_FILE_UNIX_BASIC:
6946 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6947 SSVAL(pdata,10,0); /* padding. */
6948 store_file_unix_basic(conn, pdata + 12, fsp,
6951 case SMB_QUERY_FILE_UNIX_INFO2:
6952 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6953 SSVAL(pdata,10,0); /* padding. */
6954 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6958 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6959 SSVAL(pdata,10,0); /* padding. */
6962 return NT_STATUS_OK;
6965 /****************************************************************************
6966 Delete a file with POSIX semantics.
6967 ****************************************************************************/
6969 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6970 struct smb_request *req,
6973 struct smb_filename *smb_fname)
6975 NTSTATUS status = NT_STATUS_OK;
6976 files_struct *fsp = NULL;
6980 int create_options = 0;
6982 struct share_mode_lock *lck = NULL;
6984 if (total_data < 2) {
6985 return NT_STATUS_INVALID_PARAMETER;
6988 flags = SVAL(pdata,0);
6990 if (!VALID_STAT(smb_fname->st)) {
6991 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6994 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6995 !VALID_STAT_OF_DIR(smb_fname->st)) {
6996 return NT_STATUS_NOT_A_DIRECTORY;
6999 DEBUG(10,("smb_posix_unlink: %s %s\n",
7000 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7001 smb_fname_str_dbg(smb_fname)));
7003 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7004 create_options |= FILE_DIRECTORY_FILE;
7007 status = SMB_VFS_CREATE_FILE(
7010 0, /* root_dir_fid */
7011 smb_fname, /* fname */
7012 DELETE_ACCESS, /* access_mask */
7013 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7015 FILE_OPEN, /* create_disposition*/
7016 create_options, /* create_options */
7017 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7018 0, /* oplock_request */
7019 0, /* allocation_size */
7025 if (!NT_STATUS_IS_OK(status)) {
7030 * Don't lie to client. If we can't really delete due to
7031 * non-POSIX opens return SHARING_VIOLATION.
7034 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7037 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7038 "lock for file %s\n", fsp_str_dbg(fsp)));
7039 close_file(req, fsp, NORMAL_CLOSE);
7040 return NT_STATUS_INVALID_PARAMETER;
7044 * See if others still have the file open. If this is the case, then
7045 * don't delete. If all opens are POSIX delete we can set the delete
7046 * on close disposition.
7048 for (i=0; i<lck->num_share_modes; i++) {
7049 struct share_mode_entry *e = &lck->share_modes[i];
7050 if (is_valid_share_mode_entry(e)) {
7051 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7054 /* Fail with sharing violation. */
7055 close_file(req, fsp, NORMAL_CLOSE);
7057 return NT_STATUS_SHARING_VIOLATION;
7062 * Set the delete on close.
7064 status = smb_set_file_disposition_info(conn,
7070 if (!NT_STATUS_IS_OK(status)) {
7071 close_file(req, fsp, NORMAL_CLOSE);
7076 return close_file(req, fsp, NORMAL_CLOSE);
7079 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7080 struct smb_request *req,
7081 TALLOC_CTX *mem_ctx,
7082 uint16_t info_level,
7084 struct smb_filename *smb_fname,
7085 char **ppdata, int total_data,
7088 char *pdata = *ppdata;
7089 NTSTATUS status = NT_STATUS_OK;
7090 int data_return_size = 0;
7094 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7095 return NT_STATUS_INVALID_LEVEL;
7098 if (!CAN_WRITE(conn)) {
7099 /* Allow POSIX opens. The open path will deny
7100 * any non-readonly opens. */
7101 if (info_level != SMB_POSIX_PATH_OPEN) {
7102 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7106 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7107 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7108 fsp ? fsp->fnum : -1, info_level, total_data));
7110 switch (info_level) {
7112 case SMB_INFO_STANDARD:
7114 status = smb_set_info_standard(conn,
7122 case SMB_INFO_SET_EA:
7124 status = smb_info_set_ea(conn,
7132 case SMB_SET_FILE_BASIC_INFO:
7133 case SMB_FILE_BASIC_INFORMATION:
7135 status = smb_set_file_basic_info(conn,
7143 case SMB_FILE_ALLOCATION_INFORMATION:
7144 case SMB_SET_FILE_ALLOCATION_INFO:
7146 status = smb_set_file_allocation_info(conn, req,
7154 case SMB_FILE_END_OF_FILE_INFORMATION:
7155 case SMB_SET_FILE_END_OF_FILE_INFO:
7157 status = smb_set_file_end_of_file_info(conn, req,
7165 case SMB_FILE_DISPOSITION_INFORMATION:
7166 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7169 /* JRA - We used to just ignore this on a path ?
7170 * Shouldn't this be invalid level on a pathname
7173 if (tran_call != TRANSACT2_SETFILEINFO) {
7174 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7177 status = smb_set_file_disposition_info(conn,
7185 case SMB_FILE_POSITION_INFORMATION:
7187 status = smb_file_position_information(conn,
7194 /* From tridge Samba4 :
7195 * MODE_INFORMATION in setfileinfo (I have no
7196 * idea what "mode information" on a file is - it takes a value of 0,
7197 * 2, 4 or 6. What could it be?).
7200 case SMB_FILE_MODE_INFORMATION:
7202 status = smb_file_mode_information(conn,
7209 * CIFS UNIX extensions.
7212 case SMB_SET_FILE_UNIX_BASIC:
7214 status = smb_set_file_unix_basic(conn, req,
7222 case SMB_SET_FILE_UNIX_INFO2:
7224 status = smb_set_file_unix_info2(conn, req,
7232 case SMB_SET_FILE_UNIX_LINK:
7235 /* We must have a pathname for this. */
7236 return NT_STATUS_INVALID_LEVEL;
7238 status = smb_set_file_unix_link(conn, req, pdata,
7239 total_data, smb_fname);
7243 case SMB_SET_FILE_UNIX_HLINK:
7246 /* We must have a pathname for this. */
7247 return NT_STATUS_INVALID_LEVEL;
7249 status = smb_set_file_unix_hlink(conn, req,
7255 case SMB_FILE_RENAME_INFORMATION:
7257 status = smb_file_rename_information(conn, req,
7263 #if defined(HAVE_POSIX_ACLS)
7264 case SMB_SET_POSIX_ACL:
7266 status = smb_set_posix_acl(conn,
7275 case SMB_SET_POSIX_LOCK:
7278 return NT_STATUS_INVALID_LEVEL;
7280 status = smb_set_posix_lock(conn, req,
7281 pdata, total_data, fsp);
7285 case SMB_POSIX_PATH_OPEN:
7288 /* We must have a pathname for this. */
7289 return NT_STATUS_INVALID_LEVEL;
7292 status = smb_posix_open(conn, req,
7300 case SMB_POSIX_PATH_UNLINK:
7303 /* We must have a pathname for this. */
7304 return NT_STATUS_INVALID_LEVEL;
7307 status = smb_posix_unlink(conn, req,
7315 return NT_STATUS_INVALID_LEVEL;
7318 if (!NT_STATUS_IS_OK(status)) {
7322 *ret_data_size = data_return_size;
7323 return NT_STATUS_OK;
7326 /****************************************************************************
7327 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7328 ****************************************************************************/
7330 static void call_trans2setfilepathinfo(connection_struct *conn,
7331 struct smb_request *req,
7332 unsigned int tran_call,
7333 char **pparams, int total_params,
7334 char **ppdata, int total_data,
7335 unsigned int max_data_bytes)
7337 char *params = *pparams;
7338 char *pdata = *ppdata;
7340 struct smb_filename *smb_fname = NULL;
7341 files_struct *fsp = NULL;
7342 NTSTATUS status = NT_STATUS_OK;
7343 int data_return_size = 0;
7346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7350 if (tran_call == TRANSACT2_SETFILEINFO) {
7351 if (total_params < 4) {
7352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7356 fsp = file_fsp(req, SVAL(params,0));
7357 /* Basic check for non-null fsp. */
7358 if (!check_fsp_open(conn, req, fsp)) {
7361 info_level = SVAL(params,2);
7363 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7365 if (!NT_STATUS_IS_OK(status)) {
7366 reply_nterror(req, status);
7370 if(fsp->is_directory || fsp->fh->fd == -1) {
7372 * This is actually a SETFILEINFO on a directory
7373 * handle (returned from an NT SMB). NT5.0 seems
7374 * to do this call. JRA.
7376 if (INFO_LEVEL_IS_UNIX(info_level)) {
7377 /* Always do lstat for UNIX calls. */
7378 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7379 DEBUG(3,("call_trans2setfilepathinfo: "
7380 "SMB_VFS_LSTAT of %s failed "
7382 smb_fname_str_dbg(smb_fname),
7384 reply_nterror(req, map_nt_error_from_unix(errno));
7388 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7389 DEBUG(3,("call_trans2setfilepathinfo: "
7390 "fileinfo of %s failed (%s)\n",
7391 smb_fname_str_dbg(smb_fname),
7393 reply_nterror(req, map_nt_error_from_unix(errno));
7397 } else if (fsp->print_file) {
7399 * Doing a DELETE_ON_CLOSE should cancel a print job.
7401 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7402 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7404 DEBUG(3,("call_trans2setfilepathinfo: "
7405 "Cancelling print job (%s)\n",
7409 send_trans2_replies(conn, req, params, 2,
7414 reply_doserror(req, ERRDOS, ERRbadpath);
7419 * Original code - this is an open file.
7421 if (!check_fsp(conn, req, fsp)) {
7425 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7426 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7427 "of fnum %d failed (%s)\n", fsp->fnum,
7429 reply_nterror(req, map_nt_error_from_unix(errno));
7437 if (total_params < 7) {
7438 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7442 info_level = SVAL(params,0);
7443 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7444 total_params - 6, STR_TERMINATE,
7446 if (!NT_STATUS_IS_OK(status)) {
7447 reply_nterror(req, status);
7451 status = filename_convert(req, conn,
7452 req->flags2 & FLAGS2_DFS_PATHNAMES,
7457 if (!NT_STATUS_IS_OK(status)) {
7458 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7459 reply_botherror(req,
7460 NT_STATUS_PATH_NOT_COVERED,
7461 ERRSRV, ERRbadpath);
7464 reply_nterror(req, status);
7468 if (INFO_LEVEL_IS_UNIX(info_level)) {
7470 * For CIFS UNIX extensions the target name may not exist.
7473 /* Always do lstat for UNIX calls. */
7474 SMB_VFS_LSTAT(conn, smb_fname);
7476 } else if (!VALID_STAT(smb_fname->st) &&
7477 SMB_VFS_STAT(conn, smb_fname)) {
7478 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7480 smb_fname_str_dbg(smb_fname),
7482 reply_nterror(req, map_nt_error_from_unix(errno));
7487 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7488 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7489 fsp ? fsp->fnum : -1, info_level,total_data));
7491 /* Realloc the parameter size */
7492 *pparams = (char *)SMB_REALLOC(*pparams,2);
7493 if (*pparams == NULL) {
7494 reply_nterror(req, NT_STATUS_NO_MEMORY);
7501 status = smbd_do_setfilepathinfo(conn, req, req,
7507 if (!NT_STATUS_IS_OK(status)) {
7508 if (open_was_deferred(req->mid)) {
7509 /* We have re-scheduled this call. */
7512 if (blocking_lock_was_deferred(req->mid)) {
7513 /* We have re-scheduled this call. */
7516 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7517 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7518 ERRSRV, ERRbadpath);
7521 if (info_level == SMB_POSIX_PATH_OPEN) {
7522 reply_openerror(req, status);
7526 reply_nterror(req, status);
7530 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7536 /****************************************************************************
7537 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7538 ****************************************************************************/
7540 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7541 char **pparams, int total_params,
7542 char **ppdata, int total_data,
7543 unsigned int max_data_bytes)
7545 struct smb_filename *smb_dname = NULL;
7546 char *params = *pparams;
7547 char *pdata = *ppdata;
7548 char *directory = NULL;
7549 NTSTATUS status = NT_STATUS_OK;
7550 struct ea_list *ea_list = NULL;
7551 TALLOC_CTX *ctx = talloc_tos();
7553 if (!CAN_WRITE(conn)) {
7554 reply_doserror(req, ERRSRV, ERRaccess);
7558 if (total_params < 5) {
7559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7563 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7564 total_params - 4, STR_TERMINATE,
7566 if (!NT_STATUS_IS_OK(status)) {
7567 reply_nterror(req, status);
7571 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7573 status = filename_convert(ctx,
7575 req->flags2 & FLAGS2_DFS_PATHNAMES,
7581 if (!NT_STATUS_IS_OK(status)) {
7582 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7583 reply_botherror(req,
7584 NT_STATUS_PATH_NOT_COVERED,
7585 ERRSRV, ERRbadpath);
7588 reply_nterror(req, status);
7592 /* Any data in this call is an EA list. */
7593 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7594 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7599 * OS/2 workplace shell seems to send SET_EA requests of "null"
7600 * length (4 bytes containing IVAL 4).
7601 * They seem to have no effect. Bug #3212. JRA.
7604 if (total_data != 4) {
7605 if (total_data < 10) {
7606 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7610 if (IVAL(pdata,0) > total_data) {
7611 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7612 IVAL(pdata,0), (unsigned int)total_data));
7613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7617 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7624 /* If total_data == 4 Windows doesn't care what values
7625 * are placed in that field, it just ignores them.
7626 * The System i QNTC IBM SMB client puts bad values here,
7627 * so ignore them. */
7629 status = create_directory(conn, req, smb_dname);
7631 if (!NT_STATUS_IS_OK(status)) {
7632 reply_nterror(req, status);
7636 /* Try and set any given EA. */
7638 status = set_ea(conn, NULL, smb_dname, ea_list);
7639 if (!NT_STATUS_IS_OK(status)) {
7640 reply_nterror(req, status);
7645 /* Realloc the parameter and data sizes */
7646 *pparams = (char *)SMB_REALLOC(*pparams,2);
7647 if(*pparams == NULL) {
7648 reply_nterror(req, NT_STATUS_NO_MEMORY);
7655 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7658 TALLOC_FREE(smb_dname);
7662 /****************************************************************************
7663 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7664 We don't actually do this - we just send a null response.
7665 ****************************************************************************/
7667 static void call_trans2findnotifyfirst(connection_struct *conn,
7668 struct smb_request *req,
7669 char **pparams, int total_params,
7670 char **ppdata, int total_data,
7671 unsigned int max_data_bytes)
7673 char *params = *pparams;
7676 if (total_params < 6) {
7677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7681 info_level = SVAL(params,4);
7682 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7684 switch (info_level) {
7689 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7693 /* Realloc the parameter and data sizes */
7694 *pparams = (char *)SMB_REALLOC(*pparams,6);
7695 if (*pparams == NULL) {
7696 reply_nterror(req, NT_STATUS_NO_MEMORY);
7701 SSVAL(params,0,fnf_handle);
7702 SSVAL(params,2,0); /* No changes */
7703 SSVAL(params,4,0); /* No EA errors */
7710 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7715 /****************************************************************************
7716 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7717 changes). Currently this does nothing.
7718 ****************************************************************************/
7720 static void call_trans2findnotifynext(connection_struct *conn,
7721 struct smb_request *req,
7722 char **pparams, int total_params,
7723 char **ppdata, int total_data,
7724 unsigned int max_data_bytes)
7726 char *params = *pparams;
7728 DEBUG(3,("call_trans2findnotifynext\n"));
7730 /* Realloc the parameter and data sizes */
7731 *pparams = (char *)SMB_REALLOC(*pparams,4);
7732 if (*pparams == NULL) {
7733 reply_nterror(req, NT_STATUS_NO_MEMORY);
7738 SSVAL(params,0,0); /* No changes */
7739 SSVAL(params,2,0); /* No EA errors */
7741 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7746 /****************************************************************************
7747 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7748 ****************************************************************************/
7750 static void call_trans2getdfsreferral(connection_struct *conn,
7751 struct smb_request *req,
7752 char **pparams, int total_params,
7753 char **ppdata, int total_data,
7754 unsigned int max_data_bytes)
7756 char *params = *pparams;
7757 char *pathname = NULL;
7759 int max_referral_level;
7760 NTSTATUS status = NT_STATUS_OK;
7761 TALLOC_CTX *ctx = talloc_tos();
7763 DEBUG(10,("call_trans2getdfsreferral\n"));
7765 if (total_params < 3) {
7766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7770 max_referral_level = SVAL(params,0);
7772 if(!lp_host_msdfs()) {
7773 reply_doserror(req, ERRDOS, ERRbadfunc);
7777 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7778 total_params - 2, STR_TERMINATE);
7780 reply_nterror(req, NT_STATUS_NOT_FOUND);
7783 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7784 ppdata,&status)) < 0) {
7785 reply_nterror(req, status);
7789 SSVAL(req->inbuf, smb_flg2,
7790 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7791 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7796 #define LMCAT_SPL 0x53
7797 #define LMFUNC_GETJOBID 0x60
7799 /****************************************************************************
7800 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7801 ****************************************************************************/
7803 static void call_trans2ioctl(connection_struct *conn,
7804 struct smb_request *req,
7805 char **pparams, int total_params,
7806 char **ppdata, int total_data,
7807 unsigned int max_data_bytes)
7809 char *pdata = *ppdata;
7810 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7812 /* check for an invalid fid before proceeding */
7815 reply_doserror(req, ERRDOS, ERRbadfid);
7819 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7820 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7821 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7822 if (*ppdata == NULL) {
7823 reply_nterror(req, NT_STATUS_NO_MEMORY);
7828 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7829 CAN ACCEPT THIS IN UNICODE. JRA. */
7831 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7832 srvstr_push(pdata, req->flags2, pdata + 2,
7833 global_myname(), 15,
7834 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7835 srvstr_push(pdata, req->flags2, pdata+18,
7836 lp_servicename(SNUM(conn)), 13,
7837 STR_ASCII|STR_TERMINATE); /* Service name */
7838 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7843 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7844 reply_doserror(req, ERRSRV, ERRerror);
7847 /****************************************************************************
7848 Reply to a SMBfindclose (stop trans2 directory search).
7849 ****************************************************************************/
7851 void reply_findclose(struct smb_request *req)
7855 START_PROFILE(SMBfindclose);
7858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7859 END_PROFILE(SMBfindclose);
7863 dptr_num = SVALS(req->vwv+0, 0);
7865 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7867 dptr_close(&dptr_num);
7869 reply_outbuf(req, 0, 0);
7871 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7873 END_PROFILE(SMBfindclose);
7877 /****************************************************************************
7878 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7879 ****************************************************************************/
7881 void reply_findnclose(struct smb_request *req)
7885 START_PROFILE(SMBfindnclose);
7888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7889 END_PROFILE(SMBfindnclose);
7893 dptr_num = SVAL(req->vwv+0, 0);
7895 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7897 /* We never give out valid handles for a
7898 findnotifyfirst - so any dptr_num is ok here.
7901 reply_outbuf(req, 0, 0);
7903 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7905 END_PROFILE(SMBfindnclose);
7909 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7910 struct trans_state *state)
7912 if (Protocol >= PROTOCOL_NT1) {
7913 req->flags2 |= 0x40; /* IS_LONG_NAME */
7914 SSVAL(req->inbuf,smb_flg2,req->flags2);
7917 if (conn->encrypt_level == Required && !req->encrypted) {
7918 if (state->call != TRANSACT2_QFSINFO &&
7919 state->call != TRANSACT2_SETFSINFO) {
7920 DEBUG(0,("handle_trans2: encryption required "
7922 (unsigned int)state->call));
7923 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7928 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7930 /* Now we must call the relevant TRANS2 function */
7931 switch(state->call) {
7932 case TRANSACT2_OPEN:
7934 START_PROFILE(Trans2_open);
7935 call_trans2open(conn, req,
7936 &state->param, state->total_param,
7937 &state->data, state->total_data,
7938 state->max_data_return);
7939 END_PROFILE(Trans2_open);
7943 case TRANSACT2_FINDFIRST:
7945 START_PROFILE(Trans2_findfirst);
7946 call_trans2findfirst(conn, req,
7947 &state->param, state->total_param,
7948 &state->data, state->total_data,
7949 state->max_data_return);
7950 END_PROFILE(Trans2_findfirst);
7954 case TRANSACT2_FINDNEXT:
7956 START_PROFILE(Trans2_findnext);
7957 call_trans2findnext(conn, req,
7958 &state->param, state->total_param,
7959 &state->data, state->total_data,
7960 state->max_data_return);
7961 END_PROFILE(Trans2_findnext);
7965 case TRANSACT2_QFSINFO:
7967 START_PROFILE(Trans2_qfsinfo);
7968 call_trans2qfsinfo(conn, req,
7969 &state->param, state->total_param,
7970 &state->data, state->total_data,
7971 state->max_data_return);
7972 END_PROFILE(Trans2_qfsinfo);
7976 case TRANSACT2_SETFSINFO:
7978 START_PROFILE(Trans2_setfsinfo);
7979 call_trans2setfsinfo(conn, req,
7980 &state->param, state->total_param,
7981 &state->data, state->total_data,
7982 state->max_data_return);
7983 END_PROFILE(Trans2_setfsinfo);
7987 case TRANSACT2_QPATHINFO:
7988 case TRANSACT2_QFILEINFO:
7990 START_PROFILE(Trans2_qpathinfo);
7991 call_trans2qfilepathinfo(conn, req, state->call,
7992 &state->param, state->total_param,
7993 &state->data, state->total_data,
7994 state->max_data_return);
7995 END_PROFILE(Trans2_qpathinfo);
7999 case TRANSACT2_SETPATHINFO:
8000 case TRANSACT2_SETFILEINFO:
8002 START_PROFILE(Trans2_setpathinfo);
8003 call_trans2setfilepathinfo(conn, req, state->call,
8004 &state->param, state->total_param,
8005 &state->data, state->total_data,
8006 state->max_data_return);
8007 END_PROFILE(Trans2_setpathinfo);
8011 case TRANSACT2_FINDNOTIFYFIRST:
8013 START_PROFILE(Trans2_findnotifyfirst);
8014 call_trans2findnotifyfirst(conn, req,
8015 &state->param, state->total_param,
8016 &state->data, state->total_data,
8017 state->max_data_return);
8018 END_PROFILE(Trans2_findnotifyfirst);
8022 case TRANSACT2_FINDNOTIFYNEXT:
8024 START_PROFILE(Trans2_findnotifynext);
8025 call_trans2findnotifynext(conn, req,
8026 &state->param, state->total_param,
8027 &state->data, state->total_data,
8028 state->max_data_return);
8029 END_PROFILE(Trans2_findnotifynext);
8033 case TRANSACT2_MKDIR:
8035 START_PROFILE(Trans2_mkdir);
8036 call_trans2mkdir(conn, req,
8037 &state->param, state->total_param,
8038 &state->data, state->total_data,
8039 state->max_data_return);
8040 END_PROFILE(Trans2_mkdir);
8044 case TRANSACT2_GET_DFS_REFERRAL:
8046 START_PROFILE(Trans2_get_dfs_referral);
8047 call_trans2getdfsreferral(conn, req,
8048 &state->param, state->total_param,
8049 &state->data, state->total_data,
8050 state->max_data_return);
8051 END_PROFILE(Trans2_get_dfs_referral);
8055 case TRANSACT2_IOCTL:
8057 START_PROFILE(Trans2_ioctl);
8058 call_trans2ioctl(conn, req,
8059 &state->param, state->total_param,
8060 &state->data, state->total_data,
8061 state->max_data_return);
8062 END_PROFILE(Trans2_ioctl);
8067 /* Error in request */
8068 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8069 reply_doserror(req, ERRSRV,ERRerror);
8073 /****************************************************************************
8074 Reply to a SMBtrans2.
8075 ****************************************************************************/
8077 void reply_trans2(struct smb_request *req)
8079 connection_struct *conn = req->conn;
8084 unsigned int tran_call;
8085 struct trans_state *state;
8088 START_PROFILE(SMBtrans2);
8090 if (req->wct < 14) {
8091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8092 END_PROFILE(SMBtrans2);
8096 dsoff = SVAL(req->vwv+12, 0);
8097 dscnt = SVAL(req->vwv+11, 0);
8098 psoff = SVAL(req->vwv+10, 0);
8099 pscnt = SVAL(req->vwv+9, 0);
8100 tran_call = SVAL(req->vwv+14, 0);
8102 result = allow_new_trans(conn->pending_trans, req->mid);
8103 if (!NT_STATUS_IS_OK(result)) {
8104 DEBUG(2, ("Got invalid trans2 request: %s\n",
8105 nt_errstr(result)));
8106 reply_nterror(req, result);
8107 END_PROFILE(SMBtrans2);
8112 switch (tran_call) {
8113 /* List the allowed trans2 calls on IPC$ */
8114 case TRANSACT2_OPEN:
8115 case TRANSACT2_GET_DFS_REFERRAL:
8116 case TRANSACT2_QFILEINFO:
8117 case TRANSACT2_QFSINFO:
8118 case TRANSACT2_SETFSINFO:
8121 reply_doserror(req, ERRSRV, ERRaccess);
8122 END_PROFILE(SMBtrans2);
8127 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8128 DEBUG(0, ("talloc failed\n"));
8129 reply_nterror(req, NT_STATUS_NO_MEMORY);
8130 END_PROFILE(SMBtrans2);
8134 state->cmd = SMBtrans2;
8136 state->mid = req->mid;
8137 state->vuid = req->vuid;
8138 state->setup_count = SVAL(req->vwv+13, 0);
8139 state->setup = NULL;
8140 state->total_param = SVAL(req->vwv+0, 0);
8141 state->param = NULL;
8142 state->total_data = SVAL(req->vwv+1, 0);
8144 state->max_param_return = SVAL(req->vwv+2, 0);
8145 state->max_data_return = SVAL(req->vwv+3, 0);
8146 state->max_setup_return = SVAL(req->vwv+4, 0);
8147 state->close_on_completion = BITSETW(req->vwv+5, 0);
8148 state->one_way = BITSETW(req->vwv+5, 1);
8150 state->call = tran_call;
8152 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8153 is so as a sanity check */
8154 if (state->setup_count != 1) {
8156 * Need to have rc=0 for ioctl to get job id for OS/2.
8157 * Network printing will fail if function is not successful.
8158 * Similar function in reply.c will be used if protocol
8159 * is LANMAN1.0 instead of LM1.2X002.
8160 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8161 * outbuf doesn't have to be set(only job id is used).
8163 if ( (state->setup_count == 4)
8164 && (tran_call == TRANSACT2_IOCTL)
8165 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8166 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8167 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8169 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8170 DEBUG(2,("Transaction is %d\n",tran_call));
8172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8173 END_PROFILE(SMBtrans2);
8178 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8181 if (state->total_data) {
8183 if (trans_oob(state->total_data, 0, dscnt)
8184 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8188 /* Can't use talloc here, the core routines do realloc on the
8189 * params and data. */
8190 state->data = (char *)SMB_MALLOC(state->total_data);
8191 if (state->data == NULL) {
8192 DEBUG(0,("reply_trans2: data malloc fail for %u "
8193 "bytes !\n", (unsigned int)state->total_data));
8195 reply_nterror(req, NT_STATUS_NO_MEMORY);
8196 END_PROFILE(SMBtrans2);
8200 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8203 if (state->total_param) {
8205 if (trans_oob(state->total_param, 0, pscnt)
8206 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8210 /* Can't use talloc here, the core routines do realloc on the
8211 * params and data. */
8212 state->param = (char *)SMB_MALLOC(state->total_param);
8213 if (state->param == NULL) {
8214 DEBUG(0,("reply_trans: param malloc fail for %u "
8215 "bytes !\n", (unsigned int)state->total_param));
8216 SAFE_FREE(state->data);
8218 reply_nterror(req, NT_STATUS_NO_MEMORY);
8219 END_PROFILE(SMBtrans2);
8223 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8226 state->received_data = dscnt;
8227 state->received_param = pscnt;
8229 if ((state->received_param == state->total_param) &&
8230 (state->received_data == state->total_data)) {
8232 handle_trans2(conn, req, state);
8234 SAFE_FREE(state->data);
8235 SAFE_FREE(state->param);
8237 END_PROFILE(SMBtrans2);
8241 DLIST_ADD(conn->pending_trans, state);
8243 /* We need to send an interim response then receive the rest
8244 of the parameter/data bytes */
8245 reply_outbuf(req, 0, 0);
8246 show_msg((char *)req->outbuf);
8247 END_PROFILE(SMBtrans2);
8252 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8253 SAFE_FREE(state->data);
8254 SAFE_FREE(state->param);
8256 END_PROFILE(SMBtrans2);
8257 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8261 /****************************************************************************
8262 Reply to a SMBtranss2
8263 ****************************************************************************/
8265 void reply_transs2(struct smb_request *req)
8267 connection_struct *conn = req->conn;
8268 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8269 struct trans_state *state;
8271 START_PROFILE(SMBtranss2);
8273 show_msg((char *)req->inbuf);
8276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8277 END_PROFILE(SMBtranss2);
8281 for (state = conn->pending_trans; state != NULL;
8282 state = state->next) {
8283 if (state->mid == req->mid) {
8288 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8290 END_PROFILE(SMBtranss2);
8294 /* Revise state->total_param and state->total_data in case they have
8295 changed downwards */
8297 if (SVAL(req->vwv+0, 0) < state->total_param)
8298 state->total_param = SVAL(req->vwv+0, 0);
8299 if (SVAL(req->vwv+1, 0) < state->total_data)
8300 state->total_data = SVAL(req->vwv+1, 0);
8302 pcnt = SVAL(req->vwv+2, 0);
8303 poff = SVAL(req->vwv+3, 0);
8304 pdisp = SVAL(req->vwv+4, 0);
8306 dcnt = SVAL(req->vwv+5, 0);
8307 doff = SVAL(req->vwv+6, 0);
8308 ddisp = SVAL(req->vwv+7, 0);
8310 state->received_param += pcnt;
8311 state->received_data += dcnt;
8313 if ((state->received_data > state->total_data) ||
8314 (state->received_param > state->total_param))
8318 if (trans_oob(state->total_param, pdisp, pcnt)
8319 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8322 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8326 if (trans_oob(state->total_data, ddisp, dcnt)
8327 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8330 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8333 if ((state->received_param < state->total_param) ||
8334 (state->received_data < state->total_data)) {
8335 END_PROFILE(SMBtranss2);
8339 handle_trans2(conn, req, state);
8341 DLIST_REMOVE(conn->pending_trans, state);
8342 SAFE_FREE(state->data);
8343 SAFE_FREE(state->param);
8346 END_PROFILE(SMBtranss2);
8351 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8352 DLIST_REMOVE(conn->pending_trans, state);
8353 SAFE_FREE(state->data);
8354 SAFE_FREE(state->param);
8356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8357 END_PROFILE(SMBtranss2);