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 get_Protocol(state->conn->sconn),
1373 state->conn->case_sensitive);
1376 if(!got_match && state->check_mangled_names &&
1377 !mangle_is_8_3(fname, false, state->conn->params)) {
1379 * It turns out that NT matches wildcards against
1380 * both long *and* short names. This may explain some
1381 * of the wildcard wierdness from old DOS clients
1382 * that some people have been seeing.... JRA.
1384 /* Force the mangling into 8.3. */
1385 ok = name_to_8_3(fname, mangled_name,
1386 false, state->conn->params);
1391 got_match = exact_match(state->has_wild,
1392 state->conn->case_sensitive,
1393 mangled_name, mask);
1394 state->got_exact_match = got_match;
1396 got_match = mask_match(
1398 get_Protocol(state->conn->sconn),
1399 state->conn->case_sensitive);
1407 *_fname = talloc_strdup(ctx, fname);
1408 if (*_fname == NULL) {
1415 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1417 struct smb_filename *smb_fname,
1420 struct smbd_dirptr_lanman2_state *state =
1421 (struct smbd_dirptr_lanman2_state *)private_data;
1422 bool ms_dfs_link = false;
1425 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1426 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1427 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1428 "Couldn't lstat [%s] (%s)\n",
1429 smb_fname_str_dbg(smb_fname),
1433 } else if (!VALID_STAT(smb_fname->st) &&
1434 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1435 /* Needed to show the msdfs symlinks as
1438 ms_dfs_link = check_msdfs_link(state->conn,
1439 smb_fname->base_name,
1442 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1443 "Couldn't stat [%s] (%s)\n",
1444 smb_fname_str_dbg(smb_fname),
1451 mode = dos_mode_msdfs(state->conn, smb_fname);
1453 mode = dos_mode(state->conn, smb_fname);
1460 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1461 connection_struct *conn,
1463 uint32_t info_level,
1464 struct ea_list *name_list,
1465 bool check_mangled_names,
1466 bool requires_resume_key,
1469 const struct smb_filename *smb_fname,
1470 uint64_t space_remaining,
1477 uint64_t *last_entry_off)
1479 char *p, *q, *pdata = *ppdata;
1481 uint64_t file_size = 0;
1482 uint64_t allocation_size = 0;
1484 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1485 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1486 time_t c_date = (time_t)0;
1488 char *last_entry_ptr;
1490 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1494 *out_of_space = false;
1496 ZERO_STRUCT(mdate_ts);
1497 ZERO_STRUCT(adate_ts);
1498 ZERO_STRUCT(create_date_ts);
1499 ZERO_STRUCT(cdate_ts);
1501 if (!(mode & aDIR)) {
1502 file_size = get_file_size_stat(&smb_fname->st);
1504 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1506 mdate_ts = smb_fname->st.st_ex_mtime;
1507 adate_ts = smb_fname->st.st_ex_atime;
1508 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1509 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1511 if (lp_dos_filetime_resolution(SNUM(conn))) {
1512 dos_filetime_timespec(&create_date_ts);
1513 dos_filetime_timespec(&mdate_ts);
1514 dos_filetime_timespec(&adate_ts);
1515 dos_filetime_timespec(&cdate_ts);
1518 create_date = convert_timespec_to_time_t(create_date_ts);
1519 mdate = convert_timespec_to_time_t(mdate_ts);
1520 adate = convert_timespec_to_time_t(adate_ts);
1521 c_date = convert_timespec_to_time_t(cdate_ts);
1523 /* align the record */
1524 off = PTR_DIFF(pdata, base_data);
1525 pad = (off + (align-1)) & ~(align-1);
1528 /* initialize padding to 0 */
1530 memset(pdata, 0, pad);
1532 space_remaining -= pad;
1541 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1543 switch (info_level) {
1544 case SMB_FIND_INFO_STANDARD:
1545 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1546 if(requires_resume_key) {
1550 srv_put_dos_date2(p,0,create_date);
1551 srv_put_dos_date2(p,4,adate);
1552 srv_put_dos_date2(p,8,mdate);
1553 SIVAL(p,12,(uint32)file_size);
1554 SIVAL(p,16,(uint32)allocation_size);
1558 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1559 p += ucs2_align(base_data, p, 0);
1561 len = srvstr_push(base_data, flags2, p,
1562 fname, PTR_DIFF(end_data, p),
1564 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1566 SCVAL(nameptr, -1, len - 2);
1568 SCVAL(nameptr, -1, 0);
1572 SCVAL(nameptr, -1, len - 1);
1574 SCVAL(nameptr, -1, 0);
1580 case SMB_FIND_EA_SIZE:
1581 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1582 if (requires_resume_key) {
1586 srv_put_dos_date2(p,0,create_date);
1587 srv_put_dos_date2(p,4,adate);
1588 srv_put_dos_date2(p,8,mdate);
1589 SIVAL(p,12,(uint32)file_size);
1590 SIVAL(p,16,(uint32)allocation_size);
1593 unsigned int ea_size = estimate_ea_size(conn, NULL,
1594 smb_fname->base_name);
1595 SIVAL(p,22,ea_size); /* Extended attributes */
1599 len = srvstr_push(base_data, flags2,
1600 p, fname, PTR_DIFF(end_data, p),
1601 STR_TERMINATE | STR_NOALIGN);
1602 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1615 SCVAL(nameptr,0,len);
1617 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1620 case SMB_FIND_EA_LIST:
1622 struct ea_list *file_list = NULL;
1625 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1629 if (requires_resume_key) {
1633 srv_put_dos_date2(p,0,create_date);
1634 srv_put_dos_date2(p,4,adate);
1635 srv_put_dos_date2(p,8,mdate);
1636 SIVAL(p,12,(uint32)file_size);
1637 SIVAL(p,16,(uint32)allocation_size);
1639 p += 22; /* p now points to the EA area. */
1641 file_list = get_ea_list_from_file(ctx, conn, NULL,
1642 smb_fname->base_name,
1644 name_list = ea_list_union(name_list, file_list, &ea_len);
1646 /* We need to determine if this entry will fit in the space available. */
1647 /* Max string size is 255 bytes. */
1648 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1649 *out_of_space = true;
1650 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1651 return False; /* Not finished - just out of space */
1654 /* Push the ea_data followed by the name. */
1655 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1657 len = srvstr_push(base_data, flags2,
1658 p + 1, fname, PTR_DIFF(end_data, p+1),
1659 STR_TERMINATE | STR_NOALIGN);
1660 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1673 SCVAL(nameptr,0,len);
1675 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1679 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1680 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1681 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1683 SIVAL(p,0,reskey); p += 4;
1684 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1685 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1686 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1687 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1688 SOFF_T(p,0,file_size); p += 8;
1689 SOFF_T(p,0,allocation_size); p += 8;
1690 SIVAL(p,0,nt_extmode); p += 4;
1691 q = p; p += 4; /* q is placeholder for name length. */
1693 unsigned int ea_size = estimate_ea_size(conn, NULL,
1694 smb_fname->base_name);
1695 SIVAL(p,0,ea_size); /* Extended attributes */
1698 /* Clear the short name buffer. This is
1699 * IMPORTANT as not doing so will trigger
1700 * a Win2k client bug. JRA.
1702 if (!was_8_3 && check_mangled_names) {
1703 char mangled_name[13]; /* mangled 8.3 name. */
1704 if (!name_to_8_3(fname,mangled_name,True,
1706 /* Error - mangle failed ! */
1707 memset(mangled_name,'\0',12);
1709 mangled_name[12] = 0;
1710 len = srvstr_push(base_data, flags2,
1711 p+2, mangled_name, 24,
1712 STR_UPPER|STR_UNICODE);
1714 memset(p + 2 + len,'\0',24 - len);
1721 len = srvstr_push(base_data, flags2, p,
1722 fname, PTR_DIFF(end_data, p),
1723 STR_TERMINATE_ASCII);
1727 len = PTR_DIFF(p, pdata);
1728 pad = (len + (align-1)) & ~(align-1);
1730 * offset to the next entry, the caller
1731 * will overwrite it for the last entry
1732 * that's why we always include the padding
1736 * set padding to zero
1739 memset(p, 0, pad - len);
1746 case SMB_FIND_FILE_DIRECTORY_INFO:
1747 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1749 SIVAL(p,0,reskey); p += 4;
1750 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1751 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1752 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1753 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1754 SOFF_T(p,0,file_size); p += 8;
1755 SOFF_T(p,0,allocation_size); p += 8;
1756 SIVAL(p,0,nt_extmode); p += 4;
1757 len = srvstr_push(base_data, flags2,
1758 p + 4, fname, PTR_DIFF(end_data, p+4),
1759 STR_TERMINATE_ASCII);
1763 len = PTR_DIFF(p, pdata);
1764 pad = (len + (align-1)) & ~(align-1);
1766 * offset to the next entry, the caller
1767 * will overwrite it for the last entry
1768 * that's why we always include the padding
1772 * set padding to zero
1775 memset(p, 0, pad - len);
1782 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1783 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1785 SIVAL(p,0,reskey); p += 4;
1786 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1787 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1788 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1789 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1790 SOFF_T(p,0,file_size); p += 8;
1791 SOFF_T(p,0,allocation_size); p += 8;
1792 SIVAL(p,0,nt_extmode); p += 4;
1793 q = p; p += 4; /* q is placeholder for name length. */
1795 unsigned int ea_size = estimate_ea_size(conn, NULL,
1796 smb_fname->base_name);
1797 SIVAL(p,0,ea_size); /* Extended attributes */
1800 len = srvstr_push(base_data, flags2, p,
1801 fname, PTR_DIFF(end_data, p),
1802 STR_TERMINATE_ASCII);
1806 len = PTR_DIFF(p, pdata);
1807 pad = (len + (align-1)) & ~(align-1);
1809 * offset to the next entry, the caller
1810 * will overwrite it for the last entry
1811 * that's why we always include the padding
1815 * set padding to zero
1818 memset(p, 0, pad - len);
1825 case SMB_FIND_FILE_NAMES_INFO:
1826 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1828 SIVAL(p,0,reskey); p += 4;
1830 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1831 acl on a dir (tridge) */
1832 len = srvstr_push(base_data, flags2, p,
1833 fname, PTR_DIFF(end_data, p),
1834 STR_TERMINATE_ASCII);
1838 len = PTR_DIFF(p, pdata);
1839 pad = (len + (align-1)) & ~(align-1);
1841 * offset to the next entry, the caller
1842 * will overwrite it for the last entry
1843 * that's why we always include the padding
1847 * set padding to zero
1850 memset(p, 0, pad - len);
1857 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1858 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1860 SIVAL(p,0,reskey); p += 4;
1861 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1862 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1863 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1864 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1865 SOFF_T(p,0,file_size); p += 8;
1866 SOFF_T(p,0,allocation_size); p += 8;
1867 SIVAL(p,0,nt_extmode); p += 4;
1868 q = p; p += 4; /* q is placeholder for name length. */
1870 unsigned int ea_size = estimate_ea_size(conn, NULL,
1871 smb_fname->base_name);
1872 SIVAL(p,0,ea_size); /* Extended attributes */
1875 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1876 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1877 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1878 len = srvstr_push(base_data, flags2, p,
1879 fname, PTR_DIFF(end_data, p),
1880 STR_TERMINATE_ASCII);
1884 len = PTR_DIFF(p, pdata);
1885 pad = (len + (align-1)) & ~(align-1);
1887 * offset to the next entry, the caller
1888 * will overwrite it for the last entry
1889 * that's why we always include the padding
1893 * set padding to zero
1896 memset(p, 0, pad - len);
1903 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1905 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1907 SIVAL(p,0,reskey); p += 4;
1908 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1910 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1911 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1912 SOFF_T(p,0,file_size); p += 8;
1913 SOFF_T(p,0,allocation_size); p += 8;
1914 SIVAL(p,0,nt_extmode); p += 4;
1915 q = p; p += 4; /* q is placeholder for name length */
1917 unsigned int ea_size = estimate_ea_size(conn, NULL,
1918 smb_fname->base_name);
1919 SIVAL(p,0,ea_size); /* Extended attributes */
1922 /* Clear the short name buffer. This is
1923 * IMPORTANT as not doing so will trigger
1924 * a Win2k client bug. JRA.
1926 if (!was_8_3 && check_mangled_names) {
1927 char mangled_name[13]; /* mangled 8.3 name. */
1928 if (!name_to_8_3(fname,mangled_name,True,
1930 /* Error - mangle failed ! */
1931 memset(mangled_name,'\0',12);
1933 mangled_name[12] = 0;
1934 len = srvstr_push(base_data, flags2,
1935 p+2, mangled_name, 24,
1936 STR_UPPER|STR_UNICODE);
1939 memset(p + 2 + len,'\0',24 - len);
1946 SSVAL(p,0,0); p += 2; /* Reserved ? */
1947 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1948 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1949 len = srvstr_push(base_data, flags2, p,
1950 fname, PTR_DIFF(end_data, p),
1951 STR_TERMINATE_ASCII);
1955 len = PTR_DIFF(p, pdata);
1956 pad = (len + (align-1)) & ~(align-1);
1958 * offset to the next entry, the caller
1959 * will overwrite it for the last entry
1960 * that's why we always include the padding
1964 * set padding to zero
1967 memset(p, 0, pad - len);
1974 /* CIFS UNIX Extension. */
1976 case SMB_FIND_FILE_UNIX:
1977 case SMB_FIND_FILE_UNIX_INFO2:
1979 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1981 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1983 if (info_level == SMB_FIND_FILE_UNIX) {
1984 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1985 p = store_file_unix_basic(conn, p,
1986 NULL, &smb_fname->st);
1987 len = srvstr_push(base_data, flags2, p,
1988 fname, PTR_DIFF(end_data, p),
1991 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1992 p = store_file_unix_basic_info2(conn, p,
1993 NULL, &smb_fname->st);
1996 len = srvstr_push(base_data, flags2, p, fname,
1997 PTR_DIFF(end_data, p), 0);
1998 SIVAL(nameptr, 0, len);
2003 len = PTR_DIFF(p, pdata);
2004 pad = (len + (align-1)) & ~(align-1);
2006 * offset to the next entry, the caller
2007 * will overwrite it for the last entry
2008 * that's why we always include the padding
2012 * set padding to zero
2015 memset(p, 0, pad - len);
2020 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2028 if (PTR_DIFF(p,pdata) > space_remaining) {
2029 *out_of_space = true;
2030 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2031 return false; /* Not finished - just out of space */
2034 /* Setup the last entry pointer, as an offset from base_data */
2035 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2036 /* Advance the data pointer to the next slot */
2042 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2043 connection_struct *conn,
2044 struct dptr_struct *dirptr,
2046 const char *path_mask,
2049 int requires_resume_key,
2057 int space_remaining,
2059 bool *got_exact_match,
2060 int *_last_entry_off,
2061 struct ea_list *name_list)
2064 const char *mask = NULL;
2065 long prev_dirpos = 0;
2068 struct smb_filename *smb_fname = NULL;
2069 struct smbd_dirptr_lanman2_state state;
2071 uint64_t last_entry_off = 0;
2075 state.info_level = info_level;
2076 state.check_mangled_names = lp_manglednames(conn->params);
2077 state.has_wild = dptr_has_wild(dirptr);
2078 state.got_exact_match = false;
2080 *out_of_space = false;
2081 *got_exact_match = false;
2083 p = strrchr_m(path_mask,'/');
2094 ok = smbd_dirptr_get_entry(ctx,
2100 smbd_dirptr_lanman2_match_fn,
2101 smbd_dirptr_lanman2_mode_fn,
2111 *got_exact_match = state.got_exact_match;
2113 ok = smbd_marshall_dir_entry(ctx,
2118 state.check_mangled_names,
2119 requires_resume_key,
2132 TALLOC_FREE(smb_fname);
2133 if (*out_of_space) {
2134 dptr_SeekDir(dirptr, prev_dirpos);
2141 *_last_entry_off = last_entry_off;
2145 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2146 connection_struct *conn,
2147 struct dptr_struct *dirptr,
2149 const char *path_mask,
2152 bool requires_resume_key,
2158 int space_remaining,
2160 bool *got_exact_match,
2161 int *last_entry_off,
2162 struct ea_list *name_list)
2165 const bool do_pad = true;
2167 if (info_level >= 1 && info_level <= 3) {
2168 /* No alignment on earlier info levels. */
2172 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2173 path_mask, dirtype, info_level,
2174 requires_resume_key, dont_descend, ask_sharemode,
2176 ppdata, base_data, end_data,
2178 out_of_space, got_exact_match,
2179 last_entry_off, name_list);
2182 /****************************************************************************
2183 Reply to a TRANS2_FINDFIRST.
2184 ****************************************************************************/
2186 static void call_trans2findfirst(connection_struct *conn,
2187 struct smb_request *req,
2188 char **pparams, int total_params,
2189 char **ppdata, int total_data,
2190 unsigned int max_data_bytes)
2192 /* We must be careful here that we don't return more than the
2193 allowed number of data bytes. If this means returning fewer than
2194 maxentries then so be it. We assume that the redirector has
2195 enough room for the fixed number of parameter bytes it has
2197 struct smb_filename *smb_dname = NULL;
2198 char *params = *pparams;
2199 char *pdata = *ppdata;
2203 uint16 findfirst_flags;
2204 bool close_after_first;
2206 bool requires_resume_key;
2208 char *directory = NULL;
2211 int last_entry_off=0;
2215 bool finished = False;
2216 bool dont_descend = False;
2217 bool out_of_space = False;
2218 int space_remaining;
2219 bool mask_contains_wcard = False;
2220 struct ea_list *ea_list = NULL;
2221 NTSTATUS ntstatus = NT_STATUS_OK;
2222 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2223 TALLOC_CTX *ctx = talloc_tos();
2224 struct dptr_struct *dirptr = NULL;
2225 struct smbd_server_connection *sconn = smbd_server_conn;
2227 if (total_params < 13) {
2228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2232 dirtype = SVAL(params,0);
2233 maxentries = SVAL(params,2);
2234 findfirst_flags = SVAL(params,4);
2235 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2236 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2237 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2238 info_level = SVAL(params,6);
2240 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2241 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2242 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2243 info_level, max_data_bytes));
2246 /* W2K3 seems to treat zero as 1. */
2250 switch (info_level) {
2251 case SMB_FIND_INFO_STANDARD:
2252 case SMB_FIND_EA_SIZE:
2253 case SMB_FIND_EA_LIST:
2254 case SMB_FIND_FILE_DIRECTORY_INFO:
2255 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2256 case SMB_FIND_FILE_NAMES_INFO:
2257 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2258 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2259 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2261 case SMB_FIND_FILE_UNIX:
2262 case SMB_FIND_FILE_UNIX_INFO2:
2263 /* Always use filesystem for UNIX mtime query. */
2264 ask_sharemode = false;
2265 if (!lp_unix_extensions()) {
2266 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2271 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2275 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2276 params+12, total_params - 12,
2277 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2278 if (!NT_STATUS_IS_OK(ntstatus)) {
2279 reply_nterror(req, ntstatus);
2283 ntstatus = filename_convert(ctx, conn,
2284 req->flags2 & FLAGS2_DFS_PATHNAMES,
2287 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2288 &mask_contains_wcard,
2290 if (!NT_STATUS_IS_OK(ntstatus)) {
2291 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2292 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2293 ERRSRV, ERRbadpath);
2296 reply_nterror(req, ntstatus);
2300 mask = smb_dname->original_lcomp;
2302 directory = smb_dname->base_name;
2304 p = strrchr_m(directory,'/');
2306 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2307 if((directory[0] == '.') && (directory[1] == '\0')) {
2308 mask = talloc_strdup(ctx,"*");
2310 reply_nterror(req, NT_STATUS_NO_MEMORY);
2313 mask_contains_wcard = True;
2315 directory = talloc_strdup(talloc_tos(), "./");
2317 reply_nterror(req, NT_STATUS_NO_MEMORY);
2324 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2326 if (info_level == SMB_FIND_EA_LIST) {
2329 if (total_data < 4) {
2330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2334 ea_size = IVAL(pdata,0);
2335 if (ea_size != total_data) {
2336 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2337 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2342 if (!lp_ea_support(SNUM(conn))) {
2343 reply_doserror(req, ERRDOS, ERReasnotsupported);
2347 /* Pull out the list of names. */
2348 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2355 *ppdata = (char *)SMB_REALLOC(
2356 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2357 if(*ppdata == NULL ) {
2358 reply_nterror(req, NT_STATUS_NO_MEMORY);
2362 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2364 /* Realloc the params space */
2365 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2366 if (*pparams == NULL) {
2367 reply_nterror(req, NT_STATUS_NO_MEMORY);
2372 /* Save the wildcard match and attribs we are using on this directory -
2373 needed as lanman2 assumes these are being saved between calls */
2375 ntstatus = dptr_create(conn,
2381 mask_contains_wcard,
2385 if (!NT_STATUS_IS_OK(ntstatus)) {
2386 reply_nterror(req, ntstatus);
2390 dptr_num = dptr_dnum(dirptr);
2391 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2393 /* Initialize per TRANS2_FIND_FIRST operation data */
2394 dptr_init_search_op(dirptr);
2396 /* We don't need to check for VOL here as this is returned by
2397 a different TRANS2 call. */
2399 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2400 directory,lp_dontdescend(SNUM(conn))));
2401 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2402 dont_descend = True;
2405 space_remaining = max_data_bytes;
2406 out_of_space = False;
2408 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2409 bool got_exact_match = False;
2411 /* this is a heuristic to avoid seeking the dirptr except when
2412 absolutely necessary. It allows for a filename of about 40 chars */
2413 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2414 out_of_space = True;
2417 finished = !get_lanman2_dir_entry(ctx,
2421 mask,dirtype,info_level,
2422 requires_resume_key,dont_descend,
2425 space_remaining, &out_of_space,
2427 &last_entry_off, ea_list);
2430 if (finished && out_of_space)
2433 if (!finished && !out_of_space)
2437 * As an optimisation if we know we aren't looking
2438 * for a wildcard name (ie. the name matches the wildcard exactly)
2439 * then we can finish on any (first) match.
2440 * This speeds up large directory searches. JRA.
2446 /* Ensure space_remaining never goes -ve. */
2447 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2448 space_remaining = 0;
2449 out_of_space = true;
2451 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2455 /* Check if we can close the dirptr */
2456 if(close_after_first || (finished && close_if_end)) {
2457 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2458 dptr_close(sconn, &dptr_num);
2462 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2463 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2464 * the protocol level is less than NT1. Tested with smbclient. JRA.
2465 * This should fix the OS/2 client bug #2335.
2468 if(numentries == 0) {
2469 dptr_close(sconn, &dptr_num);
2470 if (get_Protocol(sconn) < PROTOCOL_NT1) {
2471 reply_doserror(req, ERRDOS, ERRnofiles);
2474 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2475 ERRDOS, ERRbadfile);
2480 /* At this point pdata points to numentries directory entries. */
2482 /* Set up the return parameter block */
2483 SSVAL(params,0,dptr_num);
2484 SSVAL(params,2,numentries);
2485 SSVAL(params,4,finished);
2486 SSVAL(params,6,0); /* Never an EA error */
2487 SSVAL(params,8,last_entry_off);
2489 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2492 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2493 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2495 reply_nterror(req, NT_STATUS_NO_MEMORY);
2499 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2500 smb_fn_name(req->cmd),
2501 mask, directory, dirtype, numentries ) );
2504 * Force a name mangle here to ensure that the
2505 * mask as an 8.3 name is top of the mangled cache.
2506 * The reasons for this are subtle. Don't remove
2507 * this code unless you know what you are doing
2508 * (see PR#13758). JRA.
2511 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2512 char mangled_name[13];
2513 name_to_8_3(mask, mangled_name, True, conn->params);
2516 TALLOC_FREE(smb_dname);
2520 /****************************************************************************
2521 Reply to a TRANS2_FINDNEXT.
2522 ****************************************************************************/
2524 static void call_trans2findnext(connection_struct *conn,
2525 struct smb_request *req,
2526 char **pparams, int total_params,
2527 char **ppdata, int total_data,
2528 unsigned int max_data_bytes)
2530 /* We must be careful here that we don't return more than the
2531 allowed number of data bytes. If this means returning fewer than
2532 maxentries then so be it. We assume that the redirector has
2533 enough room for the fixed number of parameter bytes it has
2535 char *params = *pparams;
2536 char *pdata = *ppdata;
2542 uint16 findnext_flags;
2543 bool close_after_request;
2545 bool requires_resume_key;
2547 bool mask_contains_wcard = False;
2548 char *resume_name = NULL;
2549 const char *mask = NULL;
2550 const char *directory = NULL;
2554 int i, last_entry_off=0;
2555 bool finished = False;
2556 bool dont_descend = False;
2557 bool out_of_space = False;
2558 int space_remaining;
2559 struct ea_list *ea_list = NULL;
2560 NTSTATUS ntstatus = NT_STATUS_OK;
2561 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2562 TALLOC_CTX *ctx = talloc_tos();
2563 struct dptr_struct *dirptr;
2564 struct smbd_server_connection *sconn = smbd_server_conn;
2566 if (total_params < 13) {
2567 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2571 dptr_num = SVAL(params,0);
2572 maxentries = SVAL(params,2);
2573 info_level = SVAL(params,4);
2574 resume_key = IVAL(params,6);
2575 findnext_flags = SVAL(params,10);
2576 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2577 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2578 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2579 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2581 if (!continue_bit) {
2582 /* We only need resume_name if continue_bit is zero. */
2583 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2585 total_params - 12, STR_TERMINATE, &ntstatus,
2586 &mask_contains_wcard);
2587 if (!NT_STATUS_IS_OK(ntstatus)) {
2588 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2589 complain (it thinks we're asking for the directory above the shared
2590 path or an invalid name). Catch this as the resume name is only compared, never used in
2591 a file access. JRA. */
2592 srvstr_pull_talloc(ctx, params, req->flags2,
2593 &resume_name, params+12,
2597 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2598 reply_nterror(req, ntstatus);
2604 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2605 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2606 resume_key = %d resume name = %s continue=%d level = %d\n",
2607 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2608 requires_resume_key, resume_key,
2609 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2612 /* W2K3 seems to treat zero as 1. */
2616 switch (info_level) {
2617 case SMB_FIND_INFO_STANDARD:
2618 case SMB_FIND_EA_SIZE:
2619 case SMB_FIND_EA_LIST:
2620 case SMB_FIND_FILE_DIRECTORY_INFO:
2621 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2622 case SMB_FIND_FILE_NAMES_INFO:
2623 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2624 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2625 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2627 case SMB_FIND_FILE_UNIX:
2628 case SMB_FIND_FILE_UNIX_INFO2:
2629 /* Always use filesystem for UNIX mtime query. */
2630 ask_sharemode = false;
2631 if (!lp_unix_extensions()) {
2632 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2637 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2641 if (info_level == SMB_FIND_EA_LIST) {
2644 if (total_data < 4) {
2645 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2649 ea_size = IVAL(pdata,0);
2650 if (ea_size != total_data) {
2651 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2652 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2653 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2657 if (!lp_ea_support(SNUM(conn))) {
2658 reply_doserror(req, ERRDOS, ERReasnotsupported);
2662 /* Pull out the list of names. */
2663 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2670 *ppdata = (char *)SMB_REALLOC(
2671 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2672 if(*ppdata == NULL) {
2673 reply_nterror(req, NT_STATUS_NO_MEMORY);
2678 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2680 /* Realloc the params space */
2681 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2682 if(*pparams == NULL ) {
2683 reply_nterror(req, NT_STATUS_NO_MEMORY);
2689 /* Check that the dptr is valid */
2690 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2691 reply_doserror(req, ERRDOS, ERRnofiles);
2695 directory = dptr_path(sconn, dptr_num);
2697 /* Get the wildcard mask from the dptr */
2698 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2699 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2700 reply_doserror(req, ERRDOS, ERRnofiles);
2706 /* Get the attr mask from the dptr */
2707 dirtype = dptr_attr(sconn, dptr_num);
2709 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2710 dptr_num, mask, dirtype,
2712 dptr_TellDir(dirptr)));
2714 /* Initialize per TRANS2_FIND_NEXT operation data */
2715 dptr_init_search_op(dirptr);
2717 /* We don't need to check for VOL here as this is returned by
2718 a different TRANS2 call. */
2720 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2721 directory,lp_dontdescend(SNUM(conn))));
2722 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2723 dont_descend = True;
2726 space_remaining = max_data_bytes;
2727 out_of_space = False;
2730 * Seek to the correct position. We no longer use the resume key but
2731 * depend on the last file name instead.
2734 if(!continue_bit && resume_name && *resume_name) {
2737 long current_pos = 0;
2739 * Remember, name_to_8_3 is called by
2740 * get_lanman2_dir_entry(), so the resume name
2741 * could be mangled. Ensure we check the unmangled name.
2744 if (mangle_is_mangled(resume_name, conn->params)) {
2745 char *new_resume_name = NULL;
2746 mangle_lookup_name_from_8_3(ctx,
2750 if (new_resume_name) {
2751 resume_name = new_resume_name;
2756 * Fix for NT redirector problem triggered by resume key indexes
2757 * changing between directory scans. We now return a resume key of 0
2758 * and instead look for the filename to continue from (also given
2759 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2760 * findfirst/findnext (as is usual) then the directory pointer
2761 * should already be at the correct place.
2764 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2765 } /* end if resume_name && !continue_bit */
2767 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2768 bool got_exact_match = False;
2770 /* this is a heuristic to avoid seeking the dirptr except when
2771 absolutely necessary. It allows for a filename of about 40 chars */
2772 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2773 out_of_space = True;
2776 finished = !get_lanman2_dir_entry(ctx,
2780 mask,dirtype,info_level,
2781 requires_resume_key,dont_descend,
2784 space_remaining, &out_of_space,
2786 &last_entry_off, ea_list);
2789 if (finished && out_of_space)
2792 if (!finished && !out_of_space)
2796 * As an optimisation if we know we aren't looking
2797 * for a wildcard name (ie. the name matches the wildcard exactly)
2798 * then we can finish on any (first) match.
2799 * This speeds up large directory searches. JRA.
2805 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2808 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2809 smb_fn_name(req->cmd),
2810 mask, directory, dirtype, numentries ) );
2812 /* Check if we can close the dirptr */
2813 if(close_after_request || (finished && close_if_end)) {
2814 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2815 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2818 /* Set up the return parameter block */
2819 SSVAL(params,0,numentries);
2820 SSVAL(params,2,finished);
2821 SSVAL(params,4,0); /* Never an EA error */
2822 SSVAL(params,6,last_entry_off);
2824 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2830 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2832 E_md4hash(lp_servicename(SNUM(conn)),objid);
2836 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2838 SMB_ASSERT(extended_info != NULL);
2840 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2841 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2842 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2843 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2844 #ifdef SAMBA_VERSION_REVISION
2845 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2847 extended_info->samba_subversion = 0;
2848 #ifdef SAMBA_VERSION_RC_RELEASE
2849 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2851 #ifdef SAMBA_VERSION_PRE_RELEASE
2852 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2855 #ifdef SAMBA_VERSION_VENDOR_PATCH
2856 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2858 extended_info->samba_gitcommitdate = 0;
2859 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2860 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2863 memset(extended_info->samba_version_string, 0,
2864 sizeof(extended_info->samba_version_string));
2866 snprintf (extended_info->samba_version_string,
2867 sizeof(extended_info->samba_version_string),
2868 "%s", samba_version_string());
2871 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2872 TALLOC_CTX *mem_ctx,
2873 uint16_t info_level,
2875 unsigned int max_data_bytes,
2879 char *pdata, *end_data;
2880 int data_len = 0, len;
2881 const char *vname = volume_label(SNUM(conn));
2882 int snum = SNUM(conn);
2883 char *fstype = lp_fstype(SNUM(conn));
2884 uint32 additional_flags = 0;
2885 struct smb_filename smb_fname_dot;
2889 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2890 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2891 "info level (0x%x) on IPC$.\n",
2892 (unsigned int)info_level));
2893 return NT_STATUS_ACCESS_DENIED;
2897 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2899 ZERO_STRUCT(smb_fname_dot);
2900 smb_fname_dot.base_name = discard_const_p(char, ".");
2902 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2903 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2904 return map_nt_error_from_unix(errno);
2907 st = smb_fname_dot.st;
2909 *ppdata = (char *)SMB_REALLOC(
2910 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2911 if (*ppdata == NULL) {
2912 return NT_STATUS_NO_MEMORY;
2916 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2917 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2919 switch (info_level) {
2920 case SMB_INFO_ALLOCATION:
2922 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2924 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2925 return map_nt_error_from_unix(errno);
2928 block_size = lp_block_size(snum);
2929 if (bsize < block_size) {
2930 uint64_t factor = block_size/bsize;
2935 if (bsize > block_size) {
2936 uint64_t factor = bsize/block_size;
2941 bytes_per_sector = 512;
2942 sectors_per_unit = bsize/bytes_per_sector;
2944 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2945 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2946 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2948 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2949 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2950 SIVAL(pdata,l1_cUnit,dsize);
2951 SIVAL(pdata,l1_cUnitAvail,dfree);
2952 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2956 case SMB_INFO_VOLUME:
2957 /* Return volume name */
2959 * Add volume serial number - hash of a combination of
2960 * the called hostname and the service name.
2962 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2964 * Win2k3 and previous mess this up by sending a name length
2965 * one byte short. I believe only older clients (OS/2 Win9x) use
2966 * this call so try fixing this by adding a terminating null to
2967 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2971 pdata+l2_vol_szVolLabel, vname,
2972 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2973 STR_NOALIGN|STR_TERMINATE);
2974 SCVAL(pdata,l2_vol_cch,len);
2975 data_len = l2_vol_szVolLabel + len;
2976 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2977 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2981 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2982 case SMB_FS_ATTRIBUTE_INFORMATION:
2984 additional_flags = 0;
2985 #if defined(HAVE_SYS_QUOTAS)
2986 additional_flags |= FILE_VOLUME_QUOTAS;
2989 if(lp_nt_acl_support(SNUM(conn))) {
2990 additional_flags |= FILE_PERSISTENT_ACLS;
2993 /* Capabilities are filled in at connection time through STATVFS call */
2994 additional_flags |= conn->fs_capabilities;
2995 additional_flags |= lp_parm_int(conn->params->service,
2996 "share", "fake_fscaps",
2999 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3000 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3001 additional_flags); /* FS ATTRIBUTES */
3003 SIVAL(pdata,4,255); /* Max filename component length */
3004 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3005 and will think we can't do long filenames */
3006 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3007 PTR_DIFF(end_data, pdata+12),
3010 data_len = 12 + len;
3013 case SMB_QUERY_FS_LABEL_INFO:
3014 case SMB_FS_LABEL_INFORMATION:
3015 len = srvstr_push(pdata, flags2, pdata+4, vname,
3016 PTR_DIFF(end_data, pdata+4), 0);
3021 case SMB_QUERY_FS_VOLUME_INFO:
3022 case SMB_FS_VOLUME_INFORMATION:
3025 * Add volume serial number - hash of a combination of
3026 * the called hostname and the service name.
3028 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3029 (str_checksum(get_local_machine_name())<<16));
3031 /* Max label len is 32 characters. */
3032 len = srvstr_push(pdata, flags2, pdata+18, vname,
3033 PTR_DIFF(end_data, pdata+18),
3035 SIVAL(pdata,12,len);
3038 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3039 (int)strlen(vname),vname, lp_servicename(snum)));
3042 case SMB_QUERY_FS_SIZE_INFO:
3043 case SMB_FS_SIZE_INFORMATION:
3045 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3047 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3048 return map_nt_error_from_unix(errno);
3050 block_size = lp_block_size(snum);
3051 if (bsize < block_size) {
3052 uint64_t factor = block_size/bsize;
3057 if (bsize > block_size) {
3058 uint64_t factor = bsize/block_size;
3063 bytes_per_sector = 512;
3064 sectors_per_unit = bsize/bytes_per_sector;
3065 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3066 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3067 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3068 SBIG_UINT(pdata,0,dsize);
3069 SBIG_UINT(pdata,8,dfree);
3070 SIVAL(pdata,16,sectors_per_unit);
3071 SIVAL(pdata,20,bytes_per_sector);
3075 case SMB_FS_FULL_SIZE_INFORMATION:
3077 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3079 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3080 return map_nt_error_from_unix(errno);
3082 block_size = lp_block_size(snum);
3083 if (bsize < block_size) {
3084 uint64_t factor = block_size/bsize;
3089 if (bsize > block_size) {
3090 uint64_t factor = bsize/block_size;
3095 bytes_per_sector = 512;
3096 sectors_per_unit = bsize/bytes_per_sector;
3097 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3098 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3099 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3100 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3101 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3102 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3103 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3104 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3108 case SMB_QUERY_FS_DEVICE_INFO:
3109 case SMB_FS_DEVICE_INFORMATION:
3111 SIVAL(pdata,0,0); /* dev type */
3112 SIVAL(pdata,4,0); /* characteristics */
3115 #ifdef HAVE_SYS_QUOTAS
3116 case SMB_FS_QUOTA_INFORMATION:
3118 * what we have to send --metze:
3120 * Unknown1: 24 NULL bytes
3121 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3122 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3123 * Quota Flags: 2 byte :
3124 * Unknown3: 6 NULL bytes
3128 * details for Quota Flags:
3130 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3131 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3132 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3133 * 0x0001 Enable Quotas: enable quota for this fs
3137 /* we need to fake up a fsp here,
3138 * because its not send in this call
3141 SMB_NTQUOTA_STRUCT quotas;
3144 ZERO_STRUCT(quotas);
3150 if (conn->server_info->utok.uid != sec_initial_uid()) {
3151 DEBUG(0,("set_user_quota: access_denied "
3152 "service [%s] user [%s]\n",
3153 lp_servicename(SNUM(conn)),
3154 conn->server_info->unix_name));
3155 return NT_STATUS_ACCESS_DENIED;
3158 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3159 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3160 return map_nt_error_from_unix(errno);
3165 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3166 lp_servicename(SNUM(conn))));
3168 /* Unknown1 24 NULL bytes*/
3169 SBIG_UINT(pdata,0,(uint64_t)0);
3170 SBIG_UINT(pdata,8,(uint64_t)0);
3171 SBIG_UINT(pdata,16,(uint64_t)0);
3173 /* Default Soft Quota 8 bytes */
3174 SBIG_UINT(pdata,24,quotas.softlim);
3176 /* Default Hard Quota 8 bytes */
3177 SBIG_UINT(pdata,32,quotas.hardlim);
3179 /* Quota flag 2 bytes */
3180 SSVAL(pdata,40,quotas.qflags);
3182 /* Unknown3 6 NULL bytes */
3188 #endif /* HAVE_SYS_QUOTAS */
3189 case SMB_FS_OBJECTID_INFORMATION:
3191 unsigned char objid[16];
3192 struct smb_extended_info extended_info;
3193 memcpy(pdata,create_volume_objectid(conn, objid),16);
3194 samba_extended_info_version (&extended_info);
3195 SIVAL(pdata,16,extended_info.samba_magic);
3196 SIVAL(pdata,20,extended_info.samba_version);
3197 SIVAL(pdata,24,extended_info.samba_subversion);
3198 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3199 memcpy(pdata+36,extended_info.samba_version_string,28);
3205 * Query the version and capabilities of the CIFS UNIX extensions
3209 case SMB_QUERY_CIFS_UNIX_INFO:
3211 bool large_write = lp_min_receive_file_size() &&
3212 !srv_is_signing_active(smbd_server_conn);
3213 bool large_read = !srv_is_signing_active(smbd_server_conn);
3214 int encrypt_caps = 0;
3216 if (!lp_unix_extensions()) {
3217 return NT_STATUS_INVALID_LEVEL;
3220 switch (conn->encrypt_level) {
3226 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3229 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3230 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3231 large_write = false;
3237 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3238 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3240 /* We have POSIX ACLs, pathname, encryption,
3241 * large read/write, and locking capability. */
3243 SBIG_UINT(pdata,4,((uint64_t)(
3244 CIFS_UNIX_POSIX_ACLS_CAP|
3245 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3246 CIFS_UNIX_FCNTL_LOCKS_CAP|
3247 CIFS_UNIX_EXTATTR_CAP|
3248 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3250 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3252 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3256 case SMB_QUERY_POSIX_FS_INFO:
3259 vfs_statvfs_struct svfs;
3261 if (!lp_unix_extensions()) {
3262 return NT_STATUS_INVALID_LEVEL;
3265 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3269 SIVAL(pdata,0,svfs.OptimalTransferSize);
3270 SIVAL(pdata,4,svfs.BlockSize);
3271 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3272 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3273 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3274 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3275 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3276 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3277 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3279 } else if (rc == EOPNOTSUPP) {
3280 return NT_STATUS_INVALID_LEVEL;
3281 #endif /* EOPNOTSUPP */
3283 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3284 return NT_STATUS_DOS(ERRSRV, ERRerror);
3289 case SMB_QUERY_POSIX_WHOAMI:
3295 if (!lp_unix_extensions()) {
3296 return NT_STATUS_INVALID_LEVEL;
3299 if (max_data_bytes < 40) {
3300 return NT_STATUS_BUFFER_TOO_SMALL;
3303 /* We ARE guest if global_sid_Builtin_Guests is
3304 * in our list of SIDs.
3306 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3307 conn->server_info->ptok)) {
3308 flags |= SMB_WHOAMI_GUEST;
3311 /* We are NOT guest if global_sid_Authenticated_Users
3312 * is in our list of SIDs.
3314 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3315 conn->server_info->ptok)) {
3316 flags &= ~SMB_WHOAMI_GUEST;
3319 /* NOTE: 8 bytes for UID/GID, irrespective of native
3320 * platform size. This matches
3321 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3323 data_len = 4 /* flags */
3330 + 4 /* pad/reserved */
3331 + (conn->server_info->utok.ngroups * 8)
3333 + (conn->server_info->ptok->num_sids *
3337 SIVAL(pdata, 0, flags);
3338 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3340 (uint64_t)conn->server_info->utok.uid);
3341 SBIG_UINT(pdata, 16,
3342 (uint64_t)conn->server_info->utok.gid);
3345 if (data_len >= max_data_bytes) {
3346 /* Potential overflow, skip the GIDs and SIDs. */
3348 SIVAL(pdata, 24, 0); /* num_groups */
3349 SIVAL(pdata, 28, 0); /* num_sids */
3350 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3351 SIVAL(pdata, 36, 0); /* reserved */
3357 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3358 SIVAL(pdata, 28, conn->server_info->num_sids);
3360 /* We walk the SID list twice, but this call is fairly
3361 * infrequent, and I don't expect that it's performance
3362 * sensitive -- jpeach
3364 for (i = 0, sid_bytes = 0;
3365 i < conn->server_info->ptok->num_sids; ++i) {
3366 sid_bytes += ndr_size_dom_sid(
3367 &conn->server_info->ptok->user_sids[i],
3372 /* SID list byte count */
3373 SIVAL(pdata, 32, sid_bytes);
3375 /* 4 bytes pad/reserved - must be zero */
3376 SIVAL(pdata, 36, 0);
3380 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3381 SBIG_UINT(pdata, data_len,
3382 (uint64_t)conn->server_info->utok.groups[i]);
3388 i < conn->server_info->ptok->num_sids; ++i) {
3389 int sid_len = ndr_size_dom_sid(
3390 &conn->server_info->ptok->user_sids[i],
3394 sid_linearize(pdata + data_len, sid_len,
3395 &conn->server_info->ptok->user_sids[i]);
3396 data_len += sid_len;
3402 case SMB_MAC_QUERY_FS_INFO:
3404 * Thursby MAC extension... ONLY on NTFS filesystems
3405 * once we do streams then we don't need this
3407 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3409 SIVAL(pdata,84,0x100); /* Don't support mac... */
3414 return NT_STATUS_INVALID_LEVEL;
3417 *ret_data_len = data_len;
3418 return NT_STATUS_OK;
3421 /****************************************************************************
3422 Reply to a TRANS2_QFSINFO (query filesystem info).
3423 ****************************************************************************/
3425 static void call_trans2qfsinfo(connection_struct *conn,
3426 struct smb_request *req,
3427 char **pparams, int total_params,
3428 char **ppdata, int total_data,
3429 unsigned int max_data_bytes)
3431 char *params = *pparams;
3432 uint16_t info_level;
3436 if (total_params < 2) {
3437 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3441 info_level = SVAL(params,0);
3443 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3444 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3445 DEBUG(0,("call_trans2qfsinfo: encryption required "
3446 "and info level 0x%x sent.\n",
3447 (unsigned int)info_level));
3448 exit_server_cleanly("encryption required "
3454 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3456 status = smbd_do_qfsinfo(conn, req,
3461 if (!NT_STATUS_IS_OK(status)) {
3462 reply_nterror(req, status);
3466 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3469 DEBUG( 4, ( "%s info_level = %d\n",
3470 smb_fn_name(req->cmd), info_level) );
3475 /****************************************************************************
3476 Reply to a TRANS2_SETFSINFO (set filesystem info).
3477 ****************************************************************************/
3479 static void call_trans2setfsinfo(connection_struct *conn,
3480 struct smb_request *req,
3481 char **pparams, int total_params,
3482 char **ppdata, int total_data,
3483 unsigned int max_data_bytes)
3485 char *pdata = *ppdata;
3486 char *params = *pparams;
3489 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3492 if (total_params < 4) {
3493 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3499 info_level = SVAL(params,2);
3502 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3503 info_level != SMB_SET_CIFS_UNIX_INFO) {
3504 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3505 "info level (0x%x) on IPC$.\n",
3506 (unsigned int)info_level));
3507 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3512 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3513 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3514 DEBUG(0,("call_trans2setfsinfo: encryption required "
3515 "and info level 0x%x sent.\n",
3516 (unsigned int)info_level));
3517 exit_server_cleanly("encryption required "
3523 switch(info_level) {
3524 case SMB_SET_CIFS_UNIX_INFO:
3526 uint16 client_unix_major;
3527 uint16 client_unix_minor;
3528 uint32 client_unix_cap_low;
3529 uint32 client_unix_cap_high;
3531 if (!lp_unix_extensions()) {
3533 NT_STATUS_INVALID_LEVEL);
3537 /* There should be 12 bytes of capabilities set. */
3538 if (total_data < 8) {
3541 NT_STATUS_INVALID_PARAMETER);
3544 client_unix_major = SVAL(pdata,0);
3545 client_unix_minor = SVAL(pdata,2);
3546 client_unix_cap_low = IVAL(pdata,4);
3547 client_unix_cap_high = IVAL(pdata,8);
3548 /* Just print these values for now. */
3549 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3550 cap_low = 0x%x, cap_high = 0x%x\n",
3551 (unsigned int)client_unix_major,
3552 (unsigned int)client_unix_minor,
3553 (unsigned int)client_unix_cap_low,
3554 (unsigned int)client_unix_cap_high ));
3556 /* Here is where we must switch to posix pathname processing... */
3557 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3558 lp_set_posix_pathnames();
3559 mangle_change_to_posix();
3562 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3563 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3564 /* Client that knows how to do posix locks,
3565 * but not posix open/mkdir operations. Set a
3566 * default type for read/write checks. */
3568 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3574 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3577 size_t param_len = 0;
3578 size_t data_len = total_data;
3580 if (!lp_unix_extensions()) {
3583 NT_STATUS_INVALID_LEVEL);
3587 if (lp_smb_encrypt(SNUM(conn)) == false) {
3590 NT_STATUS_NOT_SUPPORTED);
3594 DEBUG( 4,("call_trans2setfsinfo: "
3595 "request transport encryption.\n"));
3597 status = srv_request_encryption_setup(conn,
3598 (unsigned char **)ppdata,
3600 (unsigned char **)pparams,
3603 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3604 !NT_STATUS_IS_OK(status)) {
3605 reply_nterror(req, status);
3609 send_trans2_replies(conn, req,
3616 if (NT_STATUS_IS_OK(status)) {
3617 /* Server-side transport
3618 * encryption is now *on*. */
3619 status = srv_encryption_start(conn);
3620 if (!NT_STATUS_IS_OK(status)) {
3621 exit_server_cleanly(
3622 "Failure in setting "
3623 "up encrypted transport");
3629 case SMB_FS_QUOTA_INFORMATION:
3631 files_struct *fsp = NULL;
3632 SMB_NTQUOTA_STRUCT quotas;
3634 ZERO_STRUCT(quotas);
3637 if ((conn->server_info->utok.uid != sec_initial_uid())
3638 ||!CAN_WRITE(conn)) {
3639 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3640 lp_servicename(SNUM(conn)),
3641 conn->server_info->unix_name));
3642 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3646 /* note: normaly there're 48 bytes,
3647 * but we didn't use the last 6 bytes for now
3650 fsp = file_fsp(req, SVAL(params,0));
3652 if (!check_fsp_ntquota_handle(conn, req,
3654 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3656 req, NT_STATUS_INVALID_HANDLE);
3660 if (total_data < 42) {
3661 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3665 NT_STATUS_INVALID_PARAMETER);
3669 /* unknown_1 24 NULL bytes in pdata*/
3671 /* the soft quotas 8 bytes (uint64_t)*/
3672 quotas.softlim = (uint64_t)IVAL(pdata,24);
3673 #ifdef LARGE_SMB_OFF_T
3674 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3675 #else /* LARGE_SMB_OFF_T */
3676 if ((IVAL(pdata,28) != 0)&&
3677 ((quotas.softlim != 0xFFFFFFFF)||
3678 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3679 /* more than 32 bits? */
3682 NT_STATUS_INVALID_PARAMETER);
3685 #endif /* LARGE_SMB_OFF_T */
3687 /* the hard quotas 8 bytes (uint64_t)*/
3688 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3689 #ifdef LARGE_SMB_OFF_T
3690 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3691 #else /* LARGE_SMB_OFF_T */
3692 if ((IVAL(pdata,36) != 0)&&
3693 ((quotas.hardlim != 0xFFFFFFFF)||
3694 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3695 /* more than 32 bits? */
3698 NT_STATUS_INVALID_PARAMETER);
3701 #endif /* LARGE_SMB_OFF_T */
3703 /* quota_flags 2 bytes **/
3704 quotas.qflags = SVAL(pdata,40);
3706 /* unknown_2 6 NULL bytes follow*/
3708 /* now set the quotas */
3709 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3710 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3711 reply_nterror(req, map_nt_error_from_unix(errno));
3718 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3720 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3726 * sending this reply works fine,
3727 * but I'm not sure it's the same
3728 * like windows do...
3731 reply_outbuf(req, 10, 0);
3734 #if defined(HAVE_POSIX_ACLS)
3735 /****************************************************************************
3736 Utility function to count the number of entries in a POSIX acl.
3737 ****************************************************************************/
3739 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3741 unsigned int ace_count = 0;
3742 int entry_id = SMB_ACL_FIRST_ENTRY;
3743 SMB_ACL_ENTRY_T entry;
3745 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3747 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3748 entry_id = SMB_ACL_NEXT_ENTRY;
3755 /****************************************************************************
3756 Utility function to marshall a POSIX acl into wire format.
3757 ****************************************************************************/
3759 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3761 int entry_id = SMB_ACL_FIRST_ENTRY;
3762 SMB_ACL_ENTRY_T entry;
3764 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3765 SMB_ACL_TAG_T tagtype;
3766 SMB_ACL_PERMSET_T permset;
3767 unsigned char perms = 0;
3768 unsigned int own_grp;
3771 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3772 entry_id = SMB_ACL_NEXT_ENTRY;
3775 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3776 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3780 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3781 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3785 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3786 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3787 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3789 SCVAL(pdata,1,perms);
3792 case SMB_ACL_USER_OBJ:
3793 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3794 own_grp = (unsigned int)pst->st_ex_uid;
3795 SIVAL(pdata,2,own_grp);
3800 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3802 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3805 own_grp = (unsigned int)*puid;
3806 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3807 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3808 SIVAL(pdata,2,own_grp);
3812 case SMB_ACL_GROUP_OBJ:
3813 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3814 own_grp = (unsigned int)pst->st_ex_gid;
3815 SIVAL(pdata,2,own_grp);
3820 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3822 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3825 own_grp = (unsigned int)*pgid;
3826 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3827 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3828 SIVAL(pdata,2,own_grp);
3833 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3834 SIVAL(pdata,2,0xFFFFFFFF);
3835 SIVAL(pdata,6,0xFFFFFFFF);
3838 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3839 SIVAL(pdata,2,0xFFFFFFFF);
3840 SIVAL(pdata,6,0xFFFFFFFF);
3843 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3846 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3853 /****************************************************************************
3854 Store the FILE_UNIX_BASIC info.
3855 ****************************************************************************/
3857 static char *store_file_unix_basic(connection_struct *conn,
3860 const SMB_STRUCT_STAT *psbuf)
3862 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3863 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3865 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3868 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3871 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3872 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3873 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3876 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3880 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3884 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3887 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3891 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3895 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3898 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3902 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3909 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3910 * the chflags(2) (or equivalent) flags.
3912 * XXX: this really should be behind the VFS interface. To do this, we would
3913 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3914 * Each VFS module could then implement its own mapping as appropriate for the
3915 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3917 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3921 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3925 { UF_IMMUTABLE, EXT_IMMUTABLE },
3929 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3933 { UF_HIDDEN, EXT_HIDDEN },
3936 /* Do not remove. We need to guarantee that this array has at least one
3937 * entry to build on HP-UX.
3943 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3944 uint32 *smb_fflags, uint32 *smb_fmask)
3948 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3949 *smb_fmask |= info2_flags_map[i].smb_fflag;
3950 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3951 *smb_fflags |= info2_flags_map[i].smb_fflag;
3956 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3957 const uint32 smb_fflags,
3958 const uint32 smb_fmask,
3961 uint32 max_fmask = 0;
3964 *stat_fflags = psbuf->st_ex_flags;
3966 /* For each flags requested in smb_fmask, check the state of the
3967 * corresponding flag in smb_fflags and set or clear the matching
3971 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3972 max_fmask |= info2_flags_map[i].smb_fflag;
3973 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3974 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3975 *stat_fflags |= info2_flags_map[i].stat_fflag;
3977 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3982 /* If smb_fmask is asking to set any bits that are not supported by
3983 * our flag mappings, we should fail.
3985 if ((smb_fmask & max_fmask) != smb_fmask) {
3993 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3994 * of file flags and birth (create) time.
3996 static char *store_file_unix_basic_info2(connection_struct *conn,
3999 const SMB_STRUCT_STAT *psbuf)
4001 uint32 file_flags = 0;
4002 uint32 flags_mask = 0;
4004 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4006 /* Create (birth) time 64 bit */
4007 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4010 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4011 SIVAL(pdata, 0, file_flags); /* flags */
4012 SIVAL(pdata, 4, flags_mask); /* mask */
4018 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4019 const struct stream_struct *streams,
4021 unsigned int max_data_bytes,
4022 unsigned int *data_size)
4025 unsigned int ofs = 0;
4027 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4028 unsigned int next_offset;
4030 smb_ucs2_t *namebuf;
4032 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4033 streams[i].name, &namelen) ||
4036 return NT_STATUS_INVALID_PARAMETER;
4040 * name_buf is now null-terminated, we need to marshall as not
4046 SIVAL(data, ofs+4, namelen);
4047 SOFF_T(data, ofs+8, streams[i].size);
4048 SOFF_T(data, ofs+16, streams[i].alloc_size);
4049 memcpy(data+ofs+24, namebuf, namelen);
4050 TALLOC_FREE(namebuf);
4052 next_offset = ofs + 24 + namelen;
4054 if (i == num_streams-1) {
4055 SIVAL(data, ofs, 0);
4058 unsigned int align = ndr_align_size(next_offset, 8);
4060 memset(data+next_offset, 0, align);
4061 next_offset += align;
4063 SIVAL(data, ofs, next_offset - ofs);
4072 return NT_STATUS_OK;
4075 /****************************************************************************
4076 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4077 ****************************************************************************/
4079 static void call_trans2qpipeinfo(connection_struct *conn,
4080 struct smb_request *req,
4081 unsigned int tran_call,
4082 char **pparams, int total_params,
4083 char **ppdata, int total_data,
4084 unsigned int max_data_bytes)
4086 char *params = *pparams;
4087 char *pdata = *ppdata;
4088 unsigned int data_size = 0;
4089 unsigned int param_size = 2;
4094 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4098 if (total_params < 4) {
4099 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4103 fsp = file_fsp(req, SVAL(params,0));
4104 if (!fsp_is_np(fsp)) {
4105 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4109 info_level = SVAL(params,2);
4111 *pparams = (char *)SMB_REALLOC(*pparams,2);
4112 if (*pparams == NULL) {
4113 reply_nterror(req, NT_STATUS_NO_MEMORY);
4118 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4119 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4120 if (*ppdata == NULL ) {
4121 reply_nterror(req, NT_STATUS_NO_MEMORY);
4126 switch (info_level) {
4127 case SMB_FILE_STANDARD_INFORMATION:
4129 SOFF_T(pdata,0,4096LL);
4136 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4140 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4146 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4147 TALLOC_CTX *mem_ctx,
4148 uint16_t info_level,
4150 struct smb_filename *smb_fname,
4151 bool delete_pending,
4152 struct timespec write_time_ts,
4154 struct ea_list *ea_list,
4155 int lock_data_count,
4158 unsigned int max_data_bytes,
4160 unsigned int *pdata_size)
4162 char *pdata = *ppdata;
4163 char *dstart, *dend;
4164 unsigned int data_size;
4165 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4166 time_t create_time, mtime, atime, c_time;
4167 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4174 uint64_t file_size = 0;
4176 uint64_t allocation_size = 0;
4177 uint64_t file_index = 0;
4178 uint32_t access_mask = 0;
4180 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4181 return NT_STATUS_INVALID_LEVEL;
4184 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4185 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4186 info_level, max_data_bytes));
4189 mode = dos_mode_msdfs(conn, smb_fname);
4191 mode = dos_mode(conn, smb_fname);
4194 mode = FILE_ATTRIBUTE_NORMAL;
4196 nlink = psbuf->st_ex_nlink;
4198 if (nlink && (mode&aDIR)) {
4202 if ((nlink > 0) && delete_pending) {
4206 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4207 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4208 if (*ppdata == NULL) {
4209 return NT_STATUS_NO_MEMORY;
4213 dend = dstart + data_size - 1;
4215 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4216 update_stat_ex_mtime(psbuf, write_time_ts);
4219 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4220 mtime_ts = psbuf->st_ex_mtime;
4221 atime_ts = psbuf->st_ex_atime;
4222 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4224 if (lp_dos_filetime_resolution(SNUM(conn))) {
4225 dos_filetime_timespec(&create_time_ts);
4226 dos_filetime_timespec(&mtime_ts);
4227 dos_filetime_timespec(&atime_ts);
4228 dos_filetime_timespec(&ctime_ts);
4231 create_time = convert_timespec_to_time_t(create_time_ts);
4232 mtime = convert_timespec_to_time_t(mtime_ts);
4233 atime = convert_timespec_to_time_t(atime_ts);
4234 c_time = convert_timespec_to_time_t(ctime_ts);
4236 p = strrchr_m(smb_fname->base_name,'/');
4238 base_name = smb_fname->base_name;
4242 /* NT expects the name to be in an exact form of the *full*
4243 filename. See the trans2 torture test */
4244 if (ISDOT(base_name)) {
4245 dos_fname = talloc_strdup(mem_ctx, "\\");
4247 return NT_STATUS_NO_MEMORY;
4250 dos_fname = talloc_asprintf(mem_ctx,
4252 smb_fname->base_name);
4254 return NT_STATUS_NO_MEMORY;
4256 if (is_ntfs_stream_smb_fname(smb_fname)) {
4257 dos_fname = talloc_asprintf(dos_fname, "%s",
4258 smb_fname->stream_name);
4260 return NT_STATUS_NO_MEMORY;
4264 string_replace(dos_fname, '/', '\\');
4267 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4270 /* Do we have this path open ? */
4272 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4273 fsp1 = file_find_di_first(fileid);
4274 if (fsp1 && fsp1->initial_allocation_size) {
4275 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4279 if (!(mode & aDIR)) {
4280 file_size = get_file_size_stat(psbuf);
4284 pos = fsp->fh->position_information;
4288 access_mask = fsp->access_mask;
4290 /* GENERIC_EXECUTE mapping from Windows */
4291 access_mask = 0x12019F;
4294 /* This should be an index number - looks like
4297 I think this causes us to fail the IFSKIT
4298 BasicFileInformationTest. -tpot */
4299 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4300 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4302 switch (info_level) {
4303 case SMB_INFO_STANDARD:
4304 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4306 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4307 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4308 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4309 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4310 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4311 SSVAL(pdata,l1_attrFile,mode);
4314 case SMB_INFO_QUERY_EA_SIZE:
4316 unsigned int ea_size =
4317 estimate_ea_size(conn, fsp,
4318 smb_fname->base_name);
4319 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4321 srv_put_dos_date2(pdata,0,create_time);
4322 srv_put_dos_date2(pdata,4,atime);
4323 srv_put_dos_date2(pdata,8,mtime); /* write time */
4324 SIVAL(pdata,12,(uint32)file_size);
4325 SIVAL(pdata,16,(uint32)allocation_size);
4326 SSVAL(pdata,20,mode);
4327 SIVAL(pdata,22,ea_size);
4331 case SMB_INFO_IS_NAME_VALID:
4332 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4334 /* os/2 needs this ? really ?*/
4335 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4337 /* This is only reached for qpathinfo */
4341 case SMB_INFO_QUERY_EAS_FROM_LIST:
4343 size_t total_ea_len = 0;
4344 struct ea_list *ea_file_list = NULL;
4346 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4349 get_ea_list_from_file(mem_ctx, conn, fsp,
4350 smb_fname->base_name,
4352 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4354 if (!ea_list || (total_ea_len > data_size)) {
4356 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4360 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4364 case SMB_INFO_QUERY_ALL_EAS:
4366 /* We have data_size bytes to put EA's into. */
4367 size_t total_ea_len = 0;
4369 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4371 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4372 smb_fname->base_name,
4374 if (!ea_list || (total_ea_len > data_size)) {
4376 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4380 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4384 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4386 /* This is FileFullEaInformation - 0xF which maps to
4387 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4389 /* We have data_size bytes to put EA's into. */
4390 size_t total_ea_len = 0;
4391 struct ea_list *ea_file_list = NULL;
4393 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4395 /*TODO: add filtering and index handling */
4398 get_ea_list_from_file(mem_ctx, conn, fsp,
4399 smb_fname->base_name,
4401 if (!ea_file_list) {
4402 return NT_STATUS_NO_EAS_ON_FILE;
4405 status = fill_ea_chained_buffer(mem_ctx,
4409 conn, ea_file_list);
4410 if (!NT_STATUS_IS_OK(status)) {
4416 case SMB_FILE_BASIC_INFORMATION:
4417 case SMB_QUERY_FILE_BASIC_INFO:
4419 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4420 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4421 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4423 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4427 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4428 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4429 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4430 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4431 SIVAL(pdata,32,mode);
4433 DEBUG(5,("SMB_QFBI - "));
4434 DEBUG(5,("create: %s ", ctime(&create_time)));
4435 DEBUG(5,("access: %s ", ctime(&atime)));
4436 DEBUG(5,("write: %s ", ctime(&mtime)));
4437 DEBUG(5,("change: %s ", ctime(&c_time)));
4438 DEBUG(5,("mode: %x\n", mode));
4441 case SMB_FILE_STANDARD_INFORMATION:
4442 case SMB_QUERY_FILE_STANDARD_INFO:
4444 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4446 SOFF_T(pdata,0,allocation_size);
4447 SOFF_T(pdata,8,file_size);
4448 SIVAL(pdata,16,nlink);
4449 SCVAL(pdata,20,delete_pending?1:0);
4450 SCVAL(pdata,21,(mode&aDIR)?1:0);
4451 SSVAL(pdata,22,0); /* Padding. */
4454 case SMB_FILE_EA_INFORMATION:
4455 case SMB_QUERY_FILE_EA_INFO:
4457 unsigned int ea_size =
4458 estimate_ea_size(conn, fsp, smb_fname->base_name);
4459 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4461 SIVAL(pdata,0,ea_size);
4465 /* Get the 8.3 name - used if NT SMB was negotiated. */
4466 case SMB_QUERY_FILE_ALT_NAME_INFO:
4467 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4470 char mangled_name[13];
4471 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4472 if (!name_to_8_3(base_name,mangled_name,
4473 True,conn->params)) {
4474 return NT_STATUS_NO_MEMORY;
4476 len = srvstr_push(dstart, flags2,
4477 pdata+4, mangled_name,
4478 PTR_DIFF(dend, pdata+4),
4480 data_size = 4 + len;
4485 case SMB_QUERY_FILE_NAME_INFO:
4489 this must be *exactly* right for ACLs on mapped drives to work
4491 len = srvstr_push(dstart, flags2,
4493 PTR_DIFF(dend, pdata+4),
4495 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4496 data_size = 4 + len;
4501 case SMB_FILE_ALLOCATION_INFORMATION:
4502 case SMB_QUERY_FILE_ALLOCATION_INFO:
4503 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4505 SOFF_T(pdata,0,allocation_size);
4508 case SMB_FILE_END_OF_FILE_INFORMATION:
4509 case SMB_QUERY_FILE_END_OF_FILEINFO:
4510 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4512 SOFF_T(pdata,0,file_size);
4515 case SMB_QUERY_FILE_ALL_INFO:
4516 case SMB_FILE_ALL_INFORMATION:
4519 unsigned int ea_size =
4520 estimate_ea_size(conn, fsp, smb_fname->base_name);
4521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4522 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4523 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4524 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4525 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4526 SIVAL(pdata,32,mode);
4527 SIVAL(pdata,36,0); /* padding. */
4529 SOFF_T(pdata,0,allocation_size);
4530 SOFF_T(pdata,8,file_size);
4531 SIVAL(pdata,16,nlink);
4532 SCVAL(pdata,20,delete_pending);
4533 SCVAL(pdata,21,(mode&aDIR)?1:0);
4536 SIVAL(pdata,0,ea_size);
4537 pdata += 4; /* EA info */
4538 len = srvstr_push(dstart, flags2,
4540 PTR_DIFF(dend, pdata+4),
4544 data_size = PTR_DIFF(pdata,(*ppdata));
4548 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4551 unsigned int ea_size =
4552 estimate_ea_size(conn, fsp, smb_fname->base_name);
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4554 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4555 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4556 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4557 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4558 SIVAL(pdata, 0x20, mode);
4559 SIVAL(pdata, 0x24, 0); /* padding. */
4560 SBVAL(pdata, 0x28, allocation_size);
4561 SBVAL(pdata, 0x30, file_size);
4562 SIVAL(pdata, 0x38, nlink);
4563 SCVAL(pdata, 0x3C, delete_pending);
4564 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4565 SSVAL(pdata, 0x3E, 0); /* padding */
4566 SBVAL(pdata, 0x40, file_index);
4567 SIVAL(pdata, 0x48, ea_size);
4568 SIVAL(pdata, 0x4C, access_mask);
4569 SBVAL(pdata, 0x50, pos);
4570 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4571 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4575 len = srvstr_push(dstart, flags2,
4577 PTR_DIFF(dend, pdata+4),
4581 data_size = PTR_DIFF(pdata,(*ppdata));
4584 case SMB_FILE_INTERNAL_INFORMATION:
4586 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4587 SBVAL(pdata, 0, file_index);
4591 case SMB_FILE_ACCESS_INFORMATION:
4592 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4593 SIVAL(pdata, 0, access_mask);
4597 case SMB_FILE_NAME_INFORMATION:
4598 /* Pathname with leading '\'. */
4601 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4603 SIVAL(pdata,0,byte_len);
4604 data_size = 4 + byte_len;
4608 case SMB_FILE_DISPOSITION_INFORMATION:
4609 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4611 SCVAL(pdata,0,delete_pending);
4614 case SMB_FILE_POSITION_INFORMATION:
4615 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4617 SOFF_T(pdata,0,pos);
4620 case SMB_FILE_MODE_INFORMATION:
4621 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4622 SIVAL(pdata,0,mode);
4626 case SMB_FILE_ALIGNMENT_INFORMATION:
4627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4628 SIVAL(pdata,0,0); /* No alignment needed. */
4633 * NT4 server just returns "invalid query" to this - if we try
4634 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4637 /* The first statement above is false - verified using Thursby
4638 * client against NT4 -- gcolley.
4640 case SMB_QUERY_FILE_STREAM_INFO:
4641 case SMB_FILE_STREAM_INFORMATION: {
4642 unsigned int num_streams;
4643 struct stream_struct *streams;
4645 DEBUG(10,("smbd_do_qfilepathinfo: "
4646 "SMB_FILE_STREAM_INFORMATION\n"));
4648 if (is_ntfs_stream_smb_fname(smb_fname)) {
4649 return NT_STATUS_INVALID_PARAMETER;
4652 status = SMB_VFS_STREAMINFO(
4653 conn, fsp, smb_fname->base_name, talloc_tos(),
4654 &num_streams, &streams);
4656 if (!NT_STATUS_IS_OK(status)) {
4657 DEBUG(10, ("could not get stream info: %s\n",
4658 nt_errstr(status)));
4662 status = marshall_stream_info(num_streams, streams,
4663 pdata, max_data_bytes,
4666 if (!NT_STATUS_IS_OK(status)) {
4667 DEBUG(10, ("marshall_stream_info failed: %s\n",
4668 nt_errstr(status)));
4672 TALLOC_FREE(streams);
4676 case SMB_QUERY_COMPRESSION_INFO:
4677 case SMB_FILE_COMPRESSION_INFORMATION:
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4679 SOFF_T(pdata,0,file_size);
4680 SIVAL(pdata,8,0); /* ??? */
4681 SIVAL(pdata,12,0); /* ??? */
4685 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4686 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4687 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4688 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4689 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4690 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4691 SOFF_T(pdata,32,allocation_size);
4692 SOFF_T(pdata,40,file_size);
4693 SIVAL(pdata,48,mode);
4694 SIVAL(pdata,52,0); /* ??? */
4698 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4699 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4700 SIVAL(pdata,0,mode);
4706 * CIFS UNIX Extensions.
4709 case SMB_QUERY_FILE_UNIX_BASIC:
4711 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4712 data_size = PTR_DIFF(pdata,(*ppdata));
4716 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4718 for (i=0; i<100; i++)
4719 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4725 case SMB_QUERY_FILE_UNIX_INFO2:
4727 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4728 data_size = PTR_DIFF(pdata,(*ppdata));
4732 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4734 for (i=0; i<100; i++)
4735 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4741 case SMB_QUERY_FILE_UNIX_LINK:
4744 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4747 return NT_STATUS_NO_MEMORY;
4750 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4752 if(!S_ISLNK(psbuf->st_ex_mode)) {
4753 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4756 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4758 len = SMB_VFS_READLINK(conn,
4759 smb_fname->base_name,
4762 return map_nt_error_from_unix(errno);
4765 len = srvstr_push(dstart, flags2,
4767 PTR_DIFF(dend, pdata),
4770 data_size = PTR_DIFF(pdata,(*ppdata));
4775 #if defined(HAVE_POSIX_ACLS)
4776 case SMB_QUERY_POSIX_ACL:
4778 SMB_ACL_T file_acl = NULL;
4779 SMB_ACL_T def_acl = NULL;
4780 uint16 num_file_acls = 0;
4781 uint16 num_def_acls = 0;
4783 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4784 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4787 SMB_VFS_SYS_ACL_GET_FILE(conn,
4788 smb_fname->base_name,
4789 SMB_ACL_TYPE_ACCESS);
4792 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4793 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4794 "not implemented on "
4795 "filesystem containing %s\n",
4796 smb_fname->base_name));
4797 return NT_STATUS_NOT_IMPLEMENTED;
4800 if (S_ISDIR(psbuf->st_ex_mode)) {
4801 if (fsp && fsp->is_directory) {
4803 SMB_VFS_SYS_ACL_GET_FILE(
4805 fsp->fsp_name->base_name,
4806 SMB_ACL_TYPE_DEFAULT);
4809 SMB_VFS_SYS_ACL_GET_FILE(
4811 smb_fname->base_name,
4812 SMB_ACL_TYPE_DEFAULT);
4814 def_acl = free_empty_sys_acl(conn, def_acl);
4817 num_file_acls = count_acl_entries(conn, file_acl);
4818 num_def_acls = count_acl_entries(conn, def_acl);
4820 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4821 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4823 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4824 SMB_POSIX_ACL_HEADER_SIZE) ));
4826 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4829 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4831 return NT_STATUS_BUFFER_TOO_SMALL;
4834 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4835 SSVAL(pdata,2,num_file_acls);
4836 SSVAL(pdata,4,num_def_acls);
4837 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4839 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4842 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4844 return NT_STATUS_INTERNAL_ERROR;
4846 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4848 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4851 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4853 return NT_STATUS_INTERNAL_ERROR;
4857 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4860 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4862 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4868 case SMB_QUERY_POSIX_LOCK:
4873 enum brl_type lock_type;
4875 /* We need an open file with a real fd for this. */
4876 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4877 return NT_STATUS_INVALID_LEVEL;
4880 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4881 return NT_STATUS_INVALID_PARAMETER;
4884 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4885 case POSIX_LOCK_TYPE_READ:
4886 lock_type = READ_LOCK;
4888 case POSIX_LOCK_TYPE_WRITE:
4889 lock_type = WRITE_LOCK;
4891 case POSIX_LOCK_TYPE_UNLOCK:
4893 /* There's no point in asking for an unlock... */
4894 return NT_STATUS_INVALID_PARAMETER;
4897 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4898 #if defined(HAVE_LONGLONG)
4899 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4900 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4901 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4902 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4903 #else /* HAVE_LONGLONG */
4904 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4905 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4906 #endif /* HAVE_LONGLONG */
4908 status = query_lock(fsp,
4915 if (ERROR_WAS_LOCK_DENIED(status)) {
4916 /* Here we need to report who has it locked... */
4917 data_size = POSIX_LOCK_DATA_SIZE;
4919 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4920 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4921 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4922 #if defined(HAVE_LONGLONG)
4923 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4924 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4925 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4926 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4927 #else /* HAVE_LONGLONG */
4928 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4929 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4930 #endif /* HAVE_LONGLONG */
4932 } else if (NT_STATUS_IS_OK(status)) {
4933 /* For success we just return a copy of what we sent
4934 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4935 data_size = POSIX_LOCK_DATA_SIZE;
4936 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4937 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4945 return NT_STATUS_INVALID_LEVEL;
4948 *pdata_size = data_size;
4949 return NT_STATUS_OK;
4952 /****************************************************************************
4953 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4954 file name or file id).
4955 ****************************************************************************/
4957 static void call_trans2qfilepathinfo(connection_struct *conn,
4958 struct smb_request *req,
4959 unsigned int tran_call,
4960 char **pparams, int total_params,
4961 char **ppdata, int total_data,
4962 unsigned int max_data_bytes)
4964 char *params = *pparams;
4965 char *pdata = *ppdata;
4967 unsigned int data_size = 0;
4968 unsigned int param_size = 2;
4969 struct smb_filename *smb_fname = NULL;
4970 bool delete_pending = False;
4971 struct timespec write_time_ts;
4972 files_struct *fsp = NULL;
4973 struct file_id fileid;
4974 struct ea_list *ea_list = NULL;
4975 int lock_data_count = 0;
4976 char *lock_data = NULL;
4977 bool ms_dfs_link = false;
4978 NTSTATUS status = NT_STATUS_OK;
4981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4985 ZERO_STRUCT(write_time_ts);
4987 if (tran_call == TRANSACT2_QFILEINFO) {
4988 if (total_params < 4) {
4989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4994 call_trans2qpipeinfo(conn, req, tran_call,
4995 pparams, total_params,
5001 fsp = file_fsp(req, SVAL(params,0));
5002 info_level = SVAL(params,2);
5004 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5006 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5007 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5011 /* Initial check for valid fsp ptr. */
5012 if (!check_fsp_open(conn, req, fsp)) {
5016 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5018 if (!NT_STATUS_IS_OK(status)) {
5019 reply_nterror(req, status);
5023 if(fsp->fake_file_handle) {
5025 * This is actually for the QUOTA_FAKE_FILE --metze
5028 /* We know this name is ok, it's already passed the checks. */
5030 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5032 * This is actually a QFILEINFO on a directory
5033 * handle (returned from an NT SMB). NT5.0 seems
5034 * to do this call. JRA.
5037 if (INFO_LEVEL_IS_UNIX(info_level)) {
5038 /* Always do lstat for UNIX calls. */
5039 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5040 DEBUG(3,("call_trans2qfilepathinfo: "
5041 "SMB_VFS_LSTAT of %s failed "
5043 smb_fname_str_dbg(smb_fname),
5046 map_nt_error_from_unix(errno));
5049 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5050 DEBUG(3,("call_trans2qfilepathinfo: "
5051 "SMB_VFS_STAT of %s failed (%s)\n",
5052 smb_fname_str_dbg(smb_fname),
5055 map_nt_error_from_unix(errno));
5059 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5060 get_file_infos(fileid, &delete_pending, &write_time_ts);
5063 * Original code - this is an open file.
5065 if (!check_fsp(conn, req, fsp)) {
5069 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5070 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5071 fsp->fnum, strerror(errno)));
5073 map_nt_error_from_unix(errno));
5076 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5077 get_file_infos(fileid, &delete_pending, &write_time_ts);
5084 if (total_params < 7) {
5085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5089 info_level = SVAL(params,0);
5091 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5093 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5094 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5098 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5100 STR_TERMINATE, &status);
5101 if (!NT_STATUS_IS_OK(status)) {
5102 reply_nterror(req, status);
5106 status = filename_convert(req,
5108 req->flags2 & FLAGS2_DFS_PATHNAMES,
5113 if (!NT_STATUS_IS_OK(status)) {
5114 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5115 reply_botherror(req,
5116 NT_STATUS_PATH_NOT_COVERED,
5117 ERRSRV, ERRbadpath);
5120 reply_nterror(req, status);
5124 /* If this is a stream, check if there is a delete_pending. */
5125 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5126 && is_ntfs_stream_smb_fname(smb_fname)) {
5127 struct smb_filename *smb_fname_base = NULL;
5129 /* Create an smb_filename with stream_name == NULL. */
5131 create_synthetic_smb_fname(talloc_tos(),
5132 smb_fname->base_name,
5135 if (!NT_STATUS_IS_OK(status)) {
5136 reply_nterror(req, status);
5140 if (INFO_LEVEL_IS_UNIX(info_level)) {
5141 /* Always do lstat for UNIX calls. */
5142 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5143 DEBUG(3,("call_trans2qfilepathinfo: "
5144 "SMB_VFS_LSTAT of %s failed "
5146 smb_fname_str_dbg(smb_fname_base),
5148 TALLOC_FREE(smb_fname_base);
5150 map_nt_error_from_unix(errno));
5154 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5155 DEBUG(3,("call_trans2qfilepathinfo: "
5156 "fileinfo of %s failed "
5158 smb_fname_str_dbg(smb_fname_base),
5160 TALLOC_FREE(smb_fname_base);
5162 map_nt_error_from_unix(errno));
5167 fileid = vfs_file_id_from_sbuf(conn,
5168 &smb_fname_base->st);
5169 TALLOC_FREE(smb_fname_base);
5170 get_file_infos(fileid, &delete_pending, NULL);
5171 if (delete_pending) {
5172 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5177 if (INFO_LEVEL_IS_UNIX(info_level)) {
5178 /* Always do lstat for UNIX calls. */
5179 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5180 DEBUG(3,("call_trans2qfilepathinfo: "
5181 "SMB_VFS_LSTAT of %s failed (%s)\n",
5182 smb_fname_str_dbg(smb_fname),
5185 map_nt_error_from_unix(errno));
5189 } else if (!VALID_STAT(smb_fname->st) &&
5190 SMB_VFS_STAT(conn, smb_fname) &&
5191 (info_level != SMB_INFO_IS_NAME_VALID)) {
5192 ms_dfs_link = check_msdfs_link(conn,
5193 smb_fname->base_name,
5197 DEBUG(3,("call_trans2qfilepathinfo: "
5198 "SMB_VFS_STAT of %s failed (%s)\n",
5199 smb_fname_str_dbg(smb_fname),
5202 map_nt_error_from_unix(errno));
5207 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5208 get_file_infos(fileid, &delete_pending, &write_time_ts);
5209 if (delete_pending) {
5210 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5215 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5216 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5217 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5219 /* Pull out any data sent here before we realloc. */
5220 switch (info_level) {
5221 case SMB_INFO_QUERY_EAS_FROM_LIST:
5223 /* Pull any EA list from the data portion. */
5226 if (total_data < 4) {
5228 req, NT_STATUS_INVALID_PARAMETER);
5231 ea_size = IVAL(pdata,0);
5233 if (total_data > 0 && ea_size != total_data) {
5234 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5235 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5237 req, NT_STATUS_INVALID_PARAMETER);
5241 if (!lp_ea_support(SNUM(conn))) {
5242 reply_doserror(req, ERRDOS,
5243 ERReasnotsupported);
5247 /* Pull out the list of names. */
5248 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5251 req, NT_STATUS_INVALID_PARAMETER);
5257 case SMB_QUERY_POSIX_LOCK:
5259 if (fsp == NULL || fsp->fh->fd == -1) {
5260 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5264 if (total_data != POSIX_LOCK_DATA_SIZE) {
5266 req, NT_STATUS_INVALID_PARAMETER);
5270 /* Copy the lock range data. */
5271 lock_data = (char *)TALLOC_MEMDUP(
5272 req, pdata, total_data);
5274 reply_nterror(req, NT_STATUS_NO_MEMORY);
5277 lock_data_count = total_data;
5283 *pparams = (char *)SMB_REALLOC(*pparams,2);
5284 if (*pparams == NULL) {
5285 reply_nterror(req, NT_STATUS_NO_MEMORY);
5292 * draft-leach-cifs-v1-spec-02.txt
5293 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5296 * The requested information is placed in the Data portion of the
5297 * transaction response. For the information levels greater than 0x100,
5298 * the transaction response has 1 parameter word which should be
5299 * ignored by the client.
5301 * However Windows only follows this rule for the IS_NAME_VALID call.
5303 switch (info_level) {
5304 case SMB_INFO_IS_NAME_VALID:
5309 if ((info_level & 0xFF00) == 0xFF00) {
5311 * We use levels that start with 0xFF00
5312 * internally to represent SMB2 specific levels
5314 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5318 status = smbd_do_qfilepathinfo(conn, req, info_level,
5320 delete_pending, write_time_ts,
5321 ms_dfs_link, ea_list,
5322 lock_data_count, lock_data,
5323 req->flags2, max_data_bytes,
5324 ppdata, &data_size);
5325 if (!NT_STATUS_IS_OK(status)) {
5326 reply_nterror(req, status);
5330 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5336 /****************************************************************************
5337 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5339 ****************************************************************************/
5341 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5342 connection_struct *conn,
5343 const struct smb_filename *smb_fname_old,
5344 const struct smb_filename *smb_fname_new)
5346 NTSTATUS status = NT_STATUS_OK;
5348 /* source must already exist. */
5349 if (!VALID_STAT(smb_fname_old->st)) {
5350 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5353 /* Disallow if newname already exists. */
5354 if (VALID_STAT(smb_fname_new->st)) {
5355 return NT_STATUS_OBJECT_NAME_COLLISION;
5358 /* No links from a directory. */
5359 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5360 return NT_STATUS_FILE_IS_A_DIRECTORY;
5363 /* Setting a hardlink to/from a stream isn't currently supported. */
5364 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5365 is_ntfs_stream_smb_fname(smb_fname_new)) {
5366 return NT_STATUS_INVALID_PARAMETER;
5369 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5370 smb_fname_old->base_name, smb_fname_new->base_name));
5372 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5373 smb_fname_new->base_name) != 0) {
5374 status = map_nt_error_from_unix(errno);
5375 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5376 nt_errstr(status), smb_fname_old->base_name,
5377 smb_fname_new->base_name));
5382 /****************************************************************************
5383 Deal with setting the time from any of the setfilepathinfo functions.
5384 ****************************************************************************/
5386 NTSTATUS smb_set_file_time(connection_struct *conn,
5388 const struct smb_filename *smb_fname,
5389 struct smb_file_time *ft,
5390 bool setting_write_time)
5392 struct smb_filename smb_fname_base;
5394 FILE_NOTIFY_CHANGE_LAST_ACCESS
5395 |FILE_NOTIFY_CHANGE_LAST_WRITE
5396 |FILE_NOTIFY_CHANGE_CREATION;
5398 if (!VALID_STAT(smb_fname->st)) {
5399 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5402 /* get some defaults (no modifications) if any info is zero or -1. */
5403 if (null_timespec(ft->create_time)) {
5404 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5407 if (null_timespec(ft->atime)) {
5408 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5411 if (null_timespec(ft->mtime)) {
5412 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5415 if (!setting_write_time) {
5416 /* ft->mtime comes from change time, not write time. */
5417 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5420 /* Ensure the resolution is the correct for
5421 * what we can store on this filesystem. */
5423 round_timespec(conn->ts_res, &ft->create_time);
5424 round_timespec(conn->ts_res, &ft->ctime);
5425 round_timespec(conn->ts_res, &ft->atime);
5426 round_timespec(conn->ts_res, &ft->mtime);
5428 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5429 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5430 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5431 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5432 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5433 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5434 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5435 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5437 if (setting_write_time) {
5439 * This was a Windows setfileinfo on an open file.
5440 * NT does this a lot. We also need to
5441 * set the time here, as it can be read by
5442 * FindFirst/FindNext and with the patch for bug #2045
5443 * in smbd/fileio.c it ensures that this timestamp is
5444 * kept sticky even after a write. We save the request
5445 * away and will set it on file close and after a write. JRA.
5448 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5449 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5452 if (fsp->base_fsp) {
5453 set_sticky_write_time_fsp(fsp->base_fsp,
5456 set_sticky_write_time_fsp(fsp, ft->mtime);
5459 set_sticky_write_time_path(
5460 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5465 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5467 /* Always call ntimes on the base, even if a stream was passed in. */
5468 smb_fname_base = *smb_fname;
5469 smb_fname_base.stream_name = NULL;
5471 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5472 return map_nt_error_from_unix(errno);
5475 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5476 smb_fname->base_name);
5477 return NT_STATUS_OK;
5480 /****************************************************************************
5481 Deal with setting the dosmode from any of the setfilepathinfo functions.
5482 ****************************************************************************/
5484 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5485 const struct smb_filename *smb_fname,
5488 struct smb_filename *smb_fname_base = NULL;
5491 if (!VALID_STAT(smb_fname->st)) {
5492 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5495 /* Always operate on the base_name, even if a stream was passed in. */
5496 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5497 NULL, &smb_fname->st,
5499 if (!NT_STATUS_IS_OK(status)) {
5504 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5511 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5513 /* check the mode isn't different, before changing it */
5514 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5515 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5516 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5517 (unsigned int)dosmode));
5519 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5521 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5523 smb_fname_str_dbg(smb_fname_base),
5525 status = map_nt_error_from_unix(errno);
5529 status = NT_STATUS_OK;
5531 TALLOC_FREE(smb_fname_base);
5535 /****************************************************************************
5536 Deal with setting the size from any of the setfilepathinfo functions.
5537 ****************************************************************************/
5539 static NTSTATUS smb_set_file_size(connection_struct *conn,
5540 struct smb_request *req,
5542 const struct smb_filename *smb_fname,
5543 const SMB_STRUCT_STAT *psbuf,
5546 NTSTATUS status = NT_STATUS_OK;
5547 struct smb_filename *smb_fname_tmp = NULL;
5548 files_struct *new_fsp = NULL;
5550 if (!VALID_STAT(*psbuf)) {
5551 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5554 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5556 if (size == get_file_size_stat(psbuf)) {
5557 return NT_STATUS_OK;
5560 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5561 smb_fname_str_dbg(smb_fname), (double)size));
5563 if (fsp && fsp->fh->fd != -1) {
5564 /* Handle based call. */
5565 if (vfs_set_filelen(fsp, size) == -1) {
5566 return map_nt_error_from_unix(errno);
5568 trigger_write_time_update_immediate(fsp);
5569 return NT_STATUS_OK;
5572 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5573 if (!NT_STATUS_IS_OK(status)) {
5577 smb_fname_tmp->st = *psbuf;
5579 status = SMB_VFS_CREATE_FILE(
5582 0, /* root_dir_fid */
5583 smb_fname_tmp, /* fname */
5584 FILE_WRITE_ATTRIBUTES, /* access_mask */
5585 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5587 FILE_OPEN, /* create_disposition*/
5588 0, /* create_options */
5589 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5590 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5591 0, /* allocation_size */
5594 &new_fsp, /* result */
5597 TALLOC_FREE(smb_fname_tmp);
5599 if (!NT_STATUS_IS_OK(status)) {
5600 /* NB. We check for open_was_deferred in the caller. */
5604 if (vfs_set_filelen(new_fsp, size) == -1) {
5605 status = map_nt_error_from_unix(errno);
5606 close_file(req, new_fsp,NORMAL_CLOSE);
5610 trigger_write_time_update_immediate(new_fsp);
5611 close_file(req, new_fsp,NORMAL_CLOSE);
5612 return NT_STATUS_OK;
5615 /****************************************************************************
5616 Deal with SMB_INFO_SET_EA.
5617 ****************************************************************************/
5619 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5623 const struct smb_filename *smb_fname)
5625 struct ea_list *ea_list = NULL;
5626 TALLOC_CTX *ctx = NULL;
5627 NTSTATUS status = NT_STATUS_OK;
5629 if (total_data < 10) {
5631 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5632 length. They seem to have no effect. Bug #3212. JRA */
5634 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5635 /* We're done. We only get EA info in this call. */
5636 return NT_STATUS_OK;
5639 return NT_STATUS_INVALID_PARAMETER;
5642 if (IVAL(pdata,0) > total_data) {
5643 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5644 IVAL(pdata,0), (unsigned int)total_data));
5645 return NT_STATUS_INVALID_PARAMETER;
5649 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5651 return NT_STATUS_INVALID_PARAMETER;
5653 status = set_ea(conn, fsp, smb_fname, ea_list);
5658 /****************************************************************************
5659 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5660 ****************************************************************************/
5662 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5667 struct ea_list *ea_list = NULL;
5671 return NT_STATUS_INVALID_HANDLE;
5674 if (!lp_ea_support(SNUM(conn))) {
5675 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5676 "EA's not supported.\n",
5677 (unsigned int)total_data));
5678 return NT_STATUS_EAS_NOT_SUPPORTED;
5681 if (total_data < 10) {
5682 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5684 (unsigned int)total_data));
5685 return NT_STATUS_INVALID_PARAMETER;
5688 ea_list = read_nttrans_ea_list(talloc_tos(),
5693 return NT_STATUS_INVALID_PARAMETER;
5695 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5697 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5698 smb_fname_str_dbg(fsp->fsp_name),
5699 nt_errstr(status) ));
5705 /****************************************************************************
5706 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5707 ****************************************************************************/
5709 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5713 struct smb_filename *smb_fname)
5715 NTSTATUS status = NT_STATUS_OK;
5716 bool delete_on_close;
5719 if (total_data < 1) {
5720 return NT_STATUS_INVALID_PARAMETER;
5724 return NT_STATUS_INVALID_HANDLE;
5727 delete_on_close = (CVAL(pdata,0) ? True : False);
5728 dosmode = dos_mode(conn, smb_fname);
5730 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5731 "delete_on_close = %u\n",
5732 smb_fname_str_dbg(smb_fname),
5733 (unsigned int)dosmode,
5734 (unsigned int)delete_on_close ));
5736 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5738 if (!NT_STATUS_IS_OK(status)) {
5742 /* The set is across all open files on this dev/inode pair. */
5743 if (!set_delete_on_close(fsp, delete_on_close,
5744 &conn->server_info->utok)) {
5745 return NT_STATUS_ACCESS_DENIED;
5747 return NT_STATUS_OK;
5750 /****************************************************************************
5751 Deal with SMB_FILE_POSITION_INFORMATION.
5752 ****************************************************************************/
5754 static NTSTATUS smb_file_position_information(connection_struct *conn,
5759 uint64_t position_information;
5761 if (total_data < 8) {
5762 return NT_STATUS_INVALID_PARAMETER;
5766 /* Ignore on pathname based set. */
5767 return NT_STATUS_OK;
5770 position_information = (uint64_t)IVAL(pdata,0);
5771 #ifdef LARGE_SMB_OFF_T
5772 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5773 #else /* LARGE_SMB_OFF_T */
5774 if (IVAL(pdata,4) != 0) {
5775 /* more than 32 bits? */
5776 return NT_STATUS_INVALID_PARAMETER;
5778 #endif /* LARGE_SMB_OFF_T */
5780 DEBUG(10,("smb_file_position_information: Set file position "
5781 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5782 (double)position_information));
5783 fsp->fh->position_information = position_information;
5784 return NT_STATUS_OK;
5787 /****************************************************************************
5788 Deal with SMB_FILE_MODE_INFORMATION.
5789 ****************************************************************************/
5791 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5797 if (total_data < 4) {
5798 return NT_STATUS_INVALID_PARAMETER;
5800 mode = IVAL(pdata,0);
5801 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5802 return NT_STATUS_INVALID_PARAMETER;
5804 return NT_STATUS_OK;
5807 /****************************************************************************
5808 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5809 ****************************************************************************/
5811 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5812 struct smb_request *req,
5815 const struct smb_filename *smb_fname)
5817 char *link_target = NULL;
5818 const char *newname = smb_fname->base_name;
5819 NTSTATUS status = NT_STATUS_OK;
5820 TALLOC_CTX *ctx = talloc_tos();
5822 /* Set a symbolic link. */
5823 /* Don't allow this if follow links is false. */
5825 if (total_data == 0) {
5826 return NT_STATUS_INVALID_PARAMETER;
5829 if (!lp_symlinks(SNUM(conn))) {
5830 return NT_STATUS_ACCESS_DENIED;
5833 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5834 total_data, STR_TERMINATE);
5837 return NT_STATUS_INVALID_PARAMETER;
5840 /* !widelinks forces the target path to be within the share. */
5841 /* This means we can interpret the target as a pathname. */
5842 if (!lp_widelinks(SNUM(conn))) {
5843 char *rel_name = NULL;
5844 char *last_dirp = NULL;
5846 if (*link_target == '/') {
5847 /* No absolute paths allowed. */
5848 return NT_STATUS_ACCESS_DENIED;
5850 rel_name = talloc_strdup(ctx,newname);
5852 return NT_STATUS_NO_MEMORY;
5854 last_dirp = strrchr_m(rel_name, '/');
5856 last_dirp[1] = '\0';
5858 rel_name = talloc_strdup(ctx,"./");
5860 return NT_STATUS_NO_MEMORY;
5863 rel_name = talloc_asprintf_append(rel_name,
5867 return NT_STATUS_NO_MEMORY;
5870 status = check_name(conn, rel_name);
5871 if (!NT_STATUS_IS_OK(status)) {
5876 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5877 newname, link_target ));
5879 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5880 return map_nt_error_from_unix(errno);
5883 return NT_STATUS_OK;
5886 /****************************************************************************
5887 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5888 ****************************************************************************/
5890 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5891 struct smb_request *req,
5892 const char *pdata, int total_data,
5893 const struct smb_filename *smb_fname_new)
5895 char *oldname = NULL;
5896 struct smb_filename *smb_fname_old = NULL;
5897 TALLOC_CTX *ctx = talloc_tos();
5898 NTSTATUS status = NT_STATUS_OK;
5900 /* Set a hard link. */
5901 if (total_data == 0) {
5902 return NT_STATUS_INVALID_PARAMETER;
5905 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5906 total_data, STR_TERMINATE, &status);
5907 if (!NT_STATUS_IS_OK(status)) {
5911 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5912 smb_fname_str_dbg(smb_fname_new), oldname));
5914 status = filename_convert(ctx,
5916 req->flags2 & FLAGS2_DFS_PATHNAMES,
5921 if (!NT_STATUS_IS_OK(status)) {
5925 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5928 /****************************************************************************
5929 Deal with SMB_FILE_RENAME_INFORMATION.
5930 ****************************************************************************/
5932 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5933 struct smb_request *req,
5937 struct smb_filename *smb_fname_src)
5942 char *newname = NULL;
5943 struct smb_filename *smb_fname_dst = NULL;
5944 bool dest_has_wcard = False;
5945 NTSTATUS status = NT_STATUS_OK;
5947 TALLOC_CTX *ctx = talloc_tos();
5949 if (total_data < 13) {
5950 return NT_STATUS_INVALID_PARAMETER;
5953 overwrite = (CVAL(pdata,0) ? True : False);
5954 root_fid = IVAL(pdata,4);
5955 len = IVAL(pdata,8);
5957 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5958 return NT_STATUS_INVALID_PARAMETER;
5961 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5964 if (!NT_STATUS_IS_OK(status)) {
5968 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5971 status = resolve_dfspath_wcard(ctx, conn,
5972 req->flags2 & FLAGS2_DFS_PATHNAMES,
5976 if (!NT_STATUS_IS_OK(status)) {
5980 /* Check the new name has no '/' characters. */
5981 if (strchr_m(newname, '/')) {
5982 return NT_STATUS_NOT_SUPPORTED;
5985 if (fsp && fsp->base_fsp) {
5986 /* newname must be a stream name. */
5987 if (newname[0] != ':') {
5988 return NT_STATUS_NOT_SUPPORTED;
5991 /* Create an smb_fname to call rename_internals_fsp() with. */
5992 status = create_synthetic_smb_fname(talloc_tos(),
5993 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5995 if (!NT_STATUS_IS_OK(status)) {
6000 * Set the original last component, since
6001 * rename_internals_fsp() requires it.
6003 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6005 if (smb_fname_dst->original_lcomp == NULL) {
6006 status = NT_STATUS_NO_MEMORY;
6012 * Build up an smb_fname_dst based on the filename passed in.
6013 * We basically just strip off the last component, and put on
6014 * the newname instead.
6016 char *base_name = NULL;
6018 /* newname must *not* be a stream name. */
6019 if (newname[0] == ':') {
6020 return NT_STATUS_NOT_SUPPORTED;
6024 * Strip off the last component (filename) of the path passed
6027 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6029 return NT_STATUS_NO_MEMORY;
6031 p = strrchr_m(base_name, '/');
6035 base_name = talloc_strdup(ctx, "./");
6037 return NT_STATUS_NO_MEMORY;
6040 /* Append the new name. */
6041 base_name = talloc_asprintf_append(base_name,
6045 return NT_STATUS_NO_MEMORY;
6048 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6051 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6054 /* If an error we expect this to be
6055 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6057 if (!NT_STATUS_IS_OK(status)) {
6058 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6062 /* Create an smb_fname to call rename_internals_fsp() */
6063 status = create_synthetic_smb_fname(ctx,
6067 if (!NT_STATUS_IS_OK(status)) {
6074 DEBUG(10,("smb_file_rename_information: "
6075 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6076 fsp->fnum, fsp_str_dbg(fsp),
6077 smb_fname_str_dbg(smb_fname_dst)));
6078 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6081 DEBUG(10,("smb_file_rename_information: "
6082 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6083 smb_fname_str_dbg(smb_fname_src),
6084 smb_fname_str_dbg(smb_fname_dst)));
6085 status = rename_internals(ctx, conn, req, smb_fname_src,
6086 smb_fname_dst, 0, overwrite, false,
6088 FILE_WRITE_ATTRIBUTES);
6091 TALLOC_FREE(smb_fname_dst);
6095 /****************************************************************************
6096 Deal with SMB_SET_POSIX_ACL.
6097 ****************************************************************************/
6099 #if defined(HAVE_POSIX_ACLS)
6100 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6104 const struct smb_filename *smb_fname)
6106 uint16 posix_acl_version;
6107 uint16 num_file_acls;
6108 uint16 num_def_acls;
6109 bool valid_file_acls = True;
6110 bool valid_def_acls = True;
6112 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6113 return NT_STATUS_INVALID_PARAMETER;
6115 posix_acl_version = SVAL(pdata,0);
6116 num_file_acls = SVAL(pdata,2);
6117 num_def_acls = SVAL(pdata,4);
6119 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6120 valid_file_acls = False;
6124 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6125 valid_def_acls = False;
6129 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6130 return NT_STATUS_INVALID_PARAMETER;
6133 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6134 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6135 return NT_STATUS_INVALID_PARAMETER;
6138 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6139 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6140 (unsigned int)num_file_acls,
6141 (unsigned int)num_def_acls));
6143 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6144 smb_fname->base_name, num_file_acls,
6145 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6146 return map_nt_error_from_unix(errno);
6149 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6150 smb_fname->base_name, &smb_fname->st, num_def_acls,
6151 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6152 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6153 return map_nt_error_from_unix(errno);
6155 return NT_STATUS_OK;
6159 /****************************************************************************
6160 Deal with SMB_SET_POSIX_LOCK.
6161 ****************************************************************************/
6163 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6164 struct smb_request *req,
6172 bool blocking_lock = False;
6173 enum brl_type lock_type;
6175 NTSTATUS status = NT_STATUS_OK;
6177 if (fsp == NULL || fsp->fh->fd == -1) {
6178 return NT_STATUS_INVALID_HANDLE;
6181 if (total_data != POSIX_LOCK_DATA_SIZE) {
6182 return NT_STATUS_INVALID_PARAMETER;
6185 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6186 case POSIX_LOCK_TYPE_READ:
6187 lock_type = READ_LOCK;
6189 case POSIX_LOCK_TYPE_WRITE:
6190 /* Return the right POSIX-mappable error code for files opened read-only. */
6191 if (!fsp->can_write) {
6192 return NT_STATUS_INVALID_HANDLE;
6194 lock_type = WRITE_LOCK;
6196 case POSIX_LOCK_TYPE_UNLOCK:
6197 lock_type = UNLOCK_LOCK;
6200 return NT_STATUS_INVALID_PARAMETER;
6203 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6204 blocking_lock = False;
6205 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6206 blocking_lock = True;
6208 return NT_STATUS_INVALID_PARAMETER;
6211 if (!lp_blocking_locks(SNUM(conn))) {
6212 blocking_lock = False;
6215 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6216 #if defined(HAVE_LONGLONG)
6217 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6218 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6219 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6220 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6221 #else /* HAVE_LONGLONG */
6222 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6223 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6224 #endif /* HAVE_LONGLONG */
6226 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6227 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6229 (unsigned int)lock_type,
6230 (unsigned int)lock_pid,
6234 if (lock_type == UNLOCK_LOCK) {
6235 status = do_unlock(smbd_messaging_context(),
6242 uint32 block_smbpid;
6244 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6256 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6258 * A blocking lock was requested. Package up
6259 * this smb into a queued request and push it
6260 * onto the blocking lock queue.
6262 if(push_blocking_lock_request(br_lck,
6265 -1, /* infinite timeout. */
6273 TALLOC_FREE(br_lck);
6277 TALLOC_FREE(br_lck);
6283 /****************************************************************************
6284 Deal with SMB_SET_FILE_BASIC_INFO.
6285 ****************************************************************************/
6287 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6291 const struct smb_filename *smb_fname)
6293 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6294 struct smb_file_time ft;
6296 NTSTATUS status = NT_STATUS_OK;
6300 if (total_data < 36) {
6301 return NT_STATUS_INVALID_PARAMETER;
6304 /* Set the attributes */
6305 dosmode = IVAL(pdata,32);
6306 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6307 if (!NT_STATUS_IS_OK(status)) {
6312 ft.create_time = interpret_long_date(pdata);
6315 ft.atime = interpret_long_date(pdata+8);
6318 ft.mtime = interpret_long_date(pdata+16);
6321 ft.ctime = interpret_long_date(pdata+24);
6323 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6324 smb_fname_str_dbg(smb_fname)));
6326 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6330 /****************************************************************************
6331 Deal with SMB_INFO_STANDARD.
6332 ****************************************************************************/
6334 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6338 const struct smb_filename *smb_fname)
6340 struct smb_file_time ft;
6344 if (total_data < 12) {
6345 return NT_STATUS_INVALID_PARAMETER;
6349 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6351 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6353 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6355 DEBUG(10,("smb_set_info_standard: file %s\n",
6356 smb_fname_str_dbg(smb_fname)));
6358 return smb_set_file_time(conn,
6365 /****************************************************************************
6366 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6367 ****************************************************************************/
6369 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6370 struct smb_request *req,
6374 struct smb_filename *smb_fname)
6376 uint64_t allocation_size = 0;
6377 NTSTATUS status = NT_STATUS_OK;
6378 files_struct *new_fsp = NULL;
6380 if (!VALID_STAT(smb_fname->st)) {
6381 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6384 if (total_data < 8) {
6385 return NT_STATUS_INVALID_PARAMETER;
6388 allocation_size = (uint64_t)IVAL(pdata,0);
6389 #ifdef LARGE_SMB_OFF_T
6390 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6391 #else /* LARGE_SMB_OFF_T */
6392 if (IVAL(pdata,4) != 0) {
6393 /* more than 32 bits? */
6394 return NT_STATUS_INVALID_PARAMETER;
6396 #endif /* LARGE_SMB_OFF_T */
6398 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6399 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6400 (double)allocation_size));
6402 if (allocation_size) {
6403 allocation_size = smb_roundup(conn, allocation_size);
6406 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6407 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6408 (double)allocation_size));
6410 if (fsp && fsp->fh->fd != -1) {
6411 /* Open file handle. */
6412 /* Only change if needed. */
6413 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6414 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6415 return map_nt_error_from_unix(errno);
6418 /* But always update the time. */
6420 * This is equivalent to a write. Ensure it's seen immediately
6421 * if there are no pending writes.
6423 trigger_write_time_update_immediate(fsp);
6424 return NT_STATUS_OK;
6427 /* Pathname or stat or directory file. */
6428 status = SMB_VFS_CREATE_FILE(
6431 0, /* root_dir_fid */
6432 smb_fname, /* fname */
6433 FILE_WRITE_DATA, /* access_mask */
6434 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6436 FILE_OPEN, /* create_disposition*/
6437 0, /* create_options */
6438 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6439 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6440 0, /* allocation_size */
6443 &new_fsp, /* result */
6446 if (!NT_STATUS_IS_OK(status)) {
6447 /* NB. We check for open_was_deferred in the caller. */
6451 /* Only change if needed. */
6452 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6453 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6454 status = map_nt_error_from_unix(errno);
6455 close_file(req, new_fsp, NORMAL_CLOSE);
6460 /* Changing the allocation size should set the last mod time. */
6462 * This is equivalent to a write. Ensure it's seen immediately
6463 * if there are no pending writes.
6465 trigger_write_time_update_immediate(new_fsp);
6467 close_file(req, new_fsp, NORMAL_CLOSE);
6468 return NT_STATUS_OK;
6471 /****************************************************************************
6472 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6473 ****************************************************************************/
6475 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6476 struct smb_request *req,
6480 const struct smb_filename *smb_fname)
6484 if (total_data < 8) {
6485 return NT_STATUS_INVALID_PARAMETER;
6488 size = IVAL(pdata,0);
6489 #ifdef LARGE_SMB_OFF_T
6490 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6491 #else /* LARGE_SMB_OFF_T */
6492 if (IVAL(pdata,4) != 0) {
6493 /* more than 32 bits? */
6494 return NT_STATUS_INVALID_PARAMETER;
6496 #endif /* LARGE_SMB_OFF_T */
6497 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6498 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6501 return smb_set_file_size(conn, req,
6508 /****************************************************************************
6509 Allow a UNIX info mknod.
6510 ****************************************************************************/
6512 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6515 const struct smb_filename *smb_fname)
6517 uint32 file_type = IVAL(pdata,56);
6518 #if defined(HAVE_MAKEDEV)
6519 uint32 dev_major = IVAL(pdata,60);
6520 uint32 dev_minor = IVAL(pdata,68);
6522 SMB_DEV_T dev = (SMB_DEV_T)0;
6523 uint32 raw_unixmode = IVAL(pdata,84);
6527 if (total_data < 100) {
6528 return NT_STATUS_INVALID_PARAMETER;
6531 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6532 PERM_NEW_FILE, &unixmode);
6533 if (!NT_STATUS_IS_OK(status)) {
6537 #if defined(HAVE_MAKEDEV)
6538 dev = makedev(dev_major, dev_minor);
6541 switch (file_type) {
6542 #if defined(S_IFIFO)
6543 case UNIX_TYPE_FIFO:
6544 unixmode |= S_IFIFO;
6547 #if defined(S_IFSOCK)
6548 case UNIX_TYPE_SOCKET:
6549 unixmode |= S_IFSOCK;
6552 #if defined(S_IFCHR)
6553 case UNIX_TYPE_CHARDEV:
6554 unixmode |= S_IFCHR;
6557 #if defined(S_IFBLK)
6558 case UNIX_TYPE_BLKDEV:
6559 unixmode |= S_IFBLK;
6563 return NT_STATUS_INVALID_PARAMETER;
6566 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6567 "%.0f mode 0%o for file %s\n", (double)dev,
6568 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6570 /* Ok - do the mknod. */
6571 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6572 return map_nt_error_from_unix(errno);
6575 /* If any of the other "set" calls fail we
6576 * don't want to end up with a half-constructed mknod.
6579 if (lp_inherit_perms(SNUM(conn))) {
6581 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6583 return NT_STATUS_NO_MEMORY;
6585 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6587 TALLOC_FREE(parent);
6590 return NT_STATUS_OK;
6593 /****************************************************************************
6594 Deal with SMB_SET_FILE_UNIX_BASIC.
6595 ****************************************************************************/
6597 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6598 struct smb_request *req,
6602 const struct smb_filename *smb_fname)
6604 struct smb_file_time ft;
6605 uint32 raw_unixmode;
6608 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6609 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6610 NTSTATUS status = NT_STATUS_OK;
6611 bool delete_on_fail = False;
6612 enum perm_type ptype;
6613 files_struct *all_fsps = NULL;
6614 bool modify_mtime = true;
6616 SMB_STRUCT_STAT sbuf;
6620 if (total_data < 100) {
6621 return NT_STATUS_INVALID_PARAMETER;
6624 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6625 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6626 size=IVAL(pdata,0); /* first 8 Bytes are size */
6627 #ifdef LARGE_SMB_OFF_T
6628 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6629 #else /* LARGE_SMB_OFF_T */
6630 if (IVAL(pdata,4) != 0) {
6631 /* more than 32 bits? */
6632 return NT_STATUS_INVALID_PARAMETER;
6634 #endif /* LARGE_SMB_OFF_T */
6637 ft.atime = interpret_long_date(pdata+24); /* access_time */
6638 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6639 set_owner = (uid_t)IVAL(pdata,40);
6640 set_grp = (gid_t)IVAL(pdata,48);
6641 raw_unixmode = IVAL(pdata,84);
6643 if (VALID_STAT(smb_fname->st)) {
6644 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6645 ptype = PERM_EXISTING_DIR;
6647 ptype = PERM_EXISTING_FILE;
6650 ptype = PERM_NEW_FILE;
6653 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6655 if (!NT_STATUS_IS_OK(status)) {
6659 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6660 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6661 smb_fname_str_dbg(smb_fname), (double)size,
6662 (unsigned int)set_owner, (unsigned int)set_grp,
6663 (int)raw_unixmode));
6665 sbuf = smb_fname->st;
6667 if (!VALID_STAT(sbuf)) {
6668 struct smb_filename *smb_fname_tmp = NULL;
6670 * The only valid use of this is to create character and block
6671 * devices, and named pipes. This is deprecated (IMHO) and
6672 * a new info level should be used for mknod. JRA.
6675 status = smb_unix_mknod(conn,
6679 if (!NT_STATUS_IS_OK(status)) {
6683 status = copy_smb_filename(talloc_tos(), smb_fname,
6685 if (!NT_STATUS_IS_OK(status)) {
6689 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6690 status = map_nt_error_from_unix(errno);
6691 TALLOC_FREE(smb_fname_tmp);
6692 SMB_VFS_UNLINK(conn, smb_fname);
6696 sbuf = smb_fname_tmp->st;
6697 TALLOC_FREE(smb_fname_tmp);
6699 /* Ensure we don't try and change anything else. */
6700 raw_unixmode = SMB_MODE_NO_CHANGE;
6701 size = get_file_size_stat(&sbuf);
6702 ft.atime = sbuf.st_ex_atime;
6703 ft.mtime = sbuf.st_ex_mtime;
6705 * We continue here as we might want to change the
6708 delete_on_fail = True;
6712 /* Horrible backwards compatibility hack as an old server bug
6713 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6717 size = get_file_size_stat(&sbuf);
6722 * Deal with the UNIX specific mode set.
6725 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6726 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6727 "setting mode 0%o for file %s\n",
6728 (unsigned int)unixmode,
6729 smb_fname_str_dbg(smb_fname)));
6730 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6731 return map_nt_error_from_unix(errno);
6736 * Deal with the UNIX specific uid set.
6739 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6740 (sbuf.st_ex_uid != set_owner)) {
6743 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6744 "changing owner %u for path %s\n",
6745 (unsigned int)set_owner,
6746 smb_fname_str_dbg(smb_fname)));
6748 if (S_ISLNK(sbuf.st_ex_mode)) {
6749 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6750 set_owner, (gid_t)-1);
6752 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6753 set_owner, (gid_t)-1);
6757 status = map_nt_error_from_unix(errno);
6758 if (delete_on_fail) {
6759 SMB_VFS_UNLINK(conn, smb_fname);
6766 * Deal with the UNIX specific gid set.
6769 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6770 (sbuf.st_ex_gid != set_grp)) {
6771 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6772 "changing group %u for file %s\n",
6773 (unsigned int)set_owner,
6774 smb_fname_str_dbg(smb_fname)));
6775 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6777 status = map_nt_error_from_unix(errno);
6778 if (delete_on_fail) {
6779 SMB_VFS_UNLINK(conn, smb_fname);
6785 /* Deal with any size changes. */
6787 status = smb_set_file_size(conn, req,
6792 if (!NT_STATUS_IS_OK(status)) {
6796 /* Deal with any time changes. */
6797 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6798 /* No change, don't cancel anything. */
6802 id = vfs_file_id_from_sbuf(conn, &sbuf);
6803 for(all_fsps = file_find_di_first(id); all_fsps;
6804 all_fsps = file_find_di_next(all_fsps)) {
6806 * We're setting the time explicitly for UNIX.
6807 * Cancel any pending changes over all handles.
6809 all_fsps->update_write_time_on_close = false;
6810 TALLOC_FREE(all_fsps->update_write_time_event);
6814 * Override the "setting_write_time"
6815 * parameter here as it almost does what
6816 * we need. Just remember if we modified
6817 * mtime and send the notify ourselves.
6819 if (null_timespec(ft.mtime)) {
6820 modify_mtime = false;
6823 status = smb_set_file_time(conn,
6829 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6830 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6835 /****************************************************************************
6836 Deal with SMB_SET_FILE_UNIX_INFO2.
6837 ****************************************************************************/
6839 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6840 struct smb_request *req,
6844 const struct smb_filename *smb_fname)
6850 if (total_data < 116) {
6851 return NT_STATUS_INVALID_PARAMETER;
6854 /* Start by setting all the fields that are common between UNIX_BASIC
6857 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6859 if (!NT_STATUS_IS_OK(status)) {
6863 smb_fflags = IVAL(pdata, 108);
6864 smb_fmask = IVAL(pdata, 112);
6866 /* NB: We should only attempt to alter the file flags if the client
6867 * sends a non-zero mask.
6869 if (smb_fmask != 0) {
6870 int stat_fflags = 0;
6872 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6873 smb_fmask, &stat_fflags)) {
6874 /* Client asked to alter a flag we don't understand. */
6875 return NT_STATUS_INVALID_PARAMETER;
6878 if (fsp && fsp->fh->fd != -1) {
6879 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6880 return NT_STATUS_NOT_SUPPORTED;
6882 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6883 stat_fflags) != 0) {
6884 return map_nt_error_from_unix(errno);
6889 /* XXX: need to add support for changing the create_time here. You
6890 * can do this for paths on Darwin with setattrlist(2). The right way
6891 * to hook this up is probably by extending the VFS utimes interface.
6894 return NT_STATUS_OK;
6897 /****************************************************************************
6898 Create a directory with POSIX semantics.
6899 ****************************************************************************/
6901 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6902 struct smb_request *req,
6905 struct smb_filename *smb_fname,
6906 int *pdata_return_size)
6908 NTSTATUS status = NT_STATUS_OK;
6909 uint32 raw_unixmode = 0;
6910 uint32 mod_unixmode = 0;
6911 mode_t unixmode = (mode_t)0;
6912 files_struct *fsp = NULL;
6913 uint16 info_level_return = 0;
6915 char *pdata = *ppdata;
6917 if (total_data < 18) {
6918 return NT_STATUS_INVALID_PARAMETER;
6921 raw_unixmode = IVAL(pdata,8);
6922 /* Next 4 bytes are not yet defined. */
6924 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6925 PERM_NEW_DIR, &unixmode);
6926 if (!NT_STATUS_IS_OK(status)) {
6930 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6932 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6933 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6935 status = SMB_VFS_CREATE_FILE(
6938 0, /* root_dir_fid */
6939 smb_fname, /* fname */
6940 FILE_READ_ATTRIBUTES, /* access_mask */
6941 FILE_SHARE_NONE, /* share_access */
6942 FILE_CREATE, /* create_disposition*/
6943 FILE_DIRECTORY_FILE, /* create_options */
6944 mod_unixmode, /* file_attributes */
6945 0, /* oplock_request */
6946 0, /* allocation_size */
6952 if (NT_STATUS_IS_OK(status)) {
6953 close_file(req, fsp, NORMAL_CLOSE);
6956 info_level_return = SVAL(pdata,16);
6958 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6959 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6960 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6961 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6963 *pdata_return_size = 12;
6966 /* Realloc the data size */
6967 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6968 if (*ppdata == NULL) {
6969 *pdata_return_size = 0;
6970 return NT_STATUS_NO_MEMORY;
6974 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6975 SSVAL(pdata,2,0); /* No fnum. */
6976 SIVAL(pdata,4,info); /* Was directory created. */
6978 switch (info_level_return) {
6979 case SMB_QUERY_FILE_UNIX_BASIC:
6980 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6981 SSVAL(pdata,10,0); /* Padding. */
6982 store_file_unix_basic(conn, pdata + 12, fsp,
6985 case SMB_QUERY_FILE_UNIX_INFO2:
6986 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6987 SSVAL(pdata,10,0); /* Padding. */
6988 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6992 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6993 SSVAL(pdata,10,0); /* Padding. */
7000 /****************************************************************************
7001 Open/Create a file with POSIX semantics.
7002 ****************************************************************************/
7004 static NTSTATUS smb_posix_open(connection_struct *conn,
7005 struct smb_request *req,
7008 struct smb_filename *smb_fname,
7009 int *pdata_return_size)
7011 bool extended_oplock_granted = False;
7012 char *pdata = *ppdata;
7014 uint32 wire_open_mode = 0;
7015 uint32 raw_unixmode = 0;
7016 uint32 mod_unixmode = 0;
7017 uint32 create_disp = 0;
7018 uint32 access_mask = 0;
7019 uint32 create_options = 0;
7020 NTSTATUS status = NT_STATUS_OK;
7021 mode_t unixmode = (mode_t)0;
7022 files_struct *fsp = NULL;
7023 int oplock_request = 0;
7025 uint16 info_level_return = 0;
7027 if (total_data < 18) {
7028 return NT_STATUS_INVALID_PARAMETER;
7031 flags = IVAL(pdata,0);
7032 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7033 if (oplock_request) {
7034 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7037 wire_open_mode = IVAL(pdata,4);
7039 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7040 return smb_posix_mkdir(conn, req,
7047 switch (wire_open_mode & SMB_ACCMODE) {
7049 access_mask = FILE_READ_DATA;
7052 access_mask = FILE_WRITE_DATA;
7055 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7058 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7059 (unsigned int)wire_open_mode ));
7060 return NT_STATUS_INVALID_PARAMETER;
7063 wire_open_mode &= ~SMB_ACCMODE;
7065 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7066 create_disp = FILE_CREATE;
7067 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7068 create_disp = FILE_OVERWRITE_IF;
7069 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7070 create_disp = FILE_OPEN_IF;
7071 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7072 create_disp = FILE_OPEN;
7074 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7075 (unsigned int)wire_open_mode ));
7076 return NT_STATUS_INVALID_PARAMETER;
7079 raw_unixmode = IVAL(pdata,8);
7080 /* Next 4 bytes are not yet defined. */
7082 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7083 (VALID_STAT(smb_fname->st) ?
7084 PERM_EXISTING_FILE : PERM_NEW_FILE),
7087 if (!NT_STATUS_IS_OK(status)) {
7091 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7093 if (wire_open_mode & SMB_O_SYNC) {
7094 create_options |= FILE_WRITE_THROUGH;
7096 if (wire_open_mode & SMB_O_APPEND) {
7097 access_mask |= FILE_APPEND_DATA;
7099 if (wire_open_mode & SMB_O_DIRECT) {
7100 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7103 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7104 smb_fname_str_dbg(smb_fname),
7105 (unsigned int)wire_open_mode,
7106 (unsigned int)unixmode ));
7108 status = SMB_VFS_CREATE_FILE(
7111 0, /* root_dir_fid */
7112 smb_fname, /* fname */
7113 access_mask, /* access_mask */
7114 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7116 create_disp, /* create_disposition*/
7117 FILE_NON_DIRECTORY_FILE, /* create_options */
7118 mod_unixmode, /* file_attributes */
7119 oplock_request, /* oplock_request */
7120 0, /* allocation_size */
7126 if (!NT_STATUS_IS_OK(status)) {
7130 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7131 extended_oplock_granted = True;
7134 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7135 extended_oplock_granted = True;
7138 info_level_return = SVAL(pdata,16);
7140 /* Allocate the correct return size. */
7142 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7143 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7144 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7145 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7147 *pdata_return_size = 12;
7150 /* Realloc the data size */
7151 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7152 if (*ppdata == NULL) {
7153 close_file(req, fsp, ERROR_CLOSE);
7154 *pdata_return_size = 0;
7155 return NT_STATUS_NO_MEMORY;
7159 if (extended_oplock_granted) {
7160 if (flags & REQUEST_BATCH_OPLOCK) {
7161 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7163 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7165 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7166 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7168 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7171 SSVAL(pdata,2,fsp->fnum);
7172 SIVAL(pdata,4,info); /* Was file created etc. */
7174 switch (info_level_return) {
7175 case SMB_QUERY_FILE_UNIX_BASIC:
7176 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7177 SSVAL(pdata,10,0); /* padding. */
7178 store_file_unix_basic(conn, pdata + 12, fsp,
7181 case SMB_QUERY_FILE_UNIX_INFO2:
7182 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7183 SSVAL(pdata,10,0); /* padding. */
7184 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7188 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7189 SSVAL(pdata,10,0); /* padding. */
7192 return NT_STATUS_OK;
7195 /****************************************************************************
7196 Delete a file with POSIX semantics.
7197 ****************************************************************************/
7199 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7200 struct smb_request *req,
7203 struct smb_filename *smb_fname)
7205 NTSTATUS status = NT_STATUS_OK;
7206 files_struct *fsp = NULL;
7210 int create_options = 0;
7212 struct share_mode_lock *lck = NULL;
7214 if (total_data < 2) {
7215 return NT_STATUS_INVALID_PARAMETER;
7218 flags = SVAL(pdata,0);
7220 if (!VALID_STAT(smb_fname->st)) {
7221 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7224 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7225 !VALID_STAT_OF_DIR(smb_fname->st)) {
7226 return NT_STATUS_NOT_A_DIRECTORY;
7229 DEBUG(10,("smb_posix_unlink: %s %s\n",
7230 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7231 smb_fname_str_dbg(smb_fname)));
7233 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7234 create_options |= FILE_DIRECTORY_FILE;
7237 status = SMB_VFS_CREATE_FILE(
7240 0, /* root_dir_fid */
7241 smb_fname, /* fname */
7242 DELETE_ACCESS, /* access_mask */
7243 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7245 FILE_OPEN, /* create_disposition*/
7246 create_options, /* create_options */
7247 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7248 0, /* oplock_request */
7249 0, /* allocation_size */
7255 if (!NT_STATUS_IS_OK(status)) {
7260 * Don't lie to client. If we can't really delete due to
7261 * non-POSIX opens return SHARING_VIOLATION.
7264 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7267 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7268 "lock for file %s\n", fsp_str_dbg(fsp)));
7269 close_file(req, fsp, NORMAL_CLOSE);
7270 return NT_STATUS_INVALID_PARAMETER;
7274 * See if others still have the file open. If this is the case, then
7275 * don't delete. If all opens are POSIX delete we can set the delete
7276 * on close disposition.
7278 for (i=0; i<lck->num_share_modes; i++) {
7279 struct share_mode_entry *e = &lck->share_modes[i];
7280 if (is_valid_share_mode_entry(e)) {
7281 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7284 /* Fail with sharing violation. */
7285 close_file(req, fsp, NORMAL_CLOSE);
7287 return NT_STATUS_SHARING_VIOLATION;
7292 * Set the delete on close.
7294 status = smb_set_file_disposition_info(conn,
7300 if (!NT_STATUS_IS_OK(status)) {
7301 close_file(req, fsp, NORMAL_CLOSE);
7306 return close_file(req, fsp, NORMAL_CLOSE);
7309 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7310 struct smb_request *req,
7311 TALLOC_CTX *mem_ctx,
7312 uint16_t info_level,
7314 struct smb_filename *smb_fname,
7315 char **ppdata, int total_data,
7318 char *pdata = *ppdata;
7319 NTSTATUS status = NT_STATUS_OK;
7320 int data_return_size = 0;
7324 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7325 return NT_STATUS_INVALID_LEVEL;
7328 if (!CAN_WRITE(conn)) {
7329 /* Allow POSIX opens. The open path will deny
7330 * any non-readonly opens. */
7331 if (info_level != SMB_POSIX_PATH_OPEN) {
7332 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7336 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7337 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7338 fsp ? fsp->fnum : -1, info_level, total_data));
7340 switch (info_level) {
7342 case SMB_INFO_STANDARD:
7344 status = smb_set_info_standard(conn,
7352 case SMB_INFO_SET_EA:
7354 status = smb_info_set_ea(conn,
7362 case SMB_SET_FILE_BASIC_INFO:
7363 case SMB_FILE_BASIC_INFORMATION:
7365 status = smb_set_file_basic_info(conn,
7373 case SMB_FILE_ALLOCATION_INFORMATION:
7374 case SMB_SET_FILE_ALLOCATION_INFO:
7376 status = smb_set_file_allocation_info(conn, req,
7384 case SMB_FILE_END_OF_FILE_INFORMATION:
7385 case SMB_SET_FILE_END_OF_FILE_INFO:
7387 status = smb_set_file_end_of_file_info(conn, req,
7395 case SMB_FILE_DISPOSITION_INFORMATION:
7396 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7399 /* JRA - We used to just ignore this on a path ?
7400 * Shouldn't this be invalid level on a pathname
7403 if (tran_call != TRANSACT2_SETFILEINFO) {
7404 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7407 status = smb_set_file_disposition_info(conn,
7415 case SMB_FILE_POSITION_INFORMATION:
7417 status = smb_file_position_information(conn,
7424 case SMB_FILE_FULL_EA_INFORMATION:
7426 status = smb_set_file_full_ea_info(conn,
7433 /* From tridge Samba4 :
7434 * MODE_INFORMATION in setfileinfo (I have no
7435 * idea what "mode information" on a file is - it takes a value of 0,
7436 * 2, 4 or 6. What could it be?).
7439 case SMB_FILE_MODE_INFORMATION:
7441 status = smb_file_mode_information(conn,
7448 * CIFS UNIX extensions.
7451 case SMB_SET_FILE_UNIX_BASIC:
7453 status = smb_set_file_unix_basic(conn, req,
7461 case SMB_SET_FILE_UNIX_INFO2:
7463 status = smb_set_file_unix_info2(conn, req,
7471 case SMB_SET_FILE_UNIX_LINK:
7474 /* We must have a pathname for this. */
7475 return NT_STATUS_INVALID_LEVEL;
7477 status = smb_set_file_unix_link(conn, req, pdata,
7478 total_data, smb_fname);
7482 case SMB_SET_FILE_UNIX_HLINK:
7485 /* We must have a pathname for this. */
7486 return NT_STATUS_INVALID_LEVEL;
7488 status = smb_set_file_unix_hlink(conn, req,
7494 case SMB_FILE_RENAME_INFORMATION:
7496 status = smb_file_rename_information(conn, req,
7502 #if defined(HAVE_POSIX_ACLS)
7503 case SMB_SET_POSIX_ACL:
7505 status = smb_set_posix_acl(conn,
7514 case SMB_SET_POSIX_LOCK:
7517 return NT_STATUS_INVALID_LEVEL;
7519 status = smb_set_posix_lock(conn, req,
7520 pdata, total_data, fsp);
7524 case SMB_POSIX_PATH_OPEN:
7527 /* We must have a pathname for this. */
7528 return NT_STATUS_INVALID_LEVEL;
7531 status = smb_posix_open(conn, req,
7539 case SMB_POSIX_PATH_UNLINK:
7542 /* We must have a pathname for this. */
7543 return NT_STATUS_INVALID_LEVEL;
7546 status = smb_posix_unlink(conn, req,
7554 return NT_STATUS_INVALID_LEVEL;
7557 if (!NT_STATUS_IS_OK(status)) {
7561 *ret_data_size = data_return_size;
7562 return NT_STATUS_OK;
7565 /****************************************************************************
7566 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7567 ****************************************************************************/
7569 static void call_trans2setfilepathinfo(connection_struct *conn,
7570 struct smb_request *req,
7571 unsigned int tran_call,
7572 char **pparams, int total_params,
7573 char **ppdata, int total_data,
7574 unsigned int max_data_bytes)
7576 char *params = *pparams;
7577 char *pdata = *ppdata;
7579 struct smb_filename *smb_fname = NULL;
7580 files_struct *fsp = NULL;
7581 NTSTATUS status = NT_STATUS_OK;
7582 int data_return_size = 0;
7585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7589 if (tran_call == TRANSACT2_SETFILEINFO) {
7590 if (total_params < 4) {
7591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7595 fsp = file_fsp(req, SVAL(params,0));
7596 /* Basic check for non-null fsp. */
7597 if (!check_fsp_open(conn, req, fsp)) {
7600 info_level = SVAL(params,2);
7602 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7604 if (!NT_STATUS_IS_OK(status)) {
7605 reply_nterror(req, status);
7609 if(fsp->is_directory || fsp->fh->fd == -1) {
7611 * This is actually a SETFILEINFO on a directory
7612 * handle (returned from an NT SMB). NT5.0 seems
7613 * to do this call. JRA.
7615 if (INFO_LEVEL_IS_UNIX(info_level)) {
7616 /* Always do lstat for UNIX calls. */
7617 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7618 DEBUG(3,("call_trans2setfilepathinfo: "
7619 "SMB_VFS_LSTAT of %s failed "
7621 smb_fname_str_dbg(smb_fname),
7623 reply_nterror(req, map_nt_error_from_unix(errno));
7627 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7628 DEBUG(3,("call_trans2setfilepathinfo: "
7629 "fileinfo of %s failed (%s)\n",
7630 smb_fname_str_dbg(smb_fname),
7632 reply_nterror(req, map_nt_error_from_unix(errno));
7636 } else if (fsp->print_file) {
7638 * Doing a DELETE_ON_CLOSE should cancel a print job.
7640 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7641 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7643 DEBUG(3,("call_trans2setfilepathinfo: "
7644 "Cancelling print job (%s)\n",
7648 send_trans2_replies(conn, req, params, 2,
7653 reply_doserror(req, ERRDOS, ERRbadpath);
7658 * Original code - this is an open file.
7660 if (!check_fsp(conn, req, fsp)) {
7664 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7665 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7666 "of fnum %d failed (%s)\n", fsp->fnum,
7668 reply_nterror(req, map_nt_error_from_unix(errno));
7676 if (total_params < 7) {
7677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7681 info_level = SVAL(params,0);
7682 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7683 total_params - 6, STR_TERMINATE,
7685 if (!NT_STATUS_IS_OK(status)) {
7686 reply_nterror(req, status);
7690 status = filename_convert(req, conn,
7691 req->flags2 & FLAGS2_DFS_PATHNAMES,
7696 if (!NT_STATUS_IS_OK(status)) {
7697 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7698 reply_botherror(req,
7699 NT_STATUS_PATH_NOT_COVERED,
7700 ERRSRV, ERRbadpath);
7703 reply_nterror(req, status);
7707 if (INFO_LEVEL_IS_UNIX(info_level)) {
7709 * For CIFS UNIX extensions the target name may not exist.
7712 /* Always do lstat for UNIX calls. */
7713 SMB_VFS_LSTAT(conn, smb_fname);
7715 } else if (!VALID_STAT(smb_fname->st) &&
7716 SMB_VFS_STAT(conn, smb_fname)) {
7717 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7719 smb_fname_str_dbg(smb_fname),
7721 reply_nterror(req, map_nt_error_from_unix(errno));
7726 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7727 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7728 fsp ? fsp->fnum : -1, info_level,total_data));
7730 /* Realloc the parameter size */
7731 *pparams = (char *)SMB_REALLOC(*pparams,2);
7732 if (*pparams == NULL) {
7733 reply_nterror(req, NT_STATUS_NO_MEMORY);
7740 status = smbd_do_setfilepathinfo(conn, req, req,
7746 if (!NT_STATUS_IS_OK(status)) {
7747 if (open_was_deferred(req->mid)) {
7748 /* We have re-scheduled this call. */
7751 if (blocking_lock_was_deferred(req->mid)) {
7752 /* We have re-scheduled this call. */
7755 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7756 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7757 ERRSRV, ERRbadpath);
7760 if (info_level == SMB_POSIX_PATH_OPEN) {
7761 reply_openerror(req, status);
7765 reply_nterror(req, status);
7769 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7775 /****************************************************************************
7776 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7777 ****************************************************************************/
7779 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7780 char **pparams, int total_params,
7781 char **ppdata, int total_data,
7782 unsigned int max_data_bytes)
7784 struct smb_filename *smb_dname = NULL;
7785 char *params = *pparams;
7786 char *pdata = *ppdata;
7787 char *directory = NULL;
7788 NTSTATUS status = NT_STATUS_OK;
7789 struct ea_list *ea_list = NULL;
7790 TALLOC_CTX *ctx = talloc_tos();
7792 if (!CAN_WRITE(conn)) {
7793 reply_doserror(req, ERRSRV, ERRaccess);
7797 if (total_params < 5) {
7798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7802 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7803 total_params - 4, STR_TERMINATE,
7805 if (!NT_STATUS_IS_OK(status)) {
7806 reply_nterror(req, status);
7810 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7812 status = filename_convert(ctx,
7814 req->flags2 & FLAGS2_DFS_PATHNAMES,
7820 if (!NT_STATUS_IS_OK(status)) {
7821 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7822 reply_botherror(req,
7823 NT_STATUS_PATH_NOT_COVERED,
7824 ERRSRV, ERRbadpath);
7827 reply_nterror(req, status);
7831 /* Any data in this call is an EA list. */
7832 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7833 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7838 * OS/2 workplace shell seems to send SET_EA requests of "null"
7839 * length (4 bytes containing IVAL 4).
7840 * They seem to have no effect. Bug #3212. JRA.
7843 if (total_data != 4) {
7844 if (total_data < 10) {
7845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7849 if (IVAL(pdata,0) > total_data) {
7850 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7851 IVAL(pdata,0), (unsigned int)total_data));
7852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7856 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7863 /* If total_data == 4 Windows doesn't care what values
7864 * are placed in that field, it just ignores them.
7865 * The System i QNTC IBM SMB client puts bad values here,
7866 * so ignore them. */
7868 status = create_directory(conn, req, smb_dname);
7870 if (!NT_STATUS_IS_OK(status)) {
7871 reply_nterror(req, status);
7875 /* Try and set any given EA. */
7877 status = set_ea(conn, NULL, smb_dname, ea_list);
7878 if (!NT_STATUS_IS_OK(status)) {
7879 reply_nterror(req, status);
7884 /* Realloc the parameter and data sizes */
7885 *pparams = (char *)SMB_REALLOC(*pparams,2);
7886 if(*pparams == NULL) {
7887 reply_nterror(req, NT_STATUS_NO_MEMORY);
7894 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7897 TALLOC_FREE(smb_dname);
7901 /****************************************************************************
7902 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7903 We don't actually do this - we just send a null response.
7904 ****************************************************************************/
7906 static void call_trans2findnotifyfirst(connection_struct *conn,
7907 struct smb_request *req,
7908 char **pparams, int total_params,
7909 char **ppdata, int total_data,
7910 unsigned int max_data_bytes)
7912 char *params = *pparams;
7915 if (total_params < 6) {
7916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7920 info_level = SVAL(params,4);
7921 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7923 switch (info_level) {
7928 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7932 /* Realloc the parameter and data sizes */
7933 *pparams = (char *)SMB_REALLOC(*pparams,6);
7934 if (*pparams == NULL) {
7935 reply_nterror(req, NT_STATUS_NO_MEMORY);
7940 SSVAL(params,0,fnf_handle);
7941 SSVAL(params,2,0); /* No changes */
7942 SSVAL(params,4,0); /* No EA errors */
7949 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7954 /****************************************************************************
7955 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7956 changes). Currently this does nothing.
7957 ****************************************************************************/
7959 static void call_trans2findnotifynext(connection_struct *conn,
7960 struct smb_request *req,
7961 char **pparams, int total_params,
7962 char **ppdata, int total_data,
7963 unsigned int max_data_bytes)
7965 char *params = *pparams;
7967 DEBUG(3,("call_trans2findnotifynext\n"));
7969 /* Realloc the parameter and data sizes */
7970 *pparams = (char *)SMB_REALLOC(*pparams,4);
7971 if (*pparams == NULL) {
7972 reply_nterror(req, NT_STATUS_NO_MEMORY);
7977 SSVAL(params,0,0); /* No changes */
7978 SSVAL(params,2,0); /* No EA errors */
7980 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7985 /****************************************************************************
7986 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7987 ****************************************************************************/
7989 static void call_trans2getdfsreferral(connection_struct *conn,
7990 struct smb_request *req,
7991 char **pparams, int total_params,
7992 char **ppdata, int total_data,
7993 unsigned int max_data_bytes)
7995 char *params = *pparams;
7996 char *pathname = NULL;
7998 int max_referral_level;
7999 NTSTATUS status = NT_STATUS_OK;
8000 TALLOC_CTX *ctx = talloc_tos();
8002 DEBUG(10,("call_trans2getdfsreferral\n"));
8004 if (total_params < 3) {
8005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8009 max_referral_level = SVAL(params,0);
8011 if(!lp_host_msdfs()) {
8012 reply_doserror(req, ERRDOS, ERRbadfunc);
8016 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8017 total_params - 2, STR_TERMINATE);
8019 reply_nterror(req, NT_STATUS_NOT_FOUND);
8022 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8023 ppdata,&status)) < 0) {
8024 reply_nterror(req, status);
8028 SSVAL(req->inbuf, smb_flg2,
8029 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8030 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8035 #define LMCAT_SPL 0x53
8036 #define LMFUNC_GETJOBID 0x60
8038 /****************************************************************************
8039 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8040 ****************************************************************************/
8042 static void call_trans2ioctl(connection_struct *conn,
8043 struct smb_request *req,
8044 char **pparams, int total_params,
8045 char **ppdata, int total_data,
8046 unsigned int max_data_bytes)
8048 char *pdata = *ppdata;
8049 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8051 /* check for an invalid fid before proceeding */
8054 reply_doserror(req, ERRDOS, ERRbadfid);
8058 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8059 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8060 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8061 if (*ppdata == NULL) {
8062 reply_nterror(req, NT_STATUS_NO_MEMORY);
8067 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8068 CAN ACCEPT THIS IN UNICODE. JRA. */
8070 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8071 srvstr_push(pdata, req->flags2, pdata + 2,
8072 global_myname(), 15,
8073 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8074 srvstr_push(pdata, req->flags2, pdata+18,
8075 lp_servicename(SNUM(conn)), 13,
8076 STR_ASCII|STR_TERMINATE); /* Service name */
8077 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8082 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8083 reply_doserror(req, ERRSRV, ERRerror);
8086 /****************************************************************************
8087 Reply to a SMBfindclose (stop trans2 directory search).
8088 ****************************************************************************/
8090 void reply_findclose(struct smb_request *req)
8093 struct smbd_server_connection *sconn = smbd_server_conn;
8095 START_PROFILE(SMBfindclose);
8098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8099 END_PROFILE(SMBfindclose);
8103 dptr_num = SVALS(req->vwv+0, 0);
8105 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8107 dptr_close(sconn, &dptr_num);
8109 reply_outbuf(req, 0, 0);
8111 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8113 END_PROFILE(SMBfindclose);
8117 /****************************************************************************
8118 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8119 ****************************************************************************/
8121 void reply_findnclose(struct smb_request *req)
8125 START_PROFILE(SMBfindnclose);
8128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8129 END_PROFILE(SMBfindnclose);
8133 dptr_num = SVAL(req->vwv+0, 0);
8135 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8137 /* We never give out valid handles for a
8138 findnotifyfirst - so any dptr_num is ok here.
8141 reply_outbuf(req, 0, 0);
8143 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8145 END_PROFILE(SMBfindnclose);
8149 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8150 struct trans_state *state)
8152 if (get_Protocol(req->sconn) >= PROTOCOL_NT1) {
8153 req->flags2 |= 0x40; /* IS_LONG_NAME */
8154 SSVAL(req->inbuf,smb_flg2,req->flags2);
8157 if (conn->encrypt_level == Required && !req->encrypted) {
8158 if (state->call != TRANSACT2_QFSINFO &&
8159 state->call != TRANSACT2_SETFSINFO) {
8160 DEBUG(0,("handle_trans2: encryption required "
8162 (unsigned int)state->call));
8163 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8168 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8170 /* Now we must call the relevant TRANS2 function */
8171 switch(state->call) {
8172 case TRANSACT2_OPEN:
8174 START_PROFILE(Trans2_open);
8175 call_trans2open(conn, req,
8176 &state->param, state->total_param,
8177 &state->data, state->total_data,
8178 state->max_data_return);
8179 END_PROFILE(Trans2_open);
8183 case TRANSACT2_FINDFIRST:
8185 START_PROFILE(Trans2_findfirst);
8186 call_trans2findfirst(conn, req,
8187 &state->param, state->total_param,
8188 &state->data, state->total_data,
8189 state->max_data_return);
8190 END_PROFILE(Trans2_findfirst);
8194 case TRANSACT2_FINDNEXT:
8196 START_PROFILE(Trans2_findnext);
8197 call_trans2findnext(conn, req,
8198 &state->param, state->total_param,
8199 &state->data, state->total_data,
8200 state->max_data_return);
8201 END_PROFILE(Trans2_findnext);
8205 case TRANSACT2_QFSINFO:
8207 START_PROFILE(Trans2_qfsinfo);
8208 call_trans2qfsinfo(conn, req,
8209 &state->param, state->total_param,
8210 &state->data, state->total_data,
8211 state->max_data_return);
8212 END_PROFILE(Trans2_qfsinfo);
8216 case TRANSACT2_SETFSINFO:
8218 START_PROFILE(Trans2_setfsinfo);
8219 call_trans2setfsinfo(conn, req,
8220 &state->param, state->total_param,
8221 &state->data, state->total_data,
8222 state->max_data_return);
8223 END_PROFILE(Trans2_setfsinfo);
8227 case TRANSACT2_QPATHINFO:
8228 case TRANSACT2_QFILEINFO:
8230 START_PROFILE(Trans2_qpathinfo);
8231 call_trans2qfilepathinfo(conn, req, state->call,
8232 &state->param, state->total_param,
8233 &state->data, state->total_data,
8234 state->max_data_return);
8235 END_PROFILE(Trans2_qpathinfo);
8239 case TRANSACT2_SETPATHINFO:
8240 case TRANSACT2_SETFILEINFO:
8242 START_PROFILE(Trans2_setpathinfo);
8243 call_trans2setfilepathinfo(conn, req, state->call,
8244 &state->param, state->total_param,
8245 &state->data, state->total_data,
8246 state->max_data_return);
8247 END_PROFILE(Trans2_setpathinfo);
8251 case TRANSACT2_FINDNOTIFYFIRST:
8253 START_PROFILE(Trans2_findnotifyfirst);
8254 call_trans2findnotifyfirst(conn, req,
8255 &state->param, state->total_param,
8256 &state->data, state->total_data,
8257 state->max_data_return);
8258 END_PROFILE(Trans2_findnotifyfirst);
8262 case TRANSACT2_FINDNOTIFYNEXT:
8264 START_PROFILE(Trans2_findnotifynext);
8265 call_trans2findnotifynext(conn, req,
8266 &state->param, state->total_param,
8267 &state->data, state->total_data,
8268 state->max_data_return);
8269 END_PROFILE(Trans2_findnotifynext);
8273 case TRANSACT2_MKDIR:
8275 START_PROFILE(Trans2_mkdir);
8276 call_trans2mkdir(conn, req,
8277 &state->param, state->total_param,
8278 &state->data, state->total_data,
8279 state->max_data_return);
8280 END_PROFILE(Trans2_mkdir);
8284 case TRANSACT2_GET_DFS_REFERRAL:
8286 START_PROFILE(Trans2_get_dfs_referral);
8287 call_trans2getdfsreferral(conn, req,
8288 &state->param, state->total_param,
8289 &state->data, state->total_data,
8290 state->max_data_return);
8291 END_PROFILE(Trans2_get_dfs_referral);
8295 case TRANSACT2_IOCTL:
8297 START_PROFILE(Trans2_ioctl);
8298 call_trans2ioctl(conn, req,
8299 &state->param, state->total_param,
8300 &state->data, state->total_data,
8301 state->max_data_return);
8302 END_PROFILE(Trans2_ioctl);
8307 /* Error in request */
8308 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8309 reply_doserror(req, ERRSRV,ERRerror);
8313 /****************************************************************************
8314 Reply to a SMBtrans2.
8315 ****************************************************************************/
8317 void reply_trans2(struct smb_request *req)
8319 connection_struct *conn = req->conn;
8324 unsigned int tran_call;
8325 struct trans_state *state;
8328 START_PROFILE(SMBtrans2);
8330 if (req->wct < 14) {
8331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8332 END_PROFILE(SMBtrans2);
8336 dsoff = SVAL(req->vwv+12, 0);
8337 dscnt = SVAL(req->vwv+11, 0);
8338 psoff = SVAL(req->vwv+10, 0);
8339 pscnt = SVAL(req->vwv+9, 0);
8340 tran_call = SVAL(req->vwv+14, 0);
8342 result = allow_new_trans(conn->pending_trans, req->mid);
8343 if (!NT_STATUS_IS_OK(result)) {
8344 DEBUG(2, ("Got invalid trans2 request: %s\n",
8345 nt_errstr(result)));
8346 reply_nterror(req, result);
8347 END_PROFILE(SMBtrans2);
8352 switch (tran_call) {
8353 /* List the allowed trans2 calls on IPC$ */
8354 case TRANSACT2_OPEN:
8355 case TRANSACT2_GET_DFS_REFERRAL:
8356 case TRANSACT2_QFILEINFO:
8357 case TRANSACT2_QFSINFO:
8358 case TRANSACT2_SETFSINFO:
8361 reply_doserror(req, ERRSRV, ERRaccess);
8362 END_PROFILE(SMBtrans2);
8367 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8368 DEBUG(0, ("talloc failed\n"));
8369 reply_nterror(req, NT_STATUS_NO_MEMORY);
8370 END_PROFILE(SMBtrans2);
8374 state->cmd = SMBtrans2;
8376 state->mid = req->mid;
8377 state->vuid = req->vuid;
8378 state->setup_count = SVAL(req->vwv+13, 0);
8379 state->setup = NULL;
8380 state->total_param = SVAL(req->vwv+0, 0);
8381 state->param = NULL;
8382 state->total_data = SVAL(req->vwv+1, 0);
8384 state->max_param_return = SVAL(req->vwv+2, 0);
8385 state->max_data_return = SVAL(req->vwv+3, 0);
8386 state->max_setup_return = SVAL(req->vwv+4, 0);
8387 state->close_on_completion = BITSETW(req->vwv+5, 0);
8388 state->one_way = BITSETW(req->vwv+5, 1);
8390 state->call = tran_call;
8392 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8393 is so as a sanity check */
8394 if (state->setup_count != 1) {
8396 * Need to have rc=0 for ioctl to get job id for OS/2.
8397 * Network printing will fail if function is not successful.
8398 * Similar function in reply.c will be used if protocol
8399 * is LANMAN1.0 instead of LM1.2X002.
8400 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8401 * outbuf doesn't have to be set(only job id is used).
8403 if ( (state->setup_count == 4)
8404 && (tran_call == TRANSACT2_IOCTL)
8405 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8406 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8407 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8409 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8410 DEBUG(2,("Transaction is %d\n",tran_call));
8412 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8413 END_PROFILE(SMBtrans2);
8418 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8421 if (state->total_data) {
8423 if (trans_oob(state->total_data, 0, dscnt)
8424 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8428 /* Can't use talloc here, the core routines do realloc on the
8429 * params and data. */
8430 state->data = (char *)SMB_MALLOC(state->total_data);
8431 if (state->data == NULL) {
8432 DEBUG(0,("reply_trans2: data malloc fail for %u "
8433 "bytes !\n", (unsigned int)state->total_data));
8435 reply_nterror(req, NT_STATUS_NO_MEMORY);
8436 END_PROFILE(SMBtrans2);
8440 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8443 if (state->total_param) {
8445 if (trans_oob(state->total_param, 0, pscnt)
8446 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8450 /* Can't use talloc here, the core routines do realloc on the
8451 * params and data. */
8452 state->param = (char *)SMB_MALLOC(state->total_param);
8453 if (state->param == NULL) {
8454 DEBUG(0,("reply_trans: param malloc fail for %u "
8455 "bytes !\n", (unsigned int)state->total_param));
8456 SAFE_FREE(state->data);
8458 reply_nterror(req, NT_STATUS_NO_MEMORY);
8459 END_PROFILE(SMBtrans2);
8463 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8466 state->received_data = dscnt;
8467 state->received_param = pscnt;
8469 if ((state->received_param == state->total_param) &&
8470 (state->received_data == state->total_data)) {
8472 handle_trans2(conn, req, state);
8474 SAFE_FREE(state->data);
8475 SAFE_FREE(state->param);
8477 END_PROFILE(SMBtrans2);
8481 DLIST_ADD(conn->pending_trans, state);
8483 /* We need to send an interim response then receive the rest
8484 of the parameter/data bytes */
8485 reply_outbuf(req, 0, 0);
8486 show_msg((char *)req->outbuf);
8487 END_PROFILE(SMBtrans2);
8492 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8493 SAFE_FREE(state->data);
8494 SAFE_FREE(state->param);
8496 END_PROFILE(SMBtrans2);
8497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8501 /****************************************************************************
8502 Reply to a SMBtranss2
8503 ****************************************************************************/
8505 void reply_transs2(struct smb_request *req)
8507 connection_struct *conn = req->conn;
8508 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8509 struct trans_state *state;
8511 START_PROFILE(SMBtranss2);
8513 show_msg((char *)req->inbuf);
8516 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8517 END_PROFILE(SMBtranss2);
8521 for (state = conn->pending_trans; state != NULL;
8522 state = state->next) {
8523 if (state->mid == req->mid) {
8528 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8530 END_PROFILE(SMBtranss2);
8534 /* Revise state->total_param and state->total_data in case they have
8535 changed downwards */
8537 if (SVAL(req->vwv+0, 0) < state->total_param)
8538 state->total_param = SVAL(req->vwv+0, 0);
8539 if (SVAL(req->vwv+1, 0) < state->total_data)
8540 state->total_data = SVAL(req->vwv+1, 0);
8542 pcnt = SVAL(req->vwv+2, 0);
8543 poff = SVAL(req->vwv+3, 0);
8544 pdisp = SVAL(req->vwv+4, 0);
8546 dcnt = SVAL(req->vwv+5, 0);
8547 doff = SVAL(req->vwv+6, 0);
8548 ddisp = SVAL(req->vwv+7, 0);
8550 state->received_param += pcnt;
8551 state->received_data += dcnt;
8553 if ((state->received_data > state->total_data) ||
8554 (state->received_param > state->total_param))
8558 if (trans_oob(state->total_param, pdisp, pcnt)
8559 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8562 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8566 if (trans_oob(state->total_data, ddisp, dcnt)
8567 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8570 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8573 if ((state->received_param < state->total_param) ||
8574 (state->received_data < state->total_data)) {
8575 END_PROFILE(SMBtranss2);
8579 handle_trans2(conn, req, state);
8581 DLIST_REMOVE(conn->pending_trans, state);
8582 SAFE_FREE(state->data);
8583 SAFE_FREE(state->param);
8586 END_PROFILE(SMBtranss2);
8591 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8592 DLIST_REMOVE(conn->pending_trans, state);
8593 SAFE_FREE(state->data);
8594 SAFE_FREE(state->param);
8596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8597 END_PROFILE(SMBtranss2);