2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct *conn,
36 const SMB_STRUCT_STAT *psbuf);
38 static char *store_file_unix_basic_info2(connection_struct *conn,
41 const SMB_STRUCT_STAT *psbuf);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
50 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type = get_remote_arch();
54 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
55 val = SMB_ROUNDUP(val,rval);
60 /****************************************************************************
61 Utility functions for dealing with extended attributes.
62 ****************************************************************************/
64 /****************************************************************************
65 Refuse to allow clients to overwrite our private xattrs.
66 ****************************************************************************/
68 static bool samba_private_attr_name(const char *unix_ea_name)
70 static const char * const prohibited_ea_names[] = {
71 SAMBA_POSIX_INHERITANCE_EA_NAME,
72 SAMBA_XATTR_DOS_ATTRIB,
73 SAMBA_XATTR_DOSTIMESTAMPS,
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))) {
166 * TALLOC the result early to get the talloc hierarchy right.
169 names = TALLOC_ARRAY(mem_ctx, char *, 1);
171 DEBUG(0, ("talloc failed\n"));
172 return NT_STATUS_NO_MEMORY;
175 while (ea_namelist_size <= 65536) {
177 ea_namelist = TALLOC_REALLOC_ARRAY(
178 names, ea_namelist, char, ea_namelist_size);
179 if (ea_namelist == NULL) {
180 DEBUG(0, ("talloc failed\n"));
182 return NT_STATUS_NO_MEMORY;
185 if (fsp && fsp->fh->fd != -1) {
186 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
189 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
193 if ((sizeret == -1) && (errno == ERANGE)) {
194 ea_namelist_size *= 2;
203 return map_nt_error_from_unix(errno);
206 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
207 (unsigned int)sizeret));
219 * Ensure the result is 0-terminated
222 if (ea_namelist[sizeret-1] != '\0') {
224 return NT_STATUS_INTERNAL_ERROR;
232 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
236 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
238 DEBUG(0, ("talloc failed\n"));
240 return NT_STATUS_NO_MEMORY;
246 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
247 names[num_names++] = p;
255 *pnum_names = num_names;
259 /****************************************************************************
260 Return a linked list of the total EA's. Plus the total size
261 ****************************************************************************/
263 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
264 const char *fname, size_t *pea_total_len)
266 /* Get a list of all xattrs. Max namesize is 64k. */
269 struct ea_list *ea_list_head = NULL;
274 if (!lp_ea_support(SNUM(conn))) {
278 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
281 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
285 for (i=0; i<num_names; i++) {
286 struct ea_list *listp;
289 if (strnequal(names[i], "system.", 7)
290 || samba_private_attr_name(names[i]))
293 listp = TALLOC_P(mem_ctx, struct ea_list);
298 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
304 push_ascii_fstring(dos_ea_name, listp->ea.name);
307 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
309 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
310 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
311 (unsigned int)listp->ea.value.length));
313 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
317 /* Add on 4 for total length. */
318 if (*pea_total_len) {
322 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
323 (unsigned int)*pea_total_len));
328 /****************************************************************************
329 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
331 ****************************************************************************/
333 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
334 connection_struct *conn, struct ea_list *ea_list)
336 unsigned int ret_data_size = 4;
339 SMB_ASSERT(total_data_size >= 4);
341 if (!lp_ea_support(SNUM(conn))) {
346 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
349 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
350 dos_namelen = strlen(dos_ea_name);
351 if (dos_namelen > 255 || dos_namelen == 0) {
354 if (ea_list->ea.value.length > 65535) {
357 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
361 /* We know we have room. */
362 SCVAL(p,0,ea_list->ea.flags);
363 SCVAL(p,1,dos_namelen);
364 SSVAL(p,2,ea_list->ea.value.length);
365 fstrcpy(p+4, dos_ea_name);
366 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
368 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
369 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
372 ret_data_size = PTR_DIFF(p, pdata);
373 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
374 SIVAL(pdata,0,ret_data_size);
375 return ret_data_size;
378 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
380 unsigned int total_data_size,
381 unsigned int *ret_data_size,
382 connection_struct *conn,
383 struct ea_list *ea_list)
385 uint8_t *p = (uint8_t *)pdata;
386 uint8_t *last_start = NULL;
390 if (!lp_ea_support(SNUM(conn))) {
391 return NT_STATUS_NO_EAS_ON_FILE;
394 for (; ea_list; ea_list = ea_list->next) {
400 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
404 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
405 dos_namelen = strlen(dos_ea_name);
406 if (dos_namelen > 255 || dos_namelen == 0) {
407 return NT_STATUS_INTERNAL_ERROR;
409 if (ea_list->ea.value.length > 65535) {
410 return NT_STATUS_INTERNAL_ERROR;
413 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
416 size_t pad = 4 - (this_size % 4);
420 if (this_size > total_data_size) {
421 return NT_STATUS_INFO_LENGTH_MISMATCH;
424 /* We know we have room. */
425 SIVAL(p, 0x00, 0); /* next offset */
426 SCVAL(p, 0x04, ea_list->ea.flags);
427 SCVAL(p, 0x05, dos_namelen);
428 SSVAL(p, 0x06, ea_list->ea.value.length);
429 fstrcpy((char *)(p+0x08), dos_ea_name);
430 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
432 total_data_size -= this_size;
436 *ret_data_size = PTR_DIFF(p, pdata);
437 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
441 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
443 size_t total_ea_len = 0;
444 TALLOC_CTX *mem_ctx = NULL;
446 if (!lp_ea_support(SNUM(conn))) {
449 mem_ctx = talloc_tos();
450 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
454 /****************************************************************************
455 Ensure the EA name is case insensitive by matching any existing EA name.
456 ****************************************************************************/
458 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
461 TALLOC_CTX *mem_ctx = talloc_tos();
462 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
464 for (; ea_list; ea_list = ea_list->next) {
465 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
466 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
467 &unix_ea_name[5], ea_list->ea.name));
468 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
474 /****************************************************************************
475 Set or delete an extended attribute.
476 ****************************************************************************/
478 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
479 const struct smb_filename *smb_fname, struct ea_list *ea_list)
483 if (!lp_ea_support(SNUM(conn))) {
484 return NT_STATUS_EAS_NOT_SUPPORTED;
487 /* For now setting EAs on streams isn't supported. */
488 fname = smb_fname->base_name;
490 for (;ea_list; ea_list = ea_list->next) {
492 fstring unix_ea_name;
494 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
495 fstrcat(unix_ea_name, ea_list->ea.name);
497 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
499 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
501 if (samba_private_attr_name(unix_ea_name)) {
502 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
503 return NT_STATUS_ACCESS_DENIED;
506 if (ea_list->ea.value.length == 0) {
507 /* Remove the attribute. */
508 if (fsp && (fsp->fh->fd != -1)) {
509 DEBUG(10,("set_ea: deleting ea name %s on "
510 "file %s by file descriptor.\n",
511 unix_ea_name, fsp_str_dbg(fsp)));
512 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
514 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
515 unix_ea_name, fname));
516 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
519 /* Removing a non existent attribute always succeeds. */
520 if (ret == -1 && errno == ENOATTR) {
521 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
527 if (fsp && (fsp->fh->fd != -1)) {
528 DEBUG(10,("set_ea: setting ea name %s on file "
529 "%s by file descriptor.\n",
530 unix_ea_name, fsp_str_dbg(fsp)));
531 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
532 ea_list->ea.value.data, ea_list->ea.value.length, 0);
534 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
535 unix_ea_name, fname));
536 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
537 ea_list->ea.value.data, ea_list->ea.value.length, 0);
543 if (errno == ENOTSUP) {
544 return NT_STATUS_EAS_NOT_SUPPORTED;
547 return map_nt_error_from_unix(errno);
553 /****************************************************************************
554 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
555 ****************************************************************************/
557 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
559 struct ea_list *ea_list_head = NULL;
560 size_t converted_size, offset = 0;
562 while (offset + 2 < data_size) {
563 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
564 unsigned int namelen = CVAL(pdata,offset);
566 offset++; /* Go past the namelen byte. */
568 /* integer wrap paranioa. */
569 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
570 (offset > data_size) || (namelen > data_size) ||
571 (offset + namelen >= data_size)) {
574 /* Ensure the name is null terminated. */
575 if (pdata[offset + namelen] != '\0') {
578 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
580 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
581 "failed: %s", strerror(errno)));
587 offset += (namelen + 1); /* Go past the name + terminating zero. */
588 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
589 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
595 /****************************************************************************
596 Read one EA list entry from the buffer.
597 ****************************************************************************/
599 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
601 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
603 unsigned int namelen;
604 size_t converted_size;
614 eal->ea.flags = CVAL(pdata,0);
615 namelen = CVAL(pdata,1);
616 val_len = SVAL(pdata,2);
618 if (4 + namelen + 1 + val_len > data_size) {
622 /* Ensure the name is null terminated. */
623 if (pdata[namelen + 4] != '\0') {
626 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
627 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
634 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
635 if (!eal->ea.value.data) {
639 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
641 /* Ensure we're null terminated just in case we print the value. */
642 eal->ea.value.data[val_len] = '\0';
643 /* But don't count the null. */
644 eal->ea.value.length--;
647 *pbytes_used = 4 + namelen + 1 + val_len;
650 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
651 dump_data(10, eal->ea.value.data, eal->ea.value.length);
656 /****************************************************************************
657 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
658 ****************************************************************************/
660 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
662 struct ea_list *ea_list_head = NULL;
664 size_t bytes_used = 0;
666 while (offset < data_size) {
667 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
673 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
674 offset += bytes_used;
680 /****************************************************************************
681 Count the total EA size needed.
682 ****************************************************************************/
684 static size_t ea_list_size(struct ea_list *ealist)
687 struct ea_list *listp;
690 for (listp = ealist; listp; listp = listp->next) {
691 push_ascii_fstring(dos_ea_name, listp->ea.name);
692 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
694 /* Add on 4 for total length. */
702 /****************************************************************************
703 Return a union of EA's from a file list and a list of names.
704 The TALLOC context for the two lists *MUST* be identical as we steal
705 memory from one list to add to another. JRA.
706 ****************************************************************************/
708 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
710 struct ea_list *nlistp, *flistp;
712 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
713 for (flistp = file_list; flistp; flistp = flistp->next) {
714 if (strequal(nlistp->ea.name, flistp->ea.name)) {
720 /* Copy the data from this entry. */
721 nlistp->ea.flags = flistp->ea.flags;
722 nlistp->ea.value = flistp->ea.value;
725 nlistp->ea.flags = 0;
726 ZERO_STRUCT(nlistp->ea.value);
730 *total_ea_len = ea_list_size(name_list);
734 /****************************************************************************
735 Send the required number of replies back.
736 We assume all fields other than the data fields are
737 set correctly for the type of call.
738 HACK ! Always assumes smb_setup field is zero.
739 ****************************************************************************/
741 void send_trans2_replies(connection_struct *conn,
742 struct smb_request *req,
749 /* As we are using a protocol > LANMAN1 then the max_send
750 variable must have been set in the sessetupX call.
751 This takes precedence over the max_xmit field in the
752 global struct. These different max_xmit variables should
753 be merged as this is now too confusing */
755 int data_to_send = datasize;
756 int params_to_send = paramsize;
758 const char *pp = params;
759 const char *pd = pdata;
760 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
761 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
762 int data_alignment_offset = 0;
763 bool overflow = False;
764 struct smbd_server_connection *sconn = smbd_server_conn;
765 int max_send = sconn->smb1.sessions.max_send;
767 /* Modify the data_to_send and datasize and set the error if
768 we're trying to send more than max_data_bytes. We still send
769 the part of the packet(s) that fit. Strange, but needed
772 if (max_data_bytes > 0 && datasize > max_data_bytes) {
773 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
774 max_data_bytes, datasize ));
775 datasize = data_to_send = max_data_bytes;
779 /* If there genuinely are no parameters or data to send just send the empty packet */
781 if(params_to_send == 0 && data_to_send == 0) {
782 reply_outbuf(req, 10, 0);
783 show_msg((char *)req->outbuf);
784 if (!srv_send_smb(smbd_server_fd(),
787 IS_CONN_ENCRYPTED(conn),
789 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
791 TALLOC_FREE(req->outbuf);
795 /* When sending params and data ensure that both are nicely aligned */
796 /* Only do this alignment when there is also data to send - else
797 can cause NT redirector problems. */
799 if (((params_to_send % 4) != 0) && (data_to_send != 0))
800 data_alignment_offset = 4 - (params_to_send % 4);
802 /* Space is bufsize minus Netbios over TCP header minus SMB header */
803 /* The alignment_offset is to align the param bytes on an even byte
804 boundary. NT 4.0 Beta needs this to work correctly. */
806 useable_space = max_send - (smb_size
809 + data_alignment_offset);
811 if (useable_space < 0) {
812 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
813 "= %d!!!", useable_space));
814 exit_server_cleanly("send_trans2_replies: Not enough space");
817 while (params_to_send || data_to_send) {
818 /* Calculate whether we will totally or partially fill this packet */
820 total_sent_thistime = params_to_send + data_to_send;
822 /* We can never send more than useable_space */
824 * Note that 'useable_space' does not include the alignment offsets,
825 * but we must include the alignment offsets in the calculation of
826 * the length of the data we send over the wire, as the alignment offsets
827 * are sent here. Fix from Marc_Jacobsen@hp.com.
830 total_sent_thistime = MIN(total_sent_thistime, useable_space);
832 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
833 + data_alignment_offset);
836 * We might have SMBtrans2s in req which was transferred to
837 * the outbuf, fix that.
839 SCVAL(req->outbuf, smb_com, SMBtrans2);
841 /* Set total params and data to be sent */
842 SSVAL(req->outbuf,smb_tprcnt,paramsize);
843 SSVAL(req->outbuf,smb_tdrcnt,datasize);
845 /* Calculate how many parameters and data we can fit into
846 * this packet. Parameters get precedence
849 params_sent_thistime = MIN(params_to_send,useable_space);
850 data_sent_thistime = useable_space - params_sent_thistime;
851 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
853 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
855 /* smb_proff is the offset from the start of the SMB header to the
856 parameter bytes, however the first 4 bytes of outbuf are
857 the Netbios over TCP header. Thus use smb_base() to subtract
858 them from the calculation */
860 SSVAL(req->outbuf,smb_proff,
861 ((smb_buf(req->outbuf)+alignment_offset)
862 - smb_base(req->outbuf)));
864 if(params_sent_thistime == 0)
865 SSVAL(req->outbuf,smb_prdisp,0);
867 /* Absolute displacement of param bytes sent in this packet */
868 SSVAL(req->outbuf,smb_prdisp,pp - params);
870 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
871 if(data_sent_thistime == 0) {
872 SSVAL(req->outbuf,smb_droff,0);
873 SSVAL(req->outbuf,smb_drdisp, 0);
875 /* The offset of the data bytes is the offset of the
876 parameter bytes plus the number of parameters being sent this time */
877 SSVAL(req->outbuf, smb_droff,
878 ((smb_buf(req->outbuf)+alignment_offset)
879 - smb_base(req->outbuf))
880 + params_sent_thistime + data_alignment_offset);
881 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
884 /* Initialize the padding for alignment */
886 if (alignment_offset != 0) {
887 memset(smb_buf(req->outbuf), 0, alignment_offset);
890 /* Copy the param bytes into the packet */
892 if(params_sent_thistime) {
893 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
894 params_sent_thistime);
897 /* Copy in the data bytes */
898 if(data_sent_thistime) {
899 if (data_alignment_offset != 0) {
900 memset((smb_buf(req->outbuf)+alignment_offset+
901 params_sent_thistime), 0,
902 data_alignment_offset);
904 memcpy(smb_buf(req->outbuf)+alignment_offset
905 +params_sent_thistime+data_alignment_offset,
906 pd,data_sent_thistime);
909 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
910 params_sent_thistime, data_sent_thistime, useable_space));
911 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
912 params_to_send, data_to_send, paramsize, datasize));
915 error_packet_set((char *)req->outbuf,
916 ERRDOS,ERRbufferoverflow,
917 STATUS_BUFFER_OVERFLOW,
921 /* Send the packet */
922 show_msg((char *)req->outbuf);
923 if (!srv_send_smb(smbd_server_fd(),
926 IS_CONN_ENCRYPTED(conn),
928 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
930 TALLOC_FREE(req->outbuf);
932 pp += params_sent_thistime;
933 pd += data_sent_thistime;
935 params_to_send -= params_sent_thistime;
936 data_to_send -= data_sent_thistime;
939 if(params_to_send < 0 || data_to_send < 0) {
940 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
941 params_to_send, data_to_send));
949 /****************************************************************************
950 Reply to a TRANSACT2_OPEN.
951 ****************************************************************************/
953 static void call_trans2open(connection_struct *conn,
954 struct smb_request *req,
955 char **pparams, int total_params,
956 char **ppdata, int total_data,
957 unsigned int max_data_bytes)
959 struct smb_filename *smb_fname = NULL;
960 char *params = *pparams;
961 char *pdata = *ppdata;
966 bool return_additional_info;
979 struct ea_list *ea_list = NULL;
984 uint32 create_disposition;
985 uint32 create_options = 0;
986 TALLOC_CTX *ctx = talloc_tos();
989 * Ensure we have enough parameters to perform the operation.
992 if (total_params < 29) {
993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
997 flags = SVAL(params, 0);
998 deny_mode = SVAL(params, 2);
999 open_attr = SVAL(params,6);
1000 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1001 if (oplock_request) {
1002 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1006 return_additional_info = BITSETW(params,0);
1007 open_sattr = SVAL(params, 4);
1008 open_time = make_unix_date3(params+8);
1010 open_ofun = SVAL(params,12);
1011 open_size = IVAL(params,14);
1012 pname = ¶ms[28];
1015 reply_doserror(req, ERRSRV, ERRaccess);
1019 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1020 total_params - 28, STR_TERMINATE,
1022 if (!NT_STATUS_IS_OK(status)) {
1023 reply_nterror(req, status);
1027 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1028 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1029 (unsigned int)open_ofun, open_size));
1031 status = filename_convert(ctx,
1033 req->flags2 & FLAGS2_DFS_PATHNAMES,
1038 if (!NT_STATUS_IS_OK(status)) {
1039 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1040 reply_botherror(req,
1041 NT_STATUS_PATH_NOT_COVERED,
1042 ERRSRV, ERRbadpath);
1045 reply_nterror(req, status);
1049 if (open_ofun == 0) {
1050 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1054 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1055 &access_mask, &share_mode,
1056 &create_disposition,
1058 reply_doserror(req, ERRDOS, ERRbadaccess);
1062 /* Any data in this call is an EA list. */
1063 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1064 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1068 if (total_data != 4) {
1069 if (total_data < 10) {
1070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1074 if (IVAL(pdata,0) > total_data) {
1075 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1076 IVAL(pdata,0), (unsigned int)total_data));
1077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1081 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1087 } else if (IVAL(pdata,0) != 4) {
1088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1092 status = SMB_VFS_CREATE_FILE(
1095 0, /* root_dir_fid */
1096 smb_fname, /* fname */
1097 access_mask, /* access_mask */
1098 share_mode, /* share_access */
1099 create_disposition, /* create_disposition*/
1100 create_options, /* create_options */
1101 open_attr, /* file_attributes */
1102 oplock_request, /* oplock_request */
1103 open_size, /* allocation_size */
1105 ea_list, /* ea_list */
1107 &smb_action); /* psbuf */
1109 if (!NT_STATUS_IS_OK(status)) {
1110 if (open_was_deferred(req->mid)) {
1111 /* We have re-scheduled this call. */
1114 reply_openerror(req, status);
1118 size = get_file_size_stat(&smb_fname->st);
1119 fattr = dos_mode(conn, smb_fname);
1120 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1121 inode = smb_fname->st.st_ex_ino;
1123 close_file(req, fsp, ERROR_CLOSE);
1124 reply_doserror(req, ERRDOS,ERRnoaccess);
1128 /* Realloc the size of parameters and data we will return */
1129 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1130 if(*pparams == NULL ) {
1131 reply_nterror(req, NT_STATUS_NO_MEMORY);
1136 SSVAL(params,0,fsp->fnum);
1137 SSVAL(params,2,fattr);
1138 srv_put_dos_date2(params,4, mtime);
1139 SIVAL(params,8, (uint32)size);
1140 SSVAL(params,12,deny_mode);
1141 SSVAL(params,14,0); /* open_type - file or directory. */
1142 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1144 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1145 smb_action |= EXTENDED_OPLOCK_GRANTED;
1148 SSVAL(params,18,smb_action);
1151 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1153 SIVAL(params,20,inode);
1154 SSVAL(params,24,0); /* Padding. */
1156 uint32 ea_size = estimate_ea_size(conn, fsp,
1157 fsp->fsp_name->base_name);
1158 SIVAL(params, 26, ea_size);
1160 SIVAL(params, 26, 0);
1163 /* Send the required number of replies */
1164 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1166 TALLOC_FREE(smb_fname);
1169 /*********************************************************
1170 Routine to check if a given string matches exactly.
1171 as a special case a mask of "." does NOT match. That
1172 is required for correct wildcard semantics
1173 Case can be significant or not.
1174 **********************************************************/
1176 static bool exact_match(bool has_wild,
1177 bool case_sensitive,
1181 if (mask[0] == '.' && mask[1] == 0) {
1189 if (case_sensitive) {
1190 return strcmp(str,mask)==0;
1192 return StrCaseCmp(str,mask) == 0;
1196 /****************************************************************************
1197 Return the filetype for UNIX extensions.
1198 ****************************************************************************/
1200 static uint32 unix_filetype(mode_t mode)
1203 return UNIX_TYPE_FILE;
1204 else if(S_ISDIR(mode))
1205 return UNIX_TYPE_DIR;
1207 else if(S_ISLNK(mode))
1208 return UNIX_TYPE_SYMLINK;
1211 else if(S_ISCHR(mode))
1212 return UNIX_TYPE_CHARDEV;
1215 else if(S_ISBLK(mode))
1216 return UNIX_TYPE_BLKDEV;
1219 else if(S_ISFIFO(mode))
1220 return UNIX_TYPE_FIFO;
1223 else if(S_ISSOCK(mode))
1224 return UNIX_TYPE_SOCKET;
1227 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1228 return UNIX_TYPE_UNKNOWN;
1231 /****************************************************************************
1232 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1233 ****************************************************************************/
1235 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1237 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1238 const SMB_STRUCT_STAT *psbuf,
1240 enum perm_type ptype,
1245 if (perms == SMB_MODE_NO_CHANGE) {
1246 if (!VALID_STAT(*psbuf)) {
1247 return NT_STATUS_INVALID_PARAMETER;
1249 *ret_perms = psbuf->st_ex_mode;
1250 return NT_STATUS_OK;
1254 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1255 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1256 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1257 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1258 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1259 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1260 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1261 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1262 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1264 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1267 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1270 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1275 /* Apply mode mask */
1276 ret &= lp_create_mask(SNUM(conn));
1277 /* Add in force bits */
1278 ret |= lp_force_create_mode(SNUM(conn));
1281 ret &= lp_dir_mask(SNUM(conn));
1282 /* Add in force bits */
1283 ret |= lp_force_dir_mode(SNUM(conn));
1285 case PERM_EXISTING_FILE:
1286 /* Apply mode mask */
1287 ret &= lp_security_mask(SNUM(conn));
1288 /* Add in force bits */
1289 ret |= lp_force_security_mode(SNUM(conn));
1291 case PERM_EXISTING_DIR:
1292 /* Apply mode mask */
1293 ret &= lp_dir_security_mask(SNUM(conn));
1294 /* Add in force bits */
1295 ret |= lp_force_dir_security_mode(SNUM(conn));
1300 return NT_STATUS_OK;
1303 /****************************************************************************
1304 Needed to show the msdfs symlinks as directories. Modifies psbuf
1305 to be a directory if it's a msdfs link.
1306 ****************************************************************************/
1308 static bool check_msdfs_link(connection_struct *conn,
1309 const char *pathname,
1310 SMB_STRUCT_STAT *psbuf)
1312 int saved_errno = errno;
1313 if(lp_host_msdfs() &&
1314 lp_msdfs_root(SNUM(conn)) &&
1315 is_msdfs_link(conn, pathname, psbuf)) {
1317 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1320 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1321 errno = saved_errno;
1324 errno = saved_errno;
1329 /****************************************************************************
1330 Get a level dependent lanman2 dir entry.
1331 ****************************************************************************/
1333 struct smbd_dirptr_lanman2_state {
1334 connection_struct *conn;
1335 uint32_t info_level;
1336 bool check_mangled_names;
1338 bool got_exact_match;
1341 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1347 struct smbd_dirptr_lanman2_state *state =
1348 (struct smbd_dirptr_lanman2_state *)private_data;
1350 char mangled_name[13]; /* mangled 8.3 name. */
1354 /* Mangle fname if it's an illegal name. */
1355 if (mangle_must_mangle(dname, state->conn->params)) {
1356 ok = name_to_8_3(dname, mangled_name,
1357 true, state->conn->params);
1361 fname = mangled_name;
1366 got_match = exact_match(state->has_wild,
1367 state->conn->case_sensitive,
1369 state->got_exact_match = got_match;
1371 got_match = mask_match(fname, mask,
1372 state->conn->case_sensitive);
1375 if(!got_match && state->check_mangled_names &&
1376 !mangle_is_8_3(fname, false, state->conn->params)) {
1378 * It turns out that NT matches wildcards against
1379 * both long *and* short names. This may explain some
1380 * of the wildcard wierdness from old DOS clients
1381 * that some people have been seeing.... JRA.
1383 /* Force the mangling into 8.3. */
1384 ok = name_to_8_3(fname, mangled_name,
1385 false, state->conn->params);
1390 got_match = exact_match(state->has_wild,
1391 state->conn->case_sensitive,
1392 mangled_name, mask);
1393 state->got_exact_match = got_match;
1395 got_match = mask_match(mangled_name, mask,
1396 state->conn->case_sensitive);
1404 *_fname = talloc_strdup(ctx, fname);
1405 if (*_fname == NULL) {
1412 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1414 struct smb_filename *smb_fname,
1417 struct smbd_dirptr_lanman2_state *state =
1418 (struct smbd_dirptr_lanman2_state *)private_data;
1419 bool ms_dfs_link = false;
1422 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1423 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1424 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1425 "Couldn't lstat [%s] (%s)\n",
1426 smb_fname_str_dbg(smb_fname),
1430 } else if (!VALID_STAT(smb_fname->st) &&
1431 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1432 /* Needed to show the msdfs symlinks as
1435 ms_dfs_link = check_msdfs_link(state->conn,
1436 smb_fname->base_name,
1439 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1440 "Couldn't stat [%s] (%s)\n",
1441 smb_fname_str_dbg(smb_fname),
1448 mode = dos_mode_msdfs(state->conn, smb_fname);
1450 mode = dos_mode(state->conn, smb_fname);
1457 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1458 connection_struct *conn,
1460 uint32_t info_level,
1461 struct ea_list *name_list,
1462 bool check_mangled_names,
1463 bool requires_resume_key,
1466 const struct smb_filename *smb_fname,
1467 uint64_t space_remaining,
1474 uint64_t *last_entry_off)
1476 char *p, *q, *pdata = *ppdata;
1478 uint64_t file_size = 0;
1479 uint64_t allocation_size = 0;
1481 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1482 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1483 time_t c_date = (time_t)0;
1485 char *last_entry_ptr;
1487 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1491 *out_of_space = false;
1493 ZERO_STRUCT(mdate_ts);
1494 ZERO_STRUCT(adate_ts);
1495 ZERO_STRUCT(create_date_ts);
1496 ZERO_STRUCT(cdate_ts);
1498 if (!(mode & aDIR)) {
1499 file_size = get_file_size_stat(&smb_fname->st);
1501 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1503 mdate_ts = smb_fname->st.st_ex_mtime;
1504 adate_ts = smb_fname->st.st_ex_atime;
1505 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1506 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1508 if (lp_dos_filetime_resolution(SNUM(conn))) {
1509 dos_filetime_timespec(&create_date_ts);
1510 dos_filetime_timespec(&mdate_ts);
1511 dos_filetime_timespec(&adate_ts);
1512 dos_filetime_timespec(&cdate_ts);
1515 create_date = convert_timespec_to_time_t(create_date_ts);
1516 mdate = convert_timespec_to_time_t(mdate_ts);
1517 adate = convert_timespec_to_time_t(adate_ts);
1518 c_date = convert_timespec_to_time_t(cdate_ts);
1520 /* align the record */
1521 off = PTR_DIFF(pdata, base_data);
1522 pad = (off + (align-1)) & ~(align-1);
1525 /* initialize padding to 0 */
1527 memset(pdata, 0, pad);
1529 space_remaining -= pad;
1538 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1540 switch (info_level) {
1541 case SMB_FIND_INFO_STANDARD:
1542 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1543 if(requires_resume_key) {
1547 srv_put_dos_date2(p,0,create_date);
1548 srv_put_dos_date2(p,4,adate);
1549 srv_put_dos_date2(p,8,mdate);
1550 SIVAL(p,12,(uint32)file_size);
1551 SIVAL(p,16,(uint32)allocation_size);
1555 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1556 p += ucs2_align(base_data, p, 0);
1558 len = srvstr_push(base_data, flags2, p,
1559 fname, PTR_DIFF(end_data, p),
1561 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1563 SCVAL(nameptr, -1, len - 2);
1565 SCVAL(nameptr, -1, 0);
1569 SCVAL(nameptr, -1, len - 1);
1571 SCVAL(nameptr, -1, 0);
1577 case SMB_FIND_EA_SIZE:
1578 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1579 if (requires_resume_key) {
1583 srv_put_dos_date2(p,0,create_date);
1584 srv_put_dos_date2(p,4,adate);
1585 srv_put_dos_date2(p,8,mdate);
1586 SIVAL(p,12,(uint32)file_size);
1587 SIVAL(p,16,(uint32)allocation_size);
1590 unsigned int ea_size = estimate_ea_size(conn, NULL,
1591 smb_fname->base_name);
1592 SIVAL(p,22,ea_size); /* Extended attributes */
1596 len = srvstr_push(base_data, flags2,
1597 p, fname, PTR_DIFF(end_data, p),
1598 STR_TERMINATE | STR_NOALIGN);
1599 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1612 SCVAL(nameptr,0,len);
1614 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1617 case SMB_FIND_EA_LIST:
1619 struct ea_list *file_list = NULL;
1622 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1626 if (requires_resume_key) {
1630 srv_put_dos_date2(p,0,create_date);
1631 srv_put_dos_date2(p,4,adate);
1632 srv_put_dos_date2(p,8,mdate);
1633 SIVAL(p,12,(uint32)file_size);
1634 SIVAL(p,16,(uint32)allocation_size);
1636 p += 22; /* p now points to the EA area. */
1638 file_list = get_ea_list_from_file(ctx, conn, NULL,
1639 smb_fname->base_name,
1641 name_list = ea_list_union(name_list, file_list, &ea_len);
1643 /* We need to determine if this entry will fit in the space available. */
1644 /* Max string size is 255 bytes. */
1645 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1646 *out_of_space = true;
1647 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1648 return False; /* Not finished - just out of space */
1651 /* Push the ea_data followed by the name. */
1652 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1654 len = srvstr_push(base_data, flags2,
1655 p + 1, fname, PTR_DIFF(end_data, p+1),
1656 STR_TERMINATE | STR_NOALIGN);
1657 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1670 SCVAL(nameptr,0,len);
1672 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1676 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1677 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1678 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1680 SIVAL(p,0,reskey); p += 4;
1681 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1682 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1683 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1684 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1685 SOFF_T(p,0,file_size); p += 8;
1686 SOFF_T(p,0,allocation_size); p += 8;
1687 SIVAL(p,0,nt_extmode); p += 4;
1688 q = p; p += 4; /* q is placeholder for name length. */
1690 unsigned int ea_size = estimate_ea_size(conn, NULL,
1691 smb_fname->base_name);
1692 SIVAL(p,0,ea_size); /* Extended attributes */
1695 /* Clear the short name buffer. This is
1696 * IMPORTANT as not doing so will trigger
1697 * a Win2k client bug. JRA.
1699 if (!was_8_3 && check_mangled_names) {
1700 char mangled_name[13]; /* mangled 8.3 name. */
1701 if (!name_to_8_3(fname,mangled_name,True,
1703 /* Error - mangle failed ! */
1704 memset(mangled_name,'\0',12);
1706 mangled_name[12] = 0;
1707 len = srvstr_push(base_data, flags2,
1708 p+2, mangled_name, 24,
1709 STR_UPPER|STR_UNICODE);
1711 memset(p + 2 + len,'\0',24 - len);
1718 len = srvstr_push(base_data, flags2, p,
1719 fname, PTR_DIFF(end_data, p),
1720 STR_TERMINATE_ASCII);
1724 len = PTR_DIFF(p, pdata);
1725 pad = (len + (align-1)) & ~(align-1);
1727 * offset to the next entry, the caller
1728 * will overwrite it for the last entry
1729 * that's why we always include the padding
1733 * set padding to zero
1736 memset(p, 0, pad - len);
1743 case SMB_FIND_FILE_DIRECTORY_INFO:
1744 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1746 SIVAL(p,0,reskey); p += 4;
1747 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1748 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1749 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1750 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1751 SOFF_T(p,0,file_size); p += 8;
1752 SOFF_T(p,0,allocation_size); p += 8;
1753 SIVAL(p,0,nt_extmode); p += 4;
1754 len = srvstr_push(base_data, flags2,
1755 p + 4, fname, PTR_DIFF(end_data, p+4),
1756 STR_TERMINATE_ASCII);
1760 len = PTR_DIFF(p, pdata);
1761 pad = (len + (align-1)) & ~(align-1);
1763 * offset to the next entry, the caller
1764 * will overwrite it for the last entry
1765 * that's why we always include the padding
1769 * set padding to zero
1772 memset(p, 0, pad - len);
1779 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1780 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1782 SIVAL(p,0,reskey); p += 4;
1783 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1784 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1785 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1787 SOFF_T(p,0,file_size); p += 8;
1788 SOFF_T(p,0,allocation_size); p += 8;
1789 SIVAL(p,0,nt_extmode); p += 4;
1790 q = p; p += 4; /* q is placeholder for name length. */
1792 unsigned int ea_size = estimate_ea_size(conn, NULL,
1793 smb_fname->base_name);
1794 SIVAL(p,0,ea_size); /* Extended attributes */
1797 len = srvstr_push(base_data, flags2, p,
1798 fname, PTR_DIFF(end_data, p),
1799 STR_TERMINATE_ASCII);
1803 len = PTR_DIFF(p, pdata);
1804 pad = (len + (align-1)) & ~(align-1);
1806 * offset to the next entry, the caller
1807 * will overwrite it for the last entry
1808 * that's why we always include the padding
1812 * set padding to zero
1815 memset(p, 0, pad - len);
1822 case SMB_FIND_FILE_NAMES_INFO:
1823 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1825 SIVAL(p,0,reskey); p += 4;
1827 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1828 acl on a dir (tridge) */
1829 len = srvstr_push(base_data, flags2, p,
1830 fname, PTR_DIFF(end_data, p),
1831 STR_TERMINATE_ASCII);
1835 len = PTR_DIFF(p, pdata);
1836 pad = (len + (align-1)) & ~(align-1);
1838 * offset to the next entry, the caller
1839 * will overwrite it for the last entry
1840 * that's why we always include the padding
1844 * set padding to zero
1847 memset(p, 0, pad - len);
1854 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1855 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1857 SIVAL(p,0,reskey); p += 4;
1858 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1859 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1862 SOFF_T(p,0,file_size); p += 8;
1863 SOFF_T(p,0,allocation_size); p += 8;
1864 SIVAL(p,0,nt_extmode); p += 4;
1865 q = p; p += 4; /* q is placeholder for name length. */
1867 unsigned int ea_size = estimate_ea_size(conn, NULL,
1868 smb_fname->base_name);
1869 SIVAL(p,0,ea_size); /* Extended attributes */
1872 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1873 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1874 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1875 len = srvstr_push(base_data, flags2, p,
1876 fname, PTR_DIFF(end_data, p),
1877 STR_TERMINATE_ASCII);
1881 len = PTR_DIFF(p, pdata);
1882 pad = (len + (align-1)) & ~(align-1);
1884 * offset to the next entry, the caller
1885 * will overwrite it for the last entry
1886 * that's why we always include the padding
1890 * set padding to zero
1893 memset(p, 0, pad - len);
1900 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1901 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1902 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1904 SIVAL(p,0,reskey); p += 4;
1905 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1906 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1907 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1909 SOFF_T(p,0,file_size); p += 8;
1910 SOFF_T(p,0,allocation_size); p += 8;
1911 SIVAL(p,0,nt_extmode); p += 4;
1912 q = p; p += 4; /* q is placeholder for name length */
1914 unsigned int ea_size = estimate_ea_size(conn, NULL,
1915 smb_fname->base_name);
1916 SIVAL(p,0,ea_size); /* Extended attributes */
1919 /* Clear the short name buffer. This is
1920 * IMPORTANT as not doing so will trigger
1921 * a Win2k client bug. JRA.
1923 if (!was_8_3 && check_mangled_names) {
1924 char mangled_name[13]; /* mangled 8.3 name. */
1925 if (!name_to_8_3(fname,mangled_name,True,
1927 /* Error - mangle failed ! */
1928 memset(mangled_name,'\0',12);
1930 mangled_name[12] = 0;
1931 len = srvstr_push(base_data, flags2,
1932 p+2, mangled_name, 24,
1933 STR_UPPER|STR_UNICODE);
1936 memset(p + 2 + len,'\0',24 - len);
1943 SSVAL(p,0,0); p += 2; /* Reserved ? */
1944 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1945 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1946 len = srvstr_push(base_data, flags2, p,
1947 fname, PTR_DIFF(end_data, p),
1948 STR_TERMINATE_ASCII);
1952 len = PTR_DIFF(p, pdata);
1953 pad = (len + (align-1)) & ~(align-1);
1955 * offset to the next entry, the caller
1956 * will overwrite it for the last entry
1957 * that's why we always include the padding
1961 * set padding to zero
1964 memset(p, 0, pad - len);
1971 /* CIFS UNIX Extension. */
1973 case SMB_FIND_FILE_UNIX:
1974 case SMB_FIND_FILE_UNIX_INFO2:
1976 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1978 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1980 if (info_level == SMB_FIND_FILE_UNIX) {
1981 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1982 p = store_file_unix_basic(conn, p,
1983 NULL, &smb_fname->st);
1984 len = srvstr_push(base_data, flags2, p,
1985 fname, PTR_DIFF(end_data, p),
1988 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1989 p = store_file_unix_basic_info2(conn, p,
1990 NULL, &smb_fname->st);
1993 len = srvstr_push(base_data, flags2, p, fname,
1994 PTR_DIFF(end_data, p), 0);
1995 SIVAL(nameptr, 0, len);
2000 len = PTR_DIFF(p, pdata);
2001 pad = (len + (align-1)) & ~(align-1);
2003 * offset to the next entry, the caller
2004 * will overwrite it for the last entry
2005 * that's why we always include the padding
2009 * set padding to zero
2012 memset(p, 0, pad - len);
2017 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2025 if (PTR_DIFF(p,pdata) > space_remaining) {
2026 *out_of_space = true;
2027 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2028 return false; /* Not finished - just out of space */
2031 /* Setup the last entry pointer, as an offset from base_data */
2032 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2033 /* Advance the data pointer to the next slot */
2039 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2040 connection_struct *conn,
2041 struct dptr_struct *dirptr,
2043 const char *path_mask,
2046 int requires_resume_key,
2054 int space_remaining,
2056 bool *got_exact_match,
2057 int *_last_entry_off,
2058 struct ea_list *name_list)
2061 const char *mask = NULL;
2062 long prev_dirpos = 0;
2065 struct smb_filename *smb_fname = NULL;
2066 struct smbd_dirptr_lanman2_state state;
2068 uint64_t last_entry_off = 0;
2072 state.info_level = info_level;
2073 state.check_mangled_names = lp_manglednames(conn->params);
2074 state.has_wild = dptr_has_wild(dirptr);
2075 state.got_exact_match = false;
2077 *out_of_space = false;
2078 *got_exact_match = false;
2080 p = strrchr_m(path_mask,'/');
2091 ok = smbd_dirptr_get_entry(ctx,
2097 smbd_dirptr_lanman2_match_fn,
2098 smbd_dirptr_lanman2_mode_fn,
2108 *got_exact_match = state.got_exact_match;
2110 ok = smbd_marshall_dir_entry(ctx,
2115 state.check_mangled_names,
2116 requires_resume_key,
2129 TALLOC_FREE(smb_fname);
2130 if (*out_of_space) {
2131 dptr_SeekDir(dirptr, prev_dirpos);
2138 *_last_entry_off = last_entry_off;
2142 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2143 connection_struct *conn,
2144 struct dptr_struct *dirptr,
2146 const char *path_mask,
2149 bool requires_resume_key,
2155 int space_remaining,
2157 bool *got_exact_match,
2158 int *last_entry_off,
2159 struct ea_list *name_list)
2162 const bool do_pad = true;
2164 if (info_level >= 1 && info_level <= 3) {
2165 /* No alignment on earlier info levels. */
2169 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2170 path_mask, dirtype, info_level,
2171 requires_resume_key, dont_descend, ask_sharemode,
2173 ppdata, base_data, end_data,
2175 out_of_space, got_exact_match,
2176 last_entry_off, name_list);
2179 /****************************************************************************
2180 Reply to a TRANS2_FINDFIRST.
2181 ****************************************************************************/
2183 static void call_trans2findfirst(connection_struct *conn,
2184 struct smb_request *req,
2185 char **pparams, int total_params,
2186 char **ppdata, int total_data,
2187 unsigned int max_data_bytes)
2189 /* We must be careful here that we don't return more than the
2190 allowed number of data bytes. If this means returning fewer than
2191 maxentries then so be it. We assume that the redirector has
2192 enough room for the fixed number of parameter bytes it has
2194 struct smb_filename *smb_dname = NULL;
2195 char *params = *pparams;
2196 char *pdata = *ppdata;
2200 uint16 findfirst_flags;
2201 bool close_after_first;
2203 bool requires_resume_key;
2205 char *directory = NULL;
2208 int last_entry_off=0;
2212 bool finished = False;
2213 bool dont_descend = False;
2214 bool out_of_space = False;
2215 int space_remaining;
2216 bool mask_contains_wcard = False;
2217 struct ea_list *ea_list = NULL;
2218 NTSTATUS ntstatus = NT_STATUS_OK;
2219 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2220 TALLOC_CTX *ctx = talloc_tos();
2221 struct dptr_struct *dirptr = NULL;
2222 struct smbd_server_connection *sconn = smbd_server_conn;
2224 if (total_params < 13) {
2225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2229 dirtype = SVAL(params,0);
2230 maxentries = SVAL(params,2);
2231 findfirst_flags = SVAL(params,4);
2232 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2233 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2234 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2235 info_level = SVAL(params,6);
2237 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2238 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2239 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2240 info_level, max_data_bytes));
2243 /* W2K3 seems to treat zero as 1. */
2247 switch (info_level) {
2248 case SMB_FIND_INFO_STANDARD:
2249 case SMB_FIND_EA_SIZE:
2250 case SMB_FIND_EA_LIST:
2251 case SMB_FIND_FILE_DIRECTORY_INFO:
2252 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2253 case SMB_FIND_FILE_NAMES_INFO:
2254 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2255 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2256 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2258 case SMB_FIND_FILE_UNIX:
2259 case SMB_FIND_FILE_UNIX_INFO2:
2260 /* Always use filesystem for UNIX mtime query. */
2261 ask_sharemode = false;
2262 if (!lp_unix_extensions()) {
2263 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2268 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2272 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2273 params+12, total_params - 12,
2274 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2275 if (!NT_STATUS_IS_OK(ntstatus)) {
2276 reply_nterror(req, ntstatus);
2280 ntstatus = filename_convert(ctx, conn,
2281 req->flags2 & FLAGS2_DFS_PATHNAMES,
2284 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2285 &mask_contains_wcard,
2287 if (!NT_STATUS_IS_OK(ntstatus)) {
2288 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2289 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2290 ERRSRV, ERRbadpath);
2293 reply_nterror(req, ntstatus);
2297 mask = smb_dname->original_lcomp;
2299 directory = smb_dname->base_name;
2301 p = strrchr_m(directory,'/');
2303 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2304 if((directory[0] == '.') && (directory[1] == '\0')) {
2305 mask = talloc_strdup(ctx,"*");
2307 reply_nterror(req, NT_STATUS_NO_MEMORY);
2310 mask_contains_wcard = True;
2312 directory = talloc_strdup(talloc_tos(), "./");
2314 reply_nterror(req, NT_STATUS_NO_MEMORY);
2321 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2323 if (info_level == SMB_FIND_EA_LIST) {
2326 if (total_data < 4) {
2327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2331 ea_size = IVAL(pdata,0);
2332 if (ea_size != total_data) {
2333 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2334 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2339 if (!lp_ea_support(SNUM(conn))) {
2340 reply_doserror(req, ERRDOS, ERReasnotsupported);
2344 /* Pull out the list of names. */
2345 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2352 *ppdata = (char *)SMB_REALLOC(
2353 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2354 if(*ppdata == NULL ) {
2355 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2361 /* Realloc the params space */
2362 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2363 if (*pparams == NULL) {
2364 reply_nterror(req, NT_STATUS_NO_MEMORY);
2369 /* Save the wildcard match and attribs we are using on this directory -
2370 needed as lanman2 assumes these are being saved between calls */
2372 ntstatus = dptr_create(conn,
2378 mask_contains_wcard,
2382 if (!NT_STATUS_IS_OK(ntstatus)) {
2383 reply_nterror(req, ntstatus);
2387 dptr_num = dptr_dnum(dirptr);
2388 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2390 /* Initialize per TRANS2_FIND_FIRST operation data */
2391 dptr_init_search_op(dirptr);
2393 /* We don't need to check for VOL here as this is returned by
2394 a different TRANS2 call. */
2396 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2397 directory,lp_dontdescend(SNUM(conn))));
2398 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2399 dont_descend = True;
2402 space_remaining = max_data_bytes;
2403 out_of_space = False;
2405 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2406 bool got_exact_match = False;
2408 /* this is a heuristic to avoid seeking the dirptr except when
2409 absolutely necessary. It allows for a filename of about 40 chars */
2410 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2411 out_of_space = True;
2414 finished = !get_lanman2_dir_entry(ctx,
2418 mask,dirtype,info_level,
2419 requires_resume_key,dont_descend,
2422 space_remaining, &out_of_space,
2424 &last_entry_off, ea_list);
2427 if (finished && out_of_space)
2430 if (!finished && !out_of_space)
2434 * As an optimisation if we know we aren't looking
2435 * for a wildcard name (ie. the name matches the wildcard exactly)
2436 * then we can finish on any (first) match.
2437 * This speeds up large directory searches. JRA.
2443 /* Ensure space_remaining never goes -ve. */
2444 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2445 space_remaining = 0;
2446 out_of_space = true;
2448 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2452 /* Check if we can close the dirptr */
2453 if(close_after_first || (finished && close_if_end)) {
2454 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2455 dptr_close(sconn, &dptr_num);
2459 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2460 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2461 * the protocol level is less than NT1. Tested with smbclient. JRA.
2462 * This should fix the OS/2 client bug #2335.
2465 if(numentries == 0) {
2466 dptr_close(sconn, &dptr_num);
2467 if (get_Protocol() < PROTOCOL_NT1) {
2468 reply_doserror(req, ERRDOS, ERRnofiles);
2471 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2472 ERRDOS, ERRbadfile);
2477 /* At this point pdata points to numentries directory entries. */
2479 /* Set up the return parameter block */
2480 SSVAL(params,0,dptr_num);
2481 SSVAL(params,2,numentries);
2482 SSVAL(params,4,finished);
2483 SSVAL(params,6,0); /* Never an EA error */
2484 SSVAL(params,8,last_entry_off);
2486 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2489 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2490 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2492 reply_nterror(req, NT_STATUS_NO_MEMORY);
2496 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2497 smb_fn_name(req->cmd),
2498 mask, directory, dirtype, numentries ) );
2501 * Force a name mangle here to ensure that the
2502 * mask as an 8.3 name is top of the mangled cache.
2503 * The reasons for this are subtle. Don't remove
2504 * this code unless you know what you are doing
2505 * (see PR#13758). JRA.
2508 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2509 char mangled_name[13];
2510 name_to_8_3(mask, mangled_name, True, conn->params);
2513 TALLOC_FREE(smb_dname);
2517 /****************************************************************************
2518 Reply to a TRANS2_FINDNEXT.
2519 ****************************************************************************/
2521 static void call_trans2findnext(connection_struct *conn,
2522 struct smb_request *req,
2523 char **pparams, int total_params,
2524 char **ppdata, int total_data,
2525 unsigned int max_data_bytes)
2527 /* We must be careful here that we don't return more than the
2528 allowed number of data bytes. If this means returning fewer than
2529 maxentries then so be it. We assume that the redirector has
2530 enough room for the fixed number of parameter bytes it has
2532 char *params = *pparams;
2533 char *pdata = *ppdata;
2539 uint16 findnext_flags;
2540 bool close_after_request;
2542 bool requires_resume_key;
2544 bool mask_contains_wcard = False;
2545 char *resume_name = NULL;
2546 const char *mask = NULL;
2547 const char *directory = NULL;
2551 int i, last_entry_off=0;
2552 bool finished = False;
2553 bool dont_descend = False;
2554 bool out_of_space = False;
2555 int space_remaining;
2556 struct ea_list *ea_list = NULL;
2557 NTSTATUS ntstatus = NT_STATUS_OK;
2558 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2559 TALLOC_CTX *ctx = talloc_tos();
2560 struct dptr_struct *dirptr;
2561 struct smbd_server_connection *sconn = smbd_server_conn;
2563 if (total_params < 13) {
2564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2568 dptr_num = SVAL(params,0);
2569 maxentries = SVAL(params,2);
2570 info_level = SVAL(params,4);
2571 resume_key = IVAL(params,6);
2572 findnext_flags = SVAL(params,10);
2573 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2574 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2575 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2576 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2578 if (!continue_bit) {
2579 /* We only need resume_name if continue_bit is zero. */
2580 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2582 total_params - 12, STR_TERMINATE, &ntstatus,
2583 &mask_contains_wcard);
2584 if (!NT_STATUS_IS_OK(ntstatus)) {
2585 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2586 complain (it thinks we're asking for the directory above the shared
2587 path or an invalid name). Catch this as the resume name is only compared, never used in
2588 a file access. JRA. */
2589 srvstr_pull_talloc(ctx, params, req->flags2,
2590 &resume_name, params+12,
2594 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2595 reply_nterror(req, ntstatus);
2601 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2602 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2603 resume_key = %d resume name = %s continue=%d level = %d\n",
2604 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2605 requires_resume_key, resume_key,
2606 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2609 /* W2K3 seems to treat zero as 1. */
2613 switch (info_level) {
2614 case SMB_FIND_INFO_STANDARD:
2615 case SMB_FIND_EA_SIZE:
2616 case SMB_FIND_EA_LIST:
2617 case SMB_FIND_FILE_DIRECTORY_INFO:
2618 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2619 case SMB_FIND_FILE_NAMES_INFO:
2620 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2621 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2622 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2624 case SMB_FIND_FILE_UNIX:
2625 case SMB_FIND_FILE_UNIX_INFO2:
2626 /* Always use filesystem for UNIX mtime query. */
2627 ask_sharemode = false;
2628 if (!lp_unix_extensions()) {
2629 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2634 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2638 if (info_level == SMB_FIND_EA_LIST) {
2641 if (total_data < 4) {
2642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2646 ea_size = IVAL(pdata,0);
2647 if (ea_size != total_data) {
2648 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2649 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2654 if (!lp_ea_support(SNUM(conn))) {
2655 reply_doserror(req, ERRDOS, ERReasnotsupported);
2659 /* Pull out the list of names. */
2660 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2667 *ppdata = (char *)SMB_REALLOC(
2668 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2669 if(*ppdata == NULL) {
2670 reply_nterror(req, NT_STATUS_NO_MEMORY);
2675 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2677 /* Realloc the params space */
2678 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2679 if(*pparams == NULL ) {
2680 reply_nterror(req, NT_STATUS_NO_MEMORY);
2686 /* Check that the dptr is valid */
2687 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2688 reply_doserror(req, ERRDOS, ERRnofiles);
2692 directory = dptr_path(sconn, dptr_num);
2694 /* Get the wildcard mask from the dptr */
2695 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2696 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2697 reply_doserror(req, ERRDOS, ERRnofiles);
2703 /* Get the attr mask from the dptr */
2704 dirtype = dptr_attr(sconn, dptr_num);
2706 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2707 dptr_num, mask, dirtype,
2709 dptr_TellDir(dirptr)));
2711 /* Initialize per TRANS2_FIND_NEXT operation data */
2712 dptr_init_search_op(dirptr);
2714 /* We don't need to check for VOL here as this is returned by
2715 a different TRANS2 call. */
2717 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2718 directory,lp_dontdescend(SNUM(conn))));
2719 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2720 dont_descend = True;
2723 space_remaining = max_data_bytes;
2724 out_of_space = False;
2727 * Seek to the correct position. We no longer use the resume key but
2728 * depend on the last file name instead.
2731 if(!continue_bit && resume_name && *resume_name) {
2734 long current_pos = 0;
2736 * Remember, name_to_8_3 is called by
2737 * get_lanman2_dir_entry(), so the resume name
2738 * could be mangled. Ensure we check the unmangled name.
2741 if (mangle_is_mangled(resume_name, conn->params)) {
2742 char *new_resume_name = NULL;
2743 mangle_lookup_name_from_8_3(ctx,
2747 if (new_resume_name) {
2748 resume_name = new_resume_name;
2753 * Fix for NT redirector problem triggered by resume key indexes
2754 * changing between directory scans. We now return a resume key of 0
2755 * and instead look for the filename to continue from (also given
2756 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2757 * findfirst/findnext (as is usual) then the directory pointer
2758 * should already be at the correct place.
2761 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2762 } /* end if resume_name && !continue_bit */
2764 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2765 bool got_exact_match = False;
2767 /* this is a heuristic to avoid seeking the dirptr except when
2768 absolutely necessary. It allows for a filename of about 40 chars */
2769 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2770 out_of_space = True;
2773 finished = !get_lanman2_dir_entry(ctx,
2777 mask,dirtype,info_level,
2778 requires_resume_key,dont_descend,
2781 space_remaining, &out_of_space,
2783 &last_entry_off, ea_list);
2786 if (finished && out_of_space)
2789 if (!finished && !out_of_space)
2793 * As an optimisation if we know we aren't looking
2794 * for a wildcard name (ie. the name matches the wildcard exactly)
2795 * then we can finish on any (first) match.
2796 * This speeds up large directory searches. JRA.
2802 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2805 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2806 smb_fn_name(req->cmd),
2807 mask, directory, dirtype, numentries ) );
2809 /* Check if we can close the dirptr */
2810 if(close_after_request || (finished && close_if_end)) {
2811 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2812 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2815 /* Set up the return parameter block */
2816 SSVAL(params,0,numentries);
2817 SSVAL(params,2,finished);
2818 SSVAL(params,4,0); /* Never an EA error */
2819 SSVAL(params,6,last_entry_off);
2821 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2827 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2829 E_md4hash(lp_servicename(SNUM(conn)),objid);
2833 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2835 SMB_ASSERT(extended_info != NULL);
2837 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2838 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2839 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2840 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2841 #ifdef SAMBA_VERSION_REVISION
2842 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2844 extended_info->samba_subversion = 0;
2845 #ifdef SAMBA_VERSION_RC_RELEASE
2846 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2848 #ifdef SAMBA_VERSION_PRE_RELEASE
2849 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2852 #ifdef SAMBA_VERSION_VENDOR_PATCH
2853 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2855 extended_info->samba_gitcommitdate = 0;
2856 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2857 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2860 memset(extended_info->samba_version_string, 0,
2861 sizeof(extended_info->samba_version_string));
2863 snprintf (extended_info->samba_version_string,
2864 sizeof(extended_info->samba_version_string),
2865 "%s", samba_version_string());
2868 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2869 TALLOC_CTX *mem_ctx,
2870 uint16_t info_level,
2872 unsigned int max_data_bytes,
2876 char *pdata, *end_data;
2877 int data_len = 0, len;
2878 const char *vname = volume_label(SNUM(conn));
2879 int snum = SNUM(conn);
2880 char *fstype = lp_fstype(SNUM(conn));
2881 uint32 additional_flags = 0;
2882 struct smb_filename *smb_fname_dot = NULL;
2887 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2888 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2889 "info level (0x%x) on IPC$.\n",
2890 (unsigned int)info_level));
2891 return NT_STATUS_ACCESS_DENIED;
2895 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2897 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2899 if (!NT_STATUS_IS_OK(status)) {
2903 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2904 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2905 TALLOC_FREE(smb_fname_dot);
2906 return map_nt_error_from_unix(errno);
2909 st = smb_fname_dot->st;
2910 TALLOC_FREE(smb_fname_dot);
2912 *ppdata = (char *)SMB_REALLOC(
2913 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2914 if (*ppdata == NULL) {
2915 return NT_STATUS_NO_MEMORY;
2919 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2920 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2922 switch (info_level) {
2923 case SMB_INFO_ALLOCATION:
2925 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2927 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2928 return map_nt_error_from_unix(errno);
2931 block_size = lp_block_size(snum);
2932 if (bsize < block_size) {
2933 uint64_t factor = block_size/bsize;
2938 if (bsize > block_size) {
2939 uint64_t factor = bsize/block_size;
2944 bytes_per_sector = 512;
2945 sectors_per_unit = bsize/bytes_per_sector;
2947 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2948 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2949 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2951 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2952 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2953 SIVAL(pdata,l1_cUnit,dsize);
2954 SIVAL(pdata,l1_cUnitAvail,dfree);
2955 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2959 case SMB_INFO_VOLUME:
2960 /* Return volume name */
2962 * Add volume serial number - hash of a combination of
2963 * the called hostname and the service name.
2965 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2967 * Win2k3 and previous mess this up by sending a name length
2968 * one byte short. I believe only older clients (OS/2 Win9x) use
2969 * this call so try fixing this by adding a terminating null to
2970 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2974 pdata+l2_vol_szVolLabel, vname,
2975 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2976 STR_NOALIGN|STR_TERMINATE);
2977 SCVAL(pdata,l2_vol_cch,len);
2978 data_len = l2_vol_szVolLabel + len;
2979 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2980 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2984 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2985 case SMB_FS_ATTRIBUTE_INFORMATION:
2987 additional_flags = 0;
2988 #if defined(HAVE_SYS_QUOTAS)
2989 additional_flags |= FILE_VOLUME_QUOTAS;
2992 if(lp_nt_acl_support(SNUM(conn))) {
2993 additional_flags |= FILE_PERSISTENT_ACLS;
2996 /* Capabilities are filled in at connection time through STATVFS call */
2997 additional_flags |= conn->fs_capabilities;
2998 additional_flags |= lp_parm_int(conn->params->service,
2999 "share", "fake_fscaps",
3002 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3003 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3004 additional_flags); /* FS ATTRIBUTES */
3006 SIVAL(pdata,4,255); /* Max filename component length */
3007 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3008 and will think we can't do long filenames */
3009 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3010 PTR_DIFF(end_data, pdata+12),
3013 data_len = 12 + len;
3016 case SMB_QUERY_FS_LABEL_INFO:
3017 case SMB_FS_LABEL_INFORMATION:
3018 len = srvstr_push(pdata, flags2, pdata+4, vname,
3019 PTR_DIFF(end_data, pdata+4), 0);
3024 case SMB_QUERY_FS_VOLUME_INFO:
3025 case SMB_FS_VOLUME_INFORMATION:
3028 * Add volume serial number - hash of a combination of
3029 * the called hostname and the service name.
3031 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3032 (str_checksum(get_local_machine_name())<<16));
3034 /* Max label len is 32 characters. */
3035 len = srvstr_push(pdata, flags2, pdata+18, vname,
3036 PTR_DIFF(end_data, pdata+18),
3038 SIVAL(pdata,12,len);
3041 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3042 (int)strlen(vname),vname, lp_servicename(snum)));
3045 case SMB_QUERY_FS_SIZE_INFO:
3046 case SMB_FS_SIZE_INFORMATION:
3048 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3050 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3051 return map_nt_error_from_unix(errno);
3053 block_size = lp_block_size(snum);
3054 if (bsize < block_size) {
3055 uint64_t factor = block_size/bsize;
3060 if (bsize > block_size) {
3061 uint64_t factor = bsize/block_size;
3066 bytes_per_sector = 512;
3067 sectors_per_unit = bsize/bytes_per_sector;
3068 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3069 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3070 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3071 SBIG_UINT(pdata,0,dsize);
3072 SBIG_UINT(pdata,8,dfree);
3073 SIVAL(pdata,16,sectors_per_unit);
3074 SIVAL(pdata,20,bytes_per_sector);
3078 case SMB_FS_FULL_SIZE_INFORMATION:
3080 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3082 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3083 return map_nt_error_from_unix(errno);
3085 block_size = lp_block_size(snum);
3086 if (bsize < block_size) {
3087 uint64_t factor = block_size/bsize;
3092 if (bsize > block_size) {
3093 uint64_t factor = bsize/block_size;
3098 bytes_per_sector = 512;
3099 sectors_per_unit = bsize/bytes_per_sector;
3100 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3101 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3102 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3103 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3104 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3105 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3106 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3107 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3111 case SMB_QUERY_FS_DEVICE_INFO:
3112 case SMB_FS_DEVICE_INFORMATION:
3114 SIVAL(pdata,0,0); /* dev type */
3115 SIVAL(pdata,4,0); /* characteristics */
3118 #ifdef HAVE_SYS_QUOTAS
3119 case SMB_FS_QUOTA_INFORMATION:
3121 * what we have to send --metze:
3123 * Unknown1: 24 NULL bytes
3124 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3125 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3126 * Quota Flags: 2 byte :
3127 * Unknown3: 6 NULL bytes
3131 * details for Quota Flags:
3133 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3134 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3135 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3136 * 0x0001 Enable Quotas: enable quota for this fs
3140 /* we need to fake up a fsp here,
3141 * because its not send in this call
3144 SMB_NTQUOTA_STRUCT quotas;
3147 ZERO_STRUCT(quotas);
3153 if (conn->server_info->utok.uid != sec_initial_uid()) {
3154 DEBUG(0,("set_user_quota: access_denied "
3155 "service [%s] user [%s]\n",
3156 lp_servicename(SNUM(conn)),
3157 conn->server_info->unix_name));
3158 return NT_STATUS_ACCESS_DENIED;
3161 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3162 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3163 return map_nt_error_from_unix(errno);
3168 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3169 lp_servicename(SNUM(conn))));
3171 /* Unknown1 24 NULL bytes*/
3172 SBIG_UINT(pdata,0,(uint64_t)0);
3173 SBIG_UINT(pdata,8,(uint64_t)0);
3174 SBIG_UINT(pdata,16,(uint64_t)0);
3176 /* Default Soft Quota 8 bytes */
3177 SBIG_UINT(pdata,24,quotas.softlim);
3179 /* Default Hard Quota 8 bytes */
3180 SBIG_UINT(pdata,32,quotas.hardlim);
3182 /* Quota flag 2 bytes */
3183 SSVAL(pdata,40,quotas.qflags);
3185 /* Unknown3 6 NULL bytes */
3191 #endif /* HAVE_SYS_QUOTAS */
3192 case SMB_FS_OBJECTID_INFORMATION:
3194 unsigned char objid[16];
3195 struct smb_extended_info extended_info;
3196 memcpy(pdata,create_volume_objectid(conn, objid),16);
3197 samba_extended_info_version (&extended_info);
3198 SIVAL(pdata,16,extended_info.samba_magic);
3199 SIVAL(pdata,20,extended_info.samba_version);
3200 SIVAL(pdata,24,extended_info.samba_subversion);
3201 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3202 memcpy(pdata+36,extended_info.samba_version_string,28);
3208 * Query the version and capabilities of the CIFS UNIX extensions
3212 case SMB_QUERY_CIFS_UNIX_INFO:
3214 bool large_write = lp_min_receive_file_size() &&
3215 !srv_is_signing_active(smbd_server_conn);
3216 bool large_read = !srv_is_signing_active(smbd_server_conn);
3217 int encrypt_caps = 0;
3219 if (!lp_unix_extensions()) {
3220 return NT_STATUS_INVALID_LEVEL;
3223 switch (conn->encrypt_level) {
3229 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3232 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3233 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3234 large_write = false;
3240 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3241 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3243 /* We have POSIX ACLs, pathname, encryption,
3244 * large read/write, and locking capability. */
3246 SBIG_UINT(pdata,4,((uint64_t)(
3247 CIFS_UNIX_POSIX_ACLS_CAP|
3248 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3249 CIFS_UNIX_FCNTL_LOCKS_CAP|
3250 CIFS_UNIX_EXTATTR_CAP|
3251 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3253 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3255 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3259 case SMB_QUERY_POSIX_FS_INFO:
3262 vfs_statvfs_struct svfs;
3264 if (!lp_unix_extensions()) {
3265 return NT_STATUS_INVALID_LEVEL;
3268 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3272 SIVAL(pdata,0,svfs.OptimalTransferSize);
3273 SIVAL(pdata,4,svfs.BlockSize);
3274 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3275 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3276 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3277 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3278 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3279 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3280 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3282 } else if (rc == EOPNOTSUPP) {
3283 return NT_STATUS_INVALID_LEVEL;
3284 #endif /* EOPNOTSUPP */
3286 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3287 return NT_STATUS_DOS(ERRSRV, ERRerror);
3292 case SMB_QUERY_POSIX_WHOAMI:
3298 if (!lp_unix_extensions()) {
3299 return NT_STATUS_INVALID_LEVEL;
3302 if (max_data_bytes < 40) {
3303 return NT_STATUS_BUFFER_TOO_SMALL;
3306 /* We ARE guest if global_sid_Builtin_Guests is
3307 * in our list of SIDs.
3309 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3310 conn->server_info->ptok)) {
3311 flags |= SMB_WHOAMI_GUEST;
3314 /* We are NOT guest if global_sid_Authenticated_Users
3315 * is in our list of SIDs.
3317 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3318 conn->server_info->ptok)) {
3319 flags &= ~SMB_WHOAMI_GUEST;
3322 /* NOTE: 8 bytes for UID/GID, irrespective of native
3323 * platform size. This matches
3324 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3326 data_len = 4 /* flags */
3333 + 4 /* pad/reserved */
3334 + (conn->server_info->utok.ngroups * 8)
3336 + (conn->server_info->ptok->num_sids *
3340 SIVAL(pdata, 0, flags);
3341 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3343 (uint64_t)conn->server_info->utok.uid);
3344 SBIG_UINT(pdata, 16,
3345 (uint64_t)conn->server_info->utok.gid);
3348 if (data_len >= max_data_bytes) {
3349 /* Potential overflow, skip the GIDs and SIDs. */
3351 SIVAL(pdata, 24, 0); /* num_groups */
3352 SIVAL(pdata, 28, 0); /* num_sids */
3353 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3354 SIVAL(pdata, 36, 0); /* reserved */
3360 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3361 SIVAL(pdata, 28, conn->server_info->num_sids);
3363 /* We walk the SID list twice, but this call is fairly
3364 * infrequent, and I don't expect that it's performance
3365 * sensitive -- jpeach
3367 for (i = 0, sid_bytes = 0;
3368 i < conn->server_info->ptok->num_sids; ++i) {
3369 sid_bytes += ndr_size_dom_sid(
3370 &conn->server_info->ptok->user_sids[i],
3375 /* SID list byte count */
3376 SIVAL(pdata, 32, sid_bytes);
3378 /* 4 bytes pad/reserved - must be zero */
3379 SIVAL(pdata, 36, 0);
3383 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3384 SBIG_UINT(pdata, data_len,
3385 (uint64_t)conn->server_info->utok.groups[i]);
3391 i < conn->server_info->ptok->num_sids; ++i) {
3392 int sid_len = ndr_size_dom_sid(
3393 &conn->server_info->ptok->user_sids[i],
3397 sid_linearize(pdata + data_len, sid_len,
3398 &conn->server_info->ptok->user_sids[i]);
3399 data_len += sid_len;
3405 case SMB_MAC_QUERY_FS_INFO:
3407 * Thursby MAC extension... ONLY on NTFS filesystems
3408 * once we do streams then we don't need this
3410 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3412 SIVAL(pdata,84,0x100); /* Don't support mac... */
3417 return NT_STATUS_INVALID_LEVEL;
3420 *ret_data_len = data_len;
3421 return NT_STATUS_OK;
3424 /****************************************************************************
3425 Reply to a TRANS2_QFSINFO (query filesystem info).
3426 ****************************************************************************/
3428 static void call_trans2qfsinfo(connection_struct *conn,
3429 struct smb_request *req,
3430 char **pparams, int total_params,
3431 char **ppdata, int total_data,
3432 unsigned int max_data_bytes)
3434 char *params = *pparams;
3435 uint16_t info_level;
3439 if (total_params < 2) {
3440 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3444 info_level = SVAL(params,0);
3446 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3447 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3448 DEBUG(0,("call_trans2qfsinfo: encryption required "
3449 "and info level 0x%x sent.\n",
3450 (unsigned int)info_level));
3451 exit_server_cleanly("encryption required "
3457 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3459 status = smbd_do_qfsinfo(conn, req,
3464 if (!NT_STATUS_IS_OK(status)) {
3465 reply_nterror(req, status);
3469 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3472 DEBUG( 4, ( "%s info_level = %d\n",
3473 smb_fn_name(req->cmd), info_level) );
3478 /****************************************************************************
3479 Reply to a TRANS2_SETFSINFO (set filesystem info).
3480 ****************************************************************************/
3482 static void call_trans2setfsinfo(connection_struct *conn,
3483 struct smb_request *req,
3484 char **pparams, int total_params,
3485 char **ppdata, int total_data,
3486 unsigned int max_data_bytes)
3488 char *pdata = *ppdata;
3489 char *params = *pparams;
3492 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3495 if (total_params < 4) {
3496 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3498 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3502 info_level = SVAL(params,2);
3505 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3506 info_level != SMB_SET_CIFS_UNIX_INFO) {
3507 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3508 "info level (0x%x) on IPC$.\n",
3509 (unsigned int)info_level));
3510 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3515 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3516 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3517 DEBUG(0,("call_trans2setfsinfo: encryption required "
3518 "and info level 0x%x sent.\n",
3519 (unsigned int)info_level));
3520 exit_server_cleanly("encryption required "
3526 switch(info_level) {
3527 case SMB_SET_CIFS_UNIX_INFO:
3529 uint16 client_unix_major;
3530 uint16 client_unix_minor;
3531 uint32 client_unix_cap_low;
3532 uint32 client_unix_cap_high;
3534 if (!lp_unix_extensions()) {
3536 NT_STATUS_INVALID_LEVEL);
3540 /* There should be 12 bytes of capabilities set. */
3541 if (total_data < 8) {
3544 NT_STATUS_INVALID_PARAMETER);
3547 client_unix_major = SVAL(pdata,0);
3548 client_unix_minor = SVAL(pdata,2);
3549 client_unix_cap_low = IVAL(pdata,4);
3550 client_unix_cap_high = IVAL(pdata,8);
3551 /* Just print these values for now. */
3552 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3553 cap_low = 0x%x, cap_high = 0x%x\n",
3554 (unsigned int)client_unix_major,
3555 (unsigned int)client_unix_minor,
3556 (unsigned int)client_unix_cap_low,
3557 (unsigned int)client_unix_cap_high ));
3559 /* Here is where we must switch to posix pathname processing... */
3560 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3561 lp_set_posix_pathnames();
3562 mangle_change_to_posix();
3565 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3566 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3567 /* Client that knows how to do posix locks,
3568 * but not posix open/mkdir operations. Set a
3569 * default type for read/write checks. */
3571 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3577 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3580 size_t param_len = 0;
3581 size_t data_len = total_data;
3583 if (!lp_unix_extensions()) {
3586 NT_STATUS_INVALID_LEVEL);
3590 if (lp_smb_encrypt(SNUM(conn)) == false) {
3593 NT_STATUS_NOT_SUPPORTED);
3597 DEBUG( 4,("call_trans2setfsinfo: "
3598 "request transport encryption.\n"));
3600 status = srv_request_encryption_setup(conn,
3601 (unsigned char **)ppdata,
3603 (unsigned char **)pparams,
3606 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3607 !NT_STATUS_IS_OK(status)) {
3608 reply_nterror(req, status);
3612 send_trans2_replies(conn, req,
3619 if (NT_STATUS_IS_OK(status)) {
3620 /* Server-side transport
3621 * encryption is now *on*. */
3622 status = srv_encryption_start(conn);
3623 if (!NT_STATUS_IS_OK(status)) {
3624 exit_server_cleanly(
3625 "Failure in setting "
3626 "up encrypted transport");
3632 case SMB_FS_QUOTA_INFORMATION:
3634 files_struct *fsp = NULL;
3635 SMB_NTQUOTA_STRUCT quotas;
3637 ZERO_STRUCT(quotas);
3640 if ((conn->server_info->utok.uid != sec_initial_uid())
3641 ||!CAN_WRITE(conn)) {
3642 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3643 lp_servicename(SNUM(conn)),
3644 conn->server_info->unix_name));
3645 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3649 /* note: normaly there're 48 bytes,
3650 * but we didn't use the last 6 bytes for now
3653 fsp = file_fsp(req, SVAL(params,0));
3655 if (!check_fsp_ntquota_handle(conn, req,
3657 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3659 req, NT_STATUS_INVALID_HANDLE);
3663 if (total_data < 42) {
3664 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3668 NT_STATUS_INVALID_PARAMETER);
3672 /* unknown_1 24 NULL bytes in pdata*/
3674 /* the soft quotas 8 bytes (uint64_t)*/
3675 quotas.softlim = (uint64_t)IVAL(pdata,24);
3676 #ifdef LARGE_SMB_OFF_T
3677 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3678 #else /* LARGE_SMB_OFF_T */
3679 if ((IVAL(pdata,28) != 0)&&
3680 ((quotas.softlim != 0xFFFFFFFF)||
3681 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3682 /* more than 32 bits? */
3685 NT_STATUS_INVALID_PARAMETER);
3688 #endif /* LARGE_SMB_OFF_T */
3690 /* the hard quotas 8 bytes (uint64_t)*/
3691 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3692 #ifdef LARGE_SMB_OFF_T
3693 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3694 #else /* LARGE_SMB_OFF_T */
3695 if ((IVAL(pdata,36) != 0)&&
3696 ((quotas.hardlim != 0xFFFFFFFF)||
3697 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3698 /* more than 32 bits? */
3701 NT_STATUS_INVALID_PARAMETER);
3704 #endif /* LARGE_SMB_OFF_T */
3706 /* quota_flags 2 bytes **/
3707 quotas.qflags = SVAL(pdata,40);
3709 /* unknown_2 6 NULL bytes follow*/
3711 /* now set the quotas */
3712 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3713 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3714 reply_nterror(req, map_nt_error_from_unix(errno));
3721 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3723 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3729 * sending this reply works fine,
3730 * but I'm not sure it's the same
3731 * like windows do...
3734 reply_outbuf(req, 10, 0);
3737 #if defined(HAVE_POSIX_ACLS)
3738 /****************************************************************************
3739 Utility function to count the number of entries in a POSIX acl.
3740 ****************************************************************************/
3742 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3744 unsigned int ace_count = 0;
3745 int entry_id = SMB_ACL_FIRST_ENTRY;
3746 SMB_ACL_ENTRY_T entry;
3748 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3750 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3751 entry_id = SMB_ACL_NEXT_ENTRY;
3758 /****************************************************************************
3759 Utility function to marshall a POSIX acl into wire format.
3760 ****************************************************************************/
3762 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3764 int entry_id = SMB_ACL_FIRST_ENTRY;
3765 SMB_ACL_ENTRY_T entry;
3767 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3768 SMB_ACL_TAG_T tagtype;
3769 SMB_ACL_PERMSET_T permset;
3770 unsigned char perms = 0;
3771 unsigned int own_grp;
3774 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3775 entry_id = SMB_ACL_NEXT_ENTRY;
3778 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3779 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3783 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3784 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3788 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3789 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3790 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3792 SCVAL(pdata,1,perms);
3795 case SMB_ACL_USER_OBJ:
3796 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3797 own_grp = (unsigned int)pst->st_ex_uid;
3798 SIVAL(pdata,2,own_grp);
3803 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3805 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3808 own_grp = (unsigned int)*puid;
3809 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3810 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3811 SIVAL(pdata,2,own_grp);
3815 case SMB_ACL_GROUP_OBJ:
3816 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3817 own_grp = (unsigned int)pst->st_ex_gid;
3818 SIVAL(pdata,2,own_grp);
3823 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3825 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3828 own_grp = (unsigned int)*pgid;
3829 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3830 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3831 SIVAL(pdata,2,own_grp);
3836 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3837 SIVAL(pdata,2,0xFFFFFFFF);
3838 SIVAL(pdata,6,0xFFFFFFFF);
3841 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3842 SIVAL(pdata,2,0xFFFFFFFF);
3843 SIVAL(pdata,6,0xFFFFFFFF);
3846 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3849 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3856 /****************************************************************************
3857 Store the FILE_UNIX_BASIC info.
3858 ****************************************************************************/
3860 static char *store_file_unix_basic(connection_struct *conn,
3863 const SMB_STRUCT_STAT *psbuf)
3865 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3866 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3868 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3871 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3874 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3875 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3876 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3879 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3883 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3887 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3890 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3894 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3898 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3901 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3905 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3912 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3913 * the chflags(2) (or equivalent) flags.
3915 * XXX: this really should be behind the VFS interface. To do this, we would
3916 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3917 * Each VFS module could then implement its own mapping as appropriate for the
3918 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3920 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3924 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3928 { UF_IMMUTABLE, EXT_IMMUTABLE },
3932 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3936 { UF_HIDDEN, EXT_HIDDEN },
3939 /* Do not remove. We need to guarantee that this array has at least one
3940 * entry to build on HP-UX.
3946 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3947 uint32 *smb_fflags, uint32 *smb_fmask)
3951 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3952 *smb_fmask |= info2_flags_map[i].smb_fflag;
3953 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3954 *smb_fflags |= info2_flags_map[i].smb_fflag;
3959 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3960 const uint32 smb_fflags,
3961 const uint32 smb_fmask,
3964 uint32 max_fmask = 0;
3967 *stat_fflags = psbuf->st_ex_flags;
3969 /* For each flags requested in smb_fmask, check the state of the
3970 * corresponding flag in smb_fflags and set or clear the matching
3974 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3975 max_fmask |= info2_flags_map[i].smb_fflag;
3976 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3977 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3978 *stat_fflags |= info2_flags_map[i].stat_fflag;
3980 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3985 /* If smb_fmask is asking to set any bits that are not supported by
3986 * our flag mappings, we should fail.
3988 if ((smb_fmask & max_fmask) != smb_fmask) {
3996 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3997 * of file flags and birth (create) time.
3999 static char *store_file_unix_basic_info2(connection_struct *conn,
4002 const SMB_STRUCT_STAT *psbuf)
4004 uint32 file_flags = 0;
4005 uint32 flags_mask = 0;
4007 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4009 /* Create (birth) time 64 bit */
4010 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4013 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4014 SIVAL(pdata, 0, file_flags); /* flags */
4015 SIVAL(pdata, 4, flags_mask); /* mask */
4021 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4022 const struct stream_struct *streams,
4024 unsigned int max_data_bytes,
4025 unsigned int *data_size)
4028 unsigned int ofs = 0;
4030 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4031 unsigned int next_offset;
4033 smb_ucs2_t *namebuf;
4035 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4036 streams[i].name, &namelen) ||
4039 return NT_STATUS_INVALID_PARAMETER;
4043 * name_buf is now null-terminated, we need to marshall as not
4049 SIVAL(data, ofs+4, namelen);
4050 SOFF_T(data, ofs+8, streams[i].size);
4051 SOFF_T(data, ofs+16, streams[i].alloc_size);
4052 memcpy(data+ofs+24, namebuf, namelen);
4053 TALLOC_FREE(namebuf);
4055 next_offset = ofs + 24 + namelen;
4057 if (i == num_streams-1) {
4058 SIVAL(data, ofs, 0);
4061 unsigned int align = ndr_align_size(next_offset, 8);
4063 memset(data+next_offset, 0, align);
4064 next_offset += align;
4066 SIVAL(data, ofs, next_offset - ofs);
4075 return NT_STATUS_OK;
4078 /****************************************************************************
4079 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4080 ****************************************************************************/
4082 static void call_trans2qpipeinfo(connection_struct *conn,
4083 struct smb_request *req,
4084 unsigned int tran_call,
4085 char **pparams, int total_params,
4086 char **ppdata, int total_data,
4087 unsigned int max_data_bytes)
4089 char *params = *pparams;
4090 char *pdata = *ppdata;
4091 unsigned int data_size = 0;
4092 unsigned int param_size = 2;
4097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4101 if (total_params < 4) {
4102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4106 fsp = file_fsp(req, SVAL(params,0));
4107 if (!fsp_is_np(fsp)) {
4108 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4112 info_level = SVAL(params,2);
4114 *pparams = (char *)SMB_REALLOC(*pparams,2);
4115 if (*pparams == NULL) {
4116 reply_nterror(req, NT_STATUS_NO_MEMORY);
4121 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4122 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4123 if (*ppdata == NULL ) {
4124 reply_nterror(req, NT_STATUS_NO_MEMORY);
4129 switch (info_level) {
4130 case SMB_FILE_STANDARD_INFORMATION:
4132 SOFF_T(pdata,0,4096LL);
4139 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4143 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4149 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4150 TALLOC_CTX *mem_ctx,
4151 uint16_t info_level,
4153 struct smb_filename *smb_fname,
4154 bool delete_pending,
4155 struct timespec write_time_ts,
4157 struct ea_list *ea_list,
4158 int lock_data_count,
4161 unsigned int max_data_bytes,
4163 unsigned int *pdata_size)
4165 char *pdata = *ppdata;
4166 char *dstart, *dend;
4167 unsigned int data_size;
4168 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4169 time_t create_time, mtime, atime, c_time;
4170 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4177 uint64_t file_size = 0;
4179 uint64_t allocation_size = 0;
4180 uint64_t file_index = 0;
4181 uint32_t access_mask = 0;
4183 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4184 return NT_STATUS_INVALID_LEVEL;
4187 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4188 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4189 info_level, max_data_bytes));
4192 mode = dos_mode_msdfs(conn, smb_fname);
4194 mode = dos_mode(conn, smb_fname);
4197 mode = FILE_ATTRIBUTE_NORMAL;
4199 nlink = psbuf->st_ex_nlink;
4201 if (nlink && (mode&aDIR)) {
4205 if ((nlink > 0) && delete_pending) {
4209 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4210 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4211 if (*ppdata == NULL) {
4212 return NT_STATUS_NO_MEMORY;
4216 dend = dstart + data_size - 1;
4218 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4219 update_stat_ex_mtime(psbuf, write_time_ts);
4222 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4223 mtime_ts = psbuf->st_ex_mtime;
4224 atime_ts = psbuf->st_ex_atime;
4225 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4227 if (lp_dos_filetime_resolution(SNUM(conn))) {
4228 dos_filetime_timespec(&create_time_ts);
4229 dos_filetime_timespec(&mtime_ts);
4230 dos_filetime_timespec(&atime_ts);
4231 dos_filetime_timespec(&ctime_ts);
4234 create_time = convert_timespec_to_time_t(create_time_ts);
4235 mtime = convert_timespec_to_time_t(mtime_ts);
4236 atime = convert_timespec_to_time_t(atime_ts);
4237 c_time = convert_timespec_to_time_t(ctime_ts);
4239 p = strrchr_m(smb_fname->base_name,'/');
4241 base_name = smb_fname->base_name;
4245 /* NT expects the name to be in an exact form of the *full*
4246 filename. See the trans2 torture test */
4247 if (ISDOT(base_name)) {
4248 dos_fname = talloc_strdup(mem_ctx, "\\");
4250 return NT_STATUS_NO_MEMORY;
4253 dos_fname = talloc_asprintf(mem_ctx,
4255 smb_fname->base_name);
4257 return NT_STATUS_NO_MEMORY;
4259 if (is_ntfs_stream_smb_fname(smb_fname)) {
4260 dos_fname = talloc_asprintf(dos_fname, "%s",
4261 smb_fname->stream_name);
4263 return NT_STATUS_NO_MEMORY;
4267 string_replace(dos_fname, '/', '\\');
4270 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4273 /* Do we have this path open ? */
4275 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4276 fsp1 = file_find_di_first(fileid);
4277 if (fsp1 && fsp1->initial_allocation_size) {
4278 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4282 if (!(mode & aDIR)) {
4283 file_size = get_file_size_stat(psbuf);
4287 pos = fsp->fh->position_information;
4291 access_mask = fsp->access_mask;
4293 /* GENERIC_EXECUTE mapping from Windows */
4294 access_mask = 0x12019F;
4297 /* This should be an index number - looks like
4300 I think this causes us to fail the IFSKIT
4301 BasicFileInformationTest. -tpot */
4302 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4303 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4305 switch (info_level) {
4306 case SMB_INFO_STANDARD:
4307 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4309 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4310 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4311 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4312 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4313 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4314 SSVAL(pdata,l1_attrFile,mode);
4317 case SMB_INFO_QUERY_EA_SIZE:
4319 unsigned int ea_size =
4320 estimate_ea_size(conn, fsp,
4321 smb_fname->base_name);
4322 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4324 srv_put_dos_date2(pdata,0,create_time);
4325 srv_put_dos_date2(pdata,4,atime);
4326 srv_put_dos_date2(pdata,8,mtime); /* write time */
4327 SIVAL(pdata,12,(uint32)file_size);
4328 SIVAL(pdata,16,(uint32)allocation_size);
4329 SSVAL(pdata,20,mode);
4330 SIVAL(pdata,22,ea_size);
4334 case SMB_INFO_IS_NAME_VALID:
4335 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4337 /* os/2 needs this ? really ?*/
4338 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4340 /* This is only reached for qpathinfo */
4344 case SMB_INFO_QUERY_EAS_FROM_LIST:
4346 size_t total_ea_len = 0;
4347 struct ea_list *ea_file_list = NULL;
4349 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4352 get_ea_list_from_file(mem_ctx, conn, fsp,
4353 smb_fname->base_name,
4355 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4357 if (!ea_list || (total_ea_len > data_size)) {
4359 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4363 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4367 case SMB_INFO_QUERY_ALL_EAS:
4369 /* We have data_size bytes to put EA's into. */
4370 size_t total_ea_len = 0;
4372 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4374 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4375 smb_fname->base_name,
4377 if (!ea_list || (total_ea_len > data_size)) {
4379 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4383 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4387 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4389 /* This is FileFullEaInformation - 0xF which maps to
4390 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4392 /* We have data_size bytes to put EA's into. */
4393 size_t total_ea_len = 0;
4394 struct ea_list *ea_file_list = NULL;
4396 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4398 /*TODO: add filtering and index handling */
4401 get_ea_list_from_file(mem_ctx, conn, fsp,
4402 smb_fname->base_name,
4404 if (!ea_file_list) {
4405 return NT_STATUS_NO_EAS_ON_FILE;
4408 status = fill_ea_chained_buffer(mem_ctx,
4412 conn, ea_file_list);
4413 if (!NT_STATUS_IS_OK(status)) {
4419 case SMB_FILE_BASIC_INFORMATION:
4420 case SMB_QUERY_FILE_BASIC_INFO:
4422 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4423 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4424 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4426 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4430 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4431 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4432 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4433 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4434 SIVAL(pdata,32,mode);
4436 DEBUG(5,("SMB_QFBI - "));
4437 DEBUG(5,("create: %s ", ctime(&create_time)));
4438 DEBUG(5,("access: %s ", ctime(&atime)));
4439 DEBUG(5,("write: %s ", ctime(&mtime)));
4440 DEBUG(5,("change: %s ", ctime(&c_time)));
4441 DEBUG(5,("mode: %x\n", mode));
4444 case SMB_FILE_STANDARD_INFORMATION:
4445 case SMB_QUERY_FILE_STANDARD_INFO:
4447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4449 SOFF_T(pdata,0,allocation_size);
4450 SOFF_T(pdata,8,file_size);
4451 SIVAL(pdata,16,nlink);
4452 SCVAL(pdata,20,delete_pending?1:0);
4453 SCVAL(pdata,21,(mode&aDIR)?1:0);
4454 SSVAL(pdata,22,0); /* Padding. */
4457 case SMB_FILE_EA_INFORMATION:
4458 case SMB_QUERY_FILE_EA_INFO:
4460 unsigned int ea_size =
4461 estimate_ea_size(conn, fsp, smb_fname->base_name);
4462 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4464 SIVAL(pdata,0,ea_size);
4468 /* Get the 8.3 name - used if NT SMB was negotiated. */
4469 case SMB_QUERY_FILE_ALT_NAME_INFO:
4470 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4473 char mangled_name[13];
4474 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4475 if (!name_to_8_3(base_name,mangled_name,
4476 True,conn->params)) {
4477 return NT_STATUS_NO_MEMORY;
4479 len = srvstr_push(dstart, flags2,
4480 pdata+4, mangled_name,
4481 PTR_DIFF(dend, pdata+4),
4483 data_size = 4 + len;
4488 case SMB_QUERY_FILE_NAME_INFO:
4492 this must be *exactly* right for ACLs on mapped drives to work
4494 len = srvstr_push(dstart, flags2,
4496 PTR_DIFF(dend, pdata+4),
4498 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4499 data_size = 4 + len;
4504 case SMB_FILE_ALLOCATION_INFORMATION:
4505 case SMB_QUERY_FILE_ALLOCATION_INFO:
4506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4508 SOFF_T(pdata,0,allocation_size);
4511 case SMB_FILE_END_OF_FILE_INFORMATION:
4512 case SMB_QUERY_FILE_END_OF_FILEINFO:
4513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4515 SOFF_T(pdata,0,file_size);
4518 case SMB_QUERY_FILE_ALL_INFO:
4519 case SMB_FILE_ALL_INFORMATION:
4522 unsigned int ea_size =
4523 estimate_ea_size(conn, fsp, smb_fname->base_name);
4524 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4525 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4526 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4527 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4528 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4529 SIVAL(pdata,32,mode);
4530 SIVAL(pdata,36,0); /* padding. */
4532 SOFF_T(pdata,0,allocation_size);
4533 SOFF_T(pdata,8,file_size);
4534 SIVAL(pdata,16,nlink);
4535 SCVAL(pdata,20,delete_pending);
4536 SCVAL(pdata,21,(mode&aDIR)?1:0);
4539 SIVAL(pdata,0,ea_size);
4540 pdata += 4; /* EA info */
4541 len = srvstr_push(dstart, flags2,
4543 PTR_DIFF(dend, pdata+4),
4547 data_size = PTR_DIFF(pdata,(*ppdata));
4551 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4554 unsigned int ea_size =
4555 estimate_ea_size(conn, fsp, smb_fname->base_name);
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4557 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4558 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4559 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4560 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4561 SIVAL(pdata, 0x20, mode);
4562 SIVAL(pdata, 0x24, 0); /* padding. */
4563 SBVAL(pdata, 0x28, allocation_size);
4564 SBVAL(pdata, 0x30, file_size);
4565 SIVAL(pdata, 0x38, nlink);
4566 SCVAL(pdata, 0x3C, delete_pending);
4567 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4568 SSVAL(pdata, 0x3E, 0); /* padding */
4569 SBVAL(pdata, 0x40, file_index);
4570 SIVAL(pdata, 0x48, ea_size);
4571 SIVAL(pdata, 0x4C, access_mask);
4572 SBVAL(pdata, 0x50, pos);
4573 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4574 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4578 len = srvstr_push(dstart, flags2,
4580 PTR_DIFF(dend, pdata+4),
4584 data_size = PTR_DIFF(pdata,(*ppdata));
4587 case SMB_FILE_INTERNAL_INFORMATION:
4589 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4590 SBVAL(pdata, 0, file_index);
4594 case SMB_FILE_ACCESS_INFORMATION:
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4596 SIVAL(pdata, 0, access_mask);
4600 case SMB_FILE_NAME_INFORMATION:
4601 /* Pathname with leading '\'. */
4604 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4605 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4606 SIVAL(pdata,0,byte_len);
4607 data_size = 4 + byte_len;
4611 case SMB_FILE_DISPOSITION_INFORMATION:
4612 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4614 SCVAL(pdata,0,delete_pending);
4617 case SMB_FILE_POSITION_INFORMATION:
4618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4620 SOFF_T(pdata,0,pos);
4623 case SMB_FILE_MODE_INFORMATION:
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4625 SIVAL(pdata,0,mode);
4629 case SMB_FILE_ALIGNMENT_INFORMATION:
4630 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4631 SIVAL(pdata,0,0); /* No alignment needed. */
4636 * NT4 server just returns "invalid query" to this - if we try
4637 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4640 /* The first statement above is false - verified using Thursby
4641 * client against NT4 -- gcolley.
4643 case SMB_QUERY_FILE_STREAM_INFO:
4644 case SMB_FILE_STREAM_INFORMATION: {
4645 unsigned int num_streams;
4646 struct stream_struct *streams;
4648 DEBUG(10,("smbd_do_qfilepathinfo: "
4649 "SMB_FILE_STREAM_INFORMATION\n"));
4651 if (is_ntfs_stream_smb_fname(smb_fname)) {
4652 return NT_STATUS_INVALID_PARAMETER;
4655 status = SMB_VFS_STREAMINFO(
4656 conn, fsp, smb_fname->base_name, talloc_tos(),
4657 &num_streams, &streams);
4659 if (!NT_STATUS_IS_OK(status)) {
4660 DEBUG(10, ("could not get stream info: %s\n",
4661 nt_errstr(status)));
4665 status = marshall_stream_info(num_streams, streams,
4666 pdata, max_data_bytes,
4669 if (!NT_STATUS_IS_OK(status)) {
4670 DEBUG(10, ("marshall_stream_info failed: %s\n",
4671 nt_errstr(status)));
4675 TALLOC_FREE(streams);
4679 case SMB_QUERY_COMPRESSION_INFO:
4680 case SMB_FILE_COMPRESSION_INFORMATION:
4681 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4682 SOFF_T(pdata,0,file_size);
4683 SIVAL(pdata,8,0); /* ??? */
4684 SIVAL(pdata,12,0); /* ??? */
4688 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4689 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4690 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4691 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4692 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4693 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4694 SOFF_T(pdata,32,allocation_size);
4695 SOFF_T(pdata,40,file_size);
4696 SIVAL(pdata,48,mode);
4697 SIVAL(pdata,52,0); /* ??? */
4701 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4702 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4703 SIVAL(pdata,0,mode);
4709 * CIFS UNIX Extensions.
4712 case SMB_QUERY_FILE_UNIX_BASIC:
4714 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4715 data_size = PTR_DIFF(pdata,(*ppdata));
4719 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4721 for (i=0; i<100; i++)
4722 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4728 case SMB_QUERY_FILE_UNIX_INFO2:
4730 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4731 data_size = PTR_DIFF(pdata,(*ppdata));
4735 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4737 for (i=0; i<100; i++)
4738 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4744 case SMB_QUERY_FILE_UNIX_LINK:
4747 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4750 return NT_STATUS_NO_MEMORY;
4753 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4755 if(!S_ISLNK(psbuf->st_ex_mode)) {
4756 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4759 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4761 len = SMB_VFS_READLINK(conn,
4762 smb_fname->base_name,
4765 return map_nt_error_from_unix(errno);
4768 len = srvstr_push(dstart, flags2,
4770 PTR_DIFF(dend, pdata),
4773 data_size = PTR_DIFF(pdata,(*ppdata));
4778 #if defined(HAVE_POSIX_ACLS)
4779 case SMB_QUERY_POSIX_ACL:
4781 SMB_ACL_T file_acl = NULL;
4782 SMB_ACL_T def_acl = NULL;
4783 uint16 num_file_acls = 0;
4784 uint16 num_def_acls = 0;
4786 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4787 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4790 SMB_VFS_SYS_ACL_GET_FILE(conn,
4791 smb_fname->base_name,
4792 SMB_ACL_TYPE_ACCESS);
4795 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4796 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4797 "not implemented on "
4798 "filesystem containing %s\n",
4799 smb_fname->base_name));
4800 return NT_STATUS_NOT_IMPLEMENTED;
4803 if (S_ISDIR(psbuf->st_ex_mode)) {
4804 if (fsp && fsp->is_directory) {
4806 SMB_VFS_SYS_ACL_GET_FILE(
4808 fsp->fsp_name->base_name,
4809 SMB_ACL_TYPE_DEFAULT);
4812 SMB_VFS_SYS_ACL_GET_FILE(
4814 smb_fname->base_name,
4815 SMB_ACL_TYPE_DEFAULT);
4817 def_acl = free_empty_sys_acl(conn, def_acl);
4820 num_file_acls = count_acl_entries(conn, file_acl);
4821 num_def_acls = count_acl_entries(conn, def_acl);
4823 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4824 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4826 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4827 SMB_POSIX_ACL_HEADER_SIZE) ));
4829 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4832 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4834 return NT_STATUS_BUFFER_TOO_SMALL;
4837 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4838 SSVAL(pdata,2,num_file_acls);
4839 SSVAL(pdata,4,num_def_acls);
4840 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4842 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4845 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4847 return NT_STATUS_INTERNAL_ERROR;
4849 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4851 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4854 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4856 return NT_STATUS_INTERNAL_ERROR;
4860 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4863 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4865 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4871 case SMB_QUERY_POSIX_LOCK:
4876 enum brl_type lock_type;
4878 /* We need an open file with a real fd for this. */
4879 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4880 return NT_STATUS_INVALID_LEVEL;
4883 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4884 return NT_STATUS_INVALID_PARAMETER;
4887 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4888 case POSIX_LOCK_TYPE_READ:
4889 lock_type = READ_LOCK;
4891 case POSIX_LOCK_TYPE_WRITE:
4892 lock_type = WRITE_LOCK;
4894 case POSIX_LOCK_TYPE_UNLOCK:
4896 /* There's no point in asking for an unlock... */
4897 return NT_STATUS_INVALID_PARAMETER;
4900 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4901 #if defined(HAVE_LONGLONG)
4902 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4903 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4904 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4905 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4906 #else /* HAVE_LONGLONG */
4907 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4908 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4909 #endif /* HAVE_LONGLONG */
4911 status = query_lock(fsp,
4918 if (ERROR_WAS_LOCK_DENIED(status)) {
4919 /* Here we need to report who has it locked... */
4920 data_size = POSIX_LOCK_DATA_SIZE;
4922 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4923 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4924 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4925 #if defined(HAVE_LONGLONG)
4926 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4927 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4928 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4929 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4930 #else /* HAVE_LONGLONG */
4931 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4932 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4933 #endif /* HAVE_LONGLONG */
4935 } else if (NT_STATUS_IS_OK(status)) {
4936 /* For success we just return a copy of what we sent
4937 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4938 data_size = POSIX_LOCK_DATA_SIZE;
4939 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4940 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4948 return NT_STATUS_INVALID_LEVEL;
4951 *pdata_size = data_size;
4952 return NT_STATUS_OK;
4955 /****************************************************************************
4956 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4957 file name or file id).
4958 ****************************************************************************/
4960 static void call_trans2qfilepathinfo(connection_struct *conn,
4961 struct smb_request *req,
4962 unsigned int tran_call,
4963 char **pparams, int total_params,
4964 char **ppdata, int total_data,
4965 unsigned int max_data_bytes)
4967 char *params = *pparams;
4968 char *pdata = *ppdata;
4970 unsigned int data_size = 0;
4971 unsigned int param_size = 2;
4972 struct smb_filename *smb_fname = NULL;
4973 bool delete_pending = False;
4974 struct timespec write_time_ts;
4975 files_struct *fsp = NULL;
4976 struct file_id fileid;
4977 struct ea_list *ea_list = NULL;
4978 int lock_data_count = 0;
4979 char *lock_data = NULL;
4980 bool ms_dfs_link = false;
4981 NTSTATUS status = NT_STATUS_OK;
4984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4988 ZERO_STRUCT(write_time_ts);
4990 if (tran_call == TRANSACT2_QFILEINFO) {
4991 if (total_params < 4) {
4992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4997 call_trans2qpipeinfo(conn, req, tran_call,
4998 pparams, total_params,
5004 fsp = file_fsp(req, SVAL(params,0));
5005 info_level = SVAL(params,2);
5007 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5009 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5010 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5014 /* Initial check for valid fsp ptr. */
5015 if (!check_fsp_open(conn, req, fsp)) {
5019 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5021 if (!NT_STATUS_IS_OK(status)) {
5022 reply_nterror(req, status);
5026 if(fsp->fake_file_handle) {
5028 * This is actually for the QUOTA_FAKE_FILE --metze
5031 /* We know this name is ok, it's already passed the checks. */
5033 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5035 * This is actually a QFILEINFO on a directory
5036 * handle (returned from an NT SMB). NT5.0 seems
5037 * to do this call. JRA.
5040 if (INFO_LEVEL_IS_UNIX(info_level)) {
5041 /* Always do lstat for UNIX calls. */
5042 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5043 DEBUG(3,("call_trans2qfilepathinfo: "
5044 "SMB_VFS_LSTAT of %s failed "
5046 smb_fname_str_dbg(smb_fname),
5049 map_nt_error_from_unix(errno));
5052 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5053 DEBUG(3,("call_trans2qfilepathinfo: "
5054 "SMB_VFS_STAT of %s failed (%s)\n",
5055 smb_fname_str_dbg(smb_fname),
5058 map_nt_error_from_unix(errno));
5062 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5063 get_file_infos(fileid, &delete_pending, &write_time_ts);
5066 * Original code - this is an open file.
5068 if (!check_fsp(conn, req, fsp)) {
5072 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5073 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5074 fsp->fnum, strerror(errno)));
5076 map_nt_error_from_unix(errno));
5079 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5080 get_file_infos(fileid, &delete_pending, &write_time_ts);
5087 if (total_params < 7) {
5088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5092 info_level = SVAL(params,0);
5094 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5096 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5097 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5101 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5103 STR_TERMINATE, &status);
5104 if (!NT_STATUS_IS_OK(status)) {
5105 reply_nterror(req, status);
5109 status = filename_convert(req,
5111 req->flags2 & FLAGS2_DFS_PATHNAMES,
5116 if (!NT_STATUS_IS_OK(status)) {
5117 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5118 reply_botherror(req,
5119 NT_STATUS_PATH_NOT_COVERED,
5120 ERRSRV, ERRbadpath);
5123 reply_nterror(req, status);
5127 /* If this is a stream, check if there is a delete_pending. */
5128 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5129 && is_ntfs_stream_smb_fname(smb_fname)) {
5130 struct smb_filename *smb_fname_base = NULL;
5132 /* Create an smb_filename with stream_name == NULL. */
5134 create_synthetic_smb_fname(talloc_tos(),
5135 smb_fname->base_name,
5138 if (!NT_STATUS_IS_OK(status)) {
5139 reply_nterror(req, status);
5143 if (INFO_LEVEL_IS_UNIX(info_level)) {
5144 /* Always do lstat for UNIX calls. */
5145 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5146 DEBUG(3,("call_trans2qfilepathinfo: "
5147 "SMB_VFS_LSTAT of %s failed "
5149 smb_fname_str_dbg(smb_fname_base),
5151 TALLOC_FREE(smb_fname_base);
5153 map_nt_error_from_unix(errno));
5157 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5158 DEBUG(3,("call_trans2qfilepathinfo: "
5159 "fileinfo of %s failed "
5161 smb_fname_str_dbg(smb_fname_base),
5163 TALLOC_FREE(smb_fname_base);
5165 map_nt_error_from_unix(errno));
5170 fileid = vfs_file_id_from_sbuf(conn,
5171 &smb_fname_base->st);
5172 TALLOC_FREE(smb_fname_base);
5173 get_file_infos(fileid, &delete_pending, NULL);
5174 if (delete_pending) {
5175 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5180 if (INFO_LEVEL_IS_UNIX(info_level)) {
5181 /* Always do lstat for UNIX calls. */
5182 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5183 DEBUG(3,("call_trans2qfilepathinfo: "
5184 "SMB_VFS_LSTAT of %s failed (%s)\n",
5185 smb_fname_str_dbg(smb_fname),
5188 map_nt_error_from_unix(errno));
5192 } else if (!VALID_STAT(smb_fname->st) &&
5193 SMB_VFS_STAT(conn, smb_fname) &&
5194 (info_level != SMB_INFO_IS_NAME_VALID)) {
5195 ms_dfs_link = check_msdfs_link(conn,
5196 smb_fname->base_name,
5200 DEBUG(3,("call_trans2qfilepathinfo: "
5201 "SMB_VFS_STAT of %s failed (%s)\n",
5202 smb_fname_str_dbg(smb_fname),
5205 map_nt_error_from_unix(errno));
5210 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5211 get_file_infos(fileid, &delete_pending, &write_time_ts);
5212 if (delete_pending) {
5213 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5218 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5219 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5220 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5222 /* Pull out any data sent here before we realloc. */
5223 switch (info_level) {
5224 case SMB_INFO_QUERY_EAS_FROM_LIST:
5226 /* Pull any EA list from the data portion. */
5229 if (total_data < 4) {
5231 req, NT_STATUS_INVALID_PARAMETER);
5234 ea_size = IVAL(pdata,0);
5236 if (total_data > 0 && ea_size != total_data) {
5237 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5238 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5240 req, NT_STATUS_INVALID_PARAMETER);
5244 if (!lp_ea_support(SNUM(conn))) {
5245 reply_doserror(req, ERRDOS,
5246 ERReasnotsupported);
5250 /* Pull out the list of names. */
5251 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5254 req, NT_STATUS_INVALID_PARAMETER);
5260 case SMB_QUERY_POSIX_LOCK:
5262 if (fsp == NULL || fsp->fh->fd == -1) {
5263 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5267 if (total_data != POSIX_LOCK_DATA_SIZE) {
5269 req, NT_STATUS_INVALID_PARAMETER);
5273 /* Copy the lock range data. */
5274 lock_data = (char *)TALLOC_MEMDUP(
5275 req, pdata, total_data);
5277 reply_nterror(req, NT_STATUS_NO_MEMORY);
5280 lock_data_count = total_data;
5286 *pparams = (char *)SMB_REALLOC(*pparams,2);
5287 if (*pparams == NULL) {
5288 reply_nterror(req, NT_STATUS_NO_MEMORY);
5295 * draft-leach-cifs-v1-spec-02.txt
5296 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5299 * The requested information is placed in the Data portion of the
5300 * transaction response. For the information levels greater than 0x100,
5301 * the transaction response has 1 parameter word which should be
5302 * ignored by the client.
5304 * However Windows only follows this rule for the IS_NAME_VALID call.
5306 switch (info_level) {
5307 case SMB_INFO_IS_NAME_VALID:
5312 if ((info_level & 0xFF00) == 0xFF00) {
5314 * We use levels that start with 0xFF00
5315 * internally to represent SMB2 specific levels
5317 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5321 status = smbd_do_qfilepathinfo(conn, req, info_level,
5323 delete_pending, write_time_ts,
5324 ms_dfs_link, ea_list,
5325 lock_data_count, lock_data,
5326 req->flags2, max_data_bytes,
5327 ppdata, &data_size);
5328 if (!NT_STATUS_IS_OK(status)) {
5329 reply_nterror(req, status);
5333 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5339 /****************************************************************************
5340 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5342 ****************************************************************************/
5344 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5345 connection_struct *conn,
5346 const struct smb_filename *smb_fname_old,
5347 const struct smb_filename *smb_fname_new)
5349 NTSTATUS status = NT_STATUS_OK;
5351 /* source must already exist. */
5352 if (!VALID_STAT(smb_fname_old->st)) {
5353 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5356 /* Disallow if newname already exists. */
5357 if (VALID_STAT(smb_fname_new->st)) {
5358 return NT_STATUS_OBJECT_NAME_COLLISION;
5361 /* No links from a directory. */
5362 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5363 return NT_STATUS_FILE_IS_A_DIRECTORY;
5366 /* Setting a hardlink to/from a stream isn't currently supported. */
5367 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5368 is_ntfs_stream_smb_fname(smb_fname_new)) {
5369 return NT_STATUS_INVALID_PARAMETER;
5372 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5373 smb_fname_old->base_name, smb_fname_new->base_name));
5375 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5376 smb_fname_new->base_name) != 0) {
5377 status = map_nt_error_from_unix(errno);
5378 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5379 nt_errstr(status), smb_fname_old->base_name,
5380 smb_fname_new->base_name));
5385 /****************************************************************************
5386 Deal with setting the time from any of the setfilepathinfo functions.
5387 ****************************************************************************/
5389 NTSTATUS smb_set_file_time(connection_struct *conn,
5391 const struct smb_filename *smb_fname,
5392 struct smb_file_time *ft,
5393 bool setting_write_time)
5395 struct smb_filename *smb_fname_base = NULL;
5397 FILE_NOTIFY_CHANGE_LAST_ACCESS
5398 |FILE_NOTIFY_CHANGE_LAST_WRITE
5399 |FILE_NOTIFY_CHANGE_CREATION;
5402 if (!VALID_STAT(smb_fname->st)) {
5403 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5406 /* get some defaults (no modifications) if any info is zero or -1. */
5407 if (null_timespec(ft->create_time)) {
5408 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5411 if (null_timespec(ft->atime)) {
5412 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5415 if (null_timespec(ft->mtime)) {
5416 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5419 if (!setting_write_time) {
5420 /* ft->mtime comes from change time, not write time. */
5421 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5424 /* Ensure the resolution is the correct for
5425 * what we can store on this filesystem. */
5427 round_timespec(conn->ts_res, &ft->create_time);
5428 round_timespec(conn->ts_res, &ft->ctime);
5429 round_timespec(conn->ts_res, &ft->atime);
5430 round_timespec(conn->ts_res, &ft->mtime);
5432 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5433 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5434 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5435 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5436 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5437 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5438 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5439 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5441 if (setting_write_time) {
5443 * This was a Windows setfileinfo on an open file.
5444 * NT does this a lot. We also need to
5445 * set the time here, as it can be read by
5446 * FindFirst/FindNext and with the patch for bug #2045
5447 * in smbd/fileio.c it ensures that this timestamp is
5448 * kept sticky even after a write. We save the request
5449 * away and will set it on file close and after a write. JRA.
5452 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5453 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5456 if (fsp->base_fsp) {
5457 set_sticky_write_time_fsp(fsp->base_fsp,
5460 set_sticky_write_time_fsp(fsp, ft->mtime);
5463 set_sticky_write_time_path(
5464 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5469 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5471 /* Always call ntimes on the base, even if a stream was passed in. */
5472 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5473 NULL, &smb_fname->st,
5475 if (!NT_STATUS_IS_OK(status)) {
5479 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5480 TALLOC_FREE(smb_fname_base);
5481 return map_nt_error_from_unix(errno);
5483 TALLOC_FREE(smb_fname_base);
5485 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5486 smb_fname->base_name);
5487 return NT_STATUS_OK;
5490 /****************************************************************************
5491 Deal with setting the dosmode from any of the setfilepathinfo functions.
5492 ****************************************************************************/
5494 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5495 const struct smb_filename *smb_fname,
5498 struct smb_filename *smb_fname_base = NULL;
5501 if (!VALID_STAT(smb_fname->st)) {
5502 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5505 /* Always operate on the base_name, even if a stream was passed in. */
5506 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5507 NULL, &smb_fname->st,
5509 if (!NT_STATUS_IS_OK(status)) {
5514 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5521 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5523 /* check the mode isn't different, before changing it */
5524 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5525 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5526 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5527 (unsigned int)dosmode));
5529 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5531 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5533 smb_fname_str_dbg(smb_fname_base),
5535 status = map_nt_error_from_unix(errno);
5539 status = NT_STATUS_OK;
5541 TALLOC_FREE(smb_fname_base);
5545 /****************************************************************************
5546 Deal with setting the size from any of the setfilepathinfo functions.
5547 ****************************************************************************/
5549 static NTSTATUS smb_set_file_size(connection_struct *conn,
5550 struct smb_request *req,
5552 const struct smb_filename *smb_fname,
5553 const SMB_STRUCT_STAT *psbuf,
5556 NTSTATUS status = NT_STATUS_OK;
5557 struct smb_filename *smb_fname_tmp = NULL;
5558 files_struct *new_fsp = NULL;
5560 if (!VALID_STAT(*psbuf)) {
5561 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5564 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5566 if (size == get_file_size_stat(psbuf)) {
5567 return NT_STATUS_OK;
5570 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5571 smb_fname_str_dbg(smb_fname), (double)size));
5573 if (fsp && fsp->fh->fd != -1) {
5574 /* Handle based call. */
5575 if (vfs_set_filelen(fsp, size) == -1) {
5576 return map_nt_error_from_unix(errno);
5578 trigger_write_time_update_immediate(fsp);
5579 return NT_STATUS_OK;
5582 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5583 if (!NT_STATUS_IS_OK(status)) {
5587 smb_fname_tmp->st = *psbuf;
5589 status = SMB_VFS_CREATE_FILE(
5592 0, /* root_dir_fid */
5593 smb_fname_tmp, /* fname */
5594 FILE_WRITE_ATTRIBUTES, /* access_mask */
5595 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5597 FILE_OPEN, /* create_disposition*/
5598 0, /* create_options */
5599 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5600 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5601 0, /* allocation_size */
5604 &new_fsp, /* result */
5607 TALLOC_FREE(smb_fname_tmp);
5609 if (!NT_STATUS_IS_OK(status)) {
5610 /* NB. We check for open_was_deferred in the caller. */
5614 if (vfs_set_filelen(new_fsp, size) == -1) {
5615 status = map_nt_error_from_unix(errno);
5616 close_file(req, new_fsp,NORMAL_CLOSE);
5620 trigger_write_time_update_immediate(new_fsp);
5621 close_file(req, new_fsp,NORMAL_CLOSE);
5622 return NT_STATUS_OK;
5625 /****************************************************************************
5626 Deal with SMB_INFO_SET_EA.
5627 ****************************************************************************/
5629 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5633 const struct smb_filename *smb_fname)
5635 struct ea_list *ea_list = NULL;
5636 TALLOC_CTX *ctx = NULL;
5637 NTSTATUS status = NT_STATUS_OK;
5639 if (total_data < 10) {
5641 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5642 length. They seem to have no effect. Bug #3212. JRA */
5644 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5645 /* We're done. We only get EA info in this call. */
5646 return NT_STATUS_OK;
5649 return NT_STATUS_INVALID_PARAMETER;
5652 if (IVAL(pdata,0) > total_data) {
5653 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5654 IVAL(pdata,0), (unsigned int)total_data));
5655 return NT_STATUS_INVALID_PARAMETER;
5659 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5661 return NT_STATUS_INVALID_PARAMETER;
5663 status = set_ea(conn, fsp, smb_fname, ea_list);
5668 /****************************************************************************
5669 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5670 ****************************************************************************/
5672 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5677 struct ea_list *ea_list = NULL;
5681 return NT_STATUS_INVALID_HANDLE;
5684 if (!lp_ea_support(SNUM(conn))) {
5685 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5686 "EA's not supported.\n",
5687 (unsigned int)total_data));
5688 return NT_STATUS_EAS_NOT_SUPPORTED;
5691 if (total_data < 10) {
5692 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5694 (unsigned int)total_data));
5695 return NT_STATUS_INVALID_PARAMETER;
5698 ea_list = read_nttrans_ea_list(talloc_tos(),
5703 return NT_STATUS_INVALID_PARAMETER;
5705 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5707 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5708 smb_fname_str_dbg(fsp->fsp_name),
5709 nt_errstr(status) ));
5715 /****************************************************************************
5716 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5717 ****************************************************************************/
5719 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5723 struct smb_filename *smb_fname)
5725 NTSTATUS status = NT_STATUS_OK;
5726 bool delete_on_close;
5729 if (total_data < 1) {
5730 return NT_STATUS_INVALID_PARAMETER;
5734 return NT_STATUS_INVALID_HANDLE;
5737 delete_on_close = (CVAL(pdata,0) ? True : False);
5738 dosmode = dos_mode(conn, smb_fname);
5740 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5741 "delete_on_close = %u\n",
5742 smb_fname_str_dbg(smb_fname),
5743 (unsigned int)dosmode,
5744 (unsigned int)delete_on_close ));
5746 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5748 if (!NT_STATUS_IS_OK(status)) {
5752 /* The set is across all open files on this dev/inode pair. */
5753 if (!set_delete_on_close(fsp, delete_on_close,
5754 &conn->server_info->utok)) {
5755 return NT_STATUS_ACCESS_DENIED;
5757 return NT_STATUS_OK;
5760 /****************************************************************************
5761 Deal with SMB_FILE_POSITION_INFORMATION.
5762 ****************************************************************************/
5764 static NTSTATUS smb_file_position_information(connection_struct *conn,
5769 uint64_t position_information;
5771 if (total_data < 8) {
5772 return NT_STATUS_INVALID_PARAMETER;
5776 /* Ignore on pathname based set. */
5777 return NT_STATUS_OK;
5780 position_information = (uint64_t)IVAL(pdata,0);
5781 #ifdef LARGE_SMB_OFF_T
5782 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5783 #else /* LARGE_SMB_OFF_T */
5784 if (IVAL(pdata,4) != 0) {
5785 /* more than 32 bits? */
5786 return NT_STATUS_INVALID_PARAMETER;
5788 #endif /* LARGE_SMB_OFF_T */
5790 DEBUG(10,("smb_file_position_information: Set file position "
5791 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5792 (double)position_information));
5793 fsp->fh->position_information = position_information;
5794 return NT_STATUS_OK;
5797 /****************************************************************************
5798 Deal with SMB_FILE_MODE_INFORMATION.
5799 ****************************************************************************/
5801 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5807 if (total_data < 4) {
5808 return NT_STATUS_INVALID_PARAMETER;
5810 mode = IVAL(pdata,0);
5811 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5812 return NT_STATUS_INVALID_PARAMETER;
5814 return NT_STATUS_OK;
5817 /****************************************************************************
5818 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5819 ****************************************************************************/
5821 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5822 struct smb_request *req,
5825 const struct smb_filename *smb_fname)
5827 char *link_target = NULL;
5828 const char *newname = smb_fname->base_name;
5829 NTSTATUS status = NT_STATUS_OK;
5830 TALLOC_CTX *ctx = talloc_tos();
5832 /* Set a symbolic link. */
5833 /* Don't allow this if follow links is false. */
5835 if (total_data == 0) {
5836 return NT_STATUS_INVALID_PARAMETER;
5839 if (!lp_symlinks(SNUM(conn))) {
5840 return NT_STATUS_ACCESS_DENIED;
5843 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5844 total_data, STR_TERMINATE);
5847 return NT_STATUS_INVALID_PARAMETER;
5850 /* !widelinks forces the target path to be within the share. */
5851 /* This means we can interpret the target as a pathname. */
5852 if (!lp_widelinks(SNUM(conn))) {
5853 char *rel_name = NULL;
5854 char *last_dirp = NULL;
5856 if (*link_target == '/') {
5857 /* No absolute paths allowed. */
5858 return NT_STATUS_ACCESS_DENIED;
5860 rel_name = talloc_strdup(ctx,newname);
5862 return NT_STATUS_NO_MEMORY;
5864 last_dirp = strrchr_m(rel_name, '/');
5866 last_dirp[1] = '\0';
5868 rel_name = talloc_strdup(ctx,"./");
5870 return NT_STATUS_NO_MEMORY;
5873 rel_name = talloc_asprintf_append(rel_name,
5877 return NT_STATUS_NO_MEMORY;
5880 status = check_name(conn, rel_name);
5881 if (!NT_STATUS_IS_OK(status)) {
5886 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5887 newname, link_target ));
5889 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5890 return map_nt_error_from_unix(errno);
5893 return NT_STATUS_OK;
5896 /****************************************************************************
5897 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5898 ****************************************************************************/
5900 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5901 struct smb_request *req,
5902 const char *pdata, int total_data,
5903 const struct smb_filename *smb_fname_new)
5905 char *oldname = NULL;
5906 struct smb_filename *smb_fname_old = NULL;
5907 TALLOC_CTX *ctx = talloc_tos();
5908 NTSTATUS status = NT_STATUS_OK;
5910 /* Set a hard link. */
5911 if (total_data == 0) {
5912 return NT_STATUS_INVALID_PARAMETER;
5915 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5916 total_data, STR_TERMINATE, &status);
5917 if (!NT_STATUS_IS_OK(status)) {
5921 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5922 smb_fname_str_dbg(smb_fname_new), oldname));
5924 status = filename_convert(ctx,
5926 req->flags2 & FLAGS2_DFS_PATHNAMES,
5931 if (!NT_STATUS_IS_OK(status)) {
5935 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5938 /****************************************************************************
5939 Deal with SMB_FILE_RENAME_INFORMATION.
5940 ****************************************************************************/
5942 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5943 struct smb_request *req,
5947 struct smb_filename *smb_fname_src)
5952 char *newname = NULL;
5953 struct smb_filename *smb_fname_dst = NULL;
5954 bool dest_has_wcard = False;
5955 NTSTATUS status = NT_STATUS_OK;
5957 TALLOC_CTX *ctx = talloc_tos();
5959 if (total_data < 13) {
5960 return NT_STATUS_INVALID_PARAMETER;
5963 overwrite = (CVAL(pdata,0) ? True : False);
5964 root_fid = IVAL(pdata,4);
5965 len = IVAL(pdata,8);
5967 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5968 return NT_STATUS_INVALID_PARAMETER;
5971 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5974 if (!NT_STATUS_IS_OK(status)) {
5978 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5981 status = resolve_dfspath_wcard(ctx, conn,
5982 req->flags2 & FLAGS2_DFS_PATHNAMES,
5986 if (!NT_STATUS_IS_OK(status)) {
5990 /* Check the new name has no '/' characters. */
5991 if (strchr_m(newname, '/')) {
5992 return NT_STATUS_NOT_SUPPORTED;
5995 if (fsp && fsp->base_fsp) {
5996 /* newname must be a stream name. */
5997 if (newname[0] != ':') {
5998 return NT_STATUS_NOT_SUPPORTED;
6001 /* Create an smb_fname to call rename_internals_fsp() with. */
6002 status = create_synthetic_smb_fname(talloc_tos(),
6003 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6005 if (!NT_STATUS_IS_OK(status)) {
6010 * Set the original last component, since
6011 * rename_internals_fsp() requires it.
6013 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6015 if (smb_fname_dst->original_lcomp == NULL) {
6016 status = NT_STATUS_NO_MEMORY;
6022 * Build up an smb_fname_dst based on the filename passed in.
6023 * We basically just strip off the last component, and put on
6024 * the newname instead.
6026 char *base_name = NULL;
6028 /* newname must *not* be a stream name. */
6029 if (newname[0] == ':') {
6030 return NT_STATUS_NOT_SUPPORTED;
6034 * Strip off the last component (filename) of the path passed
6037 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6039 return NT_STATUS_NO_MEMORY;
6041 p = strrchr_m(base_name, '/');
6045 base_name = talloc_strdup(ctx, "./");
6047 return NT_STATUS_NO_MEMORY;
6050 /* Append the new name. */
6051 base_name = talloc_asprintf_append(base_name,
6055 return NT_STATUS_NO_MEMORY;
6058 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6061 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6064 /* If an error we expect this to be
6065 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6067 if (!NT_STATUS_IS_OK(status)) {
6068 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6072 /* Create an smb_fname to call rename_internals_fsp() */
6073 status = create_synthetic_smb_fname(ctx,
6077 if (!NT_STATUS_IS_OK(status)) {
6084 DEBUG(10,("smb_file_rename_information: "
6085 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6086 fsp->fnum, fsp_str_dbg(fsp),
6087 smb_fname_str_dbg(smb_fname_dst)));
6088 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6091 DEBUG(10,("smb_file_rename_information: "
6092 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6093 smb_fname_str_dbg(smb_fname_src),
6094 smb_fname_str_dbg(smb_fname_dst)));
6095 status = rename_internals(ctx, conn, req, smb_fname_src,
6096 smb_fname_dst, 0, overwrite, false,
6098 FILE_WRITE_ATTRIBUTES);
6101 TALLOC_FREE(smb_fname_dst);
6105 /****************************************************************************
6106 Deal with SMB_SET_POSIX_ACL.
6107 ****************************************************************************/
6109 #if defined(HAVE_POSIX_ACLS)
6110 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6114 const struct smb_filename *smb_fname)
6116 uint16 posix_acl_version;
6117 uint16 num_file_acls;
6118 uint16 num_def_acls;
6119 bool valid_file_acls = True;
6120 bool valid_def_acls = True;
6122 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6123 return NT_STATUS_INVALID_PARAMETER;
6125 posix_acl_version = SVAL(pdata,0);
6126 num_file_acls = SVAL(pdata,2);
6127 num_def_acls = SVAL(pdata,4);
6129 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6130 valid_file_acls = False;
6134 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6135 valid_def_acls = False;
6139 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6140 return NT_STATUS_INVALID_PARAMETER;
6143 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6144 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6145 return NT_STATUS_INVALID_PARAMETER;
6148 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6149 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6150 (unsigned int)num_file_acls,
6151 (unsigned int)num_def_acls));
6153 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6154 smb_fname->base_name, num_file_acls,
6155 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6156 return map_nt_error_from_unix(errno);
6159 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6160 smb_fname->base_name, &smb_fname->st, num_def_acls,
6161 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6162 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6163 return map_nt_error_from_unix(errno);
6165 return NT_STATUS_OK;
6169 /****************************************************************************
6170 Deal with SMB_SET_POSIX_LOCK.
6171 ****************************************************************************/
6173 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6174 struct smb_request *req,
6182 bool blocking_lock = False;
6183 enum brl_type lock_type;
6185 NTSTATUS status = NT_STATUS_OK;
6187 if (fsp == NULL || fsp->fh->fd == -1) {
6188 return NT_STATUS_INVALID_HANDLE;
6191 if (total_data != POSIX_LOCK_DATA_SIZE) {
6192 return NT_STATUS_INVALID_PARAMETER;
6195 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6196 case POSIX_LOCK_TYPE_READ:
6197 lock_type = READ_LOCK;
6199 case POSIX_LOCK_TYPE_WRITE:
6200 /* Return the right POSIX-mappable error code for files opened read-only. */
6201 if (!fsp->can_write) {
6202 return NT_STATUS_INVALID_HANDLE;
6204 lock_type = WRITE_LOCK;
6206 case POSIX_LOCK_TYPE_UNLOCK:
6207 lock_type = UNLOCK_LOCK;
6210 return NT_STATUS_INVALID_PARAMETER;
6213 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6214 blocking_lock = False;
6215 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6216 blocking_lock = True;
6218 return NT_STATUS_INVALID_PARAMETER;
6221 if (!lp_blocking_locks(SNUM(conn))) {
6222 blocking_lock = False;
6225 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6226 #if defined(HAVE_LONGLONG)
6227 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6228 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6229 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6230 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6231 #else /* HAVE_LONGLONG */
6232 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6233 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6234 #endif /* HAVE_LONGLONG */
6236 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6237 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6239 (unsigned int)lock_type,
6240 (unsigned int)lock_pid,
6244 if (lock_type == UNLOCK_LOCK) {
6245 status = do_unlock(smbd_messaging_context(),
6252 uint32 block_smbpid;
6254 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6266 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6268 * A blocking lock was requested. Package up
6269 * this smb into a queued request and push it
6270 * onto the blocking lock queue.
6272 if(push_blocking_lock_request(br_lck,
6275 -1, /* infinite timeout. */
6283 TALLOC_FREE(br_lck);
6287 TALLOC_FREE(br_lck);
6293 /****************************************************************************
6294 Deal with SMB_SET_FILE_BASIC_INFO.
6295 ****************************************************************************/
6297 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6301 const struct smb_filename *smb_fname)
6303 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6304 struct smb_file_time ft;
6306 NTSTATUS status = NT_STATUS_OK;
6310 if (total_data < 36) {
6311 return NT_STATUS_INVALID_PARAMETER;
6314 /* Set the attributes */
6315 dosmode = IVAL(pdata,32);
6316 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6317 if (!NT_STATUS_IS_OK(status)) {
6322 ft.create_time = interpret_long_date(pdata);
6325 ft.atime = interpret_long_date(pdata+8);
6328 ft.mtime = interpret_long_date(pdata+16);
6331 ft.ctime = interpret_long_date(pdata+24);
6333 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6334 smb_fname_str_dbg(smb_fname)));
6336 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6340 /****************************************************************************
6341 Deal with SMB_INFO_STANDARD.
6342 ****************************************************************************/
6344 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6348 const struct smb_filename *smb_fname)
6350 struct smb_file_time ft;
6354 if (total_data < 12) {
6355 return NT_STATUS_INVALID_PARAMETER;
6359 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6361 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6363 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6365 DEBUG(10,("smb_set_info_standard: file %s\n",
6366 smb_fname_str_dbg(smb_fname)));
6368 return smb_set_file_time(conn,
6375 /****************************************************************************
6376 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6377 ****************************************************************************/
6379 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6380 struct smb_request *req,
6384 struct smb_filename *smb_fname)
6386 uint64_t allocation_size = 0;
6387 NTSTATUS status = NT_STATUS_OK;
6388 files_struct *new_fsp = NULL;
6390 if (!VALID_STAT(smb_fname->st)) {
6391 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6394 if (total_data < 8) {
6395 return NT_STATUS_INVALID_PARAMETER;
6398 allocation_size = (uint64_t)IVAL(pdata,0);
6399 #ifdef LARGE_SMB_OFF_T
6400 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6401 #else /* LARGE_SMB_OFF_T */
6402 if (IVAL(pdata,4) != 0) {
6403 /* more than 32 bits? */
6404 return NT_STATUS_INVALID_PARAMETER;
6406 #endif /* LARGE_SMB_OFF_T */
6408 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6409 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6410 (double)allocation_size));
6412 if (allocation_size) {
6413 allocation_size = smb_roundup(conn, allocation_size);
6416 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6417 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6418 (double)allocation_size));
6420 if (fsp && fsp->fh->fd != -1) {
6421 /* Open file handle. */
6422 /* Only change if needed. */
6423 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6424 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6425 return map_nt_error_from_unix(errno);
6428 /* But always update the time. */
6430 * This is equivalent to a write. Ensure it's seen immediately
6431 * if there are no pending writes.
6433 trigger_write_time_update_immediate(fsp);
6434 return NT_STATUS_OK;
6437 /* Pathname or stat or directory file. */
6438 status = SMB_VFS_CREATE_FILE(
6441 0, /* root_dir_fid */
6442 smb_fname, /* fname */
6443 FILE_WRITE_DATA, /* access_mask */
6444 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6446 FILE_OPEN, /* create_disposition*/
6447 0, /* create_options */
6448 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6449 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6450 0, /* allocation_size */
6453 &new_fsp, /* result */
6456 if (!NT_STATUS_IS_OK(status)) {
6457 /* NB. We check for open_was_deferred in the caller. */
6461 /* Only change if needed. */
6462 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6463 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6464 status = map_nt_error_from_unix(errno);
6465 close_file(req, new_fsp, NORMAL_CLOSE);
6470 /* Changing the allocation size should set the last mod time. */
6472 * This is equivalent to a write. Ensure it's seen immediately
6473 * if there are no pending writes.
6475 trigger_write_time_update_immediate(new_fsp);
6477 close_file(req, new_fsp, NORMAL_CLOSE);
6478 return NT_STATUS_OK;
6481 /****************************************************************************
6482 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6483 ****************************************************************************/
6485 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6486 struct smb_request *req,
6490 const struct smb_filename *smb_fname)
6494 if (total_data < 8) {
6495 return NT_STATUS_INVALID_PARAMETER;
6498 size = IVAL(pdata,0);
6499 #ifdef LARGE_SMB_OFF_T
6500 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6501 #else /* LARGE_SMB_OFF_T */
6502 if (IVAL(pdata,4) != 0) {
6503 /* more than 32 bits? */
6504 return NT_STATUS_INVALID_PARAMETER;
6506 #endif /* LARGE_SMB_OFF_T */
6507 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6508 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6511 return smb_set_file_size(conn, req,
6518 /****************************************************************************
6519 Allow a UNIX info mknod.
6520 ****************************************************************************/
6522 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6525 const struct smb_filename *smb_fname)
6527 uint32 file_type = IVAL(pdata,56);
6528 #if defined(HAVE_MAKEDEV)
6529 uint32 dev_major = IVAL(pdata,60);
6530 uint32 dev_minor = IVAL(pdata,68);
6532 SMB_DEV_T dev = (SMB_DEV_T)0;
6533 uint32 raw_unixmode = IVAL(pdata,84);
6537 if (total_data < 100) {
6538 return NT_STATUS_INVALID_PARAMETER;
6541 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6542 PERM_NEW_FILE, &unixmode);
6543 if (!NT_STATUS_IS_OK(status)) {
6547 #if defined(HAVE_MAKEDEV)
6548 dev = makedev(dev_major, dev_minor);
6551 switch (file_type) {
6552 #if defined(S_IFIFO)
6553 case UNIX_TYPE_FIFO:
6554 unixmode |= S_IFIFO;
6557 #if defined(S_IFSOCK)
6558 case UNIX_TYPE_SOCKET:
6559 unixmode |= S_IFSOCK;
6562 #if defined(S_IFCHR)
6563 case UNIX_TYPE_CHARDEV:
6564 unixmode |= S_IFCHR;
6567 #if defined(S_IFBLK)
6568 case UNIX_TYPE_BLKDEV:
6569 unixmode |= S_IFBLK;
6573 return NT_STATUS_INVALID_PARAMETER;
6576 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6577 "%.0f mode 0%o for file %s\n", (double)dev,
6578 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6580 /* Ok - do the mknod. */
6581 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6582 return map_nt_error_from_unix(errno);
6585 /* If any of the other "set" calls fail we
6586 * don't want to end up with a half-constructed mknod.
6589 if (lp_inherit_perms(SNUM(conn))) {
6591 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6593 return NT_STATUS_NO_MEMORY;
6595 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6597 TALLOC_FREE(parent);
6600 return NT_STATUS_OK;
6603 /****************************************************************************
6604 Deal with SMB_SET_FILE_UNIX_BASIC.
6605 ****************************************************************************/
6607 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6608 struct smb_request *req,
6612 const struct smb_filename *smb_fname)
6614 struct smb_file_time ft;
6615 uint32 raw_unixmode;
6618 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6619 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6620 NTSTATUS status = NT_STATUS_OK;
6621 bool delete_on_fail = False;
6622 enum perm_type ptype;
6623 files_struct *all_fsps = NULL;
6624 bool modify_mtime = true;
6626 SMB_STRUCT_STAT sbuf;
6630 if (total_data < 100) {
6631 return NT_STATUS_INVALID_PARAMETER;
6634 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6635 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6636 size=IVAL(pdata,0); /* first 8 Bytes are size */
6637 #ifdef LARGE_SMB_OFF_T
6638 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6639 #else /* LARGE_SMB_OFF_T */
6640 if (IVAL(pdata,4) != 0) {
6641 /* more than 32 bits? */
6642 return NT_STATUS_INVALID_PARAMETER;
6644 #endif /* LARGE_SMB_OFF_T */
6647 ft.atime = interpret_long_date(pdata+24); /* access_time */
6648 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6649 set_owner = (uid_t)IVAL(pdata,40);
6650 set_grp = (gid_t)IVAL(pdata,48);
6651 raw_unixmode = IVAL(pdata,84);
6653 if (VALID_STAT(smb_fname->st)) {
6654 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6655 ptype = PERM_EXISTING_DIR;
6657 ptype = PERM_EXISTING_FILE;
6660 ptype = PERM_NEW_FILE;
6663 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6665 if (!NT_STATUS_IS_OK(status)) {
6669 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6670 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6671 smb_fname_str_dbg(smb_fname), (double)size,
6672 (unsigned int)set_owner, (unsigned int)set_grp,
6673 (int)raw_unixmode));
6675 sbuf = smb_fname->st;
6677 if (!VALID_STAT(sbuf)) {
6678 struct smb_filename *smb_fname_tmp = NULL;
6680 * The only valid use of this is to create character and block
6681 * devices, and named pipes. This is deprecated (IMHO) and
6682 * a new info level should be used for mknod. JRA.
6685 status = smb_unix_mknod(conn,
6689 if (!NT_STATUS_IS_OK(status)) {
6693 status = copy_smb_filename(talloc_tos(), smb_fname,
6695 if (!NT_STATUS_IS_OK(status)) {
6699 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6700 status = map_nt_error_from_unix(errno);
6701 TALLOC_FREE(smb_fname_tmp);
6702 SMB_VFS_UNLINK(conn, smb_fname);
6706 sbuf = smb_fname_tmp->st;
6707 TALLOC_FREE(smb_fname_tmp);
6709 /* Ensure we don't try and change anything else. */
6710 raw_unixmode = SMB_MODE_NO_CHANGE;
6711 size = get_file_size_stat(&sbuf);
6712 ft.atime = sbuf.st_ex_atime;
6713 ft.mtime = sbuf.st_ex_mtime;
6715 * We continue here as we might want to change the
6718 delete_on_fail = True;
6722 /* Horrible backwards compatibility hack as an old server bug
6723 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6727 size = get_file_size_stat(&sbuf);
6732 * Deal with the UNIX specific mode set.
6735 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6736 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6737 "setting mode 0%o for file %s\n",
6738 (unsigned int)unixmode,
6739 smb_fname_str_dbg(smb_fname)));
6740 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6741 return map_nt_error_from_unix(errno);
6746 * Deal with the UNIX specific uid set.
6749 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6750 (sbuf.st_ex_uid != set_owner)) {
6753 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6754 "changing owner %u for path %s\n",
6755 (unsigned int)set_owner,
6756 smb_fname_str_dbg(smb_fname)));
6758 if (S_ISLNK(sbuf.st_ex_mode)) {
6759 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6760 set_owner, (gid_t)-1);
6762 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6763 set_owner, (gid_t)-1);
6767 status = map_nt_error_from_unix(errno);
6768 if (delete_on_fail) {
6769 SMB_VFS_UNLINK(conn, smb_fname);
6776 * Deal with the UNIX specific gid set.
6779 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6780 (sbuf.st_ex_gid != set_grp)) {
6781 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6782 "changing group %u for file %s\n",
6783 (unsigned int)set_owner,
6784 smb_fname_str_dbg(smb_fname)));
6785 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6787 status = map_nt_error_from_unix(errno);
6788 if (delete_on_fail) {
6789 SMB_VFS_UNLINK(conn, smb_fname);
6795 /* Deal with any size changes. */
6797 status = smb_set_file_size(conn, req,
6802 if (!NT_STATUS_IS_OK(status)) {
6806 /* Deal with any time changes. */
6807 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6808 /* No change, don't cancel anything. */
6812 id = vfs_file_id_from_sbuf(conn, &sbuf);
6813 for(all_fsps = file_find_di_first(id); all_fsps;
6814 all_fsps = file_find_di_next(all_fsps)) {
6816 * We're setting the time explicitly for UNIX.
6817 * Cancel any pending changes over all handles.
6819 all_fsps->update_write_time_on_close = false;
6820 TALLOC_FREE(all_fsps->update_write_time_event);
6824 * Override the "setting_write_time"
6825 * parameter here as it almost does what
6826 * we need. Just remember if we modified
6827 * mtime and send the notify ourselves.
6829 if (null_timespec(ft.mtime)) {
6830 modify_mtime = false;
6833 status = smb_set_file_time(conn,
6839 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6840 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6845 /****************************************************************************
6846 Deal with SMB_SET_FILE_UNIX_INFO2.
6847 ****************************************************************************/
6849 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6850 struct smb_request *req,
6854 const struct smb_filename *smb_fname)
6860 if (total_data < 116) {
6861 return NT_STATUS_INVALID_PARAMETER;
6864 /* Start by setting all the fields that are common between UNIX_BASIC
6867 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6869 if (!NT_STATUS_IS_OK(status)) {
6873 smb_fflags = IVAL(pdata, 108);
6874 smb_fmask = IVAL(pdata, 112);
6876 /* NB: We should only attempt to alter the file flags if the client
6877 * sends a non-zero mask.
6879 if (smb_fmask != 0) {
6880 int stat_fflags = 0;
6882 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6883 smb_fmask, &stat_fflags)) {
6884 /* Client asked to alter a flag we don't understand. */
6885 return NT_STATUS_INVALID_PARAMETER;
6888 if (fsp && fsp->fh->fd != -1) {
6889 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6890 return NT_STATUS_NOT_SUPPORTED;
6892 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6893 stat_fflags) != 0) {
6894 return map_nt_error_from_unix(errno);
6899 /* XXX: need to add support for changing the create_time here. You
6900 * can do this for paths on Darwin with setattrlist(2). The right way
6901 * to hook this up is probably by extending the VFS utimes interface.
6904 return NT_STATUS_OK;
6907 /****************************************************************************
6908 Create a directory with POSIX semantics.
6909 ****************************************************************************/
6911 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6912 struct smb_request *req,
6915 struct smb_filename *smb_fname,
6916 int *pdata_return_size)
6918 NTSTATUS status = NT_STATUS_OK;
6919 uint32 raw_unixmode = 0;
6920 uint32 mod_unixmode = 0;
6921 mode_t unixmode = (mode_t)0;
6922 files_struct *fsp = NULL;
6923 uint16 info_level_return = 0;
6925 char *pdata = *ppdata;
6927 if (total_data < 18) {
6928 return NT_STATUS_INVALID_PARAMETER;
6931 raw_unixmode = IVAL(pdata,8);
6932 /* Next 4 bytes are not yet defined. */
6934 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6935 PERM_NEW_DIR, &unixmode);
6936 if (!NT_STATUS_IS_OK(status)) {
6940 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6942 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6943 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6945 status = SMB_VFS_CREATE_FILE(
6948 0, /* root_dir_fid */
6949 smb_fname, /* fname */
6950 FILE_READ_ATTRIBUTES, /* access_mask */
6951 FILE_SHARE_NONE, /* share_access */
6952 FILE_CREATE, /* create_disposition*/
6953 FILE_DIRECTORY_FILE, /* create_options */
6954 mod_unixmode, /* file_attributes */
6955 0, /* oplock_request */
6956 0, /* allocation_size */
6962 if (NT_STATUS_IS_OK(status)) {
6963 close_file(req, fsp, NORMAL_CLOSE);
6966 info_level_return = SVAL(pdata,16);
6968 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6969 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6970 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6971 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6973 *pdata_return_size = 12;
6976 /* Realloc the data size */
6977 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6978 if (*ppdata == NULL) {
6979 *pdata_return_size = 0;
6980 return NT_STATUS_NO_MEMORY;
6984 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6985 SSVAL(pdata,2,0); /* No fnum. */
6986 SIVAL(pdata,4,info); /* Was directory created. */
6988 switch (info_level_return) {
6989 case SMB_QUERY_FILE_UNIX_BASIC:
6990 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6991 SSVAL(pdata,10,0); /* Padding. */
6992 store_file_unix_basic(conn, pdata + 12, fsp,
6995 case SMB_QUERY_FILE_UNIX_INFO2:
6996 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6997 SSVAL(pdata,10,0); /* Padding. */
6998 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7002 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7003 SSVAL(pdata,10,0); /* Padding. */
7010 /****************************************************************************
7011 Open/Create a file with POSIX semantics.
7012 ****************************************************************************/
7014 static NTSTATUS smb_posix_open(connection_struct *conn,
7015 struct smb_request *req,
7018 struct smb_filename *smb_fname,
7019 int *pdata_return_size)
7021 bool extended_oplock_granted = False;
7022 char *pdata = *ppdata;
7024 uint32 wire_open_mode = 0;
7025 uint32 raw_unixmode = 0;
7026 uint32 mod_unixmode = 0;
7027 uint32 create_disp = 0;
7028 uint32 access_mask = 0;
7029 uint32 create_options = 0;
7030 NTSTATUS status = NT_STATUS_OK;
7031 mode_t unixmode = (mode_t)0;
7032 files_struct *fsp = NULL;
7033 int oplock_request = 0;
7035 uint16 info_level_return = 0;
7037 if (total_data < 18) {
7038 return NT_STATUS_INVALID_PARAMETER;
7041 flags = IVAL(pdata,0);
7042 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7043 if (oplock_request) {
7044 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7047 wire_open_mode = IVAL(pdata,4);
7049 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7050 return smb_posix_mkdir(conn, req,
7057 switch (wire_open_mode & SMB_ACCMODE) {
7059 access_mask = FILE_READ_DATA;
7062 access_mask = FILE_WRITE_DATA;
7065 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7068 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7069 (unsigned int)wire_open_mode ));
7070 return NT_STATUS_INVALID_PARAMETER;
7073 wire_open_mode &= ~SMB_ACCMODE;
7075 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7076 create_disp = FILE_CREATE;
7077 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7078 create_disp = FILE_OVERWRITE_IF;
7079 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7080 create_disp = FILE_OPEN_IF;
7081 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7082 create_disp = FILE_OPEN;
7084 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7085 (unsigned int)wire_open_mode ));
7086 return NT_STATUS_INVALID_PARAMETER;
7089 raw_unixmode = IVAL(pdata,8);
7090 /* Next 4 bytes are not yet defined. */
7092 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7093 (VALID_STAT(smb_fname->st) ?
7094 PERM_EXISTING_FILE : PERM_NEW_FILE),
7097 if (!NT_STATUS_IS_OK(status)) {
7101 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7103 if (wire_open_mode & SMB_O_SYNC) {
7104 create_options |= FILE_WRITE_THROUGH;
7106 if (wire_open_mode & SMB_O_APPEND) {
7107 access_mask |= FILE_APPEND_DATA;
7109 if (wire_open_mode & SMB_O_DIRECT) {
7110 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7113 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7114 smb_fname_str_dbg(smb_fname),
7115 (unsigned int)wire_open_mode,
7116 (unsigned int)unixmode ));
7118 status = SMB_VFS_CREATE_FILE(
7121 0, /* root_dir_fid */
7122 smb_fname, /* fname */
7123 access_mask, /* access_mask */
7124 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7126 create_disp, /* create_disposition*/
7127 FILE_NON_DIRECTORY_FILE, /* create_options */
7128 mod_unixmode, /* file_attributes */
7129 oplock_request, /* oplock_request */
7130 0, /* allocation_size */
7136 if (!NT_STATUS_IS_OK(status)) {
7140 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7141 extended_oplock_granted = True;
7144 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7145 extended_oplock_granted = True;
7148 info_level_return = SVAL(pdata,16);
7150 /* Allocate the correct return size. */
7152 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7153 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7154 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7155 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7157 *pdata_return_size = 12;
7160 /* Realloc the data size */
7161 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7162 if (*ppdata == NULL) {
7163 close_file(req, fsp, ERROR_CLOSE);
7164 *pdata_return_size = 0;
7165 return NT_STATUS_NO_MEMORY;
7169 if (extended_oplock_granted) {
7170 if (flags & REQUEST_BATCH_OPLOCK) {
7171 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7173 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7175 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7176 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7178 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7181 SSVAL(pdata,2,fsp->fnum);
7182 SIVAL(pdata,4,info); /* Was file created etc. */
7184 switch (info_level_return) {
7185 case SMB_QUERY_FILE_UNIX_BASIC:
7186 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7187 SSVAL(pdata,10,0); /* padding. */
7188 store_file_unix_basic(conn, pdata + 12, fsp,
7191 case SMB_QUERY_FILE_UNIX_INFO2:
7192 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7193 SSVAL(pdata,10,0); /* padding. */
7194 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7198 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7199 SSVAL(pdata,10,0); /* padding. */
7202 return NT_STATUS_OK;
7205 /****************************************************************************
7206 Delete a file with POSIX semantics.
7207 ****************************************************************************/
7209 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7210 struct smb_request *req,
7213 struct smb_filename *smb_fname)
7215 NTSTATUS status = NT_STATUS_OK;
7216 files_struct *fsp = NULL;
7220 int create_options = 0;
7222 struct share_mode_lock *lck = NULL;
7224 if (total_data < 2) {
7225 return NT_STATUS_INVALID_PARAMETER;
7228 flags = SVAL(pdata,0);
7230 if (!VALID_STAT(smb_fname->st)) {
7231 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7234 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7235 !VALID_STAT_OF_DIR(smb_fname->st)) {
7236 return NT_STATUS_NOT_A_DIRECTORY;
7239 DEBUG(10,("smb_posix_unlink: %s %s\n",
7240 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7241 smb_fname_str_dbg(smb_fname)));
7243 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7244 create_options |= FILE_DIRECTORY_FILE;
7247 status = SMB_VFS_CREATE_FILE(
7250 0, /* root_dir_fid */
7251 smb_fname, /* fname */
7252 DELETE_ACCESS, /* access_mask */
7253 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7255 FILE_OPEN, /* create_disposition*/
7256 create_options, /* create_options */
7257 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7258 0, /* oplock_request */
7259 0, /* allocation_size */
7265 if (!NT_STATUS_IS_OK(status)) {
7270 * Don't lie to client. If we can't really delete due to
7271 * non-POSIX opens return SHARING_VIOLATION.
7274 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7277 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7278 "lock for file %s\n", fsp_str_dbg(fsp)));
7279 close_file(req, fsp, NORMAL_CLOSE);
7280 return NT_STATUS_INVALID_PARAMETER;
7284 * See if others still have the file open. If this is the case, then
7285 * don't delete. If all opens are POSIX delete we can set the delete
7286 * on close disposition.
7288 for (i=0; i<lck->num_share_modes; i++) {
7289 struct share_mode_entry *e = &lck->share_modes[i];
7290 if (is_valid_share_mode_entry(e)) {
7291 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7294 /* Fail with sharing violation. */
7295 close_file(req, fsp, NORMAL_CLOSE);
7297 return NT_STATUS_SHARING_VIOLATION;
7302 * Set the delete on close.
7304 status = smb_set_file_disposition_info(conn,
7310 if (!NT_STATUS_IS_OK(status)) {
7311 close_file(req, fsp, NORMAL_CLOSE);
7316 return close_file(req, fsp, NORMAL_CLOSE);
7319 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7320 struct smb_request *req,
7321 TALLOC_CTX *mem_ctx,
7322 uint16_t info_level,
7324 struct smb_filename *smb_fname,
7325 char **ppdata, int total_data,
7328 char *pdata = *ppdata;
7329 NTSTATUS status = NT_STATUS_OK;
7330 int data_return_size = 0;
7334 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7335 return NT_STATUS_INVALID_LEVEL;
7338 if (!CAN_WRITE(conn)) {
7339 /* Allow POSIX opens. The open path will deny
7340 * any non-readonly opens. */
7341 if (info_level != SMB_POSIX_PATH_OPEN) {
7342 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7346 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7347 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7348 fsp ? fsp->fnum : -1, info_level, total_data));
7350 switch (info_level) {
7352 case SMB_INFO_STANDARD:
7354 status = smb_set_info_standard(conn,
7362 case SMB_INFO_SET_EA:
7364 status = smb_info_set_ea(conn,
7372 case SMB_SET_FILE_BASIC_INFO:
7373 case SMB_FILE_BASIC_INFORMATION:
7375 status = smb_set_file_basic_info(conn,
7383 case SMB_FILE_ALLOCATION_INFORMATION:
7384 case SMB_SET_FILE_ALLOCATION_INFO:
7386 status = smb_set_file_allocation_info(conn, req,
7394 case SMB_FILE_END_OF_FILE_INFORMATION:
7395 case SMB_SET_FILE_END_OF_FILE_INFO:
7397 status = smb_set_file_end_of_file_info(conn, req,
7405 case SMB_FILE_DISPOSITION_INFORMATION:
7406 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7409 /* JRA - We used to just ignore this on a path ?
7410 * Shouldn't this be invalid level on a pathname
7413 if (tran_call != TRANSACT2_SETFILEINFO) {
7414 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7417 status = smb_set_file_disposition_info(conn,
7425 case SMB_FILE_POSITION_INFORMATION:
7427 status = smb_file_position_information(conn,
7434 case SMB_FILE_FULL_EA_INFORMATION:
7436 status = smb_set_file_full_ea_info(conn,
7443 /* From tridge Samba4 :
7444 * MODE_INFORMATION in setfileinfo (I have no
7445 * idea what "mode information" on a file is - it takes a value of 0,
7446 * 2, 4 or 6. What could it be?).
7449 case SMB_FILE_MODE_INFORMATION:
7451 status = smb_file_mode_information(conn,
7458 * CIFS UNIX extensions.
7461 case SMB_SET_FILE_UNIX_BASIC:
7463 status = smb_set_file_unix_basic(conn, req,
7471 case SMB_SET_FILE_UNIX_INFO2:
7473 status = smb_set_file_unix_info2(conn, req,
7481 case SMB_SET_FILE_UNIX_LINK:
7484 /* We must have a pathname for this. */
7485 return NT_STATUS_INVALID_LEVEL;
7487 status = smb_set_file_unix_link(conn, req, pdata,
7488 total_data, smb_fname);
7492 case SMB_SET_FILE_UNIX_HLINK:
7495 /* We must have a pathname for this. */
7496 return NT_STATUS_INVALID_LEVEL;
7498 status = smb_set_file_unix_hlink(conn, req,
7504 case SMB_FILE_RENAME_INFORMATION:
7506 status = smb_file_rename_information(conn, req,
7512 #if defined(HAVE_POSIX_ACLS)
7513 case SMB_SET_POSIX_ACL:
7515 status = smb_set_posix_acl(conn,
7524 case SMB_SET_POSIX_LOCK:
7527 return NT_STATUS_INVALID_LEVEL;
7529 status = smb_set_posix_lock(conn, req,
7530 pdata, total_data, fsp);
7534 case SMB_POSIX_PATH_OPEN:
7537 /* We must have a pathname for this. */
7538 return NT_STATUS_INVALID_LEVEL;
7541 status = smb_posix_open(conn, req,
7549 case SMB_POSIX_PATH_UNLINK:
7552 /* We must have a pathname for this. */
7553 return NT_STATUS_INVALID_LEVEL;
7556 status = smb_posix_unlink(conn, req,
7564 return NT_STATUS_INVALID_LEVEL;
7567 if (!NT_STATUS_IS_OK(status)) {
7571 *ret_data_size = data_return_size;
7572 return NT_STATUS_OK;
7575 /****************************************************************************
7576 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7577 ****************************************************************************/
7579 static void call_trans2setfilepathinfo(connection_struct *conn,
7580 struct smb_request *req,
7581 unsigned int tran_call,
7582 char **pparams, int total_params,
7583 char **ppdata, int total_data,
7584 unsigned int max_data_bytes)
7586 char *params = *pparams;
7587 char *pdata = *ppdata;
7589 struct smb_filename *smb_fname = NULL;
7590 files_struct *fsp = NULL;
7591 NTSTATUS status = NT_STATUS_OK;
7592 int data_return_size = 0;
7595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7599 if (tran_call == TRANSACT2_SETFILEINFO) {
7600 if (total_params < 4) {
7601 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7605 fsp = file_fsp(req, SVAL(params,0));
7606 /* Basic check for non-null fsp. */
7607 if (!check_fsp_open(conn, req, fsp)) {
7610 info_level = SVAL(params,2);
7612 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7614 if (!NT_STATUS_IS_OK(status)) {
7615 reply_nterror(req, status);
7619 if(fsp->is_directory || fsp->fh->fd == -1) {
7621 * This is actually a SETFILEINFO on a directory
7622 * handle (returned from an NT SMB). NT5.0 seems
7623 * to do this call. JRA.
7625 if (INFO_LEVEL_IS_UNIX(info_level)) {
7626 /* Always do lstat for UNIX calls. */
7627 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7628 DEBUG(3,("call_trans2setfilepathinfo: "
7629 "SMB_VFS_LSTAT of %s failed "
7631 smb_fname_str_dbg(smb_fname),
7633 reply_nterror(req, map_nt_error_from_unix(errno));
7637 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7638 DEBUG(3,("call_trans2setfilepathinfo: "
7639 "fileinfo of %s failed (%s)\n",
7640 smb_fname_str_dbg(smb_fname),
7642 reply_nterror(req, map_nt_error_from_unix(errno));
7646 } else if (fsp->print_file) {
7648 * Doing a DELETE_ON_CLOSE should cancel a print job.
7650 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7651 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7653 DEBUG(3,("call_trans2setfilepathinfo: "
7654 "Cancelling print job (%s)\n",
7658 send_trans2_replies(conn, req, params, 2,
7663 reply_doserror(req, ERRDOS, ERRbadpath);
7668 * Original code - this is an open file.
7670 if (!check_fsp(conn, req, fsp)) {
7674 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7675 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7676 "of fnum %d failed (%s)\n", fsp->fnum,
7678 reply_nterror(req, map_nt_error_from_unix(errno));
7686 if (total_params < 7) {
7687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7691 info_level = SVAL(params,0);
7692 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7693 total_params - 6, STR_TERMINATE,
7695 if (!NT_STATUS_IS_OK(status)) {
7696 reply_nterror(req, status);
7700 status = filename_convert(req, conn,
7701 req->flags2 & FLAGS2_DFS_PATHNAMES,
7706 if (!NT_STATUS_IS_OK(status)) {
7707 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7708 reply_botherror(req,
7709 NT_STATUS_PATH_NOT_COVERED,
7710 ERRSRV, ERRbadpath);
7713 reply_nterror(req, status);
7717 if (INFO_LEVEL_IS_UNIX(info_level)) {
7719 * For CIFS UNIX extensions the target name may not exist.
7722 /* Always do lstat for UNIX calls. */
7723 SMB_VFS_LSTAT(conn, smb_fname);
7725 } else if (!VALID_STAT(smb_fname->st) &&
7726 SMB_VFS_STAT(conn, smb_fname)) {
7727 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7729 smb_fname_str_dbg(smb_fname),
7731 reply_nterror(req, map_nt_error_from_unix(errno));
7736 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7737 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7738 fsp ? fsp->fnum : -1, info_level,total_data));
7740 /* Realloc the parameter size */
7741 *pparams = (char *)SMB_REALLOC(*pparams,2);
7742 if (*pparams == NULL) {
7743 reply_nterror(req, NT_STATUS_NO_MEMORY);
7750 status = smbd_do_setfilepathinfo(conn, req, req,
7756 if (!NT_STATUS_IS_OK(status)) {
7757 if (open_was_deferred(req->mid)) {
7758 /* We have re-scheduled this call. */
7761 if (blocking_lock_was_deferred(req->mid)) {
7762 /* We have re-scheduled this call. */
7765 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7766 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7767 ERRSRV, ERRbadpath);
7770 if (info_level == SMB_POSIX_PATH_OPEN) {
7771 reply_openerror(req, status);
7775 reply_nterror(req, status);
7779 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7785 /****************************************************************************
7786 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7787 ****************************************************************************/
7789 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7790 char **pparams, int total_params,
7791 char **ppdata, int total_data,
7792 unsigned int max_data_bytes)
7794 struct smb_filename *smb_dname = NULL;
7795 char *params = *pparams;
7796 char *pdata = *ppdata;
7797 char *directory = NULL;
7798 NTSTATUS status = NT_STATUS_OK;
7799 struct ea_list *ea_list = NULL;
7800 TALLOC_CTX *ctx = talloc_tos();
7802 if (!CAN_WRITE(conn)) {
7803 reply_doserror(req, ERRSRV, ERRaccess);
7807 if (total_params < 5) {
7808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7812 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7813 total_params - 4, STR_TERMINATE,
7815 if (!NT_STATUS_IS_OK(status)) {
7816 reply_nterror(req, status);
7820 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7822 status = filename_convert(ctx,
7824 req->flags2 & FLAGS2_DFS_PATHNAMES,
7830 if (!NT_STATUS_IS_OK(status)) {
7831 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7832 reply_botherror(req,
7833 NT_STATUS_PATH_NOT_COVERED,
7834 ERRSRV, ERRbadpath);
7837 reply_nterror(req, status);
7841 /* Any data in this call is an EA list. */
7842 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7843 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7848 * OS/2 workplace shell seems to send SET_EA requests of "null"
7849 * length (4 bytes containing IVAL 4).
7850 * They seem to have no effect. Bug #3212. JRA.
7853 if (total_data != 4) {
7854 if (total_data < 10) {
7855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7859 if (IVAL(pdata,0) > total_data) {
7860 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7861 IVAL(pdata,0), (unsigned int)total_data));
7862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7866 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7873 /* If total_data == 4 Windows doesn't care what values
7874 * are placed in that field, it just ignores them.
7875 * The System i QNTC IBM SMB client puts bad values here,
7876 * so ignore them. */
7878 status = create_directory(conn, req, smb_dname);
7880 if (!NT_STATUS_IS_OK(status)) {
7881 reply_nterror(req, status);
7885 /* Try and set any given EA. */
7887 status = set_ea(conn, NULL, smb_dname, ea_list);
7888 if (!NT_STATUS_IS_OK(status)) {
7889 reply_nterror(req, status);
7894 /* Realloc the parameter and data sizes */
7895 *pparams = (char *)SMB_REALLOC(*pparams,2);
7896 if(*pparams == NULL) {
7897 reply_nterror(req, NT_STATUS_NO_MEMORY);
7904 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7907 TALLOC_FREE(smb_dname);
7911 /****************************************************************************
7912 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7913 We don't actually do this - we just send a null response.
7914 ****************************************************************************/
7916 static void call_trans2findnotifyfirst(connection_struct *conn,
7917 struct smb_request *req,
7918 char **pparams, int total_params,
7919 char **ppdata, int total_data,
7920 unsigned int max_data_bytes)
7922 char *params = *pparams;
7925 if (total_params < 6) {
7926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7930 info_level = SVAL(params,4);
7931 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7933 switch (info_level) {
7938 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7942 /* Realloc the parameter and data sizes */
7943 *pparams = (char *)SMB_REALLOC(*pparams,6);
7944 if (*pparams == NULL) {
7945 reply_nterror(req, NT_STATUS_NO_MEMORY);
7950 SSVAL(params,0,fnf_handle);
7951 SSVAL(params,2,0); /* No changes */
7952 SSVAL(params,4,0); /* No EA errors */
7959 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7964 /****************************************************************************
7965 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7966 changes). Currently this does nothing.
7967 ****************************************************************************/
7969 static void call_trans2findnotifynext(connection_struct *conn,
7970 struct smb_request *req,
7971 char **pparams, int total_params,
7972 char **ppdata, int total_data,
7973 unsigned int max_data_bytes)
7975 char *params = *pparams;
7977 DEBUG(3,("call_trans2findnotifynext\n"));
7979 /* Realloc the parameter and data sizes */
7980 *pparams = (char *)SMB_REALLOC(*pparams,4);
7981 if (*pparams == NULL) {
7982 reply_nterror(req, NT_STATUS_NO_MEMORY);
7987 SSVAL(params,0,0); /* No changes */
7988 SSVAL(params,2,0); /* No EA errors */
7990 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7995 /****************************************************************************
7996 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7997 ****************************************************************************/
7999 static void call_trans2getdfsreferral(connection_struct *conn,
8000 struct smb_request *req,
8001 char **pparams, int total_params,
8002 char **ppdata, int total_data,
8003 unsigned int max_data_bytes)
8005 char *params = *pparams;
8006 char *pathname = NULL;
8008 int max_referral_level;
8009 NTSTATUS status = NT_STATUS_OK;
8010 TALLOC_CTX *ctx = talloc_tos();
8012 DEBUG(10,("call_trans2getdfsreferral\n"));
8014 if (total_params < 3) {
8015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8019 max_referral_level = SVAL(params,0);
8021 if(!lp_host_msdfs()) {
8022 reply_doserror(req, ERRDOS, ERRbadfunc);
8026 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8027 total_params - 2, STR_TERMINATE);
8029 reply_nterror(req, NT_STATUS_NOT_FOUND);
8032 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8033 ppdata,&status)) < 0) {
8034 reply_nterror(req, status);
8038 SSVAL(req->inbuf, smb_flg2,
8039 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8040 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8045 #define LMCAT_SPL 0x53
8046 #define LMFUNC_GETJOBID 0x60
8048 /****************************************************************************
8049 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8050 ****************************************************************************/
8052 static void call_trans2ioctl(connection_struct *conn,
8053 struct smb_request *req,
8054 char **pparams, int total_params,
8055 char **ppdata, int total_data,
8056 unsigned int max_data_bytes)
8058 char *pdata = *ppdata;
8059 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8061 /* check for an invalid fid before proceeding */
8064 reply_doserror(req, ERRDOS, ERRbadfid);
8068 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8069 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8070 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8071 if (*ppdata == NULL) {
8072 reply_nterror(req, NT_STATUS_NO_MEMORY);
8077 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8078 CAN ACCEPT THIS IN UNICODE. JRA. */
8080 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8081 srvstr_push(pdata, req->flags2, pdata + 2,
8082 global_myname(), 15,
8083 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8084 srvstr_push(pdata, req->flags2, pdata+18,
8085 lp_servicename(SNUM(conn)), 13,
8086 STR_ASCII|STR_TERMINATE); /* Service name */
8087 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8092 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8093 reply_doserror(req, ERRSRV, ERRerror);
8096 /****************************************************************************
8097 Reply to a SMBfindclose (stop trans2 directory search).
8098 ****************************************************************************/
8100 void reply_findclose(struct smb_request *req)
8103 struct smbd_server_connection *sconn = smbd_server_conn;
8105 START_PROFILE(SMBfindclose);
8108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8109 END_PROFILE(SMBfindclose);
8113 dptr_num = SVALS(req->vwv+0, 0);
8115 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8117 dptr_close(sconn, &dptr_num);
8119 reply_outbuf(req, 0, 0);
8121 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8123 END_PROFILE(SMBfindclose);
8127 /****************************************************************************
8128 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8129 ****************************************************************************/
8131 void reply_findnclose(struct smb_request *req)
8135 START_PROFILE(SMBfindnclose);
8138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8139 END_PROFILE(SMBfindnclose);
8143 dptr_num = SVAL(req->vwv+0, 0);
8145 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8147 /* We never give out valid handles for a
8148 findnotifyfirst - so any dptr_num is ok here.
8151 reply_outbuf(req, 0, 0);
8153 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8155 END_PROFILE(SMBfindnclose);
8159 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8160 struct trans_state *state)
8162 if (get_Protocol() >= PROTOCOL_NT1) {
8163 req->flags2 |= 0x40; /* IS_LONG_NAME */
8164 SSVAL(req->inbuf,smb_flg2,req->flags2);
8167 if (conn->encrypt_level == Required && !req->encrypted) {
8168 if (state->call != TRANSACT2_QFSINFO &&
8169 state->call != TRANSACT2_SETFSINFO) {
8170 DEBUG(0,("handle_trans2: encryption required "
8172 (unsigned int)state->call));
8173 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8178 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8180 /* Now we must call the relevant TRANS2 function */
8181 switch(state->call) {
8182 case TRANSACT2_OPEN:
8184 START_PROFILE(Trans2_open);
8185 call_trans2open(conn, req,
8186 &state->param, state->total_param,
8187 &state->data, state->total_data,
8188 state->max_data_return);
8189 END_PROFILE(Trans2_open);
8193 case TRANSACT2_FINDFIRST:
8195 START_PROFILE(Trans2_findfirst);
8196 call_trans2findfirst(conn, req,
8197 &state->param, state->total_param,
8198 &state->data, state->total_data,
8199 state->max_data_return);
8200 END_PROFILE(Trans2_findfirst);
8204 case TRANSACT2_FINDNEXT:
8206 START_PROFILE(Trans2_findnext);
8207 call_trans2findnext(conn, req,
8208 &state->param, state->total_param,
8209 &state->data, state->total_data,
8210 state->max_data_return);
8211 END_PROFILE(Trans2_findnext);
8215 case TRANSACT2_QFSINFO:
8217 START_PROFILE(Trans2_qfsinfo);
8218 call_trans2qfsinfo(conn, req,
8219 &state->param, state->total_param,
8220 &state->data, state->total_data,
8221 state->max_data_return);
8222 END_PROFILE(Trans2_qfsinfo);
8226 case TRANSACT2_SETFSINFO:
8228 START_PROFILE(Trans2_setfsinfo);
8229 call_trans2setfsinfo(conn, req,
8230 &state->param, state->total_param,
8231 &state->data, state->total_data,
8232 state->max_data_return);
8233 END_PROFILE(Trans2_setfsinfo);
8237 case TRANSACT2_QPATHINFO:
8238 case TRANSACT2_QFILEINFO:
8240 START_PROFILE(Trans2_qpathinfo);
8241 call_trans2qfilepathinfo(conn, req, state->call,
8242 &state->param, state->total_param,
8243 &state->data, state->total_data,
8244 state->max_data_return);
8245 END_PROFILE(Trans2_qpathinfo);
8249 case TRANSACT2_SETPATHINFO:
8250 case TRANSACT2_SETFILEINFO:
8252 START_PROFILE(Trans2_setpathinfo);
8253 call_trans2setfilepathinfo(conn, req, state->call,
8254 &state->param, state->total_param,
8255 &state->data, state->total_data,
8256 state->max_data_return);
8257 END_PROFILE(Trans2_setpathinfo);
8261 case TRANSACT2_FINDNOTIFYFIRST:
8263 START_PROFILE(Trans2_findnotifyfirst);
8264 call_trans2findnotifyfirst(conn, req,
8265 &state->param, state->total_param,
8266 &state->data, state->total_data,
8267 state->max_data_return);
8268 END_PROFILE(Trans2_findnotifyfirst);
8272 case TRANSACT2_FINDNOTIFYNEXT:
8274 START_PROFILE(Trans2_findnotifynext);
8275 call_trans2findnotifynext(conn, req,
8276 &state->param, state->total_param,
8277 &state->data, state->total_data,
8278 state->max_data_return);
8279 END_PROFILE(Trans2_findnotifynext);
8283 case TRANSACT2_MKDIR:
8285 START_PROFILE(Trans2_mkdir);
8286 call_trans2mkdir(conn, req,
8287 &state->param, state->total_param,
8288 &state->data, state->total_data,
8289 state->max_data_return);
8290 END_PROFILE(Trans2_mkdir);
8294 case TRANSACT2_GET_DFS_REFERRAL:
8296 START_PROFILE(Trans2_get_dfs_referral);
8297 call_trans2getdfsreferral(conn, req,
8298 &state->param, state->total_param,
8299 &state->data, state->total_data,
8300 state->max_data_return);
8301 END_PROFILE(Trans2_get_dfs_referral);
8305 case TRANSACT2_IOCTL:
8307 START_PROFILE(Trans2_ioctl);
8308 call_trans2ioctl(conn, req,
8309 &state->param, state->total_param,
8310 &state->data, state->total_data,
8311 state->max_data_return);
8312 END_PROFILE(Trans2_ioctl);
8317 /* Error in request */
8318 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8319 reply_doserror(req, ERRSRV,ERRerror);
8323 /****************************************************************************
8324 Reply to a SMBtrans2.
8325 ****************************************************************************/
8327 void reply_trans2(struct smb_request *req)
8329 connection_struct *conn = req->conn;
8334 unsigned int tran_call;
8335 struct trans_state *state;
8338 START_PROFILE(SMBtrans2);
8340 if (req->wct < 14) {
8341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8342 END_PROFILE(SMBtrans2);
8346 dsoff = SVAL(req->vwv+12, 0);
8347 dscnt = SVAL(req->vwv+11, 0);
8348 psoff = SVAL(req->vwv+10, 0);
8349 pscnt = SVAL(req->vwv+9, 0);
8350 tran_call = SVAL(req->vwv+14, 0);
8352 result = allow_new_trans(conn->pending_trans, req->mid);
8353 if (!NT_STATUS_IS_OK(result)) {
8354 DEBUG(2, ("Got invalid trans2 request: %s\n",
8355 nt_errstr(result)));
8356 reply_nterror(req, result);
8357 END_PROFILE(SMBtrans2);
8362 switch (tran_call) {
8363 /* List the allowed trans2 calls on IPC$ */
8364 case TRANSACT2_OPEN:
8365 case TRANSACT2_GET_DFS_REFERRAL:
8366 case TRANSACT2_QFILEINFO:
8367 case TRANSACT2_QFSINFO:
8368 case TRANSACT2_SETFSINFO:
8371 reply_doserror(req, ERRSRV, ERRaccess);
8372 END_PROFILE(SMBtrans2);
8377 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8378 DEBUG(0, ("talloc failed\n"));
8379 reply_nterror(req, NT_STATUS_NO_MEMORY);
8380 END_PROFILE(SMBtrans2);
8384 state->cmd = SMBtrans2;
8386 state->mid = req->mid;
8387 state->vuid = req->vuid;
8388 state->setup_count = SVAL(req->vwv+13, 0);
8389 state->setup = NULL;
8390 state->total_param = SVAL(req->vwv+0, 0);
8391 state->param = NULL;
8392 state->total_data = SVAL(req->vwv+1, 0);
8394 state->max_param_return = SVAL(req->vwv+2, 0);
8395 state->max_data_return = SVAL(req->vwv+3, 0);
8396 state->max_setup_return = SVAL(req->vwv+4, 0);
8397 state->close_on_completion = BITSETW(req->vwv+5, 0);
8398 state->one_way = BITSETW(req->vwv+5, 1);
8400 state->call = tran_call;
8402 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8403 is so as a sanity check */
8404 if (state->setup_count != 1) {
8406 * Need to have rc=0 for ioctl to get job id for OS/2.
8407 * Network printing will fail if function is not successful.
8408 * Similar function in reply.c will be used if protocol
8409 * is LANMAN1.0 instead of LM1.2X002.
8410 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8411 * outbuf doesn't have to be set(only job id is used).
8413 if ( (state->setup_count == 4)
8414 && (tran_call == TRANSACT2_IOCTL)
8415 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8416 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8417 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8419 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8420 DEBUG(2,("Transaction is %d\n",tran_call));
8422 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8423 END_PROFILE(SMBtrans2);
8428 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8431 if (state->total_data) {
8433 if (trans_oob(state->total_data, 0, dscnt)
8434 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8438 /* Can't use talloc here, the core routines do realloc on the
8439 * params and data. */
8440 state->data = (char *)SMB_MALLOC(state->total_data);
8441 if (state->data == NULL) {
8442 DEBUG(0,("reply_trans2: data malloc fail for %u "
8443 "bytes !\n", (unsigned int)state->total_data));
8445 reply_nterror(req, NT_STATUS_NO_MEMORY);
8446 END_PROFILE(SMBtrans2);
8450 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8453 if (state->total_param) {
8455 if (trans_oob(state->total_param, 0, pscnt)
8456 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8460 /* Can't use talloc here, the core routines do realloc on the
8461 * params and data. */
8462 state->param = (char *)SMB_MALLOC(state->total_param);
8463 if (state->param == NULL) {
8464 DEBUG(0,("reply_trans: param malloc fail for %u "
8465 "bytes !\n", (unsigned int)state->total_param));
8466 SAFE_FREE(state->data);
8468 reply_nterror(req, NT_STATUS_NO_MEMORY);
8469 END_PROFILE(SMBtrans2);
8473 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8476 state->received_data = dscnt;
8477 state->received_param = pscnt;
8479 if ((state->received_param == state->total_param) &&
8480 (state->received_data == state->total_data)) {
8482 handle_trans2(conn, req, state);
8484 SAFE_FREE(state->data);
8485 SAFE_FREE(state->param);
8487 END_PROFILE(SMBtrans2);
8491 DLIST_ADD(conn->pending_trans, state);
8493 /* We need to send an interim response then receive the rest
8494 of the parameter/data bytes */
8495 reply_outbuf(req, 0, 0);
8496 show_msg((char *)req->outbuf);
8497 END_PROFILE(SMBtrans2);
8502 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8503 SAFE_FREE(state->data);
8504 SAFE_FREE(state->param);
8506 END_PROFILE(SMBtrans2);
8507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8511 /****************************************************************************
8512 Reply to a SMBtranss2
8513 ****************************************************************************/
8515 void reply_transs2(struct smb_request *req)
8517 connection_struct *conn = req->conn;
8518 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8519 struct trans_state *state;
8521 START_PROFILE(SMBtranss2);
8523 show_msg((char *)req->inbuf);
8526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8527 END_PROFILE(SMBtranss2);
8531 for (state = conn->pending_trans; state != NULL;
8532 state = state->next) {
8533 if (state->mid == req->mid) {
8538 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8539 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8540 END_PROFILE(SMBtranss2);
8544 /* Revise state->total_param and state->total_data in case they have
8545 changed downwards */
8547 if (SVAL(req->vwv+0, 0) < state->total_param)
8548 state->total_param = SVAL(req->vwv+0, 0);
8549 if (SVAL(req->vwv+1, 0) < state->total_data)
8550 state->total_data = SVAL(req->vwv+1, 0);
8552 pcnt = SVAL(req->vwv+2, 0);
8553 poff = SVAL(req->vwv+3, 0);
8554 pdisp = SVAL(req->vwv+4, 0);
8556 dcnt = SVAL(req->vwv+5, 0);
8557 doff = SVAL(req->vwv+6, 0);
8558 ddisp = SVAL(req->vwv+7, 0);
8560 state->received_param += pcnt;
8561 state->received_data += dcnt;
8563 if ((state->received_data > state->total_data) ||
8564 (state->received_param > state->total_param))
8568 if (trans_oob(state->total_param, pdisp, pcnt)
8569 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8572 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8576 if (trans_oob(state->total_data, ddisp, dcnt)
8577 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8580 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8583 if ((state->received_param < state->total_param) ||
8584 (state->received_data < state->total_data)) {
8585 END_PROFILE(SMBtranss2);
8589 handle_trans2(conn, req, state);
8591 DLIST_REMOVE(conn->pending_trans, state);
8592 SAFE_FREE(state->data);
8593 SAFE_FREE(state->param);
8596 END_PROFILE(SMBtranss2);
8601 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8602 DLIST_REMOVE(conn->pending_trans, state);
8603 SAFE_FREE(state->data);
8604 SAFE_FREE(state->param);
8606 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8607 END_PROFILE(SMBtranss2);