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"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.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 #include "smb1_utils.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
48 #include "source3/lib/substitute.h"
49 #include "source3/lib/adouble.h"
51 #define DIR_ENTRY_SAFETY_MARGIN 4096
53 static char *store_file_unix_basic(connection_struct *conn,
56 const SMB_STRUCT_STAT *psbuf);
58 static char *store_file_unix_basic_info2(connection_struct *conn,
61 const SMB_STRUCT_STAT *psbuf);
63 /****************************************************************************
64 Check if an open file handle is a symlink.
65 ****************************************************************************/
67 NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
70 if (!VALID_STAT(fsp->fsp_name->st)) {
71 return NT_STATUS_ACCESS_DENIED;
73 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
74 return NT_STATUS_ACCESS_DENIED;
76 if (fsp_get_pathref_fd(fsp) == -1) {
77 return NT_STATUS_ACCESS_DENIED;
82 NTSTATUS check_access_fsp(struct files_struct *fsp,
85 if (!fsp->fsp_flags.is_fsa) {
86 return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
91 if (!(fsp->access_mask & access_mask)) {
92 return NT_STATUS_ACCESS_DENIED;
97 #if defined(HAVE_POSIX_ACLS)
98 /****************************************************************************
99 Utility function to open a fsp for a POSIX handle operation.
100 ****************************************************************************/
102 static NTSTATUS get_posix_fsp(connection_struct *conn,
103 struct smb_request *req,
104 struct smb_filename *smb_fname,
105 uint32_t access_mask,
106 files_struct **ret_fsp)
109 uint32_t create_disposition = FILE_OPEN;
110 uint32_t share_access = FILE_SHARE_READ|
113 struct smb2_create_blobs *posx = NULL;
116 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
117 * but set reasonable defaults.
119 uint32_t file_attributes = 0664;
120 uint32_t oplock = NO_OPLOCK;
121 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
123 /* File or directory must exist. */
124 if (!VALID_STAT(smb_fname->st)) {
125 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
127 /* Cannot be a symlink. */
128 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
129 return NT_STATUS_ACCESS_DENIED;
131 /* Set options correctly for directory open. */
132 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
134 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
135 * directories, but set reasonable defaults.
137 file_attributes = 0775;
138 create_options = FILE_DIRECTORY_FILE;
141 status = make_smb2_posix_create_ctx(
142 talloc_tos(), &posx, file_attributes);
143 if (!NT_STATUS_IS_OK(status)) {
144 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
149 status = SMB_VFS_CREATE_FILE(
152 smb_fname, /* fname */
153 access_mask, /* access_mask */
154 share_access, /* share_access */
155 create_disposition,/* create_disposition*/
156 create_options, /* create_options */
157 file_attributes,/* file_attributes */
158 oplock, /* oplock_request */
160 0, /* allocation_size */
161 0, /* private_flags */
164 ret_fsp, /* result */
166 posx, /* in_context */
167 NULL); /* out_context */
175 /********************************************************************
176 Roundup a value to the nearest allocation roundup size boundary.
177 Only do this for Windows clients.
178 ********************************************************************/
180 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
182 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
184 /* Only roundup for Windows clients. */
185 enum remote_arch_types ra_type = get_remote_arch();
186 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
187 val = SMB_ROUNDUP(val,rval);
192 /****************************************************************************
193 Utility functions for dealing with extended attributes.
194 ****************************************************************************/
196 /****************************************************************************
197 Refuse to allow clients to overwrite our private xattrs.
198 ****************************************************************************/
200 bool samba_private_attr_name(const char *unix_ea_name)
202 static const char * const prohibited_ea_names[] = {
203 SAMBA_POSIX_INHERITANCE_EA_NAME,
204 SAMBA_XATTR_DOS_ATTRIB,
213 for (i = 0; prohibited_ea_names[i]; i++) {
214 if (strequal( prohibited_ea_names[i], unix_ea_name))
217 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
218 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
224 /****************************************************************************
225 Get one EA value. Fill in a struct ea_struct.
226 ****************************************************************************/
228 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
231 struct ea_struct *pea)
233 /* Get the value of this xattr. Max size is 64k. */
234 size_t attr_size = 256;
237 size_t max_xattr_size = 0;
240 return NT_STATUS_INVALID_HANDLE;
243 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
247 val = talloc_realloc(mem_ctx, val, char, attr_size);
249 return NT_STATUS_NO_MEMORY;
252 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
253 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
254 attr_size = max_xattr_size;
259 return map_nt_error_from_unix(errno);
262 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
263 dump_data(10, (uint8_t *)val, sizeret);
266 if (strnequal(ea_name, "user.", 5)) {
267 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
269 pea->name = talloc_strdup(mem_ctx, ea_name);
271 if (pea->name == NULL) {
273 return NT_STATUS_NO_MEMORY;
275 pea->value.data = (unsigned char *)val;
276 pea->value.length = (size_t)sizeret;
280 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
286 /* Get a list of all xattrs. Max namesize is 64k. */
287 size_t ea_namelist_size = 1024;
288 char *ea_namelist = smallbuf;
289 char *to_free = NULL;
294 ssize_t sizeret = -1;
304 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
305 * symlink. This is ok, handle it here, by just return no EA's
311 /* should be the case that fsp != NULL */
312 SMB_ASSERT(fsp != NULL);
314 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
317 if ((sizeret == -1) && (errno == ERANGE)) {
318 ea_namelist_size = 65536;
319 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
320 if (ea_namelist == NULL) {
321 return NT_STATUS_NO_MEMORY;
323 to_free = ea_namelist;
325 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
330 status = map_nt_error_from_unix(errno);
331 TALLOC_FREE(to_free);
335 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
338 TALLOC_FREE(to_free);
343 * Ensure the result is 0-terminated
346 if (ea_namelist[sizeret-1] != '\0') {
347 TALLOC_FREE(to_free);
348 return NT_STATUS_INTERNAL_ERROR;
356 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
360 *pnum_names = num_names;
362 if (pnames == NULL) {
363 TALLOC_FREE(to_free);
367 names = talloc_array(mem_ctx, char *, num_names);
369 DEBUG(0, ("talloc failed\n"));
370 TALLOC_FREE(to_free);
371 return NT_STATUS_NO_MEMORY;
374 if (ea_namelist == smallbuf) {
375 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
376 if (ea_namelist == NULL) {
378 return NT_STATUS_NO_MEMORY;
381 talloc_steal(names, ea_namelist);
383 ea_namelist = talloc_realloc(names, ea_namelist, char,
385 if (ea_namelist == NULL) {
387 return NT_STATUS_NO_MEMORY;
393 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
394 names[num_names++] = p;
402 /****************************************************************************
403 Return a linked list of the total EA's. Plus the total size
404 ****************************************************************************/
406 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
408 size_t *pea_total_len,
409 struct ea_list **ea_list)
411 /* Get a list of all xattrs. Max namesize is 64k. */
414 struct ea_list *ea_list_head = NULL;
415 bool posix_pathnames = false;
426 if (!lp_ea_support(SNUM(fsp->conn))) {
430 if (fsp_is_alternate_stream(fsp)) {
431 return NT_STATUS_INVALID_PARAMETER;
434 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
436 status = get_ea_names_from_fsp(talloc_tos(),
441 if (!NT_STATUS_IS_OK(status)) {
445 if (num_names == 0) {
449 for (i=0; i<num_names; i++) {
450 struct ea_list *listp;
453 if (strnequal(names[i], "system.", 7)
454 || samba_private_attr_name(names[i]))
458 * Filter out any underlying POSIX EA names
459 * that a Windows client can't handle.
461 if (!posix_pathnames &&
462 is_invalid_windows_ea_name(names[i])) {
466 listp = talloc(mem_ctx, struct ea_list);
468 return NT_STATUS_NO_MEMORY;
471 status = get_ea_value_fsp(listp,
476 if (!NT_STATUS_IS_OK(status)) {
481 if (listp->ea.value.length == 0) {
483 * We can never return a zero length EA.
484 * Windows reports the EA's as corrupted.
488 } else if (listp->ea.value.length > 65536) {
490 * SMB clients may report error with file
491 * if large EA is presented to them.
493 DBG_ERR("EA [%s] on file [%s] exceeds "
494 "maximum permitted EA size of 64KiB: %zu\n.",
495 listp->ea.name, fsp_str_dbg(fsp),
496 listp->ea.value.length);
501 push_ascii_fstring(dos_ea_name, listp->ea.name);
504 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
506 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
507 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
508 (unsigned int)listp->ea.value.length));
510 DLIST_ADD_END(ea_list_head, listp);
514 /* Add on 4 for total length. */
515 if (*pea_total_len) {
519 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
520 (unsigned int)*pea_total_len));
522 *ea_list = ea_list_head;
526 /****************************************************************************
527 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
529 ****************************************************************************/
531 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
532 connection_struct *conn, struct ea_list *ea_list)
534 unsigned int ret_data_size = 4;
537 SMB_ASSERT(total_data_size >= 4);
539 if (!lp_ea_support(SNUM(conn))) {
544 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
547 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
548 dos_namelen = strlen(dos_ea_name);
549 if (dos_namelen > 255 || dos_namelen == 0) {
552 if (ea_list->ea.value.length > 65535) {
555 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
559 /* We know we have room. */
560 SCVAL(p,0,ea_list->ea.flags);
561 SCVAL(p,1,dos_namelen);
562 SSVAL(p,2,ea_list->ea.value.length);
563 strlcpy(p+4, dos_ea_name, dos_namelen+1);
564 if (ea_list->ea.value.length > 0) {
565 memcpy(p + 4 + dos_namelen + 1,
566 ea_list->ea.value.data,
567 ea_list->ea.value.length);
570 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
571 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
574 ret_data_size = PTR_DIFF(p, pdata);
575 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
576 SIVAL(pdata,0,ret_data_size);
577 return ret_data_size;
580 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
582 unsigned int total_data_size,
583 unsigned int *ret_data_size,
584 connection_struct *conn,
585 struct ea_list *ea_list)
587 uint8_t *p = (uint8_t *)pdata;
588 uint8_t *last_start = NULL;
589 bool do_store_data = (pdata != NULL);
593 if (!lp_ea_support(SNUM(conn))) {
594 return NT_STATUS_NO_EAS_ON_FILE;
597 for (; ea_list; ea_list = ea_list->next) {
603 if (last_start != NULL && do_store_data) {
604 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
608 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
609 dos_namelen = strlen(dos_ea_name);
610 if (dos_namelen > 255 || dos_namelen == 0) {
611 return NT_STATUS_INTERNAL_ERROR;
613 if (ea_list->ea.value.length > 65535) {
614 return NT_STATUS_INTERNAL_ERROR;
617 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
620 pad = (4 - (this_size % 4)) % 4;
625 if (this_size > total_data_size) {
626 return NT_STATUS_INFO_LENGTH_MISMATCH;
629 /* We know we have room. */
630 SIVAL(p, 0x00, 0); /* next offset */
631 SCVAL(p, 0x04, ea_list->ea.flags);
632 SCVAL(p, 0x05, dos_namelen);
633 SSVAL(p, 0x06, ea_list->ea.value.length);
634 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
635 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
637 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
641 total_data_size -= this_size;
647 *ret_data_size = PTR_DIFF(p, pdata);
648 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
652 static unsigned int estimate_ea_size(files_struct *fsp)
654 size_t total_ea_len = 0;
656 struct ea_list *ea_list = NULL;
664 if (!lp_ea_support(SNUM(fsp->conn))) {
668 mem_ctx = talloc_stackframe();
670 /* If this is a stream fsp, then we need to instead find the
671 * estimated ea len from the main file, not the stream
672 * (streams cannot have EAs), but the estimate isn't just 0 in
674 fsp = metadata_fsp(fsp);
675 (void)get_ea_list_from_fsp(mem_ctx,
680 if(fsp->conn->sconn->using_smb2) {
681 unsigned int ret_data_size;
683 * We're going to be using fill_ea_chained_buffer() to
684 * marshall EA's - this size is significantly larger
685 * than the SMB1 buffer. Re-calculate the size without
688 status = fill_ea_chained_buffer(mem_ctx,
694 if (!NT_STATUS_IS_OK(status)) {
697 total_ea_len = ret_data_size;
699 TALLOC_FREE(mem_ctx);
703 /****************************************************************************
704 Ensure the EA name is case insensitive by matching any existing EA name.
705 ****************************************************************************/
707 static void canonicalize_ea_name(files_struct *fsp,
708 fstring unix_ea_name)
711 TALLOC_CTX *mem_ctx = talloc_tos();
712 struct ea_list *ea_list;
713 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
717 if (!NT_STATUS_IS_OK(status)) {
721 for (; ea_list; ea_list = ea_list->next) {
722 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
723 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
724 &unix_ea_name[5], ea_list->ea.name));
725 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
731 /****************************************************************************
732 Set or delete an extended attribute.
733 ****************************************************************************/
735 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
736 struct ea_list *ea_list)
739 bool posix_pathnames = false;
741 if (!lp_ea_support(SNUM(conn))) {
742 return NT_STATUS_EAS_NOT_SUPPORTED;
746 return NT_STATUS_INVALID_HANDLE;
749 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
751 status = refuse_symlink_fsp(fsp);
752 if (!NT_STATUS_IS_OK(status)) {
756 status = check_access_fsp(fsp, FILE_WRITE_EA);
757 if (!NT_STATUS_IS_OK(status)) {
761 /* Setting EAs on streams isn't supported. */
762 if (fsp_is_alternate_stream(fsp)) {
763 return NT_STATUS_INVALID_PARAMETER;
767 * Filter out invalid Windows EA names - before
768 * we set *any* of them.
771 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
772 return STATUS_INVALID_EA_NAME;
775 for (;ea_list; ea_list = ea_list->next) {
777 fstring unix_ea_name;
779 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
780 fstrcat(unix_ea_name, ea_list->ea.name);
782 canonicalize_ea_name(fsp, unix_ea_name);
784 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
786 if (samba_private_attr_name(unix_ea_name)) {
787 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
788 return NT_STATUS_ACCESS_DENIED;
791 if (ea_list->ea.value.length == 0) {
792 /* Remove the attribute. */
793 DBG_DEBUG("deleting ea name %s on "
794 "file %s by file descriptor.\n",
795 unix_ea_name, fsp_str_dbg(fsp));
796 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
798 /* Removing a non existent attribute always succeeds. */
799 if (ret == -1 && errno == ENOATTR) {
800 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
806 DEBUG(10,("set_ea: setting ea name %s on file "
807 "%s by file descriptor.\n",
808 unix_ea_name, fsp_str_dbg(fsp)));
809 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
810 ea_list->ea.value.data, ea_list->ea.value.length, 0);
815 if (errno == ENOTSUP) {
816 return NT_STATUS_EAS_NOT_SUPPORTED;
819 return map_nt_error_from_unix(errno);
825 /****************************************************************************
826 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
827 ****************************************************************************/
829 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
831 struct ea_list *ea_list_head = NULL;
832 size_t converted_size, offset = 0;
834 while (offset + 2 < data_size) {
835 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
836 unsigned int namelen = CVAL(pdata,offset);
838 offset++; /* Go past the namelen byte. */
840 /* integer wrap paranioa. */
841 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
842 (offset > data_size) || (namelen > data_size) ||
843 (offset + namelen >= data_size)) {
846 /* Ensure the name is null terminated. */
847 if (pdata[offset + namelen] != '\0') {
850 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
852 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
853 "failed: %s", strerror(errno)));
859 offset += (namelen + 1); /* Go past the name + terminating zero. */
860 DLIST_ADD_END(ea_list_head, eal);
861 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
867 /****************************************************************************
868 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
869 ****************************************************************************/
871 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
873 struct ea_list *ea_list_head = NULL;
875 size_t bytes_used = 0;
877 while (offset < data_size) {
878 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
884 DLIST_ADD_END(ea_list_head, eal);
885 offset += bytes_used;
891 /****************************************************************************
892 Count the total EA size needed.
893 ****************************************************************************/
895 static size_t ea_list_size(struct ea_list *ealist)
898 struct ea_list *listp;
901 for (listp = ealist; listp; listp = listp->next) {
902 push_ascii_fstring(dos_ea_name, listp->ea.name);
903 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
905 /* Add on 4 for total length. */
913 /****************************************************************************
914 Return a union of EA's from a file list and a list of names.
915 The TALLOC context for the two lists *MUST* be identical as we steal
916 memory from one list to add to another. JRA.
917 ****************************************************************************/
919 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
921 struct ea_list *nlistp, *flistp;
923 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
924 for (flistp = file_list; flistp; flistp = flistp->next) {
925 if (strequal(nlistp->ea.name, flistp->ea.name)) {
931 /* Copy the data from this entry. */
932 nlistp->ea.flags = flistp->ea.flags;
933 nlistp->ea.value = flistp->ea.value;
936 nlistp->ea.flags = 0;
937 ZERO_STRUCT(nlistp->ea.value);
941 *total_ea_len = ea_list_size(name_list);
945 /****************************************************************************
946 Send the required number of replies back.
947 We assume all fields other than the data fields are
948 set correctly for the type of call.
949 HACK ! Always assumes smb_setup field is zero.
950 ****************************************************************************/
952 void send_trans2_replies(connection_struct *conn,
953 struct smb_request *req,
961 /* As we are using a protocol > LANMAN1 then the max_send
962 variable must have been set in the sessetupX call.
963 This takes precedence over the max_xmit field in the
964 global struct. These different max_xmit variables should
965 be merged as this is now too confusing */
967 int data_to_send = datasize;
968 int params_to_send = paramsize;
970 const char *pp = params;
971 const char *pd = pdata;
972 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
973 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
974 int data_alignment_offset = 0;
975 bool overflow = False;
976 struct smbXsrv_connection *xconn = req->xconn;
977 int max_send = xconn->smb1.sessions.max_send;
979 /* Modify the data_to_send and datasize and set the error if
980 we're trying to send more than max_data_bytes. We still send
981 the part of the packet(s) that fit. Strange, but needed
984 if (max_data_bytes > 0 && datasize > max_data_bytes) {
985 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
986 max_data_bytes, datasize ));
987 datasize = data_to_send = max_data_bytes;
991 /* If there genuinely are no parameters or data to send just send the empty packet */
993 if(params_to_send == 0 && data_to_send == 0) {
994 reply_outbuf(req, 10, 0);
995 if (NT_STATUS_V(status)) {
998 ntstatus_to_dos(status, &eclass, &ecode);
999 error_packet_set((char *)req->outbuf,
1000 eclass, ecode, status,
1003 show_msg((char *)req->outbuf);
1004 if (!srv_send_smb(xconn,
1005 (char *)req->outbuf,
1006 true, req->seqnum+1,
1007 IS_CONN_ENCRYPTED(conn),
1009 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1011 TALLOC_FREE(req->outbuf);
1015 /* When sending params and data ensure that both are nicely aligned */
1016 /* Only do this alignment when there is also data to send - else
1017 can cause NT redirector problems. */
1019 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1020 data_alignment_offset = 4 - (params_to_send % 4);
1022 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1023 /* The alignment_offset is to align the param bytes on an even byte
1024 boundary. NT 4.0 Beta needs this to work correctly. */
1026 useable_space = max_send - (smb_size
1029 + data_alignment_offset);
1031 if (useable_space < 0) {
1032 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1033 "= %d!!!", useable_space));
1034 exit_server_cleanly("send_trans2_replies: Not enough space");
1037 while (params_to_send || data_to_send) {
1038 /* Calculate whether we will totally or partially fill this packet */
1040 total_sent_thistime = params_to_send + data_to_send;
1042 /* We can never send more than useable_space */
1044 * Note that 'useable_space' does not include the alignment offsets,
1045 * but we must include the alignment offsets in the calculation of
1046 * the length of the data we send over the wire, as the alignment offsets
1047 * are sent here. Fix from Marc_Jacobsen@hp.com.
1050 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1052 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1053 + data_alignment_offset);
1055 /* Set total params and data to be sent */
1056 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1057 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1059 /* Calculate how many parameters and data we can fit into
1060 * this packet. Parameters get precedence
1063 params_sent_thistime = MIN(params_to_send,useable_space);
1064 data_sent_thistime = useable_space - params_sent_thistime;
1065 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1067 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1069 /* smb_proff is the offset from the start of the SMB header to the
1070 parameter bytes, however the first 4 bytes of outbuf are
1071 the Netbios over TCP header. Thus use smb_base() to subtract
1072 them from the calculation */
1074 SSVAL(req->outbuf,smb_proff,
1075 ((smb_buf(req->outbuf)+alignment_offset)
1076 - smb_base(req->outbuf)));
1078 if(params_sent_thistime == 0)
1079 SSVAL(req->outbuf,smb_prdisp,0);
1081 /* Absolute displacement of param bytes sent in this packet */
1082 SSVAL(req->outbuf,smb_prdisp,pp - params);
1084 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1085 if(data_sent_thistime == 0) {
1086 SSVAL(req->outbuf,smb_droff,0);
1087 SSVAL(req->outbuf,smb_drdisp, 0);
1089 /* The offset of the data bytes is the offset of the
1090 parameter bytes plus the number of parameters being sent this time */
1091 SSVAL(req->outbuf, smb_droff,
1092 ((smb_buf(req->outbuf)+alignment_offset)
1093 - smb_base(req->outbuf))
1094 + params_sent_thistime + data_alignment_offset);
1095 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1098 /* Initialize the padding for alignment */
1100 if (alignment_offset != 0) {
1101 memset(smb_buf(req->outbuf), 0, alignment_offset);
1104 /* Copy the param bytes into the packet */
1106 if(params_sent_thistime) {
1107 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1108 params_sent_thistime);
1111 /* Copy in the data bytes */
1112 if(data_sent_thistime) {
1113 if (data_alignment_offset != 0) {
1114 memset((smb_buf(req->outbuf)+alignment_offset+
1115 params_sent_thistime), 0,
1116 data_alignment_offset);
1118 memcpy(smb_buf(req->outbuf)+alignment_offset
1119 +params_sent_thistime+data_alignment_offset,
1120 pd,data_sent_thistime);
1123 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1124 params_sent_thistime, data_sent_thistime, useable_space));
1125 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1126 params_to_send, data_to_send, paramsize, datasize));
1129 error_packet_set((char *)req->outbuf,
1130 ERRDOS,ERRbufferoverflow,
1131 STATUS_BUFFER_OVERFLOW,
1133 } else if (NT_STATUS_V(status)) {
1136 ntstatus_to_dos(status, &eclass, &ecode);
1137 error_packet_set((char *)req->outbuf,
1138 eclass, ecode, status,
1142 /* Send the packet */
1143 show_msg((char *)req->outbuf);
1144 if (!srv_send_smb(xconn,
1145 (char *)req->outbuf,
1146 true, req->seqnum+1,
1147 IS_CONN_ENCRYPTED(conn),
1149 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1151 TALLOC_FREE(req->outbuf);
1153 pp += params_sent_thistime;
1154 pd += data_sent_thistime;
1156 params_to_send -= params_sent_thistime;
1157 data_to_send -= data_sent_thistime;
1160 if(params_to_send < 0 || data_to_send < 0) {
1161 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1162 params_to_send, data_to_send));
1170 /****************************************************************************
1171 Reply to a TRANSACT2_OPEN.
1172 ****************************************************************************/
1174 static void call_trans2open(connection_struct *conn,
1175 struct smb_request *req,
1176 char **pparams, int total_params,
1177 char **ppdata, int total_data,
1178 unsigned int max_data_bytes)
1180 struct smb_filename *smb_fname = NULL;
1181 char *params = *pparams;
1182 char *pdata = *ppdata;
1185 bool oplock_request;
1187 bool return_additional_info;
1196 int fattr=0,mtime=0;
1197 SMB_INO_T inode = 0;
1200 struct ea_list *ea_list = NULL;
1203 uint32_t access_mask;
1204 uint32_t share_mode;
1205 uint32_t create_disposition;
1206 uint32_t create_options = 0;
1207 uint32_t private_flags = 0;
1208 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1209 TALLOC_CTX *ctx = talloc_tos();
1212 * Ensure we have enough parameters to perform the operation.
1215 if (total_params < 29) {
1216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1220 flags = SVAL(params, 0);
1221 deny_mode = SVAL(params, 2);
1222 open_attr = SVAL(params,6);
1223 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1224 if (oplock_request) {
1225 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1229 return_additional_info = BITSETW(params,0);
1230 open_sattr = SVAL(params, 4);
1231 open_time = make_unix_date3(params+8);
1233 open_ofun = SVAL(params,12);
1234 open_size = IVAL(params,14);
1235 pname = ¶ms[28];
1238 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1242 if (req->posix_pathnames) {
1243 srvstr_get_path_posix(ctx,
1252 srvstr_get_path(ctx,
1261 if (!NT_STATUS_IS_OK(status)) {
1262 reply_nterror(req, status);
1266 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1267 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1268 (unsigned int)open_ofun, open_size));
1270 status = filename_convert(ctx,
1276 if (!NT_STATUS_IS_OK(status)) {
1277 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1278 reply_botherror(req,
1279 NT_STATUS_PATH_NOT_COVERED,
1280 ERRSRV, ERRbadpath);
1283 reply_nterror(req, status);
1287 if (open_ofun == 0) {
1288 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1292 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1294 &access_mask, &share_mode,
1295 &create_disposition,
1298 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1302 /* Any data in this call is an EA list. */
1303 if (total_data && (total_data != 4)) {
1304 if (total_data < 10) {
1305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1309 if (IVAL(pdata,0) > total_data) {
1310 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1311 IVAL(pdata,0), (unsigned int)total_data));
1312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1316 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1323 if (!lp_ea_support(SNUM(conn))) {
1324 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1328 if (!req->posix_pathnames &&
1329 ea_list_has_invalid_name(ea_list)) {
1331 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1332 if(*pparams == NULL ) {
1333 reply_nterror(req, NT_STATUS_NO_MEMORY);
1337 memset(params, '\0', param_len);
1338 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1339 params, param_len, NULL, 0, max_data_bytes);
1344 status = SMB_VFS_CREATE_FILE(
1347 smb_fname, /* fname */
1348 access_mask, /* access_mask */
1349 share_mode, /* share_access */
1350 create_disposition, /* create_disposition*/
1351 create_options, /* create_options */
1352 open_attr, /* file_attributes */
1353 oplock_request, /* oplock_request */
1355 open_size, /* allocation_size */
1358 ea_list, /* ea_list */
1360 &smb_action, /* psbuf */
1361 NULL, NULL); /* create context */
1363 if (!NT_STATUS_IS_OK(status)) {
1364 if (open_was_deferred(req->xconn, req->mid)) {
1365 /* We have re-scheduled this call. */
1369 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1370 reply_openerror(req, status);
1374 fsp = fcb_or_dos_open(
1381 bool ok = defer_smb1_sharing_violation(req);
1385 reply_openerror(req, status);
1389 smb_action = FILE_WAS_OPENED;
1392 size = get_file_size_stat(&smb_fname->st);
1393 fattr = fdos_mode(fsp);
1394 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1395 inode = smb_fname->st.st_ex_ino;
1396 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1397 close_file_free(req, &fsp, ERROR_CLOSE);
1398 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1402 /* Realloc the size of parameters and data we will return */
1403 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1404 if(*pparams == NULL ) {
1405 reply_nterror(req, NT_STATUS_NO_MEMORY);
1410 SSVAL(params,0,fsp->fnum);
1411 SSVAL(params,2,fattr);
1412 srv_put_dos_date2(params,4, mtime);
1413 SIVAL(params,8, (uint32_t)size);
1414 SSVAL(params,12,deny_mode);
1415 SSVAL(params,14,0); /* open_type - file or directory. */
1416 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1418 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1419 smb_action |= EXTENDED_OPLOCK_GRANTED;
1422 SSVAL(params,18,smb_action);
1425 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1427 SIVAL(params,20,inode);
1428 SSVAL(params,24,0); /* Padding. */
1430 uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
1431 SIVAL(params, 26, ea_size);
1433 SIVAL(params, 26, 0);
1436 /* Send the required number of replies */
1437 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1439 TALLOC_FREE(smb_fname);
1442 /*********************************************************
1443 Routine to check if a given string matches exactly.
1444 as a special case a mask of "." does NOT match. That
1445 is required for correct wildcard semantics
1446 Case can be significant or not.
1447 **********************************************************/
1449 static bool exact_match(bool has_wild,
1450 bool case_sensitive,
1454 if (mask[0] == '.' && mask[1] == 0) {
1462 if (case_sensitive) {
1463 return strcmp(str,mask)==0;
1465 return strcasecmp_m(str,mask) == 0;
1469 /****************************************************************************
1470 Return the filetype for UNIX extensions.
1471 ****************************************************************************/
1473 static uint32_t unix_filetype(mode_t mode)
1476 return UNIX_TYPE_FILE;
1477 else if(S_ISDIR(mode))
1478 return UNIX_TYPE_DIR;
1480 else if(S_ISLNK(mode))
1481 return UNIX_TYPE_SYMLINK;
1484 else if(S_ISCHR(mode))
1485 return UNIX_TYPE_CHARDEV;
1488 else if(S_ISBLK(mode))
1489 return UNIX_TYPE_BLKDEV;
1492 else if(S_ISFIFO(mode))
1493 return UNIX_TYPE_FIFO;
1496 else if(S_ISSOCK(mode))
1497 return UNIX_TYPE_SOCKET;
1500 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1501 return UNIX_TYPE_UNKNOWN;
1504 /****************************************************************************
1505 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1506 ****************************************************************************/
1508 NTSTATUS unix_perms_from_wire(connection_struct *conn,
1509 const SMB_STRUCT_STAT *psbuf,
1511 enum perm_type ptype,
1516 if (perms == SMB_MODE_NO_CHANGE) {
1517 if (!VALID_STAT(*psbuf)) {
1518 return NT_STATUS_INVALID_PARAMETER;
1520 *ret_perms = psbuf->st_ex_mode;
1521 return NT_STATUS_OK;
1525 ret = wire_perms_to_unix(perms);
1527 if (ptype == PERM_NEW_FILE) {
1529 * "create mask"/"force create mode" are
1530 * only applied to new files, not existing ones.
1532 ret &= lp_create_mask(SNUM(conn));
1533 /* Add in force bits */
1534 ret |= lp_force_create_mode(SNUM(conn));
1535 } else if (ptype == PERM_NEW_DIR) {
1537 * "directory mask"/"force directory mode" are
1538 * only applied to new directories, not existing ones.
1540 ret &= lp_directory_mask(SNUM(conn));
1541 /* Add in force bits */
1542 ret |= lp_force_directory_mode(SNUM(conn));
1546 return NT_STATUS_OK;
1549 /****************************************************************************
1550 Needed to show the msdfs symlinks as directories. Modifies psbuf
1551 to be a directory if it's a msdfs link.
1552 ****************************************************************************/
1554 static bool check_msdfs_link(struct files_struct *dirfsp,
1555 struct smb_filename *atname,
1556 struct smb_filename *smb_fname)
1558 int saved_errno = errno;
1559 if(lp_host_msdfs() &&
1560 lp_msdfs_root(SNUM(dirfsp->conn)) &&
1561 is_msdfs_link(dirfsp, atname)) {
1564 * Copy the returned stat struct from the relative
1565 * to the full pathname.
1567 smb_fname->st = atname->st;
1569 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1571 smb_fname->base_name));
1572 smb_fname->st.st_ex_mode =
1573 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1574 errno = saved_errno;
1577 errno = saved_errno;
1582 /****************************************************************************
1583 Get a level dependent lanman2 dir entry.
1584 ****************************************************************************/
1586 struct smbd_dirptr_lanman2_state {
1587 connection_struct *conn;
1588 uint32_t info_level;
1589 bool check_mangled_names;
1591 bool got_exact_match;
1592 bool case_sensitive;
1595 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1601 struct smbd_dirptr_lanman2_state *state =
1602 (struct smbd_dirptr_lanman2_state *)private_data;
1604 char mangled_name[13]; /* mangled 8.3 name. */
1608 /* Mangle fname if it's an illegal name. */
1609 if (mangle_must_mangle(dname, state->conn->params)) {
1611 * Slow path - ensure we can push the original name as UCS2. If
1612 * not, then just don't return this name.
1616 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1617 uint8_t *tmp = talloc_array(talloc_tos(),
1621 status = srvstr_push(NULL,
1622 FLAGS2_UNICODE_STRINGS,
1631 if (!NT_STATUS_IS_OK(status)) {
1635 ok = name_to_8_3(dname, mangled_name,
1636 true, state->conn->params);
1640 fname = mangled_name;
1645 got_match = exact_match(state->has_wild,
1646 state->case_sensitive,
1648 state->got_exact_match = got_match;
1650 got_match = mask_match(fname, mask,
1651 state->case_sensitive);
1654 if(!got_match && state->check_mangled_names &&
1655 !mangle_is_8_3(fname, false, state->conn->params)) {
1657 * It turns out that NT matches wildcards against
1658 * both long *and* short names. This may explain some
1659 * of the wildcard wierdness from old DOS clients
1660 * that some people have been seeing.... JRA.
1662 /* Force the mangling into 8.3. */
1663 ok = name_to_8_3(fname, mangled_name,
1664 false, state->conn->params);
1669 got_match = exact_match(state->has_wild,
1670 state->case_sensitive,
1671 mangled_name, mask);
1672 state->got_exact_match = got_match;
1674 got_match = mask_match(mangled_name, mask,
1675 state->case_sensitive);
1683 *_fname = talloc_strdup(ctx, fname);
1684 if (*_fname == NULL) {
1691 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1693 struct files_struct *dirfsp,
1694 struct smb_filename *atname,
1695 struct smb_filename *smb_fname,
1699 struct smbd_dirptr_lanman2_state *state =
1700 (struct smbd_dirptr_lanman2_state *)private_data;
1701 bool ms_dfs_link = false;
1703 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1704 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1705 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1706 "Couldn't lstat [%s] (%s)\n",
1707 smb_fname_str_dbg(smb_fname),
1714 if (!VALID_STAT(smb_fname->st) &&
1715 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1716 /* Needed to show the msdfs symlinks as
1719 ms_dfs_link = check_msdfs_link(dirfsp,
1723 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1724 "Couldn't stat [%s] (%s)\n",
1725 smb_fname_str_dbg(smb_fname),
1730 *_mode = dos_mode_msdfs(state->conn, smb_fname);
1738 *_mode = fdos_mode(smb_fname->fsp);
1739 smb_fname->st = smb_fname->fsp->fsp_name->st;
1744 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1745 connection_struct *conn,
1747 uint32_t info_level,
1748 struct ea_list *name_list,
1749 bool check_mangled_names,
1750 bool requires_resume_key,
1753 const struct smb_filename *smb_fname,
1754 int space_remaining,
1760 uint64_t *last_entry_off)
1762 char *p, *q, *pdata = *ppdata;
1764 uint64_t file_size = 0;
1765 uint64_t allocation_size = 0;
1766 uint64_t file_id = 0;
1768 struct timespec mdate_ts = {0};
1769 struct timespec adate_ts = {0};
1770 struct timespec cdate_ts = {0};
1771 struct timespec create_date_ts = {0};
1772 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1774 char *last_entry_ptr;
1779 struct readdir_attr_data *readdir_attr_data = NULL;
1781 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1782 file_size = get_file_size_stat(&smb_fname->st);
1784 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1787 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1790 if (smb_fname->fsp != NULL &&
1791 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1792 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1794 &readdir_attr_data);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1803 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1805 mdate_ts = smb_fname->st.st_ex_mtime;
1806 adate_ts = smb_fname->st.st_ex_atime;
1807 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1808 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1810 if (lp_dos_filetime_resolution(SNUM(conn))) {
1811 dos_filetime_timespec(&create_date_ts);
1812 dos_filetime_timespec(&mdate_ts);
1813 dos_filetime_timespec(&adate_ts);
1814 dos_filetime_timespec(&cdate_ts);
1817 create_date = convert_timespec_to_time_t(create_date_ts);
1818 mdate = convert_timespec_to_time_t(mdate_ts);
1819 adate = convert_timespec_to_time_t(adate_ts);
1821 /* align the record */
1822 SMB_ASSERT(align >= 1);
1824 off = (int)PTR_DIFF(pdata, base_data);
1825 pad = (off + (align-1)) & ~(align-1);
1828 if (pad && pad > space_remaining) {
1829 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1830 "for padding (wanted %u, had %d)\n",
1833 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1837 /* initialize padding to 0 */
1839 memset(pdata, 0, pad);
1841 space_remaining -= pad;
1843 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1853 switch (info_level) {
1854 case SMB_FIND_INFO_STANDARD:
1855 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1856 if(requires_resume_key) {
1860 srv_put_dos_date2(p,0,create_date);
1861 srv_put_dos_date2(p,4,adate);
1862 srv_put_dos_date2(p,8,mdate);
1863 SIVAL(p,12,(uint32_t)file_size);
1864 SIVAL(p,16,(uint32_t)allocation_size);
1868 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1869 p += ucs2_align(base_data, p, 0);
1871 status = srvstr_push(base_data, flags2, p,
1872 fname, PTR_DIFF(end_data, p),
1873 STR_TERMINATE, &len);
1874 if (!NT_STATUS_IS_OK(status)) {
1877 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1879 SCVAL(nameptr, -1, len - 2);
1881 SCVAL(nameptr, -1, 0);
1885 SCVAL(nameptr, -1, len - 1);
1887 SCVAL(nameptr, -1, 0);
1893 case SMB_FIND_EA_SIZE:
1894 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1895 if (requires_resume_key) {
1899 srv_put_dos_date2(p,0,create_date);
1900 srv_put_dos_date2(p,4,adate);
1901 srv_put_dos_date2(p,8,mdate);
1902 SIVAL(p,12,(uint32_t)file_size);
1903 SIVAL(p,16,(uint32_t)allocation_size);
1906 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1907 SIVAL(p,22,ea_size); /* Extended attributes */
1911 status = srvstr_push(base_data, flags2,
1912 p, fname, PTR_DIFF(end_data, p),
1913 STR_TERMINATE | STR_NOALIGN, &len);
1914 if (!NT_STATUS_IS_OK(status)) {
1917 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1930 SCVAL(nameptr,0,len);
1932 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1935 case SMB_FIND_EA_LIST:
1937 struct ea_list *file_list = NULL;
1940 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1942 return NT_STATUS_INVALID_PARAMETER;
1944 if (requires_resume_key) {
1948 srv_put_dos_date2(p,0,create_date);
1949 srv_put_dos_date2(p,4,adate);
1950 srv_put_dos_date2(p,8,mdate);
1951 SIVAL(p,12,(uint32_t)file_size);
1952 SIVAL(p,16,(uint32_t)allocation_size);
1954 p += 22; /* p now points to the EA area. */
1956 status = get_ea_list_from_fsp(ctx,
1958 &ea_len, &file_list);
1959 if (!NT_STATUS_IS_OK(status)) {
1962 name_list = ea_list_union(name_list, file_list, &ea_len);
1964 /* We need to determine if this entry will fit in the space available. */
1965 /* Max string size is 255 bytes. */
1966 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1967 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1968 "(wanted %u, had %d)\n",
1969 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1971 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1974 /* Push the ea_data followed by the name. */
1975 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1977 status = srvstr_push(base_data, flags2,
1978 p + 1, fname, PTR_DIFF(end_data, p+1),
1979 STR_TERMINATE | STR_NOALIGN, &len);
1980 if (!NT_STATUS_IS_OK(status)) {
1983 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1996 SCVAL(nameptr,0,len);
1998 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2002 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2003 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2004 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2006 SIVAL(p,0,reskey); p += 4;
2007 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2008 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2009 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2010 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2011 SOFF_T(p,0,file_size); p += 8;
2012 SOFF_T(p,0,allocation_size); p += 8;
2013 SIVAL(p,0,mode); p += 4;
2014 q = p; p += 4; /* q is placeholder for name length. */
2015 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2016 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2018 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2019 SIVAL(p,0,ea_size); /* Extended attributes */
2022 /* Clear the short name buffer. This is
2023 * IMPORTANT as not doing so will trigger
2024 * a Win2k client bug. JRA.
2026 if (!was_8_3 && check_mangled_names) {
2027 char mangled_name[13]; /* mangled 8.3 name. */
2028 if (!name_to_8_3(fname,mangled_name,True,
2030 /* Error - mangle failed ! */
2031 memset(mangled_name,'\0',12);
2033 mangled_name[12] = 0;
2034 status = srvstr_push(base_data, flags2,
2035 p+2, mangled_name, 24,
2036 STR_UPPER|STR_UNICODE, &len);
2037 if (!NT_STATUS_IS_OK(status)) {
2041 memset(p + 2 + len,'\0',24 - len);
2048 status = srvstr_push(base_data, flags2, p,
2049 fname, PTR_DIFF(end_data, p),
2050 STR_TERMINATE_ASCII, &len);
2051 if (!NT_STATUS_IS_OK(status)) {
2057 len = PTR_DIFF(p, pdata);
2058 pad = (len + (align-1)) & ~(align-1);
2060 * offset to the next entry, the caller
2061 * will overwrite it for the last entry
2062 * that's why we always include the padding
2066 * set padding to zero
2069 memset(p, 0, pad - len);
2076 case SMB_FIND_FILE_DIRECTORY_INFO:
2077 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2079 SIVAL(p,0,reskey); p += 4;
2080 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2081 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2082 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2083 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2084 SOFF_T(p,0,file_size); p += 8;
2085 SOFF_T(p,0,allocation_size); p += 8;
2086 SIVAL(p,0,mode); p += 4;
2087 status = srvstr_push(base_data, flags2,
2088 p + 4, fname, PTR_DIFF(end_data, p+4),
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_FILE_FULL_DIRECTORY_INFO:
2116 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2118 SIVAL(p,0,reskey); p += 4;
2119 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2120 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2121 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2122 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2123 SOFF_T(p,0,file_size); p += 8;
2124 SOFF_T(p,0,allocation_size); p += 8;
2125 SIVAL(p,0,mode); p += 4;
2126 q = p; p += 4; /* q is placeholder for name length. */
2127 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2128 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2130 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2131 SIVAL(p,0,ea_size); /* Extended attributes */
2134 status = srvstr_push(base_data, flags2, p,
2135 fname, PTR_DIFF(end_data, p),
2136 STR_TERMINATE_ASCII, &len);
2137 if (!NT_STATUS_IS_OK(status)) {
2143 len = PTR_DIFF(p, pdata);
2144 pad = (len + (align-1)) & ~(align-1);
2146 * offset to the next entry, the caller
2147 * will overwrite it for the last entry
2148 * that's why we always include the padding
2152 * set padding to zero
2155 memset(p, 0, pad - len);
2162 case SMB_FIND_FILE_NAMES_INFO:
2163 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2165 SIVAL(p,0,reskey); p += 4;
2167 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2168 acl on a dir (tridge) */
2169 status = srvstr_push(base_data, flags2, p,
2170 fname, PTR_DIFF(end_data, p),
2171 STR_TERMINATE_ASCII, &len);
2172 if (!NT_STATUS_IS_OK(status)) {
2178 len = PTR_DIFF(p, pdata);
2179 pad = (len + (align-1)) & ~(align-1);
2181 * offset to the next entry, the caller
2182 * will overwrite it for the last entry
2183 * that's why we always include the padding
2187 * set padding to zero
2190 memset(p, 0, pad - len);
2197 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2198 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2200 SIVAL(p,0,reskey); p += 4;
2201 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2202 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2203 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2204 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2205 SOFF_T(p,0,file_size); p += 8;
2206 SOFF_T(p,0,allocation_size); p += 8;
2207 SIVAL(p,0,mode); p += 4;
2208 q = p; p += 4; /* q is placeholder for name length. */
2209 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2210 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2212 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2213 SIVAL(p,0,ea_size); /* Extended attributes */
2216 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2217 SBVAL(p,0,file_id); p += 8;
2218 status = srvstr_push(base_data, flags2, p,
2219 fname, PTR_DIFF(end_data, p),
2220 STR_TERMINATE_ASCII, &len);
2221 if (!NT_STATUS_IS_OK(status)) {
2227 len = PTR_DIFF(p, pdata);
2228 pad = (len + (align-1)) & ~(align-1);
2230 * offset to the next entry, the caller
2231 * will overwrite it for the last entry
2232 * that's why we always include the padding
2236 * set padding to zero
2239 memset(p, 0, pad - len);
2246 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2247 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2248 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2250 SIVAL(p,0,reskey); p += 4;
2251 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2252 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2253 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2254 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2255 SOFF_T(p,0,file_size); p += 8;
2256 SOFF_T(p,0,allocation_size); p += 8;
2257 SIVAL(p,0,mode); p += 4;
2258 q = p; p += 4; /* q is placeholder for name length */
2259 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2260 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2261 } else if (readdir_attr_data &&
2262 readdir_attr_data->type == RDATTR_AAPL) {
2264 * OS X specific SMB2 extension negotiated via
2265 * AAPL create context: return max_access in
2268 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2270 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2271 SIVAL(p,0,ea_size); /* Extended attributes */
2275 if (readdir_attr_data &&
2276 readdir_attr_data->type == RDATTR_AAPL) {
2278 * OS X specific SMB2 extension negotiated via
2279 * AAPL create context: return resource fork
2280 * length and compressed FinderInfo in
2283 * According to documentation short_name_len
2284 * should be 0, but on the wire behaviour
2285 * shows its set to 24 by clients.
2289 /* Resourefork length */
2290 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2292 /* Compressed FinderInfo */
2293 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2294 } else if (!was_8_3 && check_mangled_names) {
2295 char mangled_name[13]; /* mangled 8.3 name. */
2296 if (!name_to_8_3(fname,mangled_name,True,
2298 /* Error - mangle failed ! */
2299 memset(mangled_name,'\0',12);
2301 mangled_name[12] = 0;
2302 status = srvstr_push(base_data, flags2,
2303 p+2, mangled_name, 24,
2304 STR_UPPER|STR_UNICODE, &len);
2305 if (!NT_STATUS_IS_OK(status)) {
2310 memset(p + 2 + len,'\0',24 - len);
2314 /* Clear the short name buffer. This is
2315 * IMPORTANT as not doing so will trigger
2316 * a Win2k client bug. JRA.
2323 if (readdir_attr_data &&
2324 readdir_attr_data->type == RDATTR_AAPL) {
2326 * OS X specific SMB2 extension negotiated via
2327 * AAPL create context: return UNIX mode in
2330 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2331 SSVAL(p, 0, aapl_mode);
2337 SBVAL(p,0,file_id); p += 8;
2338 status = srvstr_push(base_data, flags2, p,
2339 fname, PTR_DIFF(end_data, p),
2340 STR_TERMINATE_ASCII, &len);
2341 if (!NT_STATUS_IS_OK(status)) {
2347 len = PTR_DIFF(p, pdata);
2348 pad = (len + (align-1)) & ~(align-1);
2350 * offset to the next entry, the caller
2351 * will overwrite it for the last entry
2352 * that's why we always include the padding
2356 * set padding to zero
2359 memset(p, 0, pad - len);
2366 /* CIFS UNIX Extension. */
2368 case SMB_FIND_FILE_UNIX:
2369 case SMB_FIND_FILE_UNIX_INFO2:
2371 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2373 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2375 if (info_level == SMB_FIND_FILE_UNIX) {
2376 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2377 p = store_file_unix_basic(conn, p,
2378 NULL, &smb_fname->st);
2379 status = srvstr_push(base_data, flags2, p,
2380 fname, PTR_DIFF(end_data, p),
2381 STR_TERMINATE, &len);
2382 if (!NT_STATUS_IS_OK(status)) {
2386 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2387 p = store_file_unix_basic_info2(conn, p,
2388 NULL, &smb_fname->st);
2391 status = srvstr_push(base_data, flags2, p, fname,
2392 PTR_DIFF(end_data, p), 0, &len);
2393 if (!NT_STATUS_IS_OK(status)) {
2396 SIVAL(nameptr, 0, len);
2401 len = PTR_DIFF(p, pdata);
2402 pad = (len + (align-1)) & ~(align-1);
2404 * offset to the next entry, the caller
2405 * will overwrite it for the last entry
2406 * that's why we always include the padding
2410 * set padding to zero
2413 memset(p, 0, pad - len);
2418 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2423 return NT_STATUS_INVALID_LEVEL;
2426 if (PTR_DIFF(p,pdata) > space_remaining) {
2427 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2428 "(wanted %u, had %d)\n",
2429 (unsigned int)PTR_DIFF(p,pdata),
2431 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2434 /* Setup the last entry pointer, as an offset from base_data */
2435 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2436 /* Advance the data pointer to the next slot */
2439 return NT_STATUS_OK;
2442 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2443 connection_struct *conn,
2444 struct dptr_struct *dirptr,
2446 const char *path_mask,
2449 int requires_resume_key,
2458 int space_remaining,
2459 struct smb_filename **_smb_fname,
2460 bool *got_exact_match,
2461 int *_last_entry_off,
2462 struct ea_list *name_list,
2463 struct file_id *file_id)
2466 const char *mask = NULL;
2467 long prev_dirpos = 0;
2470 struct smb_filename *smb_fname = NULL;
2471 struct smbd_dirptr_lanman2_state state;
2473 uint64_t last_entry_off = 0;
2475 enum mangled_names_options mangled_names;
2476 bool marshall_with_83_names;
2478 mangled_names = lp_mangled_names(conn->params);
2482 state.info_level = info_level;
2483 if (mangled_names != MANGLED_NAMES_NO) {
2484 state.check_mangled_names = true;
2486 state.has_wild = dptr_has_wild(dirptr);
2487 state.got_exact_match = false;
2488 state.case_sensitive = dptr_case_sensitive(dirptr);
2490 *got_exact_match = false;
2492 p = strrchr_m(path_mask,'/');
2503 ok = smbd_dirptr_get_entry(ctx,
2510 smbd_dirptr_lanman2_match_fn,
2511 smbd_dirptr_lanman2_mode_fn,
2518 return NT_STATUS_END_OF_FILE;
2521 *got_exact_match = state.got_exact_match;
2523 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2525 status = smbd_marshall_dir_entry(ctx,
2530 marshall_with_83_names,
2531 requires_resume_key,
2542 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2543 DEBUG(1,("Conversion error: illegal character: %s\n",
2544 smb_fname_str_dbg(smb_fname)));
2547 if (file_id != NULL) {
2548 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2551 if (!NT_STATUS_IS_OK(status) &&
2552 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2554 TALLOC_FREE(smb_fname);
2559 if (_smb_fname != NULL) {
2561 * smb_fname is already talloc'ed off ctx.
2562 * We just need to make sure we don't return
2563 * any stream_name, and replace base_name
2564 * with fname in case base_name got mangled.
2565 * This allows us to preserve any smb_fname->fsp
2566 * for asynchronous handle lookups.
2568 TALLOC_FREE(smb_fname->stream_name);
2569 TALLOC_FREE(smb_fname->base_name);
2570 smb_fname->base_name = talloc_strdup(smb_fname, fname);
2572 if (smb_fname->base_name == NULL) {
2573 TALLOC_FREE(smb_fname);
2575 return NT_STATUS_NO_MEMORY;
2577 *_smb_fname = smb_fname;
2579 TALLOC_FREE(smb_fname);
2583 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2584 dptr_SeekDir(dirptr, prev_dirpos);
2588 *_last_entry_off = last_entry_off;
2589 return NT_STATUS_OK;
2592 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2593 connection_struct *conn,
2594 struct dptr_struct *dirptr,
2596 const char *path_mask,
2599 bool requires_resume_key,
2605 int space_remaining,
2606 bool *got_exact_match,
2607 int *last_entry_off,
2608 struct ea_list *name_list)
2611 const bool do_pad = true;
2613 if (info_level >= 1 && info_level <= 3) {
2614 /* No alignment on earlier info levels. */
2618 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2619 path_mask, dirtype, info_level,
2620 requires_resume_key, dont_descend, ask_sharemode,
2621 true, align, do_pad,
2622 ppdata, base_data, end_data,
2626 last_entry_off, name_list, NULL);
2629 /****************************************************************************
2630 Reply to a TRANS2_FINDFIRST.
2631 ****************************************************************************/
2633 static void call_trans2findfirst(connection_struct *conn,
2634 struct smb_request *req,
2635 char **pparams, int total_params,
2636 char **ppdata, int total_data,
2637 unsigned int max_data_bytes)
2639 /* We must be careful here that we don't return more than the
2640 allowed number of data bytes. If this means returning fewer than
2641 maxentries then so be it. We assume that the redirector has
2642 enough room for the fixed number of parameter bytes it has
2644 struct smb_filename *smb_dname = NULL;
2645 char *params = *pparams;
2646 char *pdata = *ppdata;
2650 uint16_t findfirst_flags;
2651 bool close_after_first;
2653 bool requires_resume_key;
2655 char *directory = NULL;
2658 int last_entry_off=0;
2662 bool finished = False;
2663 bool dont_descend = False;
2664 bool out_of_space = False;
2665 int space_remaining;
2666 struct ea_list *ea_list = NULL;
2667 NTSTATUS ntstatus = NT_STATUS_OK;
2668 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2669 struct smbd_server_connection *sconn = req->sconn;
2670 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2671 bool backup_priv = false;
2672 bool as_root = false;
2673 files_struct *fsp = NULL;
2674 const struct loadparm_substitution *lp_sub =
2675 loadparm_s3_global_substitution();
2677 if (total_params < 13) {
2678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2682 dirtype = SVAL(params,0);
2683 maxentries = SVAL(params,2);
2684 findfirst_flags = SVAL(params,4);
2685 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2686 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2687 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2688 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2689 security_token_has_privilege(get_current_nttok(conn),
2692 info_level = SVAL(params,6);
2694 DBG_NOTICE("dirtype = %"PRIx32", maxentries = %d, "
2695 "close_after_first=%d, close_if_end = %d "
2696 "requires_resume_key = %d backup_priv = %d level = 0x%x, "
2697 "max_data_bytes = %d\n",
2702 requires_resume_key,
2708 /* W2K3 seems to treat zero as 1. */
2712 switch (info_level) {
2713 case SMB_FIND_INFO_STANDARD:
2714 case SMB_FIND_EA_SIZE:
2715 case SMB_FIND_EA_LIST:
2716 case SMB_FIND_FILE_DIRECTORY_INFO:
2717 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2718 case SMB_FIND_FILE_NAMES_INFO:
2719 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2720 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2721 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2723 case SMB_FIND_FILE_UNIX:
2724 case SMB_FIND_FILE_UNIX_INFO2:
2725 if (!lp_smb1_unix_extensions()) {
2726 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2729 if (!req->posix_pathnames) {
2730 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2735 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2739 if (req->posix_pathnames) {
2740 /* Always use filesystem for UNIX mtime query. */
2741 ask_sharemode = false;
2744 if (req->posix_pathnames) {
2745 srvstr_get_path_posix(talloc_tos(),
2754 srvstr_get_path(talloc_tos(),
2763 if (!NT_STATUS_IS_OK(ntstatus)) {
2764 reply_nterror(req, ntstatus);
2772 ntstatus = filename_convert_smb1_search_path(talloc_tos(),
2779 if (!NT_STATUS_IS_OK(ntstatus)) {
2780 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2781 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2782 ERRSRV, ERRbadpath);
2785 reply_nterror(req, ntstatus);
2789 TALLOC_FREE(directory);
2790 directory = smb_dname->base_name;
2792 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2794 if (info_level == SMB_FIND_EA_LIST) {
2797 if (total_data < 4) {
2798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2802 ea_size = IVAL(pdata,0);
2803 if (ea_size != total_data) {
2804 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2805 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2810 if (!lp_ea_support(SNUM(conn))) {
2811 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2815 /* Pull out the list of names. */
2816 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2823 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2828 *ppdata = (char *)SMB_REALLOC(
2829 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2830 if(*ppdata == NULL ) {
2831 reply_nterror(req, NT_STATUS_NO_MEMORY);
2835 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2837 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2840 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2841 /* Realloc the params space */
2842 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2843 if (*pparams == NULL) {
2844 reply_nterror(req, NT_STATUS_NO_MEMORY);
2850 * Open an fsp on this directory for the dptr.
2852 ntstatus = SMB_VFS_CREATE_FILE(
2855 smb_dname, /* dname */
2856 FILE_LIST_DIRECTORY, /* access_mask */
2858 FILE_SHARE_WRITE, /* share_access */
2859 FILE_OPEN, /* create_disposition*/
2860 FILE_DIRECTORY_FILE, /* create_options */
2861 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2862 NO_OPLOCK, /* oplock_request */
2864 0, /* allocation_size */
2865 0, /* private_flags */
2870 NULL, /* in_context */
2871 NULL);/* out_context */
2873 if (!NT_STATUS_IS_OK(ntstatus)) {
2874 DBG_ERR("failed to open directory %s\n",
2875 smb_fname_str_dbg(smb_dname));
2876 reply_nterror(req, ntstatus);
2880 /* Save the wildcard match and attribs we are using on this directory -
2881 needed as lanman2 assumes these are being saved between calls */
2883 ntstatus = dptr_create(conn,
2893 if (!NT_STATUS_IS_OK(ntstatus)) {
2895 * Use NULL here for the first parameter (req)
2896 * as this is not a client visible handle so
2897 * can'tbe part of an SMB1 chain.
2899 close_file_free(NULL, &fsp, NORMAL_CLOSE);
2900 reply_nterror(req, ntstatus);
2905 /* Remember this in case we have
2906 to do a findnext. */
2907 dptr_set_priv(fsp->dptr);
2910 dptr_num = dptr_dnum(fsp->dptr);
2911 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2913 /* We don't need to check for VOL here as this is returned by
2914 a different TRANS2 call. */
2916 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2917 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
2918 if (in_list(directory,
2919 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
2920 dptr_case_sensitive(fsp->dptr))) {
2921 dont_descend = True;
2925 space_remaining = max_data_bytes;
2926 out_of_space = False;
2928 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2929 bool got_exact_match = False;
2931 /* this is a heuristic to avoid seeking the dirptr except when
2932 absolutely necessary. It allows for a filename of about 40 chars */
2933 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2934 out_of_space = True;
2937 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2941 mask,dirtype,info_level,
2942 requires_resume_key,dont_descend,
2947 &last_entry_off, ea_list);
2948 if (NT_STATUS_EQUAL(ntstatus,
2949 NT_STATUS_ILLEGAL_CHARACTER)) {
2951 * Bad character conversion on name. Ignore this
2956 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2957 out_of_space = true;
2959 finished = !NT_STATUS_IS_OK(ntstatus);
2963 if (!finished && !out_of_space)
2967 * As an optimisation if we know we aren't looking
2968 * for a wildcard name (ie. the name matches the wildcard exactly)
2969 * then we can finish on any (first) match.
2970 * This speeds up large directory searches. JRA.
2976 /* Ensure space_remaining never goes -ve. */
2977 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2978 space_remaining = 0;
2979 out_of_space = true;
2981 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2985 /* Check if we can close the dirptr */
2986 if(close_after_first || (finished && close_if_end)) {
2987 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2989 close_file_free(NULL, &fsp, NORMAL_CLOSE);
2993 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2994 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2995 * the protocol level is less than NT1. Tested with smbclient. JRA.
2996 * This should fix the OS/2 client bug #2335.
2999 if(numentries == 0) {
3002 * We may have already closed the file in the
3003 * close_after_first or finished case above.
3006 close_file_free(NULL, &fsp, NORMAL_CLOSE);
3008 if (get_Protocol() < PROTOCOL_NT1) {
3009 reply_force_doserror(req, ERRDOS, ERRnofiles);
3012 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3013 ERRDOS, ERRbadfile);
3018 /* At this point pdata points to numentries directory entries. */
3020 /* Set up the return parameter block */
3021 SSVAL(params,0,dptr_num);
3022 SSVAL(params,2,numentries);
3023 SSVAL(params,4,finished);
3024 SSVAL(params,6,0); /* Never an EA error */
3025 SSVAL(params,8,last_entry_off);
3027 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3030 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3031 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3033 reply_nterror(req, NT_STATUS_NO_MEMORY);
3037 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3038 smb_fn_name(req->cmd),
3039 mask, directory, dirtype, numentries ) );
3042 * Force a name mangle here to ensure that the
3043 * mask as an 8.3 name is top of the mangled cache.
3044 * The reasons for this are subtle. Don't remove
3045 * this code unless you know what you are doing
3046 * (see PR#13758). JRA.
3049 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3050 char mangled_name[13];
3051 name_to_8_3(mask, mangled_name, True, conn->params);
3059 TALLOC_FREE(smb_dname);
3063 /****************************************************************************
3064 Reply to a TRANS2_FINDNEXT.
3065 ****************************************************************************/
3067 static void call_trans2findnext(connection_struct *conn,
3068 struct smb_request *req,
3069 char **pparams, int total_params,
3070 char **ppdata, int total_data,
3071 unsigned int max_data_bytes)
3073 /* We must be careful here that we don't return more than the
3074 allowed number of data bytes. If this means returning fewer than
3075 maxentries then so be it. We assume that the redirector has
3076 enough room for the fixed number of parameter bytes it has
3078 char *params = *pparams;
3079 char *pdata = *ppdata;
3083 uint16_t info_level;
3084 uint32_t resume_key;
3085 uint16_t findnext_flags;
3086 bool close_after_request;
3088 bool requires_resume_key;
3090 char *resume_name = NULL;
3091 const char *mask = NULL;
3092 const char *directory = NULL;
3096 int i, last_entry_off=0;
3097 bool finished = False;
3098 bool dont_descend = False;
3099 bool out_of_space = False;
3100 int space_remaining;
3101 struct ea_list *ea_list = NULL;
3102 NTSTATUS ntstatus = NT_STATUS_OK;
3103 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3104 TALLOC_CTX *ctx = talloc_tos();
3105 struct smbd_server_connection *sconn = req->sconn;
3106 bool backup_priv = false;
3107 bool as_root = false;
3108 files_struct *fsp = NULL;
3109 const struct loadparm_substitution *lp_sub =
3110 loadparm_s3_global_substitution();
3112 if (total_params < 13) {
3113 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3117 dptr_num = SVAL(params,0);
3118 maxentries = SVAL(params,2);
3119 info_level = SVAL(params,4);
3120 resume_key = IVAL(params,6);
3121 findnext_flags = SVAL(params,10);
3122 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3123 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3124 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3125 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3127 if (!continue_bit) {
3128 /* We only need resume_name if continue_bit is zero. */
3129 if (req->posix_pathnames) {
3130 srvstr_get_path_posix(ctx,
3139 srvstr_get_path(ctx,
3148 if (!NT_STATUS_IS_OK(ntstatus)) {
3149 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3150 complain (it thinks we're asking for the directory above the shared
3151 path or an invalid name). Catch this as the resume name is only compared, never used in
3152 a file access. JRA. */
3153 srvstr_pull_talloc(ctx, params, req->flags2,
3154 &resume_name, params+12,
3158 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3159 reply_nterror(req, ntstatus);
3165 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3166 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3167 resume_key = %d resume name = %s continue=%d level = %d\n",
3168 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3169 requires_resume_key, resume_key,
3170 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3173 /* W2K3 seems to treat zero as 1. */
3177 switch (info_level) {
3178 case SMB_FIND_INFO_STANDARD:
3179 case SMB_FIND_EA_SIZE:
3180 case SMB_FIND_EA_LIST:
3181 case SMB_FIND_FILE_DIRECTORY_INFO:
3182 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3183 case SMB_FIND_FILE_NAMES_INFO:
3184 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3185 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3186 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3188 case SMB_FIND_FILE_UNIX:
3189 case SMB_FIND_FILE_UNIX_INFO2:
3190 /* Always use filesystem for UNIX mtime query. */
3191 ask_sharemode = false;
3192 if (!lp_smb1_unix_extensions()) {
3193 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3196 if (!req->posix_pathnames) {
3197 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3202 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3206 if (info_level == SMB_FIND_EA_LIST) {
3209 if (total_data < 4) {
3210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3214 ea_size = IVAL(pdata,0);
3215 if (ea_size != total_data) {
3216 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3217 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3218 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3222 if (!lp_ea_support(SNUM(conn))) {
3223 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3227 /* Pull out the list of names. */
3228 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3235 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3236 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3240 *ppdata = (char *)SMB_REALLOC(
3241 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3242 if(*ppdata == NULL) {
3243 reply_nterror(req, NT_STATUS_NO_MEMORY);
3248 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3251 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3254 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3255 /* Realloc the params space */
3256 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3257 if(*pparams == NULL ) {
3258 reply_nterror(req, NT_STATUS_NO_MEMORY);
3264 /* Check that the dptr is valid */
3265 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3267 reply_nterror(req, STATUS_NO_MORE_FILES);
3271 directory = dptr_path(sconn, dptr_num);
3273 /* Get the wildcard mask from the dptr */
3274 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3275 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3276 reply_nterror(req, STATUS_NO_MORE_FILES);
3280 /* Get the attr mask from the dptr */
3281 dirtype = dptr_attr(sconn, dptr_num);
3283 backup_priv = dptr_get_priv(fsp->dptr);
3285 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3286 "backup_priv = %d\n",
3287 dptr_num, mask, dirtype,
3289 dptr_TellDir(fsp->dptr),
3292 /* We don't need to check for VOL here as this is returned by
3293 a different TRANS2 call. */
3295 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3296 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3297 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),
3298 dptr_case_sensitive(fsp->dptr)))
3299 dont_descend = True;
3302 space_remaining = max_data_bytes;
3303 out_of_space = False;
3311 * Seek to the correct position. We no longer use the resume key but
3312 * depend on the last file name instead.
3315 if(!continue_bit && resume_name && *resume_name) {
3317 bool posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
3319 long current_pos = 0;
3321 * Remember, name_to_8_3 is called by
3322 * get_lanman2_dir_entry(), so the resume name
3323 * could be mangled. Ensure we check the unmangled name.
3327 mangle_is_mangled(resume_name, conn->params)) {
3328 char *new_resume_name = NULL;
3329 mangle_lookup_name_from_8_3(ctx,
3333 if (new_resume_name) {
3334 resume_name = new_resume_name;
3339 * Fix for NT redirector problem triggered by resume key indexes
3340 * changing between directory scans. We now return a resume key of 0
3341 * and instead look for the filename to continue from (also given
3342 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3343 * findfirst/findnext (as is usual) then the directory pointer
3344 * should already be at the correct place.
3347 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3348 } /* end if resume_name && !continue_bit */
3350 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3351 bool got_exact_match = False;
3353 /* this is a heuristic to avoid seeking the fsp->dptr except when
3354 absolutely necessary. It allows for a filename of about 40 chars */
3355 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3356 out_of_space = True;
3359 ntstatus = get_lanman2_dir_entry(ctx,
3363 mask,dirtype,info_level,
3364 requires_resume_key,dont_descend,
3369 &last_entry_off, ea_list);
3370 if (NT_STATUS_EQUAL(ntstatus,
3371 NT_STATUS_ILLEGAL_CHARACTER)) {
3373 * Bad character conversion on name. Ignore this
3378 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3379 out_of_space = true;
3381 finished = !NT_STATUS_IS_OK(ntstatus);
3385 if (!finished && !out_of_space)
3389 * As an optimisation if we know we aren't looking
3390 * for a wildcard name (ie. the name matches the wildcard exactly)
3391 * then we can finish on any (first) match.
3392 * This speeds up large directory searches. JRA.
3398 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3401 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3402 smb_fn_name(req->cmd),
3403 mask, directory, dirtype, numentries ) );
3405 /* Check if we can close the fsp->dptr */
3406 if(close_after_request || (finished && close_if_end)) {
3407 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3409 close_file_free(NULL, &fsp, NORMAL_CLOSE);
3416 /* Set up the return parameter block */
3417 SSVAL(params,0,numentries);
3418 SSVAL(params,2,finished);
3419 SSVAL(params,4,0); /* Never an EA error */
3420 SSVAL(params,6,last_entry_off);
3422 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3428 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3430 const struct loadparm_substitution *lp_sub =
3431 loadparm_s3_global_substitution();
3433 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3437 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3439 SMB_ASSERT(extended_info != NULL);
3441 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3442 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3443 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3444 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3445 #ifdef SAMBA_VERSION_REVISION
3446 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3448 extended_info->samba_subversion = 0;
3449 #ifdef SAMBA_VERSION_RC_RELEASE
3450 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3452 #ifdef SAMBA_VERSION_PRE_RELEASE
3453 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3456 #ifdef SAMBA_VERSION_VENDOR_PATCH
3457 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3459 extended_info->samba_gitcommitdate = 0;
3460 #ifdef SAMBA_VERSION_COMMIT_TIME
3461 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3464 memset(extended_info->samba_version_string, 0,
3465 sizeof(extended_info->samba_version_string));
3467 snprintf (extended_info->samba_version_string,
3468 sizeof(extended_info->samba_version_string),
3469 "%s", samba_version_string());
3472 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3473 connection_struct *conn,
3474 TALLOC_CTX *mem_ctx,
3475 uint16_t info_level,
3477 unsigned int max_data_bytes,
3478 size_t *fixed_portion,
3479 struct smb_filename *fname,
3483 const struct loadparm_substitution *lp_sub =
3484 loadparm_s3_global_substitution();
3485 char *pdata, *end_data;
3488 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3489 int snum = SNUM(conn);
3490 const char *fstype = lp_fstype(SNUM(conn));
3491 const char *filename = NULL;
3492 const uint64_t bytes_per_sector = 512;
3493 uint32_t additional_flags = 0;
3494 struct smb_filename smb_fname;
3496 NTSTATUS status = NT_STATUS_OK;
3499 if (fname == NULL || fname->base_name == NULL) {
3502 filename = fname->base_name;
3506 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3507 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3508 "info level (0x%x) on IPC$.\n",
3509 (unsigned int)info_level));
3510 return NT_STATUS_ACCESS_DENIED;
3514 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3516 smb_fname = (struct smb_filename) {
3517 .base_name = discard_const_p(char, filename),
3518 .flags = fname ? fname->flags : 0,
3519 .twrp = fname ? fname->twrp : 0,
3522 if(info_level != SMB_FS_QUOTA_INFORMATION
3523 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3524 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3525 return map_nt_error_from_unix(errno);
3530 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3531 return NT_STATUS_INVALID_PARAMETER;
3534 *ppdata = (char *)SMB_REALLOC(
3535 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3536 if (*ppdata == NULL) {
3537 return NT_STATUS_NO_MEMORY;
3541 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3542 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3546 switch (info_level) {
3547 case SMB_INFO_ALLOCATION:
3549 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3551 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3553 if (df_ret == (uint64_t)-1) {
3554 return map_nt_error_from_unix(errno);
3557 block_size = lp_block_size(snum);
3558 if (bsize < block_size) {
3559 uint64_t factor = block_size/bsize;
3564 if (bsize > block_size) {
3565 uint64_t factor = bsize/block_size;
3570 sectors_per_unit = bsize/bytes_per_sector;
3572 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3573 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3574 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3577 * For large drives, return max values and not modulo.
3579 dsize = MIN(dsize, UINT32_MAX);
3580 dfree = MIN(dfree, UINT32_MAX);
3582 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3583 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3584 SIVAL(pdata,l1_cUnit,dsize);
3585 SIVAL(pdata,l1_cUnitAvail,dfree);
3586 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3590 case SMB_INFO_VOLUME:
3591 /* Return volume name */
3593 * Add volume serial number - hash of a combination of
3594 * the called hostname and the service name.
3596 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3598 * Win2k3 and previous mess this up by sending a name length
3599 * one byte short. I believe only older clients (OS/2 Win9x) use
3600 * this call so try fixing this by adding a terminating null to
3601 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3603 status = srvstr_push(
3605 pdata+l2_vol_szVolLabel, vname,
3606 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3607 STR_NOALIGN|STR_TERMINATE, &len);
3608 if (!NT_STATUS_IS_OK(status)) {
3611 SCVAL(pdata,l2_vol_cch,len);
3612 data_len = l2_vol_szVolLabel + len;
3613 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3614 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3615 (unsigned)len, vname));
3618 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3619 case SMB_FS_ATTRIBUTE_INFORMATION:
3621 additional_flags = 0;
3622 #if defined(HAVE_SYS_QUOTAS)
3623 additional_flags |= FILE_VOLUME_QUOTAS;
3626 if(lp_nt_acl_support(SNUM(conn))) {
3627 additional_flags |= FILE_PERSISTENT_ACLS;
3630 /* Capabilities are filled in at connection time through STATVFS call */
3631 additional_flags |= conn->fs_capabilities;
3632 additional_flags |= lp_parm_int(conn->params->service,
3633 "share", "fake_fscaps",
3636 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3637 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3638 additional_flags); /* FS ATTRIBUTES */
3640 SIVAL(pdata,4,255); /* Max filename component length */
3641 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3642 and will think we can't do long filenames */
3643 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3644 PTR_DIFF(end_data, pdata+12),
3646 if (!NT_STATUS_IS_OK(status)) {
3650 data_len = 12 + len;
3651 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3652 /* the client only requested a portion of the
3654 data_len = max_data_bytes;
3655 status = STATUS_BUFFER_OVERFLOW;
3657 *fixed_portion = 16;
3660 case SMB_QUERY_FS_LABEL_INFO:
3661 case SMB_FS_LABEL_INFORMATION:
3662 status = srvstr_push(pdata, flags2, pdata+4, vname,
3663 PTR_DIFF(end_data, pdata+4), 0, &len);
3664 if (!NT_STATUS_IS_OK(status)) {
3671 case SMB_QUERY_FS_VOLUME_INFO:
3672 case SMB_FS_VOLUME_INFORMATION:
3675 * Add volume serial number - hash of a combination of
3676 * the called hostname and the service name.
3678 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
3679 (str_checksum(get_local_machine_name())<<16));
3681 /* Max label len is 32 characters. */
3682 status = srvstr_push(pdata, flags2, pdata+18, vname,
3683 PTR_DIFF(end_data, pdata+18),
3685 if (!NT_STATUS_IS_OK(status)) {
3688 SIVAL(pdata,12,len);
3691 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3692 (int)strlen(vname),vname,
3693 lp_servicename(talloc_tos(), lp_sub, snum)));
3694 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3695 /* the client only requested a portion of the
3697 data_len = max_data_bytes;
3698 status = STATUS_BUFFER_OVERFLOW;
3700 *fixed_portion = 24;
3703 case SMB_QUERY_FS_SIZE_INFO:
3704 case SMB_FS_SIZE_INFORMATION:
3706 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3708 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3710 if (df_ret == (uint64_t)-1) {
3711 return map_nt_error_from_unix(errno);
3713 block_size = lp_block_size(snum);
3714 if (bsize < block_size) {
3715 uint64_t factor = block_size/bsize;
3720 if (bsize > block_size) {
3721 uint64_t factor = bsize/block_size;
3726 sectors_per_unit = bsize/bytes_per_sector;
3727 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3728 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3729 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3730 SBIG_UINT(pdata,0,dsize);
3731 SBIG_UINT(pdata,8,dfree);
3732 SIVAL(pdata,16,sectors_per_unit);
3733 SIVAL(pdata,20,bytes_per_sector);
3734 *fixed_portion = 24;
3738 case SMB_FS_FULL_SIZE_INFORMATION:
3740 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3742 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3744 if (df_ret == (uint64_t)-1) {
3745 return map_nt_error_from_unix(errno);
3747 block_size = lp_block_size(snum);
3748 if (bsize < block_size) {
3749 uint64_t factor = block_size/bsize;
3754 if (bsize > block_size) {
3755 uint64_t factor = bsize/block_size;
3760 sectors_per_unit = bsize/bytes_per_sector;
3761 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3762 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3763 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3764 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3765 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3766 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3767 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3768 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3769 *fixed_portion = 32;
3773 case SMB_QUERY_FS_DEVICE_INFO:
3774 case SMB_FS_DEVICE_INFORMATION:
3776 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3778 if (!CAN_WRITE(conn)) {
3779 characteristics |= FILE_READ_ONLY_DEVICE;
3782 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3783 SIVAL(pdata,4,characteristics);
3788 #ifdef HAVE_SYS_QUOTAS
3789 case SMB_FS_QUOTA_INFORMATION:
3791 * what we have to send --metze:
3793 * Unknown1: 24 NULL bytes
3794 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3795 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3796 * Quota Flags: 2 byte :
3797 * Unknown3: 6 NULL bytes
3801 * details for Quota Flags:
3803 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3804 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3805 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3806 * 0x0001 Enable Quotas: enable quota for this fs
3810 /* we need to fake up a fsp here,
3811 * because its not send in this call
3814 SMB_NTQUOTA_STRUCT quotas;
3817 ZERO_STRUCT(quotas);
3820 fsp.fnum = FNUM_FIELD_INVALID;
3823 if (get_current_uid(conn) != 0) {
3824 DEBUG(0,("get_user_quota: access_denied "
3825 "service [%s] user [%s]\n",
3826 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
3827 conn->session_info->unix_info->unix_name));
3828 return NT_STATUS_ACCESS_DENIED;
3831 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3833 if (!NT_STATUS_IS_OK(status)) {
3834 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3840 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3841 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3843 /* Unknown1 24 NULL bytes*/
3844 SBIG_UINT(pdata,0,(uint64_t)0);
3845 SBIG_UINT(pdata,8,(uint64_t)0);
3846 SBIG_UINT(pdata,16,(uint64_t)0);
3848 /* Default Soft Quota 8 bytes */
3849 SBIG_UINT(pdata,24,quotas.softlim);
3851 /* Default Hard Quota 8 bytes */
3852 SBIG_UINT(pdata,32,quotas.hardlim);
3854 /* Quota flag 2 bytes */
3855 SSVAL(pdata,40,quotas.qflags);
3857 /* Unknown3 6 NULL bytes */
3863 #endif /* HAVE_SYS_QUOTAS */
3864 case SMB_FS_OBJECTID_INFORMATION:
3866 unsigned char objid[16];
3867 struct smb_extended_info extended_info;
3868 memcpy(pdata,create_volume_objectid(conn, objid),16);
3869 samba_extended_info_version (&extended_info);
3870 SIVAL(pdata,16,extended_info.samba_magic);
3871 SIVAL(pdata,20,extended_info.samba_version);
3872 SIVAL(pdata,24,extended_info.samba_subversion);
3873 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3874 memcpy(pdata+36,extended_info.samba_version_string,28);
3879 case SMB_FS_SECTOR_SIZE_INFORMATION:
3883 * These values match a physical Windows Server 2012
3884 * share backed by NTFS atop spinning rust.
3886 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3887 /* logical_bytes_per_sector */
3888 SIVAL(pdata, 0, bytes_per_sector);
3889 /* phys_bytes_per_sector_atomic */
3890 SIVAL(pdata, 4, bytes_per_sector);
3891 /* phys_bytes_per_sector_perf */
3892 SIVAL(pdata, 8, bytes_per_sector);
3893 /* fs_effective_phys_bytes_per_sector_atomic */
3894 SIVAL(pdata, 12, bytes_per_sector);
3896 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3897 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3898 /* byte_off_sector_align */
3899 SIVAL(pdata, 20, 0);
3900 /* byte_off_partition_align */
3901 SIVAL(pdata, 24, 0);
3902 *fixed_portion = 28;
3908 * Query the version and capabilities of the CIFS UNIX extensions
3912 case SMB_QUERY_CIFS_UNIX_INFO:
3914 bool large_write = lp_min_receive_file_size() &&
3915 !smb1_srv_is_signing_active(xconn);
3916 bool large_read = !smb1_srv_is_signing_active(xconn);
3917 int encrypt_caps = 0;
3919 if (!lp_smb1_unix_extensions()) {
3920 return NT_STATUS_INVALID_LEVEL;
3923 switch (conn->encrypt_level) {
3924 case SMB_SIGNING_OFF:
3927 case SMB_SIGNING_DESIRED:
3928 case SMB_SIGNING_IF_REQUIRED:
3929 case SMB_SIGNING_DEFAULT:
3930 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3932 case SMB_SIGNING_REQUIRED:
3933 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3934 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3935 large_write = false;
3941 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3942 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3944 /* We have POSIX ACLs, pathname, encryption,
3945 * large read/write, and locking capability. */
3947 SBIG_UINT(pdata,4,((uint64_t)(
3948 CIFS_UNIX_POSIX_ACLS_CAP|
3949 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3950 CIFS_UNIX_FCNTL_LOCKS_CAP|
3951 CIFS_UNIX_EXTATTR_CAP|
3952 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3954 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3956 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3960 case SMB_QUERY_POSIX_FS_INFO:
3963 vfs_statvfs_struct svfs;
3965 if (!lp_smb1_unix_extensions()) {
3966 return NT_STATUS_INVALID_LEVEL;
3969 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3973 SIVAL(pdata,0,svfs.OptimalTransferSize);
3974 SIVAL(pdata,4,svfs.BlockSize);
3975 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3976 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3977 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3978 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3979 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3980 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3981 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3983 } else if (rc == EOPNOTSUPP) {
3984 return NT_STATUS_INVALID_LEVEL;
3985 #endif /* EOPNOTSUPP */
3987 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3988 return NT_STATUS_DOS(ERRSRV, ERRerror);
3993 case SMB_QUERY_POSIX_WHOAMI:
3999 if (!lp_smb1_unix_extensions()) {
4000 return NT_STATUS_INVALID_LEVEL;
4003 if (max_data_bytes < 40) {
4004 return NT_STATUS_BUFFER_TOO_SMALL;
4007 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4008 flags |= SMB_WHOAMI_GUEST;
4011 /* NOTE: 8 bytes for UID/GID, irrespective of native
4012 * platform size. This matches
4013 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4015 data_len = 4 /* flags */
4022 + 4 /* pad/reserved */
4023 + (conn->session_info->unix_token->ngroups * 8)
4025 + (conn->session_info->security_token->num_sids *
4029 SIVAL(pdata, 0, flags);
4030 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4032 (uint64_t)conn->session_info->unix_token->uid);
4033 SBIG_UINT(pdata, 16,
4034 (uint64_t)conn->session_info->unix_token->gid);
4037 if (data_len >= max_data_bytes) {
4038 /* Potential overflow, skip the GIDs and SIDs. */
4040 SIVAL(pdata, 24, 0); /* num_groups */
4041 SIVAL(pdata, 28, 0); /* num_sids */
4042 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4043 SIVAL(pdata, 36, 0); /* reserved */
4049 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4050 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4052 /* We walk the SID list twice, but this call is fairly
4053 * infrequent, and I don't expect that it's performance
4054 * sensitive -- jpeach
4056 for (i = 0, sid_bytes = 0;
4057 i < conn->session_info->security_token->num_sids; ++i) {
4058 sid_bytes += ndr_size_dom_sid(
4059 &conn->session_info->security_token->sids[i],
4063 /* SID list byte count */
4064 SIVAL(pdata, 32, sid_bytes);
4066 /* 4 bytes pad/reserved - must be zero */
4067 SIVAL(pdata, 36, 0);
4071 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4072 SBIG_UINT(pdata, data_len,
4073 (uint64_t)conn->session_info->unix_token->groups[i]);
4079 i < conn->session_info->security_token->num_sids; ++i) {
4080 int sid_len = ndr_size_dom_sid(
4081 &conn->session_info->security_token->sids[i],
4084 sid_linearize((uint8_t *)(pdata + data_len),
4086 &conn->session_info->security_token->sids[i]);
4087 data_len += sid_len;
4093 case SMB_MAC_QUERY_FS_INFO:
4095 * Thursby MAC extension... ONLY on NTFS filesystems
4096 * once we do streams then we don't need this
4098 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4100 SIVAL(pdata,84,0x100); /* Don't support mac... */
4106 return NT_STATUS_INVALID_LEVEL;
4109 *ret_data_len = data_len;
4113 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4114 struct smb_request *req,
4116 const DATA_BLOB *qdata)
4118 const struct loadparm_substitution *lp_sub =
4119 loadparm_s3_global_substitution();
4121 SMB_NTQUOTA_STRUCT quotas;
4123 ZERO_STRUCT(quotas);
4126 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4127 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4128 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
4129 conn->session_info->unix_info->unix_name));
4130 return NT_STATUS_ACCESS_DENIED;
4133 if (!check_fsp_ntquota_handle(conn, req,
4135 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4136 return NT_STATUS_INVALID_HANDLE;
4139 /* note: normally there're 48 bytes,
4140 * but we didn't use the last 6 bytes for now
4143 if (qdata->length < 42) {
4144 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4145 (unsigned int)qdata->length));
4146 return NT_STATUS_INVALID_PARAMETER;
4149 /* unknown_1 24 NULL bytes in pdata*/
4151 /* the soft quotas 8 bytes (uint64_t)*/
4152 quotas.softlim = BVAL(qdata->data,24);
4154 /* the hard quotas 8 bytes (uint64_t)*/
4155 quotas.hardlim = BVAL(qdata->data,32);
4157 /* quota_flags 2 bytes **/
4158 quotas.qflags = SVAL(qdata->data,40);
4160 /* unknown_2 6 NULL bytes follow*/
4162 /* now set the quotas */
4163 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4164 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4165 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4166 status = map_nt_error_from_unix(errno);
4168 status = NT_STATUS_OK;
4173 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4174 struct smb_request *req,
4175 TALLOC_CTX *mem_ctx,
4176 uint16_t info_level,
4178 const DATA_BLOB *pdata)
4180 switch (info_level) {
4181 case SMB_FS_QUOTA_INFORMATION:
4183 return smb_set_fsquota(conn,
4192 return NT_STATUS_INVALID_LEVEL;
4195 /****************************************************************************
4196 Reply to a TRANS2_QFSINFO (query filesystem info).
4197 ****************************************************************************/
4199 static void call_trans2qfsinfo(connection_struct *conn,
4200 struct smb_request *req,
4201 char **pparams, int total_params,
4202 char **ppdata, int total_data,
4203 unsigned int max_data_bytes)
4205 char *params = *pparams;
4206 uint16_t info_level;
4208 size_t fixed_portion;
4211 if (total_params < 2) {
4212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4216 info_level = SVAL(params,0);
4218 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4219 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4220 DEBUG(0,("call_trans2qfsinfo: encryption required "
4221 "and info level 0x%x sent.\n",
4222 (unsigned int)info_level));
4223 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4228 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4230 status = smbd_do_qfsinfo(req->xconn, conn, req,
4237 if (!NT_STATUS_IS_OK(status)) {
4238 reply_nterror(req, status);
4242 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4245 DEBUG( 4, ( "%s info_level = %d\n",
4246 smb_fn_name(req->cmd), info_level) );
4251 /****************************************************************************
4252 Reply to a TRANS2_SETFSINFO (set filesystem info).
4253 ****************************************************************************/
4255 static void call_trans2setfsinfo(connection_struct *conn,
4256 struct smb_request *req,
4257 char **pparams, int total_params,
4258 char **ppdata, int total_data,
4259 unsigned int max_data_bytes)
4261 const struct loadparm_substitution *lp_sub =
4262 loadparm_s3_global_substitution();
4263 struct smbXsrv_connection *xconn = req->xconn;
4264 char *pdata = *ppdata;
4265 char *params = *pparams;
4266 uint16_t info_level;
4268 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4269 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4272 if (total_params < 4) {
4273 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4279 info_level = SVAL(params,2);
4282 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4283 info_level != SMB_SET_CIFS_UNIX_INFO) {
4284 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4285 "info level (0x%x) on IPC$.\n",
4286 (unsigned int)info_level));
4287 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4292 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4293 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4294 DEBUG(0,("call_trans2setfsinfo: encryption required "
4295 "and info level 0x%x sent.\n",
4296 (unsigned int)info_level));
4297 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4302 switch(info_level) {
4303 case SMB_SET_CIFS_UNIX_INFO:
4304 if (!lp_smb1_unix_extensions()) {
4305 DEBUG(2,("call_trans2setfsinfo: "
4306 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4307 "unix extensions off\n"));
4309 NT_STATUS_INVALID_LEVEL);
4313 /* There should be 12 bytes of capabilities set. */
4314 if (total_data < 12) {
4317 NT_STATUS_INVALID_PARAMETER);
4320 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4321 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4322 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4323 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4324 /* Just print these values for now. */
4325 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4326 "major = %u, minor = %u cap_low = 0x%x, "
4328 (unsigned int)xconn->
4329 smb1.unix_info.client_major,
4330 (unsigned int)xconn->
4331 smb1.unix_info.client_minor,
4332 (unsigned int)xconn->
4333 smb1.unix_info.client_cap_low,
4334 (unsigned int)xconn->
4335 smb1.unix_info.client_cap_high));
4337 /* Here is where we must switch to posix pathname processing... */
4338 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4339 lp_set_posix_pathnames();
4340 mangle_change_to_posix();
4343 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4344 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4345 /* Client that knows how to do posix locks,
4346 * but not posix open/mkdir operations. Set a
4347 * default type for read/write checks. */
4349 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4354 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4357 size_t param_len = 0;
4358 size_t data_len = total_data;
4360 if (!lp_smb1_unix_extensions()) {
4363 NT_STATUS_INVALID_LEVEL);
4367 if (lp_server_smb_encrypt(SNUM(conn)) ==
4368 SMB_ENCRYPTION_OFF) {
4371 NT_STATUS_NOT_SUPPORTED);
4375 if (xconn->smb1.echo_handler.trusted_fde) {
4376 DEBUG( 2,("call_trans2setfsinfo: "
4377 "request transport encryption disabled"
4378 "with 'fork echo handler = yes'\n"));
4381 NT_STATUS_NOT_SUPPORTED);
4385 DEBUG( 4,("call_trans2setfsinfo: "
4386 "request transport encryption.\n"));
4388 status = srv_request_encryption_setup(conn,
4389 (unsigned char **)ppdata,
4391 (unsigned char **)pparams,
4394 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4395 !NT_STATUS_IS_OK(status)) {
4396 reply_nterror(req, status);
4400 send_trans2_replies(conn, req,
4408 if (NT_STATUS_IS_OK(status)) {
4409 /* Server-side transport
4410 * encryption is now *on*. */
4411 status = srv_encryption_start(conn);
4412 if (!NT_STATUS_IS_OK(status)) {
4413 char *reason = talloc_asprintf(talloc_tos(),
4414 "Failure in setting "
4415 "up encrypted transport: %s",
4417 exit_server_cleanly(reason);
4423 case SMB_FS_QUOTA_INFORMATION:
4427 .data = (uint8_t *)pdata,
4428 .length = total_data
4430 files_struct *fsp = NULL;
4431 fsp = file_fsp(req, SVAL(params,0));
4433 status = smb_set_fsquota(conn,
4437 if (!NT_STATUS_IS_OK(status)) {
4438 reply_nterror(req, status);
4444 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4446 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4452 * sending this reply works fine,
4453 * but I'm not sure it's the same
4454 * like windows do...
4457 reply_outbuf(req, 10, 0);
4460 #if defined(HAVE_POSIX_ACLS)
4461 /****************************************************************************
4462 Utility function to count the number of entries in a POSIX acl.
4463 ****************************************************************************/
4465 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4467 unsigned int ace_count = 0;
4468 int entry_id = SMB_ACL_FIRST_ENTRY;
4469 SMB_ACL_ENTRY_T entry;
4471 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4473 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4474 entry_id = SMB_ACL_NEXT_ENTRY;
4481 /****************************************************************************
4482 Utility function to marshall a POSIX acl into wire format.
4483 ****************************************************************************/
4485 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4487 int entry_id = SMB_ACL_FIRST_ENTRY;
4488 SMB_ACL_ENTRY_T entry;
4490 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4491 SMB_ACL_TAG_T tagtype;
4492 SMB_ACL_PERMSET_T permset;
4493 unsigned char perms = 0;
4494 unsigned int own_grp;
4497 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4498 entry_id = SMB_ACL_NEXT_ENTRY;
4501 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4502 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4506 if (sys_acl_get_permset(entry, &permset) == -1) {
4507 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4511 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4512 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4513 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4515 SCVAL(pdata,1,perms);
4518 case SMB_ACL_USER_OBJ:
4519 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4520 own_grp = (unsigned int)pst->st_ex_uid;
4521 SIVAL(pdata,2,own_grp);
4526 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4528 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4531 own_grp = (unsigned int)*puid;
4532 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4533 SIVAL(pdata,2,own_grp);
4537 case SMB_ACL_GROUP_OBJ:
4538 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4539 own_grp = (unsigned int)pst->st_ex_gid;
4540 SIVAL(pdata,2,own_grp);
4545 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4547 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4550 own_grp = (unsigned int)*pgid;
4551 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4552 SIVAL(pdata,2,own_grp);
4557 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4558 SIVAL(pdata,2,0xFFFFFFFF);
4559 SIVAL(pdata,6,0xFFFFFFFF);
4562 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4563 SIVAL(pdata,2,0xFFFFFFFF);
4564 SIVAL(pdata,6,0xFFFFFFFF);
4567 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4570 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4577 /****************************************************************************
4578 Store the FILE_UNIX_BASIC info.
4579 ****************************************************************************/
4581 static char *store_file_unix_basic(connection_struct *conn,
4584 const SMB_STRUCT_STAT *psbuf)
4588 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4589 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4591 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4594 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4597 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4598 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4599 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4602 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4606 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4610 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4613 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4614 devno = psbuf->st_ex_rdev;
4616 devno = psbuf->st_ex_dev;
4619 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4623 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4627 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4630 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4634 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4641 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4642 * the chflags(2) (or equivalent) flags.
4644 * XXX: this really should be behind the VFS interface. To do this, we would
4645 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4646 * Each VFS module could then implement its own mapping as appropriate for the
4647 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4649 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4653 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4657 { UF_IMMUTABLE, EXT_IMMUTABLE },
4661 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4665 { UF_HIDDEN, EXT_HIDDEN },
4668 /* Do not remove. We need to guarantee that this array has at least one
4669 * entry to build on HP-UX.
4675 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4676 uint32_t *smb_fflags, uint32_t *smb_fmask)
4680 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4681 *smb_fmask |= info2_flags_map[i].smb_fflag;
4682 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4683 *smb_fflags |= info2_flags_map[i].smb_fflag;
4688 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4689 const uint32_t smb_fflags,
4690 const uint32_t smb_fmask,
4693 uint32_t max_fmask = 0;
4696 *stat_fflags = psbuf->st_ex_flags;
4698 /* For each flags requested in smb_fmask, check the state of the
4699 * corresponding flag in smb_fflags and set or clear the matching
4703 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4704 max_fmask |= info2_flags_map[i].smb_fflag;
4705 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4706 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4707 *stat_fflags |= info2_flags_map[i].stat_fflag;
4709 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4714 /* If smb_fmask is asking to set any bits that are not supported by
4715 * our flag mappings, we should fail.
4717 if ((smb_fmask & max_fmask) != smb_fmask) {
4725 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4726 * of file flags and birth (create) time.
4728 static char *store_file_unix_basic_info2(connection_struct *conn,
4731 const SMB_STRUCT_STAT *psbuf)
4733 uint32_t file_flags = 0;
4734 uint32_t flags_mask = 0;
4736 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4738 /* Create (birth) time 64 bit */
4739 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4742 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4743 SIVAL(pdata, 0, file_flags); /* flags */
4744 SIVAL(pdata, 4, flags_mask); /* mask */
4750 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4751 const struct stream_struct *streams,
4753 unsigned int max_data_bytes,
4754 unsigned int *data_size)
4757 unsigned int ofs = 0;
4759 if (max_data_bytes < 32) {
4760 return NT_STATUS_INFO_LENGTH_MISMATCH;
4763 for (i = 0; i < num_streams; i++) {
4764 unsigned int next_offset;
4766 smb_ucs2_t *namebuf;
4768 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4769 streams[i].name, &namelen) ||
4772 return NT_STATUS_INVALID_PARAMETER;
4776 * name_buf is now null-terminated, we need to marshall as not
4783 * We cannot overflow ...
4785 if ((ofs + 24 + namelen) > max_data_bytes) {
4786 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4788 TALLOC_FREE(namebuf);
4789 return STATUS_BUFFER_OVERFLOW;
4792 SIVAL(data, ofs+4, namelen);
4793 SOFF_T(data, ofs+8, streams[i].size);
4794 SOFF_T(data, ofs+16, streams[i].alloc_size);
4795 memcpy(data+ofs+24, namebuf, namelen);
4796 TALLOC_FREE(namebuf);
4798 next_offset = ofs + 24 + namelen;
4800 if (i == num_streams-1) {
4801 SIVAL(data, ofs, 0);
4804 unsigned int align = ndr_align_size(next_offset, 8);
4806 if ((next_offset + align) > max_data_bytes) {
4807 DEBUG(10, ("refusing to overflow align "
4808 "reply at stream %u\n",
4810 TALLOC_FREE(namebuf);
4811 return STATUS_BUFFER_OVERFLOW;
4814 memset(data+next_offset, 0, align);
4815 next_offset += align;
4817 SIVAL(data, ofs, next_offset - ofs);
4824 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4828 return NT_STATUS_OK;
4831 static NTSTATUS smb_unix_read_symlink(connection_struct *conn,
4832 struct smb_request *req,
4833 struct smb_filename *smb_fname,
4835 unsigned int data_size_in,
4836 unsigned int *pdata_size_out)
4841 struct smb_filename *parent_fname = NULL;
4842 struct smb_filename *base_name = NULL;
4844 char *buffer = talloc_array(talloc_tos(), char, PATH_MAX+1);
4847 return NT_STATUS_NO_MEMORY;
4850 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
4851 smb_fname_str_dbg(smb_fname));
4853 if(!S_ISLNK(smb_fname->st.st_ex_mode)) {
4854 TALLOC_FREE(buffer);
4855 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4858 status = parent_pathref(talloc_tos(),
4863 if (!NT_STATUS_IS_OK(status)) {
4864 TALLOC_FREE(buffer);
4868 link_len = SMB_VFS_READLINKAT(conn,
4874 TALLOC_FREE(parent_fname);
4876 if (link_len == -1) {
4877 TALLOC_FREE(buffer);
4878 return map_nt_error_from_unix(errno);
4881 buffer[link_len] = 0;
4882 status = srvstr_push(pdata,
4889 TALLOC_FREE(buffer);
4890 if (!NT_STATUS_IS_OK(status)) {
4893 *pdata_size_out = len;
4895 return NT_STATUS_OK;
4898 #if defined(HAVE_POSIX_ACLS)
4899 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4900 struct smb_request *req,
4902 struct smb_filename *smb_fname,
4904 unsigned int data_size_in,
4905 unsigned int *pdata_size_out)
4907 SMB_ACL_T file_acl = NULL;
4908 SMB_ACL_T def_acl = NULL;
4909 uint16_t num_file_acls = 0;
4910 uint16_t num_def_acls = 0;
4911 unsigned int size_needed = 0;
4914 bool close_fsp = false;
4917 * Ensure we always operate on a file descriptor, not just
4920 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
4921 uint32_t access_mask = SEC_STD_READ_CONTROL|
4922 FILE_READ_ATTRIBUTES|
4923 FILE_WRITE_ATTRIBUTES;
4925 status = get_posix_fsp(conn,
4931 if (!NT_STATUS_IS_OK(status)) {
4937 SMB_ASSERT(fsp != NULL);
4939 status = refuse_symlink_fsp(fsp);
4940 if (!NT_STATUS_IS_OK(status)) {
4944 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
4947 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4948 DBG_INFO("ACLs not implemented on "
4949 "filesystem containing %s\n",
4951 status = NT_STATUS_NOT_IMPLEMENTED;
4955 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4957 * We can only have default POSIX ACLs on
4960 if (!fsp->fsp_flags.is_directory) {
4961 DBG_INFO("Non-directory open %s\n",
4963 status = NT_STATUS_INVALID_HANDLE;
4966 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4967 SMB_ACL_TYPE_DEFAULT,
4969 def_acl = free_empty_sys_acl(conn, def_acl);
4972 num_file_acls = count_acl_entries(conn, file_acl);
4973 num_def_acls = count_acl_entries(conn, def_acl);
4976 if (num_file_acls + num_def_acls < num_file_acls) {
4977 status = NT_STATUS_INVALID_PARAMETER;
4981 size_needed = num_file_acls + num_def_acls;
4984 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4985 * than UINT_MAX, so check by division.
4987 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4988 status = NT_STATUS_INVALID_PARAMETER;
4992 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4993 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4994 status = NT_STATUS_INVALID_PARAMETER;
4997 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4999 if ( data_size_in < size_needed) {
5000 DBG_INFO("data_size too small (%u) need %u\n",
5003 status = NT_STATUS_BUFFER_TOO_SMALL;
5007 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5008 SSVAL(pdata,2,num_file_acls);
5009 SSVAL(pdata,4,num_def_acls);
5010 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5012 ok = marshall_posix_acl(conn,
5017 status = NT_STATUS_INTERNAL_ERROR;
5020 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5022 ok = marshall_posix_acl(conn,
5027 status = NT_STATUS_INTERNAL_ERROR;
5031 *pdata_size_out = size_needed;
5032 status = NT_STATUS_OK;
5038 * Ensure the stat struct in smb_fname is up to
5039 * date. Structure copy.
5041 smb_fname->st = fsp->fsp_name->st;
5042 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
5045 TALLOC_FREE(file_acl);
5046 TALLOC_FREE(def_acl);
5051 /****************************************************************************
5052 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5053 ****************************************************************************/
5055 static void call_trans2qpipeinfo(connection_struct *conn,
5056 struct smb_request *req,
5057 unsigned int tran_call,
5058 char **pparams, int total_params,
5059 char **ppdata, int total_data,
5060 unsigned int max_data_bytes)
5062 char *params = *pparams;
5063 char *pdata = *ppdata;
5064 unsigned int data_size = 0;
5065 unsigned int param_size = 2;
5066 uint16_t info_level;
5070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5074 if (total_params < 4) {
5075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5079 fsp = file_fsp(req, SVAL(params,0));
5080 if (!fsp_is_np(fsp)) {
5081 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5085 info_level = SVAL(params,2);
5087 *pparams = (char *)SMB_REALLOC(*pparams,2);
5088 if (*pparams == NULL) {
5089 reply_nterror(req, NT_STATUS_NO_MEMORY);
5094 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5098 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5099 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5100 if (*ppdata == NULL ) {
5101 reply_nterror(req, NT_STATUS_NO_MEMORY);
5106 switch (info_level) {
5107 case SMB_FILE_STANDARD_INFORMATION:
5109 SOFF_T(pdata,0,4096LL);
5116 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5120 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5126 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5127 TALLOC_CTX *mem_ctx,
5128 struct smb_request *req,
5129 uint16_t info_level,
5131 struct smb_filename *smb_fname,
5132 bool delete_pending,
5133 struct timespec write_time_ts,
5134 struct ea_list *ea_list,
5135 int lock_data_count,
5138 unsigned int max_data_bytes,
5139 size_t *fixed_portion,
5141 unsigned int *pdata_size)
5143 char *pdata = *ppdata;
5144 char *dstart, *dend;
5145 unsigned int data_size;
5146 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5147 time_t create_time, mtime, atime, c_time;
5148 SMB_STRUCT_STAT *psbuf = NULL;
5155 uint64_t file_size = 0;
5157 uint64_t allocation_size = 0;
5158 uint64_t file_id = 0;
5159 uint32_t access_mask = 0;
5162 if (INFO_LEVEL_IS_UNIX(info_level)) {
5163 if (!lp_smb1_unix_extensions()) {
5164 return NT_STATUS_INVALID_LEVEL;
5166 if (!req->posix_pathnames) {
5167 return NT_STATUS_INVALID_LEVEL;
5171 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5172 smb_fname_str_dbg(smb_fname),
5174 info_level, max_data_bytes));
5177 * In case of querying a symlink in POSIX context,
5178 * fsp will be NULL. fdos_mode() deals with it.
5181 smb_fname = fsp->fsp_name;
5183 mode = fdos_mode(fsp);
5184 psbuf = &smb_fname->st;
5186 nlink = psbuf->st_ex_nlink;
5188 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5192 if ((nlink > 0) && delete_pending) {
5196 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5197 return NT_STATUS_INVALID_PARAMETER;
5200 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5201 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5202 if (*ppdata == NULL) {
5203 return NT_STATUS_NO_MEMORY;
5207 dend = dstart + data_size - 1;
5209 if (!is_omit_timespec(&write_time_ts) &&
5210 !INFO_LEVEL_IS_UNIX(info_level))
5212 update_stat_ex_mtime(psbuf, write_time_ts);
5215 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5216 mtime_ts = psbuf->st_ex_mtime;
5217 atime_ts = psbuf->st_ex_atime;
5218 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5220 if (lp_dos_filetime_resolution(SNUM(conn))) {
5221 dos_filetime_timespec(&create_time_ts);
5222 dos_filetime_timespec(&mtime_ts);
5223 dos_filetime_timespec(&atime_ts);
5224 dos_filetime_timespec(&ctime_ts);
5227 create_time = convert_timespec_to_time_t(create_time_ts);
5228 mtime = convert_timespec_to_time_t(mtime_ts);
5229 atime = convert_timespec_to_time_t(atime_ts);
5230 c_time = convert_timespec_to_time_t(ctime_ts);
5232 p = strrchr_m(smb_fname->base_name,'/');
5234 base_name = smb_fname->base_name;
5238 /* NT expects the name to be in an exact form of the *full*
5239 filename. See the trans2 torture test */
5240 if (ISDOT(base_name)) {
5241 dos_fname = talloc_strdup(mem_ctx, "\\");
5243 return NT_STATUS_NO_MEMORY;
5246 dos_fname = talloc_asprintf(mem_ctx,
5248 smb_fname->base_name);
5250 return NT_STATUS_NO_MEMORY;
5252 if (is_named_stream(smb_fname)) {
5253 dos_fname = talloc_asprintf(dos_fname, "%s",
5254 smb_fname->stream_name);
5256 return NT_STATUS_NO_MEMORY;
5260 string_replace(dos_fname, '/', '\\');
5263 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5265 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
5266 /* Do we have this path open ? */
5268 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5269 fsp1 = file_find_di_first(conn->sconn, fileid, true);
5270 if (fsp1 && fsp1->initial_allocation_size) {
5271 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5275 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5276 file_size = get_file_size_stat(psbuf);
5280 pos = fh_get_position_information(fsp->fh);
5284 access_mask = fsp->access_mask;
5286 /* GENERIC_EXECUTE mapping from Windows */
5287 access_mask = 0x12019F;
5290 /* This should be an index number - looks like
5293 I think this causes us to fail the IFSKIT
5294 BasicFileInformationTest. -tpot */
5295 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5299 switch (info_level) {
5300 case SMB_INFO_STANDARD:
5301 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5303 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5304 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5305 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5306 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5307 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5308 SSVAL(pdata,l1_attrFile,mode);
5311 case SMB_INFO_QUERY_EA_SIZE:
5313 unsigned int ea_size =
5314 estimate_ea_size(smb_fname->fsp);
5315 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5317 srv_put_dos_date2(pdata,0,create_time);
5318 srv_put_dos_date2(pdata,4,atime);
5319 srv_put_dos_date2(pdata,8,mtime); /* write time */
5320 SIVAL(pdata,12,(uint32_t)file_size);
5321 SIVAL(pdata,16,(uint32_t)allocation_size);
5322 SSVAL(pdata,20,mode);
5323 SIVAL(pdata,22,ea_size);
5327 case SMB_INFO_IS_NAME_VALID:
5328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5330 /* os/2 needs this ? really ?*/
5331 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5333 /* This is only reached for qpathinfo */
5337 case SMB_INFO_QUERY_EAS_FROM_LIST:
5339 size_t total_ea_len = 0;
5340 struct ea_list *ea_file_list = NULL;
5341 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5344 get_ea_list_from_fsp(mem_ctx,
5346 &total_ea_len, &ea_file_list);
5347 if (!NT_STATUS_IS_OK(status)) {
5351 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5353 if (!ea_list || (total_ea_len > data_size)) {
5355 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5359 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5363 case SMB_INFO_QUERY_ALL_EAS:
5365 /* We have data_size bytes to put EA's into. */
5366 size_t total_ea_len = 0;
5367 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5369 status = get_ea_list_from_fsp(mem_ctx,
5371 &total_ea_len, &ea_list);
5372 if (!NT_STATUS_IS_OK(status)) {
5376 if (!ea_list || (total_ea_len > data_size)) {
5378 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5382 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5386 case SMB2_FILE_FULL_EA_INFORMATION:
5388 /* We have data_size bytes to put EA's into. */
5389 size_t total_ea_len = 0;
5390 struct ea_list *ea_file_list = NULL;
5392 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5394 /*TODO: add filtering and index handling */
5397 get_ea_list_from_fsp(mem_ctx,
5399 &total_ea_len, &ea_file_list);
5400 if (!NT_STATUS_IS_OK(status)) {
5403 if (!ea_file_list) {
5404 return NT_STATUS_NO_EAS_ON_FILE;
5407 status = fill_ea_chained_buffer(mem_ctx,
5411 conn, ea_file_list);
5412 if (!NT_STATUS_IS_OK(status)) {
5418 case SMB_FILE_BASIC_INFORMATION:
5419 case SMB_QUERY_FILE_BASIC_INFO:
5421 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5423 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5429 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5430 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5431 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5432 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5433 SIVAL(pdata,32,mode);
5435 DEBUG(5,("SMB_QFBI - "));
5436 DEBUG(5,("create: %s ", ctime(&create_time)));
5437 DEBUG(5,("access: %s ", ctime(&atime)));
5438 DEBUG(5,("write: %s ", ctime(&mtime)));
5439 DEBUG(5,("change: %s ", ctime(&c_time)));
5440 DEBUG(5,("mode: %x\n", mode));
5441 *fixed_portion = data_size;
5444 case SMB_FILE_STANDARD_INFORMATION:
5445 case SMB_QUERY_FILE_STANDARD_INFO:
5447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5449 SOFF_T(pdata,0,allocation_size);
5450 SOFF_T(pdata,8,file_size);
5451 SIVAL(pdata,16,nlink);
5452 SCVAL(pdata,20,delete_pending?1:0);
5453 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5454 SSVAL(pdata,22,0); /* Padding. */
5455 *fixed_portion = 24;
5458 case SMB_FILE_EA_INFORMATION:
5459 case SMB_QUERY_FILE_EA_INFO:
5461 unsigned int ea_size =
5462 estimate_ea_size(smb_fname->fsp);
5463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5466 SIVAL(pdata,0,ea_size);
5470 /* Get the 8.3 name - used if NT SMB was negotiated. */
5471 case SMB_QUERY_FILE_ALT_NAME_INFO:
5472 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5474 char mangled_name[13];
5475 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5476 if (!name_to_8_3(base_name,mangled_name,
5477 True,conn->params)) {
5478 return NT_STATUS_NO_MEMORY;
5480 status = srvstr_push(dstart, flags2,
5481 pdata+4, mangled_name,
5482 PTR_DIFF(dend, pdata+4),
5484 if (!NT_STATUS_IS_OK(status)) {
5487 data_size = 4 + len;
5493 case SMB_QUERY_FILE_NAME_INFO:
5496 this must be *exactly* right for ACLs on mapped drives to work
5498 status = srvstr_push(dstart, flags2,
5500 PTR_DIFF(dend, pdata+4),
5502 if (!NT_STATUS_IS_OK(status)) {
5505 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5506 data_size = 4 + len;
5511 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5513 char *nfname = NULL;
5515 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5516 return NT_STATUS_INVALID_LEVEL;
5519 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5520 if (nfname == NULL) {
5521 return NT_STATUS_NO_MEMORY;
5524 if (ISDOT(nfname)) {
5527 string_replace(nfname, '/', '\\');
5529 if (fsp_is_alternate_stream(fsp)) {
5530 const char *s = smb_fname->stream_name;
5531 const char *e = NULL;
5534 SMB_ASSERT(s[0] != '\0');
5537 * smb_fname->stream_name is in form
5538 * of ':StrEam:$DATA', but we should only
5539 * append ':StrEam' here.
5542 e = strchr(&s[1], ':');
5548 nfname = talloc_strndup_append(nfname, s, n);
5549 if (nfname == NULL) {
5550 return NT_STATUS_NO_MEMORY;
5554 status = srvstr_push(dstart, flags2,
5556 PTR_DIFF(dend, pdata+4),
5558 if (!NT_STATUS_IS_OK(status)) {
5561 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5562 data_size = 4 + len;
5568 case SMB_FILE_ALLOCATION_INFORMATION:
5569 case SMB_QUERY_FILE_ALLOCATION_INFO:
5570 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5572 SOFF_T(pdata,0,allocation_size);
5575 case SMB_FILE_END_OF_FILE_INFORMATION:
5576 case SMB_QUERY_FILE_END_OF_FILEINFO:
5577 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5579 SOFF_T(pdata,0,file_size);
5582 case SMB_QUERY_FILE_ALL_INFO:
5583 case SMB_FILE_ALL_INFORMATION:
5585 unsigned int ea_size =
5586 estimate_ea_size(smb_fname->fsp);
5587 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5588 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5589 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5590 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5591 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5592 SIVAL(pdata,32,mode);
5593 SIVAL(pdata,36,0); /* padding. */
5595 SOFF_T(pdata,0,allocation_size);
5596 SOFF_T(pdata,8,file_size);
5597 SIVAL(pdata,16,nlink);
5598 SCVAL(pdata,20,delete_pending);
5599 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5602 SIVAL(pdata,0,ea_size);
5603 pdata += 4; /* EA info */
5604 status = srvstr_push(dstart, flags2,
5606 PTR_DIFF(dend, pdata+4),
5608 if (!NT_STATUS_IS_OK(status)) {
5613 data_size = PTR_DIFF(pdata,(*ppdata));
5614 *fixed_portion = 10;
5618 case SMB2_FILE_ALL_INFORMATION:
5620 unsigned int ea_size =
5621 estimate_ea_size(smb_fname->fsp);
5622 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5623 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5624 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5625 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5626 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5627 SIVAL(pdata, 0x20, mode);
5628 SIVAL(pdata, 0x24, 0); /* padding. */
5629 SBVAL(pdata, 0x28, allocation_size);
5630 SBVAL(pdata, 0x30, file_size);
5631 SIVAL(pdata, 0x38, nlink);
5632 SCVAL(pdata, 0x3C, delete_pending);
5633 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5634 SSVAL(pdata, 0x3E, 0); /* padding */
5635 SBVAL(pdata, 0x40, file_id);
5636 SIVAL(pdata, 0x48, ea_size);
5637 SIVAL(pdata, 0x4C, access_mask);
5638 SBVAL(pdata, 0x50, pos);
5639 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5640 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5644 status = srvstr_push(dstart, flags2,
5646 PTR_DIFF(dend, pdata+4),
5648 if (!NT_STATUS_IS_OK(status)) {
5653 data_size = PTR_DIFF(pdata,(*ppdata));
5654 *fixed_portion = 104;
5657 case SMB_FILE_INTERNAL_INFORMATION:
5659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5660 SBVAL(pdata, 0, file_id);
5665 case SMB_FILE_ACCESS_INFORMATION:
5666 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5667 SIVAL(pdata, 0, access_mask);
5672 case SMB_FILE_NAME_INFORMATION:
5673 /* Pathname with leading '\'. */
5676 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5677 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5678 SIVAL(pdata,0,byte_len);
5679 data_size = 4 + byte_len;
5683 case SMB_FILE_DISPOSITION_INFORMATION:
5684 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5686 SCVAL(pdata,0,delete_pending);
5690 case SMB_FILE_POSITION_INFORMATION:
5691 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5693 SOFF_T(pdata,0,pos);
5697 case SMB_FILE_MODE_INFORMATION:
5698 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5699 SIVAL(pdata,0,mode);
5704 case SMB_FILE_ALIGNMENT_INFORMATION:
5705 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5706 SIVAL(pdata,0,0); /* No alignment needed. */
5712 * NT4 server just returns "invalid query" to this - if we try
5713 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5716 /* The first statement above is false - verified using Thursby
5717 * client against NT4 -- gcolley.
5719 case SMB_QUERY_FILE_STREAM_INFO:
5720 case SMB_FILE_STREAM_INFORMATION: {
5721 unsigned int num_streams = 0;
5722 struct stream_struct *streams = NULL;
5724 DEBUG(10,("smbd_do_qfilepathinfo: "
5725 "SMB_FILE_STREAM_INFORMATION\n"));
5727 if (is_ntfs_stream_smb_fname(smb_fname)) {
5728 return NT_STATUS_INVALID_PARAMETER;
5731 status = vfs_fstreaminfo(fsp,
5736 if (!NT_STATUS_IS_OK(status)) {
5737 DEBUG(10, ("could not get stream info: %s\n",
5738 nt_errstr(status)));
5742 status = marshall_stream_info(num_streams, streams,
5743 pdata, max_data_bytes,
5746 if (!NT_STATUS_IS_OK(status)) {
5747 DEBUG(10, ("marshall_stream_info failed: %s\n",
5748 nt_errstr(status)));
5749 TALLOC_FREE(streams);
5753 TALLOC_FREE(streams);
5755 *fixed_portion = 32;
5759 case SMB_QUERY_COMPRESSION_INFO:
5760 case SMB_FILE_COMPRESSION_INFORMATION:
5761 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5762 SOFF_T(pdata,0,file_size);
5763 SIVAL(pdata,8,0); /* ??? */
5764 SIVAL(pdata,12,0); /* ??? */
5766 *fixed_portion = 16;
5769 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5770 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5771 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5772 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5773 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5774 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5775 SOFF_T(pdata,32,allocation_size);
5776 SOFF_T(pdata,40,file_size);
5777 SIVAL(pdata,48,mode);
5778 SIVAL(pdata,52,0); /* ??? */
5780 *fixed_portion = 56;
5783 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5784 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5785 SIVAL(pdata,0,mode);
5792 * CIFS UNIX Extensions.
5795 case SMB_QUERY_FILE_UNIX_BASIC:
5797 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5798 data_size = PTR_DIFF(pdata,(*ppdata));
5800 DEBUG(4,("smbd_do_qfilepathinfo: "
5801 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5802 dump_data(4, (uint8_t *)(*ppdata), data_size);
5806 case SMB_QUERY_FILE_UNIX_INFO2:
5808 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5809 data_size = PTR_DIFF(pdata,(*ppdata));
5813 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5815 for (i=0; i<100; i++)
5816 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5822 case SMB_QUERY_FILE_UNIX_LINK:
5824 status = smb_unix_read_symlink(conn,
5830 if (!NT_STATUS_IS_OK(status)) {
5836 #if defined(HAVE_POSIX_ACLS)
5837 case SMB_QUERY_POSIX_ACL:
5839 status = smb_query_posix_acl(conn,
5846 if (!NT_STATUS_IS_OK(status)) {
5854 case SMB_QUERY_POSIX_LOCK:
5859 enum brl_type lock_type;
5861 /* We need an open file with a real fd for this. */
5863 fsp->fsp_flags.is_pathref ||
5864 fsp_get_io_fd(fsp) == -1)
5866 return NT_STATUS_INVALID_LEVEL;
5869 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5870 return NT_STATUS_INVALID_PARAMETER;
5873 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5874 case POSIX_LOCK_TYPE_READ:
5875 lock_type = READ_LOCK;
5877 case POSIX_LOCK_TYPE_WRITE:
5878 lock_type = WRITE_LOCK;
5880 case POSIX_LOCK_TYPE_UNLOCK:
5882 /* There's no point in asking for an unlock... */
5883 return NT_STATUS_INVALID_PARAMETER;
5886 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5887 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5888 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5890 status = query_lock(fsp,
5897 if (ERROR_WAS_LOCK_DENIED(status)) {
5898 /* Here we need to report who has it locked... */
5899 data_size = POSIX_LOCK_DATA_SIZE;
5901 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5902 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5903 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5904 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5905 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5907 } else if (NT_STATUS_IS_OK(status)) {
5908 /* For success we just return a copy of what we sent
5909 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5910 data_size = POSIX_LOCK_DATA_SIZE;
5911 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5912 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5920 return NT_STATUS_INVALID_LEVEL;
5923 *pdata_size = data_size;
5924 return NT_STATUS_OK;
5927 /****************************************************************************
5928 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5929 file name or file id).
5930 ****************************************************************************/
5932 static void call_trans2qfilepathinfo(connection_struct *conn,
5933 struct smb_request *req,
5934 unsigned int tran_call,
5935 char **pparams, int total_params,
5936 char **ppdata, int total_data,
5937 unsigned int max_data_bytes)
5939 char *params = *pparams;
5940 char *pdata = *ppdata;
5941 uint16_t info_level;
5942 unsigned int data_size = 0;
5943 unsigned int param_size = 2;
5944 struct smb_filename *smb_fname = NULL;
5945 bool delete_pending = False;
5946 struct timespec write_time_ts;
5947 files_struct *fsp = NULL;
5948 struct file_id fileid;
5949 struct ea_list *ea_list = NULL;
5950 int lock_data_count = 0;
5951 char *lock_data = NULL;
5952 size_t fixed_portion;
5953 NTSTATUS status = NT_STATUS_OK;
5957 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5961 ZERO_STRUCT(write_time_ts);
5963 if (tran_call == TRANSACT2_QFILEINFO) {
5964 if (total_params < 4) {
5965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5970 call_trans2qpipeinfo(conn, req, tran_call,
5971 pparams, total_params,
5977 fsp = file_fsp(req, SVAL(params,0));
5978 info_level = SVAL(params,2);
5980 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5982 if (INFO_LEVEL_IS_UNIX(info_level)) {
5983 if (!lp_smb1_unix_extensions()) {
5984 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5987 if (!req->posix_pathnames) {
5988 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5993 /* Initial check for valid fsp ptr. */
5994 if (!check_fsp_open(conn, req, fsp)) {
5998 smb_fname = fsp->fsp_name;
6000 if(fsp->fake_file_handle) {
6002 * This is actually for the QUOTA_FAKE_FILE --metze
6005 /* We know this name is ok, it's already passed the checks. */
6007 } else if(fsp_get_pathref_fd(fsp) == -1) {
6009 * This is actually a QFILEINFO on a directory
6010 * handle (returned from an NT SMB). NT5.0 seems
6011 * to do this call. JRA.
6013 ret = vfs_stat(conn, smb_fname);
6015 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
6016 smb_fname_str_dbg(smb_fname),
6019 map_nt_error_from_unix(errno));
6023 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6024 fileid = vfs_file_id_from_sbuf(
6025 conn, &smb_fname->st);
6026 get_file_infos(fileid, fsp->name_hash,
6032 * Original code - this is an open file.
6034 status = vfs_stat_fsp(fsp);
6035 if (!NT_STATUS_IS_OK(status)) {
6036 DEBUG(3, ("fstat of %s failed (%s)\n",
6037 fsp_fnum_dbg(fsp), nt_errstr(status)));
6038 reply_nterror(req, status);
6041 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6042 fileid = vfs_file_id_from_sbuf(
6043 conn, &smb_fname->st);
6044 get_file_infos(fileid, fsp->name_hash,
6053 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6056 if (total_params < 7) {
6057 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6061 info_level = SVAL(params,0);
6063 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6065 if (INFO_LEVEL_IS_UNIX(info_level)) {
6066 if (!lp_smb1_unix_extensions()) {
6067 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6070 if (!req->posix_pathnames) {
6071 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6076 if (req->posix_pathnames) {
6077 srvstr_get_path_posix(req,
6086 srvstr_get_path(req,
6095 if (!NT_STATUS_IS_OK(status)) {
6096 reply_nterror(req, status);
6100 status = filename_convert(req,
6106 if (!NT_STATUS_IS_OK(status)) {
6107 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6108 reply_botherror(req,
6109 NT_STATUS_PATH_NOT_COVERED,
6110 ERRSRV, ERRbadpath);
6113 reply_nterror(req, status);
6118 * qpathinfo must operate on an existing file, so we
6119 * can exit early if filename_convert() returned the "new file"
6120 * NT_STATUS_OK, !VALID_STAT case.
6123 if (!VALID_STAT(smb_fname->st)) {
6124 reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
6129 * smb_fname->fsp may be NULL if smb_fname points at a symlink
6130 * and we're in POSIX context, so be careful when using fsp
6131 * below, it can still be NULL.
6133 fsp = smb_fname->fsp;
6135 /* If this is a stream, check if there is a delete_pending. */
6136 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6137 && is_ntfs_stream_smb_fname(smb_fname)) {
6138 struct smb_filename *smb_fname_base;
6140 /* Create an smb_filename with stream_name == NULL. */
6141 smb_fname_base = synthetic_smb_fname(
6143 smb_fname->base_name,
6148 if (smb_fname_base == NULL) {
6149 reply_nterror(req, NT_STATUS_NO_MEMORY);
6153 ret = vfs_stat(conn, smb_fname_base);
6155 DBG_NOTICE("vfs_stat of %s failed "
6157 smb_fname_str_dbg(smb_fname_base),
6159 TALLOC_FREE(smb_fname_base);
6161 map_nt_error_from_unix(errno));
6165 status = file_name_hash(conn,
6166 smb_fname_str_dbg(smb_fname_base),
6168 if (!NT_STATUS_IS_OK(status)) {
6169 TALLOC_FREE(smb_fname_base);
6170 reply_nterror(req, status);
6174 fileid = vfs_file_id_from_sbuf(conn,
6175 &smb_fname_base->st);
6176 TALLOC_FREE(smb_fname_base);
6177 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6178 if (delete_pending) {
6179 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6184 status = file_name_hash(conn,
6185 smb_fname_str_dbg(smb_fname),
6187 if (!NT_STATUS_IS_OK(status)) {
6188 reply_nterror(req, status);
6192 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6193 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6194 get_file_infos(fileid, name_hash, &delete_pending,
6198 if (delete_pending) {
6199 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6204 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6205 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6207 info_level,tran_call,total_data));
6209 /* Pull out any data sent here before we realloc. */
6210 switch (info_level) {
6211 case SMB_INFO_QUERY_EAS_FROM_LIST:
6213 /* Pull any EA list from the data portion. */
6216 if (total_data < 4) {
6218 req, NT_STATUS_INVALID_PARAMETER);
6221 ea_size = IVAL(pdata,0);
6223 if (total_data > 0 && ea_size != total_data) {
6224 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6225 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6227 req, NT_STATUS_INVALID_PARAMETER);
6231 if (!lp_ea_support(SNUM(conn))) {
6232 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6236 /* Pull out the list of names. */
6237 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6240 req, NT_STATUS_INVALID_PARAMETER);
6246 case SMB_QUERY_POSIX_LOCK:
6249 fsp->fsp_flags.is_pathref ||
6250 fsp_get_io_fd(fsp) == -1)
6252 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6256 if (total_data != POSIX_LOCK_DATA_SIZE) {
6258 req, NT_STATUS_INVALID_PARAMETER);
6262 /* Copy the lock range data. */
6263 lock_data = (char *)talloc_memdup(
6264 req, pdata, total_data);
6266 reply_nterror(req, NT_STATUS_NO_MEMORY);
6269 lock_data_count = total_data;
6276 *pparams = (char *)SMB_REALLOC(*pparams,2);
6277 if (*pparams == NULL) {
6278 reply_nterror(req, NT_STATUS_NO_MEMORY);
6285 * draft-leach-cifs-v1-spec-02.txt
6286 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6289 * The requested information is placed in the Data portion of the
6290 * transaction response. For the information levels greater than 0x100,
6291 * the transaction response has 1 parameter word which should be
6292 * ignored by the client.
6294 * However Windows only follows this rule for the IS_NAME_VALID call.
6296 switch (info_level) {
6297 case SMB_INFO_IS_NAME_VALID:
6302 if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
6304 * We use levels that start with 0xFF00
6305 * internally to represent SMB2 specific levels
6307 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6311 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6313 delete_pending, write_time_ts,
6315 lock_data_count, lock_data,
6316 req->flags2, max_data_bytes,
6318 ppdata, &data_size);
6319 if (!NT_STATUS_IS_OK(status)) {
6320 if (open_was_deferred(req->xconn, req->mid)) {
6321 /* We have re-scheduled this call. */
6324 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6325 bool ok = defer_smb1_sharing_violation(req);
6330 reply_nterror(req, status);
6333 if (fixed_portion > max_data_bytes) {
6334 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6338 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6344 /****************************************************************************
6345 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6347 ****************************************************************************/
6349 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6350 connection_struct *conn,
6351 struct smb_request *req,
6352 bool overwrite_if_exists,
6353 const struct smb_filename *smb_fname_old,
6354 struct smb_filename *smb_fname_new)
6356 NTSTATUS status = NT_STATUS_OK;
6359 struct smb_filename *parent_fname_old = NULL;
6360 struct smb_filename *base_name_old = NULL;
6361 struct smb_filename *parent_fname_new = NULL;
6362 struct smb_filename *base_name_new = NULL;
6364 /* source must already exist. */
6365 if (!VALID_STAT(smb_fname_old->st)) {
6366 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6370 /* No links from a directory. */
6371 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6372 status = NT_STATUS_FILE_IS_A_DIRECTORY;
6376 /* Setting a hardlink to/from a stream isn't currently supported. */
6377 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6379 DBG_DEBUG("Old name has streams\n");
6380 status = NT_STATUS_INVALID_PARAMETER;
6383 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6385 DBG_DEBUG("New name has streams\n");
6386 status = NT_STATUS_INVALID_PARAMETER;
6390 status = parent_pathref(talloc_tos(),
6395 if (!NT_STATUS_IS_OK(status)) {
6399 status = parent_pathref(talloc_tos(),
6404 if (!NT_STATUS_IS_OK(status)) {
6408 if (VALID_STAT(smb_fname_new->st)) {
6409 if (overwrite_if_exists) {
6410 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6411 status = NT_STATUS_FILE_IS_A_DIRECTORY;
6414 status = unlink_internals(conn,
6416 FILE_ATTRIBUTE_NORMAL,
6418 if (!NT_STATUS_IS_OK(status)) {
6422 /* Disallow if newname already exists. */
6423 status = NT_STATUS_OBJECT_NAME_COLLISION;
6428 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6429 smb_fname_old->base_name, smb_fname_new->base_name));
6431 ret = SMB_VFS_LINKAT(conn,
6432 parent_fname_old->fsp,
6434 parent_fname_new->fsp,
6439 status = map_nt_error_from_unix(errno);
6440 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6441 nt_errstr(status), smb_fname_old->base_name,
6442 smb_fname_new->base_name));
6447 TALLOC_FREE(parent_fname_old);
6448 TALLOC_FREE(parent_fname_new);
6452 /****************************************************************************
6453 Deal with setting the time from any of the setfilepathinfo functions.
6454 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6455 calling this function.
6456 ****************************************************************************/
6458 NTSTATUS smb_set_file_time(connection_struct *conn,
6460 struct smb_filename *smb_fname,
6461 struct smb_file_time *ft,
6462 bool setting_write_time)
6464 struct files_struct *set_fsp = NULL;
6465 struct timeval_buf tbuf[4];
6467 FILE_NOTIFY_CHANGE_LAST_ACCESS
6468 |FILE_NOTIFY_CHANGE_LAST_WRITE
6469 |FILE_NOTIFY_CHANGE_CREATION;
6472 if (!VALID_STAT(smb_fname->st)) {
6473 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6478 return NT_STATUS_OK;
6481 set_fsp = metadata_fsp(fsp);
6483 /* get some defaults (no modifications) if any info is zero or -1. */
6484 if (is_omit_timespec(&ft->create_time)) {
6485 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6488 if (is_omit_timespec(&ft->atime)) {
6489 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6492 if (is_omit_timespec(&ft->mtime)) {
6493 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6496 if (!setting_write_time) {
6497 /* ft->mtime comes from change time, not write time. */
6498 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6501 /* Ensure the resolution is the correct for
6502 * what we can store on this filesystem. */
6504 round_timespec(conn->ts_res, &ft->create_time);
6505 round_timespec(conn->ts_res, &ft->ctime);
6506 round_timespec(conn->ts_res, &ft->atime);
6507 round_timespec(conn->ts_res, &ft->mtime);
6509 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6510 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6511 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6512 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6513 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6514 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6515 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6516 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6518 if (setting_write_time) {
6520 * This was a Windows setfileinfo on an open file.
6521 * NT does this a lot. We also need to
6522 * set the time here, as it can be read by
6523 * FindFirst/FindNext and with the patch for bug #2045
6524 * in smbd/fileio.c it ensures that this timestamp is
6525 * kept sticky even after a write. We save the request
6526 * away and will set it on file close and after a write. JRA.
6529 DBG_DEBUG("setting pending modtime to %s\n",
6530 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6532 if (set_fsp != NULL) {
6533 set_sticky_write_time_fsp(set_fsp, ft->mtime);
6535 set_sticky_write_time_path(
6536 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6541 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6543 ret = file_ntimes(conn, set_fsp, ft);
6545 return map_nt_error_from_unix(errno);
6548 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6549 smb_fname->base_name);
6550 return NT_STATUS_OK;
6553 /****************************************************************************
6554 Deal with setting the dosmode from any of the setfilepathinfo functions.
6555 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6556 done before calling this function.
6557 ****************************************************************************/
6559 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6560 struct files_struct *fsp,
6563 struct files_struct *dos_fsp = NULL;
6564 uint32_t current_dosmode;
6567 if (!VALID_STAT(fsp->fsp_name->st)) {
6568 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6571 dos_fsp = metadata_fsp(fsp);
6574 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6575 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6577 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6581 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
6583 /* check the mode isn't different, before changing it */
6585 return NT_STATUS_OK;
6587 current_dosmode = fdos_mode(dos_fsp);
6588 if (dosmode == current_dosmode) {
6589 return NT_STATUS_OK;
6592 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
6593 fsp_str_dbg(dos_fsp), dosmode);
6595 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
6597 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
6598 fsp_str_dbg(dos_fsp), strerror(errno));
6599 return map_nt_error_from_unix(errno);
6602 return NT_STATUS_OK;
6605 /****************************************************************************
6606 Deal with setting the size from any of the setfilepathinfo functions.
6607 ****************************************************************************/
6609 static NTSTATUS smb_set_file_size(connection_struct *conn,
6610 struct smb_request *req,
6612 struct smb_filename *smb_fname,
6613 const SMB_STRUCT_STAT *psbuf,
6615 bool fail_after_createfile)
6617 NTSTATUS status = NT_STATUS_OK;
6618 files_struct *new_fsp = NULL;
6620 if (!VALID_STAT(*psbuf)) {
6621 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6624 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6626 get_file_size_stat(psbuf));
6628 if (size == get_file_size_stat(psbuf)) {
6630 return NT_STATUS_OK;
6632 if (!fsp->fsp_flags.modified) {
6633 return NT_STATUS_OK;
6635 trigger_write_time_update_immediate(fsp);
6636 return NT_STATUS_OK;
6639 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6640 smb_fname_str_dbg(smb_fname), (double)size));
6643 !fsp->fsp_flags.is_pathref &&
6644 fsp_get_io_fd(fsp) != -1)
6646 /* Handle based call. */
6647 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6648 return NT_STATUS_ACCESS_DENIED;
6651 if (vfs_set_filelen(fsp, size) == -1) {
6652 return map_nt_error_from_unix(errno);
6654 trigger_write_time_update_immediate(fsp);
6655 return NT_STATUS_OK;
6658 status = SMB_VFS_CREATE_FILE(
6661 smb_fname, /* fname */
6662 FILE_WRITE_DATA, /* access_mask */
6663 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6665 FILE_OPEN, /* create_disposition*/
6666 0, /* create_options */
6667 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6668 0, /* oplock_request */
6670 0, /* allocation_size */
6671 0, /* private_flags */
6674 &new_fsp, /* result */
6676 NULL, NULL); /* create context */
6678 if (!NT_STATUS_IS_OK(status)) {
6679 /* NB. We check for open_was_deferred in the caller. */
6683 /* See RAW-SFILEINFO-END-OF-FILE */
6684 if (fail_after_createfile) {
6685 close_file_free(req, &new_fsp, NORMAL_CLOSE);
6686 return NT_STATUS_INVALID_LEVEL;
6689 if (vfs_set_filelen(new_fsp, size) == -1) {
6690 status = map_nt_error_from_unix(errno);
6691 close_file_free(req, &new_fsp, NORMAL_CLOSE);
6695 trigger_write_time_update_immediate(new_fsp);
6696 close_file_free(req, &new_fsp, NORMAL_CLOSE);
6697 return NT_STATUS_OK;
6700 /****************************************************************************
6701 Deal with SMB_INFO_SET_EA.
6702 ****************************************************************************/
6704 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6708 struct smb_filename *smb_fname)
6710 struct ea_list *ea_list = NULL;
6711 TALLOC_CTX *ctx = NULL;
6712 NTSTATUS status = NT_STATUS_OK;
6714 if (total_data < 10) {
6716 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6717 length. They seem to have no effect. Bug #3212. JRA */
6719 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6720 /* We're done. We only get EA info in this call. */
6721 return NT_STATUS_OK;
6724 return NT_STATUS_INVALID_PARAMETER;
6727 if (IVAL(pdata,0) > total_data) {
6728 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6729 IVAL(pdata,0), (unsigned int)total_data));
6730 return NT_STATUS_INVALID_PARAMETER;
6734 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6736 return NT_STATUS_INVALID_PARAMETER;
6741 * The only way fsp can be NULL here is if
6742 * smb_fname points at a symlink and
6743 * and we're in POSIX context.
6744 * Ensure this is the case.
6746 * In this case we cannot set the EA.
6748 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
6749 return NT_STATUS_ACCESS_DENIED;
6752 status = set_ea(conn, fsp, ea_list);
6757 /****************************************************************************
6758 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6759 ****************************************************************************/
6761 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6766 struct ea_list *ea_list = NULL;
6770 return NT_STATUS_INVALID_HANDLE;
6773 if (!lp_ea_support(SNUM(conn))) {
6774 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6775 "EA's not supported.\n",
6776 (unsigned int)total_data));
6777 return NT_STATUS_EAS_NOT_SUPPORTED;
6780 if (total_data < 10) {
6781 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6783 (unsigned int)total_data));
6784 return NT_STATUS_INVALID_PARAMETER;
6787 ea_list = read_nttrans_ea_list(talloc_tos(),
6792 return NT_STATUS_INVALID_PARAMETER;
6795 status = set_ea(conn, fsp, ea_list);
6797 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6798 smb_fname_str_dbg(fsp->fsp_name),
6799 nt_errstr(status) ));
6805 /****************************************************************************
6806 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6807 ****************************************************************************/
6809 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6813 struct smb_filename *smb_fname)
6815 NTSTATUS status = NT_STATUS_OK;
6816 bool delete_on_close;
6817 uint32_t dosmode = 0;
6819 if (total_data < 1) {
6820 return NT_STATUS_INVALID_PARAMETER;
6824 return NT_STATUS_INVALID_HANDLE;
6827 delete_on_close = (CVAL(pdata,0) ? True : False);
6828 dosmode = fdos_mode(fsp);
6830 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6831 "delete_on_close = %u\n",
6832 smb_fname_str_dbg(smb_fname),
6833 (unsigned int)dosmode,
6834 (unsigned int)delete_on_close ));
6836 if (delete_on_close) {
6837 status = can_set_delete_on_close(fsp, dosmode);
6838 if (!NT_STATUS_IS_OK(status)) {
6843 /* The set is across all open files on this dev/inode pair. */
6844 if (!set_delete_on_close(fsp, delete_on_close,
6845 conn->session_info->security_token,
6846 conn->session_info->unix_token)) {
6847 return NT_STATUS_ACCESS_DENIED;
6849 return NT_STATUS_OK;
6852 /****************************************************************************
6853 Deal with SMB_FILE_POSITION_INFORMATION.
6854 ****************************************************************************/
6856 static NTSTATUS smb_file_position_information(connection_struct *conn,
6861 uint64_t position_information;
6863 if (total_data < 8) {
6864 return NT_STATUS_INVALID_PARAMETER;
6868 /* Ignore on pathname based set. */
6869 return NT_STATUS_OK;
6872 position_information = (uint64_t)IVAL(pdata,0);
6873 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6875 DEBUG(10,("smb_file_position_information: Set file position "
6876 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6877 (double)position_information));
6878 fh_set_position_information(fsp->fh, position_information);
6879 return NT_STATUS_OK;
6882 /****************************************************************************
6883 Deal with SMB_FILE_MODE_INFORMATION.
6884 ****************************************************************************/
6886 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6892 if (total_data < 4) {
6893 return NT_STATUS_INVALID_PARAMETER;
6895 mode = IVAL(pdata,0);
6896 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6897 return NT_STATUS_INVALID_PARAMETER;
6899 return NT_STATUS_OK;
6902 /****************************************************************************
6903 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6904 ****************************************************************************/
6906 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6907 struct smb_request *req,
6910 struct smb_filename *new_smb_fname)
6912 char *link_target = NULL;
6913 struct smb_filename target_fname;
6914 TALLOC_CTX *ctx = talloc_tos();
6917 struct smb_filename *parent_fname = NULL;
6918 struct smb_filename *base_name = NULL;
6920 /* Set a symbolic link. */
6921 /* Don't allow this if follow links is false. */
6923 if (total_data == 0) {
6924 return NT_STATUS_INVALID_PARAMETER;
6927 if (!lp_follow_symlinks(SNUM(conn))) {
6928 return NT_STATUS_ACCESS_DENIED;
6931 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6932 total_data, STR_TERMINATE);
6935 return NT_STATUS_INVALID_PARAMETER;
6938 target_fname = (struct smb_filename) {
6939 .base_name = link_target,
6942 /* Removes @GMT tokens if any */
6943 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
6944 if (!NT_STATUS_IS_OK(status)) {
6948 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6949 new_smb_fname->base_name, link_target ));
6951 status = parent_pathref(talloc_tos(),
6956 if (!NT_STATUS_IS_OK(status)) {
6960 ret = SMB_VFS_SYMLINKAT(conn,
6965 TALLOC_FREE(parent_fname);
6966 return map_nt_error_from_unix(errno);
6969 TALLOC_FREE(parent_fname);
6970 return NT_STATUS_OK;
6973 /****************************************************************************
6974 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6975 ****************************************************************************/
6977 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6978 struct smb_request *req,
6979 const char *pdata, int total_data,
6980 struct smb_filename *smb_fname_new)
6982 char *oldname = NULL;
6983 struct smb_filename *smb_fname_old = NULL;
6984 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6985 TALLOC_CTX *ctx = talloc_tos();
6986 NTSTATUS status = NT_STATUS_OK;
6988 /* Set a hard link. */
6989 if (total_data == 0) {
6990 return NT_STATUS_INVALID_PARAMETER;
6993 if (req->posix_pathnames) {
6994 srvstr_get_path_posix(ctx,
7003 srvstr_get_path(ctx,
7012 if (!NT_STATUS_IS_OK(status)) {
7016 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7017 smb_fname_str_dbg(smb_fname_new), oldname));
7019 status = filename_convert(ctx,
7025 if (!NT_STATUS_IS_OK(status)) {
7029 return hardlink_internals(ctx, conn, req, false,
7030 smb_fname_old, smb_fname_new);
7033 /****************************************************************************
7034 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7035 ****************************************************************************/
7037 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7038 struct smb_request *req,
7042 struct smb_filename *smb_fname_src)
7046 char *newname = NULL;
7047 struct smb_filename *smb_fname_dst = NULL;
7048 const char *dst_original_lcomp = NULL;
7049 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7050 NTSTATUS status = NT_STATUS_OK;
7051 TALLOC_CTX *ctx = talloc_tos();
7054 return NT_STATUS_INVALID_HANDLE;
7057 if (total_data < 20) {
7058 return NT_STATUS_INVALID_PARAMETER;
7061 overwrite = (CVAL(pdata,0) ? True : False);
7062 len = IVAL(pdata,16);
7064 if (len > (total_data - 20) || (len == 0)) {
7065 return NT_STATUS_INVALID_PARAMETER;
7068 if (req->posix_pathnames) {
7069 srvstr_get_path_posix(ctx,
7078 srvstr_get_path(ctx,
7087 if (!NT_STATUS_IS_OK(status)) {
7091 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7094 status = filename_convert(ctx,
7100 if (!NT_STATUS_IS_OK(status)) {
7104 if (fsp->base_fsp) {
7105 /* newname must be a stream name. */
7106 if (newname[0] != ':') {
7107 return NT_STATUS_NOT_SUPPORTED;
7110 /* Create an smb_fname to call rename_internals_fsp() with. */
7111 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7112 fsp->base_fsp->fsp_name->base_name,
7115 fsp->base_fsp->fsp_name->twrp,
7116 fsp->base_fsp->fsp_name->flags);
7117 if (smb_fname_dst == NULL) {
7118 status = NT_STATUS_NO_MEMORY;
7124 * Set the original last component, since
7125 * rename_internals_fsp() requires it.
7127 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7131 if (dst_original_lcomp == NULL) {
7132 status = NT_STATUS_NO_MEMORY;
7136 DEBUG(10,("smb2_file_rename_information: "
7137 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7138 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7139 smb_fname_str_dbg(smb_fname_dst)));
7140 status = rename_internals_fsp(conn,
7144 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7148 TALLOC_FREE(smb_fname_dst);
7152 static NTSTATUS smb_file_link_information(connection_struct *conn,
7153 struct smb_request *req,
7157 struct smb_filename *smb_fname_src)
7161 char *newname = NULL;
7162 struct smb_filename *smb_fname_dst = NULL;
7163 NTSTATUS status = NT_STATUS_OK;
7164 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7165 TALLOC_CTX *ctx = talloc_tos();
7168 return NT_STATUS_INVALID_HANDLE;
7171 if (total_data < 20) {
7172 return NT_STATUS_INVALID_PARAMETER;
7175 overwrite = (CVAL(pdata,0) ? true : false);
7176 len = IVAL(pdata,16);
7178 if (len > (total_data - 20) || (len == 0)) {
7179 return NT_STATUS_INVALID_PARAMETER;
7182 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7183 srvstr_get_path_posix(ctx,
7191 ucf_flags |= UCF_POSIX_PATHNAMES;
7193 srvstr_get_path(ctx,
7202 if (!NT_STATUS_IS_OK(status)) {
7206 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7209 status = filename_convert(ctx,
7215 if (!NT_STATUS_IS_OK(status)) {
7219 if (fsp->base_fsp) {
7220 /* No stream names. */
7221 return NT_STATUS_NOT_SUPPORTED;
7224 DEBUG(10,("smb_file_link_information: "
7225 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7226 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7227 smb_fname_str_dbg(smb_fname_dst)));
7228 status = hardlink_internals(ctx,
7235 TALLOC_FREE(smb_fname_dst);
7239 /****************************************************************************
7240 Deal with SMB_FILE_RENAME_INFORMATION.
7241 ****************************************************************************/
7243 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7244 struct smb_request *req,
7248 struct smb_filename *smb_fname_src)
7253 char *newname = NULL;
7254 struct smb_filename *smb_fname_dst = NULL;
7255 const char *dst_original_lcomp = NULL;
7256 NTSTATUS status = NT_STATUS_OK;
7258 TALLOC_CTX *ctx = talloc_tos();
7260 if (total_data < 13) {
7261 return NT_STATUS_INVALID_PARAMETER;
7264 overwrite = (CVAL(pdata,0) ? True : False);
7265 root_fid = IVAL(pdata,4);
7266 len = IVAL(pdata,8);
7268 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7269 return NT_STATUS_INVALID_PARAMETER;
7272 if (req->posix_pathnames) {
7273 srvstr_get_path_posix(ctx,
7282 srvstr_get_path(ctx,
7291 if (!NT_STATUS_IS_OK(status)) {
7295 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7298 /* Check the new name has no '/' characters. */
7299 if (strchr_m(newname, '/')) {
7300 return NT_STATUS_NOT_SUPPORTED;
7303 if (fsp && fsp->base_fsp) {
7304 /* newname must be a stream name. */
7305 if (newname[0] != ':') {
7306 return NT_STATUS_NOT_SUPPORTED;
7309 /* Create an smb_fname to call rename_internals_fsp() with. */
7310 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7311 fsp->base_fsp->fsp_name->base_name,
7314 fsp->base_fsp->fsp_name->twrp,
7315 fsp->base_fsp->fsp_name->flags);
7316 if (smb_fname_dst == NULL) {
7317 status = NT_STATUS_NO_MEMORY;
7322 * Get the original last component, since
7323 * rename_internals_fsp() requires it.
7325 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7329 if (dst_original_lcomp == NULL) {
7330 status = NT_STATUS_NO_MEMORY;
7336 * Build up an smb_fname_dst based on the filename passed in.
7337 * We basically just strip off the last component, and put on
7338 * the newname instead.
7340 char *base_name = NULL;
7341 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7343 /* newname must *not* be a stream name. */
7344 if (newname[0] == ':') {
7345 return NT_STATUS_NOT_SUPPORTED;
7349 * Strip off the last component (filename) of the path passed
7352 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7354 return NT_STATUS_NO_MEMORY;
7356 p = strrchr_m(base_name, '/');
7360 base_name = talloc_strdup(ctx, "");
7362 return NT_STATUS_NO_MEMORY;
7365 /* Append the new name. */
7366 base_name = talloc_asprintf_append(base_name,
7370 return NT_STATUS_NO_MEMORY;
7373 status = filename_convert(ctx,
7380 if (!NT_STATUS_IS_OK(status)) {
7383 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7387 if (dst_original_lcomp == NULL) {
7388 status = NT_STATUS_NO_MEMORY;
7393 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
7394 DEBUG(10,("smb_file_rename_information: "
7395 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7396 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7397 smb_fname_str_dbg(smb_fname_dst)));
7398 status = rename_internals_fsp(conn,
7405 DEBUG(10,("smb_file_rename_information: "
7406 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7407 smb_fname_str_dbg(smb_fname_src),
7408 smb_fname_str_dbg(smb_fname_dst)));
7409 status = rename_internals(ctx,
7417 FILE_WRITE_ATTRIBUTES);
7420 TALLOC_FREE(smb_fname_dst);
7424 /****************************************************************************
7425 Deal with SMB_SET_POSIX_ACL.
7426 ****************************************************************************/
7428 #if defined(HAVE_POSIX_ACLS)
7429 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7430 struct smb_request *req,
7434 struct smb_filename *smb_fname)
7436 uint16_t posix_acl_version;
7437 uint16_t num_file_acls;
7438 uint16_t num_def_acls;
7439 bool valid_file_acls = true;
7440 bool valid_def_acls = true;
7442 unsigned int size_needed;
7443 unsigned int total_data;
7444 bool close_fsp = false;
7446 if (total_data_in < 0) {
7447 status = NT_STATUS_INVALID_PARAMETER;
7451 total_data = total_data_in;
7453 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7454 status = NT_STATUS_INVALID_PARAMETER;
7457 posix_acl_version = SVAL(pdata,0);
7458 num_file_acls = SVAL(pdata,2);
7459 num_def_acls = SVAL(pdata,4);
7461 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7462 valid_file_acls = false;
7466 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7467 valid_def_acls = false;
7471 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7472 status = NT_STATUS_INVALID_PARAMETER;
7477 if (num_file_acls + num_def_acls < num_file_acls) {
7478 status = NT_STATUS_INVALID_PARAMETER;
7482 size_needed = num_file_acls + num_def_acls;
7485 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7486 * than UINT_MAX, so check by division.
7488 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7489 status = NT_STATUS_INVALID_PARAMETER;
7493 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7494 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7495 status = NT_STATUS_INVALID_PARAMETER;
7498 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7500 if (total_data < size_needed) {
7501 status = NT_STATUS_INVALID_PARAMETER;
7506 * Ensure we always operate on a file descriptor, not just
7509 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
7510 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7512 SEC_STD_READ_CONTROL|
7513 FILE_READ_ATTRIBUTES|
7514 FILE_WRITE_ATTRIBUTES;
7516 status = get_posix_fsp(conn,
7522 if (!NT_STATUS_IS_OK(status)) {
7528 /* Here we know fsp != NULL */
7529 SMB_ASSERT(fsp != NULL);
7531 status = refuse_symlink_fsp(fsp);
7532 if (!NT_STATUS_IS_OK(status)) {
7536 /* If we have a default acl, this *must* be a directory. */
7537 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
7538 DBG_INFO("Can't set default acls on "
7539 "non-directory %s\n",
7541 return NT_STATUS_INVALID_HANDLE;
7544 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7545 "num_def_acls = %"PRIu16"\n",
7550 /* Move pdata to the start of the file ACL entries. */
7551 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7553 if (valid_file_acls) {
7554 status = set_unix_posix_acl(conn,
7558 if (!NT_STATUS_IS_OK(status)) {
7563 /* Move pdata to the start of the default ACL entries. */
7564 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7566 if (valid_def_acls) {
7567 status = set_unix_posix_default_acl(conn,
7571 if (!NT_STATUS_IS_OK(status)) {
7576 status = NT_STATUS_OK;
7581 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
7587 /****************************************************************************
7588 Deal with SMB_SET_POSIX_LOCK.
7589 ****************************************************************************/
7591 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7593 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7594 struct smb_request *req,
7599 struct tevent_req *subreq = NULL;
7600 struct smbd_lock_element *lck = NULL;
7604 bool blocking_lock = False;
7605 enum brl_type lock_type;
7607 NTSTATUS status = NT_STATUS_OK;
7610 fsp->fsp_flags.is_pathref ||
7611 fsp_get_io_fd(fsp) == -1)
7613 return NT_STATUS_INVALID_HANDLE;
7616 if (total_data != POSIX_LOCK_DATA_SIZE) {
7617 return NT_STATUS_INVALID_PARAMETER;
7620 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7621 case POSIX_LOCK_TYPE_READ:
7622 lock_type = READ_LOCK;
7624 case POSIX_LOCK_TYPE_WRITE:
7625 /* Return the right POSIX-mappable error code for files opened read-only. */
7626 if (!fsp->fsp_flags.can_write) {
7627 return NT_STATUS_INVALID_HANDLE;
7629 lock_type = WRITE_LOCK;
7631 case POSIX_LOCK_TYPE_UNLOCK:
7632 lock_type = UNLOCK_LOCK;
7635 return NT_STATUS_INVALID_PARAMETER;
7638 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7639 case POSIX_LOCK_FLAG_NOWAIT:
7640 blocking_lock = false;
7642 case POSIX_LOCK_FLAG_WAIT:
7643 blocking_lock = true;
7646 return NT_STATUS_INVALID_PARAMETER;
7649 if (!lp_blocking_locks(SNUM(conn))) {
7650 blocking_lock = False;
7653 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7654 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7655 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7656 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7657 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7659 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7660 "count = %"PRIu64", offset = %"PRIu64"\n",
7662 (unsigned int)lock_type,
7667 if (lock_type == UNLOCK_LOCK) {
7668 struct smbd_lock_element l = {
7669 .req_guid = smbd_request_guid(req, 0),
7671 .brltype = UNLOCK_LOCK,
7672 .lock_flav = POSIX_LOCK,
7676 status = smbd_do_unlocking(req, fsp, 1, &l);
7680 lck = talloc(req, struct smbd_lock_element);
7682 return NT_STATUS_NO_MEMORY;
7685 *lck = (struct smbd_lock_element) {
7686 .req_guid = smbd_request_guid(req, 0),
7688 .brltype = lock_type,
7689 .lock_flav = POSIX_LOCK,
7694 subreq = smbd_smb1_do_locks_send(
7699 blocking_lock ? UINT32_MAX : 0,
7700 true, /* large_offset */
7703 if (subreq == NULL) {
7705 return NT_STATUS_NO_MEMORY;
7707 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7708 return NT_STATUS_EVENT_PENDING;
7711 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7713 struct smb_request *req = NULL;
7717 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7720 status = smbd_smb1_do_locks_recv(subreq);
7721 TALLOC_FREE(subreq);
7723 if (NT_STATUS_IS_OK(status)) {
7724 char params[2] = {0};
7725 /* Fake up max_data_bytes here - we know it fits. */
7726 send_trans2_replies(
7736 reply_nterror(req, status);
7739 (char *)req->outbuf,
7742 IS_CONN_ENCRYPTED(req->conn),
7745 exit_server_cleanly("smb_set_posix_lock_done: "
7746 "srv_send_smb failed.");
7754 /****************************************************************************
7755 Deal with SMB_SET_FILE_BASIC_INFO.
7756 ****************************************************************************/
7758 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7762 struct smb_filename *smb_fname)
7764 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7765 struct smb_file_time ft;
7766 uint32_t dosmode = 0;
7767 NTSTATUS status = NT_STATUS_OK;
7769 init_smb_file_time(&ft);
7771 if (total_data < 36) {
7772 return NT_STATUS_INVALID_PARAMETER;
7776 return NT_STATUS_INVALID_HANDLE;
7779 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7780 if (!NT_STATUS_IS_OK(status)) {
7784 /* Set the attributes */
7785 dosmode = IVAL(pdata,32);
7786 status = smb_set_file_dosmode(conn, fsp, dosmode);
7787 if (!NT_STATUS_IS_OK(status)) {
7792 ft.create_time = pull_long_date_full_timespec(pdata);
7795 ft.atime = pull_long_date_full_timespec(pdata+8);
7798 ft.mtime = pull_long_date_full_timespec(pdata+16);
7801 ft.ctime = pull_long_date_full_timespec(pdata+24);
7803 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7804 smb_fname_str_dbg(smb_fname)));
7806 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7807 if (!NT_STATUS_IS_OK(status)) {
7811 if (fsp->fsp_flags.modified) {
7812 trigger_write_time_update_immediate(fsp);
7814 return NT_STATUS_OK;
7817 /****************************************************************************
7818 Deal with SMB_INFO_STANDARD.
7819 ****************************************************************************/
7821 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7825 struct smb_filename *smb_fname)
7828 struct smb_file_time ft;
7830 init_smb_file_time(&ft);
7832 if (total_data < 12) {
7833 return NT_STATUS_INVALID_PARAMETER;
7837 return NT_STATUS_INVALID_HANDLE;
7841 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7843 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7845 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7847 DEBUG(10,("smb_set_info_standard: file %s\n",
7848 smb_fname_str_dbg(smb_fname)));
7850 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7851 if (!NT_STATUS_IS_OK(status)) {
7855 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7856 if (!NT_STATUS_IS_OK(status)) {
7860 if (fsp->fsp_flags.modified) {
7861 trigger_write_time_update_immediate(fsp);
7863 return NT_STATUS_OK;
7866 /****************************************************************************
7867 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7868 ****************************************************************************/
7870 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7871 struct smb_request *req,
7875 struct smb_filename *smb_fname)
7877 uint64_t allocation_size = 0;
7878 NTSTATUS status = NT_STATUS_OK;
7879 files_struct *new_fsp = NULL;
7881 if (!VALID_STAT(smb_fname->st)) {
7882 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7885 if (total_data < 8) {
7886 return NT_STATUS_INVALID_PARAMETER;
7889 allocation_size = (uint64_t)IVAL(pdata,0);
7890 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7891 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7892 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7893 (double)allocation_size));
7895 if (allocation_size) {
7896 allocation_size = smb_roundup(conn, allocation_size);
7899 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7900 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7901 (double)allocation_size));
7904 !fsp->fsp_flags.is_pathref &&
7905 fsp_get_io_fd(fsp) != -1)
7907 /* Open file handle. */
7908 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7909 return NT_STATUS_ACCESS_DENIED;
7912 /* Only change if needed. */
7913 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7914 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7915 return map_nt_error_from_unix(errno);
7918 /* But always update the time. */
7920 * This is equivalent to a write. Ensure it's seen immediately
7921 * if there are no pending writes.
7923 trigger_write_time_update_immediate(fsp);
7924 return NT_STATUS_OK;
7927 /* Pathname or stat or directory file. */
7928 status = SMB_VFS_CREATE_FILE(
7931 smb_fname, /* fname */
7932 FILE_WRITE_DATA, /* access_mask */
7933 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7935 FILE_OPEN, /* create_disposition*/
7936 0, /* create_options */
7937 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7938 0, /* oplock_request */
7940 0, /* allocation_size */
7941 0, /* private_flags */
7944 &new_fsp, /* result */
7946 NULL, NULL); /* create context */
7948 if (!NT_STATUS_IS_OK(status)) {
7949 /* NB. We check for open_was_deferred in the caller. */
7953 /* Only change if needed. */
7954 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7955 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7956 status = map_nt_error_from_unix(errno);
7957 close_file_free(req, &new_fsp, NORMAL_CLOSE);
7962 /* Changing the allocation size should set the last mod time. */
7964 * This is equivalent to a write. Ensure it's seen immediately
7965 * if there are no pending writes.
7967 trigger_write_time_update_immediate(new_fsp);
7968 close_file_free(req, &new_fsp, NORMAL_CLOSE);
7969 return NT_STATUS_OK;
7972 /****************************************************************************
7973 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7974 ****************************************************************************/
7976 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7977 struct smb_request *req,
7981 struct smb_filename *smb_fname,
7982 bool fail_after_createfile)
7986 if (total_data < 8) {
7987 return NT_STATUS_INVALID_PARAMETER;
7990 size = IVAL(pdata,0);
7991 size |= (((off_t)IVAL(pdata,4)) << 32);
7992 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7993 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7996 return smb_set_file_size(conn, req,
8001 fail_after_createfile);
8004 /****************************************************************************
8005 Allow a UNIX info mknod.
8006 ****************************************************************************/
8008 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8011 const struct smb_filename *smb_fname)
8013 uint32_t file_type = IVAL(pdata,56);
8014 #if defined(HAVE_MAKEDEV)
8015 uint32_t dev_major = IVAL(pdata,60);
8016 uint32_t dev_minor = IVAL(pdata,68);
8018 SMB_DEV_T dev = (SMB_DEV_T)0;
8019 uint32_t raw_unixmode = IVAL(pdata,84);
8023 struct smb_filename *parent_fname = NULL;
8024 struct smb_filename *base_name = NULL;
8026 if (total_data < 100) {
8027 return NT_STATUS_INVALID_PARAMETER;
8030 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8031 PERM_NEW_FILE, &unixmode);
8032 if (!NT_STATUS_IS_OK(status)) {
8036 #if defined(HAVE_MAKEDEV)
8037 dev = makedev(dev_major, dev_minor);
8040 switch (file_type) {
8041 /* We can't create other objects here. */
8042 case UNIX_TYPE_FILE:
8044 case UNIX_TYPE_SYMLINK:
8045 return NT_STATUS_ACCESS_DENIED;
8046 #if defined(S_IFIFO)
8047 case UNIX_TYPE_FIFO:
8048 unixmode |= S_IFIFO;
8051 #if defined(S_IFSOCK)
8052 case UNIX_TYPE_SOCKET:
8053 unixmode |= S_IFSOCK;
8056 #if defined(S_IFCHR)
8057 case UNIX_TYPE_CHARDEV:
8058 /* This is only allowed for root. */
8059 if (get_current_uid(conn) != sec_initial_uid()) {
8060 return NT_STATUS_ACCESS_DENIED;
8062 unixmode |= S_IFCHR;
8065 #if defined(S_IFBLK)
8066 case UNIX_TYPE_BLKDEV:
8067 if (get_current_uid(conn) != sec_initial_uid()) {
8068 return NT_STATUS_ACCESS_DENIED;
8070 unixmode |= S_IFBLK;
8074 return NT_STATUS_INVALID_PARAMETER;
8077 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8078 "%.0f mode 0%o for file %s\n", (double)dev,
8079 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8081 status = parent_pathref(talloc_tos(),
8086 if (!NT_STATUS_IS_OK(status)) {
8090 /* Ok - do the mknod. */
8091 ret = SMB_VFS_MKNODAT(conn,
8098 TALLOC_FREE(parent_fname);
8099 return map_nt_error_from_unix(errno);
8102 /* If any of the other "set" calls fail we
8103 * don't want to end up with a half-constructed mknod.
8106 if (lp_inherit_permissions(SNUM(conn))) {
8107 inherit_access_posix_acl(conn,
8112 TALLOC_FREE(parent_fname);
8114 return NT_STATUS_OK;
8117 /****************************************************************************
8118 Deal with SMB_SET_FILE_UNIX_BASIC.
8119 ****************************************************************************/
8121 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8122 struct smb_request *req,
8126 struct smb_filename *smb_fname)
8128 struct smb_file_time ft;
8129 uint32_t raw_unixmode;
8132 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8133 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8134 NTSTATUS status = NT_STATUS_OK;
8135 enum perm_type ptype;
8136 files_struct *all_fsps = NULL;
8137 bool modify_mtime = true;
8139 SMB_STRUCT_STAT sbuf;
8141 init_smb_file_time(&ft);
8143 if (total_data < 100) {
8144 return NT_STATUS_INVALID_PARAMETER;
8147 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8148 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8149 size=IVAL(pdata,0); /* first 8 Bytes are size */
8150 size |= (((off_t)IVAL(pdata,4)) << 32);
8153 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8154 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8155 set_owner = (uid_t)IVAL(pdata,40);
8156 set_grp = (gid_t)IVAL(pdata,48);
8157 raw_unixmode = IVAL(pdata,84);
8159 if (VALID_STAT(smb_fname->st)) {
8160 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8161 ptype = PERM_EXISTING_DIR;
8163 ptype = PERM_EXISTING_FILE;
8166 ptype = PERM_NEW_FILE;
8169 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8171 if (!NT_STATUS_IS_OK(status)) {
8175 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8176 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8177 smb_fname_str_dbg(smb_fname), (double)size,
8178 (unsigned int)set_owner, (unsigned int)set_grp,
8179 (int)raw_unixmode));
8181 sbuf = smb_fname->st;
8183 if (!VALID_STAT(sbuf)) {
8185 * The only valid use of this is to create character and block
8186 * devices, and named pipes. This is deprecated (IMHO) and
8187 * a new info level should be used for mknod. JRA.
8190 return smb_unix_mknod(conn,
8197 /* Horrible backwards compatibility hack as an old server bug
8198 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8202 size = get_file_size_stat(&sbuf);
8207 * Deal with the UNIX specific mode set.
8210 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8213 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
8214 DBG_WARNING("Can't set mode on symlink %s\n",
8215 smb_fname_str_dbg(smb_fname));
8216 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8219 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8220 "setting mode 0%o for file %s\n",
8221 (unsigned int)unixmode,
8222 smb_fname_str_dbg(smb_fname)));
8223 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8225 return map_nt_error_from_unix(errno);
8230 * Deal with the UNIX specific uid set.
8233 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8234 (sbuf.st_ex_uid != set_owner)) {
8237 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8238 "changing owner %u for path %s\n",
8239 (unsigned int)set_owner,
8240 smb_fname_str_dbg(smb_fname)));
8243 !fsp->fsp_flags.is_pathref &&
8244 fsp_get_io_fd(fsp) != -1)
8246 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8249 * UNIX extensions calls must always operate
8252 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8253 set_owner, (gid_t)-1);
8257 status = map_nt_error_from_unix(errno);
8263 * Deal with the UNIX specific gid set.
8266 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8267 (sbuf.st_ex_gid != set_grp)) {
8270 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8271 "changing group %u for file %s\n",
8272 (unsigned int)set_grp,
8273 smb_fname_str_dbg(smb_fname)));
8275 !fsp->fsp_flags.is_pathref &&
8276 fsp_get_io_fd(fsp) != -1)
8278 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8281 * UNIX extensions calls must always operate
8284 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8288 status = map_nt_error_from_unix(errno);
8293 /* Deal with any size changes. */
8295 if (S_ISREG(sbuf.st_ex_mode)) {
8296 status = smb_set_file_size(conn, req,
8302 if (!NT_STATUS_IS_OK(status)) {
8307 /* Deal with any time changes. */
8308 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8309 /* No change, don't cancel anything. */
8313 id = vfs_file_id_from_sbuf(conn, &sbuf);
8314 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
8315 all_fsps = file_find_di_next(all_fsps, true)) {
8317 * We're setting the time explicitly for UNIX.
8318 * Cancel any pending changes over all handles.
8320 all_fsps->fsp_flags.update_write_time_on_close = false;
8321 TALLOC_FREE(all_fsps->update_write_time_event);
8325 * Override the "setting_write_time"
8326 * parameter here as it almost does what
8327 * we need. Just remember if we modified
8328 * mtime and send the notify ourselves.
8330 if (is_omit_timespec(&ft.mtime)) {
8331 modify_mtime = false;
8334 status = smb_set_file_time(conn,
8340 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8341 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8346 /****************************************************************************
8347 Deal with SMB_SET_FILE_UNIX_INFO2.
8348 ****************************************************************************/
8350 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8351 struct smb_request *req,
8355 struct smb_filename *smb_fname)
8358 uint32_t smb_fflags;
8361 if (total_data < 116) {
8362 return NT_STATUS_INVALID_PARAMETER;
8365 /* Start by setting all the fields that are common between UNIX_BASIC
8368 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8370 if (!NT_STATUS_IS_OK(status)) {
8374 smb_fflags = IVAL(pdata, 108);
8375 smb_fmask = IVAL(pdata, 112);
8377 /* NB: We should only attempt to alter the file flags if the client
8378 * sends a non-zero mask.
8380 if (smb_fmask != 0) {
8381 int stat_fflags = 0;
8383 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8384 smb_fmask, &stat_fflags)) {
8385 /* Client asked to alter a flag we don't understand. */
8386 return NT_STATUS_INVALID_PARAMETER;
8389 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
8390 DBG_WARNING("Can't change flags on symlink %s\n",
8391 smb_fname_str_dbg(smb_fname));
8392 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8394 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
8395 return map_nt_error_from_unix(errno);
8399 /* XXX: need to add support for changing the create_time here. You
8400 * can do this for paths on Darwin with setattrlist(2). The right way
8401 * to hook this up is probably by extending the VFS utimes interface.
8404 return NT_STATUS_OK;
8407 /****************************************************************************
8408 Create a directory with POSIX semantics.
8409 ****************************************************************************/
8411 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8412 struct smb_request *req,
8415 struct smb_filename *smb_fname,
8416 int *pdata_return_size)
8418 NTSTATUS status = NT_STATUS_OK;
8419 uint32_t raw_unixmode = 0;
8420 mode_t unixmode = (mode_t)0;
8421 files_struct *fsp = NULL;
8422 uint16_t info_level_return = 0;
8424 char *pdata = *ppdata;
8425 struct smb2_create_blobs *posx = NULL;
8427 if (total_data < 18) {
8428 return NT_STATUS_INVALID_PARAMETER;
8431 raw_unixmode = IVAL(pdata,8);
8432 /* Next 4 bytes are not yet defined. */
8434 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8435 PERM_NEW_DIR, &unixmode);
8436 if (!NT_STATUS_IS_OK(status)) {
8440 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8441 if (!NT_STATUS_IS_OK(status)) {
8442 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8447 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8448 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8450 status = SMB_VFS_CREATE_FILE(
8453 smb_fname, /* fname */
8454 FILE_READ_ATTRIBUTES, /* access_mask */
8455 FILE_SHARE_NONE, /* share_access */
8456 FILE_CREATE, /* create_disposition*/
8457 FILE_DIRECTORY_FILE, /* create_options */
8458 0, /* file_attributes */
8459 0, /* oplock_request */
8461 0, /* allocation_size */
8462 0, /* private_flags */
8467 posx, /* in_context_blobs */
8468 NULL); /* out_context_blobs */
8472 if (NT_STATUS_IS_OK(status)) {
8473 close_file_free(req, &fsp, NORMAL_CLOSE);
8476 info_level_return = SVAL(pdata,16);
8478 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8479 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8480 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8481 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8483 *pdata_return_size = 12;
8486 /* Realloc the data size */
8487 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8488 if (*ppdata == NULL) {
8489 *pdata_return_size = 0;
8490 return NT_STATUS_NO_MEMORY;
8494 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8495 SSVAL(pdata,2,0); /* No fnum. */
8496 SIVAL(pdata,4,info); /* Was directory created. */
8498 switch (info_level_return) {
8499 case SMB_QUERY_FILE_UNIX_BASIC:
8500 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8501 SSVAL(pdata,10,0); /* Padding. */
8502 store_file_unix_basic(conn, pdata + 12, fsp,
8505 case SMB_QUERY_FILE_UNIX_INFO2:
8506 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8507 SSVAL(pdata,10,0); /* Padding. */
8508 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8512 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8513 SSVAL(pdata,10,0); /* Padding. */
8520 /****************************************************************************
8521 Open/Create a file with POSIX semantics.
8522 ****************************************************************************/
8524 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8525 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8527 static NTSTATUS smb_posix_open(connection_struct *conn,
8528 struct smb_request *req,
8531 struct smb_filename *smb_fname,
8532 int *pdata_return_size)
8534 bool extended_oplock_granted = False;
8535 char *pdata = *ppdata;
8537 uint32_t wire_open_mode = 0;
8538 uint32_t raw_unixmode = 0;
8539 uint32_t attributes = 0;
8540 uint32_t create_disp = 0;
8541 uint32_t access_mask = 0;
8542 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8543 NTSTATUS status = NT_STATUS_OK;
8544 mode_t unixmode = (mode_t)0;
8545 files_struct *fsp = NULL;
8546 int oplock_request = 0;
8548 uint16_t info_level_return = 0;
8549 struct smb2_create_blobs *posx = NULL;
8551 if (total_data < 18) {
8552 return NT_STATUS_INVALID_PARAMETER;
8555 flags = IVAL(pdata,0);
8556 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8557 if (oplock_request) {
8558 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8561 wire_open_mode = IVAL(pdata,4);
8563 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8564 return smb_posix_mkdir(conn, req,
8571 switch (wire_open_mode & SMB_ACCMODE) {
8573 access_mask = SMB_O_RDONLY_MAPPING;
8576 access_mask = SMB_O_WRONLY_MAPPING;
8579 access_mask = (SMB_O_RDONLY_MAPPING|
8580 SMB_O_WRONLY_MAPPING);
8583 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8584 (unsigned int)wire_open_mode ));
8585 return NT_STATUS_INVALID_PARAMETER;
8588 wire_open_mode &= ~SMB_ACCMODE;
8590 /* First take care of O_CREAT|O_EXCL interactions. */
8591 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8592 case (SMB_O_CREAT | SMB_O_EXCL):
8593 /* File exists fail. File not exist create. */
8594 create_disp = FILE_CREATE;
8597 /* File exists open. File not exist create. */
8598 create_disp = FILE_OPEN_IF;
8601 /* O_EXCL on its own without O_CREAT is undefined.
8602 We deliberately ignore it as some versions of
8603 Linux CIFSFS can send a bare O_EXCL on the
8604 wire which other filesystems in the kernel
8605 ignore. See bug 9519 for details. */
8610 /* File exists open. File not exist fail. */
8611 create_disp = FILE_OPEN;
8614 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8615 (unsigned int)wire_open_mode ));
8616 return NT_STATUS_INVALID_PARAMETER;
8619 /* Next factor in the effects of O_TRUNC. */
8620 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8622 if (wire_open_mode & SMB_O_TRUNC) {
8623 switch (create_disp) {
8625 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8626 /* Leave create_disp alone as
8627 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8629 /* File exists fail. File not exist create. */
8632 /* SMB_O_CREAT | SMB_O_TRUNC */
8633 /* File exists overwrite. File not exist create. */
8634 create_disp = FILE_OVERWRITE_IF;
8638 /* File exists overwrite. File not exist fail. */
8639 create_disp = FILE_OVERWRITE;
8642 /* Cannot get here. */
8643 smb_panic("smb_posix_open: logic error");
8644 return NT_STATUS_INVALID_PARAMETER;
8648 raw_unixmode = IVAL(pdata,8);
8649 /* Next 4 bytes are not yet defined. */
8651 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8652 (VALID_STAT(smb_fname->st) ?
8653 PERM_EXISTING_FILE : PERM_NEW_FILE),
8656 if (!NT_STATUS_IS_OK(status)) {
8660 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8661 if (!NT_STATUS_IS_OK(status)) {
8662 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8667 if (wire_open_mode & SMB_O_SYNC) {
8668 create_options |= FILE_WRITE_THROUGH;
8670 if (wire_open_mode & SMB_O_APPEND) {
8671 access_mask |= FILE_APPEND_DATA;
8673 if (wire_open_mode & SMB_O_DIRECT) {
8674 attributes |= FILE_FLAG_NO_BUFFERING;
8677 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8678 VALID_STAT_OF_DIR(smb_fname->st)) {
8679 if (access_mask != SMB_O_RDONLY_MAPPING) {
8680 return NT_STATUS_FILE_IS_A_DIRECTORY;
8682 create_options &= ~FILE_NON_DIRECTORY_FILE;
8683 create_options |= FILE_DIRECTORY_FILE;
8686 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8687 smb_fname_str_dbg(smb_fname),
8688 (unsigned int)wire_open_mode,
8689 (unsigned int)unixmode ));
8691 status = SMB_VFS_CREATE_FILE(
8694 smb_fname, /* fname */
8695 access_mask, /* access_mask */
8696 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8698 create_disp, /* create_disposition*/
8699 create_options, /* create_options */
8700 attributes, /* file_attributes */
8701 oplock_request, /* oplock_request */
8703 0, /* allocation_size */
8704 0, /* private_flags */
8709 posx, /* in_context_blobs */
8710 NULL); /* out_context_blobs */
8714 if (!NT_STATUS_IS_OK(status)) {
8718 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8719 extended_oplock_granted = True;
8722 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8723 extended_oplock_granted = True;
8726 info_level_return = SVAL(pdata,16);
8728 /* Allocate the correct return size. */
8730 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8731 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8732 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8733 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8735 *pdata_return_size = 12;
8738 /* Realloc the data size */
8739 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8740 if (*ppdata == NULL) {
8741 close_file_free(req, &fsp, ERROR_CLOSE);
8742 *pdata_return_size = 0;
8743 return NT_STATUS_NO_MEMORY;
8747 if (extended_oplock_granted) {
8748 if (flags & REQUEST_BATCH_OPLOCK) {
8749 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8751 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8753 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8754 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8756 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8759 SSVAL(pdata,2,fsp->fnum);
8760 SIVAL(pdata,4,info); /* Was file created etc. */
8762 switch (info_level_return) {
8763 case SMB_QUERY_FILE_UNIX_BASIC:
8764 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8765 SSVAL(pdata,10,0); /* padding. */
8766 store_file_unix_basic(conn, pdata + 12, fsp,
8769 case SMB_QUERY_FILE_UNIX_INFO2:
8770 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8771 SSVAL(pdata,10,0); /* padding. */
8772 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8776 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8777 SSVAL(pdata,10,0); /* padding. */
8780 return NT_STATUS_OK;
8783 /****************************************************************************
8784 Delete a file with POSIX semantics.
8785 ****************************************************************************/
8787 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8788 struct smb_request *req,
8791 struct smb_filename *smb_fname)
8793 NTSTATUS status = NT_STATUS_OK;
8794 files_struct *fsp = NULL;
8798 int create_options = 0;
8799 struct share_mode_lock *lck = NULL;
8800 bool other_nonposix_opens;
8801 struct smb2_create_blobs *posx = NULL;
8803 if (total_data < 2) {
8804 return NT_STATUS_INVALID_PARAMETER;
8807 flags = SVAL(pdata,0);
8809 if (!VALID_STAT(smb_fname->st)) {
8810 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8813 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8814 !VALID_STAT_OF_DIR(smb_fname->st)) {
8815 return NT_STATUS_NOT_A_DIRECTORY;
8818 DEBUG(10,("smb_posix_unlink: %s %s\n",
8819 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8820 smb_fname_str_dbg(smb_fname)));
8822 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8823 create_options |= FILE_DIRECTORY_FILE;
8826 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8827 if (!NT_STATUS_IS_OK(status)) {
8828 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8833 status = SMB_VFS_CREATE_FILE(
8836 smb_fname, /* fname */
8837 DELETE_ACCESS, /* access_mask */
8838 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8840 FILE_OPEN, /* create_disposition*/
8841 create_options, /* create_options */
8842 0, /* file_attributes */
8843 0, /* oplock_request */
8845 0, /* allocation_size */
8846 0, /* private_flags */
8851 posx, /* in_context_blobs */
8852 NULL); /* out_context_blobs */
8856 if (!NT_STATUS_IS_OK(status)) {
8861 * Don't lie to client. If we can't really delete due to
8862 * non-POSIX opens return SHARING_VIOLATION.
8865 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8867 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8868 "lock for file %s\n", fsp_str_dbg(fsp)));
8869 close_file_free(req, &fsp, NORMAL_CLOSE);
8870 return NT_STATUS_INVALID_PARAMETER;
8873 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8874 if (other_nonposix_opens) {
8875 /* Fail with sharing violation. */
8877 close_file_free(req, &fsp, NORMAL_CLOSE);
8878 return NT_STATUS_SHARING_VIOLATION;
8882 * Set the delete on close.
8884 status = smb_set_file_disposition_info(conn,
8892 if (!NT_STATUS_IS_OK(status)) {
8893 close_file_free(req, &fsp, NORMAL_CLOSE);
8896 return close_file_free(req, &fsp, NORMAL_CLOSE);
8899 static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
8900 struct smb_request *req,
8901 TALLOC_CTX *mem_ctx,
8902 uint16_t info_level,
8903 struct smb_filename *smb_fname,
8909 char *pdata = *ppdata;
8910 NTSTATUS status = NT_STATUS_OK;
8911 int data_return_size = 0;
8915 if (!CAN_WRITE(conn)) {
8916 /* Allow POSIX opens. The open path will deny
8917 * any non-readonly opens. */
8918 if (info_level != SMB_POSIX_PATH_OPEN) {
8919 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8923 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
8924 smb_fname_str_dbg(smb_fname),
8929 switch (info_level) {
8930 case SMB_SET_FILE_UNIX_BASIC:
8932 status = smb_set_file_unix_basic(conn, req,
8940 case SMB_SET_FILE_UNIX_INFO2:
8942 status = smb_set_file_unix_info2(conn, req,
8950 case SMB_SET_FILE_UNIX_LINK:
8952 if (smb_fname == NULL) {
8953 /* We must have a pathname for this. */
8954 return NT_STATUS_INVALID_LEVEL;
8956 status = smb_set_file_unix_link(conn, req, pdata,
8957 total_data, smb_fname);
8961 case SMB_SET_FILE_UNIX_HLINK:
8963 if (smb_fname == NULL) {
8964 /* We must have a pathname for this. */
8965 return NT_STATUS_INVALID_LEVEL;
8967 status = smb_set_file_unix_hlink(conn, req,
8973 #if defined(HAVE_POSIX_ACLS)
8974 case SMB_SET_POSIX_ACL:
8976 status = smb_set_posix_acl(conn,
8986 case SMB_SET_POSIX_LOCK:
8989 return NT_STATUS_INVALID_LEVEL;
8991 status = smb_set_posix_lock(conn, req,
8992 pdata, total_data, fsp);
8996 case SMB_POSIX_PATH_OPEN:
8998 if (smb_fname == NULL) {
8999 /* We must have a pathname for this. */
9000 return NT_STATUS_INVALID_LEVEL;
9003 status = smb_posix_open(conn, req,
9011 case SMB_POSIX_PATH_UNLINK:
9013 if (smb_fname == NULL) {
9014 /* We must have a pathname for this. */
9015 return NT_STATUS_INVALID_LEVEL;
9018 status = smb_posix_unlink(conn, req,
9026 return NT_STATUS_INVALID_LEVEL;
9029 if (!NT_STATUS_IS_OK(status)) {
9033 *ret_data_size = data_return_size;
9034 return NT_STATUS_OK;
9037 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
9038 struct smb_request *req,
9039 TALLOC_CTX *mem_ctx,
9040 uint16_t info_level,
9042 struct smb_filename *smb_fname,
9043 char **ppdata, int total_data,
9046 char *pdata = *ppdata;
9047 NTSTATUS status = NT_STATUS_OK;
9048 int data_return_size = 0;
9050 if (INFO_LEVEL_IS_UNIX(info_level)) {
9051 if (!lp_smb1_unix_extensions()) {
9052 return NT_STATUS_INVALID_LEVEL;
9054 if (!req->posix_pathnames) {
9055 return NT_STATUS_INVALID_LEVEL;
9057 status = smbd_do_posix_setfilepathinfo(conn,
9066 if (!NT_STATUS_IS_OK(status)) {
9069 *ret_data_size = data_return_size;
9070 return NT_STATUS_OK;
9075 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
9076 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
9078 info_level, total_data));
9080 switch (info_level) {
9082 case SMB_INFO_STANDARD:
9084 status = smb_set_info_standard(conn,
9092 case SMB_INFO_SET_EA:
9094 status = smb_info_set_ea(conn,
9102 case SMB_SET_FILE_BASIC_INFO:
9103 case SMB_FILE_BASIC_INFORMATION:
9105 status = smb_set_file_basic_info(conn,
9113 case SMB_FILE_ALLOCATION_INFORMATION:
9114 case SMB_SET_FILE_ALLOCATION_INFO:
9116 status = smb_set_file_allocation_info(conn, req,
9124 case SMB_FILE_END_OF_FILE_INFORMATION:
9125 case SMB_SET_FILE_END_OF_FILE_INFO:
9128 * XP/Win7 both fail after the createfile with
9129 * SMB_SET_FILE_END_OF_FILE_INFO but not
9130 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9131 * The level is known here, so pass it down
9135 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
9137 status = smb_set_file_end_of_file_info(conn, req,
9146 case SMB_FILE_DISPOSITION_INFORMATION:
9147 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
9150 /* JRA - We used to just ignore this on a path ?
9151 * Shouldn't this be invalid level on a pathname
9154 if (tran_call != TRANSACT2_SETFILEINFO) {
9155 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
9158 status = smb_set_file_disposition_info(conn,
9166 case SMB_FILE_POSITION_INFORMATION:
9168 status = smb_file_position_information(conn,
9175 case SMB_FILE_FULL_EA_INFORMATION:
9177 status = smb_set_file_full_ea_info(conn,
9184 /* From tridge Samba4 :
9185 * MODE_INFORMATION in setfileinfo (I have no
9186 * idea what "mode information" on a file is - it takes a value of 0,
9187 * 2, 4 or 6. What could it be?).
9190 case SMB_FILE_MODE_INFORMATION:
9192 status = smb_file_mode_information(conn,
9198 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9199 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9200 case SMB_FILE_SHORT_NAME_INFORMATION:
9201 return NT_STATUS_NOT_SUPPORTED;
9203 case SMB_FILE_RENAME_INFORMATION:
9205 status = smb_file_rename_information(conn, req,
9211 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9213 /* SMB2 rename information. */
9214 status = smb2_file_rename_information(conn, req,
9220 case SMB_FILE_LINK_INFORMATION:
9222 status = smb_file_link_information(conn, req,
9229 return NT_STATUS_INVALID_LEVEL;
9232 if (!NT_STATUS_IS_OK(status)) {
9236 *ret_data_size = data_return_size;
9237 return NT_STATUS_OK;
9240 /****************************************************************************
9241 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9242 ****************************************************************************/
9244 static void call_trans2setfilepathinfo(connection_struct *conn,
9245 struct smb_request *req,
9246 unsigned int tran_call,
9247 char **pparams, int total_params,
9248 char **ppdata, int total_data,
9249 unsigned int max_data_bytes)
9251 char *params = *pparams;
9252 char *pdata = *ppdata;
9253 uint16_t info_level;
9254 struct smb_filename *smb_fname = NULL;
9255 files_struct *fsp = NULL;
9256 NTSTATUS status = NT_STATUS_OK;
9257 int data_return_size = 0;
9261 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9265 if (tran_call == TRANSACT2_SETFILEINFO) {
9266 if (total_params < 4) {
9267 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9271 fsp = file_fsp(req, SVAL(params,0));
9272 /* Basic check for non-null fsp. */
9273 if (!check_fsp_open(conn, req, fsp)) {
9276 info_level = SVAL(params,2);
9278 if (INFO_LEVEL_IS_UNIX(info_level)) {
9279 if (!lp_smb1_unix_extensions()) {
9280 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9283 if (!req->posix_pathnames) {
9284 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9289 smb_fname = fsp->fsp_name;
9291 if (fsp_get_pathref_fd(fsp) == -1) {
9293 * This is actually a SETFILEINFO on a directory
9294 * handle (returned from an NT SMB). NT5.0 seems
9295 * to do this call. JRA.
9297 ret = vfs_stat(conn, smb_fname);
9299 DBG_NOTICE("vfs_stat of %s failed (%s)\n",
9300 smb_fname_str_dbg(smb_fname),
9303 map_nt_error_from_unix(errno));
9306 } else if (fsp->print_file) {
9308 * Doing a DELETE_ON_CLOSE should cancel a print job.
9310 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9311 uint32_t new_private_options =
9312 fh_get_private_options(fsp->fh);
9313 new_private_options |=
9314 NTCREATEX_FLAG_DELETE_ON_CLOSE;
9315 fh_set_private_options(fsp->fh,
9316 new_private_options);
9318 DEBUG(3,("call_trans2setfilepathinfo: "
9319 "Cancelling print job (%s)\n",
9323 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9329 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9334 * Original code - this is an open file.
9336 status = vfs_stat_fsp(fsp);
9337 if (!NT_STATUS_IS_OK(status)) {
9338 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9339 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9340 nt_errstr(status)));
9341 reply_nterror(req, status);
9347 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9348 bool require_existing_object = true;
9351 if (total_params < 7) {
9352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9356 info_level = SVAL(params,0);
9358 if (INFO_LEVEL_IS_UNIX(info_level)) {
9359 if (!lp_smb1_unix_extensions()) {
9360 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9363 if (!req->posix_pathnames) {
9364 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9369 if (req->posix_pathnames) {
9370 srvstr_get_path_posix(req,
9379 srvstr_get_path(req,
9388 if (!NT_STATUS_IS_OK(status)) {
9389 reply_nterror(req, status);
9393 status = filename_convert(req, conn,
9398 if (!NT_STATUS_IS_OK(status)) {
9399 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9400 reply_botherror(req,
9401 NT_STATUS_PATH_NOT_COVERED,
9402 ERRSRV, ERRbadpath);
9405 reply_nterror(req, status);
9410 * smb_fname->fsp may be NULL if smb_fname points at a symlink
9411 * and we're in POSIX context, so be careful when using fsp
9412 * below, it can still be NULL.
9414 fsp = smb_fname->fsp;
9417 * There are 4 info levels which can
9418 * create a new object in the filesystem.
9420 * SMB_SET_FILE_UNIX_LINK -> creates POSIX symlink.
9421 * SMB_POSIX_PATH_OPEN -> creates POSIX file or directory.
9422 * SMB_SET_FILE_UNIX_BASIC:
9423 * SMB_SET_FILE_UNIX_INFO2: can create a POSIX special file.
9425 * These info levels do not require an existing object.
9427 switch (info_level) {
9428 case SMB_SET_FILE_UNIX_LINK:
9429 case SMB_POSIX_PATH_OPEN:
9430 case SMB_SET_FILE_UNIX_BASIC:
9431 case SMB_SET_FILE_UNIX_INFO2:
9432 require_existing_object = false;
9438 if (!VALID_STAT(smb_fname->st) && require_existing_object) {
9439 reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
9443 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9444 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9446 info_level,total_data));
9448 /* Realloc the parameter size */
9449 *pparams = (char *)SMB_REALLOC(*pparams,2);
9450 if (*pparams == NULL) {
9451 reply_nterror(req, NT_STATUS_NO_MEMORY);
9458 status = smbd_do_setfilepathinfo(conn, req, req,
9464 if (!NT_STATUS_IS_OK(status)) {
9465 if (open_was_deferred(req->xconn, req->mid)) {
9466 /* We have re-scheduled this call. */
9469 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9470 bool ok = defer_smb1_sharing_violation(req);
9475 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9476 /* We have re-scheduled this call. */
9479 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9480 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9481 ERRSRV, ERRbadpath);
9484 if (info_level == SMB_POSIX_PATH_OPEN) {
9485 reply_openerror(req, status);
9490 * Invalid EA name needs to return 2 param bytes,
9491 * not a zero-length error packet.
9493 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9494 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9497 reply_nterror(req, status);
9502 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9508 /****************************************************************************
9509 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9510 ****************************************************************************/
9512 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9513 char **pparams, int total_params,
9514 char **ppdata, int total_data,
9515 unsigned int max_data_bytes)
9517 struct files_struct *fsp = NULL;
9518 struct smb_filename *smb_dname = NULL;
9519 char *params = *pparams;
9520 char *pdata = *ppdata;
9521 char *directory = NULL;
9522 NTSTATUS status = NT_STATUS_OK;
9523 struct ea_list *ea_list = NULL;
9524 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9525 TALLOC_CTX *ctx = talloc_tos();
9527 if (!CAN_WRITE(conn)) {
9528 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9532 if (total_params < 5) {
9533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9537 if (req->posix_pathnames) {
9538 srvstr_get_path_posix(ctx,
9547 srvstr_get_path(ctx,
9556 if (!NT_STATUS_IS_OK(status)) {
9557 reply_nterror(req, status);
9561 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9563 status = filename_convert(ctx,
9570 if (!NT_STATUS_IS_OK(status)) {
9571 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9572 reply_botherror(req,
9573 NT_STATUS_PATH_NOT_COVERED,
9574 ERRSRV, ERRbadpath);
9577 reply_nterror(req, status);
9582 * OS/2 workplace shell seems to send SET_EA requests of "null"
9583 * length (4 bytes containing IVAL 4).
9584 * They seem to have no effect. Bug #3212. JRA.
9587 if (total_data && (total_data != 4)) {
9588 /* Any data in this call is an EA list. */
9589 if (total_data < 10) {
9590 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9594 if (IVAL(pdata,0) > total_data) {
9595 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9596 IVAL(pdata,0), (unsigned int)total_data));
9597 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9601 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9608 if (!lp_ea_support(SNUM(conn))) {
9609 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9613 /* If total_data == 4 Windows doesn't care what values
9614 * are placed in that field, it just ignores them.
9615 * The System i QNTC IBM SMB client puts bad values here,
9616 * so ignore them. */
9618 status = SMB_VFS_CREATE_FILE(
9621 smb_dname, /* fname */
9622 MAXIMUM_ALLOWED_ACCESS, /* access_mask */
9623 FILE_SHARE_NONE, /* share_access */
9624 FILE_CREATE, /* create_disposition*/
9625 FILE_DIRECTORY_FILE, /* create_options */
9626 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
9627 0, /* oplock_request */
9629 0, /* allocation_size */
9630 0, /* private_flags */
9635 NULL, NULL); /* create context */
9636 if (!NT_STATUS_IS_OK(status)) {
9637 reply_nterror(req, status);
9641 /* Try and set any given EA. */
9643 status = set_ea(conn, fsp, ea_list);
9644 if (!NT_STATUS_IS_OK(status)) {
9645 reply_nterror(req, status);
9650 /* Realloc the parameter and data sizes */
9651 *pparams = (char *)SMB_REALLOC(*pparams,2);
9652 if(*pparams == NULL) {
9653 reply_nterror(req, NT_STATUS_NO_MEMORY);
9660 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9664 close_file_free(NULL, &fsp, NORMAL_CLOSE);
9666 TALLOC_FREE(smb_dname);
9670 /****************************************************************************
9671 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9672 We don't actually do this - we just send a null response.
9673 ****************************************************************************/
9675 static void call_trans2findnotifyfirst(connection_struct *conn,
9676 struct smb_request *req,
9677 char **pparams, int total_params,
9678 char **ppdata, int total_data,
9679 unsigned int max_data_bytes)
9681 char *params = *pparams;
9682 uint16_t info_level;
9684 if (total_params < 6) {
9685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9689 info_level = SVAL(params,4);
9690 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9692 switch (info_level) {
9697 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9701 /* Realloc the parameter and data sizes */
9702 *pparams = (char *)SMB_REALLOC(*pparams,6);
9703 if (*pparams == NULL) {
9704 reply_nterror(req, NT_STATUS_NO_MEMORY);
9709 SSVAL(params,0,fnf_handle);
9710 SSVAL(params,2,0); /* No changes */
9711 SSVAL(params,4,0); /* No EA errors */
9718 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9723 /****************************************************************************
9724 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9725 changes). Currently this does nothing.
9726 ****************************************************************************/
9728 static void call_trans2findnotifynext(connection_struct *conn,
9729 struct smb_request *req,
9730 char **pparams, int total_params,
9731 char **ppdata, int total_data,
9732 unsigned int max_data_bytes)
9734 char *params = *pparams;
9736 DEBUG(3,("call_trans2findnotifynext\n"));
9738 /* Realloc the parameter and data sizes */
9739 *pparams = (char *)SMB_REALLOC(*pparams,4);
9740 if (*pparams == NULL) {
9741 reply_nterror(req, NT_STATUS_NO_MEMORY);
9746 SSVAL(params,0,0); /* No changes */
9747 SSVAL(params,2,0); /* No EA errors */
9749 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9754 /****************************************************************************
9755 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9756 ****************************************************************************/
9758 static void call_trans2getdfsreferral(connection_struct *conn,
9759 struct smb_request *req,
9760 char **pparams, int total_params,
9761 char **ppdata, int total_data,
9762 unsigned int max_data_bytes)
9764 char *params = *pparams;
9765 char *pathname = NULL;
9767 int max_referral_level;
9768 NTSTATUS status = NT_STATUS_OK;
9769 TALLOC_CTX *ctx = talloc_tos();
9771 DEBUG(10,("call_trans2getdfsreferral\n"));
9773 if (total_params < 3) {
9774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9778 max_referral_level = SVAL(params,0);
9780 if(!lp_host_msdfs()) {
9781 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9785 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9786 total_params - 2, STR_TERMINATE);
9788 reply_nterror(req, NT_STATUS_NOT_FOUND);
9791 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9792 ppdata,&status)) < 0) {
9793 reply_nterror(req, status);
9797 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9798 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9799 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9804 #define LMCAT_SPL 0x53
9805 #define LMFUNC_GETJOBID 0x60
9807 /****************************************************************************
9808 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9809 ****************************************************************************/
9811 static void call_trans2ioctl(connection_struct *conn,
9812 struct smb_request *req,
9813 char **pparams, int total_params,
9814 char **ppdata, int total_data,
9815 unsigned int max_data_bytes)
9817 const struct loadparm_substitution *lp_sub =
9818 loadparm_s3_global_substitution();
9819 char *pdata = *ppdata;
9820 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9824 /* check for an invalid fid before proceeding */
9827 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9831 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9832 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9833 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9834 if (*ppdata == NULL) {
9835 reply_nterror(req, NT_STATUS_NO_MEMORY);
9840 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9841 CAN ACCEPT THIS IN UNICODE. JRA. */
9844 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9846 status = srvstr_push(pdata, req->flags2, pdata + 2,
9847 lp_netbios_name(), 15,
9848 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9849 if (!NT_STATUS_IS_OK(status)) {
9850 reply_nterror(req, status);
9853 status = srvstr_push(pdata, req->flags2, pdata+18,
9854 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9855 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9856 if (!NT_STATUS_IS_OK(status)) {
9857 reply_nterror(req, status);
9860 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9865 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9866 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9869 /****************************************************************************
9870 Reply to a SMBfindclose (stop trans2 directory search).
9871 ****************************************************************************/
9873 void reply_findclose(struct smb_request *req)
9876 struct smbd_server_connection *sconn = req->sconn;
9877 files_struct *fsp = NULL;
9879 START_PROFILE(SMBfindclose);
9882 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9883 END_PROFILE(SMBfindclose);
9887 dptr_num = SVALS(req->vwv+0, 0);
9889 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9892 * OS/2 seems to use -1 to indicate "close all directories"
9893 * This has to mean on this specific connection struct.
9895 if (dptr_num == -1) {
9896 dptr_closecnum(req->conn);
9898 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9901 close_file_free(NULL, &fsp, NORMAL_CLOSE);
9905 reply_outbuf(req, 0, 0);
9907 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9909 END_PROFILE(SMBfindclose);
9913 /****************************************************************************
9914 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9915 ****************************************************************************/
9917 void reply_findnclose(struct smb_request *req)
9921 START_PROFILE(SMBfindnclose);
9924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9925 END_PROFILE(SMBfindnclose);
9929 dptr_num = SVAL(req->vwv+0, 0);
9931 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9933 /* We never give out valid handles for a
9934 findnotifyfirst - so any dptr_num is ok here.
9937 reply_outbuf(req, 0, 0);
9939 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9941 END_PROFILE(SMBfindnclose);
9945 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9946 struct trans_state *state)
9948 if (get_Protocol() >= PROTOCOL_NT1) {
9949 req->flags2 |= 0x40; /* IS_LONG_NAME */
9950 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9953 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9954 if (state->call != TRANSACT2_QFSINFO &&
9955 state->call != TRANSACT2_SETFSINFO) {
9956 DEBUG(0,("handle_trans2: encryption required "
9958 (unsigned int)state->call));
9959 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9964 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9966 /* Now we must call the relevant TRANS2 function */
9967 switch(state->call) {
9968 case TRANSACT2_OPEN:
9970 START_PROFILE(Trans2_open);
9971 call_trans2open(conn, req,
9972 &state->param, state->total_param,
9973 &state->data, state->total_data,
9974 state->max_data_return);
9975 END_PROFILE(Trans2_open);
9979 case TRANSACT2_FINDFIRST:
9981 START_PROFILE(Trans2_findfirst);
9982 call_trans2findfirst(conn, req,
9983 &state->param, state->total_param,
9984 &state->data, state->total_data,
9985 state->max_data_return);
9986 END_PROFILE(Trans2_findfirst);
9990 case TRANSACT2_FINDNEXT:
9992 START_PROFILE(Trans2_findnext);
9993 call_trans2findnext(conn, req,
9994 &state->param, state->total_param,
9995 &state->data, state->total_data,
9996 state->max_data_return);
9997 END_PROFILE(Trans2_findnext);
10001 case TRANSACT2_QFSINFO:
10003 START_PROFILE(Trans2_qfsinfo);
10004 call_trans2qfsinfo(conn, req,
10005 &state->param, state->total_param,
10006 &state->data, state->total_data,
10007 state->max_data_return);
10008 END_PROFILE(Trans2_qfsinfo);
10012 case TRANSACT2_SETFSINFO:
10014 START_PROFILE(Trans2_setfsinfo);
10015 call_trans2setfsinfo(conn, req,
10016 &state->param, state->total_param,
10017 &state->data, state->total_data,
10018 state->max_data_return);
10019 END_PROFILE(Trans2_setfsinfo);
10023 case TRANSACT2_QPATHINFO:
10024 case TRANSACT2_QFILEINFO:
10026 START_PROFILE(Trans2_qpathinfo);
10027 call_trans2qfilepathinfo(conn, req, state->call,
10028 &state->param, state->total_param,
10029 &state->data, state->total_data,
10030 state->max_data_return);
10031 END_PROFILE(Trans2_qpathinfo);
10035 case TRANSACT2_SETPATHINFO:
10036 case TRANSACT2_SETFILEINFO:
10038 START_PROFILE(Trans2_setpathinfo);
10039 call_trans2setfilepathinfo(conn, req, state->call,
10040 &state->param, state->total_param,
10041 &state->data, state->total_data,
10042 state->max_data_return);
10043 END_PROFILE(Trans2_setpathinfo);
10047 case TRANSACT2_FINDNOTIFYFIRST:
10049 START_PROFILE(Trans2_findnotifyfirst);
10050 call_trans2findnotifyfirst(conn, req,
10051 &state->param, state->total_param,
10052 &state->data, state->total_data,
10053 state->max_data_return);
10054 END_PROFILE(Trans2_findnotifyfirst);
10058 case TRANSACT2_FINDNOTIFYNEXT:
10060 START_PROFILE(Trans2_findnotifynext);
10061 call_trans2findnotifynext(conn, req,
10062 &state->param, state->total_param,
10063 &state->data, state->total_data,
10064 state->max_data_return);
10065 END_PROFILE(Trans2_findnotifynext);
10069 case TRANSACT2_MKDIR:
10071 START_PROFILE(Trans2_mkdir);
10072 call_trans2mkdir(conn, req,
10073 &state->param, state->total_param,
10074 &state->data, state->total_data,
10075 state->max_data_return);
10076 END_PROFILE(Trans2_mkdir);
10080 case TRANSACT2_GET_DFS_REFERRAL:
10082 START_PROFILE(Trans2_get_dfs_referral);
10083 call_trans2getdfsreferral(conn, req,
10084 &state->param, state->total_param,
10085 &state->data, state->total_data,
10086 state->max_data_return);
10087 END_PROFILE(Trans2_get_dfs_referral);
10091 case TRANSACT2_IOCTL:
10093 START_PROFILE(Trans2_ioctl);
10094 call_trans2ioctl(conn, req,
10095 &state->param, state->total_param,
10096 &state->data, state->total_data,
10097 state->max_data_return);
10098 END_PROFILE(Trans2_ioctl);
10103 /* Error in request */
10104 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
10105 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10109 /****************************************************************************
10110 Reply to a SMBtrans2.
10111 ****************************************************************************/
10113 void reply_trans2(struct smb_request *req)
10115 connection_struct *conn = req->conn;
10116 unsigned int dsoff;
10117 unsigned int dscnt;
10118 unsigned int psoff;
10119 unsigned int pscnt;
10120 unsigned int tran_call;
10121 struct trans_state *state;
10124 START_PROFILE(SMBtrans2);
10126 if (req->wct < 14) {
10127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10128 END_PROFILE(SMBtrans2);
10132 dsoff = SVAL(req->vwv+12, 0);
10133 dscnt = SVAL(req->vwv+11, 0);
10134 psoff = SVAL(req->vwv+10, 0);
10135 pscnt = SVAL(req->vwv+9, 0);
10136 tran_call = SVAL(req->vwv+14, 0);
10138 result = allow_new_trans(conn->pending_trans, req->mid);
10139 if (!NT_STATUS_IS_OK(result)) {
10140 DEBUG(2, ("Got invalid trans2 request: %s\n",
10141 nt_errstr(result)));
10142 reply_nterror(req, result);
10143 END_PROFILE(SMBtrans2);
10147 if (IS_IPC(conn)) {
10148 switch (tran_call) {
10149 /* List the allowed trans2 calls on IPC$ */
10150 case TRANSACT2_OPEN:
10151 case TRANSACT2_GET_DFS_REFERRAL:
10152 case TRANSACT2_QFILEINFO:
10153 case TRANSACT2_QFSINFO:
10154 case TRANSACT2_SETFSINFO:
10157 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10158 END_PROFILE(SMBtrans2);
10163 if ((state = talloc(conn, struct trans_state)) == NULL) {
10164 DEBUG(0, ("talloc failed\n"));
10165 reply_nterror(req, NT_STATUS_NO_MEMORY);
10166 END_PROFILE(SMBtrans2);
10170 state->cmd = SMBtrans2;
10172 state->mid = req->mid;
10173 state->vuid = req->vuid;
10174 state->setup_count = SVAL(req->vwv+13, 0);
10175 state->setup = NULL;
10176 state->total_param = SVAL(req->vwv+0, 0);
10177 state->param = NULL;
10178 state->total_data = SVAL(req->vwv+1, 0);
10179 state->data = NULL;
10180 state->max_param_return = SVAL(req->vwv+2, 0);
10181 state->max_data_return = SVAL(req->vwv+3, 0);
10182 state->max_setup_return = SVAL(req->vwv+4, 0);
10183 state->close_on_completion = BITSETW(req->vwv+5, 0);
10184 state->one_way = BITSETW(req->vwv+5, 1);
10186 state->call = tran_call;
10188 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10189 is so as a sanity check */
10190 if (state->setup_count != 1) {
10192 * Need to have rc=0 for ioctl to get job id for OS/2.
10193 * Network printing will fail if function is not successful.
10194 * Similar function in reply.c will be used if protocol
10195 * is LANMAN1.0 instead of LM1.2X002.
10196 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10197 * outbuf doesn't have to be set(only job id is used).
10199 if ( (state->setup_count == 4)
10200 && (tran_call == TRANSACT2_IOCTL)
10201 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10202 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10203 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10205 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10206 DEBUG(2,("Transaction is %d\n",tran_call));
10207 TALLOC_FREE(state);
10208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10209 END_PROFILE(SMBtrans2);
10214 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10217 if (state->total_data) {
10219 if (smb_buffer_oob(state->total_data, 0, dscnt)
10220 || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10224 /* Can't use talloc here, the core routines do realloc on the
10225 * params and data. */
10226 state->data = (char *)SMB_MALLOC(state->total_data);
10227 if (state->data == NULL) {
10228 DEBUG(0,("reply_trans2: data malloc fail for %u "
10229 "bytes !\n", (unsigned int)state->total_data));
10230 TALLOC_FREE(state);
10231 reply_nterror(req, NT_STATUS_NO_MEMORY);
10232 END_PROFILE(SMBtrans2);
10236 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10239 if (state->total_param) {
10241 if (smb_buffer_oob(state->total_param, 0, pscnt)
10242 || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
10246 /* Can't use talloc here, the core routines do realloc on the
10247 * params and data. */
10248 state->param = (char *)SMB_MALLOC(state->total_param);
10249 if (state->param == NULL) {
10250 DEBUG(0,("reply_trans: param malloc fail for %u "
10251 "bytes !\n", (unsigned int)state->total_param));
10252 SAFE_FREE(state->data);
10253 TALLOC_FREE(state);
10254 reply_nterror(req, NT_STATUS_NO_MEMORY);
10255 END_PROFILE(SMBtrans2);
10259 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10262 state->received_data = dscnt;
10263 state->received_param = pscnt;
10265 if ((state->received_param == state->total_param) &&
10266 (state->received_data == state->total_data)) {
10268 handle_trans2(conn, req, state);
10270 SAFE_FREE(state->data);
10271 SAFE_FREE(state->param);
10272 TALLOC_FREE(state);
10273 END_PROFILE(SMBtrans2);
10277 DLIST_ADD(conn->pending_trans, state);
10279 /* We need to send an interim response then receive the rest
10280 of the parameter/data bytes */
10281 reply_outbuf(req, 0, 0);
10282 show_msg((char *)req->outbuf);
10283 END_PROFILE(SMBtrans2);
10288 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10289 SAFE_FREE(state->data);
10290 SAFE_FREE(state->param);
10291 TALLOC_FREE(state);
10292 END_PROFILE(SMBtrans2);
10293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10297 /****************************************************************************
10298 Reply to a SMBtranss2
10299 ****************************************************************************/
10301 void reply_transs2(struct smb_request *req)
10303 connection_struct *conn = req->conn;
10304 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10305 struct trans_state *state;
10307 START_PROFILE(SMBtranss2);
10309 show_msg((const char *)req->inbuf);
10311 /* Windows clients expect all replies to
10312 a transact secondary (SMBtranss2 0x33)
10313 to have a command code of transact
10314 (SMBtrans2 0x32). See bug #8989
10315 and also [MS-CIFS] section 2.2.4.47.2
10318 req->cmd = SMBtrans2;
10320 if (req->wct < 8) {
10321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10322 END_PROFILE(SMBtranss2);
10326 for (state = conn->pending_trans; state != NULL;
10327 state = state->next) {
10328 if (state->mid == req->mid) {
10333 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10335 END_PROFILE(SMBtranss2);
10339 /* Revise state->total_param and state->total_data in case they have
10340 changed downwards */
10342 if (SVAL(req->vwv+0, 0) < state->total_param)
10343 state->total_param = SVAL(req->vwv+0, 0);
10344 if (SVAL(req->vwv+1, 0) < state->total_data)
10345 state->total_data = SVAL(req->vwv+1, 0);
10347 pcnt = SVAL(req->vwv+2, 0);
10348 poff = SVAL(req->vwv+3, 0);
10349 pdisp = SVAL(req->vwv+4, 0);
10351 dcnt = SVAL(req->vwv+5, 0);
10352 doff = SVAL(req->vwv+6, 0);
10353 ddisp = SVAL(req->vwv+7, 0);
10355 state->received_param += pcnt;
10356 state->received_data += dcnt;
10358 if ((state->received_data > state->total_data) ||
10359 (state->received_param > state->total_param))
10363 if (smb_buffer_oob(state->total_param, pdisp, pcnt)
10364 || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
10367 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10371 if (smb_buffer_oob(state->total_data, ddisp, dcnt)
10372 || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
10375 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10378 if ((state->received_param < state->total_param) ||
10379 (state->received_data < state->total_data)) {
10380 END_PROFILE(SMBtranss2);
10384 handle_trans2(conn, req, state);
10386 DLIST_REMOVE(conn->pending_trans, state);
10387 SAFE_FREE(state->data);
10388 SAFE_FREE(state->param);
10389 TALLOC_FREE(state);
10391 END_PROFILE(SMBtranss2);
10396 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10397 DLIST_REMOVE(conn->pending_trans, state);
10398 SAFE_FREE(state->data);
10399 SAFE_FREE(state->param);
10400 TALLOC_FREE(state);
10401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10402 END_PROFILE(SMBtranss2);