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 "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 NTSTATUS check_access_fsp(const struct files_struct *fsp,
60 if (!(fsp->access_mask & access_mask)) {
61 return NT_STATUS_ACCESS_DENIED;
66 /********************************************************************
67 The canonical "check access" based on object handle or path function.
68 ********************************************************************/
70 NTSTATUS check_access(connection_struct *conn,
72 const struct smb_filename *smb_fname,
78 status = check_access_fsp(fsp, access_mask);
80 status = smbd_check_access_rights(conn, smb_fname,
87 /********************************************************************
88 Roundup a value to the nearest allocation roundup size boundary.
89 Only do this for Windows clients.
90 ********************************************************************/
92 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
94 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
96 /* Only roundup for Windows clients. */
97 enum remote_arch_types ra_type = get_remote_arch();
98 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
99 val = SMB_ROUNDUP(val,rval);
104 /********************************************************************
105 Create a 64 bit FileIndex. If the file is on the same device as
106 the root of the share, just return the 64-bit inode. If it isn't,
107 mangle as we used to do.
108 ********************************************************************/
110 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
113 if (conn->base_share_dev == psbuf->st_ex_dev) {
114 return (uint64_t)psbuf->st_ex_ino;
116 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
117 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
121 /****************************************************************************
122 Utility functions for dealing with extended attributes.
123 ****************************************************************************/
125 /****************************************************************************
126 Refuse to allow clients to overwrite our private xattrs.
127 ****************************************************************************/
129 bool samba_private_attr_name(const char *unix_ea_name)
131 static const char * const prohibited_ea_names[] = {
132 SAMBA_POSIX_INHERITANCE_EA_NAME,
133 SAMBA_XATTR_DOS_ATTRIB,
141 for (i = 0; prohibited_ea_names[i]; i++) {
142 if (strequal( prohibited_ea_names[i], unix_ea_name))
145 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
146 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
152 /****************************************************************************
153 Get one EA value. Fill in a struct ea_struct.
154 ****************************************************************************/
156 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
157 files_struct *fsp, const char *fname,
158 const char *ea_name, struct ea_struct *pea)
160 /* Get the value of this xattr. Max size is 64k. */
161 size_t attr_size = 256;
167 val = talloc_realloc(mem_ctx, val, char, attr_size);
169 return NT_STATUS_NO_MEMORY;
172 if (fsp && fsp->fh->fd != -1) {
173 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
175 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
178 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
184 return map_nt_error_from_unix(errno);
187 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
188 dump_data(10, (uint8_t *)val, sizeret);
191 if (strnequal(ea_name, "user.", 5)) {
192 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
194 pea->name = talloc_strdup(mem_ctx, ea_name);
196 if (pea->name == NULL) {
198 return NT_STATUS_NO_MEMORY;
200 pea->value.data = (unsigned char *)val;
201 pea->value.length = (size_t)sizeret;
205 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
206 files_struct *fsp, const char *fname,
207 char ***pnames, size_t *pnum_names)
209 /* Get a list of all xattrs. Max namesize is 64k. */
210 size_t ea_namelist_size = 1024;
211 char *ea_namelist = NULL;
216 ssize_t sizeret = -1;
218 if (!lp_ea_support(SNUM(conn))) {
227 * TALLOC the result early to get the talloc hierarchy right.
230 names = talloc_array(mem_ctx, char *, 1);
232 DEBUG(0, ("talloc failed\n"));
233 return NT_STATUS_NO_MEMORY;
236 while (ea_namelist_size <= 65536) {
238 ea_namelist = talloc_realloc(
239 names, ea_namelist, char, ea_namelist_size);
240 if (ea_namelist == NULL) {
241 DEBUG(0, ("talloc failed\n"));
243 return NT_STATUS_NO_MEMORY;
246 if (fsp && fsp->fh->fd != -1) {
247 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
250 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
254 if ((sizeret == -1) && (errno == ERANGE)) {
255 ea_namelist_size *= 2;
264 return map_nt_error_from_unix(errno);
267 DEBUG(10, ("%s: ea_namelist size = %u\n",
268 __func__, (unsigned int)sizeret));
280 * Ensure the result is 0-terminated
283 if (ea_namelist[sizeret-1] != '\0') {
285 return NT_STATUS_INTERNAL_ERROR;
293 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
297 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
299 DEBUG(0, ("talloc failed\n"));
301 return NT_STATUS_NO_MEMORY;
307 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
308 names[num_names++] = p;
316 *pnum_names = num_names;
320 /****************************************************************************
321 Return a linked list of the total EA's. Plus the total size
322 ****************************************************************************/
324 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
325 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
327 /* Get a list of all xattrs. Max namesize is 64k. */
330 struct ea_list *ea_list_head = NULL;
336 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
339 if (!NT_STATUS_IS_OK(status)) {
343 if (num_names == 0) {
348 for (i=0; i<num_names; i++) {
349 struct ea_list *listp;
352 if (strnequal(names[i], "system.", 7)
353 || samba_private_attr_name(names[i]))
357 * Filter out any underlying POSIX EA names
358 * that a Windows client can't handle.
360 if (!lp_posix_pathnames() &&
361 is_invalid_windows_ea_name(names[i])) {
365 listp = talloc(mem_ctx, struct ea_list);
367 return NT_STATUS_NO_MEMORY;
370 status = get_ea_value(listp, conn, fsp,
374 if (!NT_STATUS_IS_OK(status)) {
379 if (listp->ea.value.length == 0) {
381 * We can never return a zero length EA.
382 * Windows reports the EA's as corrupted.
388 push_ascii_fstring(dos_ea_name, listp->ea.name);
391 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
393 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
394 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
395 (unsigned int)listp->ea.value.length));
397 DLIST_ADD_END(ea_list_head, listp);
401 /* Add on 4 for total length. */
402 if (*pea_total_len) {
406 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
407 (unsigned int)*pea_total_len));
409 *ea_list = ea_list_head;
413 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
414 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
419 if (!lp_ea_support(SNUM(conn))) {
423 if (is_ntfs_stream_smb_fname(smb_fname)) {
424 return NT_STATUS_INVALID_PARAMETER;
427 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
430 /****************************************************************************
431 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
433 ****************************************************************************/
435 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
436 connection_struct *conn, struct ea_list *ea_list)
438 unsigned int ret_data_size = 4;
441 SMB_ASSERT(total_data_size >= 4);
443 if (!lp_ea_support(SNUM(conn))) {
448 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
451 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
452 dos_namelen = strlen(dos_ea_name);
453 if (dos_namelen > 255 || dos_namelen == 0) {
456 if (ea_list->ea.value.length > 65535) {
459 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
463 /* We know we have room. */
464 SCVAL(p,0,ea_list->ea.flags);
465 SCVAL(p,1,dos_namelen);
466 SSVAL(p,2,ea_list->ea.value.length);
467 strlcpy(p+4, dos_ea_name, dos_namelen+1);
468 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
470 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
471 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
474 ret_data_size = PTR_DIFF(p, pdata);
475 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
476 SIVAL(pdata,0,ret_data_size);
477 return ret_data_size;
480 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
482 unsigned int total_data_size,
483 unsigned int *ret_data_size,
484 connection_struct *conn,
485 struct ea_list *ea_list)
487 uint8_t *p = (uint8_t *)pdata;
488 uint8_t *last_start = NULL;
489 bool do_store_data = (pdata != NULL);
493 if (!lp_ea_support(SNUM(conn))) {
494 return NT_STATUS_NO_EAS_ON_FILE;
497 for (; ea_list; ea_list = ea_list->next) {
503 if (last_start != NULL && do_store_data) {
504 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
508 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
509 dos_namelen = strlen(dos_ea_name);
510 if (dos_namelen > 255 || dos_namelen == 0) {
511 return NT_STATUS_INTERNAL_ERROR;
513 if (ea_list->ea.value.length > 65535) {
514 return NT_STATUS_INTERNAL_ERROR;
517 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
520 pad = (4 - (this_size % 4)) % 4;
525 if (this_size > total_data_size) {
526 return NT_STATUS_INFO_LENGTH_MISMATCH;
529 /* We know we have room. */
530 SIVAL(p, 0x00, 0); /* next offset */
531 SCVAL(p, 0x04, ea_list->ea.flags);
532 SCVAL(p, 0x05, dos_namelen);
533 SSVAL(p, 0x06, ea_list->ea.value.length);
534 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
535 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
537 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
541 total_data_size -= this_size;
547 *ret_data_size = PTR_DIFF(p, pdata);
548 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
552 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
554 size_t total_ea_len = 0;
556 struct ea_list *ea_list = NULL;
558 if (!lp_ea_support(SNUM(conn))) {
561 mem_ctx = talloc_stackframe();
563 /* If this is a stream fsp, then we need to instead find the
564 * estimated ea len from the main file, not the stream
565 * (streams cannot have EAs), but the estimate isn't just 0 in
567 if (is_ntfs_stream_smb_fname(smb_fname)) {
570 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
571 if(conn->sconn->using_smb2) {
573 unsigned int ret_data_size;
575 * We're going to be using fill_ea_chained_buffer() to
576 * marshall EA's - this size is significantly larger
577 * than the SMB1 buffer. Re-calculate the size without
580 status = fill_ea_chained_buffer(mem_ctx,
586 if (!NT_STATUS_IS_OK(status)) {
589 total_ea_len = ret_data_size;
591 TALLOC_FREE(mem_ctx);
595 /****************************************************************************
596 Ensure the EA name is case insensitive by matching any existing EA name.
597 ****************************************************************************/
599 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
602 TALLOC_CTX *mem_ctx = talloc_tos();
603 struct ea_list *ea_list;
604 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
605 if (!NT_STATUS_IS_OK(status)) {
609 for (; ea_list; ea_list = ea_list->next) {
610 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
611 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
612 &unix_ea_name[5], ea_list->ea.name));
613 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
619 /****************************************************************************
620 Set or delete an extended attribute.
621 ****************************************************************************/
623 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
624 const struct smb_filename *smb_fname, struct ea_list *ea_list)
629 if (!lp_ea_support(SNUM(conn))) {
630 return NT_STATUS_EAS_NOT_SUPPORTED;
633 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
634 if (!NT_STATUS_IS_OK(status)) {
638 /* Setting EAs on streams isn't supported. */
639 if (is_ntfs_stream_smb_fname(smb_fname)) {
640 return NT_STATUS_INVALID_PARAMETER;
644 * Filter out invalid Windows EA names - before
645 * we set *any* of them.
648 if (ea_list_has_invalid_name(ea_list)) {
649 return STATUS_INVALID_EA_NAME;
652 fname = smb_fname->base_name;
654 for (;ea_list; ea_list = ea_list->next) {
656 fstring unix_ea_name;
658 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
659 fstrcat(unix_ea_name, ea_list->ea.name);
661 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
663 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
665 if (samba_private_attr_name(unix_ea_name)) {
666 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
667 return NT_STATUS_ACCESS_DENIED;
670 if (ea_list->ea.value.length == 0) {
671 /* Remove the attribute. */
672 if (fsp && (fsp->fh->fd != -1)) {
673 DEBUG(10,("set_ea: deleting ea name %s on "
674 "file %s by file descriptor.\n",
675 unix_ea_name, fsp_str_dbg(fsp)));
676 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
678 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
679 unix_ea_name, fname));
680 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
683 /* Removing a non existent attribute always succeeds. */
684 if (ret == -1 && errno == ENOATTR) {
685 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
691 if (fsp && (fsp->fh->fd != -1)) {
692 DEBUG(10,("set_ea: setting ea name %s on file "
693 "%s by file descriptor.\n",
694 unix_ea_name, fsp_str_dbg(fsp)));
695 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
696 ea_list->ea.value.data, ea_list->ea.value.length, 0);
698 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
699 unix_ea_name, fname));
700 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
701 ea_list->ea.value.data, ea_list->ea.value.length, 0);
707 if (errno == ENOTSUP) {
708 return NT_STATUS_EAS_NOT_SUPPORTED;
711 return map_nt_error_from_unix(errno);
717 /****************************************************************************
718 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
719 ****************************************************************************/
721 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
723 struct ea_list *ea_list_head = NULL;
724 size_t converted_size, offset = 0;
726 while (offset + 2 < data_size) {
727 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
728 unsigned int namelen = CVAL(pdata,offset);
730 offset++; /* Go past the namelen byte. */
732 /* integer wrap paranioa. */
733 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
734 (offset > data_size) || (namelen > data_size) ||
735 (offset + namelen >= data_size)) {
738 /* Ensure the name is null terminated. */
739 if (pdata[offset + namelen] != '\0') {
742 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
744 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
745 "failed: %s", strerror(errno)));
751 offset += (namelen + 1); /* Go past the name + terminating zero. */
752 DLIST_ADD_END(ea_list_head, eal);
753 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
759 /****************************************************************************
760 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
761 ****************************************************************************/
763 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
765 struct ea_list *ea_list_head = NULL;
767 size_t bytes_used = 0;
769 while (offset < data_size) {
770 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
776 DLIST_ADD_END(ea_list_head, eal);
777 offset += bytes_used;
783 /****************************************************************************
784 Count the total EA size needed.
785 ****************************************************************************/
787 static size_t ea_list_size(struct ea_list *ealist)
790 struct ea_list *listp;
793 for (listp = ealist; listp; listp = listp->next) {
794 push_ascii_fstring(dos_ea_name, listp->ea.name);
795 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
797 /* Add on 4 for total length. */
805 /****************************************************************************
806 Return a union of EA's from a file list and a list of names.
807 The TALLOC context for the two lists *MUST* be identical as we steal
808 memory from one list to add to another. JRA.
809 ****************************************************************************/
811 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
813 struct ea_list *nlistp, *flistp;
815 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
816 for (flistp = file_list; flistp; flistp = flistp->next) {
817 if (strequal(nlistp->ea.name, flistp->ea.name)) {
823 /* Copy the data from this entry. */
824 nlistp->ea.flags = flistp->ea.flags;
825 nlistp->ea.value = flistp->ea.value;
828 nlistp->ea.flags = 0;
829 ZERO_STRUCT(nlistp->ea.value);
833 *total_ea_len = ea_list_size(name_list);
837 /****************************************************************************
838 Send the required number of replies back.
839 We assume all fields other than the data fields are
840 set correctly for the type of call.
841 HACK ! Always assumes smb_setup field is zero.
842 ****************************************************************************/
844 void send_trans2_replies(connection_struct *conn,
845 struct smb_request *req,
853 /* As we are using a protocol > LANMAN1 then the max_send
854 variable must have been set in the sessetupX call.
855 This takes precedence over the max_xmit field in the
856 global struct. These different max_xmit variables should
857 be merged as this is now too confusing */
859 int data_to_send = datasize;
860 int params_to_send = paramsize;
862 const char *pp = params;
863 const char *pd = pdata;
864 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
865 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
866 int data_alignment_offset = 0;
867 bool overflow = False;
868 struct smbXsrv_connection *xconn = req->xconn;
869 int max_send = xconn->smb1.sessions.max_send;
871 /* Modify the data_to_send and datasize and set the error if
872 we're trying to send more than max_data_bytes. We still send
873 the part of the packet(s) that fit. Strange, but needed
876 if (max_data_bytes > 0 && datasize > max_data_bytes) {
877 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
878 max_data_bytes, datasize ));
879 datasize = data_to_send = max_data_bytes;
883 /* If there genuinely are no parameters or data to send just send the empty packet */
885 if(params_to_send == 0 && data_to_send == 0) {
886 reply_outbuf(req, 10, 0);
887 if (NT_STATUS_V(status)) {
890 ntstatus_to_dos(status, &eclass, &ecode);
891 error_packet_set((char *)req->outbuf,
892 eclass, ecode, status,
895 show_msg((char *)req->outbuf);
896 if (!srv_send_smb(xconn,
899 IS_CONN_ENCRYPTED(conn),
901 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
903 TALLOC_FREE(req->outbuf);
907 /* When sending params and data ensure that both are nicely aligned */
908 /* Only do this alignment when there is also data to send - else
909 can cause NT redirector problems. */
911 if (((params_to_send % 4) != 0) && (data_to_send != 0))
912 data_alignment_offset = 4 - (params_to_send % 4);
914 /* Space is bufsize minus Netbios over TCP header minus SMB header */
915 /* The alignment_offset is to align the param bytes on an even byte
916 boundary. NT 4.0 Beta needs this to work correctly. */
918 useable_space = max_send - (smb_size
921 + data_alignment_offset);
923 if (useable_space < 0) {
924 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
925 "= %d!!!", useable_space));
926 exit_server_cleanly("send_trans2_replies: Not enough space");
929 while (params_to_send || data_to_send) {
930 /* Calculate whether we will totally or partially fill this packet */
932 total_sent_thistime = params_to_send + data_to_send;
934 /* We can never send more than useable_space */
936 * Note that 'useable_space' does not include the alignment offsets,
937 * but we must include the alignment offsets in the calculation of
938 * the length of the data we send over the wire, as the alignment offsets
939 * are sent here. Fix from Marc_Jacobsen@hp.com.
942 total_sent_thistime = MIN(total_sent_thistime, useable_space);
944 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
945 + data_alignment_offset);
947 /* Set total params and data to be sent */
948 SSVAL(req->outbuf,smb_tprcnt,paramsize);
949 SSVAL(req->outbuf,smb_tdrcnt,datasize);
951 /* Calculate how many parameters and data we can fit into
952 * this packet. Parameters get precedence
955 params_sent_thistime = MIN(params_to_send,useable_space);
956 data_sent_thistime = useable_space - params_sent_thistime;
957 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
959 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
961 /* smb_proff is the offset from the start of the SMB header to the
962 parameter bytes, however the first 4 bytes of outbuf are
963 the Netbios over TCP header. Thus use smb_base() to subtract
964 them from the calculation */
966 SSVAL(req->outbuf,smb_proff,
967 ((smb_buf(req->outbuf)+alignment_offset)
968 - smb_base(req->outbuf)));
970 if(params_sent_thistime == 0)
971 SSVAL(req->outbuf,smb_prdisp,0);
973 /* Absolute displacement of param bytes sent in this packet */
974 SSVAL(req->outbuf,smb_prdisp,pp - params);
976 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
977 if(data_sent_thistime == 0) {
978 SSVAL(req->outbuf,smb_droff,0);
979 SSVAL(req->outbuf,smb_drdisp, 0);
981 /* The offset of the data bytes is the offset of the
982 parameter bytes plus the number of parameters being sent this time */
983 SSVAL(req->outbuf, smb_droff,
984 ((smb_buf(req->outbuf)+alignment_offset)
985 - smb_base(req->outbuf))
986 + params_sent_thistime + data_alignment_offset);
987 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
990 /* Initialize the padding for alignment */
992 if (alignment_offset != 0) {
993 memset(smb_buf(req->outbuf), 0, alignment_offset);
996 /* Copy the param bytes into the packet */
998 if(params_sent_thistime) {
999 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1000 params_sent_thistime);
1003 /* Copy in the data bytes */
1004 if(data_sent_thistime) {
1005 if (data_alignment_offset != 0) {
1006 memset((smb_buf(req->outbuf)+alignment_offset+
1007 params_sent_thistime), 0,
1008 data_alignment_offset);
1010 memcpy(smb_buf(req->outbuf)+alignment_offset
1011 +params_sent_thistime+data_alignment_offset,
1012 pd,data_sent_thistime);
1015 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1016 params_sent_thistime, data_sent_thistime, useable_space));
1017 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1018 params_to_send, data_to_send, paramsize, datasize));
1021 error_packet_set((char *)req->outbuf,
1022 ERRDOS,ERRbufferoverflow,
1023 STATUS_BUFFER_OVERFLOW,
1025 } else if (NT_STATUS_V(status)) {
1028 ntstatus_to_dos(status, &eclass, &ecode);
1029 error_packet_set((char *)req->outbuf,
1030 eclass, ecode, status,
1034 /* Send the packet */
1035 show_msg((char *)req->outbuf);
1036 if (!srv_send_smb(xconn,
1037 (char *)req->outbuf,
1038 true, req->seqnum+1,
1039 IS_CONN_ENCRYPTED(conn),
1041 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1043 TALLOC_FREE(req->outbuf);
1045 pp += params_sent_thistime;
1046 pd += data_sent_thistime;
1048 params_to_send -= params_sent_thistime;
1049 data_to_send -= data_sent_thistime;
1052 if(params_to_send < 0 || data_to_send < 0) {
1053 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1054 params_to_send, data_to_send));
1062 /****************************************************************************
1063 Reply to a TRANSACT2_OPEN.
1064 ****************************************************************************/
1066 static void call_trans2open(connection_struct *conn,
1067 struct smb_request *req,
1068 char **pparams, int total_params,
1069 char **ppdata, int total_data,
1070 unsigned int max_data_bytes)
1072 struct smb_filename *smb_fname = NULL;
1073 char *params = *pparams;
1074 char *pdata = *ppdata;
1077 bool oplock_request;
1079 bool return_additional_info;
1088 int fattr=0,mtime=0;
1089 SMB_INO_T inode = 0;
1092 struct ea_list *ea_list = NULL;
1095 uint32_t access_mask;
1096 uint32_t share_mode;
1097 uint32_t create_disposition;
1098 uint32_t create_options = 0;
1099 uint32_t private_flags = 0;
1100 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1101 TALLOC_CTX *ctx = talloc_tos();
1104 * Ensure we have enough parameters to perform the operation.
1107 if (total_params < 29) {
1108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1112 flags = SVAL(params, 0);
1113 deny_mode = SVAL(params, 2);
1114 open_attr = SVAL(params,6);
1115 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1116 if (oplock_request) {
1117 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1121 return_additional_info = BITSETW(params,0);
1122 open_sattr = SVAL(params, 4);
1123 open_time = make_unix_date3(params+8);
1125 open_ofun = SVAL(params,12);
1126 open_size = IVAL(params,14);
1127 pname = ¶ms[28];
1130 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1134 if (req->posix_pathnames) {
1135 srvstr_get_path_posix(ctx,
1144 srvstr_get_path(ctx,
1153 if (!NT_STATUS_IS_OK(status)) {
1154 reply_nterror(req, status);
1158 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1159 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1160 (unsigned int)open_ofun, open_size));
1162 status = filename_convert(ctx,
1164 req->flags2 & FLAGS2_DFS_PATHNAMES,
1169 if (!NT_STATUS_IS_OK(status)) {
1170 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1171 reply_botherror(req,
1172 NT_STATUS_PATH_NOT_COVERED,
1173 ERRSRV, ERRbadpath);
1176 reply_nterror(req, status);
1180 if (open_ofun == 0) {
1181 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1185 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1187 &access_mask, &share_mode,
1188 &create_disposition,
1191 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1195 /* Any data in this call is an EA list. */
1196 if (total_data && (total_data != 4)) {
1197 if (total_data < 10) {
1198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1202 if (IVAL(pdata,0) > total_data) {
1203 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1204 IVAL(pdata,0), (unsigned int)total_data));
1205 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1209 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1216 if (!lp_ea_support(SNUM(conn))) {
1217 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1221 if (ea_list_has_invalid_name(ea_list)) {
1223 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1224 if(*pparams == NULL ) {
1225 reply_nterror(req, NT_STATUS_NO_MEMORY);
1229 memset(params, '\0', param_len);
1230 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1231 params, param_len, NULL, 0, max_data_bytes);
1236 status = SMB_VFS_CREATE_FILE(
1239 0, /* root_dir_fid */
1240 smb_fname, /* fname */
1241 access_mask, /* access_mask */
1242 share_mode, /* share_access */
1243 create_disposition, /* create_disposition*/
1244 create_options, /* create_options */
1245 open_attr, /* file_attributes */
1246 oplock_request, /* oplock_request */
1248 open_size, /* allocation_size */
1251 ea_list, /* ea_list */
1253 &smb_action, /* psbuf */
1254 NULL, NULL); /* create context */
1256 if (!NT_STATUS_IS_OK(status)) {
1257 if (open_was_deferred(req->xconn, req->mid)) {
1258 /* We have re-scheduled this call. */
1261 reply_openerror(req, status);
1265 size = get_file_size_stat(&smb_fname->st);
1266 fattr = dos_mode(conn, smb_fname);
1267 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1268 inode = smb_fname->st.st_ex_ino;
1269 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1270 close_file(req, fsp, ERROR_CLOSE);
1271 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1275 /* Realloc the size of parameters and data we will return */
1276 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1277 if(*pparams == NULL ) {
1278 reply_nterror(req, NT_STATUS_NO_MEMORY);
1283 SSVAL(params,0,fsp->fnum);
1284 SSVAL(params,2,fattr);
1285 srv_put_dos_date2(params,4, mtime);
1286 SIVAL(params,8, (uint32_t)size);
1287 SSVAL(params,12,deny_mode);
1288 SSVAL(params,14,0); /* open_type - file or directory. */
1289 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1291 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1292 smb_action |= EXTENDED_OPLOCK_GRANTED;
1295 SSVAL(params,18,smb_action);
1298 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1300 SIVAL(params,20,inode);
1301 SSVAL(params,24,0); /* Padding. */
1303 uint32_t ea_size = estimate_ea_size(conn, fsp,
1305 SIVAL(params, 26, ea_size);
1307 SIVAL(params, 26, 0);
1310 /* Send the required number of replies */
1311 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1313 TALLOC_FREE(smb_fname);
1316 /*********************************************************
1317 Routine to check if a given string matches exactly.
1318 as a special case a mask of "." does NOT match. That
1319 is required for correct wildcard semantics
1320 Case can be significant or not.
1321 **********************************************************/
1323 static bool exact_match(bool has_wild,
1324 bool case_sensitive,
1328 if (mask[0] == '.' && mask[1] == 0) {
1336 if (case_sensitive) {
1337 return strcmp(str,mask)==0;
1339 return strcasecmp_m(str,mask) == 0;
1343 /****************************************************************************
1344 Return the filetype for UNIX extensions.
1345 ****************************************************************************/
1347 static uint32_t unix_filetype(mode_t mode)
1350 return UNIX_TYPE_FILE;
1351 else if(S_ISDIR(mode))
1352 return UNIX_TYPE_DIR;
1354 else if(S_ISLNK(mode))
1355 return UNIX_TYPE_SYMLINK;
1358 else if(S_ISCHR(mode))
1359 return UNIX_TYPE_CHARDEV;
1362 else if(S_ISBLK(mode))
1363 return UNIX_TYPE_BLKDEV;
1366 else if(S_ISFIFO(mode))
1367 return UNIX_TYPE_FIFO;
1370 else if(S_ISSOCK(mode))
1371 return UNIX_TYPE_SOCKET;
1374 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1375 return UNIX_TYPE_UNKNOWN;
1378 /****************************************************************************
1379 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1380 ****************************************************************************/
1382 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1384 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1385 const SMB_STRUCT_STAT *psbuf,
1387 enum perm_type ptype,
1392 if (perms == SMB_MODE_NO_CHANGE) {
1393 if (!VALID_STAT(*psbuf)) {
1394 return NT_STATUS_INVALID_PARAMETER;
1396 *ret_perms = psbuf->st_ex_mode;
1397 return NT_STATUS_OK;
1401 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1402 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1403 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1404 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1405 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1406 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1407 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1408 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1409 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1411 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1414 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1417 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1420 if (ptype == PERM_NEW_FILE) {
1422 * "create mask"/"force create mode" are
1423 * only applied to new files, not existing ones.
1425 ret &= lp_create_mask(SNUM(conn));
1426 /* Add in force bits */
1427 ret |= lp_force_create_mode(SNUM(conn));
1428 } else if (ptype == PERM_NEW_DIR) {
1430 * "directory mask"/"force directory mode" are
1431 * only applied to new directories, not existing ones.
1433 ret &= lp_directory_mask(SNUM(conn));
1434 /* Add in force bits */
1435 ret |= lp_force_directory_mode(SNUM(conn));
1439 return NT_STATUS_OK;
1442 /****************************************************************************
1443 Needed to show the msdfs symlinks as directories. Modifies psbuf
1444 to be a directory if it's a msdfs link.
1445 ****************************************************************************/
1447 static bool check_msdfs_link(connection_struct *conn,
1448 const char *pathname,
1449 SMB_STRUCT_STAT *psbuf)
1451 int saved_errno = errno;
1452 if(lp_host_msdfs() &&
1453 lp_msdfs_root(SNUM(conn)) &&
1454 is_msdfs_link(conn, pathname, psbuf)) {
1456 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1459 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1460 errno = saved_errno;
1463 errno = saved_errno;
1468 /****************************************************************************
1469 Get a level dependent lanman2 dir entry.
1470 ****************************************************************************/
1472 struct smbd_dirptr_lanman2_state {
1473 connection_struct *conn;
1474 uint32_t info_level;
1475 bool check_mangled_names;
1477 bool got_exact_match;
1480 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1486 struct smbd_dirptr_lanman2_state *state =
1487 (struct smbd_dirptr_lanman2_state *)private_data;
1489 char mangled_name[13]; /* mangled 8.3 name. */
1493 /* Mangle fname if it's an illegal name. */
1494 if (mangle_must_mangle(dname, state->conn->params)) {
1496 * Slow path - ensure we can push the original name as UCS2. If
1497 * not, then just don't return this name.
1501 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1502 uint8_t *tmp = talloc_array(talloc_tos(),
1506 status = srvstr_push(NULL,
1507 FLAGS2_UNICODE_STRINGS,
1516 if (!NT_STATUS_IS_OK(status)) {
1520 ok = name_to_8_3(dname, mangled_name,
1521 true, state->conn->params);
1525 fname = mangled_name;
1530 got_match = exact_match(state->has_wild,
1531 state->conn->case_sensitive,
1533 state->got_exact_match = got_match;
1535 got_match = mask_match(fname, mask,
1536 state->conn->case_sensitive);
1539 if(!got_match && state->check_mangled_names &&
1540 !mangle_is_8_3(fname, false, state->conn->params)) {
1542 * It turns out that NT matches wildcards against
1543 * both long *and* short names. This may explain some
1544 * of the wildcard wierdness from old DOS clients
1545 * that some people have been seeing.... JRA.
1547 /* Force the mangling into 8.3. */
1548 ok = name_to_8_3(fname, mangled_name,
1549 false, state->conn->params);
1554 got_match = exact_match(state->has_wild,
1555 state->conn->case_sensitive,
1556 mangled_name, mask);
1557 state->got_exact_match = got_match;
1559 got_match = mask_match(mangled_name, mask,
1560 state->conn->case_sensitive);
1568 *_fname = talloc_strdup(ctx, fname);
1569 if (*_fname == NULL) {
1576 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1578 struct smb_filename *smb_fname,
1581 struct smbd_dirptr_lanman2_state *state =
1582 (struct smbd_dirptr_lanman2_state *)private_data;
1583 bool ms_dfs_link = false;
1586 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1587 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1588 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1589 "Couldn't lstat [%s] (%s)\n",
1590 smb_fname_str_dbg(smb_fname),
1594 } else if (!VALID_STAT(smb_fname->st) &&
1595 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1596 /* Needed to show the msdfs symlinks as
1599 ms_dfs_link = check_msdfs_link(state->conn,
1600 smb_fname->base_name,
1603 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1604 "Couldn't stat [%s] (%s)\n",
1605 smb_fname_str_dbg(smb_fname),
1612 mode = dos_mode_msdfs(state->conn, smb_fname);
1614 mode = dos_mode(state->conn, smb_fname);
1621 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1622 connection_struct *conn,
1624 uint32_t info_level,
1625 struct ea_list *name_list,
1626 bool check_mangled_names,
1627 bool requires_resume_key,
1630 const struct smb_filename *smb_fname,
1631 int space_remaining,
1637 uint64_t *last_entry_off)
1639 char *p, *q, *pdata = *ppdata;
1641 uint64_t file_size = 0;
1642 uint64_t allocation_size = 0;
1643 uint64_t file_index = 0;
1645 struct timespec mdate_ts = {0};
1646 struct timespec adate_ts = {0};
1647 struct timespec cdate_ts = {0};
1648 struct timespec create_date_ts = {0};
1649 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1651 char *last_entry_ptr;
1656 struct readdir_attr_data *readdir_attr_data = NULL;
1658 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1659 file_size = get_file_size_stat(&smb_fname->st);
1661 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1663 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1664 if (!NT_STATUS_IS_OK(status)) {
1665 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1670 file_index = get_FileIndex(conn, &smb_fname->st);
1672 mdate_ts = smb_fname->st.st_ex_mtime;
1673 adate_ts = smb_fname->st.st_ex_atime;
1674 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1675 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1677 if (lp_dos_filetime_resolution(SNUM(conn))) {
1678 dos_filetime_timespec(&create_date_ts);
1679 dos_filetime_timespec(&mdate_ts);
1680 dos_filetime_timespec(&adate_ts);
1681 dos_filetime_timespec(&cdate_ts);
1684 create_date = convert_timespec_to_time_t(create_date_ts);
1685 mdate = convert_timespec_to_time_t(mdate_ts);
1686 adate = convert_timespec_to_time_t(adate_ts);
1688 /* align the record */
1689 SMB_ASSERT(align >= 1);
1691 off = (int)PTR_DIFF(pdata, base_data);
1692 pad = (off + (align-1)) & ~(align-1);
1695 if (pad && pad > space_remaining) {
1696 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1697 "for padding (wanted %u, had %d)\n",
1700 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1704 /* initialize padding to 0 */
1706 memset(pdata, 0, pad);
1708 space_remaining -= pad;
1710 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1720 switch (info_level) {
1721 case SMB_FIND_INFO_STANDARD:
1722 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1723 if(requires_resume_key) {
1727 srv_put_dos_date2(p,0,create_date);
1728 srv_put_dos_date2(p,4,adate);
1729 srv_put_dos_date2(p,8,mdate);
1730 SIVAL(p,12,(uint32_t)file_size);
1731 SIVAL(p,16,(uint32_t)allocation_size);
1735 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1736 p += ucs2_align(base_data, p, 0);
1738 status = srvstr_push(base_data, flags2, p,
1739 fname, PTR_DIFF(end_data, p),
1740 STR_TERMINATE, &len);
1741 if (!NT_STATUS_IS_OK(status)) {
1744 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1746 SCVAL(nameptr, -1, len - 2);
1748 SCVAL(nameptr, -1, 0);
1752 SCVAL(nameptr, -1, len - 1);
1754 SCVAL(nameptr, -1, 0);
1760 case SMB_FIND_EA_SIZE:
1761 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1762 if (requires_resume_key) {
1766 srv_put_dos_date2(p,0,create_date);
1767 srv_put_dos_date2(p,4,adate);
1768 srv_put_dos_date2(p,8,mdate);
1769 SIVAL(p,12,(uint32_t)file_size);
1770 SIVAL(p,16,(uint32_t)allocation_size);
1773 unsigned int ea_size = estimate_ea_size(conn, NULL,
1775 SIVAL(p,22,ea_size); /* Extended attributes */
1779 status = srvstr_push(base_data, flags2,
1780 p, fname, PTR_DIFF(end_data, p),
1781 STR_TERMINATE | STR_NOALIGN, &len);
1782 if (!NT_STATUS_IS_OK(status)) {
1785 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1798 SCVAL(nameptr,0,len);
1800 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1803 case SMB_FIND_EA_LIST:
1805 struct ea_list *file_list = NULL;
1808 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1810 return NT_STATUS_INVALID_PARAMETER;
1812 if (requires_resume_key) {
1816 srv_put_dos_date2(p,0,create_date);
1817 srv_put_dos_date2(p,4,adate);
1818 srv_put_dos_date2(p,8,mdate);
1819 SIVAL(p,12,(uint32_t)file_size);
1820 SIVAL(p,16,(uint32_t)allocation_size);
1822 p += 22; /* p now points to the EA area. */
1824 status = get_ea_list_from_file(ctx, conn, NULL,
1826 &ea_len, &file_list);
1827 if (!NT_STATUS_IS_OK(status)) {
1830 name_list = ea_list_union(name_list, file_list, &ea_len);
1832 /* We need to determine if this entry will fit in the space available. */
1833 /* Max string size is 255 bytes. */
1834 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1835 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1836 "(wanted %u, had %d)\n",
1837 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1839 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1842 /* Push the ea_data followed by the name. */
1843 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1845 status = srvstr_push(base_data, flags2,
1846 p + 1, fname, PTR_DIFF(end_data, p+1),
1847 STR_TERMINATE | STR_NOALIGN, &len);
1848 if (!NT_STATUS_IS_OK(status)) {
1851 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1864 SCVAL(nameptr,0,len);
1866 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1870 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1871 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1872 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1874 SIVAL(p,0,reskey); p += 4;
1875 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1876 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1877 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1878 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1879 SOFF_T(p,0,file_size); p += 8;
1880 SOFF_T(p,0,allocation_size); p += 8;
1881 SIVAL(p,0,mode); p += 4;
1882 q = p; p += 4; /* q is placeholder for name length. */
1883 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1884 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1886 unsigned int ea_size = estimate_ea_size(conn, NULL,
1888 SIVAL(p,0,ea_size); /* Extended attributes */
1891 /* Clear the short name buffer. This is
1892 * IMPORTANT as not doing so will trigger
1893 * a Win2k client bug. JRA.
1895 if (!was_8_3 && check_mangled_names) {
1896 char mangled_name[13]; /* mangled 8.3 name. */
1897 if (!name_to_8_3(fname,mangled_name,True,
1899 /* Error - mangle failed ! */
1900 memset(mangled_name,'\0',12);
1902 mangled_name[12] = 0;
1903 status = srvstr_push(base_data, flags2,
1904 p+2, mangled_name, 24,
1905 STR_UPPER|STR_UNICODE, &len);
1906 if (!NT_STATUS_IS_OK(status)) {
1910 memset(p + 2 + len,'\0',24 - len);
1917 status = srvstr_push(base_data, flags2, p,
1918 fname, PTR_DIFF(end_data, p),
1919 STR_TERMINATE_ASCII, &len);
1920 if (!NT_STATUS_IS_OK(status)) {
1926 len = PTR_DIFF(p, pdata);
1927 pad = (len + (align-1)) & ~(align-1);
1929 * offset to the next entry, the caller
1930 * will overwrite it for the last entry
1931 * that's why we always include the padding
1935 * set padding to zero
1938 memset(p, 0, pad - len);
1945 case SMB_FIND_FILE_DIRECTORY_INFO:
1946 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1948 SIVAL(p,0,reskey); p += 4;
1949 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1950 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1951 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1952 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1953 SOFF_T(p,0,file_size); p += 8;
1954 SOFF_T(p,0,allocation_size); p += 8;
1955 SIVAL(p,0,mode); p += 4;
1956 status = srvstr_push(base_data, flags2,
1957 p + 4, fname, PTR_DIFF(end_data, p+4),
1958 STR_TERMINATE_ASCII, &len);
1959 if (!NT_STATUS_IS_OK(status)) {
1965 len = PTR_DIFF(p, pdata);
1966 pad = (len + (align-1)) & ~(align-1);
1968 * offset to the next entry, the caller
1969 * will overwrite it for the last entry
1970 * that's why we always include the padding
1974 * set padding to zero
1977 memset(p, 0, pad - len);
1984 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1985 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1987 SIVAL(p,0,reskey); p += 4;
1988 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1989 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1990 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1991 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1992 SOFF_T(p,0,file_size); p += 8;
1993 SOFF_T(p,0,allocation_size); p += 8;
1994 SIVAL(p,0,mode); p += 4;
1995 q = p; p += 4; /* q is placeholder for name length. */
1997 unsigned int ea_size = estimate_ea_size(conn, NULL,
1999 SIVAL(p,0,ea_size); /* Extended attributes */
2002 status = srvstr_push(base_data, flags2, p,
2003 fname, PTR_DIFF(end_data, p),
2004 STR_TERMINATE_ASCII, &len);
2005 if (!NT_STATUS_IS_OK(status)) {
2011 len = PTR_DIFF(p, pdata);
2012 pad = (len + (align-1)) & ~(align-1);
2014 * offset to the next entry, the caller
2015 * will overwrite it for the last entry
2016 * that's why we always include the padding
2020 * set padding to zero
2023 memset(p, 0, pad - len);
2030 case SMB_FIND_FILE_NAMES_INFO:
2031 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2033 SIVAL(p,0,reskey); p += 4;
2035 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2036 acl on a dir (tridge) */
2037 status = srvstr_push(base_data, flags2, p,
2038 fname, PTR_DIFF(end_data, p),
2039 STR_TERMINATE_ASCII, &len);
2040 if (!NT_STATUS_IS_OK(status)) {
2046 len = PTR_DIFF(p, pdata);
2047 pad = (len + (align-1)) & ~(align-1);
2049 * offset to the next entry, the caller
2050 * will overwrite it for the last entry
2051 * that's why we always include the padding
2055 * set padding to zero
2058 memset(p, 0, pad - len);
2065 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2066 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2068 SIVAL(p,0,reskey); p += 4;
2069 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2070 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2071 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2072 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2073 SOFF_T(p,0,file_size); p += 8;
2074 SOFF_T(p,0,allocation_size); p += 8;
2075 SIVAL(p,0,mode); p += 4;
2076 q = p; p += 4; /* q is placeholder for name length. */
2077 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2078 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2080 unsigned int ea_size = estimate_ea_size(conn, NULL,
2082 SIVAL(p,0,ea_size); /* Extended attributes */
2085 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2086 SBVAL(p,0,file_index); p += 8;
2087 status = srvstr_push(base_data, flags2, p,
2088 fname, PTR_DIFF(end_data, p),
2089 STR_TERMINATE_ASCII, &len);
2090 if (!NT_STATUS_IS_OK(status)) {
2096 len = PTR_DIFF(p, pdata);
2097 pad = (len + (align-1)) & ~(align-1);
2099 * offset to the next entry, the caller
2100 * will overwrite it for the last entry
2101 * that's why we always include the padding
2105 * set padding to zero
2108 memset(p, 0, pad - len);
2115 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2116 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2117 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2119 SIVAL(p,0,reskey); p += 4;
2120 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2121 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2122 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2123 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2124 SOFF_T(p,0,file_size); p += 8;
2125 SOFF_T(p,0,allocation_size); p += 8;
2126 SIVAL(p,0,mode); p += 4;
2127 q = p; p += 4; /* q is placeholder for name length */
2128 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2129 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2130 } else if (readdir_attr_data &&
2131 readdir_attr_data->type == RDATTR_AAPL) {
2133 * OS X specific SMB2 extension negotiated via
2134 * AAPL create context: return max_access in
2137 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2139 unsigned int ea_size = estimate_ea_size(conn, NULL,
2141 SIVAL(p,0,ea_size); /* Extended attributes */
2145 if (readdir_attr_data &&
2146 readdir_attr_data->type == RDATTR_AAPL) {
2148 * OS X specific SMB2 extension negotiated via
2149 * AAPL create context: return resource fork
2150 * length and compressed FinderInfo in
2153 * According to documentation short_name_len
2154 * should be 0, but on the wire behaviour
2155 * shows its set to 24 by clients.
2159 /* Resourefork length */
2160 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2162 /* Compressed FinderInfo */
2163 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2164 } else if (!was_8_3 && check_mangled_names) {
2165 char mangled_name[13]; /* mangled 8.3 name. */
2166 if (!name_to_8_3(fname,mangled_name,True,
2168 /* Error - mangle failed ! */
2169 memset(mangled_name,'\0',12);
2171 mangled_name[12] = 0;
2172 status = srvstr_push(base_data, flags2,
2173 p+2, mangled_name, 24,
2174 STR_UPPER|STR_UNICODE, &len);
2175 if (!NT_STATUS_IS_OK(status)) {
2180 memset(p + 2 + len,'\0',24 - len);
2184 /* Clear the short name buffer. This is
2185 * IMPORTANT as not doing so will trigger
2186 * a Win2k client bug. JRA.
2193 if (readdir_attr_data &&
2194 readdir_attr_data->type == RDATTR_AAPL) {
2196 * OS X specific SMB2 extension negotiated via
2197 * AAPL create context: return UNIX mode in
2200 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2201 SSVAL(p, 0, aapl_mode);
2207 SBVAL(p,0,file_index); p += 8;
2208 status = srvstr_push(base_data, flags2, p,
2209 fname, PTR_DIFF(end_data, p),
2210 STR_TERMINATE_ASCII, &len);
2211 if (!NT_STATUS_IS_OK(status)) {
2217 len = PTR_DIFF(p, pdata);
2218 pad = (len + (align-1)) & ~(align-1);
2220 * offset to the next entry, the caller
2221 * will overwrite it for the last entry
2222 * that's why we always include the padding
2226 * set padding to zero
2229 memset(p, 0, pad - len);
2236 /* CIFS UNIX Extension. */
2238 case SMB_FIND_FILE_UNIX:
2239 case SMB_FIND_FILE_UNIX_INFO2:
2241 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2243 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2245 if (info_level == SMB_FIND_FILE_UNIX) {
2246 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2247 p = store_file_unix_basic(conn, p,
2248 NULL, &smb_fname->st);
2249 status = srvstr_push(base_data, flags2, p,
2250 fname, PTR_DIFF(end_data, p),
2251 STR_TERMINATE, &len);
2252 if (!NT_STATUS_IS_OK(status)) {
2256 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2257 p = store_file_unix_basic_info2(conn, p,
2258 NULL, &smb_fname->st);
2261 status = srvstr_push(base_data, flags2, p, fname,
2262 PTR_DIFF(end_data, p), 0, &len);
2263 if (!NT_STATUS_IS_OK(status)) {
2266 SIVAL(nameptr, 0, len);
2271 len = PTR_DIFF(p, pdata);
2272 pad = (len + (align-1)) & ~(align-1);
2274 * offset to the next entry, the caller
2275 * will overwrite it for the last entry
2276 * that's why we always include the padding
2280 * set padding to zero
2283 memset(p, 0, pad - len);
2288 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2293 return NT_STATUS_INVALID_LEVEL;
2296 if (PTR_DIFF(p,pdata) > space_remaining) {
2297 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2298 "(wanted %u, had %d)\n",
2299 (unsigned int)PTR_DIFF(p,pdata),
2301 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2304 /* Setup the last entry pointer, as an offset from base_data */
2305 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2306 /* Advance the data pointer to the next slot */
2309 return NT_STATUS_OK;
2312 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2313 connection_struct *conn,
2314 struct dptr_struct *dirptr,
2316 const char *path_mask,
2319 int requires_resume_key,
2327 int space_remaining,
2328 bool *got_exact_match,
2329 int *_last_entry_off,
2330 struct ea_list *name_list)
2333 const char *mask = NULL;
2334 long prev_dirpos = 0;
2337 struct smb_filename *smb_fname = NULL;
2338 struct smbd_dirptr_lanman2_state state;
2340 uint64_t last_entry_off = 0;
2345 state.info_level = info_level;
2346 state.check_mangled_names = lp_mangled_names(conn->params);
2347 state.has_wild = dptr_has_wild(dirptr);
2348 state.got_exact_match = false;
2350 *got_exact_match = false;
2352 p = strrchr_m(path_mask,'/');
2363 ok = smbd_dirptr_get_entry(ctx,
2369 smbd_dirptr_lanman2_match_fn,
2370 smbd_dirptr_lanman2_mode_fn,
2377 return NT_STATUS_END_OF_FILE;
2380 *got_exact_match = state.got_exact_match;
2382 status = smbd_marshall_dir_entry(ctx,
2387 state.check_mangled_names,
2388 requires_resume_key,
2399 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2400 DEBUG(1,("Conversion error: illegal character: %s\n",
2401 smb_fname_str_dbg(smb_fname)));
2404 TALLOC_FREE(smb_fname);
2405 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2406 dptr_SeekDir(dirptr, prev_dirpos);
2409 if (!NT_STATUS_IS_OK(status)) {
2413 *_last_entry_off = last_entry_off;
2414 return NT_STATUS_OK;
2417 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2418 connection_struct *conn,
2419 struct dptr_struct *dirptr,
2421 const char *path_mask,
2424 bool requires_resume_key,
2430 int space_remaining,
2431 bool *got_exact_match,
2432 int *last_entry_off,
2433 struct ea_list *name_list)
2436 const bool do_pad = true;
2438 if (info_level >= 1 && info_level <= 3) {
2439 /* No alignment on earlier info levels. */
2443 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2444 path_mask, dirtype, info_level,
2445 requires_resume_key, dont_descend, ask_sharemode,
2447 ppdata, base_data, end_data,
2450 last_entry_off, name_list);
2453 /****************************************************************************
2454 Reply to a TRANS2_FINDFIRST.
2455 ****************************************************************************/
2457 static void call_trans2findfirst(connection_struct *conn,
2458 struct smb_request *req,
2459 char **pparams, int total_params,
2460 char **ppdata, int total_data,
2461 unsigned int max_data_bytes)
2463 /* We must be careful here that we don't return more than the
2464 allowed number of data bytes. If this means returning fewer than
2465 maxentries then so be it. We assume that the redirector has
2466 enough room for the fixed number of parameter bytes it has
2468 struct smb_filename *smb_dname = NULL;
2469 char *params = *pparams;
2470 char *pdata = *ppdata;
2474 uint16_t findfirst_flags;
2475 bool close_after_first;
2477 bool requires_resume_key;
2479 char *directory = NULL;
2482 int last_entry_off=0;
2486 bool finished = False;
2487 bool dont_descend = False;
2488 bool out_of_space = False;
2489 int space_remaining;
2490 bool mask_contains_wcard = False;
2491 struct ea_list *ea_list = NULL;
2492 NTSTATUS ntstatus = NT_STATUS_OK;
2493 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2494 TALLOC_CTX *ctx = talloc_tos();
2495 struct dptr_struct *dirptr = NULL;
2496 struct smbd_server_connection *sconn = req->sconn;
2497 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2498 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2499 bool backup_priv = false;
2500 bool as_root = false;
2502 if (total_params < 13) {
2503 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2507 dirtype = SVAL(params,0);
2508 maxentries = SVAL(params,2);
2509 findfirst_flags = SVAL(params,4);
2510 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2511 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2512 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2513 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2514 security_token_has_privilege(get_current_nttok(conn),
2517 info_level = SVAL(params,6);
2519 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2520 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2521 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2523 info_level, max_data_bytes));
2526 /* W2K3 seems to treat zero as 1. */
2530 switch (info_level) {
2531 case SMB_FIND_INFO_STANDARD:
2532 case SMB_FIND_EA_SIZE:
2533 case SMB_FIND_EA_LIST:
2534 case SMB_FIND_FILE_DIRECTORY_INFO:
2535 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2536 case SMB_FIND_FILE_NAMES_INFO:
2537 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2538 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2539 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2541 case SMB_FIND_FILE_UNIX:
2542 case SMB_FIND_FILE_UNIX_INFO2:
2543 /* Always use filesystem for UNIX mtime query. */
2544 ask_sharemode = false;
2545 if (!lp_unix_extensions()) {
2546 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2549 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2552 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2556 if (req->posix_pathnames) {
2557 srvstr_get_path_wcard_posix(ctx,
2565 &mask_contains_wcard);
2567 srvstr_get_path_wcard(ctx,
2575 &mask_contains_wcard);
2577 if (!NT_STATUS_IS_OK(ntstatus)) {
2578 reply_nterror(req, ntstatus);
2585 ntstatus = filename_convert_with_privilege(ctx,
2590 &mask_contains_wcard,
2593 ntstatus = filename_convert(ctx, conn,
2594 req->flags2 & FLAGS2_DFS_PATHNAMES,
2597 &mask_contains_wcard,
2601 if (!NT_STATUS_IS_OK(ntstatus)) {
2602 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2603 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2604 ERRSRV, ERRbadpath);
2607 reply_nterror(req, ntstatus);
2611 mask = smb_dname->original_lcomp;
2613 directory = smb_dname->base_name;
2615 p = strrchr_m(directory,'/');
2617 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2618 if((directory[0] == '.') && (directory[1] == '\0')) {
2619 mask = talloc_strdup(ctx,"*");
2621 reply_nterror(req, NT_STATUS_NO_MEMORY);
2624 mask_contains_wcard = True;
2630 if (p == NULL || p == directory) {
2631 /* Ensure we don't have a directory name of "". */
2632 directory = talloc_strdup(talloc_tos(), ".");
2634 reply_nterror(req, NT_STATUS_NO_MEMORY);
2639 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
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_trans2findfirst: 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_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
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 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2675 *ppdata = (char *)SMB_REALLOC(
2676 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2677 if(*ppdata == NULL ) {
2678 reply_nterror(req, NT_STATUS_NO_MEMORY);
2682 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2684 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2687 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2688 /* Realloc the params space */
2689 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2690 if (*pparams == NULL) {
2691 reply_nterror(req, NT_STATUS_NO_MEMORY);
2696 /* Save the wildcard match and attribs we are using on this directory -
2697 needed as lanman2 assumes these are being saved between calls */
2699 ntstatus = dptr_create(conn,
2707 mask_contains_wcard,
2711 if (!NT_STATUS_IS_OK(ntstatus)) {
2712 reply_nterror(req, ntstatus);
2717 /* Remember this in case we have
2718 to do a findnext. */
2719 dptr_set_priv(dirptr);
2722 dptr_num = dptr_dnum(dirptr);
2723 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2725 /* Initialize per TRANS2_FIND_FIRST operation data */
2726 dptr_init_search_op(dirptr);
2728 /* We don't need to check for VOL here as this is returned by
2729 a different TRANS2 call. */
2731 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2732 directory,lp_dont_descend(ctx, SNUM(conn))));
2733 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2734 dont_descend = True;
2737 space_remaining = max_data_bytes;
2738 out_of_space = False;
2740 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2741 bool got_exact_match = False;
2743 /* this is a heuristic to avoid seeking the dirptr except when
2744 absolutely necessary. It allows for a filename of about 40 chars */
2745 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2746 out_of_space = True;
2749 ntstatus = get_lanman2_dir_entry(ctx,
2753 mask,dirtype,info_level,
2754 requires_resume_key,dont_descend,
2759 &last_entry_off, ea_list);
2760 if (NT_STATUS_EQUAL(ntstatus,
2761 NT_STATUS_ILLEGAL_CHARACTER)) {
2763 * Bad character conversion on name. Ignore this
2768 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2769 out_of_space = true;
2771 finished = !NT_STATUS_IS_OK(ntstatus);
2775 if (!finished && !out_of_space)
2779 * As an optimisation if we know we aren't looking
2780 * for a wildcard name (ie. the name matches the wildcard exactly)
2781 * then we can finish on any (first) match.
2782 * This speeds up large directory searches. JRA.
2788 /* Ensure space_remaining never goes -ve. */
2789 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2790 space_remaining = 0;
2791 out_of_space = true;
2793 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2797 /* Check if we can close the dirptr */
2798 if(close_after_first || (finished && close_if_end)) {
2799 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2800 dptr_close(sconn, &dptr_num);
2804 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2805 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2806 * the protocol level is less than NT1. Tested with smbclient. JRA.
2807 * This should fix the OS/2 client bug #2335.
2810 if(numentries == 0) {
2811 dptr_close(sconn, &dptr_num);
2812 if (get_Protocol() < PROTOCOL_NT1) {
2813 reply_force_doserror(req, ERRDOS, ERRnofiles);
2816 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2817 ERRDOS, ERRbadfile);
2822 /* At this point pdata points to numentries directory entries. */
2824 /* Set up the return parameter block */
2825 SSVAL(params,0,dptr_num);
2826 SSVAL(params,2,numentries);
2827 SSVAL(params,4,finished);
2828 SSVAL(params,6,0); /* Never an EA error */
2829 SSVAL(params,8,last_entry_off);
2831 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2834 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2835 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2837 reply_nterror(req, NT_STATUS_NO_MEMORY);
2841 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2842 smb_fn_name(req->cmd),
2843 mask, directory, dirtype, numentries ) );
2846 * Force a name mangle here to ensure that the
2847 * mask as an 8.3 name is top of the mangled cache.
2848 * The reasons for this are subtle. Don't remove
2849 * this code unless you know what you are doing
2850 * (see PR#13758). JRA.
2853 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2854 char mangled_name[13];
2855 name_to_8_3(mask, mangled_name, True, conn->params);
2863 TALLOC_FREE(smb_dname);
2867 /****************************************************************************
2868 Reply to a TRANS2_FINDNEXT.
2869 ****************************************************************************/
2871 static void call_trans2findnext(connection_struct *conn,
2872 struct smb_request *req,
2873 char **pparams, int total_params,
2874 char **ppdata, int total_data,
2875 unsigned int max_data_bytes)
2877 /* We must be careful here that we don't return more than the
2878 allowed number of data bytes. If this means returning fewer than
2879 maxentries then so be it. We assume that the redirector has
2880 enough room for the fixed number of parameter bytes it has
2882 char *params = *pparams;
2883 char *pdata = *ppdata;
2887 uint16_t info_level;
2888 uint32_t resume_key;
2889 uint16_t findnext_flags;
2890 bool close_after_request;
2892 bool requires_resume_key;
2894 bool mask_contains_wcard = False;
2895 char *resume_name = NULL;
2896 const char *mask = NULL;
2897 const char *directory = NULL;
2901 int i, last_entry_off=0;
2902 bool finished = False;
2903 bool dont_descend = False;
2904 bool out_of_space = False;
2905 int space_remaining;
2906 struct ea_list *ea_list = NULL;
2907 NTSTATUS ntstatus = NT_STATUS_OK;
2908 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2909 TALLOC_CTX *ctx = talloc_tos();
2910 struct dptr_struct *dirptr;
2911 struct smbd_server_connection *sconn = req->sconn;
2912 bool backup_priv = false;
2913 bool as_root = false;
2915 if (total_params < 13) {
2916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2920 dptr_num = SVAL(params,0);
2921 maxentries = SVAL(params,2);
2922 info_level = SVAL(params,4);
2923 resume_key = IVAL(params,6);
2924 findnext_flags = SVAL(params,10);
2925 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2926 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2927 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2928 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2930 if (!continue_bit) {
2931 /* We only need resume_name if continue_bit is zero. */
2932 if (req->posix_pathnames) {
2933 srvstr_get_path_wcard_posix(ctx,
2941 &mask_contains_wcard);
2943 srvstr_get_path_wcard(ctx,
2951 &mask_contains_wcard);
2953 if (!NT_STATUS_IS_OK(ntstatus)) {
2954 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2955 complain (it thinks we're asking for the directory above the shared
2956 path or an invalid name). Catch this as the resume name is only compared, never used in
2957 a file access. JRA. */
2958 srvstr_pull_talloc(ctx, params, req->flags2,
2959 &resume_name, params+12,
2963 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2964 reply_nterror(req, ntstatus);
2970 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2971 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2972 resume_key = %d resume name = %s continue=%d level = %d\n",
2973 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2974 requires_resume_key, resume_key,
2975 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2978 /* W2K3 seems to treat zero as 1. */
2982 switch (info_level) {
2983 case SMB_FIND_INFO_STANDARD:
2984 case SMB_FIND_EA_SIZE:
2985 case SMB_FIND_EA_LIST:
2986 case SMB_FIND_FILE_DIRECTORY_INFO:
2987 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2988 case SMB_FIND_FILE_NAMES_INFO:
2989 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2990 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2991 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2993 case SMB_FIND_FILE_UNIX:
2994 case SMB_FIND_FILE_UNIX_INFO2:
2995 /* Always use filesystem for UNIX mtime query. */
2996 ask_sharemode = false;
2997 if (!lp_unix_extensions()) {
2998 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3003 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3007 if (info_level == SMB_FIND_EA_LIST) {
3010 if (total_data < 4) {
3011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3015 ea_size = IVAL(pdata,0);
3016 if (ea_size != total_data) {
3017 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3018 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3023 if (!lp_ea_support(SNUM(conn))) {
3024 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3028 /* Pull out the list of names. */
3029 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3036 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3041 *ppdata = (char *)SMB_REALLOC(
3042 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3043 if(*ppdata == NULL) {
3044 reply_nterror(req, NT_STATUS_NO_MEMORY);
3049 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3052 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3055 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3056 /* Realloc the params space */
3057 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3058 if(*pparams == NULL ) {
3059 reply_nterror(req, NT_STATUS_NO_MEMORY);
3065 /* Check that the dptr is valid */
3066 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3067 reply_nterror(req, STATUS_NO_MORE_FILES);
3071 directory = dptr_path(sconn, dptr_num);
3073 /* Get the wildcard mask from the dptr */
3074 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3075 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3076 reply_nterror(req, STATUS_NO_MORE_FILES);
3080 /* Get the attr mask from the dptr */
3081 dirtype = dptr_attr(sconn, dptr_num);
3083 backup_priv = dptr_get_priv(dirptr);
3085 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3086 "backup_priv = %d\n",
3087 dptr_num, mask, dirtype,
3089 dptr_TellDir(dirptr),
3092 /* Initialize per TRANS2_FIND_NEXT operation data */
3093 dptr_init_search_op(dirptr);
3095 /* We don't need to check for VOL here as this is returned by
3096 a different TRANS2 call. */
3098 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3099 directory,lp_dont_descend(ctx, SNUM(conn))));
3100 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3101 dont_descend = True;
3104 space_remaining = max_data_bytes;
3105 out_of_space = False;
3113 * Seek to the correct position. We no longer use the resume key but
3114 * depend on the last file name instead.
3117 if(!continue_bit && resume_name && *resume_name) {
3120 long current_pos = 0;
3122 * Remember, name_to_8_3 is called by
3123 * get_lanman2_dir_entry(), so the resume name
3124 * could be mangled. Ensure we check the unmangled name.
3127 if (mangle_is_mangled(resume_name, conn->params)) {
3128 char *new_resume_name = NULL;
3129 mangle_lookup_name_from_8_3(ctx,
3133 if (new_resume_name) {
3134 resume_name = new_resume_name;
3139 * Fix for NT redirector problem triggered by resume key indexes
3140 * changing between directory scans. We now return a resume key of 0
3141 * and instead look for the filename to continue from (also given
3142 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3143 * findfirst/findnext (as is usual) then the directory pointer
3144 * should already be at the correct place.
3147 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3148 } /* end if resume_name && !continue_bit */
3150 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3151 bool got_exact_match = False;
3153 /* this is a heuristic to avoid seeking the dirptr except when
3154 absolutely necessary. It allows for a filename of about 40 chars */
3155 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3156 out_of_space = True;
3159 ntstatus = get_lanman2_dir_entry(ctx,
3163 mask,dirtype,info_level,
3164 requires_resume_key,dont_descend,
3169 &last_entry_off, ea_list);
3170 if (NT_STATUS_EQUAL(ntstatus,
3171 NT_STATUS_ILLEGAL_CHARACTER)) {
3173 * Bad character conversion on name. Ignore this
3178 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3179 out_of_space = true;
3181 finished = !NT_STATUS_IS_OK(ntstatus);
3185 if (!finished && !out_of_space)
3189 * As an optimisation if we know we aren't looking
3190 * for a wildcard name (ie. the name matches the wildcard exactly)
3191 * then we can finish on any (first) match.
3192 * This speeds up large directory searches. JRA.
3198 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3201 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3202 smb_fn_name(req->cmd),
3203 mask, directory, dirtype, numentries ) );
3205 /* Check if we can close the dirptr */
3206 if(close_after_request || (finished && close_if_end)) {
3207 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3208 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3215 /* Set up the return parameter block */
3216 SSVAL(params,0,numentries);
3217 SSVAL(params,2,finished);
3218 SSVAL(params,4,0); /* Never an EA error */
3219 SSVAL(params,6,last_entry_off);
3221 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3227 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3229 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3233 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3235 SMB_ASSERT(extended_info != NULL);
3237 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3238 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3239 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3240 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3241 #ifdef SAMBA_VERSION_REVISION
3242 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3244 extended_info->samba_subversion = 0;
3245 #ifdef SAMBA_VERSION_RC_RELEASE
3246 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3248 #ifdef SAMBA_VERSION_PRE_RELEASE
3249 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3252 #ifdef SAMBA_VERSION_VENDOR_PATCH
3253 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3255 extended_info->samba_gitcommitdate = 0;
3256 #ifdef SAMBA_VERSION_COMMIT_TIME
3257 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3260 memset(extended_info->samba_version_string, 0,
3261 sizeof(extended_info->samba_version_string));
3263 snprintf (extended_info->samba_version_string,
3264 sizeof(extended_info->samba_version_string),
3265 "%s", samba_version_string());
3268 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3269 connection_struct *conn,
3270 TALLOC_CTX *mem_ctx,
3271 uint16_t info_level,
3273 unsigned int max_data_bytes,
3274 size_t *fixed_portion,
3275 struct smb_filename *fname,
3279 char *pdata, *end_data;
3282 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3283 int snum = SNUM(conn);
3284 const char *fstype = lp_fstype(SNUM(conn));
3285 const char *filename = NULL;
3286 const uint64_t bytes_per_sector = 512;
3287 uint32_t additional_flags = 0;
3288 struct smb_filename smb_fname;
3290 NTSTATUS status = NT_STATUS_OK;
3293 if (fname == NULL || fname->base_name == NULL) {
3296 filename = fname->base_name;
3300 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3301 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3302 "info level (0x%x) on IPC$.\n",
3303 (unsigned int)info_level));
3304 return NT_STATUS_ACCESS_DENIED;
3308 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3310 ZERO_STRUCT(smb_fname);
3311 smb_fname.base_name = discard_const_p(char, filename);
3313 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3314 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3315 return map_nt_error_from_unix(errno);
3320 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3321 return NT_STATUS_INVALID_PARAMETER;
3324 *ppdata = (char *)SMB_REALLOC(
3325 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3326 if (*ppdata == NULL) {
3327 return NT_STATUS_NO_MEMORY;
3331 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3332 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3336 switch (info_level) {
3337 case SMB_INFO_ALLOCATION:
3339 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3341 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3343 if (df_ret == (uint64_t)-1) {
3344 return map_nt_error_from_unix(errno);
3347 block_size = lp_block_size(snum);
3348 if (bsize < block_size) {
3349 uint64_t factor = block_size/bsize;
3354 if (bsize > block_size) {
3355 uint64_t factor = bsize/block_size;
3360 sectors_per_unit = bsize/bytes_per_sector;
3362 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3363 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3364 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3366 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3367 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3368 SIVAL(pdata,l1_cUnit,dsize);
3369 SIVAL(pdata,l1_cUnitAvail,dfree);
3370 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3374 case SMB_INFO_VOLUME:
3375 /* Return volume name */
3377 * Add volume serial number - hash of a combination of
3378 * the called hostname and the service name.
3380 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3382 * Win2k3 and previous mess this up by sending a name length
3383 * one byte short. I believe only older clients (OS/2 Win9x) use
3384 * this call so try fixing this by adding a terminating null to
3385 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3387 status = srvstr_push(
3389 pdata+l2_vol_szVolLabel, vname,
3390 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3391 STR_NOALIGN|STR_TERMINATE, &len);
3392 if (!NT_STATUS_IS_OK(status)) {
3395 SCVAL(pdata,l2_vol_cch,len);
3396 data_len = l2_vol_szVolLabel + len;
3397 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3398 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3399 (unsigned)len, vname));
3402 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3403 case SMB_FS_ATTRIBUTE_INFORMATION:
3405 additional_flags = 0;
3406 #if defined(HAVE_SYS_QUOTAS)
3407 additional_flags |= FILE_VOLUME_QUOTAS;
3410 if(lp_nt_acl_support(SNUM(conn))) {
3411 additional_flags |= FILE_PERSISTENT_ACLS;
3414 /* Capabilities are filled in at connection time through STATVFS call */
3415 additional_flags |= conn->fs_capabilities;
3416 additional_flags |= lp_parm_int(conn->params->service,
3417 "share", "fake_fscaps",
3420 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3421 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3422 additional_flags); /* FS ATTRIBUTES */
3424 SIVAL(pdata,4,255); /* Max filename component length */
3425 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3426 and will think we can't do long filenames */
3427 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3428 PTR_DIFF(end_data, pdata+12),
3430 if (!NT_STATUS_IS_OK(status)) {
3434 data_len = 12 + len;
3435 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3436 /* the client only requested a portion of the
3438 data_len = max_data_bytes;
3439 status = STATUS_BUFFER_OVERFLOW;
3441 *fixed_portion = 16;
3444 case SMB_QUERY_FS_LABEL_INFO:
3445 case SMB_FS_LABEL_INFORMATION:
3446 status = srvstr_push(pdata, flags2, pdata+4, vname,
3447 PTR_DIFF(end_data, pdata+4), 0, &len);
3448 if (!NT_STATUS_IS_OK(status)) {
3455 case SMB_QUERY_FS_VOLUME_INFO:
3456 case SMB_FS_VOLUME_INFORMATION:
3459 * Add volume serial number - hash of a combination of
3460 * the called hostname and the service name.
3462 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3463 (str_checksum(get_local_machine_name())<<16));
3465 /* Max label len is 32 characters. */
3466 status = srvstr_push(pdata, flags2, pdata+18, vname,
3467 PTR_DIFF(end_data, pdata+18),
3469 if (!NT_STATUS_IS_OK(status)) {
3472 SIVAL(pdata,12,len);
3475 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3476 (int)strlen(vname),vname,
3477 lp_servicename(talloc_tos(), snum)));
3478 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3479 /* the client only requested a portion of the
3481 data_len = max_data_bytes;
3482 status = STATUS_BUFFER_OVERFLOW;
3484 *fixed_portion = 24;
3487 case SMB_QUERY_FS_SIZE_INFO:
3488 case SMB_FS_SIZE_INFORMATION:
3490 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3492 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3494 if (df_ret == (uint64_t)-1) {
3495 return map_nt_error_from_unix(errno);
3497 block_size = lp_block_size(snum);
3498 if (bsize < block_size) {
3499 uint64_t factor = block_size/bsize;
3504 if (bsize > block_size) {
3505 uint64_t factor = bsize/block_size;
3510 sectors_per_unit = bsize/bytes_per_sector;
3511 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3512 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3513 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3514 SBIG_UINT(pdata,0,dsize);
3515 SBIG_UINT(pdata,8,dfree);
3516 SIVAL(pdata,16,sectors_per_unit);
3517 SIVAL(pdata,20,bytes_per_sector);
3518 *fixed_portion = 24;
3522 case SMB_FS_FULL_SIZE_INFORMATION:
3524 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3526 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3528 if (df_ret == (uint64_t)-1) {
3529 return map_nt_error_from_unix(errno);
3531 block_size = lp_block_size(snum);
3532 if (bsize < block_size) {
3533 uint64_t factor = block_size/bsize;
3538 if (bsize > block_size) {
3539 uint64_t factor = bsize/block_size;
3544 sectors_per_unit = bsize/bytes_per_sector;
3545 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3546 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3547 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3548 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3549 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3550 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3551 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3552 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3553 *fixed_portion = 32;
3557 case SMB_QUERY_FS_DEVICE_INFO:
3558 case SMB_FS_DEVICE_INFORMATION:
3560 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3562 if (!CAN_WRITE(conn)) {
3563 characteristics |= FILE_READ_ONLY_DEVICE;
3566 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3567 SIVAL(pdata,4,characteristics);
3572 #ifdef HAVE_SYS_QUOTAS
3573 case SMB_FS_QUOTA_INFORMATION:
3575 * what we have to send --metze:
3577 * Unknown1: 24 NULL bytes
3578 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3579 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3580 * Quota Flags: 2 byte :
3581 * Unknown3: 6 NULL bytes
3585 * details for Quota Flags:
3587 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3588 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3589 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3590 * 0x0001 Enable Quotas: enable quota for this fs
3594 /* we need to fake up a fsp here,
3595 * because its not send in this call
3598 SMB_NTQUOTA_STRUCT quotas;
3601 ZERO_STRUCT(quotas);
3604 fsp.fnum = FNUM_FIELD_INVALID;
3607 if (get_current_uid(conn) != 0) {
3608 DEBUG(0,("get_user_quota: access_denied "
3609 "service [%s] user [%s]\n",
3610 lp_servicename(talloc_tos(), SNUM(conn)),
3611 conn->session_info->unix_info->unix_name));
3612 return NT_STATUS_ACCESS_DENIED;
3615 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3616 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3617 return map_nt_error_from_unix(errno);
3622 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3623 lp_servicename(talloc_tos(), SNUM(conn))));
3625 /* Unknown1 24 NULL bytes*/
3626 SBIG_UINT(pdata,0,(uint64_t)0);
3627 SBIG_UINT(pdata,8,(uint64_t)0);
3628 SBIG_UINT(pdata,16,(uint64_t)0);
3630 /* Default Soft Quota 8 bytes */
3631 SBIG_UINT(pdata,24,quotas.softlim);
3633 /* Default Hard Quota 8 bytes */
3634 SBIG_UINT(pdata,32,quotas.hardlim);
3636 /* Quota flag 2 bytes */
3637 SSVAL(pdata,40,quotas.qflags);
3639 /* Unknown3 6 NULL bytes */
3645 #endif /* HAVE_SYS_QUOTAS */
3646 case SMB_FS_OBJECTID_INFORMATION:
3648 unsigned char objid[16];
3649 struct smb_extended_info extended_info;
3650 memcpy(pdata,create_volume_objectid(conn, objid),16);
3651 samba_extended_info_version (&extended_info);
3652 SIVAL(pdata,16,extended_info.samba_magic);
3653 SIVAL(pdata,20,extended_info.samba_version);
3654 SIVAL(pdata,24,extended_info.samba_subversion);
3655 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3656 memcpy(pdata+36,extended_info.samba_version_string,28);
3661 case SMB_FS_SECTOR_SIZE_INFORMATION:
3665 * These values match a physical Windows Server 2012
3666 * share backed by NTFS atop spinning rust.
3668 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3669 /* logical_bytes_per_sector */
3670 SIVAL(pdata, 0, bytes_per_sector);
3671 /* phys_bytes_per_sector_atomic */
3672 SIVAL(pdata, 4, bytes_per_sector);
3673 /* phys_bytes_per_sector_perf */
3674 SIVAL(pdata, 8, bytes_per_sector);
3675 /* fs_effective_phys_bytes_per_sector_atomic */
3676 SIVAL(pdata, 12, bytes_per_sector);
3678 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3679 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3680 /* byte_off_sector_align */
3681 SIVAL(pdata, 20, 0);
3682 /* byte_off_partition_align */
3683 SIVAL(pdata, 24, 0);
3684 *fixed_portion = 28;
3690 * Query the version and capabilities of the CIFS UNIX extensions
3694 case SMB_QUERY_CIFS_UNIX_INFO:
3696 bool large_write = lp_min_receive_file_size() &&
3697 !srv_is_signing_active(xconn);
3698 bool large_read = !srv_is_signing_active(xconn);
3699 int encrypt_caps = 0;
3701 if (!lp_unix_extensions()) {
3702 return NT_STATUS_INVALID_LEVEL;
3705 switch (conn->encrypt_level) {
3706 case SMB_SIGNING_OFF:
3709 case SMB_SIGNING_DESIRED:
3710 case SMB_SIGNING_IF_REQUIRED:
3711 case SMB_SIGNING_DEFAULT:
3712 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3714 case SMB_SIGNING_REQUIRED:
3715 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3716 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3717 large_write = false;
3723 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3724 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3726 /* We have POSIX ACLs, pathname, encryption,
3727 * large read/write, and locking capability. */
3729 SBIG_UINT(pdata,4,((uint64_t)(
3730 CIFS_UNIX_POSIX_ACLS_CAP|
3731 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3732 CIFS_UNIX_FCNTL_LOCKS_CAP|
3733 CIFS_UNIX_EXTATTR_CAP|
3734 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3736 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3738 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3742 case SMB_QUERY_POSIX_FS_INFO:
3745 vfs_statvfs_struct svfs;
3747 if (!lp_unix_extensions()) {
3748 return NT_STATUS_INVALID_LEVEL;
3751 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3755 SIVAL(pdata,0,svfs.OptimalTransferSize);
3756 SIVAL(pdata,4,svfs.BlockSize);
3757 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3758 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3759 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3760 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3761 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3762 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3763 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3765 } else if (rc == EOPNOTSUPP) {
3766 return NT_STATUS_INVALID_LEVEL;
3767 #endif /* EOPNOTSUPP */
3769 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3770 return NT_STATUS_DOS(ERRSRV, ERRerror);
3775 case SMB_QUERY_POSIX_WHOAMI:
3781 if (!lp_unix_extensions()) {
3782 return NT_STATUS_INVALID_LEVEL;
3785 if (max_data_bytes < 40) {
3786 return NT_STATUS_BUFFER_TOO_SMALL;
3789 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3790 flags |= SMB_WHOAMI_GUEST;
3793 /* NOTE: 8 bytes for UID/GID, irrespective of native
3794 * platform size. This matches
3795 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3797 data_len = 4 /* flags */
3804 + 4 /* pad/reserved */
3805 + (conn->session_info->unix_token->ngroups * 8)
3807 + (conn->session_info->security_token->num_sids *
3811 SIVAL(pdata, 0, flags);
3812 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3814 (uint64_t)conn->session_info->unix_token->uid);
3815 SBIG_UINT(pdata, 16,
3816 (uint64_t)conn->session_info->unix_token->gid);
3819 if (data_len >= max_data_bytes) {
3820 /* Potential overflow, skip the GIDs and SIDs. */
3822 SIVAL(pdata, 24, 0); /* num_groups */
3823 SIVAL(pdata, 28, 0); /* num_sids */
3824 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3825 SIVAL(pdata, 36, 0); /* reserved */
3831 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3832 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3834 /* We walk the SID list twice, but this call is fairly
3835 * infrequent, and I don't expect that it's performance
3836 * sensitive -- jpeach
3838 for (i = 0, sid_bytes = 0;
3839 i < conn->session_info->security_token->num_sids; ++i) {
3840 sid_bytes += ndr_size_dom_sid(
3841 &conn->session_info->security_token->sids[i],
3845 /* SID list byte count */
3846 SIVAL(pdata, 32, sid_bytes);
3848 /* 4 bytes pad/reserved - must be zero */
3849 SIVAL(pdata, 36, 0);
3853 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3854 SBIG_UINT(pdata, data_len,
3855 (uint64_t)conn->session_info->unix_token->groups[i]);
3861 i < conn->session_info->security_token->num_sids; ++i) {
3862 int sid_len = ndr_size_dom_sid(
3863 &conn->session_info->security_token->sids[i],
3866 sid_linearize((uint8_t *)(pdata + data_len),
3868 &conn->session_info->security_token->sids[i]);
3869 data_len += sid_len;
3875 case SMB_MAC_QUERY_FS_INFO:
3877 * Thursby MAC extension... ONLY on NTFS filesystems
3878 * once we do streams then we don't need this
3880 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3882 SIVAL(pdata,84,0x100); /* Don't support mac... */
3887 return NT_STATUS_INVALID_LEVEL;
3890 *ret_data_len = data_len;
3894 /****************************************************************************
3895 Reply to a TRANS2_QFSINFO (query filesystem info).
3896 ****************************************************************************/
3898 static void call_trans2qfsinfo(connection_struct *conn,
3899 struct smb_request *req,
3900 char **pparams, int total_params,
3901 char **ppdata, int total_data,
3902 unsigned int max_data_bytes)
3904 char *params = *pparams;
3905 uint16_t info_level;
3907 size_t fixed_portion;
3910 if (total_params < 2) {
3911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3915 info_level = SVAL(params,0);
3917 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3918 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3919 DEBUG(0,("call_trans2qfsinfo: encryption required "
3920 "and info level 0x%x sent.\n",
3921 (unsigned int)info_level));
3922 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3927 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3929 status = smbd_do_qfsinfo(req->xconn, conn, req,
3936 if (!NT_STATUS_IS_OK(status)) {
3937 reply_nterror(req, status);
3941 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3944 DEBUG( 4, ( "%s info_level = %d\n",
3945 smb_fn_name(req->cmd), info_level) );
3950 /****************************************************************************
3951 Reply to a TRANS2_SETFSINFO (set filesystem info).
3952 ****************************************************************************/
3954 static void call_trans2setfsinfo(connection_struct *conn,
3955 struct smb_request *req,
3956 char **pparams, int total_params,
3957 char **ppdata, int total_data,
3958 unsigned int max_data_bytes)
3960 struct smbXsrv_connection *xconn = req->xconn;
3961 char *pdata = *ppdata;
3962 char *params = *pparams;
3963 uint16_t info_level;
3965 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3966 lp_servicename(talloc_tos(), SNUM(conn))));
3969 if (total_params < 4) {
3970 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3972 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3976 info_level = SVAL(params,2);
3979 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3980 info_level != SMB_SET_CIFS_UNIX_INFO) {
3981 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3982 "info level (0x%x) on IPC$.\n",
3983 (unsigned int)info_level));
3984 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3989 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3990 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3991 DEBUG(0,("call_trans2setfsinfo: encryption required "
3992 "and info level 0x%x sent.\n",
3993 (unsigned int)info_level));
3994 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3999 switch(info_level) {
4000 case SMB_SET_CIFS_UNIX_INFO:
4001 if (!lp_unix_extensions()) {
4002 DEBUG(2,("call_trans2setfsinfo: "
4003 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4004 "unix extensions off\n"));
4006 NT_STATUS_INVALID_LEVEL);
4010 /* There should be 12 bytes of capabilities set. */
4011 if (total_data < 12) {
4014 NT_STATUS_INVALID_PARAMETER);
4017 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4018 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4019 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4020 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4021 /* Just print these values for now. */
4022 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4023 "major = %u, minor = %u cap_low = 0x%x, "
4025 (unsigned int)xconn->
4026 smb1.unix_info.client_major,
4027 (unsigned int)xconn->
4028 smb1.unix_info.client_minor,
4029 (unsigned int)xconn->
4030 smb1.unix_info.client_cap_low,
4031 (unsigned int)xconn->
4032 smb1.unix_info.client_cap_high));
4034 /* Here is where we must switch to posix pathname processing... */
4035 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4036 lp_set_posix_pathnames();
4037 mangle_change_to_posix();
4040 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4041 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4042 /* Client that knows how to do posix locks,
4043 * but not posix open/mkdir operations. Set a
4044 * default type for read/write checks. */
4046 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4051 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4054 size_t param_len = 0;
4055 size_t data_len = total_data;
4057 if (!lp_unix_extensions()) {
4060 NT_STATUS_INVALID_LEVEL);
4064 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4067 NT_STATUS_NOT_SUPPORTED);
4071 if (xconn->smb1.echo_handler.trusted_fde) {
4072 DEBUG( 2,("call_trans2setfsinfo: "
4073 "request transport encryption disabled"
4074 "with 'fork echo handler = yes'\n"));
4077 NT_STATUS_NOT_SUPPORTED);
4081 DEBUG( 4,("call_trans2setfsinfo: "
4082 "request transport encryption.\n"));
4084 status = srv_request_encryption_setup(conn,
4085 (unsigned char **)ppdata,
4087 (unsigned char **)pparams,
4090 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4091 !NT_STATUS_IS_OK(status)) {
4092 reply_nterror(req, status);
4096 send_trans2_replies(conn, req,
4104 if (NT_STATUS_IS_OK(status)) {
4105 /* Server-side transport
4106 * encryption is now *on*. */
4107 status = srv_encryption_start(conn);
4108 if (!NT_STATUS_IS_OK(status)) {
4109 char *reason = talloc_asprintf(talloc_tos(),
4110 "Failure in setting "
4111 "up encrypted transport: %s",
4113 exit_server_cleanly(reason);
4119 case SMB_FS_QUOTA_INFORMATION:
4121 files_struct *fsp = NULL;
4122 SMB_NTQUOTA_STRUCT quotas;
4124 ZERO_STRUCT(quotas);
4127 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4128 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4129 lp_servicename(talloc_tos(), SNUM(conn)),
4130 conn->session_info->unix_info->unix_name));
4131 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4135 /* note: normally there're 48 bytes,
4136 * but we didn't use the last 6 bytes for now
4139 fsp = file_fsp(req, SVAL(params,0));
4141 if (!check_fsp_ntquota_handle(conn, req,
4143 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4145 req, NT_STATUS_INVALID_HANDLE);
4149 if (total_data < 42) {
4150 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4154 NT_STATUS_INVALID_PARAMETER);
4158 /* unknown_1 24 NULL bytes in pdata*/
4160 /* the soft quotas 8 bytes (uint64_t)*/
4161 quotas.softlim = BVAL(pdata,24);
4163 /* the hard quotas 8 bytes (uint64_t)*/
4164 quotas.hardlim = BVAL(pdata,32);
4166 /* quota_flags 2 bytes **/
4167 quotas.qflags = SVAL(pdata,40);
4169 /* unknown_2 6 NULL bytes follow*/
4171 /* now set the quotas */
4172 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4173 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4174 reply_nterror(req, map_nt_error_from_unix(errno));
4181 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4183 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4189 * sending this reply works fine,
4190 * but I'm not sure it's the same
4191 * like windows do...
4194 reply_outbuf(req, 10, 0);
4197 #if defined(HAVE_POSIX_ACLS)
4198 /****************************************************************************
4199 Utility function to count the number of entries in a POSIX acl.
4200 ****************************************************************************/
4202 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4204 unsigned int ace_count = 0;
4205 int entry_id = SMB_ACL_FIRST_ENTRY;
4206 SMB_ACL_ENTRY_T entry;
4208 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4210 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4211 entry_id = SMB_ACL_NEXT_ENTRY;
4218 /****************************************************************************
4219 Utility function to marshall a POSIX acl into wire format.
4220 ****************************************************************************/
4222 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4224 int entry_id = SMB_ACL_FIRST_ENTRY;
4225 SMB_ACL_ENTRY_T entry;
4227 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4228 SMB_ACL_TAG_T tagtype;
4229 SMB_ACL_PERMSET_T permset;
4230 unsigned char perms = 0;
4231 unsigned int own_grp;
4234 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4235 entry_id = SMB_ACL_NEXT_ENTRY;
4238 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4239 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4243 if (sys_acl_get_permset(entry, &permset) == -1) {
4244 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4248 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4249 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4250 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4252 SCVAL(pdata,1,perms);
4255 case SMB_ACL_USER_OBJ:
4256 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4257 own_grp = (unsigned int)pst->st_ex_uid;
4258 SIVAL(pdata,2,own_grp);
4263 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4265 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4268 own_grp = (unsigned int)*puid;
4269 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4270 SIVAL(pdata,2,own_grp);
4274 case SMB_ACL_GROUP_OBJ:
4275 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4276 own_grp = (unsigned int)pst->st_ex_gid;
4277 SIVAL(pdata,2,own_grp);
4282 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4284 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4287 own_grp = (unsigned int)*pgid;
4288 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4289 SIVAL(pdata,2,own_grp);
4294 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4295 SIVAL(pdata,2,0xFFFFFFFF);
4296 SIVAL(pdata,6,0xFFFFFFFF);
4299 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4300 SIVAL(pdata,2,0xFFFFFFFF);
4301 SIVAL(pdata,6,0xFFFFFFFF);
4304 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4307 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4314 /****************************************************************************
4315 Store the FILE_UNIX_BASIC info.
4316 ****************************************************************************/
4318 static char *store_file_unix_basic(connection_struct *conn,
4321 const SMB_STRUCT_STAT *psbuf)
4323 uint64_t file_index = get_FileIndex(conn, psbuf);
4326 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4327 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4329 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4332 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4335 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4336 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4337 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4340 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4344 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4348 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4351 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4352 devno = psbuf->st_ex_rdev;
4354 devno = psbuf->st_ex_dev;
4357 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4361 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4365 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4368 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4372 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4379 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4380 * the chflags(2) (or equivalent) flags.
4382 * XXX: this really should be behind the VFS interface. To do this, we would
4383 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4384 * Each VFS module could then implement its own mapping as appropriate for the
4385 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4387 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4391 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4395 { UF_IMMUTABLE, EXT_IMMUTABLE },
4399 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4403 { UF_HIDDEN, EXT_HIDDEN },
4406 /* Do not remove. We need to guarantee that this array has at least one
4407 * entry to build on HP-UX.
4413 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4414 uint32_t *smb_fflags, uint32_t *smb_fmask)
4418 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4419 *smb_fmask |= info2_flags_map[i].smb_fflag;
4420 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4421 *smb_fflags |= info2_flags_map[i].smb_fflag;
4426 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4427 const uint32_t smb_fflags,
4428 const uint32_t smb_fmask,
4431 uint32_t max_fmask = 0;
4434 *stat_fflags = psbuf->st_ex_flags;
4436 /* For each flags requested in smb_fmask, check the state of the
4437 * corresponding flag in smb_fflags and set or clear the matching
4441 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4442 max_fmask |= info2_flags_map[i].smb_fflag;
4443 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4444 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4445 *stat_fflags |= info2_flags_map[i].stat_fflag;
4447 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4452 /* If smb_fmask is asking to set any bits that are not supported by
4453 * our flag mappings, we should fail.
4455 if ((smb_fmask & max_fmask) != smb_fmask) {
4463 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4464 * of file flags and birth (create) time.
4466 static char *store_file_unix_basic_info2(connection_struct *conn,
4469 const SMB_STRUCT_STAT *psbuf)
4471 uint32_t file_flags = 0;
4472 uint32_t flags_mask = 0;
4474 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4476 /* Create (birth) time 64 bit */
4477 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4480 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4481 SIVAL(pdata, 0, file_flags); /* flags */
4482 SIVAL(pdata, 4, flags_mask); /* mask */
4488 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4489 const struct stream_struct *streams,
4491 unsigned int max_data_bytes,
4492 unsigned int *data_size)
4495 unsigned int ofs = 0;
4497 if (max_data_bytes < 32) {
4498 return NT_STATUS_INFO_LENGTH_MISMATCH;
4501 for (i = 0; i < num_streams; i++) {
4502 unsigned int next_offset;
4504 smb_ucs2_t *namebuf;
4506 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4507 streams[i].name, &namelen) ||
4510 return NT_STATUS_INVALID_PARAMETER;
4514 * name_buf is now null-terminated, we need to marshall as not
4521 * We cannot overflow ...
4523 if ((ofs + 24 + namelen) > max_data_bytes) {
4524 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4526 TALLOC_FREE(namebuf);
4527 return STATUS_BUFFER_OVERFLOW;
4530 SIVAL(data, ofs+4, namelen);
4531 SOFF_T(data, ofs+8, streams[i].size);
4532 SOFF_T(data, ofs+16, streams[i].alloc_size);
4533 memcpy(data+ofs+24, namebuf, namelen);
4534 TALLOC_FREE(namebuf);
4536 next_offset = ofs + 24 + namelen;
4538 if (i == num_streams-1) {
4539 SIVAL(data, ofs, 0);
4542 unsigned int align = ndr_align_size(next_offset, 8);
4544 if ((next_offset + align) > max_data_bytes) {
4545 DEBUG(10, ("refusing to overflow align "
4546 "reply at stream %u\n",
4548 TALLOC_FREE(namebuf);
4549 return STATUS_BUFFER_OVERFLOW;
4552 memset(data+next_offset, 0, align);
4553 next_offset += align;
4555 SIVAL(data, ofs, next_offset - ofs);
4562 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4566 return NT_STATUS_OK;
4569 /****************************************************************************
4570 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4571 ****************************************************************************/
4573 static void call_trans2qpipeinfo(connection_struct *conn,
4574 struct smb_request *req,
4575 unsigned int tran_call,
4576 char **pparams, int total_params,
4577 char **ppdata, int total_data,
4578 unsigned int max_data_bytes)
4580 char *params = *pparams;
4581 char *pdata = *ppdata;
4582 unsigned int data_size = 0;
4583 unsigned int param_size = 2;
4584 uint16_t info_level;
4588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4592 if (total_params < 4) {
4593 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4597 fsp = file_fsp(req, SVAL(params,0));
4598 if (!fsp_is_np(fsp)) {
4599 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4603 info_level = SVAL(params,2);
4605 *pparams = (char *)SMB_REALLOC(*pparams,2);
4606 if (*pparams == NULL) {
4607 reply_nterror(req, NT_STATUS_NO_MEMORY);
4612 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4616 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4617 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4618 if (*ppdata == NULL ) {
4619 reply_nterror(req, NT_STATUS_NO_MEMORY);
4624 switch (info_level) {
4625 case SMB_FILE_STANDARD_INFORMATION:
4627 SOFF_T(pdata,0,4096LL);
4634 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4638 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4644 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4645 TALLOC_CTX *mem_ctx,
4646 uint16_t info_level,
4648 struct smb_filename *smb_fname,
4649 bool delete_pending,
4650 struct timespec write_time_ts,
4651 struct ea_list *ea_list,
4652 int lock_data_count,
4655 unsigned int max_data_bytes,
4656 size_t *fixed_portion,
4658 unsigned int *pdata_size)
4660 char *pdata = *ppdata;
4661 char *dstart, *dend;
4662 unsigned int data_size;
4663 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4664 time_t create_time, mtime, atime, c_time;
4665 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4672 uint64_t file_size = 0;
4674 uint64_t allocation_size = 0;
4675 uint64_t file_index = 0;
4676 uint32_t access_mask = 0;
4679 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4680 return NT_STATUS_INVALID_LEVEL;
4683 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4684 smb_fname_str_dbg(smb_fname),
4686 info_level, max_data_bytes));
4688 mode = dos_mode(conn, smb_fname);
4689 nlink = psbuf->st_ex_nlink;
4691 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4695 if ((nlink > 0) && delete_pending) {
4699 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4700 return NT_STATUS_INVALID_PARAMETER;
4703 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4704 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4705 if (*ppdata == NULL) {
4706 return NT_STATUS_NO_MEMORY;
4710 dend = dstart + data_size - 1;
4712 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4713 update_stat_ex_mtime(psbuf, write_time_ts);
4716 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4717 mtime_ts = psbuf->st_ex_mtime;
4718 atime_ts = psbuf->st_ex_atime;
4719 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4721 if (lp_dos_filetime_resolution(SNUM(conn))) {
4722 dos_filetime_timespec(&create_time_ts);
4723 dos_filetime_timespec(&mtime_ts);
4724 dos_filetime_timespec(&atime_ts);
4725 dos_filetime_timespec(&ctime_ts);
4728 create_time = convert_timespec_to_time_t(create_time_ts);
4729 mtime = convert_timespec_to_time_t(mtime_ts);
4730 atime = convert_timespec_to_time_t(atime_ts);
4731 c_time = convert_timespec_to_time_t(ctime_ts);
4733 p = strrchr_m(smb_fname->base_name,'/');
4735 base_name = smb_fname->base_name;
4739 /* NT expects the name to be in an exact form of the *full*
4740 filename. See the trans2 torture test */
4741 if (ISDOT(base_name)) {
4742 dos_fname = talloc_strdup(mem_ctx, "\\");
4744 return NT_STATUS_NO_MEMORY;
4747 dos_fname = talloc_asprintf(mem_ctx,
4749 smb_fname->base_name);
4751 return NT_STATUS_NO_MEMORY;
4753 if (is_ntfs_stream_smb_fname(smb_fname)) {
4754 dos_fname = talloc_asprintf(dos_fname, "%s",
4755 smb_fname->stream_name);
4757 return NT_STATUS_NO_MEMORY;
4761 string_replace(dos_fname, '/', '\\');
4764 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4767 /* Do we have this path open ? */
4769 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4770 fsp1 = file_find_di_first(conn->sconn, fileid);
4771 if (fsp1 && fsp1->initial_allocation_size) {
4772 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4776 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4777 file_size = get_file_size_stat(psbuf);
4781 pos = fsp->fh->position_information;
4785 access_mask = fsp->access_mask;
4787 /* GENERIC_EXECUTE mapping from Windows */
4788 access_mask = 0x12019F;
4791 /* This should be an index number - looks like
4794 I think this causes us to fail the IFSKIT
4795 BasicFileInformationTest. -tpot */
4796 file_index = get_FileIndex(conn, psbuf);
4800 switch (info_level) {
4801 case SMB_INFO_STANDARD:
4802 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4804 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4805 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4806 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4807 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4808 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4809 SSVAL(pdata,l1_attrFile,mode);
4812 case SMB_INFO_QUERY_EA_SIZE:
4814 unsigned int ea_size =
4815 estimate_ea_size(conn, fsp,
4817 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4819 srv_put_dos_date2(pdata,0,create_time);
4820 srv_put_dos_date2(pdata,4,atime);
4821 srv_put_dos_date2(pdata,8,mtime); /* write time */
4822 SIVAL(pdata,12,(uint32_t)file_size);
4823 SIVAL(pdata,16,(uint32_t)allocation_size);
4824 SSVAL(pdata,20,mode);
4825 SIVAL(pdata,22,ea_size);
4829 case SMB_INFO_IS_NAME_VALID:
4830 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4832 /* os/2 needs this ? really ?*/
4833 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4835 /* This is only reached for qpathinfo */
4839 case SMB_INFO_QUERY_EAS_FROM_LIST:
4841 size_t total_ea_len = 0;
4842 struct ea_list *ea_file_list = NULL;
4843 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4846 get_ea_list_from_file(mem_ctx, conn, fsp,
4848 &total_ea_len, &ea_file_list);
4849 if (!NT_STATUS_IS_OK(status)) {
4853 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4855 if (!ea_list || (total_ea_len > data_size)) {
4857 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4861 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4865 case SMB_INFO_QUERY_ALL_EAS:
4867 /* We have data_size bytes to put EA's into. */
4868 size_t total_ea_len = 0;
4869 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4871 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4873 &total_ea_len, &ea_list);
4874 if (!NT_STATUS_IS_OK(status)) {
4878 if (!ea_list || (total_ea_len > data_size)) {
4880 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4884 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4888 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4890 /* This is FileFullEaInformation - 0xF which maps to
4891 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4893 /* We have data_size bytes to put EA's into. */
4894 size_t total_ea_len = 0;
4895 struct ea_list *ea_file_list = NULL;
4897 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4899 /*TODO: add filtering and index handling */
4902 get_ea_list_from_file(mem_ctx, conn, fsp,
4904 &total_ea_len, &ea_file_list);
4905 if (!NT_STATUS_IS_OK(status)) {
4908 if (!ea_file_list) {
4909 return NT_STATUS_NO_EAS_ON_FILE;
4912 status = fill_ea_chained_buffer(mem_ctx,
4916 conn, ea_file_list);
4917 if (!NT_STATUS_IS_OK(status)) {
4923 case SMB_FILE_BASIC_INFORMATION:
4924 case SMB_QUERY_FILE_BASIC_INFO:
4926 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4927 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4928 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4930 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4934 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4935 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4936 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4937 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4938 SIVAL(pdata,32,mode);
4940 DEBUG(5,("SMB_QFBI - "));
4941 DEBUG(5,("create: %s ", ctime(&create_time)));
4942 DEBUG(5,("access: %s ", ctime(&atime)));
4943 DEBUG(5,("write: %s ", ctime(&mtime)));
4944 DEBUG(5,("change: %s ", ctime(&c_time)));
4945 DEBUG(5,("mode: %x\n", mode));
4946 *fixed_portion = data_size;
4949 case SMB_FILE_STANDARD_INFORMATION:
4950 case SMB_QUERY_FILE_STANDARD_INFO:
4952 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4954 SOFF_T(pdata,0,allocation_size);
4955 SOFF_T(pdata,8,file_size);
4956 SIVAL(pdata,16,nlink);
4957 SCVAL(pdata,20,delete_pending?1:0);
4958 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4959 SSVAL(pdata,22,0); /* Padding. */
4960 *fixed_portion = 24;
4963 case SMB_FILE_EA_INFORMATION:
4964 case SMB_QUERY_FILE_EA_INFO:
4966 unsigned int ea_size =
4967 estimate_ea_size(conn, fsp, smb_fname);
4968 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4971 SIVAL(pdata,0,ea_size);
4975 /* Get the 8.3 name - used if NT SMB was negotiated. */
4976 case SMB_QUERY_FILE_ALT_NAME_INFO:
4977 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4979 char mangled_name[13];
4980 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4981 if (!name_to_8_3(base_name,mangled_name,
4982 True,conn->params)) {
4983 return NT_STATUS_NO_MEMORY;
4985 status = srvstr_push(dstart, flags2,
4986 pdata+4, mangled_name,
4987 PTR_DIFF(dend, pdata+4),
4989 if (!NT_STATUS_IS_OK(status)) {
4992 data_size = 4 + len;
4998 case SMB_QUERY_FILE_NAME_INFO:
5001 this must be *exactly* right for ACLs on mapped drives to work
5003 status = srvstr_push(dstart, flags2,
5005 PTR_DIFF(dend, pdata+4),
5007 if (!NT_STATUS_IS_OK(status)) {
5010 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5011 data_size = 4 + len;
5016 case SMB_FILE_ALLOCATION_INFORMATION:
5017 case SMB_QUERY_FILE_ALLOCATION_INFO:
5018 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5020 SOFF_T(pdata,0,allocation_size);
5023 case SMB_FILE_END_OF_FILE_INFORMATION:
5024 case SMB_QUERY_FILE_END_OF_FILEINFO:
5025 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5027 SOFF_T(pdata,0,file_size);
5030 case SMB_QUERY_FILE_ALL_INFO:
5031 case SMB_FILE_ALL_INFORMATION:
5033 unsigned int ea_size =
5034 estimate_ea_size(conn, fsp, smb_fname);
5035 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5036 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5037 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5038 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5039 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5040 SIVAL(pdata,32,mode);
5041 SIVAL(pdata,36,0); /* padding. */
5043 SOFF_T(pdata,0,allocation_size);
5044 SOFF_T(pdata,8,file_size);
5045 SIVAL(pdata,16,nlink);
5046 SCVAL(pdata,20,delete_pending);
5047 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5050 SIVAL(pdata,0,ea_size);
5051 pdata += 4; /* EA info */
5052 status = srvstr_push(dstart, flags2,
5054 PTR_DIFF(dend, pdata+4),
5056 if (!NT_STATUS_IS_OK(status)) {
5061 data_size = PTR_DIFF(pdata,(*ppdata));
5062 *fixed_portion = 10;
5066 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5068 unsigned int ea_size =
5069 estimate_ea_size(conn, fsp, smb_fname);
5070 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5071 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5072 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5073 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5074 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5075 SIVAL(pdata, 0x20, mode);
5076 SIVAL(pdata, 0x24, 0); /* padding. */
5077 SBVAL(pdata, 0x28, allocation_size);
5078 SBVAL(pdata, 0x30, file_size);
5079 SIVAL(pdata, 0x38, nlink);
5080 SCVAL(pdata, 0x3C, delete_pending);
5081 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5082 SSVAL(pdata, 0x3E, 0); /* padding */
5083 SBVAL(pdata, 0x40, file_index);
5084 SIVAL(pdata, 0x48, ea_size);
5085 SIVAL(pdata, 0x4C, access_mask);
5086 SBVAL(pdata, 0x50, pos);
5087 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5088 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5092 status = srvstr_push(dstart, flags2,
5094 PTR_DIFF(dend, pdata+4),
5096 if (!NT_STATUS_IS_OK(status)) {
5101 data_size = PTR_DIFF(pdata,(*ppdata));
5102 *fixed_portion = 104;
5105 case SMB_FILE_INTERNAL_INFORMATION:
5107 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5108 SBVAL(pdata, 0, file_index);
5113 case SMB_FILE_ACCESS_INFORMATION:
5114 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5115 SIVAL(pdata, 0, access_mask);
5120 case SMB_FILE_NAME_INFORMATION:
5121 /* Pathname with leading '\'. */
5124 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5125 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5126 SIVAL(pdata,0,byte_len);
5127 data_size = 4 + byte_len;
5131 case SMB_FILE_DISPOSITION_INFORMATION:
5132 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5134 SCVAL(pdata,0,delete_pending);
5138 case SMB_FILE_POSITION_INFORMATION:
5139 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5141 SOFF_T(pdata,0,pos);
5145 case SMB_FILE_MODE_INFORMATION:
5146 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5147 SIVAL(pdata,0,mode);
5152 case SMB_FILE_ALIGNMENT_INFORMATION:
5153 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5154 SIVAL(pdata,0,0); /* No alignment needed. */
5160 * NT4 server just returns "invalid query" to this - if we try
5161 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5164 /* The first statement above is false - verified using Thursby
5165 * client against NT4 -- gcolley.
5167 case SMB_QUERY_FILE_STREAM_INFO:
5168 case SMB_FILE_STREAM_INFORMATION: {
5169 unsigned int num_streams = 0;
5170 struct stream_struct *streams = NULL;
5172 DEBUG(10,("smbd_do_qfilepathinfo: "
5173 "SMB_FILE_STREAM_INFORMATION\n"));
5175 if (is_ntfs_stream_smb_fname(smb_fname)) {
5176 return NT_STATUS_INVALID_PARAMETER;
5179 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
5180 talloc_tos(), &num_streams, &streams);
5182 if (!NT_STATUS_IS_OK(status)) {
5183 DEBUG(10, ("could not get stream info: %s\n",
5184 nt_errstr(status)));
5188 status = marshall_stream_info(num_streams, streams,
5189 pdata, max_data_bytes,
5192 if (!NT_STATUS_IS_OK(status)) {
5193 DEBUG(10, ("marshall_stream_info failed: %s\n",
5194 nt_errstr(status)));
5195 TALLOC_FREE(streams);
5199 TALLOC_FREE(streams);
5201 *fixed_portion = 32;
5205 case SMB_QUERY_COMPRESSION_INFO:
5206 case SMB_FILE_COMPRESSION_INFORMATION:
5207 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5208 SOFF_T(pdata,0,file_size);
5209 SIVAL(pdata,8,0); /* ??? */
5210 SIVAL(pdata,12,0); /* ??? */
5212 *fixed_portion = 16;
5215 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5216 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5217 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5218 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5219 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5220 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5221 SOFF_T(pdata,32,allocation_size);
5222 SOFF_T(pdata,40,file_size);
5223 SIVAL(pdata,48,mode);
5224 SIVAL(pdata,52,0); /* ??? */
5226 *fixed_portion = 56;
5229 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5230 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5231 SIVAL(pdata,0,mode);
5238 * CIFS UNIX Extensions.
5241 case SMB_QUERY_FILE_UNIX_BASIC:
5243 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5244 data_size = PTR_DIFF(pdata,(*ppdata));
5246 DEBUG(4,("smbd_do_qfilepathinfo: "
5247 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5248 dump_data(4, (uint8_t *)(*ppdata), data_size);
5252 case SMB_QUERY_FILE_UNIX_INFO2:
5254 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5255 data_size = PTR_DIFF(pdata,(*ppdata));
5259 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5261 for (i=0; i<100; i++)
5262 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5268 case SMB_QUERY_FILE_UNIX_LINK:
5271 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5274 return NT_STATUS_NO_MEMORY;
5277 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5279 if(!S_ISLNK(psbuf->st_ex_mode)) {
5280 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5283 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5285 link_len = SMB_VFS_READLINK(conn,
5286 smb_fname->base_name,
5288 if (link_len == -1) {
5289 return map_nt_error_from_unix(errno);
5291 buffer[link_len] = 0;
5292 status = srvstr_push(dstart, flags2,
5294 PTR_DIFF(dend, pdata),
5295 STR_TERMINATE, &len);
5296 if (!NT_STATUS_IS_OK(status)) {
5300 data_size = PTR_DIFF(pdata,(*ppdata));
5305 #if defined(HAVE_POSIX_ACLS)
5306 case SMB_QUERY_POSIX_ACL:
5308 SMB_ACL_T file_acl = NULL;
5309 SMB_ACL_T def_acl = NULL;
5310 uint16_t num_file_acls = 0;
5311 uint16_t num_def_acls = 0;
5313 if (fsp && fsp->fh->fd != -1) {
5314 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5318 SMB_VFS_SYS_ACL_GET_FILE(conn,
5319 smb_fname->base_name,
5320 SMB_ACL_TYPE_ACCESS,
5324 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5325 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5326 "not implemented on "
5327 "filesystem containing %s\n",
5328 smb_fname->base_name));
5329 return NT_STATUS_NOT_IMPLEMENTED;
5332 if (S_ISDIR(psbuf->st_ex_mode)) {
5333 if (fsp && fsp->is_directory) {
5335 SMB_VFS_SYS_ACL_GET_FILE(
5337 fsp->fsp_name->base_name,
5338 SMB_ACL_TYPE_DEFAULT,
5342 SMB_VFS_SYS_ACL_GET_FILE(
5344 smb_fname->base_name,
5345 SMB_ACL_TYPE_DEFAULT,
5348 def_acl = free_empty_sys_acl(conn, def_acl);
5351 num_file_acls = count_acl_entries(conn, file_acl);
5352 num_def_acls = count_acl_entries(conn, def_acl);
5354 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5355 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5357 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5358 SMB_POSIX_ACL_HEADER_SIZE) ));
5360 TALLOC_FREE(file_acl);
5363 TALLOC_FREE(def_acl);
5365 return NT_STATUS_BUFFER_TOO_SMALL;
5368 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5369 SSVAL(pdata,2,num_file_acls);
5370 SSVAL(pdata,4,num_def_acls);
5371 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5373 TALLOC_FREE(file_acl);
5376 TALLOC_FREE(def_acl);
5378 return NT_STATUS_INTERNAL_ERROR;
5380 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5382 TALLOC_FREE(file_acl);
5385 TALLOC_FREE(def_acl);
5387 return NT_STATUS_INTERNAL_ERROR;
5391 TALLOC_FREE(file_acl);
5394 TALLOC_FREE(def_acl);
5396 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5402 case SMB_QUERY_POSIX_LOCK:
5407 enum brl_type lock_type;
5409 /* We need an open file with a real fd for this. */
5410 if (!fsp || fsp->fh->fd == -1) {
5411 return NT_STATUS_INVALID_LEVEL;
5414 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5415 return NT_STATUS_INVALID_PARAMETER;
5418 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5419 case POSIX_LOCK_TYPE_READ:
5420 lock_type = READ_LOCK;
5422 case POSIX_LOCK_TYPE_WRITE:
5423 lock_type = WRITE_LOCK;
5425 case POSIX_LOCK_TYPE_UNLOCK:
5427 /* There's no point in asking for an unlock... */
5428 return NT_STATUS_INVALID_PARAMETER;
5431 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5432 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5433 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5435 status = query_lock(fsp,
5442 if (ERROR_WAS_LOCK_DENIED(status)) {
5443 /* Here we need to report who has it locked... */
5444 data_size = POSIX_LOCK_DATA_SIZE;
5446 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5447 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5448 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5449 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5450 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5452 } else if (NT_STATUS_IS_OK(status)) {
5453 /* For success we just return a copy of what we sent
5454 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5455 data_size = POSIX_LOCK_DATA_SIZE;
5456 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5457 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5465 return NT_STATUS_INVALID_LEVEL;
5468 *pdata_size = data_size;
5469 return NT_STATUS_OK;
5472 /****************************************************************************
5473 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5474 file name or file id).
5475 ****************************************************************************/
5477 static void call_trans2qfilepathinfo(connection_struct *conn,
5478 struct smb_request *req,
5479 unsigned int tran_call,
5480 char **pparams, int total_params,
5481 char **ppdata, int total_data,
5482 unsigned int max_data_bytes)
5484 char *params = *pparams;
5485 char *pdata = *ppdata;
5486 uint16_t info_level;
5487 unsigned int data_size = 0;
5488 unsigned int param_size = 2;
5489 struct smb_filename *smb_fname = NULL;
5490 bool delete_pending = False;
5491 struct timespec write_time_ts;
5492 files_struct *fsp = NULL;
5493 struct file_id fileid;
5494 struct ea_list *ea_list = NULL;
5495 int lock_data_count = 0;
5496 char *lock_data = NULL;
5497 size_t fixed_portion;
5498 NTSTATUS status = NT_STATUS_OK;
5501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5505 ZERO_STRUCT(write_time_ts);
5507 if (tran_call == TRANSACT2_QFILEINFO) {
5508 if (total_params < 4) {
5509 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5514 call_trans2qpipeinfo(conn, req, tran_call,
5515 pparams, total_params,
5521 fsp = file_fsp(req, SVAL(params,0));
5522 info_level = SVAL(params,2);
5524 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5526 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5527 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5531 /* Initial check for valid fsp ptr. */
5532 if (!check_fsp_open(conn, req, fsp)) {
5536 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5537 if (smb_fname == NULL) {
5538 reply_nterror(req, NT_STATUS_NO_MEMORY);
5542 if(fsp->fake_file_handle) {
5544 * This is actually for the QUOTA_FAKE_FILE --metze
5547 /* We know this name is ok, it's already passed the checks. */
5549 } else if(fsp->fh->fd == -1) {
5551 * This is actually a QFILEINFO on a directory
5552 * handle (returned from an NT SMB). NT5.0 seems
5553 * to do this call. JRA.
5556 if (INFO_LEVEL_IS_UNIX(info_level)) {
5557 /* Always do lstat for UNIX calls. */
5558 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5559 DEBUG(3,("call_trans2qfilepathinfo: "
5560 "SMB_VFS_LSTAT of %s failed "
5562 smb_fname_str_dbg(smb_fname),
5565 map_nt_error_from_unix(errno));
5568 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5569 DEBUG(3,("call_trans2qfilepathinfo: "
5570 "SMB_VFS_STAT of %s failed (%s)\n",
5571 smb_fname_str_dbg(smb_fname),
5574 map_nt_error_from_unix(errno));
5578 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5579 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5582 * Original code - this is an open file.
5584 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5585 DEBUG(3, ("fstat of %s failed (%s)\n",
5586 fsp_fnum_dbg(fsp), strerror(errno)));
5588 map_nt_error_from_unix(errno));
5591 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5592 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5598 uint32_t ucf_flags = (req->posix_pathnames ?
5599 UCF_POSIX_PATHNAMES : 0);
5602 if (total_params < 7) {
5603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5607 info_level = SVAL(params,0);
5609 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5611 if (INFO_LEVEL_IS_UNIX(info_level)) {
5612 if (!lp_unix_extensions()) {
5613 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5616 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5617 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5618 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5619 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5623 if (req->posix_pathnames) {
5624 srvstr_get_path_posix(req,
5633 srvstr_get_path(req,
5642 if (!NT_STATUS_IS_OK(status)) {
5643 reply_nterror(req, status);
5647 status = filename_convert(req,
5649 req->flags2 & FLAGS2_DFS_PATHNAMES,
5654 if (!NT_STATUS_IS_OK(status)) {
5655 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5656 reply_botherror(req,
5657 NT_STATUS_PATH_NOT_COVERED,
5658 ERRSRV, ERRbadpath);
5661 reply_nterror(req, status);
5665 /* If this is a stream, check if there is a delete_pending. */
5666 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5667 && is_ntfs_stream_smb_fname(smb_fname)) {
5668 struct smb_filename *smb_fname_base;
5670 /* Create an smb_filename with stream_name == NULL. */
5671 smb_fname_base = synthetic_smb_fname(
5672 talloc_tos(), smb_fname->base_name,
5674 if (smb_fname_base == NULL) {
5675 reply_nterror(req, NT_STATUS_NO_MEMORY);
5679 if (INFO_LEVEL_IS_UNIX(info_level)) {
5680 /* Always do lstat for UNIX calls. */
5681 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5682 DEBUG(3,("call_trans2qfilepathinfo: "
5683 "SMB_VFS_LSTAT of %s failed "
5685 smb_fname_str_dbg(smb_fname_base),
5687 TALLOC_FREE(smb_fname_base);
5689 map_nt_error_from_unix(errno));
5693 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5694 DEBUG(3,("call_trans2qfilepathinfo: "
5695 "fileinfo of %s failed "
5697 smb_fname_str_dbg(smb_fname_base),
5699 TALLOC_FREE(smb_fname_base);
5701 map_nt_error_from_unix(errno));
5706 status = file_name_hash(conn,
5707 smb_fname_str_dbg(smb_fname_base),
5709 if (!NT_STATUS_IS_OK(status)) {
5710 TALLOC_FREE(smb_fname_base);
5711 reply_nterror(req, status);
5715 fileid = vfs_file_id_from_sbuf(conn,
5716 &smb_fname_base->st);
5717 TALLOC_FREE(smb_fname_base);
5718 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5719 if (delete_pending) {
5720 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5725 if (INFO_LEVEL_IS_UNIX(info_level)) {
5726 /* Always do lstat for UNIX calls. */
5727 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5728 DEBUG(3,("call_trans2qfilepathinfo: "
5729 "SMB_VFS_LSTAT of %s failed (%s)\n",
5730 smb_fname_str_dbg(smb_fname),
5733 map_nt_error_from_unix(errno));
5738 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5739 DEBUG(3,("call_trans2qfilepathinfo: "
5740 "SMB_VFS_STAT of %s failed (%s)\n",
5741 smb_fname_str_dbg(smb_fname),
5744 map_nt_error_from_unix(errno));
5749 status = file_name_hash(conn,
5750 smb_fname_str_dbg(smb_fname),
5752 if (!NT_STATUS_IS_OK(status)) {
5753 reply_nterror(req, status);
5757 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5758 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5759 if (delete_pending) {
5760 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5765 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5766 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5768 info_level,tran_call,total_data));
5770 /* Pull out any data sent here before we realloc. */
5771 switch (info_level) {
5772 case SMB_INFO_QUERY_EAS_FROM_LIST:
5774 /* Pull any EA list from the data portion. */
5777 if (total_data < 4) {
5779 req, NT_STATUS_INVALID_PARAMETER);
5782 ea_size = IVAL(pdata,0);
5784 if (total_data > 0 && ea_size != total_data) {
5785 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5786 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5788 req, NT_STATUS_INVALID_PARAMETER);
5792 if (!lp_ea_support(SNUM(conn))) {
5793 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5797 /* Pull out the list of names. */
5798 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5801 req, NT_STATUS_INVALID_PARAMETER);
5807 case SMB_QUERY_POSIX_LOCK:
5809 if (fsp == NULL || fsp->fh->fd == -1) {
5810 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5814 if (total_data != POSIX_LOCK_DATA_SIZE) {
5816 req, NT_STATUS_INVALID_PARAMETER);
5820 /* Copy the lock range data. */
5821 lock_data = (char *)talloc_memdup(
5822 req, pdata, total_data);
5824 reply_nterror(req, NT_STATUS_NO_MEMORY);
5827 lock_data_count = total_data;
5833 *pparams = (char *)SMB_REALLOC(*pparams,2);
5834 if (*pparams == NULL) {
5835 reply_nterror(req, NT_STATUS_NO_MEMORY);
5842 * draft-leach-cifs-v1-spec-02.txt
5843 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5846 * The requested information is placed in the Data portion of the
5847 * transaction response. For the information levels greater than 0x100,
5848 * the transaction response has 1 parameter word which should be
5849 * ignored by the client.
5851 * However Windows only follows this rule for the IS_NAME_VALID call.
5853 switch (info_level) {
5854 case SMB_INFO_IS_NAME_VALID:
5859 if ((info_level & 0xFF00) == 0xFF00) {
5861 * We use levels that start with 0xFF00
5862 * internally to represent SMB2 specific levels
5864 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5868 status = smbd_do_qfilepathinfo(conn, req, info_level,
5870 delete_pending, write_time_ts,
5872 lock_data_count, lock_data,
5873 req->flags2, max_data_bytes,
5875 ppdata, &data_size);
5876 if (!NT_STATUS_IS_OK(status)) {
5877 reply_nterror(req, status);
5880 if (fixed_portion > max_data_bytes) {
5881 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5885 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5891 /****************************************************************************
5892 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5894 ****************************************************************************/
5896 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5897 connection_struct *conn,
5898 struct smb_request *req,
5899 bool overwrite_if_exists,
5900 const struct smb_filename *smb_fname_old,
5901 struct smb_filename *smb_fname_new)
5903 NTSTATUS status = NT_STATUS_OK;
5905 /* source must already exist. */
5906 if (!VALID_STAT(smb_fname_old->st)) {
5907 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5910 if (VALID_STAT(smb_fname_new->st)) {
5911 if (overwrite_if_exists) {
5912 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5913 return NT_STATUS_FILE_IS_A_DIRECTORY;
5915 status = unlink_internals(conn,
5917 FILE_ATTRIBUTE_NORMAL,
5920 if (!NT_STATUS_IS_OK(status)) {
5924 /* Disallow if newname already exists. */
5925 return NT_STATUS_OBJECT_NAME_COLLISION;
5929 /* No links from a directory. */
5930 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5931 return NT_STATUS_FILE_IS_A_DIRECTORY;
5934 /* Setting a hardlink to/from a stream isn't currently supported. */
5935 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5936 is_ntfs_stream_smb_fname(smb_fname_new)) {
5937 return NT_STATUS_INVALID_PARAMETER;
5940 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5941 smb_fname_old->base_name, smb_fname_new->base_name));
5943 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5944 smb_fname_new->base_name) != 0) {
5945 status = map_nt_error_from_unix(errno);
5946 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5947 nt_errstr(status), smb_fname_old->base_name,
5948 smb_fname_new->base_name));
5953 /****************************************************************************
5954 Deal with setting the time from any of the setfilepathinfo functions.
5955 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5956 calling this function.
5957 ****************************************************************************/
5959 NTSTATUS smb_set_file_time(connection_struct *conn,
5961 const struct smb_filename *smb_fname,
5962 struct smb_file_time *ft,
5963 bool setting_write_time)
5965 struct smb_filename smb_fname_base;
5967 FILE_NOTIFY_CHANGE_LAST_ACCESS
5968 |FILE_NOTIFY_CHANGE_LAST_WRITE
5969 |FILE_NOTIFY_CHANGE_CREATION;
5971 if (!VALID_STAT(smb_fname->st)) {
5972 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5975 /* get some defaults (no modifications) if any info is zero or -1. */
5976 if (null_timespec(ft->create_time)) {
5977 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5980 if (null_timespec(ft->atime)) {
5981 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5984 if (null_timespec(ft->mtime)) {
5985 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5988 if (!setting_write_time) {
5989 /* ft->mtime comes from change time, not write time. */
5990 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5993 /* Ensure the resolution is the correct for
5994 * what we can store on this filesystem. */
5996 round_timespec(conn->ts_res, &ft->create_time);
5997 round_timespec(conn->ts_res, &ft->ctime);
5998 round_timespec(conn->ts_res, &ft->atime);
5999 round_timespec(conn->ts_res, &ft->mtime);
6001 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6002 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6003 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6004 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6005 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6006 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6007 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6008 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6010 if (setting_write_time) {
6012 * This was a Windows setfileinfo on an open file.
6013 * NT does this a lot. We also need to
6014 * set the time here, as it can be read by
6015 * FindFirst/FindNext and with the patch for bug #2045
6016 * in smbd/fileio.c it ensures that this timestamp is
6017 * kept sticky even after a write. We save the request
6018 * away and will set it on file close and after a write. JRA.
6021 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6022 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6025 if (fsp->base_fsp) {
6026 set_sticky_write_time_fsp(fsp->base_fsp,
6029 set_sticky_write_time_fsp(fsp, ft->mtime);
6032 set_sticky_write_time_path(
6033 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6038 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6040 /* Always call ntimes on the base, even if a stream was passed in. */
6041 smb_fname_base = *smb_fname;
6042 smb_fname_base.stream_name = NULL;
6044 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6045 return map_nt_error_from_unix(errno);
6048 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6049 smb_fname->base_name);
6050 return NT_STATUS_OK;
6053 /****************************************************************************
6054 Deal with setting the dosmode from any of the setfilepathinfo functions.
6055 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6056 done before calling this function.
6057 ****************************************************************************/
6059 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6060 const struct smb_filename *smb_fname,
6063 struct smb_filename *smb_fname_base;
6066 if (!VALID_STAT(smb_fname->st)) {
6067 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6070 /* Always operate on the base_name, even if a stream was passed in. */
6071 smb_fname_base = synthetic_smb_fname(
6072 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
6073 if (smb_fname_base == NULL) {
6074 return NT_STATUS_NO_MEMORY;
6078 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6079 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6081 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6085 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6087 /* check the mode isn't different, before changing it */
6088 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6089 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6090 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6091 (unsigned int)dosmode));
6093 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6095 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6097 smb_fname_str_dbg(smb_fname_base),
6099 status = map_nt_error_from_unix(errno);
6103 status = NT_STATUS_OK;
6105 TALLOC_FREE(smb_fname_base);
6109 /****************************************************************************
6110 Deal with setting the size from any of the setfilepathinfo functions.
6111 ****************************************************************************/
6113 static NTSTATUS smb_set_file_size(connection_struct *conn,
6114 struct smb_request *req,
6116 const struct smb_filename *smb_fname,
6117 const SMB_STRUCT_STAT *psbuf,
6119 bool fail_after_createfile)
6121 NTSTATUS status = NT_STATUS_OK;
6122 struct smb_filename *smb_fname_tmp = NULL;
6123 files_struct *new_fsp = NULL;
6125 if (!VALID_STAT(*psbuf)) {
6126 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6129 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6131 if (size == get_file_size_stat(psbuf)) {
6132 return NT_STATUS_OK;
6135 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6136 smb_fname_str_dbg(smb_fname), (double)size));
6138 if (fsp && fsp->fh->fd != -1) {
6139 /* Handle based call. */
6140 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6141 return NT_STATUS_ACCESS_DENIED;
6144 if (vfs_set_filelen(fsp, size) == -1) {
6145 return map_nt_error_from_unix(errno);
6147 trigger_write_time_update_immediate(fsp);
6148 return NT_STATUS_OK;
6151 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6152 if (smb_fname_tmp == NULL) {
6153 return NT_STATUS_NO_MEMORY;
6156 smb_fname_tmp->st = *psbuf;
6158 status = SMB_VFS_CREATE_FILE(
6161 0, /* root_dir_fid */
6162 smb_fname_tmp, /* fname */
6163 FILE_WRITE_DATA, /* access_mask */
6164 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6166 FILE_OPEN, /* create_disposition*/
6167 0, /* create_options */
6168 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6169 0, /* oplock_request */
6171 0, /* allocation_size */
6172 0, /* private_flags */
6175 &new_fsp, /* result */
6177 NULL, NULL); /* create context */
6179 TALLOC_FREE(smb_fname_tmp);
6181 if (!NT_STATUS_IS_OK(status)) {
6182 /* NB. We check for open_was_deferred in the caller. */
6186 /* See RAW-SFILEINFO-END-OF-FILE */
6187 if (fail_after_createfile) {
6188 close_file(req, new_fsp,NORMAL_CLOSE);
6189 return NT_STATUS_INVALID_LEVEL;
6192 if (vfs_set_filelen(new_fsp, size) == -1) {
6193 status = map_nt_error_from_unix(errno);
6194 close_file(req, new_fsp,NORMAL_CLOSE);
6198 trigger_write_time_update_immediate(new_fsp);
6199 close_file(req, new_fsp,NORMAL_CLOSE);
6200 return NT_STATUS_OK;
6203 /****************************************************************************
6204 Deal with SMB_INFO_SET_EA.
6205 ****************************************************************************/
6207 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6211 const struct smb_filename *smb_fname)
6213 struct ea_list *ea_list = NULL;
6214 TALLOC_CTX *ctx = NULL;
6215 NTSTATUS status = NT_STATUS_OK;
6217 if (total_data < 10) {
6219 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6220 length. They seem to have no effect. Bug #3212. JRA */
6222 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6223 /* We're done. We only get EA info in this call. */
6224 return NT_STATUS_OK;
6227 return NT_STATUS_INVALID_PARAMETER;
6230 if (IVAL(pdata,0) > total_data) {
6231 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6232 IVAL(pdata,0), (unsigned int)total_data));
6233 return NT_STATUS_INVALID_PARAMETER;
6237 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6239 return NT_STATUS_INVALID_PARAMETER;
6242 status = set_ea(conn, fsp, smb_fname, ea_list);
6247 /****************************************************************************
6248 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6249 ****************************************************************************/
6251 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6256 struct ea_list *ea_list = NULL;
6260 return NT_STATUS_INVALID_HANDLE;
6263 if (!lp_ea_support(SNUM(conn))) {
6264 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6265 "EA's not supported.\n",
6266 (unsigned int)total_data));
6267 return NT_STATUS_EAS_NOT_SUPPORTED;
6270 if (total_data < 10) {
6271 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6273 (unsigned int)total_data));
6274 return NT_STATUS_INVALID_PARAMETER;
6277 ea_list = read_nttrans_ea_list(talloc_tos(),
6282 return NT_STATUS_INVALID_PARAMETER;
6285 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6287 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6288 smb_fname_str_dbg(fsp->fsp_name),
6289 nt_errstr(status) ));
6295 /****************************************************************************
6296 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6297 ****************************************************************************/
6299 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6303 struct smb_filename *smb_fname)
6305 NTSTATUS status = NT_STATUS_OK;
6306 bool delete_on_close;
6307 uint32_t dosmode = 0;
6309 if (total_data < 1) {
6310 return NT_STATUS_INVALID_PARAMETER;
6314 return NT_STATUS_INVALID_HANDLE;
6317 delete_on_close = (CVAL(pdata,0) ? True : False);
6318 dosmode = dos_mode(conn, smb_fname);
6320 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6321 "delete_on_close = %u\n",
6322 smb_fname_str_dbg(smb_fname),
6323 (unsigned int)dosmode,
6324 (unsigned int)delete_on_close ));
6326 if (delete_on_close) {
6327 status = can_set_delete_on_close(fsp, dosmode);
6328 if (!NT_STATUS_IS_OK(status)) {
6333 /* The set is across all open files on this dev/inode pair. */
6334 if (!set_delete_on_close(fsp, delete_on_close,
6335 conn->session_info->security_token,
6336 conn->session_info->unix_token)) {
6337 return NT_STATUS_ACCESS_DENIED;
6339 return NT_STATUS_OK;
6342 /****************************************************************************
6343 Deal with SMB_FILE_POSITION_INFORMATION.
6344 ****************************************************************************/
6346 static NTSTATUS smb_file_position_information(connection_struct *conn,
6351 uint64_t position_information;
6353 if (total_data < 8) {
6354 return NT_STATUS_INVALID_PARAMETER;
6358 /* Ignore on pathname based set. */
6359 return NT_STATUS_OK;
6362 position_information = (uint64_t)IVAL(pdata,0);
6363 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6365 DEBUG(10,("smb_file_position_information: Set file position "
6366 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6367 (double)position_information));
6368 fsp->fh->position_information = position_information;
6369 return NT_STATUS_OK;
6372 /****************************************************************************
6373 Deal with SMB_FILE_MODE_INFORMATION.
6374 ****************************************************************************/
6376 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6382 if (total_data < 4) {
6383 return NT_STATUS_INVALID_PARAMETER;
6385 mode = IVAL(pdata,0);
6386 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6387 return NT_STATUS_INVALID_PARAMETER;
6389 return NT_STATUS_OK;
6392 /****************************************************************************
6393 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6394 ****************************************************************************/
6396 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6397 struct smb_request *req,
6400 const struct smb_filename *smb_fname)
6402 char *link_target = NULL;
6403 const char *newname = smb_fname->base_name;
6404 TALLOC_CTX *ctx = talloc_tos();
6406 /* Set a symbolic link. */
6407 /* Don't allow this if follow links is false. */
6409 if (total_data == 0) {
6410 return NT_STATUS_INVALID_PARAMETER;
6413 if (!lp_follow_symlinks(SNUM(conn))) {
6414 return NT_STATUS_ACCESS_DENIED;
6417 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6418 total_data, STR_TERMINATE);
6421 return NT_STATUS_INVALID_PARAMETER;
6424 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6425 newname, link_target ));
6427 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6428 return map_nt_error_from_unix(errno);
6431 return NT_STATUS_OK;
6434 /****************************************************************************
6435 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6436 ****************************************************************************/
6438 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6439 struct smb_request *req,
6440 const char *pdata, int total_data,
6441 struct smb_filename *smb_fname_new)
6443 char *oldname = NULL;
6444 struct smb_filename *smb_fname_old = NULL;
6445 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6446 TALLOC_CTX *ctx = talloc_tos();
6447 NTSTATUS status = NT_STATUS_OK;
6449 /* Set a hard link. */
6450 if (total_data == 0) {
6451 return NT_STATUS_INVALID_PARAMETER;
6454 if (req->posix_pathnames) {
6455 srvstr_get_path_posix(ctx,
6464 srvstr_get_path(ctx,
6473 if (!NT_STATUS_IS_OK(status)) {
6477 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6478 smb_fname_str_dbg(smb_fname_new), oldname));
6480 status = filename_convert(ctx,
6482 req->flags2 & FLAGS2_DFS_PATHNAMES,
6487 if (!NT_STATUS_IS_OK(status)) {
6491 return hardlink_internals(ctx, conn, req, false,
6492 smb_fname_old, smb_fname_new);
6495 /****************************************************************************
6496 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6497 ****************************************************************************/
6499 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6500 struct smb_request *req,
6504 struct smb_filename *smb_fname_src)
6508 char *newname = NULL;
6509 struct smb_filename *smb_fname_dst = NULL;
6510 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6511 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6512 NTSTATUS status = NT_STATUS_OK;
6513 TALLOC_CTX *ctx = talloc_tos();
6516 return NT_STATUS_INVALID_HANDLE;
6519 if (total_data < 20) {
6520 return NT_STATUS_INVALID_PARAMETER;
6523 overwrite = (CVAL(pdata,0) ? True : False);
6524 len = IVAL(pdata,16);
6526 if (len > (total_data - 20) || (len == 0)) {
6527 return NT_STATUS_INVALID_PARAMETER;
6530 if (req->posix_pathnames) {
6531 srvstr_get_path_posix(ctx,
6540 srvstr_get_path(ctx,
6549 if (!NT_STATUS_IS_OK(status)) {
6553 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6556 status = filename_convert(ctx,
6558 req->flags2 & FLAGS2_DFS_PATHNAMES,
6563 if (!NT_STATUS_IS_OK(status)) {
6567 if (fsp->base_fsp) {
6568 /* newname must be a stream name. */
6569 if (newname[0] != ':') {
6570 return NT_STATUS_NOT_SUPPORTED;
6573 /* Create an smb_fname to call rename_internals_fsp() with. */
6574 smb_fname_dst = synthetic_smb_fname(
6575 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6577 if (smb_fname_dst == NULL) {
6578 status = NT_STATUS_NO_MEMORY;
6583 * Set the original last component, since
6584 * rename_internals_fsp() requires it.
6586 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6588 if (smb_fname_dst->original_lcomp == NULL) {
6589 status = NT_STATUS_NO_MEMORY;
6595 DEBUG(10,("smb2_file_rename_information: "
6596 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6597 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6598 smb_fname_str_dbg(smb_fname_dst)));
6599 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6600 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6604 TALLOC_FREE(smb_fname_dst);
6608 static NTSTATUS smb_file_link_information(connection_struct *conn,
6609 struct smb_request *req,
6613 struct smb_filename *smb_fname_src)
6617 char *newname = NULL;
6618 struct smb_filename *smb_fname_dst = NULL;
6619 NTSTATUS status = NT_STATUS_OK;
6620 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6621 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6622 TALLOC_CTX *ctx = talloc_tos();
6625 return NT_STATUS_INVALID_HANDLE;
6628 if (total_data < 20) {
6629 return NT_STATUS_INVALID_PARAMETER;
6632 overwrite = (CVAL(pdata,0) ? true : false);
6633 len = IVAL(pdata,16);
6635 if (len > (total_data - 20) || (len == 0)) {
6636 return NT_STATUS_INVALID_PARAMETER;
6639 if (req->posix_pathnames) {
6640 srvstr_get_path_posix(ctx,
6649 srvstr_get_path(ctx,
6658 if (!NT_STATUS_IS_OK(status)) {
6662 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6665 status = filename_convert(ctx,
6667 req->flags2 & FLAGS2_DFS_PATHNAMES,
6672 if (!NT_STATUS_IS_OK(status)) {
6676 if (fsp->base_fsp) {
6677 /* No stream names. */
6678 return NT_STATUS_NOT_SUPPORTED;
6681 DEBUG(10,("smb_file_link_information: "
6682 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6683 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6684 smb_fname_str_dbg(smb_fname_dst)));
6685 status = hardlink_internals(ctx,
6692 TALLOC_FREE(smb_fname_dst);
6696 /****************************************************************************
6697 Deal with SMB_FILE_RENAME_INFORMATION.
6698 ****************************************************************************/
6700 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6701 struct smb_request *req,
6705 struct smb_filename *smb_fname_src)
6710 char *newname = NULL;
6711 struct smb_filename *smb_fname_dst = NULL;
6712 bool dest_has_wcard = False;
6713 NTSTATUS status = NT_STATUS_OK;
6715 TALLOC_CTX *ctx = talloc_tos();
6717 if (total_data < 13) {
6718 return NT_STATUS_INVALID_PARAMETER;
6721 overwrite = (CVAL(pdata,0) ? True : False);
6722 root_fid = IVAL(pdata,4);
6723 len = IVAL(pdata,8);
6725 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6726 return NT_STATUS_INVALID_PARAMETER;
6729 if (req->posix_pathnames) {
6730 srvstr_get_path_wcard_posix(ctx,
6740 srvstr_get_path_wcard(ctx,
6750 if (!NT_STATUS_IS_OK(status)) {
6754 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6757 status = resolve_dfspath_wcard(ctx, conn,
6758 req->flags2 & FLAGS2_DFS_PATHNAMES,
6761 !conn->sconn->using_smb2,
6764 if (!NT_STATUS_IS_OK(status)) {
6768 /* Check the new name has no '/' characters. */
6769 if (strchr_m(newname, '/')) {
6770 return NT_STATUS_NOT_SUPPORTED;
6773 if (fsp && fsp->base_fsp) {
6774 /* newname must be a stream name. */
6775 if (newname[0] != ':') {
6776 return NT_STATUS_NOT_SUPPORTED;
6779 /* Create an smb_fname to call rename_internals_fsp() with. */
6780 smb_fname_dst = synthetic_smb_fname(
6781 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6783 if (smb_fname_dst == NULL) {
6784 status = NT_STATUS_NO_MEMORY;
6789 * Set the original last component, since
6790 * rename_internals_fsp() requires it.
6792 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6794 if (smb_fname_dst->original_lcomp == NULL) {
6795 status = NT_STATUS_NO_MEMORY;
6801 * Build up an smb_fname_dst based on the filename passed in.
6802 * We basically just strip off the last component, and put on
6803 * the newname instead.
6805 char *base_name = NULL;
6807 /* newname must *not* be a stream name. */
6808 if (newname[0] == ':') {
6809 return NT_STATUS_NOT_SUPPORTED;
6813 * Strip off the last component (filename) of the path passed
6816 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6818 return NT_STATUS_NO_MEMORY;
6820 p = strrchr_m(base_name, '/');
6824 base_name = talloc_strdup(ctx, "");
6826 return NT_STATUS_NO_MEMORY;
6829 /* Append the new name. */
6830 base_name = talloc_asprintf_append(base_name,
6834 return NT_STATUS_NO_MEMORY;
6837 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6840 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6843 /* If an error we expect this to be
6844 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6846 if (!NT_STATUS_IS_OK(status)) {
6847 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6851 /* Create an smb_fname to call rename_internals_fsp() */
6852 smb_fname_dst = synthetic_smb_fname(
6853 ctx, base_name, NULL, NULL);
6854 if (smb_fname_dst == NULL) {
6855 status = NT_STATUS_NO_MEMORY;
6862 DEBUG(10,("smb_file_rename_information: "
6863 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6864 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6865 smb_fname_str_dbg(smb_fname_dst)));
6866 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6869 DEBUG(10,("smb_file_rename_information: "
6870 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6871 smb_fname_str_dbg(smb_fname_src),
6872 smb_fname_str_dbg(smb_fname_dst)));
6873 status = rename_internals(ctx, conn, req, smb_fname_src,
6874 smb_fname_dst, 0, overwrite, false,
6876 FILE_WRITE_ATTRIBUTES);
6879 TALLOC_FREE(smb_fname_dst);
6883 /****************************************************************************
6884 Deal with SMB_SET_POSIX_ACL.
6885 ****************************************************************************/
6887 #if defined(HAVE_POSIX_ACLS)
6888 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6892 const struct smb_filename *smb_fname)
6894 uint16_t posix_acl_version;
6895 uint16_t num_file_acls;
6896 uint16_t num_def_acls;
6897 bool valid_file_acls = True;
6898 bool valid_def_acls = True;
6900 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6901 return NT_STATUS_INVALID_PARAMETER;
6903 posix_acl_version = SVAL(pdata,0);
6904 num_file_acls = SVAL(pdata,2);
6905 num_def_acls = SVAL(pdata,4);
6907 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6908 valid_file_acls = False;
6912 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6913 valid_def_acls = False;
6917 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6918 return NT_STATUS_INVALID_PARAMETER;
6921 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6922 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6923 return NT_STATUS_INVALID_PARAMETER;
6926 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6927 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6928 (unsigned int)num_file_acls,
6929 (unsigned int)num_def_acls));
6931 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6932 smb_fname->base_name, num_file_acls,
6933 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6934 return map_nt_error_from_unix(errno);
6937 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6938 smb_fname->base_name, &smb_fname->st, num_def_acls,
6939 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6940 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6941 return map_nt_error_from_unix(errno);
6943 return NT_STATUS_OK;
6947 /****************************************************************************
6948 Deal with SMB_SET_POSIX_LOCK.
6949 ****************************************************************************/
6951 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6952 struct smb_request *req,
6960 bool blocking_lock = False;
6961 enum brl_type lock_type;
6963 NTSTATUS status = NT_STATUS_OK;
6965 if (fsp == NULL || fsp->fh->fd == -1) {
6966 return NT_STATUS_INVALID_HANDLE;
6969 if (total_data != POSIX_LOCK_DATA_SIZE) {
6970 return NT_STATUS_INVALID_PARAMETER;
6973 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6974 case POSIX_LOCK_TYPE_READ:
6975 lock_type = READ_LOCK;
6977 case POSIX_LOCK_TYPE_WRITE:
6978 /* Return the right POSIX-mappable error code for files opened read-only. */
6979 if (!fsp->can_write) {
6980 return NT_STATUS_INVALID_HANDLE;
6982 lock_type = WRITE_LOCK;
6984 case POSIX_LOCK_TYPE_UNLOCK:
6985 lock_type = UNLOCK_LOCK;
6988 return NT_STATUS_INVALID_PARAMETER;
6991 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6992 blocking_lock = False;
6993 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6994 blocking_lock = True;
6996 return NT_STATUS_INVALID_PARAMETER;
6999 if (!lp_blocking_locks(SNUM(conn))) {
7000 blocking_lock = False;
7003 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7004 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7005 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7006 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7007 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7009 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7010 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7012 (unsigned int)lock_type,
7013 (unsigned long long)smblctx,
7017 if (lock_type == UNLOCK_LOCK) {
7018 status = do_unlock(req->sconn->msg_ctx,
7025 uint64_t block_smblctx;
7027 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7038 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7040 * A blocking lock was requested. Package up
7041 * this smb into a queued request and push it
7042 * onto the blocking lock queue.
7044 if(push_blocking_lock_request(br_lck,
7047 -1, /* infinite timeout. */
7055 TALLOC_FREE(br_lck);
7059 TALLOC_FREE(br_lck);
7065 /****************************************************************************
7066 Deal with SMB_SET_FILE_BASIC_INFO.
7067 ****************************************************************************/
7069 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7073 const struct smb_filename *smb_fname)
7075 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7076 struct smb_file_time ft;
7077 uint32_t dosmode = 0;
7078 NTSTATUS status = NT_STATUS_OK;
7082 if (total_data < 36) {
7083 return NT_STATUS_INVALID_PARAMETER;
7086 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7087 if (!NT_STATUS_IS_OK(status)) {
7091 /* Set the attributes */
7092 dosmode = IVAL(pdata,32);
7093 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7094 if (!NT_STATUS_IS_OK(status)) {
7099 ft.create_time = interpret_long_date(pdata);
7102 ft.atime = interpret_long_date(pdata+8);
7105 ft.mtime = interpret_long_date(pdata+16);
7108 ft.ctime = interpret_long_date(pdata+24);
7110 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7111 smb_fname_str_dbg(smb_fname)));
7113 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7117 /****************************************************************************
7118 Deal with SMB_INFO_STANDARD.
7119 ****************************************************************************/
7121 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7125 const struct smb_filename *smb_fname)
7128 struct smb_file_time ft;
7132 if (total_data < 12) {
7133 return NT_STATUS_INVALID_PARAMETER;
7137 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7139 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7141 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7143 DEBUG(10,("smb_set_info_standard: file %s\n",
7144 smb_fname_str_dbg(smb_fname)));
7146 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7147 if (!NT_STATUS_IS_OK(status)) {
7151 return smb_set_file_time(conn,
7158 /****************************************************************************
7159 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7160 ****************************************************************************/
7162 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7163 struct smb_request *req,
7167 struct smb_filename *smb_fname)
7169 uint64_t allocation_size = 0;
7170 NTSTATUS status = NT_STATUS_OK;
7171 files_struct *new_fsp = NULL;
7173 if (!VALID_STAT(smb_fname->st)) {
7174 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7177 if (total_data < 8) {
7178 return NT_STATUS_INVALID_PARAMETER;
7181 allocation_size = (uint64_t)IVAL(pdata,0);
7182 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7183 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7184 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7185 (double)allocation_size));
7187 if (allocation_size) {
7188 allocation_size = smb_roundup(conn, allocation_size);
7191 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7192 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7193 (double)allocation_size));
7195 if (fsp && fsp->fh->fd != -1) {
7196 /* Open file handle. */
7197 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7198 return NT_STATUS_ACCESS_DENIED;
7201 /* Only change if needed. */
7202 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7203 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7204 return map_nt_error_from_unix(errno);
7207 /* But always update the time. */
7209 * This is equivalent to a write. Ensure it's seen immediately
7210 * if there are no pending writes.
7212 trigger_write_time_update_immediate(fsp);
7213 return NT_STATUS_OK;
7216 /* Pathname or stat or directory file. */
7217 status = SMB_VFS_CREATE_FILE(
7220 0, /* root_dir_fid */
7221 smb_fname, /* fname */
7222 FILE_WRITE_DATA, /* access_mask */
7223 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7225 FILE_OPEN, /* create_disposition*/
7226 0, /* create_options */
7227 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7228 0, /* oplock_request */
7230 0, /* allocation_size */
7231 0, /* private_flags */
7234 &new_fsp, /* result */
7236 NULL, NULL); /* create context */
7238 if (!NT_STATUS_IS_OK(status)) {
7239 /* NB. We check for open_was_deferred in the caller. */
7243 /* Only change if needed. */
7244 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7245 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7246 status = map_nt_error_from_unix(errno);
7247 close_file(req, new_fsp, NORMAL_CLOSE);
7252 /* Changing the allocation size should set the last mod time. */
7254 * This is equivalent to a write. Ensure it's seen immediately
7255 * if there are no pending writes.
7257 trigger_write_time_update_immediate(new_fsp);
7258 close_file(req, new_fsp, NORMAL_CLOSE);
7259 return NT_STATUS_OK;
7262 /****************************************************************************
7263 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7264 ****************************************************************************/
7266 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7267 struct smb_request *req,
7271 const struct smb_filename *smb_fname,
7272 bool fail_after_createfile)
7276 if (total_data < 8) {
7277 return NT_STATUS_INVALID_PARAMETER;
7280 size = IVAL(pdata,0);
7281 size |= (((off_t)IVAL(pdata,4)) << 32);
7282 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7283 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7286 return smb_set_file_size(conn, req,
7291 fail_after_createfile);
7294 /****************************************************************************
7295 Allow a UNIX info mknod.
7296 ****************************************************************************/
7298 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7301 const struct smb_filename *smb_fname)
7303 uint32_t file_type = IVAL(pdata,56);
7304 #if defined(HAVE_MAKEDEV)
7305 uint32_t dev_major = IVAL(pdata,60);
7306 uint32_t dev_minor = IVAL(pdata,68);
7308 SMB_DEV_T dev = (SMB_DEV_T)0;
7309 uint32_t raw_unixmode = IVAL(pdata,84);
7313 if (total_data < 100) {
7314 return NT_STATUS_INVALID_PARAMETER;
7317 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7318 PERM_NEW_FILE, &unixmode);
7319 if (!NT_STATUS_IS_OK(status)) {
7323 #if defined(HAVE_MAKEDEV)
7324 dev = makedev(dev_major, dev_minor);
7327 switch (file_type) {
7328 #if defined(S_IFIFO)
7329 case UNIX_TYPE_FIFO:
7330 unixmode |= S_IFIFO;
7333 #if defined(S_IFSOCK)
7334 case UNIX_TYPE_SOCKET:
7335 unixmode |= S_IFSOCK;
7338 #if defined(S_IFCHR)
7339 case UNIX_TYPE_CHARDEV:
7340 unixmode |= S_IFCHR;
7343 #if defined(S_IFBLK)
7344 case UNIX_TYPE_BLKDEV:
7345 unixmode |= S_IFBLK;
7349 return NT_STATUS_INVALID_PARAMETER;
7352 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7353 "%.0f mode 0%o for file %s\n", (double)dev,
7354 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7356 /* Ok - do the mknod. */
7357 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7358 return map_nt_error_from_unix(errno);
7361 /* If any of the other "set" calls fail we
7362 * don't want to end up with a half-constructed mknod.
7365 if (lp_inherit_permissions(SNUM(conn))) {
7367 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7369 return NT_STATUS_NO_MEMORY;
7371 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7373 TALLOC_FREE(parent);
7376 return NT_STATUS_OK;
7379 /****************************************************************************
7380 Deal with SMB_SET_FILE_UNIX_BASIC.
7381 ****************************************************************************/
7383 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7384 struct smb_request *req,
7388 const struct smb_filename *smb_fname)
7390 struct smb_file_time ft;
7391 uint32_t raw_unixmode;
7394 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7395 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7396 NTSTATUS status = NT_STATUS_OK;
7397 bool delete_on_fail = False;
7398 enum perm_type ptype;
7399 files_struct *all_fsps = NULL;
7400 bool modify_mtime = true;
7402 struct smb_filename *smb_fname_tmp = NULL;
7403 SMB_STRUCT_STAT sbuf;
7407 if (total_data < 100) {
7408 return NT_STATUS_INVALID_PARAMETER;
7411 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7412 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7413 size=IVAL(pdata,0); /* first 8 Bytes are size */
7414 size |= (((off_t)IVAL(pdata,4)) << 32);
7417 ft.atime = interpret_long_date(pdata+24); /* access_time */
7418 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7419 set_owner = (uid_t)IVAL(pdata,40);
7420 set_grp = (gid_t)IVAL(pdata,48);
7421 raw_unixmode = IVAL(pdata,84);
7423 if (VALID_STAT(smb_fname->st)) {
7424 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7425 ptype = PERM_EXISTING_DIR;
7427 ptype = PERM_EXISTING_FILE;
7430 ptype = PERM_NEW_FILE;
7433 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7435 if (!NT_STATUS_IS_OK(status)) {
7439 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7440 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7441 smb_fname_str_dbg(smb_fname), (double)size,
7442 (unsigned int)set_owner, (unsigned int)set_grp,
7443 (int)raw_unixmode));
7445 sbuf = smb_fname->st;
7447 if (!VALID_STAT(sbuf)) {
7449 * The only valid use of this is to create character and block
7450 * devices, and named pipes. This is deprecated (IMHO) and
7451 * a new info level should be used for mknod. JRA.
7454 status = smb_unix_mknod(conn,
7458 if (!NT_STATUS_IS_OK(status)) {
7462 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7463 if (smb_fname_tmp == NULL) {
7464 return NT_STATUS_NO_MEMORY;
7467 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7468 status = map_nt_error_from_unix(errno);
7469 TALLOC_FREE(smb_fname_tmp);
7470 SMB_VFS_UNLINK(conn, smb_fname);
7474 sbuf = smb_fname_tmp->st;
7475 smb_fname = smb_fname_tmp;
7477 /* Ensure we don't try and change anything else. */
7478 raw_unixmode = SMB_MODE_NO_CHANGE;
7479 size = get_file_size_stat(&sbuf);
7480 ft.atime = sbuf.st_ex_atime;
7481 ft.mtime = sbuf.st_ex_mtime;
7483 * We continue here as we might want to change the
7486 delete_on_fail = True;
7490 /* Horrible backwards compatibility hack as an old server bug
7491 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7495 size = get_file_size_stat(&sbuf);
7500 * Deal with the UNIX specific mode set.
7503 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7506 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7507 "setting mode 0%o for file %s\n",
7508 (unsigned int)unixmode,
7509 smb_fname_str_dbg(smb_fname)));
7510 if (fsp && fsp->fh->fd != -1) {
7511 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7513 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7516 return map_nt_error_from_unix(errno);
7521 * Deal with the UNIX specific uid set.
7524 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7525 (sbuf.st_ex_uid != set_owner)) {
7528 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7529 "changing owner %u for path %s\n",
7530 (unsigned int)set_owner,
7531 smb_fname_str_dbg(smb_fname)));
7533 if (fsp && fsp->fh->fd != -1) {
7534 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7537 * UNIX extensions calls must always operate
7540 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7541 set_owner, (gid_t)-1);
7545 status = map_nt_error_from_unix(errno);
7546 if (delete_on_fail) {
7547 SMB_VFS_UNLINK(conn, smb_fname);
7554 * Deal with the UNIX specific gid set.
7557 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7558 (sbuf.st_ex_gid != set_grp)) {
7561 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7562 "changing group %u for file %s\n",
7563 (unsigned int)set_owner,
7564 smb_fname_str_dbg(smb_fname)));
7565 if (fsp && fsp->fh->fd != -1) {
7566 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7569 * UNIX extensions calls must always operate
7572 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7576 status = map_nt_error_from_unix(errno);
7577 if (delete_on_fail) {
7578 SMB_VFS_UNLINK(conn, smb_fname);
7584 /* Deal with any size changes. */
7586 status = smb_set_file_size(conn, req,
7592 if (!NT_STATUS_IS_OK(status)) {
7596 /* Deal with any time changes. */
7597 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7598 /* No change, don't cancel anything. */
7602 id = vfs_file_id_from_sbuf(conn, &sbuf);
7603 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7604 all_fsps = file_find_di_next(all_fsps)) {
7606 * We're setting the time explicitly for UNIX.
7607 * Cancel any pending changes over all handles.
7609 all_fsps->update_write_time_on_close = false;
7610 TALLOC_FREE(all_fsps->update_write_time_event);
7614 * Override the "setting_write_time"
7615 * parameter here as it almost does what
7616 * we need. Just remember if we modified
7617 * mtime and send the notify ourselves.
7619 if (null_timespec(ft.mtime)) {
7620 modify_mtime = false;
7623 status = smb_set_file_time(conn,
7629 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7630 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7635 /****************************************************************************
7636 Deal with SMB_SET_FILE_UNIX_INFO2.
7637 ****************************************************************************/
7639 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7640 struct smb_request *req,
7644 const struct smb_filename *smb_fname)
7647 uint32_t smb_fflags;
7650 if (total_data < 116) {
7651 return NT_STATUS_INVALID_PARAMETER;
7654 /* Start by setting all the fields that are common between UNIX_BASIC
7657 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7659 if (!NT_STATUS_IS_OK(status)) {
7663 smb_fflags = IVAL(pdata, 108);
7664 smb_fmask = IVAL(pdata, 112);
7666 /* NB: We should only attempt to alter the file flags if the client
7667 * sends a non-zero mask.
7669 if (smb_fmask != 0) {
7670 int stat_fflags = 0;
7672 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7673 smb_fmask, &stat_fflags)) {
7674 /* Client asked to alter a flag we don't understand. */
7675 return NT_STATUS_INVALID_PARAMETER;
7678 if (fsp && fsp->fh->fd != -1) {
7679 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7680 return NT_STATUS_NOT_SUPPORTED;
7682 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7683 stat_fflags) != 0) {
7684 return map_nt_error_from_unix(errno);
7689 /* XXX: need to add support for changing the create_time here. You
7690 * can do this for paths on Darwin with setattrlist(2). The right way
7691 * to hook this up is probably by extending the VFS utimes interface.
7694 return NT_STATUS_OK;
7697 /****************************************************************************
7698 Create a directory with POSIX semantics.
7699 ****************************************************************************/
7701 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7702 struct smb_request *req,
7705 struct smb_filename *smb_fname,
7706 int *pdata_return_size)
7708 NTSTATUS status = NT_STATUS_OK;
7709 uint32_t raw_unixmode = 0;
7710 uint32_t mod_unixmode = 0;
7711 mode_t unixmode = (mode_t)0;
7712 files_struct *fsp = NULL;
7713 uint16_t info_level_return = 0;
7715 char *pdata = *ppdata;
7717 if (total_data < 18) {
7718 return NT_STATUS_INVALID_PARAMETER;
7721 raw_unixmode = IVAL(pdata,8);
7722 /* Next 4 bytes are not yet defined. */
7724 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7725 PERM_NEW_DIR, &unixmode);
7726 if (!NT_STATUS_IS_OK(status)) {
7730 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7732 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7733 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7735 status = SMB_VFS_CREATE_FILE(
7738 0, /* root_dir_fid */
7739 smb_fname, /* fname */
7740 FILE_READ_ATTRIBUTES, /* access_mask */
7741 FILE_SHARE_NONE, /* share_access */
7742 FILE_CREATE, /* create_disposition*/
7743 FILE_DIRECTORY_FILE, /* create_options */
7744 mod_unixmode, /* file_attributes */
7745 0, /* oplock_request */
7747 0, /* allocation_size */
7748 0, /* private_flags */
7753 NULL, NULL); /* create context */
7755 if (NT_STATUS_IS_OK(status)) {
7756 close_file(req, fsp, NORMAL_CLOSE);
7759 info_level_return = SVAL(pdata,16);
7761 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7762 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7763 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7764 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7766 *pdata_return_size = 12;
7769 /* Realloc the data size */
7770 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7771 if (*ppdata == NULL) {
7772 *pdata_return_size = 0;
7773 return NT_STATUS_NO_MEMORY;
7777 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7778 SSVAL(pdata,2,0); /* No fnum. */
7779 SIVAL(pdata,4,info); /* Was directory created. */
7781 switch (info_level_return) {
7782 case SMB_QUERY_FILE_UNIX_BASIC:
7783 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7784 SSVAL(pdata,10,0); /* Padding. */
7785 store_file_unix_basic(conn, pdata + 12, fsp,
7788 case SMB_QUERY_FILE_UNIX_INFO2:
7789 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7790 SSVAL(pdata,10,0); /* Padding. */
7791 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7795 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7796 SSVAL(pdata,10,0); /* Padding. */
7803 /****************************************************************************
7804 Open/Create a file with POSIX semantics.
7805 ****************************************************************************/
7807 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7808 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7810 static NTSTATUS smb_posix_open(connection_struct *conn,
7811 struct smb_request *req,
7814 struct smb_filename *smb_fname,
7815 int *pdata_return_size)
7817 bool extended_oplock_granted = False;
7818 char *pdata = *ppdata;
7820 uint32_t wire_open_mode = 0;
7821 uint32_t raw_unixmode = 0;
7822 uint32_t mod_unixmode = 0;
7823 uint32_t create_disp = 0;
7824 uint32_t access_mask = 0;
7825 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7826 NTSTATUS status = NT_STATUS_OK;
7827 mode_t unixmode = (mode_t)0;
7828 files_struct *fsp = NULL;
7829 int oplock_request = 0;
7831 uint16_t info_level_return = 0;
7833 if (total_data < 18) {
7834 return NT_STATUS_INVALID_PARAMETER;
7837 flags = IVAL(pdata,0);
7838 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7839 if (oplock_request) {
7840 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7843 wire_open_mode = IVAL(pdata,4);
7845 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7846 return smb_posix_mkdir(conn, req,
7853 switch (wire_open_mode & SMB_ACCMODE) {
7855 access_mask = SMB_O_RDONLY_MAPPING;
7858 access_mask = SMB_O_WRONLY_MAPPING;
7861 access_mask = (SMB_O_RDONLY_MAPPING|
7862 SMB_O_WRONLY_MAPPING);
7865 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7866 (unsigned int)wire_open_mode ));
7867 return NT_STATUS_INVALID_PARAMETER;
7870 wire_open_mode &= ~SMB_ACCMODE;
7872 /* First take care of O_CREAT|O_EXCL interactions. */
7873 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7874 case (SMB_O_CREAT | SMB_O_EXCL):
7875 /* File exists fail. File not exist create. */
7876 create_disp = FILE_CREATE;
7879 /* File exists open. File not exist create. */
7880 create_disp = FILE_OPEN_IF;
7883 /* O_EXCL on its own without O_CREAT is undefined.
7884 We deliberately ignore it as some versions of
7885 Linux CIFSFS can send a bare O_EXCL on the
7886 wire which other filesystems in the kernel
7887 ignore. See bug 9519 for details. */
7892 /* File exists open. File not exist fail. */
7893 create_disp = FILE_OPEN;
7896 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7897 (unsigned int)wire_open_mode ));
7898 return NT_STATUS_INVALID_PARAMETER;
7901 /* Next factor in the effects of O_TRUNC. */
7902 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7904 if (wire_open_mode & SMB_O_TRUNC) {
7905 switch (create_disp) {
7907 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7908 /* Leave create_disp alone as
7909 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7911 /* File exists fail. File not exist create. */
7914 /* SMB_O_CREAT | SMB_O_TRUNC */
7915 /* File exists overwrite. File not exist create. */
7916 create_disp = FILE_OVERWRITE_IF;
7920 /* File exists overwrite. File not exist fail. */
7921 create_disp = FILE_OVERWRITE;
7924 /* Cannot get here. */
7925 smb_panic("smb_posix_open: logic error");
7926 return NT_STATUS_INVALID_PARAMETER;
7930 raw_unixmode = IVAL(pdata,8);
7931 /* Next 4 bytes are not yet defined. */
7933 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7934 (VALID_STAT(smb_fname->st) ?
7935 PERM_EXISTING_FILE : PERM_NEW_FILE),
7938 if (!NT_STATUS_IS_OK(status)) {
7942 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7944 if (wire_open_mode & SMB_O_SYNC) {
7945 create_options |= FILE_WRITE_THROUGH;
7947 if (wire_open_mode & SMB_O_APPEND) {
7948 access_mask |= FILE_APPEND_DATA;
7950 if (wire_open_mode & SMB_O_DIRECT) {
7951 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7954 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7955 VALID_STAT_OF_DIR(smb_fname->st)) {
7956 if (access_mask != SMB_O_RDONLY_MAPPING) {
7957 return NT_STATUS_FILE_IS_A_DIRECTORY;
7959 create_options &= ~FILE_NON_DIRECTORY_FILE;
7960 create_options |= FILE_DIRECTORY_FILE;
7963 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7964 smb_fname_str_dbg(smb_fname),
7965 (unsigned int)wire_open_mode,
7966 (unsigned int)unixmode ));
7968 status = SMB_VFS_CREATE_FILE(
7971 0, /* root_dir_fid */
7972 smb_fname, /* fname */
7973 access_mask, /* access_mask */
7974 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7976 create_disp, /* create_disposition*/
7977 create_options, /* create_options */
7978 mod_unixmode, /* file_attributes */
7979 oplock_request, /* oplock_request */
7981 0, /* allocation_size */
7982 0, /* private_flags */
7987 NULL, NULL); /* create context */
7989 if (!NT_STATUS_IS_OK(status)) {
7993 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7994 extended_oplock_granted = True;
7997 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7998 extended_oplock_granted = True;
8001 info_level_return = SVAL(pdata,16);
8003 /* Allocate the correct return size. */
8005 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8006 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8007 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8008 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8010 *pdata_return_size = 12;
8013 /* Realloc the data size */
8014 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8015 if (*ppdata == NULL) {
8016 close_file(req, fsp, ERROR_CLOSE);
8017 *pdata_return_size = 0;
8018 return NT_STATUS_NO_MEMORY;
8022 if (extended_oplock_granted) {
8023 if (flags & REQUEST_BATCH_OPLOCK) {
8024 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8026 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8028 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8029 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8031 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8034 SSVAL(pdata,2,fsp->fnum);
8035 SIVAL(pdata,4,info); /* Was file created etc. */
8037 switch (info_level_return) {
8038 case SMB_QUERY_FILE_UNIX_BASIC:
8039 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8040 SSVAL(pdata,10,0); /* padding. */
8041 store_file_unix_basic(conn, pdata + 12, fsp,
8044 case SMB_QUERY_FILE_UNIX_INFO2:
8045 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8046 SSVAL(pdata,10,0); /* padding. */
8047 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8051 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8052 SSVAL(pdata,10,0); /* padding. */
8055 return NT_STATUS_OK;
8058 /****************************************************************************
8059 Delete a file with POSIX semantics.
8060 ****************************************************************************/
8062 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8063 struct smb_request *req,
8066 struct smb_filename *smb_fname)
8068 NTSTATUS status = NT_STATUS_OK;
8069 files_struct *fsp = NULL;
8073 int create_options = 0;
8075 struct share_mode_lock *lck = NULL;
8077 if (total_data < 2) {
8078 return NT_STATUS_INVALID_PARAMETER;
8081 flags = SVAL(pdata,0);
8083 if (!VALID_STAT(smb_fname->st)) {
8084 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8087 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8088 !VALID_STAT_OF_DIR(smb_fname->st)) {
8089 return NT_STATUS_NOT_A_DIRECTORY;
8092 DEBUG(10,("smb_posix_unlink: %s %s\n",
8093 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8094 smb_fname_str_dbg(smb_fname)));
8096 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8097 create_options |= FILE_DIRECTORY_FILE;
8100 status = SMB_VFS_CREATE_FILE(
8103 0, /* root_dir_fid */
8104 smb_fname, /* fname */
8105 DELETE_ACCESS, /* access_mask */
8106 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8108 FILE_OPEN, /* create_disposition*/
8109 create_options, /* create_options */
8110 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8111 0, /* oplock_request */
8113 0, /* allocation_size */
8114 0, /* private_flags */
8119 NULL, NULL); /* create context */
8121 if (!NT_STATUS_IS_OK(status)) {
8126 * Don't lie to client. If we can't really delete due to
8127 * non-POSIX opens return SHARING_VIOLATION.
8130 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8132 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8133 "lock for file %s\n", fsp_str_dbg(fsp)));
8134 close_file(req, fsp, NORMAL_CLOSE);
8135 return NT_STATUS_INVALID_PARAMETER;
8139 * See if others still have the file open. If this is the case, then
8140 * don't delete. If all opens are POSIX delete we can set the delete
8141 * on close disposition.
8143 for (i=0; i<lck->data->num_share_modes; i++) {
8144 struct share_mode_entry *e = &lck->data->share_modes[i];
8145 if (is_valid_share_mode_entry(e)) {
8146 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8149 if (share_mode_stale_pid(lck->data, i)) {
8152 /* Fail with sharing violation. */
8154 close_file(req, fsp, NORMAL_CLOSE);
8155 return NT_STATUS_SHARING_VIOLATION;
8160 * Set the delete on close.
8162 status = smb_set_file_disposition_info(conn,
8170 if (!NT_STATUS_IS_OK(status)) {
8171 close_file(req, fsp, NORMAL_CLOSE);
8174 return close_file(req, fsp, NORMAL_CLOSE);
8177 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8178 struct smb_request *req,
8179 TALLOC_CTX *mem_ctx,
8180 uint16_t info_level,
8182 struct smb_filename *smb_fname,
8183 char **ppdata, int total_data,
8186 char *pdata = *ppdata;
8187 NTSTATUS status = NT_STATUS_OK;
8188 int data_return_size = 0;
8192 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8193 return NT_STATUS_INVALID_LEVEL;
8196 if (!CAN_WRITE(conn)) {
8197 /* Allow POSIX opens. The open path will deny
8198 * any non-readonly opens. */
8199 if (info_level != SMB_POSIX_PATH_OPEN) {
8200 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8204 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8205 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8207 info_level, total_data));
8209 switch (info_level) {
8211 case SMB_INFO_STANDARD:
8213 status = smb_set_info_standard(conn,
8221 case SMB_INFO_SET_EA:
8223 status = smb_info_set_ea(conn,
8231 case SMB_SET_FILE_BASIC_INFO:
8232 case SMB_FILE_BASIC_INFORMATION:
8234 status = smb_set_file_basic_info(conn,
8242 case SMB_FILE_ALLOCATION_INFORMATION:
8243 case SMB_SET_FILE_ALLOCATION_INFO:
8245 status = smb_set_file_allocation_info(conn, req,
8253 case SMB_FILE_END_OF_FILE_INFORMATION:
8254 case SMB_SET_FILE_END_OF_FILE_INFO:
8257 * XP/Win7 both fail after the createfile with
8258 * SMB_SET_FILE_END_OF_FILE_INFO but not
8259 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8260 * The level is known here, so pass it down
8264 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8266 status = smb_set_file_end_of_file_info(conn, req,
8275 case SMB_FILE_DISPOSITION_INFORMATION:
8276 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8279 /* JRA - We used to just ignore this on a path ?
8280 * Shouldn't this be invalid level on a pathname
8283 if (tran_call != TRANSACT2_SETFILEINFO) {
8284 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8287 status = smb_set_file_disposition_info(conn,
8295 case SMB_FILE_POSITION_INFORMATION:
8297 status = smb_file_position_information(conn,
8304 case SMB_FILE_FULL_EA_INFORMATION:
8306 status = smb_set_file_full_ea_info(conn,
8313 /* From tridge Samba4 :
8314 * MODE_INFORMATION in setfileinfo (I have no
8315 * idea what "mode information" on a file is - it takes a value of 0,
8316 * 2, 4 or 6. What could it be?).
8319 case SMB_FILE_MODE_INFORMATION:
8321 status = smb_file_mode_information(conn,
8328 * CIFS UNIX extensions.
8331 case SMB_SET_FILE_UNIX_BASIC:
8333 status = smb_set_file_unix_basic(conn, req,
8341 case SMB_SET_FILE_UNIX_INFO2:
8343 status = smb_set_file_unix_info2(conn, req,
8351 case SMB_SET_FILE_UNIX_LINK:
8354 /* We must have a pathname for this. */
8355 return NT_STATUS_INVALID_LEVEL;
8357 status = smb_set_file_unix_link(conn, req, pdata,
8358 total_data, smb_fname);
8362 case SMB_SET_FILE_UNIX_HLINK:
8365 /* We must have a pathname for this. */
8366 return NT_STATUS_INVALID_LEVEL;
8368 status = smb_set_file_unix_hlink(conn, req,
8374 case SMB_FILE_RENAME_INFORMATION:
8376 status = smb_file_rename_information(conn, req,
8382 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8384 /* SMB2 rename information. */
8385 status = smb2_file_rename_information(conn, req,
8391 case SMB_FILE_LINK_INFORMATION:
8393 status = smb_file_link_information(conn, req,
8399 #if defined(HAVE_POSIX_ACLS)
8400 case SMB_SET_POSIX_ACL:
8402 status = smb_set_posix_acl(conn,
8411 case SMB_SET_POSIX_LOCK:
8414 return NT_STATUS_INVALID_LEVEL;
8416 status = smb_set_posix_lock(conn, req,
8417 pdata, total_data, fsp);
8421 case SMB_POSIX_PATH_OPEN:
8424 /* We must have a pathname for this. */
8425 return NT_STATUS_INVALID_LEVEL;
8428 status = smb_posix_open(conn, req,
8436 case SMB_POSIX_PATH_UNLINK:
8439 /* We must have a pathname for this. */
8440 return NT_STATUS_INVALID_LEVEL;
8443 status = smb_posix_unlink(conn, req,
8451 return NT_STATUS_INVALID_LEVEL;
8454 if (!NT_STATUS_IS_OK(status)) {
8458 *ret_data_size = data_return_size;
8459 return NT_STATUS_OK;
8462 /****************************************************************************
8463 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8464 ****************************************************************************/
8466 static void call_trans2setfilepathinfo(connection_struct *conn,
8467 struct smb_request *req,
8468 unsigned int tran_call,
8469 char **pparams, int total_params,
8470 char **ppdata, int total_data,
8471 unsigned int max_data_bytes)
8473 char *params = *pparams;
8474 char *pdata = *ppdata;
8475 uint16_t info_level;
8476 struct smb_filename *smb_fname = NULL;
8477 files_struct *fsp = NULL;
8478 NTSTATUS status = NT_STATUS_OK;
8479 int data_return_size = 0;
8482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8486 if (tran_call == TRANSACT2_SETFILEINFO) {
8487 if (total_params < 4) {
8488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8492 fsp = file_fsp(req, SVAL(params,0));
8493 /* Basic check for non-null fsp. */
8494 if (!check_fsp_open(conn, req, fsp)) {
8497 info_level = SVAL(params,2);
8499 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8500 if (smb_fname == NULL) {
8501 reply_nterror(req, NT_STATUS_NO_MEMORY);
8505 if(fsp->fh->fd == -1) {
8507 * This is actually a SETFILEINFO on a directory
8508 * handle (returned from an NT SMB). NT5.0 seems
8509 * to do this call. JRA.
8511 if (INFO_LEVEL_IS_UNIX(info_level)) {
8512 /* Always do lstat for UNIX calls. */
8513 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8514 DEBUG(3,("call_trans2setfilepathinfo: "
8515 "SMB_VFS_LSTAT of %s failed "
8517 smb_fname_str_dbg(smb_fname),
8519 reply_nterror(req, map_nt_error_from_unix(errno));
8523 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8524 DEBUG(3,("call_trans2setfilepathinfo: "
8525 "fileinfo of %s failed (%s)\n",
8526 smb_fname_str_dbg(smb_fname),
8528 reply_nterror(req, map_nt_error_from_unix(errno));
8532 } else if (fsp->print_file) {
8534 * Doing a DELETE_ON_CLOSE should cancel a print job.
8536 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8537 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8539 DEBUG(3,("call_trans2setfilepathinfo: "
8540 "Cancelling print job (%s)\n",
8544 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8550 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8555 * Original code - this is an open file.
8557 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8558 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8559 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8561 reply_nterror(req, map_nt_error_from_unix(errno));
8567 uint32_t ucf_flags = (req->posix_pathnames ?
8568 UCF_POSIX_PATHNAMES : 0);
8571 if (total_params < 7) {
8572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8576 info_level = SVAL(params,0);
8577 if (req->posix_pathnames) {
8578 srvstr_get_path_posix(req,
8587 srvstr_get_path(req,
8596 if (!NT_STATUS_IS_OK(status)) {
8597 reply_nterror(req, status);
8601 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8602 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8603 info_level == SMB_FILE_RENAME_INFORMATION ||
8604 info_level == SMB_POSIX_PATH_UNLINK) {
8605 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8608 status = filename_convert(req, conn,
8609 req->flags2 & FLAGS2_DFS_PATHNAMES,
8614 if (!NT_STATUS_IS_OK(status)) {
8615 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8616 reply_botherror(req,
8617 NT_STATUS_PATH_NOT_COVERED,
8618 ERRSRV, ERRbadpath);
8621 reply_nterror(req, status);
8625 if (INFO_LEVEL_IS_UNIX(info_level)) {
8627 * For CIFS UNIX extensions the target name may not exist.
8630 /* Always do lstat for UNIX calls. */
8631 SMB_VFS_LSTAT(conn, smb_fname);
8633 } else if (!VALID_STAT(smb_fname->st) &&
8634 SMB_VFS_STAT(conn, smb_fname)) {
8635 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8637 smb_fname_str_dbg(smb_fname),
8639 reply_nterror(req, map_nt_error_from_unix(errno));
8644 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8645 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8647 info_level,total_data));
8649 /* Realloc the parameter size */
8650 *pparams = (char *)SMB_REALLOC(*pparams,2);
8651 if (*pparams == NULL) {
8652 reply_nterror(req, NT_STATUS_NO_MEMORY);
8659 status = smbd_do_setfilepathinfo(conn, req, req,
8665 if (!NT_STATUS_IS_OK(status)) {
8666 if (open_was_deferred(req->xconn, req->mid)) {
8667 /* We have re-scheduled this call. */
8670 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8671 /* We have re-scheduled this call. */
8674 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8675 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8676 ERRSRV, ERRbadpath);
8679 if (info_level == SMB_POSIX_PATH_OPEN) {
8680 reply_openerror(req, status);
8685 * Invalid EA name needs to return 2 param bytes,
8686 * not a zero-length error packet.
8688 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8689 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8692 reply_nterror(req, status);
8697 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8703 /****************************************************************************
8704 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8705 ****************************************************************************/
8707 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8708 char **pparams, int total_params,
8709 char **ppdata, int total_data,
8710 unsigned int max_data_bytes)
8712 struct smb_filename *smb_dname = NULL;
8713 char *params = *pparams;
8714 char *pdata = *ppdata;
8715 char *directory = NULL;
8716 NTSTATUS status = NT_STATUS_OK;
8717 struct ea_list *ea_list = NULL;
8718 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
8719 TALLOC_CTX *ctx = talloc_tos();
8721 if (!CAN_WRITE(conn)) {
8722 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8726 if (total_params < 5) {
8727 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8731 if (req->posix_pathnames) {
8732 srvstr_get_path_posix(ctx,
8741 srvstr_get_path(ctx,
8750 if (!NT_STATUS_IS_OK(status)) {
8751 reply_nterror(req, status);
8755 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8757 status = filename_convert(ctx,
8759 req->flags2 & FLAGS2_DFS_PATHNAMES,
8765 if (!NT_STATUS_IS_OK(status)) {
8766 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8767 reply_botherror(req,
8768 NT_STATUS_PATH_NOT_COVERED,
8769 ERRSRV, ERRbadpath);
8772 reply_nterror(req, status);
8777 * OS/2 workplace shell seems to send SET_EA requests of "null"
8778 * length (4 bytes containing IVAL 4).
8779 * They seem to have no effect. Bug #3212. JRA.
8782 if (total_data && (total_data != 4)) {
8783 /* Any data in this call is an EA list. */
8784 if (total_data < 10) {
8785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8789 if (IVAL(pdata,0) > total_data) {
8790 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8791 IVAL(pdata,0), (unsigned int)total_data));
8792 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8796 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8803 if (!lp_ea_support(SNUM(conn))) {
8804 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8808 /* If total_data == 4 Windows doesn't care what values
8809 * are placed in that field, it just ignores them.
8810 * The System i QNTC IBM SMB client puts bad values here,
8811 * so ignore them. */
8813 status = create_directory(conn, req, smb_dname);
8815 if (!NT_STATUS_IS_OK(status)) {
8816 reply_nterror(req, status);
8820 /* Try and set any given EA. */
8822 status = set_ea(conn, NULL, smb_dname, ea_list);
8823 if (!NT_STATUS_IS_OK(status)) {
8824 reply_nterror(req, status);
8829 /* Realloc the parameter and data sizes */
8830 *pparams = (char *)SMB_REALLOC(*pparams,2);
8831 if(*pparams == NULL) {
8832 reply_nterror(req, NT_STATUS_NO_MEMORY);
8839 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8842 TALLOC_FREE(smb_dname);
8846 /****************************************************************************
8847 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8848 We don't actually do this - we just send a null response.
8849 ****************************************************************************/
8851 static void call_trans2findnotifyfirst(connection_struct *conn,
8852 struct smb_request *req,
8853 char **pparams, int total_params,
8854 char **ppdata, int total_data,
8855 unsigned int max_data_bytes)
8857 char *params = *pparams;
8858 uint16_t info_level;
8860 if (total_params < 6) {
8861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8865 info_level = SVAL(params,4);
8866 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8868 switch (info_level) {
8873 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8877 /* Realloc the parameter and data sizes */
8878 *pparams = (char *)SMB_REALLOC(*pparams,6);
8879 if (*pparams == NULL) {
8880 reply_nterror(req, NT_STATUS_NO_MEMORY);
8885 SSVAL(params,0,fnf_handle);
8886 SSVAL(params,2,0); /* No changes */
8887 SSVAL(params,4,0); /* No EA errors */
8894 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8899 /****************************************************************************
8900 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8901 changes). Currently this does nothing.
8902 ****************************************************************************/
8904 static void call_trans2findnotifynext(connection_struct *conn,
8905 struct smb_request *req,
8906 char **pparams, int total_params,
8907 char **ppdata, int total_data,
8908 unsigned int max_data_bytes)
8910 char *params = *pparams;
8912 DEBUG(3,("call_trans2findnotifynext\n"));
8914 /* Realloc the parameter and data sizes */
8915 *pparams = (char *)SMB_REALLOC(*pparams,4);
8916 if (*pparams == NULL) {
8917 reply_nterror(req, NT_STATUS_NO_MEMORY);
8922 SSVAL(params,0,0); /* No changes */
8923 SSVAL(params,2,0); /* No EA errors */
8925 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8930 /****************************************************************************
8931 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8932 ****************************************************************************/
8934 static void call_trans2getdfsreferral(connection_struct *conn,
8935 struct smb_request *req,
8936 char **pparams, int total_params,
8937 char **ppdata, int total_data,
8938 unsigned int max_data_bytes)
8940 char *params = *pparams;
8941 char *pathname = NULL;
8943 int max_referral_level;
8944 NTSTATUS status = NT_STATUS_OK;
8945 TALLOC_CTX *ctx = talloc_tos();
8947 DEBUG(10,("call_trans2getdfsreferral\n"));
8949 if (total_params < 3) {
8950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8954 max_referral_level = SVAL(params,0);
8956 if(!lp_host_msdfs()) {
8957 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8961 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8962 total_params - 2, STR_TERMINATE);
8964 reply_nterror(req, NT_STATUS_NOT_FOUND);
8967 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8968 ppdata,&status)) < 0) {
8969 reply_nterror(req, status);
8973 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8974 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8975 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8980 #define LMCAT_SPL 0x53
8981 #define LMFUNC_GETJOBID 0x60
8983 /****************************************************************************
8984 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8985 ****************************************************************************/
8987 static void call_trans2ioctl(connection_struct *conn,
8988 struct smb_request *req,
8989 char **pparams, int total_params,
8990 char **ppdata, int total_data,
8991 unsigned int max_data_bytes)
8993 char *pdata = *ppdata;
8994 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8998 /* check for an invalid fid before proceeding */
9001 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9005 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9006 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9007 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9008 if (*ppdata == NULL) {
9009 reply_nterror(req, NT_STATUS_NO_MEMORY);
9014 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9015 CAN ACCEPT THIS IN UNICODE. JRA. */
9018 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9020 status = srvstr_push(pdata, req->flags2, pdata + 2,
9021 lp_netbios_name(), 15,
9022 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9023 if (!NT_STATUS_IS_OK(status)) {
9024 reply_nterror(req, status);
9027 status = srvstr_push(pdata, req->flags2, pdata+18,
9028 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9029 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9030 if (!NT_STATUS_IS_OK(status)) {
9031 reply_nterror(req, status);
9034 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9039 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9040 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9043 /****************************************************************************
9044 Reply to a SMBfindclose (stop trans2 directory search).
9045 ****************************************************************************/
9047 void reply_findclose(struct smb_request *req)
9050 struct smbd_server_connection *sconn = req->sconn;
9052 START_PROFILE(SMBfindclose);
9055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9056 END_PROFILE(SMBfindclose);
9060 dptr_num = SVALS(req->vwv+0, 0);
9062 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9064 dptr_close(sconn, &dptr_num);
9066 reply_outbuf(req, 0, 0);
9068 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9070 END_PROFILE(SMBfindclose);
9074 /****************************************************************************
9075 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9076 ****************************************************************************/
9078 void reply_findnclose(struct smb_request *req)
9082 START_PROFILE(SMBfindnclose);
9085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9086 END_PROFILE(SMBfindnclose);
9090 dptr_num = SVAL(req->vwv+0, 0);
9092 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9094 /* We never give out valid handles for a
9095 findnotifyfirst - so any dptr_num is ok here.
9098 reply_outbuf(req, 0, 0);
9100 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9102 END_PROFILE(SMBfindnclose);
9106 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9107 struct trans_state *state)
9109 if (get_Protocol() >= PROTOCOL_NT1) {
9110 req->flags2 |= 0x40; /* IS_LONG_NAME */
9111 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9114 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9115 if (state->call != TRANSACT2_QFSINFO &&
9116 state->call != TRANSACT2_SETFSINFO) {
9117 DEBUG(0,("handle_trans2: encryption required "
9119 (unsigned int)state->call));
9120 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9125 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9127 /* Now we must call the relevant TRANS2 function */
9128 switch(state->call) {
9129 case TRANSACT2_OPEN:
9131 START_PROFILE(Trans2_open);
9132 call_trans2open(conn, req,
9133 &state->param, state->total_param,
9134 &state->data, state->total_data,
9135 state->max_data_return);
9136 END_PROFILE(Trans2_open);
9140 case TRANSACT2_FINDFIRST:
9142 START_PROFILE(Trans2_findfirst);
9143 call_trans2findfirst(conn, req,
9144 &state->param, state->total_param,
9145 &state->data, state->total_data,
9146 state->max_data_return);
9147 END_PROFILE(Trans2_findfirst);
9151 case TRANSACT2_FINDNEXT:
9153 START_PROFILE(Trans2_findnext);
9154 call_trans2findnext(conn, req,
9155 &state->param, state->total_param,
9156 &state->data, state->total_data,
9157 state->max_data_return);
9158 END_PROFILE(Trans2_findnext);
9162 case TRANSACT2_QFSINFO:
9164 START_PROFILE(Trans2_qfsinfo);
9165 call_trans2qfsinfo(conn, req,
9166 &state->param, state->total_param,
9167 &state->data, state->total_data,
9168 state->max_data_return);
9169 END_PROFILE(Trans2_qfsinfo);
9173 case TRANSACT2_SETFSINFO:
9175 START_PROFILE(Trans2_setfsinfo);
9176 call_trans2setfsinfo(conn, req,
9177 &state->param, state->total_param,
9178 &state->data, state->total_data,
9179 state->max_data_return);
9180 END_PROFILE(Trans2_setfsinfo);
9184 case TRANSACT2_QPATHINFO:
9185 case TRANSACT2_QFILEINFO:
9187 START_PROFILE(Trans2_qpathinfo);
9188 call_trans2qfilepathinfo(conn, req, state->call,
9189 &state->param, state->total_param,
9190 &state->data, state->total_data,
9191 state->max_data_return);
9192 END_PROFILE(Trans2_qpathinfo);
9196 case TRANSACT2_SETPATHINFO:
9197 case TRANSACT2_SETFILEINFO:
9199 START_PROFILE(Trans2_setpathinfo);
9200 call_trans2setfilepathinfo(conn, req, state->call,
9201 &state->param, state->total_param,
9202 &state->data, state->total_data,
9203 state->max_data_return);
9204 END_PROFILE(Trans2_setpathinfo);
9208 case TRANSACT2_FINDNOTIFYFIRST:
9210 START_PROFILE(Trans2_findnotifyfirst);
9211 call_trans2findnotifyfirst(conn, req,
9212 &state->param, state->total_param,
9213 &state->data, state->total_data,
9214 state->max_data_return);
9215 END_PROFILE(Trans2_findnotifyfirst);
9219 case TRANSACT2_FINDNOTIFYNEXT:
9221 START_PROFILE(Trans2_findnotifynext);
9222 call_trans2findnotifynext(conn, req,
9223 &state->param, state->total_param,
9224 &state->data, state->total_data,
9225 state->max_data_return);
9226 END_PROFILE(Trans2_findnotifynext);
9230 case TRANSACT2_MKDIR:
9232 START_PROFILE(Trans2_mkdir);
9233 call_trans2mkdir(conn, req,
9234 &state->param, state->total_param,
9235 &state->data, state->total_data,
9236 state->max_data_return);
9237 END_PROFILE(Trans2_mkdir);
9241 case TRANSACT2_GET_DFS_REFERRAL:
9243 START_PROFILE(Trans2_get_dfs_referral);
9244 call_trans2getdfsreferral(conn, req,
9245 &state->param, state->total_param,
9246 &state->data, state->total_data,
9247 state->max_data_return);
9248 END_PROFILE(Trans2_get_dfs_referral);
9252 case TRANSACT2_IOCTL:
9254 START_PROFILE(Trans2_ioctl);
9255 call_trans2ioctl(conn, req,
9256 &state->param, state->total_param,
9257 &state->data, state->total_data,
9258 state->max_data_return);
9259 END_PROFILE(Trans2_ioctl);
9264 /* Error in request */
9265 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9266 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9270 /****************************************************************************
9271 Reply to a SMBtrans2.
9272 ****************************************************************************/
9274 void reply_trans2(struct smb_request *req)
9276 connection_struct *conn = req->conn;
9281 unsigned int tran_call;
9282 struct trans_state *state;
9285 START_PROFILE(SMBtrans2);
9287 if (req->wct < 14) {
9288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9289 END_PROFILE(SMBtrans2);
9293 dsoff = SVAL(req->vwv+12, 0);
9294 dscnt = SVAL(req->vwv+11, 0);
9295 psoff = SVAL(req->vwv+10, 0);
9296 pscnt = SVAL(req->vwv+9, 0);
9297 tran_call = SVAL(req->vwv+14, 0);
9299 result = allow_new_trans(conn->pending_trans, req->mid);
9300 if (!NT_STATUS_IS_OK(result)) {
9301 DEBUG(2, ("Got invalid trans2 request: %s\n",
9302 nt_errstr(result)));
9303 reply_nterror(req, result);
9304 END_PROFILE(SMBtrans2);
9309 switch (tran_call) {
9310 /* List the allowed trans2 calls on IPC$ */
9311 case TRANSACT2_OPEN:
9312 case TRANSACT2_GET_DFS_REFERRAL:
9313 case TRANSACT2_QFILEINFO:
9314 case TRANSACT2_QFSINFO:
9315 case TRANSACT2_SETFSINFO:
9318 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9319 END_PROFILE(SMBtrans2);
9324 if ((state = talloc(conn, struct trans_state)) == NULL) {
9325 DEBUG(0, ("talloc failed\n"));
9326 reply_nterror(req, NT_STATUS_NO_MEMORY);
9327 END_PROFILE(SMBtrans2);
9331 state->cmd = SMBtrans2;
9333 state->mid = req->mid;
9334 state->vuid = req->vuid;
9335 state->setup_count = SVAL(req->vwv+13, 0);
9336 state->setup = NULL;
9337 state->total_param = SVAL(req->vwv+0, 0);
9338 state->param = NULL;
9339 state->total_data = SVAL(req->vwv+1, 0);
9341 state->max_param_return = SVAL(req->vwv+2, 0);
9342 state->max_data_return = SVAL(req->vwv+3, 0);
9343 state->max_setup_return = SVAL(req->vwv+4, 0);
9344 state->close_on_completion = BITSETW(req->vwv+5, 0);
9345 state->one_way = BITSETW(req->vwv+5, 1);
9347 state->call = tran_call;
9349 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9350 is so as a sanity check */
9351 if (state->setup_count != 1) {
9353 * Need to have rc=0 for ioctl to get job id for OS/2.
9354 * Network printing will fail if function is not successful.
9355 * Similar function in reply.c will be used if protocol
9356 * is LANMAN1.0 instead of LM1.2X002.
9357 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9358 * outbuf doesn't have to be set(only job id is used).
9360 if ( (state->setup_count == 4)
9361 && (tran_call == TRANSACT2_IOCTL)
9362 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9363 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9364 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9366 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9367 DEBUG(2,("Transaction is %d\n",tran_call));
9369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9370 END_PROFILE(SMBtrans2);
9375 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9378 if (state->total_data) {
9380 if (trans_oob(state->total_data, 0, dscnt)
9381 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9385 /* Can't use talloc here, the core routines do realloc on the
9386 * params and data. */
9387 state->data = (char *)SMB_MALLOC(state->total_data);
9388 if (state->data == NULL) {
9389 DEBUG(0,("reply_trans2: data malloc fail for %u "
9390 "bytes !\n", (unsigned int)state->total_data));
9392 reply_nterror(req, NT_STATUS_NO_MEMORY);
9393 END_PROFILE(SMBtrans2);
9397 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9400 if (state->total_param) {
9402 if (trans_oob(state->total_param, 0, pscnt)
9403 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9407 /* Can't use talloc here, the core routines do realloc on the
9408 * params and data. */
9409 state->param = (char *)SMB_MALLOC(state->total_param);
9410 if (state->param == NULL) {
9411 DEBUG(0,("reply_trans: param malloc fail for %u "
9412 "bytes !\n", (unsigned int)state->total_param));
9413 SAFE_FREE(state->data);
9415 reply_nterror(req, NT_STATUS_NO_MEMORY);
9416 END_PROFILE(SMBtrans2);
9420 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9423 state->received_data = dscnt;
9424 state->received_param = pscnt;
9426 if ((state->received_param == state->total_param) &&
9427 (state->received_data == state->total_data)) {
9429 handle_trans2(conn, req, state);
9431 SAFE_FREE(state->data);
9432 SAFE_FREE(state->param);
9434 END_PROFILE(SMBtrans2);
9438 DLIST_ADD(conn->pending_trans, state);
9440 /* We need to send an interim response then receive the rest
9441 of the parameter/data bytes */
9442 reply_outbuf(req, 0, 0);
9443 show_msg((char *)req->outbuf);
9444 END_PROFILE(SMBtrans2);
9449 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9450 SAFE_FREE(state->data);
9451 SAFE_FREE(state->param);
9453 END_PROFILE(SMBtrans2);
9454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9458 /****************************************************************************
9459 Reply to a SMBtranss2
9460 ****************************************************************************/
9462 void reply_transs2(struct smb_request *req)
9464 connection_struct *conn = req->conn;
9465 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9466 struct trans_state *state;
9468 START_PROFILE(SMBtranss2);
9470 show_msg((const char *)req->inbuf);
9472 /* Windows clients expect all replies to
9473 a transact secondary (SMBtranss2 0x33)
9474 to have a command code of transact
9475 (SMBtrans2 0x32). See bug #8989
9476 and also [MS-CIFS] section 2.2.4.47.2
9479 req->cmd = SMBtrans2;
9482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9483 END_PROFILE(SMBtranss2);
9487 for (state = conn->pending_trans; state != NULL;
9488 state = state->next) {
9489 if (state->mid == req->mid) {
9494 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9496 END_PROFILE(SMBtranss2);
9500 /* Revise state->total_param and state->total_data in case they have
9501 changed downwards */
9503 if (SVAL(req->vwv+0, 0) < state->total_param)
9504 state->total_param = SVAL(req->vwv+0, 0);
9505 if (SVAL(req->vwv+1, 0) < state->total_data)
9506 state->total_data = SVAL(req->vwv+1, 0);
9508 pcnt = SVAL(req->vwv+2, 0);
9509 poff = SVAL(req->vwv+3, 0);
9510 pdisp = SVAL(req->vwv+4, 0);
9512 dcnt = SVAL(req->vwv+5, 0);
9513 doff = SVAL(req->vwv+6, 0);
9514 ddisp = SVAL(req->vwv+7, 0);
9516 state->received_param += pcnt;
9517 state->received_data += dcnt;
9519 if ((state->received_data > state->total_data) ||
9520 (state->received_param > state->total_param))
9524 if (trans_oob(state->total_param, pdisp, pcnt)
9525 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9528 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9532 if (trans_oob(state->total_data, ddisp, dcnt)
9533 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9536 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9539 if ((state->received_param < state->total_param) ||
9540 (state->received_data < state->total_data)) {
9541 END_PROFILE(SMBtranss2);
9545 handle_trans2(conn, req, state);
9547 DLIST_REMOVE(conn->pending_trans, state);
9548 SAFE_FREE(state->data);
9549 SAFE_FREE(state->param);
9552 END_PROFILE(SMBtranss2);
9557 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9558 DLIST_REMOVE(conn->pending_trans, state);
9559 SAFE_FREE(state->data);
9560 SAFE_FREE(state->param);
9562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9563 END_PROFILE(SMBtranss2);