2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 /****************************************************************************
58 Check if an open file handle or pathname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62 const files_struct *fsp,
66 const SMB_STRUCT_STAT *pst = NULL;
69 pst = &fsp->fsp_name->st;
71 int ret = vfs_stat_smb_basename(conn,
75 return map_nt_error_from_unix(errno);
79 if (S_ISLNK(pst->st_ex_mode)) {
80 return NT_STATUS_ACCESS_DENIED;
85 NTSTATUS check_access_fsp(const struct files_struct *fsp,
88 if (!(fsp->access_mask & access_mask)) {
89 return NT_STATUS_ACCESS_DENIED;
94 /********************************************************************
95 The canonical "check access" based on object handle or path function.
96 ********************************************************************/
98 NTSTATUS check_access(connection_struct *conn,
100 const struct smb_filename *smb_fname,
101 uint32_t access_mask)
106 status = check_access_fsp(fsp, access_mask);
108 status = smbd_check_access_rights(conn, smb_fname,
115 /********************************************************************
116 Roundup a value to the nearest allocation roundup size boundary.
117 Only do this for Windows clients.
118 ********************************************************************/
120 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
122 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
124 /* Only roundup for Windows clients. */
125 enum remote_arch_types ra_type = get_remote_arch();
126 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
127 val = SMB_ROUNDUP(val,rval);
132 /********************************************************************
133 Create a 64 bit FileIndex. If the file is on the same device as
134 the root of the share, just return the 64-bit inode. If it isn't,
135 mangle as we used to do.
136 ********************************************************************/
138 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
141 if (conn->base_share_dev == psbuf->st_ex_dev) {
142 return (uint64_t)psbuf->st_ex_ino;
144 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
145 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
149 /****************************************************************************
150 Utility functions for dealing with extended attributes.
151 ****************************************************************************/
153 /****************************************************************************
154 Refuse to allow clients to overwrite our private xattrs.
155 ****************************************************************************/
157 bool samba_private_attr_name(const char *unix_ea_name)
159 static const char * const prohibited_ea_names[] = {
160 SAMBA_POSIX_INHERITANCE_EA_NAME,
161 SAMBA_XATTR_DOS_ATTRIB,
169 for (i = 0; prohibited_ea_names[i]; i++) {
170 if (strequal( prohibited_ea_names[i], unix_ea_name))
173 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
174 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
180 /****************************************************************************
181 Get one EA value. Fill in a struct ea_struct.
182 ****************************************************************************/
184 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
185 files_struct *fsp, const char *fname,
186 const char *ea_name, struct ea_struct *pea)
188 /* Get the value of this xattr. Max size is 64k. */
189 size_t attr_size = 256;
195 val = talloc_realloc(mem_ctx, val, char, attr_size);
197 return NT_STATUS_NO_MEMORY;
200 if (fsp && fsp->fh->fd != -1) {
201 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
203 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
206 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
212 return map_nt_error_from_unix(errno);
215 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
216 dump_data(10, (uint8_t *)val, sizeret);
219 if (strnequal(ea_name, "user.", 5)) {
220 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
222 pea->name = talloc_strdup(mem_ctx, ea_name);
224 if (pea->name == NULL) {
226 return NT_STATUS_NO_MEMORY;
228 pea->value.data = (unsigned char *)val;
229 pea->value.length = (size_t)sizeret;
233 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
234 files_struct *fsp, const char *fname,
235 char ***pnames, size_t *pnum_names)
237 /* Get a list of all xattrs. Max namesize is 64k. */
238 size_t ea_namelist_size = 1024;
239 char *ea_namelist = NULL;
244 ssize_t sizeret = -1;
246 if (!lp_ea_support(SNUM(conn))) {
255 * TALLOC the result early to get the talloc hierarchy right.
258 names = talloc_array(mem_ctx, char *, 1);
260 DEBUG(0, ("talloc failed\n"));
261 return NT_STATUS_NO_MEMORY;
264 while (ea_namelist_size <= 65536) {
266 ea_namelist = talloc_realloc(
267 names, ea_namelist, char, ea_namelist_size);
268 if (ea_namelist == NULL) {
269 DEBUG(0, ("talloc failed\n"));
271 return NT_STATUS_NO_MEMORY;
274 if (fsp && fsp->fh->fd != -1) {
275 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
278 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
282 if ((sizeret == -1) && (errno == ERANGE)) {
283 ea_namelist_size *= 2;
292 return map_nt_error_from_unix(errno);
295 DEBUG(10, ("%s: ea_namelist size = %u\n",
296 __func__, (unsigned int)sizeret));
308 * Ensure the result is 0-terminated
311 if (ea_namelist[sizeret-1] != '\0') {
313 return NT_STATUS_INTERNAL_ERROR;
321 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
325 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
327 DEBUG(0, ("talloc failed\n"));
329 return NT_STATUS_NO_MEMORY;
335 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
336 names[num_names++] = p;
344 *pnum_names = num_names;
348 /****************************************************************************
349 Return a linked list of the total EA's. Plus the total size
350 ****************************************************************************/
352 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
353 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
355 /* Get a list of all xattrs. Max namesize is 64k. */
358 struct ea_list *ea_list_head = NULL;
364 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
367 if (!NT_STATUS_IS_OK(status)) {
371 if (num_names == 0) {
376 for (i=0; i<num_names; i++) {
377 struct ea_list *listp;
380 if (strnequal(names[i], "system.", 7)
381 || samba_private_attr_name(names[i]))
385 * Filter out any underlying POSIX EA names
386 * that a Windows client can't handle.
388 if (!lp_posix_pathnames() &&
389 is_invalid_windows_ea_name(names[i])) {
393 listp = talloc(mem_ctx, struct ea_list);
395 return NT_STATUS_NO_MEMORY;
398 status = get_ea_value(listp, conn, fsp,
402 if (!NT_STATUS_IS_OK(status)) {
407 if (listp->ea.value.length == 0) {
409 * We can never return a zero length EA.
410 * Windows reports the EA's as corrupted.
416 push_ascii_fstring(dos_ea_name, listp->ea.name);
419 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
421 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
422 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
423 (unsigned int)listp->ea.value.length));
425 DLIST_ADD_END(ea_list_head, listp);
429 /* Add on 4 for total length. */
430 if (*pea_total_len) {
434 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
435 (unsigned int)*pea_total_len));
437 *ea_list = ea_list_head;
441 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
442 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
447 if (!lp_ea_support(SNUM(conn))) {
451 if (is_ntfs_stream_smb_fname(smb_fname)) {
452 return NT_STATUS_INVALID_PARAMETER;
455 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
458 /****************************************************************************
459 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
461 ****************************************************************************/
463 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
464 connection_struct *conn, struct ea_list *ea_list)
466 unsigned int ret_data_size = 4;
469 SMB_ASSERT(total_data_size >= 4);
471 if (!lp_ea_support(SNUM(conn))) {
476 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
479 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
480 dos_namelen = strlen(dos_ea_name);
481 if (dos_namelen > 255 || dos_namelen == 0) {
484 if (ea_list->ea.value.length > 65535) {
487 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
491 /* We know we have room. */
492 SCVAL(p,0,ea_list->ea.flags);
493 SCVAL(p,1,dos_namelen);
494 SSVAL(p,2,ea_list->ea.value.length);
495 strlcpy(p+4, dos_ea_name, dos_namelen+1);
496 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
498 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
499 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
502 ret_data_size = PTR_DIFF(p, pdata);
503 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
504 SIVAL(pdata,0,ret_data_size);
505 return ret_data_size;
508 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
510 unsigned int total_data_size,
511 unsigned int *ret_data_size,
512 connection_struct *conn,
513 struct ea_list *ea_list)
515 uint8_t *p = (uint8_t *)pdata;
516 uint8_t *last_start = NULL;
517 bool do_store_data = (pdata != NULL);
521 if (!lp_ea_support(SNUM(conn))) {
522 return NT_STATUS_NO_EAS_ON_FILE;
525 for (; ea_list; ea_list = ea_list->next) {
531 if (last_start != NULL && do_store_data) {
532 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
536 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
537 dos_namelen = strlen(dos_ea_name);
538 if (dos_namelen > 255 || dos_namelen == 0) {
539 return NT_STATUS_INTERNAL_ERROR;
541 if (ea_list->ea.value.length > 65535) {
542 return NT_STATUS_INTERNAL_ERROR;
545 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
548 pad = (4 - (this_size % 4)) % 4;
553 if (this_size > total_data_size) {
554 return NT_STATUS_INFO_LENGTH_MISMATCH;
557 /* We know we have room. */
558 SIVAL(p, 0x00, 0); /* next offset */
559 SCVAL(p, 0x04, ea_list->ea.flags);
560 SCVAL(p, 0x05, dos_namelen);
561 SSVAL(p, 0x06, ea_list->ea.value.length);
562 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
563 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
565 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
569 total_data_size -= this_size;
575 *ret_data_size = PTR_DIFF(p, pdata);
576 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
580 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
582 size_t total_ea_len = 0;
584 struct ea_list *ea_list = NULL;
586 if (!lp_ea_support(SNUM(conn))) {
589 mem_ctx = talloc_stackframe();
591 /* If this is a stream fsp, then we need to instead find the
592 * estimated ea len from the main file, not the stream
593 * (streams cannot have EAs), but the estimate isn't just 0 in
595 if (is_ntfs_stream_smb_fname(smb_fname)) {
598 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
599 if(conn->sconn->using_smb2) {
601 unsigned int ret_data_size;
603 * We're going to be using fill_ea_chained_buffer() to
604 * marshall EA's - this size is significantly larger
605 * than the SMB1 buffer. Re-calculate the size without
608 status = fill_ea_chained_buffer(mem_ctx,
614 if (!NT_STATUS_IS_OK(status)) {
617 total_ea_len = ret_data_size;
619 TALLOC_FREE(mem_ctx);
623 /****************************************************************************
624 Ensure the EA name is case insensitive by matching any existing EA name.
625 ****************************************************************************/
627 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
630 TALLOC_CTX *mem_ctx = talloc_tos();
631 struct ea_list *ea_list;
632 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
633 if (!NT_STATUS_IS_OK(status)) {
637 for (; ea_list; ea_list = ea_list->next) {
638 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
639 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
640 &unix_ea_name[5], ea_list->ea.name));
641 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
647 /****************************************************************************
648 Set or delete an extended attribute.
649 ****************************************************************************/
651 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
652 const struct smb_filename *smb_fname, struct ea_list *ea_list)
657 if (!lp_ea_support(SNUM(conn))) {
658 return NT_STATUS_EAS_NOT_SUPPORTED;
661 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
662 if (!NT_STATUS_IS_OK(status)) {
666 /* Setting EAs on streams isn't supported. */
667 if (is_ntfs_stream_smb_fname(smb_fname)) {
668 return NT_STATUS_INVALID_PARAMETER;
672 * Filter out invalid Windows EA names - before
673 * we set *any* of them.
676 if (ea_list_has_invalid_name(ea_list)) {
677 return STATUS_INVALID_EA_NAME;
680 fname = smb_fname->base_name;
682 for (;ea_list; ea_list = ea_list->next) {
684 fstring unix_ea_name;
686 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
687 fstrcat(unix_ea_name, ea_list->ea.name);
689 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
691 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
693 if (samba_private_attr_name(unix_ea_name)) {
694 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
695 return NT_STATUS_ACCESS_DENIED;
698 if (ea_list->ea.value.length == 0) {
699 /* Remove the attribute. */
700 if (fsp && (fsp->fh->fd != -1)) {
701 DEBUG(10,("set_ea: deleting ea name %s on "
702 "file %s by file descriptor.\n",
703 unix_ea_name, fsp_str_dbg(fsp)));
704 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
706 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
707 unix_ea_name, fname));
708 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
711 /* Removing a non existent attribute always succeeds. */
712 if (ret == -1 && errno == ENOATTR) {
713 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
719 if (fsp && (fsp->fh->fd != -1)) {
720 DEBUG(10,("set_ea: setting ea name %s on file "
721 "%s by file descriptor.\n",
722 unix_ea_name, fsp_str_dbg(fsp)));
723 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
724 ea_list->ea.value.data, ea_list->ea.value.length, 0);
726 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
727 unix_ea_name, fname));
728 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
729 ea_list->ea.value.data, ea_list->ea.value.length, 0);
735 if (errno == ENOTSUP) {
736 return NT_STATUS_EAS_NOT_SUPPORTED;
739 return map_nt_error_from_unix(errno);
745 /****************************************************************************
746 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
747 ****************************************************************************/
749 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
751 struct ea_list *ea_list_head = NULL;
752 size_t converted_size, offset = 0;
754 while (offset + 2 < data_size) {
755 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
756 unsigned int namelen = CVAL(pdata,offset);
758 offset++; /* Go past the namelen byte. */
760 /* integer wrap paranioa. */
761 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
762 (offset > data_size) || (namelen > data_size) ||
763 (offset + namelen >= data_size)) {
766 /* Ensure the name is null terminated. */
767 if (pdata[offset + namelen] != '\0') {
770 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
772 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
773 "failed: %s", strerror(errno)));
779 offset += (namelen + 1); /* Go past the name + terminating zero. */
780 DLIST_ADD_END(ea_list_head, eal);
781 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
787 /****************************************************************************
788 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
789 ****************************************************************************/
791 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
793 struct ea_list *ea_list_head = NULL;
795 size_t bytes_used = 0;
797 while (offset < data_size) {
798 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
804 DLIST_ADD_END(ea_list_head, eal);
805 offset += bytes_used;
811 /****************************************************************************
812 Count the total EA size needed.
813 ****************************************************************************/
815 static size_t ea_list_size(struct ea_list *ealist)
818 struct ea_list *listp;
821 for (listp = ealist; listp; listp = listp->next) {
822 push_ascii_fstring(dos_ea_name, listp->ea.name);
823 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
825 /* Add on 4 for total length. */
833 /****************************************************************************
834 Return a union of EA's from a file list and a list of names.
835 The TALLOC context for the two lists *MUST* be identical as we steal
836 memory from one list to add to another. JRA.
837 ****************************************************************************/
839 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
841 struct ea_list *nlistp, *flistp;
843 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
844 for (flistp = file_list; flistp; flistp = flistp->next) {
845 if (strequal(nlistp->ea.name, flistp->ea.name)) {
851 /* Copy the data from this entry. */
852 nlistp->ea.flags = flistp->ea.flags;
853 nlistp->ea.value = flistp->ea.value;
856 nlistp->ea.flags = 0;
857 ZERO_STRUCT(nlistp->ea.value);
861 *total_ea_len = ea_list_size(name_list);
865 /****************************************************************************
866 Send the required number of replies back.
867 We assume all fields other than the data fields are
868 set correctly for the type of call.
869 HACK ! Always assumes smb_setup field is zero.
870 ****************************************************************************/
872 void send_trans2_replies(connection_struct *conn,
873 struct smb_request *req,
881 /* As we are using a protocol > LANMAN1 then the max_send
882 variable must have been set in the sessetupX call.
883 This takes precedence over the max_xmit field in the
884 global struct. These different max_xmit variables should
885 be merged as this is now too confusing */
887 int data_to_send = datasize;
888 int params_to_send = paramsize;
890 const char *pp = params;
891 const char *pd = pdata;
892 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
893 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
894 int data_alignment_offset = 0;
895 bool overflow = False;
896 struct smbXsrv_connection *xconn = req->xconn;
897 int max_send = xconn->smb1.sessions.max_send;
899 /* Modify the data_to_send and datasize and set the error if
900 we're trying to send more than max_data_bytes. We still send
901 the part of the packet(s) that fit. Strange, but needed
904 if (max_data_bytes > 0 && datasize > max_data_bytes) {
905 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
906 max_data_bytes, datasize ));
907 datasize = data_to_send = max_data_bytes;
911 /* If there genuinely are no parameters or data to send just send the empty packet */
913 if(params_to_send == 0 && data_to_send == 0) {
914 reply_outbuf(req, 10, 0);
915 if (NT_STATUS_V(status)) {
918 ntstatus_to_dos(status, &eclass, &ecode);
919 error_packet_set((char *)req->outbuf,
920 eclass, ecode, status,
923 show_msg((char *)req->outbuf);
924 if (!srv_send_smb(xconn,
927 IS_CONN_ENCRYPTED(conn),
929 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
931 TALLOC_FREE(req->outbuf);
935 /* When sending params and data ensure that both are nicely aligned */
936 /* Only do this alignment when there is also data to send - else
937 can cause NT redirector problems. */
939 if (((params_to_send % 4) != 0) && (data_to_send != 0))
940 data_alignment_offset = 4 - (params_to_send % 4);
942 /* Space is bufsize minus Netbios over TCP header minus SMB header */
943 /* The alignment_offset is to align the param bytes on an even byte
944 boundary. NT 4.0 Beta needs this to work correctly. */
946 useable_space = max_send - (smb_size
949 + data_alignment_offset);
951 if (useable_space < 0) {
952 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
953 "= %d!!!", useable_space));
954 exit_server_cleanly("send_trans2_replies: Not enough space");
957 while (params_to_send || data_to_send) {
958 /* Calculate whether we will totally or partially fill this packet */
960 total_sent_thistime = params_to_send + data_to_send;
962 /* We can never send more than useable_space */
964 * Note that 'useable_space' does not include the alignment offsets,
965 * but we must include the alignment offsets in the calculation of
966 * the length of the data we send over the wire, as the alignment offsets
967 * are sent here. Fix from Marc_Jacobsen@hp.com.
970 total_sent_thistime = MIN(total_sent_thistime, useable_space);
972 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
973 + data_alignment_offset);
975 /* Set total params and data to be sent */
976 SSVAL(req->outbuf,smb_tprcnt,paramsize);
977 SSVAL(req->outbuf,smb_tdrcnt,datasize);
979 /* Calculate how many parameters and data we can fit into
980 * this packet. Parameters get precedence
983 params_sent_thistime = MIN(params_to_send,useable_space);
984 data_sent_thistime = useable_space - params_sent_thistime;
985 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
987 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
989 /* smb_proff is the offset from the start of the SMB header to the
990 parameter bytes, however the first 4 bytes of outbuf are
991 the Netbios over TCP header. Thus use smb_base() to subtract
992 them from the calculation */
994 SSVAL(req->outbuf,smb_proff,
995 ((smb_buf(req->outbuf)+alignment_offset)
996 - smb_base(req->outbuf)));
998 if(params_sent_thistime == 0)
999 SSVAL(req->outbuf,smb_prdisp,0);
1001 /* Absolute displacement of param bytes sent in this packet */
1002 SSVAL(req->outbuf,smb_prdisp,pp - params);
1004 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1005 if(data_sent_thistime == 0) {
1006 SSVAL(req->outbuf,smb_droff,0);
1007 SSVAL(req->outbuf,smb_drdisp, 0);
1009 /* The offset of the data bytes is the offset of the
1010 parameter bytes plus the number of parameters being sent this time */
1011 SSVAL(req->outbuf, smb_droff,
1012 ((smb_buf(req->outbuf)+alignment_offset)
1013 - smb_base(req->outbuf))
1014 + params_sent_thistime + data_alignment_offset);
1015 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1018 /* Initialize the padding for alignment */
1020 if (alignment_offset != 0) {
1021 memset(smb_buf(req->outbuf), 0, alignment_offset);
1024 /* Copy the param bytes into the packet */
1026 if(params_sent_thistime) {
1027 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1028 params_sent_thistime);
1031 /* Copy in the data bytes */
1032 if(data_sent_thistime) {
1033 if (data_alignment_offset != 0) {
1034 memset((smb_buf(req->outbuf)+alignment_offset+
1035 params_sent_thistime), 0,
1036 data_alignment_offset);
1038 memcpy(smb_buf(req->outbuf)+alignment_offset
1039 +params_sent_thistime+data_alignment_offset,
1040 pd,data_sent_thistime);
1043 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1044 params_sent_thistime, data_sent_thistime, useable_space));
1045 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1046 params_to_send, data_to_send, paramsize, datasize));
1049 error_packet_set((char *)req->outbuf,
1050 ERRDOS,ERRbufferoverflow,
1051 STATUS_BUFFER_OVERFLOW,
1053 } else if (NT_STATUS_V(status)) {
1056 ntstatus_to_dos(status, &eclass, &ecode);
1057 error_packet_set((char *)req->outbuf,
1058 eclass, ecode, status,
1062 /* Send the packet */
1063 show_msg((char *)req->outbuf);
1064 if (!srv_send_smb(xconn,
1065 (char *)req->outbuf,
1066 true, req->seqnum+1,
1067 IS_CONN_ENCRYPTED(conn),
1069 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1071 TALLOC_FREE(req->outbuf);
1073 pp += params_sent_thistime;
1074 pd += data_sent_thistime;
1076 params_to_send -= params_sent_thistime;
1077 data_to_send -= data_sent_thistime;
1080 if(params_to_send < 0 || data_to_send < 0) {
1081 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1082 params_to_send, data_to_send));
1090 /****************************************************************************
1091 Reply to a TRANSACT2_OPEN.
1092 ****************************************************************************/
1094 static void call_trans2open(connection_struct *conn,
1095 struct smb_request *req,
1096 char **pparams, int total_params,
1097 char **ppdata, int total_data,
1098 unsigned int max_data_bytes)
1100 struct smb_filename *smb_fname = NULL;
1101 char *params = *pparams;
1102 char *pdata = *ppdata;
1105 bool oplock_request;
1107 bool return_additional_info;
1116 int fattr=0,mtime=0;
1117 SMB_INO_T inode = 0;
1120 struct ea_list *ea_list = NULL;
1123 uint32_t access_mask;
1124 uint32_t share_mode;
1125 uint32_t create_disposition;
1126 uint32_t create_options = 0;
1127 uint32_t private_flags = 0;
1128 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1129 TALLOC_CTX *ctx = talloc_tos();
1132 * Ensure we have enough parameters to perform the operation.
1135 if (total_params < 29) {
1136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1140 flags = SVAL(params, 0);
1141 deny_mode = SVAL(params, 2);
1142 open_attr = SVAL(params,6);
1143 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1144 if (oplock_request) {
1145 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1149 return_additional_info = BITSETW(params,0);
1150 open_sattr = SVAL(params, 4);
1151 open_time = make_unix_date3(params+8);
1153 open_ofun = SVAL(params,12);
1154 open_size = IVAL(params,14);
1155 pname = ¶ms[28];
1158 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1162 if (req->posix_pathnames) {
1163 srvstr_get_path_posix(ctx,
1172 srvstr_get_path(ctx,
1181 if (!NT_STATUS_IS_OK(status)) {
1182 reply_nterror(req, status);
1186 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1187 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1188 (unsigned int)open_ofun, open_size));
1190 status = filename_convert(ctx,
1192 req->flags2 & FLAGS2_DFS_PATHNAMES,
1197 if (!NT_STATUS_IS_OK(status)) {
1198 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1199 reply_botherror(req,
1200 NT_STATUS_PATH_NOT_COVERED,
1201 ERRSRV, ERRbadpath);
1204 reply_nterror(req, status);
1208 if (open_ofun == 0) {
1209 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1213 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1215 &access_mask, &share_mode,
1216 &create_disposition,
1219 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1223 /* Any data in this call is an EA list. */
1224 if (total_data && (total_data != 4)) {
1225 if (total_data < 10) {
1226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1230 if (IVAL(pdata,0) > total_data) {
1231 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1232 IVAL(pdata,0), (unsigned int)total_data));
1233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1237 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1244 if (!lp_ea_support(SNUM(conn))) {
1245 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1249 if (ea_list_has_invalid_name(ea_list)) {
1251 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1252 if(*pparams == NULL ) {
1253 reply_nterror(req, NT_STATUS_NO_MEMORY);
1257 memset(params, '\0', param_len);
1258 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1259 params, param_len, NULL, 0, max_data_bytes);
1264 status = SMB_VFS_CREATE_FILE(
1267 0, /* root_dir_fid */
1268 smb_fname, /* fname */
1269 access_mask, /* access_mask */
1270 share_mode, /* share_access */
1271 create_disposition, /* create_disposition*/
1272 create_options, /* create_options */
1273 open_attr, /* file_attributes */
1274 oplock_request, /* oplock_request */
1276 open_size, /* allocation_size */
1279 ea_list, /* ea_list */
1281 &smb_action, /* psbuf */
1282 NULL, NULL); /* create context */
1284 if (!NT_STATUS_IS_OK(status)) {
1285 if (open_was_deferred(req->xconn, req->mid)) {
1286 /* We have re-scheduled this call. */
1289 reply_openerror(req, status);
1293 size = get_file_size_stat(&smb_fname->st);
1294 fattr = dos_mode(conn, smb_fname);
1295 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1296 inode = smb_fname->st.st_ex_ino;
1297 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1298 close_file(req, fsp, ERROR_CLOSE);
1299 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1303 /* Realloc the size of parameters and data we will return */
1304 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1305 if(*pparams == NULL ) {
1306 reply_nterror(req, NT_STATUS_NO_MEMORY);
1311 SSVAL(params,0,fsp->fnum);
1312 SSVAL(params,2,fattr);
1313 srv_put_dos_date2(params,4, mtime);
1314 SIVAL(params,8, (uint32_t)size);
1315 SSVAL(params,12,deny_mode);
1316 SSVAL(params,14,0); /* open_type - file or directory. */
1317 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1319 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1320 smb_action |= EXTENDED_OPLOCK_GRANTED;
1323 SSVAL(params,18,smb_action);
1326 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1328 SIVAL(params,20,inode);
1329 SSVAL(params,24,0); /* Padding. */
1331 uint32_t ea_size = estimate_ea_size(conn, fsp,
1333 SIVAL(params, 26, ea_size);
1335 SIVAL(params, 26, 0);
1338 /* Send the required number of replies */
1339 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1341 TALLOC_FREE(smb_fname);
1344 /*********************************************************
1345 Routine to check if a given string matches exactly.
1346 as a special case a mask of "." does NOT match. That
1347 is required for correct wildcard semantics
1348 Case can be significant or not.
1349 **********************************************************/
1351 static bool exact_match(bool has_wild,
1352 bool case_sensitive,
1356 if (mask[0] == '.' && mask[1] == 0) {
1364 if (case_sensitive) {
1365 return strcmp(str,mask)==0;
1367 return strcasecmp_m(str,mask) == 0;
1371 /****************************************************************************
1372 Return the filetype for UNIX extensions.
1373 ****************************************************************************/
1375 static uint32_t unix_filetype(mode_t mode)
1378 return UNIX_TYPE_FILE;
1379 else if(S_ISDIR(mode))
1380 return UNIX_TYPE_DIR;
1382 else if(S_ISLNK(mode))
1383 return UNIX_TYPE_SYMLINK;
1386 else if(S_ISCHR(mode))
1387 return UNIX_TYPE_CHARDEV;
1390 else if(S_ISBLK(mode))
1391 return UNIX_TYPE_BLKDEV;
1394 else if(S_ISFIFO(mode))
1395 return UNIX_TYPE_FIFO;
1398 else if(S_ISSOCK(mode))
1399 return UNIX_TYPE_SOCKET;
1402 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1403 return UNIX_TYPE_UNKNOWN;
1406 /****************************************************************************
1407 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1408 ****************************************************************************/
1410 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1412 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1413 const SMB_STRUCT_STAT *psbuf,
1415 enum perm_type ptype,
1420 if (perms == SMB_MODE_NO_CHANGE) {
1421 if (!VALID_STAT(*psbuf)) {
1422 return NT_STATUS_INVALID_PARAMETER;
1424 *ret_perms = psbuf->st_ex_mode;
1425 return NT_STATUS_OK;
1429 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1430 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1431 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1432 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1433 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1434 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1435 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1436 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1437 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1439 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1442 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1445 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1448 if (ptype == PERM_NEW_FILE) {
1450 * "create mask"/"force create mode" are
1451 * only applied to new files, not existing ones.
1453 ret &= lp_create_mask(SNUM(conn));
1454 /* Add in force bits */
1455 ret |= lp_force_create_mode(SNUM(conn));
1456 } else if (ptype == PERM_NEW_DIR) {
1458 * "directory mask"/"force directory mode" are
1459 * only applied to new directories, not existing ones.
1461 ret &= lp_directory_mask(SNUM(conn));
1462 /* Add in force bits */
1463 ret |= lp_force_directory_mode(SNUM(conn));
1467 return NT_STATUS_OK;
1470 /****************************************************************************
1471 Needed to show the msdfs symlinks as directories. Modifies psbuf
1472 to be a directory if it's a msdfs link.
1473 ****************************************************************************/
1475 static bool check_msdfs_link(connection_struct *conn,
1476 const char *pathname,
1477 SMB_STRUCT_STAT *psbuf)
1479 int saved_errno = errno;
1480 if(lp_host_msdfs() &&
1481 lp_msdfs_root(SNUM(conn)) &&
1482 is_msdfs_link(conn, pathname, psbuf)) {
1484 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1487 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1488 errno = saved_errno;
1491 errno = saved_errno;
1496 /****************************************************************************
1497 Get a level dependent lanman2 dir entry.
1498 ****************************************************************************/
1500 struct smbd_dirptr_lanman2_state {
1501 connection_struct *conn;
1502 uint32_t info_level;
1503 bool check_mangled_names;
1505 bool got_exact_match;
1508 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1514 struct smbd_dirptr_lanman2_state *state =
1515 (struct smbd_dirptr_lanman2_state *)private_data;
1517 char mangled_name[13]; /* mangled 8.3 name. */
1521 /* Mangle fname if it's an illegal name. */
1522 if (mangle_must_mangle(dname, state->conn->params)) {
1524 * Slow path - ensure we can push the original name as UCS2. If
1525 * not, then just don't return this name.
1529 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1530 uint8_t *tmp = talloc_array(talloc_tos(),
1534 status = srvstr_push(NULL,
1535 FLAGS2_UNICODE_STRINGS,
1544 if (!NT_STATUS_IS_OK(status)) {
1548 ok = name_to_8_3(dname, mangled_name,
1549 true, state->conn->params);
1553 fname = mangled_name;
1558 got_match = exact_match(state->has_wild,
1559 state->conn->case_sensitive,
1561 state->got_exact_match = got_match;
1563 got_match = mask_match(fname, mask,
1564 state->conn->case_sensitive);
1567 if(!got_match && state->check_mangled_names &&
1568 !mangle_is_8_3(fname, false, state->conn->params)) {
1570 * It turns out that NT matches wildcards against
1571 * both long *and* short names. This may explain some
1572 * of the wildcard wierdness from old DOS clients
1573 * that some people have been seeing.... JRA.
1575 /* Force the mangling into 8.3. */
1576 ok = name_to_8_3(fname, mangled_name,
1577 false, state->conn->params);
1582 got_match = exact_match(state->has_wild,
1583 state->conn->case_sensitive,
1584 mangled_name, mask);
1585 state->got_exact_match = got_match;
1587 got_match = mask_match(mangled_name, mask,
1588 state->conn->case_sensitive);
1596 *_fname = talloc_strdup(ctx, fname);
1597 if (*_fname == NULL) {
1604 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1606 struct smb_filename *smb_fname,
1609 struct smbd_dirptr_lanman2_state *state =
1610 (struct smbd_dirptr_lanman2_state *)private_data;
1611 bool ms_dfs_link = false;
1614 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1615 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1616 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1617 "Couldn't lstat [%s] (%s)\n",
1618 smb_fname_str_dbg(smb_fname),
1622 } else if (!VALID_STAT(smb_fname->st) &&
1623 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1624 /* Needed to show the msdfs symlinks as
1627 ms_dfs_link = check_msdfs_link(state->conn,
1628 smb_fname->base_name,
1631 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1632 "Couldn't stat [%s] (%s)\n",
1633 smb_fname_str_dbg(smb_fname),
1640 mode = dos_mode_msdfs(state->conn, smb_fname);
1642 mode = dos_mode(state->conn, smb_fname);
1649 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1650 connection_struct *conn,
1652 uint32_t info_level,
1653 struct ea_list *name_list,
1654 bool check_mangled_names,
1655 bool requires_resume_key,
1658 const struct smb_filename *smb_fname,
1659 int space_remaining,
1665 uint64_t *last_entry_off)
1667 char *p, *q, *pdata = *ppdata;
1669 uint64_t file_size = 0;
1670 uint64_t allocation_size = 0;
1671 uint64_t file_index = 0;
1673 struct timespec mdate_ts = {0};
1674 struct timespec adate_ts = {0};
1675 struct timespec cdate_ts = {0};
1676 struct timespec create_date_ts = {0};
1677 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1679 char *last_entry_ptr;
1684 struct readdir_attr_data *readdir_attr_data = NULL;
1686 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1687 file_size = get_file_size_stat(&smb_fname->st);
1689 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1691 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1692 if (!NT_STATUS_IS_OK(status)) {
1693 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1698 file_index = get_FileIndex(conn, &smb_fname->st);
1700 mdate_ts = smb_fname->st.st_ex_mtime;
1701 adate_ts = smb_fname->st.st_ex_atime;
1702 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1703 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1705 if (lp_dos_filetime_resolution(SNUM(conn))) {
1706 dos_filetime_timespec(&create_date_ts);
1707 dos_filetime_timespec(&mdate_ts);
1708 dos_filetime_timespec(&adate_ts);
1709 dos_filetime_timespec(&cdate_ts);
1712 create_date = convert_timespec_to_time_t(create_date_ts);
1713 mdate = convert_timespec_to_time_t(mdate_ts);
1714 adate = convert_timespec_to_time_t(adate_ts);
1716 /* align the record */
1717 SMB_ASSERT(align >= 1);
1719 off = (int)PTR_DIFF(pdata, base_data);
1720 pad = (off + (align-1)) & ~(align-1);
1723 if (pad && pad > space_remaining) {
1724 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1725 "for padding (wanted %u, had %d)\n",
1728 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1732 /* initialize padding to 0 */
1734 memset(pdata, 0, pad);
1736 space_remaining -= pad;
1738 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1748 switch (info_level) {
1749 case SMB_FIND_INFO_STANDARD:
1750 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1751 if(requires_resume_key) {
1755 srv_put_dos_date2(p,0,create_date);
1756 srv_put_dos_date2(p,4,adate);
1757 srv_put_dos_date2(p,8,mdate);
1758 SIVAL(p,12,(uint32_t)file_size);
1759 SIVAL(p,16,(uint32_t)allocation_size);
1763 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1764 p += ucs2_align(base_data, p, 0);
1766 status = srvstr_push(base_data, flags2, p,
1767 fname, PTR_DIFF(end_data, p),
1768 STR_TERMINATE, &len);
1769 if (!NT_STATUS_IS_OK(status)) {
1772 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1774 SCVAL(nameptr, -1, len - 2);
1776 SCVAL(nameptr, -1, 0);
1780 SCVAL(nameptr, -1, len - 1);
1782 SCVAL(nameptr, -1, 0);
1788 case SMB_FIND_EA_SIZE:
1789 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1790 if (requires_resume_key) {
1794 srv_put_dos_date2(p,0,create_date);
1795 srv_put_dos_date2(p,4,adate);
1796 srv_put_dos_date2(p,8,mdate);
1797 SIVAL(p,12,(uint32_t)file_size);
1798 SIVAL(p,16,(uint32_t)allocation_size);
1801 unsigned int ea_size = estimate_ea_size(conn, NULL,
1803 SIVAL(p,22,ea_size); /* Extended attributes */
1807 status = srvstr_push(base_data, flags2,
1808 p, fname, PTR_DIFF(end_data, p),
1809 STR_TERMINATE | STR_NOALIGN, &len);
1810 if (!NT_STATUS_IS_OK(status)) {
1813 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1826 SCVAL(nameptr,0,len);
1828 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1831 case SMB_FIND_EA_LIST:
1833 struct ea_list *file_list = NULL;
1836 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1838 return NT_STATUS_INVALID_PARAMETER;
1840 if (requires_resume_key) {
1844 srv_put_dos_date2(p,0,create_date);
1845 srv_put_dos_date2(p,4,adate);
1846 srv_put_dos_date2(p,8,mdate);
1847 SIVAL(p,12,(uint32_t)file_size);
1848 SIVAL(p,16,(uint32_t)allocation_size);
1850 p += 22; /* p now points to the EA area. */
1852 status = get_ea_list_from_file(ctx, conn, NULL,
1854 &ea_len, &file_list);
1855 if (!NT_STATUS_IS_OK(status)) {
1858 name_list = ea_list_union(name_list, file_list, &ea_len);
1860 /* We need to determine if this entry will fit in the space available. */
1861 /* Max string size is 255 bytes. */
1862 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1863 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1864 "(wanted %u, had %d)\n",
1865 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1867 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1870 /* Push the ea_data followed by the name. */
1871 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1873 status = srvstr_push(base_data, flags2,
1874 p + 1, fname, PTR_DIFF(end_data, p+1),
1875 STR_TERMINATE | STR_NOALIGN, &len);
1876 if (!NT_STATUS_IS_OK(status)) {
1879 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1892 SCVAL(nameptr,0,len);
1894 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1898 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1899 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1900 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1902 SIVAL(p,0,reskey); p += 4;
1903 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1904 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1905 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1906 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1907 SOFF_T(p,0,file_size); p += 8;
1908 SOFF_T(p,0,allocation_size); p += 8;
1909 SIVAL(p,0,mode); p += 4;
1910 q = p; p += 4; /* q is placeholder for name length. */
1911 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1912 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1914 unsigned int ea_size = estimate_ea_size(conn, NULL,
1916 SIVAL(p,0,ea_size); /* Extended attributes */
1919 /* Clear the short name buffer. This is
1920 * IMPORTANT as not doing so will trigger
1921 * a Win2k client bug. JRA.
1923 if (!was_8_3 && check_mangled_names) {
1924 char mangled_name[13]; /* mangled 8.3 name. */
1925 if (!name_to_8_3(fname,mangled_name,True,
1927 /* Error - mangle failed ! */
1928 memset(mangled_name,'\0',12);
1930 mangled_name[12] = 0;
1931 status = srvstr_push(base_data, flags2,
1932 p+2, mangled_name, 24,
1933 STR_UPPER|STR_UNICODE, &len);
1934 if (!NT_STATUS_IS_OK(status)) {
1938 memset(p + 2 + len,'\0',24 - len);
1945 status = srvstr_push(base_data, flags2, p,
1946 fname, PTR_DIFF(end_data, p),
1947 STR_TERMINATE_ASCII, &len);
1948 if (!NT_STATUS_IS_OK(status)) {
1954 len = PTR_DIFF(p, pdata);
1955 pad = (len + (align-1)) & ~(align-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1963 * set padding to zero
1966 memset(p, 0, pad - len);
1973 case SMB_FIND_FILE_DIRECTORY_INFO:
1974 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1976 SIVAL(p,0,reskey); p += 4;
1977 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1978 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1979 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1980 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1981 SOFF_T(p,0,file_size); p += 8;
1982 SOFF_T(p,0,allocation_size); p += 8;
1983 SIVAL(p,0,mode); p += 4;
1984 status = srvstr_push(base_data, flags2,
1985 p + 4, fname, PTR_DIFF(end_data, p+4),
1986 STR_TERMINATE_ASCII, &len);
1987 if (!NT_STATUS_IS_OK(status)) {
1993 len = PTR_DIFF(p, pdata);
1994 pad = (len + (align-1)) & ~(align-1);
1996 * offset to the next entry, the caller
1997 * will overwrite it for the last entry
1998 * that's why we always include the padding
2002 * set padding to zero
2005 memset(p, 0, pad - len);
2012 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2013 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2015 SIVAL(p,0,reskey); p += 4;
2016 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2017 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2018 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2019 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2020 SOFF_T(p,0,file_size); p += 8;
2021 SOFF_T(p,0,allocation_size); p += 8;
2022 SIVAL(p,0,mode); p += 4;
2023 q = p; p += 4; /* q is placeholder for name length. */
2025 unsigned int ea_size = estimate_ea_size(conn, NULL,
2027 SIVAL(p,0,ea_size); /* Extended attributes */
2030 status = srvstr_push(base_data, flags2, p,
2031 fname, PTR_DIFF(end_data, p),
2032 STR_TERMINATE_ASCII, &len);
2033 if (!NT_STATUS_IS_OK(status)) {
2039 len = PTR_DIFF(p, pdata);
2040 pad = (len + (align-1)) & ~(align-1);
2042 * offset to the next entry, the caller
2043 * will overwrite it for the last entry
2044 * that's why we always include the padding
2048 * set padding to zero
2051 memset(p, 0, pad - len);
2058 case SMB_FIND_FILE_NAMES_INFO:
2059 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2061 SIVAL(p,0,reskey); p += 4;
2063 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2064 acl on a dir (tridge) */
2065 status = srvstr_push(base_data, flags2, p,
2066 fname, PTR_DIFF(end_data, p),
2067 STR_TERMINATE_ASCII, &len);
2068 if (!NT_STATUS_IS_OK(status)) {
2074 len = PTR_DIFF(p, pdata);
2075 pad = (len + (align-1)) & ~(align-1);
2077 * offset to the next entry, the caller
2078 * will overwrite it for the last entry
2079 * that's why we always include the padding
2083 * set padding to zero
2086 memset(p, 0, pad - len);
2093 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2094 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2096 SIVAL(p,0,reskey); p += 4;
2097 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2098 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2099 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2100 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2101 SOFF_T(p,0,file_size); p += 8;
2102 SOFF_T(p,0,allocation_size); p += 8;
2103 SIVAL(p,0,mode); p += 4;
2104 q = p; p += 4; /* q is placeholder for name length. */
2105 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2106 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2108 unsigned int ea_size = estimate_ea_size(conn, NULL,
2110 SIVAL(p,0,ea_size); /* Extended attributes */
2113 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2114 SBVAL(p,0,file_index); p += 8;
2115 status = srvstr_push(base_data, flags2, p,
2116 fname, PTR_DIFF(end_data, p),
2117 STR_TERMINATE_ASCII, &len);
2118 if (!NT_STATUS_IS_OK(status)) {
2124 len = PTR_DIFF(p, pdata);
2125 pad = (len + (align-1)) & ~(align-1);
2127 * offset to the next entry, the caller
2128 * will overwrite it for the last entry
2129 * that's why we always include the padding
2133 * set padding to zero
2136 memset(p, 0, pad - len);
2143 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2144 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2145 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2147 SIVAL(p,0,reskey); p += 4;
2148 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2149 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2150 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2151 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2152 SOFF_T(p,0,file_size); p += 8;
2153 SOFF_T(p,0,allocation_size); p += 8;
2154 SIVAL(p,0,mode); p += 4;
2155 q = p; p += 4; /* q is placeholder for name length */
2156 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2157 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2158 } else if (readdir_attr_data &&
2159 readdir_attr_data->type == RDATTR_AAPL) {
2161 * OS X specific SMB2 extension negotiated via
2162 * AAPL create context: return max_access in
2165 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2167 unsigned int ea_size = estimate_ea_size(conn, NULL,
2169 SIVAL(p,0,ea_size); /* Extended attributes */
2173 if (readdir_attr_data &&
2174 readdir_attr_data->type == RDATTR_AAPL) {
2176 * OS X specific SMB2 extension negotiated via
2177 * AAPL create context: return resource fork
2178 * length and compressed FinderInfo in
2181 * According to documentation short_name_len
2182 * should be 0, but on the wire behaviour
2183 * shows its set to 24 by clients.
2187 /* Resourefork length */
2188 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2190 /* Compressed FinderInfo */
2191 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2192 } else if (!was_8_3 && check_mangled_names) {
2193 char mangled_name[13]; /* mangled 8.3 name. */
2194 if (!name_to_8_3(fname,mangled_name,True,
2196 /* Error - mangle failed ! */
2197 memset(mangled_name,'\0',12);
2199 mangled_name[12] = 0;
2200 status = srvstr_push(base_data, flags2,
2201 p+2, mangled_name, 24,
2202 STR_UPPER|STR_UNICODE, &len);
2203 if (!NT_STATUS_IS_OK(status)) {
2208 memset(p + 2 + len,'\0',24 - len);
2212 /* Clear the short name buffer. This is
2213 * IMPORTANT as not doing so will trigger
2214 * a Win2k client bug. JRA.
2221 if (readdir_attr_data &&
2222 readdir_attr_data->type == RDATTR_AAPL) {
2224 * OS X specific SMB2 extension negotiated via
2225 * AAPL create context: return UNIX mode in
2228 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2229 SSVAL(p, 0, aapl_mode);
2235 SBVAL(p,0,file_index); p += 8;
2236 status = srvstr_push(base_data, flags2, p,
2237 fname, PTR_DIFF(end_data, p),
2238 STR_TERMINATE_ASCII, &len);
2239 if (!NT_STATUS_IS_OK(status)) {
2245 len = PTR_DIFF(p, pdata);
2246 pad = (len + (align-1)) & ~(align-1);
2248 * offset to the next entry, the caller
2249 * will overwrite it for the last entry
2250 * that's why we always include the padding
2254 * set padding to zero
2257 memset(p, 0, pad - len);
2264 /* CIFS UNIX Extension. */
2266 case SMB_FIND_FILE_UNIX:
2267 case SMB_FIND_FILE_UNIX_INFO2:
2269 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2271 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2273 if (info_level == SMB_FIND_FILE_UNIX) {
2274 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2275 p = store_file_unix_basic(conn, p,
2276 NULL, &smb_fname->st);
2277 status = srvstr_push(base_data, flags2, p,
2278 fname, PTR_DIFF(end_data, p),
2279 STR_TERMINATE, &len);
2280 if (!NT_STATUS_IS_OK(status)) {
2284 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2285 p = store_file_unix_basic_info2(conn, p,
2286 NULL, &smb_fname->st);
2289 status = srvstr_push(base_data, flags2, p, fname,
2290 PTR_DIFF(end_data, p), 0, &len);
2291 if (!NT_STATUS_IS_OK(status)) {
2294 SIVAL(nameptr, 0, len);
2299 len = PTR_DIFF(p, pdata);
2300 pad = (len + (align-1)) & ~(align-1);
2302 * offset to the next entry, the caller
2303 * will overwrite it for the last entry
2304 * that's why we always include the padding
2308 * set padding to zero
2311 memset(p, 0, pad - len);
2316 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2321 return NT_STATUS_INVALID_LEVEL;
2324 if (PTR_DIFF(p,pdata) > space_remaining) {
2325 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2326 "(wanted %u, had %d)\n",
2327 (unsigned int)PTR_DIFF(p,pdata),
2329 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2332 /* Setup the last entry pointer, as an offset from base_data */
2333 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2334 /* Advance the data pointer to the next slot */
2337 return NT_STATUS_OK;
2340 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2341 connection_struct *conn,
2342 struct dptr_struct *dirptr,
2344 const char *path_mask,
2347 int requires_resume_key,
2355 int space_remaining,
2356 bool *got_exact_match,
2357 int *_last_entry_off,
2358 struct ea_list *name_list)
2361 const char *mask = NULL;
2362 long prev_dirpos = 0;
2365 struct smb_filename *smb_fname = NULL;
2366 struct smbd_dirptr_lanman2_state state;
2368 uint64_t last_entry_off = 0;
2373 state.info_level = info_level;
2374 state.check_mangled_names = lp_mangled_names(conn->params);
2375 state.has_wild = dptr_has_wild(dirptr);
2376 state.got_exact_match = false;
2378 *got_exact_match = false;
2380 p = strrchr_m(path_mask,'/');
2391 ok = smbd_dirptr_get_entry(ctx,
2397 smbd_dirptr_lanman2_match_fn,
2398 smbd_dirptr_lanman2_mode_fn,
2405 return NT_STATUS_END_OF_FILE;
2408 *got_exact_match = state.got_exact_match;
2410 status = smbd_marshall_dir_entry(ctx,
2415 state.check_mangled_names,
2416 requires_resume_key,
2427 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2428 DEBUG(1,("Conversion error: illegal character: %s\n",
2429 smb_fname_str_dbg(smb_fname)));
2432 TALLOC_FREE(smb_fname);
2433 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2434 dptr_SeekDir(dirptr, prev_dirpos);
2437 if (!NT_STATUS_IS_OK(status)) {
2441 *_last_entry_off = last_entry_off;
2442 return NT_STATUS_OK;
2445 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2446 connection_struct *conn,
2447 struct dptr_struct *dirptr,
2449 const char *path_mask,
2452 bool requires_resume_key,
2458 int space_remaining,
2459 bool *got_exact_match,
2460 int *last_entry_off,
2461 struct ea_list *name_list)
2464 const bool do_pad = true;
2466 if (info_level >= 1 && info_level <= 3) {
2467 /* No alignment on earlier info levels. */
2471 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2472 path_mask, dirtype, info_level,
2473 requires_resume_key, dont_descend, ask_sharemode,
2475 ppdata, base_data, end_data,
2478 last_entry_off, name_list);
2481 /****************************************************************************
2482 Reply to a TRANS2_FINDFIRST.
2483 ****************************************************************************/
2485 static void call_trans2findfirst(connection_struct *conn,
2486 struct smb_request *req,
2487 char **pparams, int total_params,
2488 char **ppdata, int total_data,
2489 unsigned int max_data_bytes)
2491 /* We must be careful here that we don't return more than the
2492 allowed number of data bytes. If this means returning fewer than
2493 maxentries then so be it. We assume that the redirector has
2494 enough room for the fixed number of parameter bytes it has
2496 struct smb_filename *smb_dname = NULL;
2497 char *params = *pparams;
2498 char *pdata = *ppdata;
2502 uint16_t findfirst_flags;
2503 bool close_after_first;
2505 bool requires_resume_key;
2507 char *directory = NULL;
2510 int last_entry_off=0;
2514 bool finished = False;
2515 bool dont_descend = False;
2516 bool out_of_space = False;
2517 int space_remaining;
2518 bool mask_contains_wcard = False;
2519 struct ea_list *ea_list = NULL;
2520 NTSTATUS ntstatus = NT_STATUS_OK;
2521 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2522 struct dptr_struct *dirptr = NULL;
2523 struct smbd_server_connection *sconn = req->sconn;
2524 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2525 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2526 bool backup_priv = false;
2527 bool as_root = false;
2529 if (total_params < 13) {
2530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2534 dirtype = SVAL(params,0);
2535 maxentries = SVAL(params,2);
2536 findfirst_flags = SVAL(params,4);
2537 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2538 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2539 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2540 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2541 security_token_has_privilege(get_current_nttok(conn),
2544 info_level = SVAL(params,6);
2546 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2547 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2548 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2550 info_level, max_data_bytes));
2553 /* W2K3 seems to treat zero as 1. */
2557 switch (info_level) {
2558 case SMB_FIND_INFO_STANDARD:
2559 case SMB_FIND_EA_SIZE:
2560 case SMB_FIND_EA_LIST:
2561 case SMB_FIND_FILE_DIRECTORY_INFO:
2562 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2563 case SMB_FIND_FILE_NAMES_INFO:
2564 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2565 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2566 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2568 case SMB_FIND_FILE_UNIX:
2569 case SMB_FIND_FILE_UNIX_INFO2:
2570 /* Always use filesystem for UNIX mtime query. */
2571 ask_sharemode = false;
2572 if (!lp_unix_extensions()) {
2573 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2576 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2579 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2583 if (req->posix_pathnames) {
2584 srvstr_get_path_wcard_posix(talloc_tos(),
2592 &mask_contains_wcard);
2594 srvstr_get_path_wcard(talloc_tos(),
2602 &mask_contains_wcard);
2604 if (!NT_STATUS_IS_OK(ntstatus)) {
2605 reply_nterror(req, ntstatus);
2612 ntstatus = filename_convert_with_privilege(talloc_tos(),
2617 &mask_contains_wcard,
2620 ntstatus = filename_convert(talloc_tos(), conn,
2621 req->flags2 & FLAGS2_DFS_PATHNAMES,
2624 &mask_contains_wcard,
2628 if (!NT_STATUS_IS_OK(ntstatus)) {
2629 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2630 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2631 ERRSRV, ERRbadpath);
2634 reply_nterror(req, ntstatus);
2638 mask = smb_dname->original_lcomp;
2640 directory = smb_dname->base_name;
2642 p = strrchr_m(directory,'/');
2644 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2645 if((directory[0] == '.') && (directory[1] == '\0')) {
2646 mask = talloc_strdup(talloc_tos(),"*");
2648 reply_nterror(req, NT_STATUS_NO_MEMORY);
2651 mask_contains_wcard = True;
2657 if (p == NULL || p == directory) {
2658 /* Ensure we don't have a directory name of "". */
2659 directory = talloc_strdup(talloc_tos(), ".");
2661 reply_nterror(req, NT_STATUS_NO_MEMORY);
2664 /* Ensure smb_dname->base_name matches. */
2665 smb_dname->base_name = directory;
2668 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2670 if (info_level == SMB_FIND_EA_LIST) {
2673 if (total_data < 4) {
2674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2678 ea_size = IVAL(pdata,0);
2679 if (ea_size != total_data) {
2680 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2681 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2682 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2686 if (!lp_ea_support(SNUM(conn))) {
2687 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2691 /* Pull out the list of names. */
2692 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2699 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2704 *ppdata = (char *)SMB_REALLOC(
2705 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2706 if(*ppdata == NULL ) {
2707 reply_nterror(req, NT_STATUS_NO_MEMORY);
2711 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2713 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2716 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2717 /* Realloc the params space */
2718 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2719 if (*pparams == NULL) {
2720 reply_nterror(req, NT_STATUS_NO_MEMORY);
2725 /* Save the wildcard match and attribs we are using on this directory -
2726 needed as lanman2 assumes these are being saved between calls */
2728 ntstatus = dptr_create(conn,
2736 mask_contains_wcard,
2740 if (!NT_STATUS_IS_OK(ntstatus)) {
2741 reply_nterror(req, ntstatus);
2746 /* Remember this in case we have
2747 to do a findnext. */
2748 dptr_set_priv(dirptr);
2751 dptr_num = dptr_dnum(dirptr);
2752 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2754 /* Initialize per TRANS2_FIND_FIRST operation data */
2755 dptr_init_search_op(dirptr);
2757 /* We don't need to check for VOL here as this is returned by
2758 a different TRANS2 call. */
2760 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2761 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2762 if (in_list(directory,
2763 lp_dont_descend(talloc_tos(), SNUM(conn)),
2764 conn->case_sensitive)) {
2765 dont_descend = True;
2769 space_remaining = max_data_bytes;
2770 out_of_space = False;
2772 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2773 bool got_exact_match = False;
2775 /* this is a heuristic to avoid seeking the dirptr except when
2776 absolutely necessary. It allows for a filename of about 40 chars */
2777 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2778 out_of_space = True;
2781 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2785 mask,dirtype,info_level,
2786 requires_resume_key,dont_descend,
2791 &last_entry_off, ea_list);
2792 if (NT_STATUS_EQUAL(ntstatus,
2793 NT_STATUS_ILLEGAL_CHARACTER)) {
2795 * Bad character conversion on name. Ignore this
2800 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2801 out_of_space = true;
2803 finished = !NT_STATUS_IS_OK(ntstatus);
2807 if (!finished && !out_of_space)
2811 * As an optimisation if we know we aren't looking
2812 * for a wildcard name (ie. the name matches the wildcard exactly)
2813 * then we can finish on any (first) match.
2814 * This speeds up large directory searches. JRA.
2820 /* Ensure space_remaining never goes -ve. */
2821 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2822 space_remaining = 0;
2823 out_of_space = true;
2825 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2829 /* Check if we can close the dirptr */
2830 if(close_after_first || (finished && close_if_end)) {
2831 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2832 dptr_close(sconn, &dptr_num);
2836 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2837 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2838 * the protocol level is less than NT1. Tested with smbclient. JRA.
2839 * This should fix the OS/2 client bug #2335.
2842 if(numentries == 0) {
2843 dptr_close(sconn, &dptr_num);
2844 if (get_Protocol() < PROTOCOL_NT1) {
2845 reply_force_doserror(req, ERRDOS, ERRnofiles);
2848 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2849 ERRDOS, ERRbadfile);
2854 /* At this point pdata points to numentries directory entries. */
2856 /* Set up the return parameter block */
2857 SSVAL(params,0,dptr_num);
2858 SSVAL(params,2,numentries);
2859 SSVAL(params,4,finished);
2860 SSVAL(params,6,0); /* Never an EA error */
2861 SSVAL(params,8,last_entry_off);
2863 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2866 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2867 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2869 reply_nterror(req, NT_STATUS_NO_MEMORY);
2873 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2874 smb_fn_name(req->cmd),
2875 mask, directory, dirtype, numentries ) );
2878 * Force a name mangle here to ensure that the
2879 * mask as an 8.3 name is top of the mangled cache.
2880 * The reasons for this are subtle. Don't remove
2881 * this code unless you know what you are doing
2882 * (see PR#13758). JRA.
2885 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2886 char mangled_name[13];
2887 name_to_8_3(mask, mangled_name, True, conn->params);
2895 TALLOC_FREE(smb_dname);
2899 /****************************************************************************
2900 Reply to a TRANS2_FINDNEXT.
2901 ****************************************************************************/
2903 static void call_trans2findnext(connection_struct *conn,
2904 struct smb_request *req,
2905 char **pparams, int total_params,
2906 char **ppdata, int total_data,
2907 unsigned int max_data_bytes)
2909 /* We must be careful here that we don't return more than the
2910 allowed number of data bytes. If this means returning fewer than
2911 maxentries then so be it. We assume that the redirector has
2912 enough room for the fixed number of parameter bytes it has
2914 char *params = *pparams;
2915 char *pdata = *ppdata;
2919 uint16_t info_level;
2920 uint32_t resume_key;
2921 uint16_t findnext_flags;
2922 bool close_after_request;
2924 bool requires_resume_key;
2926 bool mask_contains_wcard = False;
2927 char *resume_name = NULL;
2928 const char *mask = NULL;
2929 const char *directory = NULL;
2933 int i, last_entry_off=0;
2934 bool finished = False;
2935 bool dont_descend = False;
2936 bool out_of_space = False;
2937 int space_remaining;
2938 struct ea_list *ea_list = NULL;
2939 NTSTATUS ntstatus = NT_STATUS_OK;
2940 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2941 TALLOC_CTX *ctx = talloc_tos();
2942 struct dptr_struct *dirptr;
2943 struct smbd_server_connection *sconn = req->sconn;
2944 bool backup_priv = false;
2945 bool as_root = false;
2947 if (total_params < 13) {
2948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2952 dptr_num = SVAL(params,0);
2953 maxentries = SVAL(params,2);
2954 info_level = SVAL(params,4);
2955 resume_key = IVAL(params,6);
2956 findnext_flags = SVAL(params,10);
2957 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2958 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2959 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2960 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2962 if (!continue_bit) {
2963 /* We only need resume_name if continue_bit is zero. */
2964 if (req->posix_pathnames) {
2965 srvstr_get_path_wcard_posix(ctx,
2973 &mask_contains_wcard);
2975 srvstr_get_path_wcard(ctx,
2983 &mask_contains_wcard);
2985 if (!NT_STATUS_IS_OK(ntstatus)) {
2986 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2987 complain (it thinks we're asking for the directory above the shared
2988 path or an invalid name). Catch this as the resume name is only compared, never used in
2989 a file access. JRA. */
2990 srvstr_pull_talloc(ctx, params, req->flags2,
2991 &resume_name, params+12,
2995 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2996 reply_nterror(req, ntstatus);
3002 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3003 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3004 resume_key = %d resume name = %s continue=%d level = %d\n",
3005 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3006 requires_resume_key, resume_key,
3007 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3010 /* W2K3 seems to treat zero as 1. */
3014 switch (info_level) {
3015 case SMB_FIND_INFO_STANDARD:
3016 case SMB_FIND_EA_SIZE:
3017 case SMB_FIND_EA_LIST:
3018 case SMB_FIND_FILE_DIRECTORY_INFO:
3019 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3020 case SMB_FIND_FILE_NAMES_INFO:
3021 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3022 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3023 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3025 case SMB_FIND_FILE_UNIX:
3026 case SMB_FIND_FILE_UNIX_INFO2:
3027 /* Always use filesystem for UNIX mtime query. */
3028 ask_sharemode = false;
3029 if (!lp_unix_extensions()) {
3030 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3035 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3039 if (info_level == SMB_FIND_EA_LIST) {
3042 if (total_data < 4) {
3043 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3047 ea_size = IVAL(pdata,0);
3048 if (ea_size != total_data) {
3049 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3050 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3055 if (!lp_ea_support(SNUM(conn))) {
3056 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3060 /* Pull out the list of names. */
3061 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3068 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3073 *ppdata = (char *)SMB_REALLOC(
3074 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3075 if(*ppdata == NULL) {
3076 reply_nterror(req, NT_STATUS_NO_MEMORY);
3081 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3084 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3087 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3088 /* Realloc the params space */
3089 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3090 if(*pparams == NULL ) {
3091 reply_nterror(req, NT_STATUS_NO_MEMORY);
3097 /* Check that the dptr is valid */
3098 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3099 reply_nterror(req, STATUS_NO_MORE_FILES);
3103 directory = dptr_path(sconn, dptr_num);
3105 /* Get the wildcard mask from the dptr */
3106 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3107 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3108 reply_nterror(req, STATUS_NO_MORE_FILES);
3112 /* Get the attr mask from the dptr */
3113 dirtype = dptr_attr(sconn, dptr_num);
3115 backup_priv = dptr_get_priv(dirptr);
3117 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3118 "backup_priv = %d\n",
3119 dptr_num, mask, dirtype,
3121 dptr_TellDir(dirptr),
3124 /* Initialize per TRANS2_FIND_NEXT operation data */
3125 dptr_init_search_op(dirptr);
3127 /* We don't need to check for VOL here as this is returned by
3128 a different TRANS2 call. */
3130 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3131 directory,lp_dont_descend(ctx, SNUM(conn))));
3132 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3133 dont_descend = True;
3136 space_remaining = max_data_bytes;
3137 out_of_space = False;
3145 * Seek to the correct position. We no longer use the resume key but
3146 * depend on the last file name instead.
3149 if(!continue_bit && resume_name && *resume_name) {
3152 long current_pos = 0;
3154 * Remember, name_to_8_3 is called by
3155 * get_lanman2_dir_entry(), so the resume name
3156 * could be mangled. Ensure we check the unmangled name.
3159 if (mangle_is_mangled(resume_name, conn->params)) {
3160 char *new_resume_name = NULL;
3161 mangle_lookup_name_from_8_3(ctx,
3165 if (new_resume_name) {
3166 resume_name = new_resume_name;
3171 * Fix for NT redirector problem triggered by resume key indexes
3172 * changing between directory scans. We now return a resume key of 0
3173 * and instead look for the filename to continue from (also given
3174 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3175 * findfirst/findnext (as is usual) then the directory pointer
3176 * should already be at the correct place.
3179 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3180 } /* end if resume_name && !continue_bit */
3182 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3183 bool got_exact_match = False;
3185 /* this is a heuristic to avoid seeking the dirptr except when
3186 absolutely necessary. It allows for a filename of about 40 chars */
3187 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3188 out_of_space = True;
3191 ntstatus = get_lanman2_dir_entry(ctx,
3195 mask,dirtype,info_level,
3196 requires_resume_key,dont_descend,
3201 &last_entry_off, ea_list);
3202 if (NT_STATUS_EQUAL(ntstatus,
3203 NT_STATUS_ILLEGAL_CHARACTER)) {
3205 * Bad character conversion on name. Ignore this
3210 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3211 out_of_space = true;
3213 finished = !NT_STATUS_IS_OK(ntstatus);
3217 if (!finished && !out_of_space)
3221 * As an optimisation if we know we aren't looking
3222 * for a wildcard name (ie. the name matches the wildcard exactly)
3223 * then we can finish on any (first) match.
3224 * This speeds up large directory searches. JRA.
3230 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3233 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3234 smb_fn_name(req->cmd),
3235 mask, directory, dirtype, numentries ) );
3237 /* Check if we can close the dirptr */
3238 if(close_after_request || (finished && close_if_end)) {
3239 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3240 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3247 /* Set up the return parameter block */
3248 SSVAL(params,0,numentries);
3249 SSVAL(params,2,finished);
3250 SSVAL(params,4,0); /* Never an EA error */
3251 SSVAL(params,6,last_entry_off);
3253 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3259 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3261 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3265 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3267 SMB_ASSERT(extended_info != NULL);
3269 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3270 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3271 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3272 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3273 #ifdef SAMBA_VERSION_REVISION
3274 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3276 extended_info->samba_subversion = 0;
3277 #ifdef SAMBA_VERSION_RC_RELEASE
3278 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3280 #ifdef SAMBA_VERSION_PRE_RELEASE
3281 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3284 #ifdef SAMBA_VERSION_VENDOR_PATCH
3285 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3287 extended_info->samba_gitcommitdate = 0;
3288 #ifdef SAMBA_VERSION_COMMIT_TIME
3289 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3292 memset(extended_info->samba_version_string, 0,
3293 sizeof(extended_info->samba_version_string));
3295 snprintf (extended_info->samba_version_string,
3296 sizeof(extended_info->samba_version_string),
3297 "%s", samba_version_string());
3300 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3301 connection_struct *conn,
3302 TALLOC_CTX *mem_ctx,
3303 uint16_t info_level,
3305 unsigned int max_data_bytes,
3306 size_t *fixed_portion,
3307 struct smb_filename *fname,
3311 char *pdata, *end_data;
3314 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3315 int snum = SNUM(conn);
3316 const char *fstype = lp_fstype(SNUM(conn));
3317 const char *filename = NULL;
3318 const uint64_t bytes_per_sector = 512;
3319 uint32_t additional_flags = 0;
3320 struct smb_filename smb_fname;
3322 NTSTATUS status = NT_STATUS_OK;
3325 if (fname == NULL || fname->base_name == NULL) {
3328 filename = fname->base_name;
3332 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3333 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3334 "info level (0x%x) on IPC$.\n",
3335 (unsigned int)info_level));
3336 return NT_STATUS_ACCESS_DENIED;
3340 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3342 ZERO_STRUCT(smb_fname);
3343 smb_fname.base_name = discard_const_p(char, filename);
3345 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3346 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3347 return map_nt_error_from_unix(errno);
3352 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3353 return NT_STATUS_INVALID_PARAMETER;
3356 *ppdata = (char *)SMB_REALLOC(
3357 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3358 if (*ppdata == NULL) {
3359 return NT_STATUS_NO_MEMORY;
3363 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3364 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3368 switch (info_level) {
3369 case SMB_INFO_ALLOCATION:
3371 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3373 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3375 if (df_ret == (uint64_t)-1) {
3376 return map_nt_error_from_unix(errno);
3379 block_size = lp_block_size(snum);
3380 if (bsize < block_size) {
3381 uint64_t factor = block_size/bsize;
3386 if (bsize > block_size) {
3387 uint64_t factor = bsize/block_size;
3392 sectors_per_unit = bsize/bytes_per_sector;
3394 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3395 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3396 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3398 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3399 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3400 SIVAL(pdata,l1_cUnit,dsize);
3401 SIVAL(pdata,l1_cUnitAvail,dfree);
3402 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3406 case SMB_INFO_VOLUME:
3407 /* Return volume name */
3409 * Add volume serial number - hash of a combination of
3410 * the called hostname and the service name.
3412 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3414 * Win2k3 and previous mess this up by sending a name length
3415 * one byte short. I believe only older clients (OS/2 Win9x) use
3416 * this call so try fixing this by adding a terminating null to
3417 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3419 status = srvstr_push(
3421 pdata+l2_vol_szVolLabel, vname,
3422 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3423 STR_NOALIGN|STR_TERMINATE, &len);
3424 if (!NT_STATUS_IS_OK(status)) {
3427 SCVAL(pdata,l2_vol_cch,len);
3428 data_len = l2_vol_szVolLabel + len;
3429 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3430 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3431 (unsigned)len, vname));
3434 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3435 case SMB_FS_ATTRIBUTE_INFORMATION:
3437 additional_flags = 0;
3438 #if defined(HAVE_SYS_QUOTAS)
3439 additional_flags |= FILE_VOLUME_QUOTAS;
3442 if(lp_nt_acl_support(SNUM(conn))) {
3443 additional_flags |= FILE_PERSISTENT_ACLS;
3446 /* Capabilities are filled in at connection time through STATVFS call */
3447 additional_flags |= conn->fs_capabilities;
3448 additional_flags |= lp_parm_int(conn->params->service,
3449 "share", "fake_fscaps",
3452 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3453 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3454 additional_flags); /* FS ATTRIBUTES */
3456 SIVAL(pdata,4,255); /* Max filename component length */
3457 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3458 and will think we can't do long filenames */
3459 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3460 PTR_DIFF(end_data, pdata+12),
3462 if (!NT_STATUS_IS_OK(status)) {
3466 data_len = 12 + len;
3467 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3468 /* the client only requested a portion of the
3470 data_len = max_data_bytes;
3471 status = STATUS_BUFFER_OVERFLOW;
3473 *fixed_portion = 16;
3476 case SMB_QUERY_FS_LABEL_INFO:
3477 case SMB_FS_LABEL_INFORMATION:
3478 status = srvstr_push(pdata, flags2, pdata+4, vname,
3479 PTR_DIFF(end_data, pdata+4), 0, &len);
3480 if (!NT_STATUS_IS_OK(status)) {
3487 case SMB_QUERY_FS_VOLUME_INFO:
3488 case SMB_FS_VOLUME_INFORMATION:
3491 * Add volume serial number - hash of a combination of
3492 * the called hostname and the service name.
3494 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3495 (str_checksum(get_local_machine_name())<<16));
3497 /* Max label len is 32 characters. */
3498 status = srvstr_push(pdata, flags2, pdata+18, vname,
3499 PTR_DIFF(end_data, pdata+18),
3501 if (!NT_STATUS_IS_OK(status)) {
3504 SIVAL(pdata,12,len);
3507 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3508 (int)strlen(vname),vname,
3509 lp_servicename(talloc_tos(), snum)));
3510 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3511 /* the client only requested a portion of the
3513 data_len = max_data_bytes;
3514 status = STATUS_BUFFER_OVERFLOW;
3516 *fixed_portion = 24;
3519 case SMB_QUERY_FS_SIZE_INFO:
3520 case SMB_FS_SIZE_INFORMATION:
3522 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3524 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3526 if (df_ret == (uint64_t)-1) {
3527 return map_nt_error_from_unix(errno);
3529 block_size = lp_block_size(snum);
3530 if (bsize < block_size) {
3531 uint64_t factor = block_size/bsize;
3536 if (bsize > block_size) {
3537 uint64_t factor = bsize/block_size;
3542 sectors_per_unit = bsize/bytes_per_sector;
3543 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3544 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3545 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3546 SBIG_UINT(pdata,0,dsize);
3547 SBIG_UINT(pdata,8,dfree);
3548 SIVAL(pdata,16,sectors_per_unit);
3549 SIVAL(pdata,20,bytes_per_sector);
3550 *fixed_portion = 24;
3554 case SMB_FS_FULL_SIZE_INFORMATION:
3556 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3558 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3560 if (df_ret == (uint64_t)-1) {
3561 return map_nt_error_from_unix(errno);
3563 block_size = lp_block_size(snum);
3564 if (bsize < block_size) {
3565 uint64_t factor = block_size/bsize;
3570 if (bsize > block_size) {
3571 uint64_t factor = bsize/block_size;
3576 sectors_per_unit = bsize/bytes_per_sector;
3577 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3578 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3579 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3580 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3581 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3582 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3583 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3584 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3585 *fixed_portion = 32;
3589 case SMB_QUERY_FS_DEVICE_INFO:
3590 case SMB_FS_DEVICE_INFORMATION:
3592 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3594 if (!CAN_WRITE(conn)) {
3595 characteristics |= FILE_READ_ONLY_DEVICE;
3598 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3599 SIVAL(pdata,4,characteristics);
3604 #ifdef HAVE_SYS_QUOTAS
3605 case SMB_FS_QUOTA_INFORMATION:
3607 * what we have to send --metze:
3609 * Unknown1: 24 NULL bytes
3610 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3611 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3612 * Quota Flags: 2 byte :
3613 * Unknown3: 6 NULL bytes
3617 * details for Quota Flags:
3619 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3620 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3621 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3622 * 0x0001 Enable Quotas: enable quota for this fs
3626 /* we need to fake up a fsp here,
3627 * because its not send in this call
3630 SMB_NTQUOTA_STRUCT quotas;
3633 ZERO_STRUCT(quotas);
3636 fsp.fnum = FNUM_FIELD_INVALID;
3639 if (get_current_uid(conn) != 0) {
3640 DEBUG(0,("get_user_quota: access_denied "
3641 "service [%s] user [%s]\n",
3642 lp_servicename(talloc_tos(), SNUM(conn)),
3643 conn->session_info->unix_info->unix_name));
3644 return NT_STATUS_ACCESS_DENIED;
3647 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3648 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3649 return map_nt_error_from_unix(errno);
3654 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3655 lp_servicename(talloc_tos(), SNUM(conn))));
3657 /* Unknown1 24 NULL bytes*/
3658 SBIG_UINT(pdata,0,(uint64_t)0);
3659 SBIG_UINT(pdata,8,(uint64_t)0);
3660 SBIG_UINT(pdata,16,(uint64_t)0);
3662 /* Default Soft Quota 8 bytes */
3663 SBIG_UINT(pdata,24,quotas.softlim);
3665 /* Default Hard Quota 8 bytes */
3666 SBIG_UINT(pdata,32,quotas.hardlim);
3668 /* Quota flag 2 bytes */
3669 SSVAL(pdata,40,quotas.qflags);
3671 /* Unknown3 6 NULL bytes */
3677 #endif /* HAVE_SYS_QUOTAS */
3678 case SMB_FS_OBJECTID_INFORMATION:
3680 unsigned char objid[16];
3681 struct smb_extended_info extended_info;
3682 memcpy(pdata,create_volume_objectid(conn, objid),16);
3683 samba_extended_info_version (&extended_info);
3684 SIVAL(pdata,16,extended_info.samba_magic);
3685 SIVAL(pdata,20,extended_info.samba_version);
3686 SIVAL(pdata,24,extended_info.samba_subversion);
3687 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3688 memcpy(pdata+36,extended_info.samba_version_string,28);
3693 case SMB_FS_SECTOR_SIZE_INFORMATION:
3697 * These values match a physical Windows Server 2012
3698 * share backed by NTFS atop spinning rust.
3700 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3701 /* logical_bytes_per_sector */
3702 SIVAL(pdata, 0, bytes_per_sector);
3703 /* phys_bytes_per_sector_atomic */
3704 SIVAL(pdata, 4, bytes_per_sector);
3705 /* phys_bytes_per_sector_perf */
3706 SIVAL(pdata, 8, bytes_per_sector);
3707 /* fs_effective_phys_bytes_per_sector_atomic */
3708 SIVAL(pdata, 12, bytes_per_sector);
3710 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3711 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3712 /* byte_off_sector_align */
3713 SIVAL(pdata, 20, 0);
3714 /* byte_off_partition_align */
3715 SIVAL(pdata, 24, 0);
3716 *fixed_portion = 28;
3722 * Query the version and capabilities of the CIFS UNIX extensions
3726 case SMB_QUERY_CIFS_UNIX_INFO:
3728 bool large_write = lp_min_receive_file_size() &&
3729 !srv_is_signing_active(xconn);
3730 bool large_read = !srv_is_signing_active(xconn);
3731 int encrypt_caps = 0;
3733 if (!lp_unix_extensions()) {
3734 return NT_STATUS_INVALID_LEVEL;
3737 switch (conn->encrypt_level) {
3738 case SMB_SIGNING_OFF:
3741 case SMB_SIGNING_DESIRED:
3742 case SMB_SIGNING_IF_REQUIRED:
3743 case SMB_SIGNING_DEFAULT:
3744 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3746 case SMB_SIGNING_REQUIRED:
3747 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3748 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3749 large_write = false;
3755 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3756 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3758 /* We have POSIX ACLs, pathname, encryption,
3759 * large read/write, and locking capability. */
3761 SBIG_UINT(pdata,4,((uint64_t)(
3762 CIFS_UNIX_POSIX_ACLS_CAP|
3763 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3764 CIFS_UNIX_FCNTL_LOCKS_CAP|
3765 CIFS_UNIX_EXTATTR_CAP|
3766 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3768 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3770 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3774 case SMB_QUERY_POSIX_FS_INFO:
3777 vfs_statvfs_struct svfs;
3779 if (!lp_unix_extensions()) {
3780 return NT_STATUS_INVALID_LEVEL;
3783 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3787 SIVAL(pdata,0,svfs.OptimalTransferSize);
3788 SIVAL(pdata,4,svfs.BlockSize);
3789 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3790 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3791 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3792 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3793 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3794 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3795 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3797 } else if (rc == EOPNOTSUPP) {
3798 return NT_STATUS_INVALID_LEVEL;
3799 #endif /* EOPNOTSUPP */
3801 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3802 return NT_STATUS_DOS(ERRSRV, ERRerror);
3807 case SMB_QUERY_POSIX_WHOAMI:
3813 if (!lp_unix_extensions()) {
3814 return NT_STATUS_INVALID_LEVEL;
3817 if (max_data_bytes < 40) {
3818 return NT_STATUS_BUFFER_TOO_SMALL;
3821 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3822 flags |= SMB_WHOAMI_GUEST;
3825 /* NOTE: 8 bytes for UID/GID, irrespective of native
3826 * platform size. This matches
3827 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3829 data_len = 4 /* flags */
3836 + 4 /* pad/reserved */
3837 + (conn->session_info->unix_token->ngroups * 8)
3839 + (conn->session_info->security_token->num_sids *
3843 SIVAL(pdata, 0, flags);
3844 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3846 (uint64_t)conn->session_info->unix_token->uid);
3847 SBIG_UINT(pdata, 16,
3848 (uint64_t)conn->session_info->unix_token->gid);
3851 if (data_len >= max_data_bytes) {
3852 /* Potential overflow, skip the GIDs and SIDs. */
3854 SIVAL(pdata, 24, 0); /* num_groups */
3855 SIVAL(pdata, 28, 0); /* num_sids */
3856 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3857 SIVAL(pdata, 36, 0); /* reserved */
3863 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3864 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3866 /* We walk the SID list twice, but this call is fairly
3867 * infrequent, and I don't expect that it's performance
3868 * sensitive -- jpeach
3870 for (i = 0, sid_bytes = 0;
3871 i < conn->session_info->security_token->num_sids; ++i) {
3872 sid_bytes += ndr_size_dom_sid(
3873 &conn->session_info->security_token->sids[i],
3877 /* SID list byte count */
3878 SIVAL(pdata, 32, sid_bytes);
3880 /* 4 bytes pad/reserved - must be zero */
3881 SIVAL(pdata, 36, 0);
3885 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3886 SBIG_UINT(pdata, data_len,
3887 (uint64_t)conn->session_info->unix_token->groups[i]);
3893 i < conn->session_info->security_token->num_sids; ++i) {
3894 int sid_len = ndr_size_dom_sid(
3895 &conn->session_info->security_token->sids[i],
3898 sid_linearize((uint8_t *)(pdata + data_len),
3900 &conn->session_info->security_token->sids[i]);
3901 data_len += sid_len;
3907 case SMB_MAC_QUERY_FS_INFO:
3909 * Thursby MAC extension... ONLY on NTFS filesystems
3910 * once we do streams then we don't need this
3912 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3914 SIVAL(pdata,84,0x100); /* Don't support mac... */
3919 return NT_STATUS_INVALID_LEVEL;
3922 *ret_data_len = data_len;
3926 /****************************************************************************
3927 Reply to a TRANS2_QFSINFO (query filesystem info).
3928 ****************************************************************************/
3930 static void call_trans2qfsinfo(connection_struct *conn,
3931 struct smb_request *req,
3932 char **pparams, int total_params,
3933 char **ppdata, int total_data,
3934 unsigned int max_data_bytes)
3936 char *params = *pparams;
3937 uint16_t info_level;
3939 size_t fixed_portion;
3942 if (total_params < 2) {
3943 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3947 info_level = SVAL(params,0);
3949 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3950 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3951 DEBUG(0,("call_trans2qfsinfo: encryption required "
3952 "and info level 0x%x sent.\n",
3953 (unsigned int)info_level));
3954 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3959 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3961 status = smbd_do_qfsinfo(req->xconn, conn, req,
3968 if (!NT_STATUS_IS_OK(status)) {
3969 reply_nterror(req, status);
3973 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3976 DEBUG( 4, ( "%s info_level = %d\n",
3977 smb_fn_name(req->cmd), info_level) );
3982 /****************************************************************************
3983 Reply to a TRANS2_SETFSINFO (set filesystem info).
3984 ****************************************************************************/
3986 static void call_trans2setfsinfo(connection_struct *conn,
3987 struct smb_request *req,
3988 char **pparams, int total_params,
3989 char **ppdata, int total_data,
3990 unsigned int max_data_bytes)
3992 struct smbXsrv_connection *xconn = req->xconn;
3993 char *pdata = *ppdata;
3994 char *params = *pparams;
3995 uint16_t info_level;
3997 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3998 lp_servicename(talloc_tos(), SNUM(conn))));
4001 if (total_params < 4) {
4002 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4008 info_level = SVAL(params,2);
4011 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4012 info_level != SMB_SET_CIFS_UNIX_INFO) {
4013 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4014 "info level (0x%x) on IPC$.\n",
4015 (unsigned int)info_level));
4016 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4021 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4022 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4023 DEBUG(0,("call_trans2setfsinfo: encryption required "
4024 "and info level 0x%x sent.\n",
4025 (unsigned int)info_level));
4026 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4031 switch(info_level) {
4032 case SMB_SET_CIFS_UNIX_INFO:
4033 if (!lp_unix_extensions()) {
4034 DEBUG(2,("call_trans2setfsinfo: "
4035 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4036 "unix extensions off\n"));
4038 NT_STATUS_INVALID_LEVEL);
4042 /* There should be 12 bytes of capabilities set. */
4043 if (total_data < 12) {
4046 NT_STATUS_INVALID_PARAMETER);
4049 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4050 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4051 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4052 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4053 /* Just print these values for now. */
4054 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4055 "major = %u, minor = %u cap_low = 0x%x, "
4057 (unsigned int)xconn->
4058 smb1.unix_info.client_major,
4059 (unsigned int)xconn->
4060 smb1.unix_info.client_minor,
4061 (unsigned int)xconn->
4062 smb1.unix_info.client_cap_low,
4063 (unsigned int)xconn->
4064 smb1.unix_info.client_cap_high));
4066 /* Here is where we must switch to posix pathname processing... */
4067 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4068 lp_set_posix_pathnames();
4069 mangle_change_to_posix();
4072 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4073 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4074 /* Client that knows how to do posix locks,
4075 * but not posix open/mkdir operations. Set a
4076 * default type for read/write checks. */
4078 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4083 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4086 size_t param_len = 0;
4087 size_t data_len = total_data;
4089 if (!lp_unix_extensions()) {
4092 NT_STATUS_INVALID_LEVEL);
4096 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4099 NT_STATUS_NOT_SUPPORTED);
4103 if (xconn->smb1.echo_handler.trusted_fde) {
4104 DEBUG( 2,("call_trans2setfsinfo: "
4105 "request transport encryption disabled"
4106 "with 'fork echo handler = yes'\n"));
4109 NT_STATUS_NOT_SUPPORTED);
4113 DEBUG( 4,("call_trans2setfsinfo: "
4114 "request transport encryption.\n"));
4116 status = srv_request_encryption_setup(conn,
4117 (unsigned char **)ppdata,
4119 (unsigned char **)pparams,
4122 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4123 !NT_STATUS_IS_OK(status)) {
4124 reply_nterror(req, status);
4128 send_trans2_replies(conn, req,
4136 if (NT_STATUS_IS_OK(status)) {
4137 /* Server-side transport
4138 * encryption is now *on*. */
4139 status = srv_encryption_start(conn);
4140 if (!NT_STATUS_IS_OK(status)) {
4141 char *reason = talloc_asprintf(talloc_tos(),
4142 "Failure in setting "
4143 "up encrypted transport: %s",
4145 exit_server_cleanly(reason);
4151 case SMB_FS_QUOTA_INFORMATION:
4153 files_struct *fsp = NULL;
4154 SMB_NTQUOTA_STRUCT quotas;
4156 ZERO_STRUCT(quotas);
4159 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4160 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4161 lp_servicename(talloc_tos(), SNUM(conn)),
4162 conn->session_info->unix_info->unix_name));
4163 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4167 /* note: normally there're 48 bytes,
4168 * but we didn't use the last 6 bytes for now
4171 fsp = file_fsp(req, SVAL(params,0));
4173 if (!check_fsp_ntquota_handle(conn, req,
4175 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4177 req, NT_STATUS_INVALID_HANDLE);
4181 if (total_data < 42) {
4182 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4186 NT_STATUS_INVALID_PARAMETER);
4190 /* unknown_1 24 NULL bytes in pdata*/
4192 /* the soft quotas 8 bytes (uint64_t)*/
4193 quotas.softlim = BVAL(pdata,24);
4195 /* the hard quotas 8 bytes (uint64_t)*/
4196 quotas.hardlim = BVAL(pdata,32);
4198 /* quota_flags 2 bytes **/
4199 quotas.qflags = SVAL(pdata,40);
4201 /* unknown_2 6 NULL bytes follow*/
4203 /* now set the quotas */
4204 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4205 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4206 reply_nterror(req, map_nt_error_from_unix(errno));
4213 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4215 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4221 * sending this reply works fine,
4222 * but I'm not sure it's the same
4223 * like windows do...
4226 reply_outbuf(req, 10, 0);
4229 #if defined(HAVE_POSIX_ACLS)
4230 /****************************************************************************
4231 Utility function to count the number of entries in a POSIX acl.
4232 ****************************************************************************/
4234 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4236 unsigned int ace_count = 0;
4237 int entry_id = SMB_ACL_FIRST_ENTRY;
4238 SMB_ACL_ENTRY_T entry;
4240 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4242 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4243 entry_id = SMB_ACL_NEXT_ENTRY;
4250 /****************************************************************************
4251 Utility function to marshall a POSIX acl into wire format.
4252 ****************************************************************************/
4254 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4256 int entry_id = SMB_ACL_FIRST_ENTRY;
4257 SMB_ACL_ENTRY_T entry;
4259 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4260 SMB_ACL_TAG_T tagtype;
4261 SMB_ACL_PERMSET_T permset;
4262 unsigned char perms = 0;
4263 unsigned int own_grp;
4266 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4267 entry_id = SMB_ACL_NEXT_ENTRY;
4270 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4271 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4275 if (sys_acl_get_permset(entry, &permset) == -1) {
4276 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4280 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4281 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4282 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4284 SCVAL(pdata,1,perms);
4287 case SMB_ACL_USER_OBJ:
4288 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4289 own_grp = (unsigned int)pst->st_ex_uid;
4290 SIVAL(pdata,2,own_grp);
4295 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4297 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4300 own_grp = (unsigned int)*puid;
4301 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4302 SIVAL(pdata,2,own_grp);
4306 case SMB_ACL_GROUP_OBJ:
4307 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4308 own_grp = (unsigned int)pst->st_ex_gid;
4309 SIVAL(pdata,2,own_grp);
4314 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4316 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4319 own_grp = (unsigned int)*pgid;
4320 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4321 SIVAL(pdata,2,own_grp);
4326 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4327 SIVAL(pdata,2,0xFFFFFFFF);
4328 SIVAL(pdata,6,0xFFFFFFFF);
4331 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4332 SIVAL(pdata,2,0xFFFFFFFF);
4333 SIVAL(pdata,6,0xFFFFFFFF);
4336 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4339 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4346 /****************************************************************************
4347 Store the FILE_UNIX_BASIC info.
4348 ****************************************************************************/
4350 static char *store_file_unix_basic(connection_struct *conn,
4353 const SMB_STRUCT_STAT *psbuf)
4355 uint64_t file_index = get_FileIndex(conn, psbuf);
4358 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4359 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4361 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4364 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4367 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4368 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4369 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4372 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4376 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4380 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4383 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4384 devno = psbuf->st_ex_rdev;
4386 devno = psbuf->st_ex_dev;
4389 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4393 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4397 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4400 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4404 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4411 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4412 * the chflags(2) (or equivalent) flags.
4414 * XXX: this really should be behind the VFS interface. To do this, we would
4415 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4416 * Each VFS module could then implement its own mapping as appropriate for the
4417 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4419 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4423 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4427 { UF_IMMUTABLE, EXT_IMMUTABLE },
4431 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4435 { UF_HIDDEN, EXT_HIDDEN },
4438 /* Do not remove. We need to guarantee that this array has at least one
4439 * entry to build on HP-UX.
4445 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4446 uint32_t *smb_fflags, uint32_t *smb_fmask)
4450 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4451 *smb_fmask |= info2_flags_map[i].smb_fflag;
4452 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4453 *smb_fflags |= info2_flags_map[i].smb_fflag;
4458 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4459 const uint32_t smb_fflags,
4460 const uint32_t smb_fmask,
4463 uint32_t max_fmask = 0;
4466 *stat_fflags = psbuf->st_ex_flags;
4468 /* For each flags requested in smb_fmask, check the state of the
4469 * corresponding flag in smb_fflags and set or clear the matching
4473 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4474 max_fmask |= info2_flags_map[i].smb_fflag;
4475 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4476 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4477 *stat_fflags |= info2_flags_map[i].stat_fflag;
4479 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4484 /* If smb_fmask is asking to set any bits that are not supported by
4485 * our flag mappings, we should fail.
4487 if ((smb_fmask & max_fmask) != smb_fmask) {
4495 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4496 * of file flags and birth (create) time.
4498 static char *store_file_unix_basic_info2(connection_struct *conn,
4501 const SMB_STRUCT_STAT *psbuf)
4503 uint32_t file_flags = 0;
4504 uint32_t flags_mask = 0;
4506 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4508 /* Create (birth) time 64 bit */
4509 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4512 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4513 SIVAL(pdata, 0, file_flags); /* flags */
4514 SIVAL(pdata, 4, flags_mask); /* mask */
4520 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4521 const struct stream_struct *streams,
4523 unsigned int max_data_bytes,
4524 unsigned int *data_size)
4527 unsigned int ofs = 0;
4529 if (max_data_bytes < 32) {
4530 return NT_STATUS_INFO_LENGTH_MISMATCH;
4533 for (i = 0; i < num_streams; i++) {
4534 unsigned int next_offset;
4536 smb_ucs2_t *namebuf;
4538 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4539 streams[i].name, &namelen) ||
4542 return NT_STATUS_INVALID_PARAMETER;
4546 * name_buf is now null-terminated, we need to marshall as not
4553 * We cannot overflow ...
4555 if ((ofs + 24 + namelen) > max_data_bytes) {
4556 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4558 TALLOC_FREE(namebuf);
4559 return STATUS_BUFFER_OVERFLOW;
4562 SIVAL(data, ofs+4, namelen);
4563 SOFF_T(data, ofs+8, streams[i].size);
4564 SOFF_T(data, ofs+16, streams[i].alloc_size);
4565 memcpy(data+ofs+24, namebuf, namelen);
4566 TALLOC_FREE(namebuf);
4568 next_offset = ofs + 24 + namelen;
4570 if (i == num_streams-1) {
4571 SIVAL(data, ofs, 0);
4574 unsigned int align = ndr_align_size(next_offset, 8);
4576 if ((next_offset + align) > max_data_bytes) {
4577 DEBUG(10, ("refusing to overflow align "
4578 "reply at stream %u\n",
4580 TALLOC_FREE(namebuf);
4581 return STATUS_BUFFER_OVERFLOW;
4584 memset(data+next_offset, 0, align);
4585 next_offset += align;
4587 SIVAL(data, ofs, next_offset - ofs);
4594 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4598 return NT_STATUS_OK;
4601 /****************************************************************************
4602 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4603 ****************************************************************************/
4605 static void call_trans2qpipeinfo(connection_struct *conn,
4606 struct smb_request *req,
4607 unsigned int tran_call,
4608 char **pparams, int total_params,
4609 char **ppdata, int total_data,
4610 unsigned int max_data_bytes)
4612 char *params = *pparams;
4613 char *pdata = *ppdata;
4614 unsigned int data_size = 0;
4615 unsigned int param_size = 2;
4616 uint16_t info_level;
4620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4624 if (total_params < 4) {
4625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4629 fsp = file_fsp(req, SVAL(params,0));
4630 if (!fsp_is_np(fsp)) {
4631 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4635 info_level = SVAL(params,2);
4637 *pparams = (char *)SMB_REALLOC(*pparams,2);
4638 if (*pparams == NULL) {
4639 reply_nterror(req, NT_STATUS_NO_MEMORY);
4644 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4645 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4648 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4649 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4650 if (*ppdata == NULL ) {
4651 reply_nterror(req, NT_STATUS_NO_MEMORY);
4656 switch (info_level) {
4657 case SMB_FILE_STANDARD_INFORMATION:
4659 SOFF_T(pdata,0,4096LL);
4666 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4670 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4676 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4677 TALLOC_CTX *mem_ctx,
4678 uint16_t info_level,
4680 struct smb_filename *smb_fname,
4681 bool delete_pending,
4682 struct timespec write_time_ts,
4683 struct ea_list *ea_list,
4684 int lock_data_count,
4687 unsigned int max_data_bytes,
4688 size_t *fixed_portion,
4690 unsigned int *pdata_size)
4692 char *pdata = *ppdata;
4693 char *dstart, *dend;
4694 unsigned int data_size;
4695 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4696 time_t create_time, mtime, atime, c_time;
4697 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4704 uint64_t file_size = 0;
4706 uint64_t allocation_size = 0;
4707 uint64_t file_index = 0;
4708 uint32_t access_mask = 0;
4711 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4712 return NT_STATUS_INVALID_LEVEL;
4715 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4716 smb_fname_str_dbg(smb_fname),
4718 info_level, max_data_bytes));
4720 mode = dos_mode(conn, smb_fname);
4721 nlink = psbuf->st_ex_nlink;
4723 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4727 if ((nlink > 0) && delete_pending) {
4731 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4732 return NT_STATUS_INVALID_PARAMETER;
4735 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4736 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4737 if (*ppdata == NULL) {
4738 return NT_STATUS_NO_MEMORY;
4742 dend = dstart + data_size - 1;
4744 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4745 update_stat_ex_mtime(psbuf, write_time_ts);
4748 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4749 mtime_ts = psbuf->st_ex_mtime;
4750 atime_ts = psbuf->st_ex_atime;
4751 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4753 if (lp_dos_filetime_resolution(SNUM(conn))) {
4754 dos_filetime_timespec(&create_time_ts);
4755 dos_filetime_timespec(&mtime_ts);
4756 dos_filetime_timespec(&atime_ts);
4757 dos_filetime_timespec(&ctime_ts);
4760 create_time = convert_timespec_to_time_t(create_time_ts);
4761 mtime = convert_timespec_to_time_t(mtime_ts);
4762 atime = convert_timespec_to_time_t(atime_ts);
4763 c_time = convert_timespec_to_time_t(ctime_ts);
4765 p = strrchr_m(smb_fname->base_name,'/');
4767 base_name = smb_fname->base_name;
4771 /* NT expects the name to be in an exact form of the *full*
4772 filename. See the trans2 torture test */
4773 if (ISDOT(base_name)) {
4774 dos_fname = talloc_strdup(mem_ctx, "\\");
4776 return NT_STATUS_NO_MEMORY;
4779 dos_fname = talloc_asprintf(mem_ctx,
4781 smb_fname->base_name);
4783 return NT_STATUS_NO_MEMORY;
4785 if (is_ntfs_stream_smb_fname(smb_fname)) {
4786 dos_fname = talloc_asprintf(dos_fname, "%s",
4787 smb_fname->stream_name);
4789 return NT_STATUS_NO_MEMORY;
4793 string_replace(dos_fname, '/', '\\');
4796 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4799 /* Do we have this path open ? */
4801 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4802 fsp1 = file_find_di_first(conn->sconn, fileid);
4803 if (fsp1 && fsp1->initial_allocation_size) {
4804 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4808 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4809 file_size = get_file_size_stat(psbuf);
4813 pos = fsp->fh->position_information;
4817 access_mask = fsp->access_mask;
4819 /* GENERIC_EXECUTE mapping from Windows */
4820 access_mask = 0x12019F;
4823 /* This should be an index number - looks like
4826 I think this causes us to fail the IFSKIT
4827 BasicFileInformationTest. -tpot */
4828 file_index = get_FileIndex(conn, psbuf);
4832 switch (info_level) {
4833 case SMB_INFO_STANDARD:
4834 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4836 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4837 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4838 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4839 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4840 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4841 SSVAL(pdata,l1_attrFile,mode);
4844 case SMB_INFO_QUERY_EA_SIZE:
4846 unsigned int ea_size =
4847 estimate_ea_size(conn, fsp,
4849 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4851 srv_put_dos_date2(pdata,0,create_time);
4852 srv_put_dos_date2(pdata,4,atime);
4853 srv_put_dos_date2(pdata,8,mtime); /* write time */
4854 SIVAL(pdata,12,(uint32_t)file_size);
4855 SIVAL(pdata,16,(uint32_t)allocation_size);
4856 SSVAL(pdata,20,mode);
4857 SIVAL(pdata,22,ea_size);
4861 case SMB_INFO_IS_NAME_VALID:
4862 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4864 /* os/2 needs this ? really ?*/
4865 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4867 /* This is only reached for qpathinfo */
4871 case SMB_INFO_QUERY_EAS_FROM_LIST:
4873 size_t total_ea_len = 0;
4874 struct ea_list *ea_file_list = NULL;
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4878 get_ea_list_from_file(mem_ctx, conn, fsp,
4880 &total_ea_len, &ea_file_list);
4881 if (!NT_STATUS_IS_OK(status)) {
4885 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4887 if (!ea_list || (total_ea_len > data_size)) {
4889 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4893 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4897 case SMB_INFO_QUERY_ALL_EAS:
4899 /* We have data_size bytes to put EA's into. */
4900 size_t total_ea_len = 0;
4901 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4903 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4905 &total_ea_len, &ea_list);
4906 if (!NT_STATUS_IS_OK(status)) {
4910 if (!ea_list || (total_ea_len > data_size)) {
4912 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4916 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4920 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4922 /* This is FileFullEaInformation - 0xF which maps to
4923 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4925 /* We have data_size bytes to put EA's into. */
4926 size_t total_ea_len = 0;
4927 struct ea_list *ea_file_list = NULL;
4929 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4931 /*TODO: add filtering and index handling */
4934 get_ea_list_from_file(mem_ctx, conn, fsp,
4936 &total_ea_len, &ea_file_list);
4937 if (!NT_STATUS_IS_OK(status)) {
4940 if (!ea_file_list) {
4941 return NT_STATUS_NO_EAS_ON_FILE;
4944 status = fill_ea_chained_buffer(mem_ctx,
4948 conn, ea_file_list);
4949 if (!NT_STATUS_IS_OK(status)) {
4955 case SMB_FILE_BASIC_INFORMATION:
4956 case SMB_QUERY_FILE_BASIC_INFO:
4958 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4959 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4960 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4962 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4966 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4967 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4968 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4969 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4970 SIVAL(pdata,32,mode);
4972 DEBUG(5,("SMB_QFBI - "));
4973 DEBUG(5,("create: %s ", ctime(&create_time)));
4974 DEBUG(5,("access: %s ", ctime(&atime)));
4975 DEBUG(5,("write: %s ", ctime(&mtime)));
4976 DEBUG(5,("change: %s ", ctime(&c_time)));
4977 DEBUG(5,("mode: %x\n", mode));
4978 *fixed_portion = data_size;
4981 case SMB_FILE_STANDARD_INFORMATION:
4982 case SMB_QUERY_FILE_STANDARD_INFO:
4984 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4986 SOFF_T(pdata,0,allocation_size);
4987 SOFF_T(pdata,8,file_size);
4988 SIVAL(pdata,16,nlink);
4989 SCVAL(pdata,20,delete_pending?1:0);
4990 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4991 SSVAL(pdata,22,0); /* Padding. */
4992 *fixed_portion = 24;
4995 case SMB_FILE_EA_INFORMATION:
4996 case SMB_QUERY_FILE_EA_INFO:
4998 unsigned int ea_size =
4999 estimate_ea_size(conn, fsp, smb_fname);
5000 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5003 SIVAL(pdata,0,ea_size);
5007 /* Get the 8.3 name - used if NT SMB was negotiated. */
5008 case SMB_QUERY_FILE_ALT_NAME_INFO:
5009 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5011 char mangled_name[13];
5012 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5013 if (!name_to_8_3(base_name,mangled_name,
5014 True,conn->params)) {
5015 return NT_STATUS_NO_MEMORY;
5017 status = srvstr_push(dstart, flags2,
5018 pdata+4, mangled_name,
5019 PTR_DIFF(dend, pdata+4),
5021 if (!NT_STATUS_IS_OK(status)) {
5024 data_size = 4 + len;
5030 case SMB_QUERY_FILE_NAME_INFO:
5033 this must be *exactly* right for ACLs on mapped drives to work
5035 status = srvstr_push(dstart, flags2,
5037 PTR_DIFF(dend, pdata+4),
5039 if (!NT_STATUS_IS_OK(status)) {
5042 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5043 data_size = 4 + len;
5048 case SMB_FILE_ALLOCATION_INFORMATION:
5049 case SMB_QUERY_FILE_ALLOCATION_INFO:
5050 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5052 SOFF_T(pdata,0,allocation_size);
5055 case SMB_FILE_END_OF_FILE_INFORMATION:
5056 case SMB_QUERY_FILE_END_OF_FILEINFO:
5057 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5059 SOFF_T(pdata,0,file_size);
5062 case SMB_QUERY_FILE_ALL_INFO:
5063 case SMB_FILE_ALL_INFORMATION:
5065 unsigned int ea_size =
5066 estimate_ea_size(conn, fsp, smb_fname);
5067 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5068 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5069 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5070 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5071 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5072 SIVAL(pdata,32,mode);
5073 SIVAL(pdata,36,0); /* padding. */
5075 SOFF_T(pdata,0,allocation_size);
5076 SOFF_T(pdata,8,file_size);
5077 SIVAL(pdata,16,nlink);
5078 SCVAL(pdata,20,delete_pending);
5079 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5082 SIVAL(pdata,0,ea_size);
5083 pdata += 4; /* EA info */
5084 status = srvstr_push(dstart, flags2,
5086 PTR_DIFF(dend, pdata+4),
5088 if (!NT_STATUS_IS_OK(status)) {
5093 data_size = PTR_DIFF(pdata,(*ppdata));
5094 *fixed_portion = 10;
5098 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5100 unsigned int ea_size =
5101 estimate_ea_size(conn, fsp, smb_fname);
5102 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5103 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5104 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5105 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5106 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5107 SIVAL(pdata, 0x20, mode);
5108 SIVAL(pdata, 0x24, 0); /* padding. */
5109 SBVAL(pdata, 0x28, allocation_size);
5110 SBVAL(pdata, 0x30, file_size);
5111 SIVAL(pdata, 0x38, nlink);
5112 SCVAL(pdata, 0x3C, delete_pending);
5113 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5114 SSVAL(pdata, 0x3E, 0); /* padding */
5115 SBVAL(pdata, 0x40, file_index);
5116 SIVAL(pdata, 0x48, ea_size);
5117 SIVAL(pdata, 0x4C, access_mask);
5118 SBVAL(pdata, 0x50, pos);
5119 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5120 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5124 status = srvstr_push(dstart, flags2,
5126 PTR_DIFF(dend, pdata+4),
5128 if (!NT_STATUS_IS_OK(status)) {
5133 data_size = PTR_DIFF(pdata,(*ppdata));
5134 *fixed_portion = 104;
5137 case SMB_FILE_INTERNAL_INFORMATION:
5139 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5140 SBVAL(pdata, 0, file_index);
5145 case SMB_FILE_ACCESS_INFORMATION:
5146 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5147 SIVAL(pdata, 0, access_mask);
5152 case SMB_FILE_NAME_INFORMATION:
5153 /* Pathname with leading '\'. */
5156 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5157 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5158 SIVAL(pdata,0,byte_len);
5159 data_size = 4 + byte_len;
5163 case SMB_FILE_DISPOSITION_INFORMATION:
5164 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5166 SCVAL(pdata,0,delete_pending);
5170 case SMB_FILE_POSITION_INFORMATION:
5171 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5173 SOFF_T(pdata,0,pos);
5177 case SMB_FILE_MODE_INFORMATION:
5178 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5179 SIVAL(pdata,0,mode);
5184 case SMB_FILE_ALIGNMENT_INFORMATION:
5185 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5186 SIVAL(pdata,0,0); /* No alignment needed. */
5192 * NT4 server just returns "invalid query" to this - if we try
5193 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5196 /* The first statement above is false - verified using Thursby
5197 * client against NT4 -- gcolley.
5199 case SMB_QUERY_FILE_STREAM_INFO:
5200 case SMB_FILE_STREAM_INFORMATION: {
5201 unsigned int num_streams = 0;
5202 struct stream_struct *streams = NULL;
5204 DEBUG(10,("smbd_do_qfilepathinfo: "
5205 "SMB_FILE_STREAM_INFORMATION\n"));
5207 if (is_ntfs_stream_smb_fname(smb_fname)) {
5208 return NT_STATUS_INVALID_PARAMETER;
5211 status = vfs_streaminfo(conn,
5218 if (!NT_STATUS_IS_OK(status)) {
5219 DEBUG(10, ("could not get stream info: %s\n",
5220 nt_errstr(status)));
5224 status = marshall_stream_info(num_streams, streams,
5225 pdata, max_data_bytes,
5228 if (!NT_STATUS_IS_OK(status)) {
5229 DEBUG(10, ("marshall_stream_info failed: %s\n",
5230 nt_errstr(status)));
5231 TALLOC_FREE(streams);
5235 TALLOC_FREE(streams);
5237 *fixed_portion = 32;
5241 case SMB_QUERY_COMPRESSION_INFO:
5242 case SMB_FILE_COMPRESSION_INFORMATION:
5243 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5244 SOFF_T(pdata,0,file_size);
5245 SIVAL(pdata,8,0); /* ??? */
5246 SIVAL(pdata,12,0); /* ??? */
5248 *fixed_portion = 16;
5251 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5252 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5253 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5254 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5255 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5256 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5257 SOFF_T(pdata,32,allocation_size);
5258 SOFF_T(pdata,40,file_size);
5259 SIVAL(pdata,48,mode);
5260 SIVAL(pdata,52,0); /* ??? */
5262 *fixed_portion = 56;
5265 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5266 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5267 SIVAL(pdata,0,mode);
5274 * CIFS UNIX Extensions.
5277 case SMB_QUERY_FILE_UNIX_BASIC:
5279 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5280 data_size = PTR_DIFF(pdata,(*ppdata));
5282 DEBUG(4,("smbd_do_qfilepathinfo: "
5283 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5284 dump_data(4, (uint8_t *)(*ppdata), data_size);
5288 case SMB_QUERY_FILE_UNIX_INFO2:
5290 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5291 data_size = PTR_DIFF(pdata,(*ppdata));
5295 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5297 for (i=0; i<100; i++)
5298 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5304 case SMB_QUERY_FILE_UNIX_LINK:
5307 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5310 return NT_STATUS_NO_MEMORY;
5313 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5315 if(!S_ISLNK(psbuf->st_ex_mode)) {
5316 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5319 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5321 link_len = SMB_VFS_READLINK(conn,
5322 smb_fname->base_name,
5324 if (link_len == -1) {
5325 return map_nt_error_from_unix(errno);
5327 buffer[link_len] = 0;
5328 status = srvstr_push(dstart, flags2,
5330 PTR_DIFF(dend, pdata),
5331 STR_TERMINATE, &len);
5332 if (!NT_STATUS_IS_OK(status)) {
5336 data_size = PTR_DIFF(pdata,(*ppdata));
5341 #if defined(HAVE_POSIX_ACLS)
5342 case SMB_QUERY_POSIX_ACL:
5344 SMB_ACL_T file_acl = NULL;
5345 SMB_ACL_T def_acl = NULL;
5346 uint16_t num_file_acls = 0;
5347 uint16_t num_def_acls = 0;
5349 if (fsp && fsp->fh->fd != -1) {
5350 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5354 SMB_VFS_SYS_ACL_GET_FILE(conn,
5355 smb_fname->base_name,
5356 SMB_ACL_TYPE_ACCESS,
5360 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5361 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5362 "not implemented on "
5363 "filesystem containing %s\n",
5364 smb_fname->base_name));
5365 return NT_STATUS_NOT_IMPLEMENTED;
5368 if (S_ISDIR(psbuf->st_ex_mode)) {
5369 if (fsp && fsp->is_directory) {
5371 SMB_VFS_SYS_ACL_GET_FILE(
5373 fsp->fsp_name->base_name,
5374 SMB_ACL_TYPE_DEFAULT,
5378 SMB_VFS_SYS_ACL_GET_FILE(
5380 smb_fname->base_name,
5381 SMB_ACL_TYPE_DEFAULT,
5384 def_acl = free_empty_sys_acl(conn, def_acl);
5387 num_file_acls = count_acl_entries(conn, file_acl);
5388 num_def_acls = count_acl_entries(conn, def_acl);
5390 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5391 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5393 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5394 SMB_POSIX_ACL_HEADER_SIZE) ));
5396 TALLOC_FREE(file_acl);
5399 TALLOC_FREE(def_acl);
5401 return NT_STATUS_BUFFER_TOO_SMALL;
5404 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5405 SSVAL(pdata,2,num_file_acls);
5406 SSVAL(pdata,4,num_def_acls);
5407 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5409 TALLOC_FREE(file_acl);
5412 TALLOC_FREE(def_acl);
5414 return NT_STATUS_INTERNAL_ERROR;
5416 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5418 TALLOC_FREE(file_acl);
5421 TALLOC_FREE(def_acl);
5423 return NT_STATUS_INTERNAL_ERROR;
5427 TALLOC_FREE(file_acl);
5430 TALLOC_FREE(def_acl);
5432 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5438 case SMB_QUERY_POSIX_LOCK:
5443 enum brl_type lock_type;
5445 /* We need an open file with a real fd for this. */
5446 if (!fsp || fsp->fh->fd == -1) {
5447 return NT_STATUS_INVALID_LEVEL;
5450 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5451 return NT_STATUS_INVALID_PARAMETER;
5454 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5455 case POSIX_LOCK_TYPE_READ:
5456 lock_type = READ_LOCK;
5458 case POSIX_LOCK_TYPE_WRITE:
5459 lock_type = WRITE_LOCK;
5461 case POSIX_LOCK_TYPE_UNLOCK:
5463 /* There's no point in asking for an unlock... */
5464 return NT_STATUS_INVALID_PARAMETER;
5467 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5468 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5469 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5471 status = query_lock(fsp,
5478 if (ERROR_WAS_LOCK_DENIED(status)) {
5479 /* Here we need to report who has it locked... */
5480 data_size = POSIX_LOCK_DATA_SIZE;
5482 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5483 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5484 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5485 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5486 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5488 } else if (NT_STATUS_IS_OK(status)) {
5489 /* For success we just return a copy of what we sent
5490 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5491 data_size = POSIX_LOCK_DATA_SIZE;
5492 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5493 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5501 return NT_STATUS_INVALID_LEVEL;
5504 *pdata_size = data_size;
5505 return NT_STATUS_OK;
5508 /****************************************************************************
5509 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5510 file name or file id).
5511 ****************************************************************************/
5513 static void call_trans2qfilepathinfo(connection_struct *conn,
5514 struct smb_request *req,
5515 unsigned int tran_call,
5516 char **pparams, int total_params,
5517 char **ppdata, int total_data,
5518 unsigned int max_data_bytes)
5520 char *params = *pparams;
5521 char *pdata = *ppdata;
5522 uint16_t info_level;
5523 unsigned int data_size = 0;
5524 unsigned int param_size = 2;
5525 struct smb_filename *smb_fname = NULL;
5526 bool delete_pending = False;
5527 struct timespec write_time_ts;
5528 files_struct *fsp = NULL;
5529 struct file_id fileid;
5530 struct ea_list *ea_list = NULL;
5531 int lock_data_count = 0;
5532 char *lock_data = NULL;
5533 size_t fixed_portion;
5534 NTSTATUS status = NT_STATUS_OK;
5537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5541 ZERO_STRUCT(write_time_ts);
5543 if (tran_call == TRANSACT2_QFILEINFO) {
5544 if (total_params < 4) {
5545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5550 call_trans2qpipeinfo(conn, req, tran_call,
5551 pparams, total_params,
5557 fsp = file_fsp(req, SVAL(params,0));
5558 info_level = SVAL(params,2);
5560 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5562 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5563 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5567 /* Initial check for valid fsp ptr. */
5568 if (!check_fsp_open(conn, req, fsp)) {
5572 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5573 if (smb_fname == NULL) {
5574 reply_nterror(req, NT_STATUS_NO_MEMORY);
5578 if(fsp->fake_file_handle) {
5580 * This is actually for the QUOTA_FAKE_FILE --metze
5583 /* We know this name is ok, it's already passed the checks. */
5585 } else if(fsp->fh->fd == -1) {
5587 * This is actually a QFILEINFO on a directory
5588 * handle (returned from an NT SMB). NT5.0 seems
5589 * to do this call. JRA.
5592 if (INFO_LEVEL_IS_UNIX(info_level)) {
5593 /* Always do lstat for UNIX calls. */
5594 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5595 DEBUG(3,("call_trans2qfilepathinfo: "
5596 "SMB_VFS_LSTAT of %s failed "
5598 smb_fname_str_dbg(smb_fname),
5601 map_nt_error_from_unix(errno));
5604 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5605 DEBUG(3,("call_trans2qfilepathinfo: "
5606 "SMB_VFS_STAT of %s failed (%s)\n",
5607 smb_fname_str_dbg(smb_fname),
5610 map_nt_error_from_unix(errno));
5614 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5615 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5618 * Original code - this is an open file.
5620 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5621 DEBUG(3, ("fstat of %s failed (%s)\n",
5622 fsp_fnum_dbg(fsp), strerror(errno)));
5624 map_nt_error_from_unix(errno));
5627 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5628 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5634 uint32_t ucf_flags = (req->posix_pathnames ?
5635 UCF_POSIX_PATHNAMES : 0);
5638 if (total_params < 7) {
5639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5643 info_level = SVAL(params,0);
5645 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5647 if (INFO_LEVEL_IS_UNIX(info_level)) {
5648 if (!lp_unix_extensions()) {
5649 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5652 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5653 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5654 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5655 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5659 if (req->posix_pathnames) {
5660 srvstr_get_path_posix(req,
5669 srvstr_get_path(req,
5678 if (!NT_STATUS_IS_OK(status)) {
5679 reply_nterror(req, status);
5683 status = filename_convert(req,
5685 req->flags2 & FLAGS2_DFS_PATHNAMES,
5690 if (!NT_STATUS_IS_OK(status)) {
5691 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5692 reply_botherror(req,
5693 NT_STATUS_PATH_NOT_COVERED,
5694 ERRSRV, ERRbadpath);
5697 reply_nterror(req, status);
5701 /* If this is a stream, check if there is a delete_pending. */
5702 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5703 && is_ntfs_stream_smb_fname(smb_fname)) {
5704 struct smb_filename *smb_fname_base;
5706 /* Create an smb_filename with stream_name == NULL. */
5707 smb_fname_base = synthetic_smb_fname(
5708 talloc_tos(), smb_fname->base_name,
5710 if (smb_fname_base == NULL) {
5711 reply_nterror(req, NT_STATUS_NO_MEMORY);
5715 if (INFO_LEVEL_IS_UNIX(info_level)) {
5716 /* Always do lstat for UNIX calls. */
5717 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5718 DEBUG(3,("call_trans2qfilepathinfo: "
5719 "SMB_VFS_LSTAT of %s failed "
5721 smb_fname_str_dbg(smb_fname_base),
5723 TALLOC_FREE(smb_fname_base);
5725 map_nt_error_from_unix(errno));
5729 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5730 DEBUG(3,("call_trans2qfilepathinfo: "
5731 "fileinfo of %s failed "
5733 smb_fname_str_dbg(smb_fname_base),
5735 TALLOC_FREE(smb_fname_base);
5737 map_nt_error_from_unix(errno));
5742 status = file_name_hash(conn,
5743 smb_fname_str_dbg(smb_fname_base),
5745 if (!NT_STATUS_IS_OK(status)) {
5746 TALLOC_FREE(smb_fname_base);
5747 reply_nterror(req, status);
5751 fileid = vfs_file_id_from_sbuf(conn,
5752 &smb_fname_base->st);
5753 TALLOC_FREE(smb_fname_base);
5754 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5755 if (delete_pending) {
5756 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5761 if (INFO_LEVEL_IS_UNIX(info_level)) {
5762 /* Always do lstat for UNIX calls. */
5763 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5764 DEBUG(3,("call_trans2qfilepathinfo: "
5765 "SMB_VFS_LSTAT of %s failed (%s)\n",
5766 smb_fname_str_dbg(smb_fname),
5769 map_nt_error_from_unix(errno));
5774 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5775 DEBUG(3,("call_trans2qfilepathinfo: "
5776 "SMB_VFS_STAT of %s failed (%s)\n",
5777 smb_fname_str_dbg(smb_fname),
5780 map_nt_error_from_unix(errno));
5785 status = file_name_hash(conn,
5786 smb_fname_str_dbg(smb_fname),
5788 if (!NT_STATUS_IS_OK(status)) {
5789 reply_nterror(req, status);
5793 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5794 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5795 if (delete_pending) {
5796 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5801 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5802 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5804 info_level,tran_call,total_data));
5806 /* Pull out any data sent here before we realloc. */
5807 switch (info_level) {
5808 case SMB_INFO_QUERY_EAS_FROM_LIST:
5810 /* Pull any EA list from the data portion. */
5813 if (total_data < 4) {
5815 req, NT_STATUS_INVALID_PARAMETER);
5818 ea_size = IVAL(pdata,0);
5820 if (total_data > 0 && ea_size != total_data) {
5821 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5822 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5824 req, NT_STATUS_INVALID_PARAMETER);
5828 if (!lp_ea_support(SNUM(conn))) {
5829 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5833 /* Pull out the list of names. */
5834 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5837 req, NT_STATUS_INVALID_PARAMETER);
5843 case SMB_QUERY_POSIX_LOCK:
5845 if (fsp == NULL || fsp->fh->fd == -1) {
5846 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5850 if (total_data != POSIX_LOCK_DATA_SIZE) {
5852 req, NT_STATUS_INVALID_PARAMETER);
5856 /* Copy the lock range data. */
5857 lock_data = (char *)talloc_memdup(
5858 req, pdata, total_data);
5860 reply_nterror(req, NT_STATUS_NO_MEMORY);
5863 lock_data_count = total_data;
5869 *pparams = (char *)SMB_REALLOC(*pparams,2);
5870 if (*pparams == NULL) {
5871 reply_nterror(req, NT_STATUS_NO_MEMORY);
5878 * draft-leach-cifs-v1-spec-02.txt
5879 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5882 * The requested information is placed in the Data portion of the
5883 * transaction response. For the information levels greater than 0x100,
5884 * the transaction response has 1 parameter word which should be
5885 * ignored by the client.
5887 * However Windows only follows this rule for the IS_NAME_VALID call.
5889 switch (info_level) {
5890 case SMB_INFO_IS_NAME_VALID:
5895 if ((info_level & 0xFF00) == 0xFF00) {
5897 * We use levels that start with 0xFF00
5898 * internally to represent SMB2 specific levels
5900 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5904 status = smbd_do_qfilepathinfo(conn, req, info_level,
5906 delete_pending, write_time_ts,
5908 lock_data_count, lock_data,
5909 req->flags2, max_data_bytes,
5911 ppdata, &data_size);
5912 if (!NT_STATUS_IS_OK(status)) {
5913 reply_nterror(req, status);
5916 if (fixed_portion > max_data_bytes) {
5917 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5921 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5927 /****************************************************************************
5928 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5930 ****************************************************************************/
5932 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5933 connection_struct *conn,
5934 struct smb_request *req,
5935 bool overwrite_if_exists,
5936 const struct smb_filename *smb_fname_old,
5937 struct smb_filename *smb_fname_new)
5939 NTSTATUS status = NT_STATUS_OK;
5941 /* source must already exist. */
5942 if (!VALID_STAT(smb_fname_old->st)) {
5943 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5946 if (VALID_STAT(smb_fname_new->st)) {
5947 if (overwrite_if_exists) {
5948 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5949 return NT_STATUS_FILE_IS_A_DIRECTORY;
5951 status = unlink_internals(conn,
5953 FILE_ATTRIBUTE_NORMAL,
5956 if (!NT_STATUS_IS_OK(status)) {
5960 /* Disallow if newname already exists. */
5961 return NT_STATUS_OBJECT_NAME_COLLISION;
5965 /* No links from a directory. */
5966 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5967 return NT_STATUS_FILE_IS_A_DIRECTORY;
5970 /* Setting a hardlink to/from a stream isn't currently supported. */
5971 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5972 is_ntfs_stream_smb_fname(smb_fname_new)) {
5973 return NT_STATUS_INVALID_PARAMETER;
5976 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5977 smb_fname_old->base_name, smb_fname_new->base_name));
5979 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5980 smb_fname_new->base_name) != 0) {
5981 status = map_nt_error_from_unix(errno);
5982 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5983 nt_errstr(status), smb_fname_old->base_name,
5984 smb_fname_new->base_name));
5989 /****************************************************************************
5990 Deal with setting the time from any of the setfilepathinfo functions.
5991 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5992 calling this function.
5993 ****************************************************************************/
5995 NTSTATUS smb_set_file_time(connection_struct *conn,
5997 const struct smb_filename *smb_fname,
5998 struct smb_file_time *ft,
5999 bool setting_write_time)
6001 struct smb_filename smb_fname_base;
6003 FILE_NOTIFY_CHANGE_LAST_ACCESS
6004 |FILE_NOTIFY_CHANGE_LAST_WRITE
6005 |FILE_NOTIFY_CHANGE_CREATION;
6007 if (!VALID_STAT(smb_fname->st)) {
6008 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6011 /* get some defaults (no modifications) if any info is zero or -1. */
6012 if (null_timespec(ft->create_time)) {
6013 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6016 if (null_timespec(ft->atime)) {
6017 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6020 if (null_timespec(ft->mtime)) {
6021 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6024 if (!setting_write_time) {
6025 /* ft->mtime comes from change time, not write time. */
6026 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6029 /* Ensure the resolution is the correct for
6030 * what we can store on this filesystem. */
6032 round_timespec(conn->ts_res, &ft->create_time);
6033 round_timespec(conn->ts_res, &ft->ctime);
6034 round_timespec(conn->ts_res, &ft->atime);
6035 round_timespec(conn->ts_res, &ft->mtime);
6037 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6038 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6039 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6040 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6041 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6042 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6043 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6044 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6046 if (setting_write_time) {
6048 * This was a Windows setfileinfo on an open file.
6049 * NT does this a lot. We also need to
6050 * set the time here, as it can be read by
6051 * FindFirst/FindNext and with the patch for bug #2045
6052 * in smbd/fileio.c it ensures that this timestamp is
6053 * kept sticky even after a write. We save the request
6054 * away and will set it on file close and after a write. JRA.
6057 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6058 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6061 if (fsp->base_fsp) {
6062 set_sticky_write_time_fsp(fsp->base_fsp,
6065 set_sticky_write_time_fsp(fsp, ft->mtime);
6068 set_sticky_write_time_path(
6069 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6074 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6076 /* Always call ntimes on the base, even if a stream was passed in. */
6077 smb_fname_base = *smb_fname;
6078 smb_fname_base.stream_name = NULL;
6080 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6081 return map_nt_error_from_unix(errno);
6084 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6085 smb_fname->base_name);
6086 return NT_STATUS_OK;
6089 /****************************************************************************
6090 Deal with setting the dosmode from any of the setfilepathinfo functions.
6091 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6092 done before calling this function.
6093 ****************************************************************************/
6095 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6096 const struct smb_filename *smb_fname,
6099 struct smb_filename *smb_fname_base;
6102 if (!VALID_STAT(smb_fname->st)) {
6103 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6106 /* Always operate on the base_name, even if a stream was passed in. */
6107 smb_fname_base = synthetic_smb_fname(
6108 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
6109 if (smb_fname_base == NULL) {
6110 return NT_STATUS_NO_MEMORY;
6114 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6115 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6117 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6121 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6123 /* check the mode isn't different, before changing it */
6124 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6125 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6126 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6127 (unsigned int)dosmode));
6129 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6131 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6133 smb_fname_str_dbg(smb_fname_base),
6135 status = map_nt_error_from_unix(errno);
6139 status = NT_STATUS_OK;
6141 TALLOC_FREE(smb_fname_base);
6145 /****************************************************************************
6146 Deal with setting the size from any of the setfilepathinfo functions.
6147 ****************************************************************************/
6149 static NTSTATUS smb_set_file_size(connection_struct *conn,
6150 struct smb_request *req,
6152 const struct smb_filename *smb_fname,
6153 const SMB_STRUCT_STAT *psbuf,
6155 bool fail_after_createfile)
6157 NTSTATUS status = NT_STATUS_OK;
6158 struct smb_filename *smb_fname_tmp = NULL;
6159 files_struct *new_fsp = NULL;
6161 if (!VALID_STAT(*psbuf)) {
6162 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6165 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6167 if (size == get_file_size_stat(psbuf)) {
6168 return NT_STATUS_OK;
6171 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6172 smb_fname_str_dbg(smb_fname), (double)size));
6174 if (fsp && fsp->fh->fd != -1) {
6175 /* Handle based call. */
6176 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6177 return NT_STATUS_ACCESS_DENIED;
6180 if (vfs_set_filelen(fsp, size) == -1) {
6181 return map_nt_error_from_unix(errno);
6183 trigger_write_time_update_immediate(fsp);
6184 return NT_STATUS_OK;
6187 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6188 if (smb_fname_tmp == NULL) {
6189 return NT_STATUS_NO_MEMORY;
6192 smb_fname_tmp->st = *psbuf;
6194 status = SMB_VFS_CREATE_FILE(
6197 0, /* root_dir_fid */
6198 smb_fname_tmp, /* fname */
6199 FILE_WRITE_DATA, /* access_mask */
6200 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6202 FILE_OPEN, /* create_disposition*/
6203 0, /* create_options */
6204 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6205 0, /* oplock_request */
6207 0, /* allocation_size */
6208 0, /* private_flags */
6211 &new_fsp, /* result */
6213 NULL, NULL); /* create context */
6215 TALLOC_FREE(smb_fname_tmp);
6217 if (!NT_STATUS_IS_OK(status)) {
6218 /* NB. We check for open_was_deferred in the caller. */
6222 /* See RAW-SFILEINFO-END-OF-FILE */
6223 if (fail_after_createfile) {
6224 close_file(req, new_fsp,NORMAL_CLOSE);
6225 return NT_STATUS_INVALID_LEVEL;
6228 if (vfs_set_filelen(new_fsp, size) == -1) {
6229 status = map_nt_error_from_unix(errno);
6230 close_file(req, new_fsp,NORMAL_CLOSE);
6234 trigger_write_time_update_immediate(new_fsp);
6235 close_file(req, new_fsp,NORMAL_CLOSE);
6236 return NT_STATUS_OK;
6239 /****************************************************************************
6240 Deal with SMB_INFO_SET_EA.
6241 ****************************************************************************/
6243 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6247 const struct smb_filename *smb_fname)
6249 struct ea_list *ea_list = NULL;
6250 TALLOC_CTX *ctx = NULL;
6251 NTSTATUS status = NT_STATUS_OK;
6253 if (total_data < 10) {
6255 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6256 length. They seem to have no effect. Bug #3212. JRA */
6258 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6259 /* We're done. We only get EA info in this call. */
6260 return NT_STATUS_OK;
6263 return NT_STATUS_INVALID_PARAMETER;
6266 if (IVAL(pdata,0) > total_data) {
6267 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6268 IVAL(pdata,0), (unsigned int)total_data));
6269 return NT_STATUS_INVALID_PARAMETER;
6273 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6275 return NT_STATUS_INVALID_PARAMETER;
6278 status = set_ea(conn, fsp, smb_fname, ea_list);
6283 /****************************************************************************
6284 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6285 ****************************************************************************/
6287 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6292 struct ea_list *ea_list = NULL;
6296 return NT_STATUS_INVALID_HANDLE;
6299 if (!lp_ea_support(SNUM(conn))) {
6300 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6301 "EA's not supported.\n",
6302 (unsigned int)total_data));
6303 return NT_STATUS_EAS_NOT_SUPPORTED;
6306 if (total_data < 10) {
6307 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6309 (unsigned int)total_data));
6310 return NT_STATUS_INVALID_PARAMETER;
6313 ea_list = read_nttrans_ea_list(talloc_tos(),
6318 return NT_STATUS_INVALID_PARAMETER;
6321 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6323 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6324 smb_fname_str_dbg(fsp->fsp_name),
6325 nt_errstr(status) ));
6331 /****************************************************************************
6332 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6333 ****************************************************************************/
6335 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6339 struct smb_filename *smb_fname)
6341 NTSTATUS status = NT_STATUS_OK;
6342 bool delete_on_close;
6343 uint32_t dosmode = 0;
6345 if (total_data < 1) {
6346 return NT_STATUS_INVALID_PARAMETER;
6350 return NT_STATUS_INVALID_HANDLE;
6353 delete_on_close = (CVAL(pdata,0) ? True : False);
6354 dosmode = dos_mode(conn, smb_fname);
6356 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6357 "delete_on_close = %u\n",
6358 smb_fname_str_dbg(smb_fname),
6359 (unsigned int)dosmode,
6360 (unsigned int)delete_on_close ));
6362 if (delete_on_close) {
6363 status = can_set_delete_on_close(fsp, dosmode);
6364 if (!NT_STATUS_IS_OK(status)) {
6369 /* The set is across all open files on this dev/inode pair. */
6370 if (!set_delete_on_close(fsp, delete_on_close,
6371 conn->session_info->security_token,
6372 conn->session_info->unix_token)) {
6373 return NT_STATUS_ACCESS_DENIED;
6375 return NT_STATUS_OK;
6378 /****************************************************************************
6379 Deal with SMB_FILE_POSITION_INFORMATION.
6380 ****************************************************************************/
6382 static NTSTATUS smb_file_position_information(connection_struct *conn,
6387 uint64_t position_information;
6389 if (total_data < 8) {
6390 return NT_STATUS_INVALID_PARAMETER;
6394 /* Ignore on pathname based set. */
6395 return NT_STATUS_OK;
6398 position_information = (uint64_t)IVAL(pdata,0);
6399 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6401 DEBUG(10,("smb_file_position_information: Set file position "
6402 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6403 (double)position_information));
6404 fsp->fh->position_information = position_information;
6405 return NT_STATUS_OK;
6408 /****************************************************************************
6409 Deal with SMB_FILE_MODE_INFORMATION.
6410 ****************************************************************************/
6412 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6418 if (total_data < 4) {
6419 return NT_STATUS_INVALID_PARAMETER;
6421 mode = IVAL(pdata,0);
6422 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6423 return NT_STATUS_INVALID_PARAMETER;
6425 return NT_STATUS_OK;
6428 /****************************************************************************
6429 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6430 ****************************************************************************/
6432 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6433 struct smb_request *req,
6436 const struct smb_filename *smb_fname)
6438 char *link_target = NULL;
6439 const char *newname = smb_fname->base_name;
6440 TALLOC_CTX *ctx = talloc_tos();
6442 /* Set a symbolic link. */
6443 /* Don't allow this if follow links is false. */
6445 if (total_data == 0) {
6446 return NT_STATUS_INVALID_PARAMETER;
6449 if (!lp_follow_symlinks(SNUM(conn))) {
6450 return NT_STATUS_ACCESS_DENIED;
6453 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6454 total_data, STR_TERMINATE);
6457 return NT_STATUS_INVALID_PARAMETER;
6460 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6461 newname, link_target ));
6463 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6464 return map_nt_error_from_unix(errno);
6467 return NT_STATUS_OK;
6470 /****************************************************************************
6471 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6472 ****************************************************************************/
6474 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6475 struct smb_request *req,
6476 const char *pdata, int total_data,
6477 struct smb_filename *smb_fname_new)
6479 char *oldname = NULL;
6480 struct smb_filename *smb_fname_old = NULL;
6481 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6482 TALLOC_CTX *ctx = talloc_tos();
6483 NTSTATUS status = NT_STATUS_OK;
6485 /* Set a hard link. */
6486 if (total_data == 0) {
6487 return NT_STATUS_INVALID_PARAMETER;
6490 if (req->posix_pathnames) {
6491 srvstr_get_path_posix(ctx,
6500 srvstr_get_path(ctx,
6509 if (!NT_STATUS_IS_OK(status)) {
6513 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6514 smb_fname_str_dbg(smb_fname_new), oldname));
6516 status = filename_convert(ctx,
6518 req->flags2 & FLAGS2_DFS_PATHNAMES,
6523 if (!NT_STATUS_IS_OK(status)) {
6527 return hardlink_internals(ctx, conn, req, false,
6528 smb_fname_old, smb_fname_new);
6531 /****************************************************************************
6532 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6533 ****************************************************************************/
6535 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6536 struct smb_request *req,
6540 struct smb_filename *smb_fname_src)
6544 char *newname = NULL;
6545 struct smb_filename *smb_fname_dst = NULL;
6546 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6547 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6548 NTSTATUS status = NT_STATUS_OK;
6549 TALLOC_CTX *ctx = talloc_tos();
6552 return NT_STATUS_INVALID_HANDLE;
6555 if (total_data < 20) {
6556 return NT_STATUS_INVALID_PARAMETER;
6559 overwrite = (CVAL(pdata,0) ? True : False);
6560 len = IVAL(pdata,16);
6562 if (len > (total_data - 20) || (len == 0)) {
6563 return NT_STATUS_INVALID_PARAMETER;
6566 if (req->posix_pathnames) {
6567 srvstr_get_path_posix(ctx,
6576 srvstr_get_path(ctx,
6585 if (!NT_STATUS_IS_OK(status)) {
6589 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6592 status = filename_convert(ctx,
6594 req->flags2 & FLAGS2_DFS_PATHNAMES,
6599 if (!NT_STATUS_IS_OK(status)) {
6603 if (fsp->base_fsp) {
6604 /* newname must be a stream name. */
6605 if (newname[0] != ':') {
6606 return NT_STATUS_NOT_SUPPORTED;
6609 /* Create an smb_fname to call rename_internals_fsp() with. */
6610 smb_fname_dst = synthetic_smb_fname(
6611 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6613 if (smb_fname_dst == NULL) {
6614 status = NT_STATUS_NO_MEMORY;
6619 * Set the original last component, since
6620 * rename_internals_fsp() requires it.
6622 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6624 if (smb_fname_dst->original_lcomp == NULL) {
6625 status = NT_STATUS_NO_MEMORY;
6631 DEBUG(10,("smb2_file_rename_information: "
6632 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6633 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6634 smb_fname_str_dbg(smb_fname_dst)));
6635 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6636 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6640 TALLOC_FREE(smb_fname_dst);
6644 static NTSTATUS smb_file_link_information(connection_struct *conn,
6645 struct smb_request *req,
6649 struct smb_filename *smb_fname_src)
6653 char *newname = NULL;
6654 struct smb_filename *smb_fname_dst = NULL;
6655 NTSTATUS status = NT_STATUS_OK;
6656 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6657 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6658 TALLOC_CTX *ctx = talloc_tos();
6661 return NT_STATUS_INVALID_HANDLE;
6664 if (total_data < 20) {
6665 return NT_STATUS_INVALID_PARAMETER;
6668 overwrite = (CVAL(pdata,0) ? true : false);
6669 len = IVAL(pdata,16);
6671 if (len > (total_data - 20) || (len == 0)) {
6672 return NT_STATUS_INVALID_PARAMETER;
6675 if (req->posix_pathnames) {
6676 srvstr_get_path_posix(ctx,
6685 srvstr_get_path(ctx,
6694 if (!NT_STATUS_IS_OK(status)) {
6698 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6701 status = filename_convert(ctx,
6703 req->flags2 & FLAGS2_DFS_PATHNAMES,
6708 if (!NT_STATUS_IS_OK(status)) {
6712 if (fsp->base_fsp) {
6713 /* No stream names. */
6714 return NT_STATUS_NOT_SUPPORTED;
6717 DEBUG(10,("smb_file_link_information: "
6718 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6719 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6720 smb_fname_str_dbg(smb_fname_dst)));
6721 status = hardlink_internals(ctx,
6728 TALLOC_FREE(smb_fname_dst);
6732 /****************************************************************************
6733 Deal with SMB_FILE_RENAME_INFORMATION.
6734 ****************************************************************************/
6736 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6737 struct smb_request *req,
6741 struct smb_filename *smb_fname_src)
6746 char *newname = NULL;
6747 struct smb_filename *smb_fname_dst = NULL;
6748 bool dest_has_wcard = False;
6749 NTSTATUS status = NT_STATUS_OK;
6751 TALLOC_CTX *ctx = talloc_tos();
6753 if (total_data < 13) {
6754 return NT_STATUS_INVALID_PARAMETER;
6757 overwrite = (CVAL(pdata,0) ? True : False);
6758 root_fid = IVAL(pdata,4);
6759 len = IVAL(pdata,8);
6761 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6762 return NT_STATUS_INVALID_PARAMETER;
6765 if (req->posix_pathnames) {
6766 srvstr_get_path_wcard_posix(ctx,
6776 srvstr_get_path_wcard(ctx,
6786 if (!NT_STATUS_IS_OK(status)) {
6790 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6793 status = resolve_dfspath_wcard(ctx, conn,
6794 req->flags2 & FLAGS2_DFS_PATHNAMES,
6797 !conn->sconn->using_smb2,
6800 if (!NT_STATUS_IS_OK(status)) {
6804 /* Check the new name has no '/' characters. */
6805 if (strchr_m(newname, '/')) {
6806 return NT_STATUS_NOT_SUPPORTED;
6809 if (fsp && fsp->base_fsp) {
6810 /* newname must be a stream name. */
6811 if (newname[0] != ':') {
6812 return NT_STATUS_NOT_SUPPORTED;
6815 /* Create an smb_fname to call rename_internals_fsp() with. */
6816 smb_fname_dst = synthetic_smb_fname(
6817 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6819 if (smb_fname_dst == NULL) {
6820 status = NT_STATUS_NO_MEMORY;
6825 * Set the original last component, since
6826 * rename_internals_fsp() requires it.
6828 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6830 if (smb_fname_dst->original_lcomp == NULL) {
6831 status = NT_STATUS_NO_MEMORY;
6837 * Build up an smb_fname_dst based on the filename passed in.
6838 * We basically just strip off the last component, and put on
6839 * the newname instead.
6841 char *base_name = NULL;
6843 /* newname must *not* be a stream name. */
6844 if (newname[0] == ':') {
6845 return NT_STATUS_NOT_SUPPORTED;
6849 * Strip off the last component (filename) of the path passed
6852 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6854 return NT_STATUS_NO_MEMORY;
6856 p = strrchr_m(base_name, '/');
6860 base_name = talloc_strdup(ctx, "");
6862 return NT_STATUS_NO_MEMORY;
6865 /* Append the new name. */
6866 base_name = talloc_asprintf_append(base_name,
6870 return NT_STATUS_NO_MEMORY;
6873 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6876 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6879 /* If an error we expect this to be
6880 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6882 if (!NT_STATUS_IS_OK(status)) {
6883 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6887 /* Create an smb_fname to call rename_internals_fsp() */
6888 smb_fname_dst = synthetic_smb_fname(
6889 ctx, base_name, NULL, NULL);
6890 if (smb_fname_dst == NULL) {
6891 status = NT_STATUS_NO_MEMORY;
6898 DEBUG(10,("smb_file_rename_information: "
6899 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6900 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6901 smb_fname_str_dbg(smb_fname_dst)));
6902 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6905 DEBUG(10,("smb_file_rename_information: "
6906 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6907 smb_fname_str_dbg(smb_fname_src),
6908 smb_fname_str_dbg(smb_fname_dst)));
6909 status = rename_internals(ctx, conn, req, smb_fname_src,
6910 smb_fname_dst, 0, overwrite, false,
6912 FILE_WRITE_ATTRIBUTES);
6915 TALLOC_FREE(smb_fname_dst);
6919 /****************************************************************************
6920 Deal with SMB_SET_POSIX_ACL.
6921 ****************************************************************************/
6923 #if defined(HAVE_POSIX_ACLS)
6924 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6928 const struct smb_filename *smb_fname)
6930 uint16_t posix_acl_version;
6931 uint16_t num_file_acls;
6932 uint16_t num_def_acls;
6933 bool valid_file_acls = True;
6934 bool valid_def_acls = True;
6936 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6937 return NT_STATUS_INVALID_PARAMETER;
6939 posix_acl_version = SVAL(pdata,0);
6940 num_file_acls = SVAL(pdata,2);
6941 num_def_acls = SVAL(pdata,4);
6943 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6944 valid_file_acls = False;
6948 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6949 valid_def_acls = False;
6953 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6954 return NT_STATUS_INVALID_PARAMETER;
6957 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6958 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6959 return NT_STATUS_INVALID_PARAMETER;
6962 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6963 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6964 (unsigned int)num_file_acls,
6965 (unsigned int)num_def_acls));
6967 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6968 smb_fname->base_name, num_file_acls,
6969 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6970 return map_nt_error_from_unix(errno);
6973 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6974 smb_fname->base_name, &smb_fname->st, num_def_acls,
6975 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6976 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6977 return map_nt_error_from_unix(errno);
6979 return NT_STATUS_OK;
6983 /****************************************************************************
6984 Deal with SMB_SET_POSIX_LOCK.
6985 ****************************************************************************/
6987 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6988 struct smb_request *req,
6996 bool blocking_lock = False;
6997 enum brl_type lock_type;
6999 NTSTATUS status = NT_STATUS_OK;
7001 if (fsp == NULL || fsp->fh->fd == -1) {
7002 return NT_STATUS_INVALID_HANDLE;
7005 if (total_data != POSIX_LOCK_DATA_SIZE) {
7006 return NT_STATUS_INVALID_PARAMETER;
7009 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7010 case POSIX_LOCK_TYPE_READ:
7011 lock_type = READ_LOCK;
7013 case POSIX_LOCK_TYPE_WRITE:
7014 /* Return the right POSIX-mappable error code for files opened read-only. */
7015 if (!fsp->can_write) {
7016 return NT_STATUS_INVALID_HANDLE;
7018 lock_type = WRITE_LOCK;
7020 case POSIX_LOCK_TYPE_UNLOCK:
7021 lock_type = UNLOCK_LOCK;
7024 return NT_STATUS_INVALID_PARAMETER;
7027 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7028 blocking_lock = False;
7029 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7030 blocking_lock = True;
7032 return NT_STATUS_INVALID_PARAMETER;
7035 if (!lp_blocking_locks(SNUM(conn))) {
7036 blocking_lock = False;
7039 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7040 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7041 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7042 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7043 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7045 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7046 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7048 (unsigned int)lock_type,
7049 (unsigned long long)smblctx,
7053 if (lock_type == UNLOCK_LOCK) {
7054 status = do_unlock(req->sconn->msg_ctx,
7061 uint64_t block_smblctx;
7063 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7074 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7076 * A blocking lock was requested. Package up
7077 * this smb into a queued request and push it
7078 * onto the blocking lock queue.
7080 if(push_blocking_lock_request(br_lck,
7083 -1, /* infinite timeout. */
7091 TALLOC_FREE(br_lck);
7095 TALLOC_FREE(br_lck);
7101 /****************************************************************************
7102 Deal with SMB_SET_FILE_BASIC_INFO.
7103 ****************************************************************************/
7105 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7109 const struct smb_filename *smb_fname)
7111 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7112 struct smb_file_time ft;
7113 uint32_t dosmode = 0;
7114 NTSTATUS status = NT_STATUS_OK;
7118 if (total_data < 36) {
7119 return NT_STATUS_INVALID_PARAMETER;
7122 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7123 if (!NT_STATUS_IS_OK(status)) {
7127 /* Set the attributes */
7128 dosmode = IVAL(pdata,32);
7129 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7130 if (!NT_STATUS_IS_OK(status)) {
7135 ft.create_time = interpret_long_date(pdata);
7138 ft.atime = interpret_long_date(pdata+8);
7141 ft.mtime = interpret_long_date(pdata+16);
7144 ft.ctime = interpret_long_date(pdata+24);
7146 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7147 smb_fname_str_dbg(smb_fname)));
7149 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7153 /****************************************************************************
7154 Deal with SMB_INFO_STANDARD.
7155 ****************************************************************************/
7157 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7161 const struct smb_filename *smb_fname)
7164 struct smb_file_time ft;
7168 if (total_data < 12) {
7169 return NT_STATUS_INVALID_PARAMETER;
7173 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7175 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7177 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7179 DEBUG(10,("smb_set_info_standard: file %s\n",
7180 smb_fname_str_dbg(smb_fname)));
7182 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7183 if (!NT_STATUS_IS_OK(status)) {
7187 return smb_set_file_time(conn,
7194 /****************************************************************************
7195 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7196 ****************************************************************************/
7198 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7199 struct smb_request *req,
7203 struct smb_filename *smb_fname)
7205 uint64_t allocation_size = 0;
7206 NTSTATUS status = NT_STATUS_OK;
7207 files_struct *new_fsp = NULL;
7209 if (!VALID_STAT(smb_fname->st)) {
7210 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7213 if (total_data < 8) {
7214 return NT_STATUS_INVALID_PARAMETER;
7217 allocation_size = (uint64_t)IVAL(pdata,0);
7218 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7219 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7220 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7221 (double)allocation_size));
7223 if (allocation_size) {
7224 allocation_size = smb_roundup(conn, allocation_size);
7227 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7228 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7229 (double)allocation_size));
7231 if (fsp && fsp->fh->fd != -1) {
7232 /* Open file handle. */
7233 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7234 return NT_STATUS_ACCESS_DENIED;
7237 /* Only change if needed. */
7238 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7239 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7240 return map_nt_error_from_unix(errno);
7243 /* But always update the time. */
7245 * This is equivalent to a write. Ensure it's seen immediately
7246 * if there are no pending writes.
7248 trigger_write_time_update_immediate(fsp);
7249 return NT_STATUS_OK;
7252 /* Pathname or stat or directory file. */
7253 status = SMB_VFS_CREATE_FILE(
7256 0, /* root_dir_fid */
7257 smb_fname, /* fname */
7258 FILE_WRITE_DATA, /* access_mask */
7259 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7261 FILE_OPEN, /* create_disposition*/
7262 0, /* create_options */
7263 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7264 0, /* oplock_request */
7266 0, /* allocation_size */
7267 0, /* private_flags */
7270 &new_fsp, /* result */
7272 NULL, NULL); /* create context */
7274 if (!NT_STATUS_IS_OK(status)) {
7275 /* NB. We check for open_was_deferred in the caller. */
7279 /* Only change if needed. */
7280 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7281 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7282 status = map_nt_error_from_unix(errno);
7283 close_file(req, new_fsp, NORMAL_CLOSE);
7288 /* Changing the allocation size should set the last mod time. */
7290 * This is equivalent to a write. Ensure it's seen immediately
7291 * if there are no pending writes.
7293 trigger_write_time_update_immediate(new_fsp);
7294 close_file(req, new_fsp, NORMAL_CLOSE);
7295 return NT_STATUS_OK;
7298 /****************************************************************************
7299 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7300 ****************************************************************************/
7302 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7303 struct smb_request *req,
7307 const struct smb_filename *smb_fname,
7308 bool fail_after_createfile)
7312 if (total_data < 8) {
7313 return NT_STATUS_INVALID_PARAMETER;
7316 size = IVAL(pdata,0);
7317 size |= (((off_t)IVAL(pdata,4)) << 32);
7318 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7319 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7322 return smb_set_file_size(conn, req,
7327 fail_after_createfile);
7330 /****************************************************************************
7331 Allow a UNIX info mknod.
7332 ****************************************************************************/
7334 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7337 const struct smb_filename *smb_fname)
7339 uint32_t file_type = IVAL(pdata,56);
7340 #if defined(HAVE_MAKEDEV)
7341 uint32_t dev_major = IVAL(pdata,60);
7342 uint32_t dev_minor = IVAL(pdata,68);
7344 SMB_DEV_T dev = (SMB_DEV_T)0;
7345 uint32_t raw_unixmode = IVAL(pdata,84);
7349 if (total_data < 100) {
7350 return NT_STATUS_INVALID_PARAMETER;
7353 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7354 PERM_NEW_FILE, &unixmode);
7355 if (!NT_STATUS_IS_OK(status)) {
7359 #if defined(HAVE_MAKEDEV)
7360 dev = makedev(dev_major, dev_minor);
7363 switch (file_type) {
7364 #if defined(S_IFIFO)
7365 case UNIX_TYPE_FIFO:
7366 unixmode |= S_IFIFO;
7369 #if defined(S_IFSOCK)
7370 case UNIX_TYPE_SOCKET:
7371 unixmode |= S_IFSOCK;
7374 #if defined(S_IFCHR)
7375 case UNIX_TYPE_CHARDEV:
7376 unixmode |= S_IFCHR;
7379 #if defined(S_IFBLK)
7380 case UNIX_TYPE_BLKDEV:
7381 unixmode |= S_IFBLK;
7385 return NT_STATUS_INVALID_PARAMETER;
7388 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7389 "%.0f mode 0%o for file %s\n", (double)dev,
7390 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7392 /* Ok - do the mknod. */
7393 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7394 return map_nt_error_from_unix(errno);
7397 /* If any of the other "set" calls fail we
7398 * don't want to end up with a half-constructed mknod.
7401 if (lp_inherit_permissions(SNUM(conn))) {
7403 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7405 return NT_STATUS_NO_MEMORY;
7407 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7409 TALLOC_FREE(parent);
7412 return NT_STATUS_OK;
7415 /****************************************************************************
7416 Deal with SMB_SET_FILE_UNIX_BASIC.
7417 ****************************************************************************/
7419 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7420 struct smb_request *req,
7424 const struct smb_filename *smb_fname)
7426 struct smb_file_time ft;
7427 uint32_t raw_unixmode;
7430 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7431 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7432 NTSTATUS status = NT_STATUS_OK;
7433 bool delete_on_fail = False;
7434 enum perm_type ptype;
7435 files_struct *all_fsps = NULL;
7436 bool modify_mtime = true;
7438 struct smb_filename *smb_fname_tmp = NULL;
7439 SMB_STRUCT_STAT sbuf;
7443 if (total_data < 100) {
7444 return NT_STATUS_INVALID_PARAMETER;
7447 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7448 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7449 size=IVAL(pdata,0); /* first 8 Bytes are size */
7450 size |= (((off_t)IVAL(pdata,4)) << 32);
7453 ft.atime = interpret_long_date(pdata+24); /* access_time */
7454 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7455 set_owner = (uid_t)IVAL(pdata,40);
7456 set_grp = (gid_t)IVAL(pdata,48);
7457 raw_unixmode = IVAL(pdata,84);
7459 if (VALID_STAT(smb_fname->st)) {
7460 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7461 ptype = PERM_EXISTING_DIR;
7463 ptype = PERM_EXISTING_FILE;
7466 ptype = PERM_NEW_FILE;
7469 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7471 if (!NT_STATUS_IS_OK(status)) {
7475 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7476 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7477 smb_fname_str_dbg(smb_fname), (double)size,
7478 (unsigned int)set_owner, (unsigned int)set_grp,
7479 (int)raw_unixmode));
7481 sbuf = smb_fname->st;
7483 if (!VALID_STAT(sbuf)) {
7485 * The only valid use of this is to create character and block
7486 * devices, and named pipes. This is deprecated (IMHO) and
7487 * a new info level should be used for mknod. JRA.
7490 status = smb_unix_mknod(conn,
7494 if (!NT_STATUS_IS_OK(status)) {
7498 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7499 if (smb_fname_tmp == NULL) {
7500 return NT_STATUS_NO_MEMORY;
7503 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7504 status = map_nt_error_from_unix(errno);
7505 TALLOC_FREE(smb_fname_tmp);
7506 SMB_VFS_UNLINK(conn, smb_fname);
7510 sbuf = smb_fname_tmp->st;
7511 smb_fname = smb_fname_tmp;
7513 /* Ensure we don't try and change anything else. */
7514 raw_unixmode = SMB_MODE_NO_CHANGE;
7515 size = get_file_size_stat(&sbuf);
7516 ft.atime = sbuf.st_ex_atime;
7517 ft.mtime = sbuf.st_ex_mtime;
7519 * We continue here as we might want to change the
7522 delete_on_fail = True;
7526 /* Horrible backwards compatibility hack as an old server bug
7527 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7531 size = get_file_size_stat(&sbuf);
7536 * Deal with the UNIX specific mode set.
7539 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7542 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7543 "setting mode 0%o for file %s\n",
7544 (unsigned int)unixmode,
7545 smb_fname_str_dbg(smb_fname)));
7546 if (fsp && fsp->fh->fd != -1) {
7547 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7549 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7552 return map_nt_error_from_unix(errno);
7557 * Deal with the UNIX specific uid set.
7560 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7561 (sbuf.st_ex_uid != set_owner)) {
7564 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7565 "changing owner %u for path %s\n",
7566 (unsigned int)set_owner,
7567 smb_fname_str_dbg(smb_fname)));
7569 if (fsp && fsp->fh->fd != -1) {
7570 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7573 * UNIX extensions calls must always operate
7576 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7577 set_owner, (gid_t)-1);
7581 status = map_nt_error_from_unix(errno);
7582 if (delete_on_fail) {
7583 SMB_VFS_UNLINK(conn, smb_fname);
7590 * Deal with the UNIX specific gid set.
7593 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7594 (sbuf.st_ex_gid != set_grp)) {
7597 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7598 "changing group %u for file %s\n",
7599 (unsigned int)set_owner,
7600 smb_fname_str_dbg(smb_fname)));
7601 if (fsp && fsp->fh->fd != -1) {
7602 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7605 * UNIX extensions calls must always operate
7608 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7612 status = map_nt_error_from_unix(errno);
7613 if (delete_on_fail) {
7614 SMB_VFS_UNLINK(conn, smb_fname);
7620 /* Deal with any size changes. */
7622 status = smb_set_file_size(conn, req,
7628 if (!NT_STATUS_IS_OK(status)) {
7632 /* Deal with any time changes. */
7633 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7634 /* No change, don't cancel anything. */
7638 id = vfs_file_id_from_sbuf(conn, &sbuf);
7639 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7640 all_fsps = file_find_di_next(all_fsps)) {
7642 * We're setting the time explicitly for UNIX.
7643 * Cancel any pending changes over all handles.
7645 all_fsps->update_write_time_on_close = false;
7646 TALLOC_FREE(all_fsps->update_write_time_event);
7650 * Override the "setting_write_time"
7651 * parameter here as it almost does what
7652 * we need. Just remember if we modified
7653 * mtime and send the notify ourselves.
7655 if (null_timespec(ft.mtime)) {
7656 modify_mtime = false;
7659 status = smb_set_file_time(conn,
7665 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7666 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7671 /****************************************************************************
7672 Deal with SMB_SET_FILE_UNIX_INFO2.
7673 ****************************************************************************/
7675 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7676 struct smb_request *req,
7680 const struct smb_filename *smb_fname)
7683 uint32_t smb_fflags;
7686 if (total_data < 116) {
7687 return NT_STATUS_INVALID_PARAMETER;
7690 /* Start by setting all the fields that are common between UNIX_BASIC
7693 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7695 if (!NT_STATUS_IS_OK(status)) {
7699 smb_fflags = IVAL(pdata, 108);
7700 smb_fmask = IVAL(pdata, 112);
7702 /* NB: We should only attempt to alter the file flags if the client
7703 * sends a non-zero mask.
7705 if (smb_fmask != 0) {
7706 int stat_fflags = 0;
7708 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7709 smb_fmask, &stat_fflags)) {
7710 /* Client asked to alter a flag we don't understand. */
7711 return NT_STATUS_INVALID_PARAMETER;
7714 if (fsp && fsp->fh->fd != -1) {
7715 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7716 return NT_STATUS_NOT_SUPPORTED;
7718 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7719 stat_fflags) != 0) {
7720 return map_nt_error_from_unix(errno);
7725 /* XXX: need to add support for changing the create_time here. You
7726 * can do this for paths on Darwin with setattrlist(2). The right way
7727 * to hook this up is probably by extending the VFS utimes interface.
7730 return NT_STATUS_OK;
7733 /****************************************************************************
7734 Create a directory with POSIX semantics.
7735 ****************************************************************************/
7737 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7738 struct smb_request *req,
7741 struct smb_filename *smb_fname,
7742 int *pdata_return_size)
7744 NTSTATUS status = NT_STATUS_OK;
7745 uint32_t raw_unixmode = 0;
7746 uint32_t mod_unixmode = 0;
7747 mode_t unixmode = (mode_t)0;
7748 files_struct *fsp = NULL;
7749 uint16_t info_level_return = 0;
7751 char *pdata = *ppdata;
7753 if (total_data < 18) {
7754 return NT_STATUS_INVALID_PARAMETER;
7757 raw_unixmode = IVAL(pdata,8);
7758 /* Next 4 bytes are not yet defined. */
7760 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7761 PERM_NEW_DIR, &unixmode);
7762 if (!NT_STATUS_IS_OK(status)) {
7766 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7768 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7769 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7771 status = SMB_VFS_CREATE_FILE(
7774 0, /* root_dir_fid */
7775 smb_fname, /* fname */
7776 FILE_READ_ATTRIBUTES, /* access_mask */
7777 FILE_SHARE_NONE, /* share_access */
7778 FILE_CREATE, /* create_disposition*/
7779 FILE_DIRECTORY_FILE, /* create_options */
7780 mod_unixmode, /* file_attributes */
7781 0, /* oplock_request */
7783 0, /* allocation_size */
7784 0, /* private_flags */
7789 NULL, NULL); /* create context */
7791 if (NT_STATUS_IS_OK(status)) {
7792 close_file(req, fsp, NORMAL_CLOSE);
7795 info_level_return = SVAL(pdata,16);
7797 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7798 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7799 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7800 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7802 *pdata_return_size = 12;
7805 /* Realloc the data size */
7806 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7807 if (*ppdata == NULL) {
7808 *pdata_return_size = 0;
7809 return NT_STATUS_NO_MEMORY;
7813 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7814 SSVAL(pdata,2,0); /* No fnum. */
7815 SIVAL(pdata,4,info); /* Was directory created. */
7817 switch (info_level_return) {
7818 case SMB_QUERY_FILE_UNIX_BASIC:
7819 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7820 SSVAL(pdata,10,0); /* Padding. */
7821 store_file_unix_basic(conn, pdata + 12, fsp,
7824 case SMB_QUERY_FILE_UNIX_INFO2:
7825 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7826 SSVAL(pdata,10,0); /* Padding. */
7827 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7831 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7832 SSVAL(pdata,10,0); /* Padding. */
7839 /****************************************************************************
7840 Open/Create a file with POSIX semantics.
7841 ****************************************************************************/
7843 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7844 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7846 static NTSTATUS smb_posix_open(connection_struct *conn,
7847 struct smb_request *req,
7850 struct smb_filename *smb_fname,
7851 int *pdata_return_size)
7853 bool extended_oplock_granted = False;
7854 char *pdata = *ppdata;
7856 uint32_t wire_open_mode = 0;
7857 uint32_t raw_unixmode = 0;
7858 uint32_t mod_unixmode = 0;
7859 uint32_t create_disp = 0;
7860 uint32_t access_mask = 0;
7861 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7862 NTSTATUS status = NT_STATUS_OK;
7863 mode_t unixmode = (mode_t)0;
7864 files_struct *fsp = NULL;
7865 int oplock_request = 0;
7867 uint16_t info_level_return = 0;
7869 if (total_data < 18) {
7870 return NT_STATUS_INVALID_PARAMETER;
7873 flags = IVAL(pdata,0);
7874 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7875 if (oplock_request) {
7876 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7879 wire_open_mode = IVAL(pdata,4);
7881 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7882 return smb_posix_mkdir(conn, req,
7889 switch (wire_open_mode & SMB_ACCMODE) {
7891 access_mask = SMB_O_RDONLY_MAPPING;
7894 access_mask = SMB_O_WRONLY_MAPPING;
7897 access_mask = (SMB_O_RDONLY_MAPPING|
7898 SMB_O_WRONLY_MAPPING);
7901 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7902 (unsigned int)wire_open_mode ));
7903 return NT_STATUS_INVALID_PARAMETER;
7906 wire_open_mode &= ~SMB_ACCMODE;
7908 /* First take care of O_CREAT|O_EXCL interactions. */
7909 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7910 case (SMB_O_CREAT | SMB_O_EXCL):
7911 /* File exists fail. File not exist create. */
7912 create_disp = FILE_CREATE;
7915 /* File exists open. File not exist create. */
7916 create_disp = FILE_OPEN_IF;
7919 /* O_EXCL on its own without O_CREAT is undefined.
7920 We deliberately ignore it as some versions of
7921 Linux CIFSFS can send a bare O_EXCL on the
7922 wire which other filesystems in the kernel
7923 ignore. See bug 9519 for details. */
7928 /* File exists open. File not exist fail. */
7929 create_disp = FILE_OPEN;
7932 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7933 (unsigned int)wire_open_mode ));
7934 return NT_STATUS_INVALID_PARAMETER;
7937 /* Next factor in the effects of O_TRUNC. */
7938 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7940 if (wire_open_mode & SMB_O_TRUNC) {
7941 switch (create_disp) {
7943 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7944 /* Leave create_disp alone as
7945 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7947 /* File exists fail. File not exist create. */
7950 /* SMB_O_CREAT | SMB_O_TRUNC */
7951 /* File exists overwrite. File not exist create. */
7952 create_disp = FILE_OVERWRITE_IF;
7956 /* File exists overwrite. File not exist fail. */
7957 create_disp = FILE_OVERWRITE;
7960 /* Cannot get here. */
7961 smb_panic("smb_posix_open: logic error");
7962 return NT_STATUS_INVALID_PARAMETER;
7966 raw_unixmode = IVAL(pdata,8);
7967 /* Next 4 bytes are not yet defined. */
7969 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7970 (VALID_STAT(smb_fname->st) ?
7971 PERM_EXISTING_FILE : PERM_NEW_FILE),
7974 if (!NT_STATUS_IS_OK(status)) {
7978 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7980 if (wire_open_mode & SMB_O_SYNC) {
7981 create_options |= FILE_WRITE_THROUGH;
7983 if (wire_open_mode & SMB_O_APPEND) {
7984 access_mask |= FILE_APPEND_DATA;
7986 if (wire_open_mode & SMB_O_DIRECT) {
7987 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7990 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7991 VALID_STAT_OF_DIR(smb_fname->st)) {
7992 if (access_mask != SMB_O_RDONLY_MAPPING) {
7993 return NT_STATUS_FILE_IS_A_DIRECTORY;
7995 create_options &= ~FILE_NON_DIRECTORY_FILE;
7996 create_options |= FILE_DIRECTORY_FILE;
7999 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8000 smb_fname_str_dbg(smb_fname),
8001 (unsigned int)wire_open_mode,
8002 (unsigned int)unixmode ));
8004 status = SMB_VFS_CREATE_FILE(
8007 0, /* root_dir_fid */
8008 smb_fname, /* fname */
8009 access_mask, /* access_mask */
8010 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8012 create_disp, /* create_disposition*/
8013 create_options, /* create_options */
8014 mod_unixmode, /* file_attributes */
8015 oplock_request, /* oplock_request */
8017 0, /* allocation_size */
8018 0, /* private_flags */
8023 NULL, NULL); /* create context */
8025 if (!NT_STATUS_IS_OK(status)) {
8029 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8030 extended_oplock_granted = True;
8033 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8034 extended_oplock_granted = True;
8037 info_level_return = SVAL(pdata,16);
8039 /* Allocate the correct return size. */
8041 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8042 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8043 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8044 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8046 *pdata_return_size = 12;
8049 /* Realloc the data size */
8050 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8051 if (*ppdata == NULL) {
8052 close_file(req, fsp, ERROR_CLOSE);
8053 *pdata_return_size = 0;
8054 return NT_STATUS_NO_MEMORY;
8058 if (extended_oplock_granted) {
8059 if (flags & REQUEST_BATCH_OPLOCK) {
8060 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8062 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8064 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8065 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8067 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8070 SSVAL(pdata,2,fsp->fnum);
8071 SIVAL(pdata,4,info); /* Was file created etc. */
8073 switch (info_level_return) {
8074 case SMB_QUERY_FILE_UNIX_BASIC:
8075 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8076 SSVAL(pdata,10,0); /* padding. */
8077 store_file_unix_basic(conn, pdata + 12, fsp,
8080 case SMB_QUERY_FILE_UNIX_INFO2:
8081 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8082 SSVAL(pdata,10,0); /* padding. */
8083 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8087 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8088 SSVAL(pdata,10,0); /* padding. */
8091 return NT_STATUS_OK;
8094 /****************************************************************************
8095 Delete a file with POSIX semantics.
8096 ****************************************************************************/
8098 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8099 struct smb_request *req,
8102 struct smb_filename *smb_fname)
8104 NTSTATUS status = NT_STATUS_OK;
8105 files_struct *fsp = NULL;
8109 int create_options = 0;
8111 struct share_mode_lock *lck = NULL;
8113 if (total_data < 2) {
8114 return NT_STATUS_INVALID_PARAMETER;
8117 flags = SVAL(pdata,0);
8119 if (!VALID_STAT(smb_fname->st)) {
8120 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8123 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8124 !VALID_STAT_OF_DIR(smb_fname->st)) {
8125 return NT_STATUS_NOT_A_DIRECTORY;
8128 DEBUG(10,("smb_posix_unlink: %s %s\n",
8129 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8130 smb_fname_str_dbg(smb_fname)));
8132 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8133 create_options |= FILE_DIRECTORY_FILE;
8136 status = SMB_VFS_CREATE_FILE(
8139 0, /* root_dir_fid */
8140 smb_fname, /* fname */
8141 DELETE_ACCESS, /* access_mask */
8142 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8144 FILE_OPEN, /* create_disposition*/
8145 create_options, /* create_options */
8146 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8147 0, /* oplock_request */
8149 0, /* allocation_size */
8150 0, /* private_flags */
8155 NULL, NULL); /* create context */
8157 if (!NT_STATUS_IS_OK(status)) {
8162 * Don't lie to client. If we can't really delete due to
8163 * non-POSIX opens return SHARING_VIOLATION.
8166 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8168 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8169 "lock for file %s\n", fsp_str_dbg(fsp)));
8170 close_file(req, fsp, NORMAL_CLOSE);
8171 return NT_STATUS_INVALID_PARAMETER;
8175 * See if others still have the file open. If this is the case, then
8176 * don't delete. If all opens are POSIX delete we can set the delete
8177 * on close disposition.
8179 for (i=0; i<lck->data->num_share_modes; i++) {
8180 struct share_mode_entry *e = &lck->data->share_modes[i];
8181 if (is_valid_share_mode_entry(e)) {
8182 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8185 if (share_mode_stale_pid(lck->data, i)) {
8188 /* Fail with sharing violation. */
8190 close_file(req, fsp, NORMAL_CLOSE);
8191 return NT_STATUS_SHARING_VIOLATION;
8196 * Set the delete on close.
8198 status = smb_set_file_disposition_info(conn,
8206 if (!NT_STATUS_IS_OK(status)) {
8207 close_file(req, fsp, NORMAL_CLOSE);
8210 return close_file(req, fsp, NORMAL_CLOSE);
8213 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8214 struct smb_request *req,
8215 TALLOC_CTX *mem_ctx,
8216 uint16_t info_level,
8218 struct smb_filename *smb_fname,
8219 char **ppdata, int total_data,
8222 char *pdata = *ppdata;
8223 NTSTATUS status = NT_STATUS_OK;
8224 int data_return_size = 0;
8228 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8229 return NT_STATUS_INVALID_LEVEL;
8232 if (!CAN_WRITE(conn)) {
8233 /* Allow POSIX opens. The open path will deny
8234 * any non-readonly opens. */
8235 if (info_level != SMB_POSIX_PATH_OPEN) {
8236 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8240 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8241 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8243 info_level, total_data));
8245 switch (info_level) {
8247 case SMB_INFO_STANDARD:
8249 status = smb_set_info_standard(conn,
8257 case SMB_INFO_SET_EA:
8259 status = smb_info_set_ea(conn,
8267 case SMB_SET_FILE_BASIC_INFO:
8268 case SMB_FILE_BASIC_INFORMATION:
8270 status = smb_set_file_basic_info(conn,
8278 case SMB_FILE_ALLOCATION_INFORMATION:
8279 case SMB_SET_FILE_ALLOCATION_INFO:
8281 status = smb_set_file_allocation_info(conn, req,
8289 case SMB_FILE_END_OF_FILE_INFORMATION:
8290 case SMB_SET_FILE_END_OF_FILE_INFO:
8293 * XP/Win7 both fail after the createfile with
8294 * SMB_SET_FILE_END_OF_FILE_INFO but not
8295 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8296 * The level is known here, so pass it down
8300 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8302 status = smb_set_file_end_of_file_info(conn, req,
8311 case SMB_FILE_DISPOSITION_INFORMATION:
8312 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8315 /* JRA - We used to just ignore this on a path ?
8316 * Shouldn't this be invalid level on a pathname
8319 if (tran_call != TRANSACT2_SETFILEINFO) {
8320 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8323 status = smb_set_file_disposition_info(conn,
8331 case SMB_FILE_POSITION_INFORMATION:
8333 status = smb_file_position_information(conn,
8340 case SMB_FILE_FULL_EA_INFORMATION:
8342 status = smb_set_file_full_ea_info(conn,
8349 /* From tridge Samba4 :
8350 * MODE_INFORMATION in setfileinfo (I have no
8351 * idea what "mode information" on a file is - it takes a value of 0,
8352 * 2, 4 or 6. What could it be?).
8355 case SMB_FILE_MODE_INFORMATION:
8357 status = smb_file_mode_information(conn,
8364 * CIFS UNIX extensions.
8367 case SMB_SET_FILE_UNIX_BASIC:
8369 status = smb_set_file_unix_basic(conn, req,
8377 case SMB_SET_FILE_UNIX_INFO2:
8379 status = smb_set_file_unix_info2(conn, req,
8387 case SMB_SET_FILE_UNIX_LINK:
8390 /* We must have a pathname for this. */
8391 return NT_STATUS_INVALID_LEVEL;
8393 status = smb_set_file_unix_link(conn, req, pdata,
8394 total_data, smb_fname);
8398 case SMB_SET_FILE_UNIX_HLINK:
8401 /* We must have a pathname for this. */
8402 return NT_STATUS_INVALID_LEVEL;
8404 status = smb_set_file_unix_hlink(conn, req,
8410 case SMB_FILE_RENAME_INFORMATION:
8412 status = smb_file_rename_information(conn, req,
8418 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8420 /* SMB2 rename information. */
8421 status = smb2_file_rename_information(conn, req,
8427 case SMB_FILE_LINK_INFORMATION:
8429 status = smb_file_link_information(conn, req,
8435 #if defined(HAVE_POSIX_ACLS)
8436 case SMB_SET_POSIX_ACL:
8438 status = smb_set_posix_acl(conn,
8447 case SMB_SET_POSIX_LOCK:
8450 return NT_STATUS_INVALID_LEVEL;
8452 status = smb_set_posix_lock(conn, req,
8453 pdata, total_data, fsp);
8457 case SMB_POSIX_PATH_OPEN:
8460 /* We must have a pathname for this. */
8461 return NT_STATUS_INVALID_LEVEL;
8464 status = smb_posix_open(conn, req,
8472 case SMB_POSIX_PATH_UNLINK:
8475 /* We must have a pathname for this. */
8476 return NT_STATUS_INVALID_LEVEL;
8479 status = smb_posix_unlink(conn, req,
8487 return NT_STATUS_INVALID_LEVEL;
8490 if (!NT_STATUS_IS_OK(status)) {
8494 *ret_data_size = data_return_size;
8495 return NT_STATUS_OK;
8498 /****************************************************************************
8499 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8500 ****************************************************************************/
8502 static void call_trans2setfilepathinfo(connection_struct *conn,
8503 struct smb_request *req,
8504 unsigned int tran_call,
8505 char **pparams, int total_params,
8506 char **ppdata, int total_data,
8507 unsigned int max_data_bytes)
8509 char *params = *pparams;
8510 char *pdata = *ppdata;
8511 uint16_t info_level;
8512 struct smb_filename *smb_fname = NULL;
8513 files_struct *fsp = NULL;
8514 NTSTATUS status = NT_STATUS_OK;
8515 int data_return_size = 0;
8518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8522 if (tran_call == TRANSACT2_SETFILEINFO) {
8523 if (total_params < 4) {
8524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8528 fsp = file_fsp(req, SVAL(params,0));
8529 /* Basic check for non-null fsp. */
8530 if (!check_fsp_open(conn, req, fsp)) {
8533 info_level = SVAL(params,2);
8535 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8536 if (smb_fname == NULL) {
8537 reply_nterror(req, NT_STATUS_NO_MEMORY);
8541 if(fsp->fh->fd == -1) {
8543 * This is actually a SETFILEINFO on a directory
8544 * handle (returned from an NT SMB). NT5.0 seems
8545 * to do this call. JRA.
8547 if (INFO_LEVEL_IS_UNIX(info_level)) {
8548 /* Always do lstat for UNIX calls. */
8549 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8550 DEBUG(3,("call_trans2setfilepathinfo: "
8551 "SMB_VFS_LSTAT of %s failed "
8553 smb_fname_str_dbg(smb_fname),
8555 reply_nterror(req, map_nt_error_from_unix(errno));
8559 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8560 DEBUG(3,("call_trans2setfilepathinfo: "
8561 "fileinfo of %s failed (%s)\n",
8562 smb_fname_str_dbg(smb_fname),
8564 reply_nterror(req, map_nt_error_from_unix(errno));
8568 } else if (fsp->print_file) {
8570 * Doing a DELETE_ON_CLOSE should cancel a print job.
8572 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8573 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8575 DEBUG(3,("call_trans2setfilepathinfo: "
8576 "Cancelling print job (%s)\n",
8580 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8586 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8591 * Original code - this is an open file.
8593 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8594 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8595 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8597 reply_nterror(req, map_nt_error_from_unix(errno));
8603 uint32_t ucf_flags = (req->posix_pathnames ?
8604 UCF_POSIX_PATHNAMES : 0);
8607 if (total_params < 7) {
8608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8612 info_level = SVAL(params,0);
8613 if (req->posix_pathnames) {
8614 srvstr_get_path_posix(req,
8623 srvstr_get_path(req,
8632 if (!NT_STATUS_IS_OK(status)) {
8633 reply_nterror(req, status);
8637 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8638 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8639 info_level == SMB_FILE_RENAME_INFORMATION ||
8640 info_level == SMB_POSIX_PATH_UNLINK) {
8641 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8644 status = filename_convert(req, conn,
8645 req->flags2 & FLAGS2_DFS_PATHNAMES,
8650 if (!NT_STATUS_IS_OK(status)) {
8651 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8652 reply_botherror(req,
8653 NT_STATUS_PATH_NOT_COVERED,
8654 ERRSRV, ERRbadpath);
8657 reply_nterror(req, status);
8661 if (INFO_LEVEL_IS_UNIX(info_level)) {
8663 * For CIFS UNIX extensions the target name may not exist.
8666 /* Always do lstat for UNIX calls. */
8667 SMB_VFS_LSTAT(conn, smb_fname);
8669 } else if (!VALID_STAT(smb_fname->st) &&
8670 SMB_VFS_STAT(conn, smb_fname)) {
8671 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8673 smb_fname_str_dbg(smb_fname),
8675 reply_nterror(req, map_nt_error_from_unix(errno));
8680 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8681 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8683 info_level,total_data));
8685 /* Realloc the parameter size */
8686 *pparams = (char *)SMB_REALLOC(*pparams,2);
8687 if (*pparams == NULL) {
8688 reply_nterror(req, NT_STATUS_NO_MEMORY);
8695 status = smbd_do_setfilepathinfo(conn, req, req,
8701 if (!NT_STATUS_IS_OK(status)) {
8702 if (open_was_deferred(req->xconn, req->mid)) {
8703 /* We have re-scheduled this call. */
8706 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8707 /* We have re-scheduled this call. */
8710 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8711 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8712 ERRSRV, ERRbadpath);
8715 if (info_level == SMB_POSIX_PATH_OPEN) {
8716 reply_openerror(req, status);
8721 * Invalid EA name needs to return 2 param bytes,
8722 * not a zero-length error packet.
8724 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8725 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8728 reply_nterror(req, status);
8733 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8739 /****************************************************************************
8740 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8741 ****************************************************************************/
8743 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8744 char **pparams, int total_params,
8745 char **ppdata, int total_data,
8746 unsigned int max_data_bytes)
8748 struct smb_filename *smb_dname = NULL;
8749 char *params = *pparams;
8750 char *pdata = *ppdata;
8751 char *directory = NULL;
8752 NTSTATUS status = NT_STATUS_OK;
8753 struct ea_list *ea_list = NULL;
8754 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
8755 TALLOC_CTX *ctx = talloc_tos();
8757 if (!CAN_WRITE(conn)) {
8758 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8762 if (total_params < 5) {
8763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8767 if (req->posix_pathnames) {
8768 srvstr_get_path_posix(ctx,
8777 srvstr_get_path(ctx,
8786 if (!NT_STATUS_IS_OK(status)) {
8787 reply_nterror(req, status);
8791 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8793 status = filename_convert(ctx,
8795 req->flags2 & FLAGS2_DFS_PATHNAMES,
8801 if (!NT_STATUS_IS_OK(status)) {
8802 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8803 reply_botherror(req,
8804 NT_STATUS_PATH_NOT_COVERED,
8805 ERRSRV, ERRbadpath);
8808 reply_nterror(req, status);
8813 * OS/2 workplace shell seems to send SET_EA requests of "null"
8814 * length (4 bytes containing IVAL 4).
8815 * They seem to have no effect. Bug #3212. JRA.
8818 if (total_data && (total_data != 4)) {
8819 /* Any data in this call is an EA list. */
8820 if (total_data < 10) {
8821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8825 if (IVAL(pdata,0) > total_data) {
8826 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8827 IVAL(pdata,0), (unsigned int)total_data));
8828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8832 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8835 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8839 if (!lp_ea_support(SNUM(conn))) {
8840 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8844 /* If total_data == 4 Windows doesn't care what values
8845 * are placed in that field, it just ignores them.
8846 * The System i QNTC IBM SMB client puts bad values here,
8847 * so ignore them. */
8849 status = create_directory(conn, req, smb_dname);
8851 if (!NT_STATUS_IS_OK(status)) {
8852 reply_nterror(req, status);
8856 /* Try and set any given EA. */
8858 status = set_ea(conn, NULL, smb_dname, ea_list);
8859 if (!NT_STATUS_IS_OK(status)) {
8860 reply_nterror(req, status);
8865 /* Realloc the parameter and data sizes */
8866 *pparams = (char *)SMB_REALLOC(*pparams,2);
8867 if(*pparams == NULL) {
8868 reply_nterror(req, NT_STATUS_NO_MEMORY);
8875 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8878 TALLOC_FREE(smb_dname);
8882 /****************************************************************************
8883 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8884 We don't actually do this - we just send a null response.
8885 ****************************************************************************/
8887 static void call_trans2findnotifyfirst(connection_struct *conn,
8888 struct smb_request *req,
8889 char **pparams, int total_params,
8890 char **ppdata, int total_data,
8891 unsigned int max_data_bytes)
8893 char *params = *pparams;
8894 uint16_t info_level;
8896 if (total_params < 6) {
8897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8901 info_level = SVAL(params,4);
8902 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8904 switch (info_level) {
8909 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8913 /* Realloc the parameter and data sizes */
8914 *pparams = (char *)SMB_REALLOC(*pparams,6);
8915 if (*pparams == NULL) {
8916 reply_nterror(req, NT_STATUS_NO_MEMORY);
8921 SSVAL(params,0,fnf_handle);
8922 SSVAL(params,2,0); /* No changes */
8923 SSVAL(params,4,0); /* No EA errors */
8930 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8935 /****************************************************************************
8936 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8937 changes). Currently this does nothing.
8938 ****************************************************************************/
8940 static void call_trans2findnotifynext(connection_struct *conn,
8941 struct smb_request *req,
8942 char **pparams, int total_params,
8943 char **ppdata, int total_data,
8944 unsigned int max_data_bytes)
8946 char *params = *pparams;
8948 DEBUG(3,("call_trans2findnotifynext\n"));
8950 /* Realloc the parameter and data sizes */
8951 *pparams = (char *)SMB_REALLOC(*pparams,4);
8952 if (*pparams == NULL) {
8953 reply_nterror(req, NT_STATUS_NO_MEMORY);
8958 SSVAL(params,0,0); /* No changes */
8959 SSVAL(params,2,0); /* No EA errors */
8961 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8966 /****************************************************************************
8967 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8968 ****************************************************************************/
8970 static void call_trans2getdfsreferral(connection_struct *conn,
8971 struct smb_request *req,
8972 char **pparams, int total_params,
8973 char **ppdata, int total_data,
8974 unsigned int max_data_bytes)
8976 char *params = *pparams;
8977 char *pathname = NULL;
8979 int max_referral_level;
8980 NTSTATUS status = NT_STATUS_OK;
8981 TALLOC_CTX *ctx = talloc_tos();
8983 DEBUG(10,("call_trans2getdfsreferral\n"));
8985 if (total_params < 3) {
8986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8990 max_referral_level = SVAL(params,0);
8992 if(!lp_host_msdfs()) {
8993 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8997 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8998 total_params - 2, STR_TERMINATE);
9000 reply_nterror(req, NT_STATUS_NOT_FOUND);
9003 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9004 ppdata,&status)) < 0) {
9005 reply_nterror(req, status);
9009 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9010 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9011 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9016 #define LMCAT_SPL 0x53
9017 #define LMFUNC_GETJOBID 0x60
9019 /****************************************************************************
9020 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9021 ****************************************************************************/
9023 static void call_trans2ioctl(connection_struct *conn,
9024 struct smb_request *req,
9025 char **pparams, int total_params,
9026 char **ppdata, int total_data,
9027 unsigned int max_data_bytes)
9029 char *pdata = *ppdata;
9030 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9034 /* check for an invalid fid before proceeding */
9037 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9041 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9042 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9043 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9044 if (*ppdata == NULL) {
9045 reply_nterror(req, NT_STATUS_NO_MEMORY);
9050 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9051 CAN ACCEPT THIS IN UNICODE. JRA. */
9054 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9056 status = srvstr_push(pdata, req->flags2, pdata + 2,
9057 lp_netbios_name(), 15,
9058 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9059 if (!NT_STATUS_IS_OK(status)) {
9060 reply_nterror(req, status);
9063 status = srvstr_push(pdata, req->flags2, pdata+18,
9064 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9065 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9066 if (!NT_STATUS_IS_OK(status)) {
9067 reply_nterror(req, status);
9070 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9075 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9076 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9079 /****************************************************************************
9080 Reply to a SMBfindclose (stop trans2 directory search).
9081 ****************************************************************************/
9083 void reply_findclose(struct smb_request *req)
9086 struct smbd_server_connection *sconn = req->sconn;
9088 START_PROFILE(SMBfindclose);
9091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9092 END_PROFILE(SMBfindclose);
9096 dptr_num = SVALS(req->vwv+0, 0);
9098 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9100 dptr_close(sconn, &dptr_num);
9102 reply_outbuf(req, 0, 0);
9104 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9106 END_PROFILE(SMBfindclose);
9110 /****************************************************************************
9111 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9112 ****************************************************************************/
9114 void reply_findnclose(struct smb_request *req)
9118 START_PROFILE(SMBfindnclose);
9121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9122 END_PROFILE(SMBfindnclose);
9126 dptr_num = SVAL(req->vwv+0, 0);
9128 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9130 /* We never give out valid handles for a
9131 findnotifyfirst - so any dptr_num is ok here.
9134 reply_outbuf(req, 0, 0);
9136 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9138 END_PROFILE(SMBfindnclose);
9142 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9143 struct trans_state *state)
9145 if (get_Protocol() >= PROTOCOL_NT1) {
9146 req->flags2 |= 0x40; /* IS_LONG_NAME */
9147 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9150 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9151 if (state->call != TRANSACT2_QFSINFO &&
9152 state->call != TRANSACT2_SETFSINFO) {
9153 DEBUG(0,("handle_trans2: encryption required "
9155 (unsigned int)state->call));
9156 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9161 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9163 /* Now we must call the relevant TRANS2 function */
9164 switch(state->call) {
9165 case TRANSACT2_OPEN:
9167 START_PROFILE(Trans2_open);
9168 call_trans2open(conn, req,
9169 &state->param, state->total_param,
9170 &state->data, state->total_data,
9171 state->max_data_return);
9172 END_PROFILE(Trans2_open);
9176 case TRANSACT2_FINDFIRST:
9178 START_PROFILE(Trans2_findfirst);
9179 call_trans2findfirst(conn, req,
9180 &state->param, state->total_param,
9181 &state->data, state->total_data,
9182 state->max_data_return);
9183 END_PROFILE(Trans2_findfirst);
9187 case TRANSACT2_FINDNEXT:
9189 START_PROFILE(Trans2_findnext);
9190 call_trans2findnext(conn, req,
9191 &state->param, state->total_param,
9192 &state->data, state->total_data,
9193 state->max_data_return);
9194 END_PROFILE(Trans2_findnext);
9198 case TRANSACT2_QFSINFO:
9200 START_PROFILE(Trans2_qfsinfo);
9201 call_trans2qfsinfo(conn, req,
9202 &state->param, state->total_param,
9203 &state->data, state->total_data,
9204 state->max_data_return);
9205 END_PROFILE(Trans2_qfsinfo);
9209 case TRANSACT2_SETFSINFO:
9211 START_PROFILE(Trans2_setfsinfo);
9212 call_trans2setfsinfo(conn, req,
9213 &state->param, state->total_param,
9214 &state->data, state->total_data,
9215 state->max_data_return);
9216 END_PROFILE(Trans2_setfsinfo);
9220 case TRANSACT2_QPATHINFO:
9221 case TRANSACT2_QFILEINFO:
9223 START_PROFILE(Trans2_qpathinfo);
9224 call_trans2qfilepathinfo(conn, req, state->call,
9225 &state->param, state->total_param,
9226 &state->data, state->total_data,
9227 state->max_data_return);
9228 END_PROFILE(Trans2_qpathinfo);
9232 case TRANSACT2_SETPATHINFO:
9233 case TRANSACT2_SETFILEINFO:
9235 START_PROFILE(Trans2_setpathinfo);
9236 call_trans2setfilepathinfo(conn, req, state->call,
9237 &state->param, state->total_param,
9238 &state->data, state->total_data,
9239 state->max_data_return);
9240 END_PROFILE(Trans2_setpathinfo);
9244 case TRANSACT2_FINDNOTIFYFIRST:
9246 START_PROFILE(Trans2_findnotifyfirst);
9247 call_trans2findnotifyfirst(conn, req,
9248 &state->param, state->total_param,
9249 &state->data, state->total_data,
9250 state->max_data_return);
9251 END_PROFILE(Trans2_findnotifyfirst);
9255 case TRANSACT2_FINDNOTIFYNEXT:
9257 START_PROFILE(Trans2_findnotifynext);
9258 call_trans2findnotifynext(conn, req,
9259 &state->param, state->total_param,
9260 &state->data, state->total_data,
9261 state->max_data_return);
9262 END_PROFILE(Trans2_findnotifynext);
9266 case TRANSACT2_MKDIR:
9268 START_PROFILE(Trans2_mkdir);
9269 call_trans2mkdir(conn, req,
9270 &state->param, state->total_param,
9271 &state->data, state->total_data,
9272 state->max_data_return);
9273 END_PROFILE(Trans2_mkdir);
9277 case TRANSACT2_GET_DFS_REFERRAL:
9279 START_PROFILE(Trans2_get_dfs_referral);
9280 call_trans2getdfsreferral(conn, req,
9281 &state->param, state->total_param,
9282 &state->data, state->total_data,
9283 state->max_data_return);
9284 END_PROFILE(Trans2_get_dfs_referral);
9288 case TRANSACT2_IOCTL:
9290 START_PROFILE(Trans2_ioctl);
9291 call_trans2ioctl(conn, req,
9292 &state->param, state->total_param,
9293 &state->data, state->total_data,
9294 state->max_data_return);
9295 END_PROFILE(Trans2_ioctl);
9300 /* Error in request */
9301 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9302 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9306 /****************************************************************************
9307 Reply to a SMBtrans2.
9308 ****************************************************************************/
9310 void reply_trans2(struct smb_request *req)
9312 connection_struct *conn = req->conn;
9317 unsigned int tran_call;
9318 struct trans_state *state;
9321 START_PROFILE(SMBtrans2);
9323 if (req->wct < 14) {
9324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9325 END_PROFILE(SMBtrans2);
9329 dsoff = SVAL(req->vwv+12, 0);
9330 dscnt = SVAL(req->vwv+11, 0);
9331 psoff = SVAL(req->vwv+10, 0);
9332 pscnt = SVAL(req->vwv+9, 0);
9333 tran_call = SVAL(req->vwv+14, 0);
9335 result = allow_new_trans(conn->pending_trans, req->mid);
9336 if (!NT_STATUS_IS_OK(result)) {
9337 DEBUG(2, ("Got invalid trans2 request: %s\n",
9338 nt_errstr(result)));
9339 reply_nterror(req, result);
9340 END_PROFILE(SMBtrans2);
9345 switch (tran_call) {
9346 /* List the allowed trans2 calls on IPC$ */
9347 case TRANSACT2_OPEN:
9348 case TRANSACT2_GET_DFS_REFERRAL:
9349 case TRANSACT2_QFILEINFO:
9350 case TRANSACT2_QFSINFO:
9351 case TRANSACT2_SETFSINFO:
9354 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9355 END_PROFILE(SMBtrans2);
9360 if ((state = talloc(conn, struct trans_state)) == NULL) {
9361 DEBUG(0, ("talloc failed\n"));
9362 reply_nterror(req, NT_STATUS_NO_MEMORY);
9363 END_PROFILE(SMBtrans2);
9367 state->cmd = SMBtrans2;
9369 state->mid = req->mid;
9370 state->vuid = req->vuid;
9371 state->setup_count = SVAL(req->vwv+13, 0);
9372 state->setup = NULL;
9373 state->total_param = SVAL(req->vwv+0, 0);
9374 state->param = NULL;
9375 state->total_data = SVAL(req->vwv+1, 0);
9377 state->max_param_return = SVAL(req->vwv+2, 0);
9378 state->max_data_return = SVAL(req->vwv+3, 0);
9379 state->max_setup_return = SVAL(req->vwv+4, 0);
9380 state->close_on_completion = BITSETW(req->vwv+5, 0);
9381 state->one_way = BITSETW(req->vwv+5, 1);
9383 state->call = tran_call;
9385 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9386 is so as a sanity check */
9387 if (state->setup_count != 1) {
9389 * Need to have rc=0 for ioctl to get job id for OS/2.
9390 * Network printing will fail if function is not successful.
9391 * Similar function in reply.c will be used if protocol
9392 * is LANMAN1.0 instead of LM1.2X002.
9393 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9394 * outbuf doesn't have to be set(only job id is used).
9396 if ( (state->setup_count == 4)
9397 && (tran_call == TRANSACT2_IOCTL)
9398 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9399 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9400 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9402 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9403 DEBUG(2,("Transaction is %d\n",tran_call));
9405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9406 END_PROFILE(SMBtrans2);
9411 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9414 if (state->total_data) {
9416 if (trans_oob(state->total_data, 0, dscnt)
9417 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9421 /* Can't use talloc here, the core routines do realloc on the
9422 * params and data. */
9423 state->data = (char *)SMB_MALLOC(state->total_data);
9424 if (state->data == NULL) {
9425 DEBUG(0,("reply_trans2: data malloc fail for %u "
9426 "bytes !\n", (unsigned int)state->total_data));
9428 reply_nterror(req, NT_STATUS_NO_MEMORY);
9429 END_PROFILE(SMBtrans2);
9433 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9436 if (state->total_param) {
9438 if (trans_oob(state->total_param, 0, pscnt)
9439 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9443 /* Can't use talloc here, the core routines do realloc on the
9444 * params and data. */
9445 state->param = (char *)SMB_MALLOC(state->total_param);
9446 if (state->param == NULL) {
9447 DEBUG(0,("reply_trans: param malloc fail for %u "
9448 "bytes !\n", (unsigned int)state->total_param));
9449 SAFE_FREE(state->data);
9451 reply_nterror(req, NT_STATUS_NO_MEMORY);
9452 END_PROFILE(SMBtrans2);
9456 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9459 state->received_data = dscnt;
9460 state->received_param = pscnt;
9462 if ((state->received_param == state->total_param) &&
9463 (state->received_data == state->total_data)) {
9465 handle_trans2(conn, req, state);
9467 SAFE_FREE(state->data);
9468 SAFE_FREE(state->param);
9470 END_PROFILE(SMBtrans2);
9474 DLIST_ADD(conn->pending_trans, state);
9476 /* We need to send an interim response then receive the rest
9477 of the parameter/data bytes */
9478 reply_outbuf(req, 0, 0);
9479 show_msg((char *)req->outbuf);
9480 END_PROFILE(SMBtrans2);
9485 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9486 SAFE_FREE(state->data);
9487 SAFE_FREE(state->param);
9489 END_PROFILE(SMBtrans2);
9490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9494 /****************************************************************************
9495 Reply to a SMBtranss2
9496 ****************************************************************************/
9498 void reply_transs2(struct smb_request *req)
9500 connection_struct *conn = req->conn;
9501 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9502 struct trans_state *state;
9504 START_PROFILE(SMBtranss2);
9506 show_msg((const char *)req->inbuf);
9508 /* Windows clients expect all replies to
9509 a transact secondary (SMBtranss2 0x33)
9510 to have a command code of transact
9511 (SMBtrans2 0x32). See bug #8989
9512 and also [MS-CIFS] section 2.2.4.47.2
9515 req->cmd = SMBtrans2;
9518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9519 END_PROFILE(SMBtranss2);
9523 for (state = conn->pending_trans; state != NULL;
9524 state = state->next) {
9525 if (state->mid == req->mid) {
9530 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9532 END_PROFILE(SMBtranss2);
9536 /* Revise state->total_param and state->total_data in case they have
9537 changed downwards */
9539 if (SVAL(req->vwv+0, 0) < state->total_param)
9540 state->total_param = SVAL(req->vwv+0, 0);
9541 if (SVAL(req->vwv+1, 0) < state->total_data)
9542 state->total_data = SVAL(req->vwv+1, 0);
9544 pcnt = SVAL(req->vwv+2, 0);
9545 poff = SVAL(req->vwv+3, 0);
9546 pdisp = SVAL(req->vwv+4, 0);
9548 dcnt = SVAL(req->vwv+5, 0);
9549 doff = SVAL(req->vwv+6, 0);
9550 ddisp = SVAL(req->vwv+7, 0);
9552 state->received_param += pcnt;
9553 state->received_data += dcnt;
9555 if ((state->received_data > state->total_data) ||
9556 (state->received_param > state->total_param))
9560 if (trans_oob(state->total_param, pdisp, pcnt)
9561 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9564 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9568 if (trans_oob(state->total_data, ddisp, dcnt)
9569 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9572 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9575 if ((state->received_param < state->total_param) ||
9576 (state->received_data < state->total_data)) {
9577 END_PROFILE(SMBtranss2);
9581 handle_trans2(conn, req, state);
9583 DLIST_REMOVE(conn->pending_trans, state);
9584 SAFE_FREE(state->data);
9585 SAFE_FREE(state->param);
9588 END_PROFILE(SMBtranss2);
9593 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9594 DLIST_REMOVE(conn->pending_trans, state);
9595 SAFE_FREE(state->data);
9596 SAFE_FREE(state->param);
9598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9599 END_PROFILE(SMBtranss2);