2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 NTSTATUS check_access_fsp(const struct files_struct *fsp,
60 if (!(fsp->access_mask & access_mask)) {
61 return NT_STATUS_ACCESS_DENIED;
66 /********************************************************************
67 The canonical "check access" based on object handle or path function.
68 ********************************************************************/
70 NTSTATUS check_access(connection_struct *conn,
72 const struct smb_filename *smb_fname,
78 status = check_access_fsp(fsp, access_mask);
80 status = smbd_check_access_rights(conn, smb_fname,
87 /********************************************************************
88 Roundup a value to the nearest allocation roundup size boundary.
89 Only do this for Windows clients.
90 ********************************************************************/
92 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
94 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
96 /* Only roundup for Windows clients. */
97 enum remote_arch_types ra_type = get_remote_arch();
98 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
99 val = SMB_ROUNDUP(val,rval);
104 /********************************************************************
105 Create a 64 bit FileIndex. If the file is on the same device as
106 the root of the share, just return the 64-bit inode. If it isn't,
107 mangle as we used to do.
108 ********************************************************************/
110 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
113 if (conn->base_share_dev == psbuf->st_ex_dev) {
114 return (uint64_t)psbuf->st_ex_ino;
116 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
117 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
121 /****************************************************************************
122 Utility functions for dealing with extended attributes.
123 ****************************************************************************/
125 /****************************************************************************
126 Refuse to allow clients to overwrite our private xattrs.
127 ****************************************************************************/
129 bool samba_private_attr_name(const char *unix_ea_name)
131 static const char * const prohibited_ea_names[] = {
132 SAMBA_POSIX_INHERITANCE_EA_NAME,
133 SAMBA_XATTR_DOS_ATTRIB,
141 for (i = 0; prohibited_ea_names[i]; i++) {
142 if (strequal( prohibited_ea_names[i], unix_ea_name))
145 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
146 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
152 /****************************************************************************
153 Get one EA value. Fill in a struct ea_struct.
154 ****************************************************************************/
156 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
157 files_struct *fsp, const char *fname,
158 const char *ea_name, struct ea_struct *pea)
160 /* Get the value of this xattr. Max size is 64k. */
161 size_t attr_size = 256;
167 val = talloc_realloc(mem_ctx, val, char, attr_size);
169 return NT_STATUS_NO_MEMORY;
172 if (fsp && fsp->fh->fd != -1) {
173 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
175 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
178 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
184 return map_nt_error_from_unix(errno);
187 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
188 dump_data(10, (uint8_t *)val, sizeret);
191 if (strnequal(ea_name, "user.", 5)) {
192 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
194 pea->name = talloc_strdup(mem_ctx, ea_name);
196 if (pea->name == NULL) {
198 return NT_STATUS_NO_MEMORY;
200 pea->value.data = (unsigned char *)val;
201 pea->value.length = (size_t)sizeret;
205 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
206 files_struct *fsp, const char *fname,
207 char ***pnames, size_t *pnum_names)
209 /* Get a list of all xattrs. Max namesize is 64k. */
210 size_t ea_namelist_size = 1024;
211 char *ea_namelist = NULL;
216 ssize_t sizeret = -1;
218 if (!lp_ea_support(SNUM(conn))) {
227 * TALLOC the result early to get the talloc hierarchy right.
230 names = talloc_array(mem_ctx, char *, 1);
232 DEBUG(0, ("talloc failed\n"));
233 return NT_STATUS_NO_MEMORY;
236 while (ea_namelist_size <= 65536) {
238 ea_namelist = talloc_realloc(
239 names, ea_namelist, char, ea_namelist_size);
240 if (ea_namelist == NULL) {
241 DEBUG(0, ("talloc failed\n"));
243 return NT_STATUS_NO_MEMORY;
246 if (fsp && fsp->fh->fd != -1) {
247 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
250 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
254 if ((sizeret == -1) && (errno == ERANGE)) {
255 ea_namelist_size *= 2;
264 return map_nt_error_from_unix(errno);
267 DEBUG(10, ("%s: ea_namelist size = %u\n",
268 __func__, (unsigned int)sizeret));
280 * Ensure the result is 0-terminated
283 if (ea_namelist[sizeret-1] != '\0') {
285 return NT_STATUS_INTERNAL_ERROR;
293 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
297 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
299 DEBUG(0, ("talloc failed\n"));
301 return NT_STATUS_NO_MEMORY;
307 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
308 names[num_names++] = p;
316 *pnum_names = num_names;
320 /****************************************************************************
321 Return a linked list of the total EA's. Plus the total size
322 ****************************************************************************/
324 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
325 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
327 /* Get a list of all xattrs. Max namesize is 64k. */
330 struct ea_list *ea_list_head = NULL;
336 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
339 if (!NT_STATUS_IS_OK(status)) {
343 if (num_names == 0) {
348 for (i=0; i<num_names; i++) {
349 struct ea_list *listp;
352 if (strnequal(names[i], "system.", 7)
353 || samba_private_attr_name(names[i]))
357 * Filter out any underlying POSIX EA names
358 * that a Windows client can't handle.
360 if (!lp_posix_pathnames() &&
361 is_invalid_windows_ea_name(names[i])) {
365 listp = talloc(mem_ctx, struct ea_list);
367 return NT_STATUS_NO_MEMORY;
370 status = get_ea_value(listp, conn, fsp,
374 if (!NT_STATUS_IS_OK(status)) {
379 if (listp->ea.value.length == 0) {
381 * We can never return a zero length EA.
382 * Windows reports the EA's as corrupted.
388 push_ascii_fstring(dos_ea_name, listp->ea.name);
391 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
393 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
394 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
395 (unsigned int)listp->ea.value.length));
397 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
401 /* Add on 4 for total length. */
402 if (*pea_total_len) {
406 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
407 (unsigned int)*pea_total_len));
409 *ea_list = ea_list_head;
413 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
414 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
419 if (!lp_ea_support(SNUM(conn))) {
423 if (is_ntfs_stream_smb_fname(smb_fname)) {
424 return NT_STATUS_INVALID_PARAMETER;
427 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
430 /****************************************************************************
431 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
433 ****************************************************************************/
435 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
436 connection_struct *conn, struct ea_list *ea_list)
438 unsigned int ret_data_size = 4;
441 SMB_ASSERT(total_data_size >= 4);
443 if (!lp_ea_support(SNUM(conn))) {
448 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
451 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
452 dos_namelen = strlen(dos_ea_name);
453 if (dos_namelen > 255 || dos_namelen == 0) {
456 if (ea_list->ea.value.length > 65535) {
459 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
463 /* We know we have room. */
464 SCVAL(p,0,ea_list->ea.flags);
465 SCVAL(p,1,dos_namelen);
466 SSVAL(p,2,ea_list->ea.value.length);
467 strlcpy(p+4, dos_ea_name, dos_namelen+1);
468 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
470 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
471 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
474 ret_data_size = PTR_DIFF(p, pdata);
475 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
476 SIVAL(pdata,0,ret_data_size);
477 return ret_data_size;
480 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
482 unsigned int total_data_size,
483 unsigned int *ret_data_size,
484 connection_struct *conn,
485 struct ea_list *ea_list)
487 uint8_t *p = (uint8_t *)pdata;
488 uint8_t *last_start = NULL;
489 bool do_store_data = (pdata != NULL);
493 if (!lp_ea_support(SNUM(conn))) {
494 return NT_STATUS_NO_EAS_ON_FILE;
497 for (; ea_list; ea_list = ea_list->next) {
503 if (last_start != NULL && do_store_data) {
504 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
508 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
509 dos_namelen = strlen(dos_ea_name);
510 if (dos_namelen > 255 || dos_namelen == 0) {
511 return NT_STATUS_INTERNAL_ERROR;
513 if (ea_list->ea.value.length > 65535) {
514 return NT_STATUS_INTERNAL_ERROR;
517 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
520 pad = (4 - (this_size % 4)) % 4;
525 if (this_size > total_data_size) {
526 return NT_STATUS_INFO_LENGTH_MISMATCH;
529 /* We know we have room. */
530 SIVAL(p, 0x00, 0); /* next offset */
531 SCVAL(p, 0x04, ea_list->ea.flags);
532 SCVAL(p, 0x05, dos_namelen);
533 SSVAL(p, 0x06, ea_list->ea.value.length);
534 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
535 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
537 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
541 total_data_size -= this_size;
547 *ret_data_size = PTR_DIFF(p, pdata);
548 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
552 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
554 size_t total_ea_len = 0;
556 struct ea_list *ea_list = NULL;
558 if (!lp_ea_support(SNUM(conn))) {
561 mem_ctx = talloc_stackframe();
563 /* If this is a stream fsp, then we need to instead find the
564 * estimated ea len from the main file, not the stream
565 * (streams cannot have EAs), but the estimate isn't just 0 in
567 if (is_ntfs_stream_smb_fname(smb_fname)) {
570 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
571 if(conn->sconn->using_smb2) {
573 unsigned int ret_data_size;
575 * We're going to be using fill_ea_chained_buffer() to
576 * marshall EA's - this size is significantly larger
577 * than the SMB1 buffer. Re-calculate the size without
580 status = fill_ea_chained_buffer(mem_ctx,
586 if (!NT_STATUS_IS_OK(status)) {
589 total_ea_len = ret_data_size;
591 TALLOC_FREE(mem_ctx);
595 /****************************************************************************
596 Ensure the EA name is case insensitive by matching any existing EA name.
597 ****************************************************************************/
599 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
602 TALLOC_CTX *mem_ctx = talloc_tos();
603 struct ea_list *ea_list;
604 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
605 if (!NT_STATUS_IS_OK(status)) {
609 for (; ea_list; ea_list = ea_list->next) {
610 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
611 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
612 &unix_ea_name[5], ea_list->ea.name));
613 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
619 /****************************************************************************
620 Set or delete an extended attribute.
621 ****************************************************************************/
623 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
624 const struct smb_filename *smb_fname, struct ea_list *ea_list)
629 if (!lp_ea_support(SNUM(conn))) {
630 return NT_STATUS_EAS_NOT_SUPPORTED;
633 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
634 if (!NT_STATUS_IS_OK(status)) {
638 /* Setting EAs on streams isn't supported. */
639 if (is_ntfs_stream_smb_fname(smb_fname)) {
640 return NT_STATUS_INVALID_PARAMETER;
644 * Filter out invalid Windows EA names - before
645 * we set *any* of them.
648 if (ea_list_has_invalid_name(ea_list)) {
649 return STATUS_INVALID_EA_NAME;
652 fname = smb_fname->base_name;
654 for (;ea_list; ea_list = ea_list->next) {
656 fstring unix_ea_name;
658 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
659 fstrcat(unix_ea_name, ea_list->ea.name);
661 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
663 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
665 if (samba_private_attr_name(unix_ea_name)) {
666 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
667 return NT_STATUS_ACCESS_DENIED;
670 if (ea_list->ea.value.length == 0) {
671 /* Remove the attribute. */
672 if (fsp && (fsp->fh->fd != -1)) {
673 DEBUG(10,("set_ea: deleting ea name %s on "
674 "file %s by file descriptor.\n",
675 unix_ea_name, fsp_str_dbg(fsp)));
676 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
678 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
679 unix_ea_name, fname));
680 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
683 /* Removing a non existent attribute always succeeds. */
684 if (ret == -1 && errno == ENOATTR) {
685 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
691 if (fsp && (fsp->fh->fd != -1)) {
692 DEBUG(10,("set_ea: setting ea name %s on file "
693 "%s by file descriptor.\n",
694 unix_ea_name, fsp_str_dbg(fsp)));
695 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
696 ea_list->ea.value.data, ea_list->ea.value.length, 0);
698 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
699 unix_ea_name, fname));
700 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
701 ea_list->ea.value.data, ea_list->ea.value.length, 0);
707 if (errno == ENOTSUP) {
708 return NT_STATUS_EAS_NOT_SUPPORTED;
711 return map_nt_error_from_unix(errno);
717 /****************************************************************************
718 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
719 ****************************************************************************/
721 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
723 struct ea_list *ea_list_head = NULL;
724 size_t converted_size, offset = 0;
726 while (offset + 2 < data_size) {
727 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
728 unsigned int namelen = CVAL(pdata,offset);
730 offset++; /* Go past the namelen byte. */
732 /* integer wrap paranioa. */
733 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
734 (offset > data_size) || (namelen > data_size) ||
735 (offset + namelen >= data_size)) {
738 /* Ensure the name is null terminated. */
739 if (pdata[offset + namelen] != '\0') {
742 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
744 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
745 "failed: %s", strerror(errno)));
751 offset += (namelen + 1); /* Go past the name + terminating zero. */
752 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
753 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
759 /****************************************************************************
760 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
761 ****************************************************************************/
763 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
765 struct ea_list *ea_list_head = NULL;
767 size_t bytes_used = 0;
769 while (offset < data_size) {
770 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
776 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
777 offset += bytes_used;
783 /****************************************************************************
784 Count the total EA size needed.
785 ****************************************************************************/
787 static size_t ea_list_size(struct ea_list *ealist)
790 struct ea_list *listp;
793 for (listp = ealist; listp; listp = listp->next) {
794 push_ascii_fstring(dos_ea_name, listp->ea.name);
795 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
797 /* Add on 4 for total length. */
805 /****************************************************************************
806 Return a union of EA's from a file list and a list of names.
807 The TALLOC context for the two lists *MUST* be identical as we steal
808 memory from one list to add to another. JRA.
809 ****************************************************************************/
811 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
813 struct ea_list *nlistp, *flistp;
815 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
816 for (flistp = file_list; flistp; flistp = flistp->next) {
817 if (strequal(nlistp->ea.name, flistp->ea.name)) {
823 /* Copy the data from this entry. */
824 nlistp->ea.flags = flistp->ea.flags;
825 nlistp->ea.value = flistp->ea.value;
828 nlistp->ea.flags = 0;
829 ZERO_STRUCT(nlistp->ea.value);
833 *total_ea_len = ea_list_size(name_list);
837 /****************************************************************************
838 Send the required number of replies back.
839 We assume all fields other than the data fields are
840 set correctly for the type of call.
841 HACK ! Always assumes smb_setup field is zero.
842 ****************************************************************************/
844 void send_trans2_replies(connection_struct *conn,
845 struct smb_request *req,
853 /* As we are using a protocol > LANMAN1 then the max_send
854 variable must have been set in the sessetupX call.
855 This takes precedence over the max_xmit field in the
856 global struct. These different max_xmit variables should
857 be merged as this is now too confusing */
859 int data_to_send = datasize;
860 int params_to_send = paramsize;
862 const char *pp = params;
863 const char *pd = pdata;
864 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
865 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
866 int data_alignment_offset = 0;
867 bool overflow = False;
868 struct smbXsrv_connection *xconn = req->xconn;
869 int max_send = xconn->smb1.sessions.max_send;
871 /* Modify the data_to_send and datasize and set the error if
872 we're trying to send more than max_data_bytes. We still send
873 the part of the packet(s) that fit. Strange, but needed
876 if (max_data_bytes > 0 && datasize > max_data_bytes) {
877 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
878 max_data_bytes, datasize ));
879 datasize = data_to_send = max_data_bytes;
883 /* If there genuinely are no parameters or data to send just send the empty packet */
885 if(params_to_send == 0 && data_to_send == 0) {
886 reply_outbuf(req, 10, 0);
887 if (NT_STATUS_V(status)) {
890 ntstatus_to_dos(status, &eclass, &ecode);
891 error_packet_set((char *)req->outbuf,
892 eclass, ecode, status,
895 show_msg((char *)req->outbuf);
896 if (!srv_send_smb(xconn,
899 IS_CONN_ENCRYPTED(conn),
901 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
903 TALLOC_FREE(req->outbuf);
907 /* When sending params and data ensure that both are nicely aligned */
908 /* Only do this alignment when there is also data to send - else
909 can cause NT redirector problems. */
911 if (((params_to_send % 4) != 0) && (data_to_send != 0))
912 data_alignment_offset = 4 - (params_to_send % 4);
914 /* Space is bufsize minus Netbios over TCP header minus SMB header */
915 /* The alignment_offset is to align the param bytes on an even byte
916 boundary. NT 4.0 Beta needs this to work correctly. */
918 useable_space = max_send - (smb_size
921 + data_alignment_offset);
923 if (useable_space < 0) {
924 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
925 "= %d!!!", useable_space));
926 exit_server_cleanly("send_trans2_replies: Not enough space");
929 while (params_to_send || data_to_send) {
930 /* Calculate whether we will totally or partially fill this packet */
932 total_sent_thistime = params_to_send + data_to_send;
934 /* We can never send more than useable_space */
936 * Note that 'useable_space' does not include the alignment offsets,
937 * but we must include the alignment offsets in the calculation of
938 * the length of the data we send over the wire, as the alignment offsets
939 * are sent here. Fix from Marc_Jacobsen@hp.com.
942 total_sent_thistime = MIN(total_sent_thistime, useable_space);
944 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
945 + data_alignment_offset);
947 /* Set total params and data to be sent */
948 SSVAL(req->outbuf,smb_tprcnt,paramsize);
949 SSVAL(req->outbuf,smb_tdrcnt,datasize);
951 /* Calculate how many parameters and data we can fit into
952 * this packet. Parameters get precedence
955 params_sent_thistime = MIN(params_to_send,useable_space);
956 data_sent_thistime = useable_space - params_sent_thistime;
957 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
959 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
961 /* smb_proff is the offset from the start of the SMB header to the
962 parameter bytes, however the first 4 bytes of outbuf are
963 the Netbios over TCP header. Thus use smb_base() to subtract
964 them from the calculation */
966 SSVAL(req->outbuf,smb_proff,
967 ((smb_buf(req->outbuf)+alignment_offset)
968 - smb_base(req->outbuf)));
970 if(params_sent_thistime == 0)
971 SSVAL(req->outbuf,smb_prdisp,0);
973 /* Absolute displacement of param bytes sent in this packet */
974 SSVAL(req->outbuf,smb_prdisp,pp - params);
976 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
977 if(data_sent_thistime == 0) {
978 SSVAL(req->outbuf,smb_droff,0);
979 SSVAL(req->outbuf,smb_drdisp, 0);
981 /* The offset of the data bytes is the offset of the
982 parameter bytes plus the number of parameters being sent this time */
983 SSVAL(req->outbuf, smb_droff,
984 ((smb_buf(req->outbuf)+alignment_offset)
985 - smb_base(req->outbuf))
986 + params_sent_thistime + data_alignment_offset);
987 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
990 /* Initialize the padding for alignment */
992 if (alignment_offset != 0) {
993 memset(smb_buf(req->outbuf), 0, alignment_offset);
996 /* Copy the param bytes into the packet */
998 if(params_sent_thistime) {
999 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1000 params_sent_thistime);
1003 /* Copy in the data bytes */
1004 if(data_sent_thistime) {
1005 if (data_alignment_offset != 0) {
1006 memset((smb_buf(req->outbuf)+alignment_offset+
1007 params_sent_thistime), 0,
1008 data_alignment_offset);
1010 memcpy(smb_buf(req->outbuf)+alignment_offset
1011 +params_sent_thistime+data_alignment_offset,
1012 pd,data_sent_thistime);
1015 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1016 params_sent_thistime, data_sent_thistime, useable_space));
1017 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1018 params_to_send, data_to_send, paramsize, datasize));
1021 error_packet_set((char *)req->outbuf,
1022 ERRDOS,ERRbufferoverflow,
1023 STATUS_BUFFER_OVERFLOW,
1025 } else if (NT_STATUS_V(status)) {
1028 ntstatus_to_dos(status, &eclass, &ecode);
1029 error_packet_set((char *)req->outbuf,
1030 eclass, ecode, status,
1034 /* Send the packet */
1035 show_msg((char *)req->outbuf);
1036 if (!srv_send_smb(xconn,
1037 (char *)req->outbuf,
1038 true, req->seqnum+1,
1039 IS_CONN_ENCRYPTED(conn),
1041 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1043 TALLOC_FREE(req->outbuf);
1045 pp += params_sent_thistime;
1046 pd += data_sent_thistime;
1048 params_to_send -= params_sent_thistime;
1049 data_to_send -= data_sent_thistime;
1052 if(params_to_send < 0 || data_to_send < 0) {
1053 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1054 params_to_send, data_to_send));
1062 /****************************************************************************
1063 Reply to a TRANSACT2_OPEN.
1064 ****************************************************************************/
1066 static void call_trans2open(connection_struct *conn,
1067 struct smb_request *req,
1068 char **pparams, int total_params,
1069 char **ppdata, int total_data,
1070 unsigned int max_data_bytes)
1072 struct smb_filename *smb_fname = NULL;
1073 char *params = *pparams;
1074 char *pdata = *ppdata;
1077 bool oplock_request;
1079 bool return_additional_info;
1088 int fattr=0,mtime=0;
1089 SMB_INO_T inode = 0;
1092 struct ea_list *ea_list = NULL;
1095 uint32_t access_mask;
1096 uint32_t share_mode;
1097 uint32_t create_disposition;
1098 uint32_t create_options = 0;
1099 uint32_t private_flags = 0;
1100 uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
1101 TALLOC_CTX *ctx = talloc_tos();
1104 * Ensure we have enough parameters to perform the operation.
1107 if (total_params < 29) {
1108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1112 flags = SVAL(params, 0);
1113 deny_mode = SVAL(params, 2);
1114 open_attr = SVAL(params,6);
1115 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1116 if (oplock_request) {
1117 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1121 return_additional_info = BITSETW(params,0);
1122 open_sattr = SVAL(params, 4);
1123 open_time = make_unix_date3(params+8);
1125 open_ofun = SVAL(params,12);
1126 open_size = IVAL(params,14);
1127 pname = ¶ms[28];
1130 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1134 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1135 total_params - 28, STR_TERMINATE,
1137 if (!NT_STATUS_IS_OK(status)) {
1138 reply_nterror(req, status);
1142 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1143 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1144 (unsigned int)open_ofun, open_size));
1146 status = filename_convert(ctx,
1148 req->flags2 & FLAGS2_DFS_PATHNAMES,
1153 if (!NT_STATUS_IS_OK(status)) {
1154 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1155 reply_botherror(req,
1156 NT_STATUS_PATH_NOT_COVERED,
1157 ERRSRV, ERRbadpath);
1160 reply_nterror(req, status);
1164 if (open_ofun == 0) {
1165 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1169 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1171 &access_mask, &share_mode,
1172 &create_disposition,
1175 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1179 /* Any data in this call is an EA list. */
1180 if (total_data && (total_data != 4)) {
1181 if (total_data < 10) {
1182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1186 if (IVAL(pdata,0) > total_data) {
1187 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1188 IVAL(pdata,0), (unsigned int)total_data));
1189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1193 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1200 if (!lp_ea_support(SNUM(conn))) {
1201 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1205 if (ea_list_has_invalid_name(ea_list)) {
1207 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1208 if(*pparams == NULL ) {
1209 reply_nterror(req, NT_STATUS_NO_MEMORY);
1213 memset(params, '\0', param_len);
1214 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1215 params, param_len, NULL, 0, max_data_bytes);
1220 status = SMB_VFS_CREATE_FILE(
1223 0, /* root_dir_fid */
1224 smb_fname, /* fname */
1225 access_mask, /* access_mask */
1226 share_mode, /* share_access */
1227 create_disposition, /* create_disposition*/
1228 create_options, /* create_options */
1229 open_attr, /* file_attributes */
1230 oplock_request, /* oplock_request */
1232 open_size, /* allocation_size */
1235 ea_list, /* ea_list */
1237 &smb_action, /* psbuf */
1238 NULL, NULL); /* create context */
1240 if (!NT_STATUS_IS_OK(status)) {
1241 if (open_was_deferred(req->xconn, req->mid)) {
1242 /* We have re-scheduled this call. */
1245 reply_openerror(req, status);
1249 size = get_file_size_stat(&smb_fname->st);
1250 fattr = dos_mode(conn, smb_fname);
1251 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1252 inode = smb_fname->st.st_ex_ino;
1253 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1254 close_file(req, fsp, ERROR_CLOSE);
1255 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1259 /* Realloc the size of parameters and data we will return */
1260 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1261 if(*pparams == NULL ) {
1262 reply_nterror(req, NT_STATUS_NO_MEMORY);
1267 SSVAL(params,0,fsp->fnum);
1268 SSVAL(params,2,fattr);
1269 srv_put_dos_date2(params,4, mtime);
1270 SIVAL(params,8, (uint32_t)size);
1271 SSVAL(params,12,deny_mode);
1272 SSVAL(params,14,0); /* open_type - file or directory. */
1273 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1275 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1276 smb_action |= EXTENDED_OPLOCK_GRANTED;
1279 SSVAL(params,18,smb_action);
1282 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1284 SIVAL(params,20,inode);
1285 SSVAL(params,24,0); /* Padding. */
1287 uint32_t ea_size = estimate_ea_size(conn, fsp,
1289 SIVAL(params, 26, ea_size);
1291 SIVAL(params, 26, 0);
1294 /* Send the required number of replies */
1295 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1297 TALLOC_FREE(smb_fname);
1300 /*********************************************************
1301 Routine to check if a given string matches exactly.
1302 as a special case a mask of "." does NOT match. That
1303 is required for correct wildcard semantics
1304 Case can be significant or not.
1305 **********************************************************/
1307 static bool exact_match(bool has_wild,
1308 bool case_sensitive,
1312 if (mask[0] == '.' && mask[1] == 0) {
1320 if (case_sensitive) {
1321 return strcmp(str,mask)==0;
1323 return strcasecmp_m(str,mask) == 0;
1327 /****************************************************************************
1328 Return the filetype for UNIX extensions.
1329 ****************************************************************************/
1331 static uint32_t unix_filetype(mode_t mode)
1334 return UNIX_TYPE_FILE;
1335 else if(S_ISDIR(mode))
1336 return UNIX_TYPE_DIR;
1338 else if(S_ISLNK(mode))
1339 return UNIX_TYPE_SYMLINK;
1342 else if(S_ISCHR(mode))
1343 return UNIX_TYPE_CHARDEV;
1346 else if(S_ISBLK(mode))
1347 return UNIX_TYPE_BLKDEV;
1350 else if(S_ISFIFO(mode))
1351 return UNIX_TYPE_FIFO;
1354 else if(S_ISSOCK(mode))
1355 return UNIX_TYPE_SOCKET;
1358 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1359 return UNIX_TYPE_UNKNOWN;
1362 /****************************************************************************
1363 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1364 ****************************************************************************/
1366 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1368 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1369 const SMB_STRUCT_STAT *psbuf,
1371 enum perm_type ptype,
1376 if (perms == SMB_MODE_NO_CHANGE) {
1377 if (!VALID_STAT(*psbuf)) {
1378 return NT_STATUS_INVALID_PARAMETER;
1380 *ret_perms = psbuf->st_ex_mode;
1381 return NT_STATUS_OK;
1385 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1386 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1387 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1388 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1389 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1390 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1391 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1392 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1393 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1395 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1398 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1401 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1404 if (ptype == PERM_NEW_FILE) {
1406 * "create mask"/"force create mode" are
1407 * only applied to new files, not existing ones.
1409 ret &= lp_create_mask(SNUM(conn));
1410 /* Add in force bits */
1411 ret |= lp_force_create_mode(SNUM(conn));
1412 } else if (ptype == PERM_NEW_DIR) {
1414 * "directory mask"/"force directory mode" are
1415 * only applied to new directories, not existing ones.
1417 ret &= lp_directory_mask(SNUM(conn));
1418 /* Add in force bits */
1419 ret |= lp_force_directory_mode(SNUM(conn));
1423 return NT_STATUS_OK;
1426 /****************************************************************************
1427 Needed to show the msdfs symlinks as directories. Modifies psbuf
1428 to be a directory if it's a msdfs link.
1429 ****************************************************************************/
1431 static bool check_msdfs_link(connection_struct *conn,
1432 const char *pathname,
1433 SMB_STRUCT_STAT *psbuf)
1435 int saved_errno = errno;
1436 if(lp_host_msdfs() &&
1437 lp_msdfs_root(SNUM(conn)) &&
1438 is_msdfs_link(conn, pathname, psbuf)) {
1440 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1443 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1444 errno = saved_errno;
1447 errno = saved_errno;
1452 /****************************************************************************
1453 Get a level dependent lanman2 dir entry.
1454 ****************************************************************************/
1456 struct smbd_dirptr_lanman2_state {
1457 connection_struct *conn;
1458 uint32_t info_level;
1459 bool check_mangled_names;
1461 bool got_exact_match;
1464 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1470 struct smbd_dirptr_lanman2_state *state =
1471 (struct smbd_dirptr_lanman2_state *)private_data;
1473 char mangled_name[13]; /* mangled 8.3 name. */
1477 /* Mangle fname if it's an illegal name. */
1478 if (mangle_must_mangle(dname, state->conn->params)) {
1480 * Slow path - ensure we can push the original name as UCS2. If
1481 * not, then just don't return this name.
1485 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1486 uint8_t *tmp = talloc_array(talloc_tos(),
1490 status = srvstr_push(NULL,
1491 FLAGS2_UNICODE_STRINGS,
1500 if (!NT_STATUS_IS_OK(status)) {
1504 ok = name_to_8_3(dname, mangled_name,
1505 true, state->conn->params);
1509 fname = mangled_name;
1514 got_match = exact_match(state->has_wild,
1515 state->conn->case_sensitive,
1517 state->got_exact_match = got_match;
1519 got_match = mask_match(fname, mask,
1520 state->conn->case_sensitive);
1523 if(!got_match && state->check_mangled_names &&
1524 !mangle_is_8_3(fname, false, state->conn->params)) {
1526 * It turns out that NT matches wildcards against
1527 * both long *and* short names. This may explain some
1528 * of the wildcard wierdness from old DOS clients
1529 * that some people have been seeing.... JRA.
1531 /* Force the mangling into 8.3. */
1532 ok = name_to_8_3(fname, mangled_name,
1533 false, state->conn->params);
1538 got_match = exact_match(state->has_wild,
1539 state->conn->case_sensitive,
1540 mangled_name, mask);
1541 state->got_exact_match = got_match;
1543 got_match = mask_match(mangled_name, mask,
1544 state->conn->case_sensitive);
1552 *_fname = talloc_strdup(ctx, fname);
1553 if (*_fname == NULL) {
1560 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1562 struct smb_filename *smb_fname,
1565 struct smbd_dirptr_lanman2_state *state =
1566 (struct smbd_dirptr_lanman2_state *)private_data;
1567 bool ms_dfs_link = false;
1570 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1571 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1572 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1573 "Couldn't lstat [%s] (%s)\n",
1574 smb_fname_str_dbg(smb_fname),
1578 } else if (!VALID_STAT(smb_fname->st) &&
1579 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1580 /* Needed to show the msdfs symlinks as
1583 ms_dfs_link = check_msdfs_link(state->conn,
1584 smb_fname->base_name,
1587 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1588 "Couldn't stat [%s] (%s)\n",
1589 smb_fname_str_dbg(smb_fname),
1596 mode = dos_mode_msdfs(state->conn, smb_fname);
1598 mode = dos_mode(state->conn, smb_fname);
1605 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1606 connection_struct *conn,
1608 uint32_t info_level,
1609 struct ea_list *name_list,
1610 bool check_mangled_names,
1611 bool requires_resume_key,
1614 const struct smb_filename *smb_fname,
1615 int space_remaining,
1621 uint64_t *last_entry_off)
1623 char *p, *q, *pdata = *ppdata;
1625 uint64_t file_size = 0;
1626 uint64_t allocation_size = 0;
1627 uint64_t file_index = 0;
1629 struct timespec mdate_ts = {0};
1630 struct timespec adate_ts = {0};
1631 struct timespec cdate_ts = {0};
1632 struct timespec create_date_ts = {0};
1633 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1635 char *last_entry_ptr;
1640 struct readdir_attr_data *readdir_attr_data = NULL;
1642 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1643 file_size = get_file_size_stat(&smb_fname->st);
1645 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1647 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1648 if (!NT_STATUS_IS_OK(status)) {
1649 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1654 file_index = get_FileIndex(conn, &smb_fname->st);
1656 mdate_ts = smb_fname->st.st_ex_mtime;
1657 adate_ts = smb_fname->st.st_ex_atime;
1658 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1659 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1661 if (lp_dos_filetime_resolution(SNUM(conn))) {
1662 dos_filetime_timespec(&create_date_ts);
1663 dos_filetime_timespec(&mdate_ts);
1664 dos_filetime_timespec(&adate_ts);
1665 dos_filetime_timespec(&cdate_ts);
1668 create_date = convert_timespec_to_time_t(create_date_ts);
1669 mdate = convert_timespec_to_time_t(mdate_ts);
1670 adate = convert_timespec_to_time_t(adate_ts);
1672 /* align the record */
1673 SMB_ASSERT(align >= 1);
1675 off = (int)PTR_DIFF(pdata, base_data);
1676 pad = (off + (align-1)) & ~(align-1);
1679 if (pad && pad > space_remaining) {
1680 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1681 "for padding (wanted %u, had %d)\n",
1684 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1688 /* initialize padding to 0 */
1690 memset(pdata, 0, pad);
1692 space_remaining -= pad;
1694 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1704 switch (info_level) {
1705 case SMB_FIND_INFO_STANDARD:
1706 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1707 if(requires_resume_key) {
1711 srv_put_dos_date2(p,0,create_date);
1712 srv_put_dos_date2(p,4,adate);
1713 srv_put_dos_date2(p,8,mdate);
1714 SIVAL(p,12,(uint32_t)file_size);
1715 SIVAL(p,16,(uint32_t)allocation_size);
1719 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1720 p += ucs2_align(base_data, p, 0);
1722 status = srvstr_push(base_data, flags2, p,
1723 fname, PTR_DIFF(end_data, p),
1724 STR_TERMINATE, &len);
1725 if (!NT_STATUS_IS_OK(status)) {
1728 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1730 SCVAL(nameptr, -1, len - 2);
1732 SCVAL(nameptr, -1, 0);
1736 SCVAL(nameptr, -1, len - 1);
1738 SCVAL(nameptr, -1, 0);
1744 case SMB_FIND_EA_SIZE:
1745 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1746 if (requires_resume_key) {
1750 srv_put_dos_date2(p,0,create_date);
1751 srv_put_dos_date2(p,4,adate);
1752 srv_put_dos_date2(p,8,mdate);
1753 SIVAL(p,12,(uint32_t)file_size);
1754 SIVAL(p,16,(uint32_t)allocation_size);
1757 unsigned int ea_size = estimate_ea_size(conn, NULL,
1759 SIVAL(p,22,ea_size); /* Extended attributes */
1763 status = srvstr_push(base_data, flags2,
1764 p, fname, PTR_DIFF(end_data, p),
1765 STR_TERMINATE | STR_NOALIGN, &len);
1766 if (!NT_STATUS_IS_OK(status)) {
1769 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1782 SCVAL(nameptr,0,len);
1784 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1787 case SMB_FIND_EA_LIST:
1789 struct ea_list *file_list = NULL;
1792 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1794 return NT_STATUS_INVALID_PARAMETER;
1796 if (requires_resume_key) {
1800 srv_put_dos_date2(p,0,create_date);
1801 srv_put_dos_date2(p,4,adate);
1802 srv_put_dos_date2(p,8,mdate);
1803 SIVAL(p,12,(uint32_t)file_size);
1804 SIVAL(p,16,(uint32_t)allocation_size);
1806 p += 22; /* p now points to the EA area. */
1808 status = get_ea_list_from_file(ctx, conn, NULL,
1810 &ea_len, &file_list);
1811 if (!NT_STATUS_IS_OK(status)) {
1814 name_list = ea_list_union(name_list, file_list, &ea_len);
1816 /* We need to determine if this entry will fit in the space available. */
1817 /* Max string size is 255 bytes. */
1818 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1819 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1820 "(wanted %u, had %d)\n",
1821 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1823 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1826 /* Push the ea_data followed by the name. */
1827 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1829 status = srvstr_push(base_data, flags2,
1830 p + 1, fname, PTR_DIFF(end_data, p+1),
1831 STR_TERMINATE | STR_NOALIGN, &len);
1832 if (!NT_STATUS_IS_OK(status)) {
1835 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1848 SCVAL(nameptr,0,len);
1850 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1854 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1855 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1856 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1858 SIVAL(p,0,reskey); p += 4;
1859 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1862 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1863 SOFF_T(p,0,file_size); p += 8;
1864 SOFF_T(p,0,allocation_size); p += 8;
1865 SIVAL(p,0,mode); p += 4;
1866 q = p; p += 4; /* q is placeholder for name length. */
1867 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1868 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1870 unsigned int ea_size = estimate_ea_size(conn, NULL,
1872 SIVAL(p,0,ea_size); /* Extended attributes */
1875 /* Clear the short name buffer. This is
1876 * IMPORTANT as not doing so will trigger
1877 * a Win2k client bug. JRA.
1879 if (!was_8_3 && check_mangled_names) {
1880 char mangled_name[13]; /* mangled 8.3 name. */
1881 if (!name_to_8_3(fname,mangled_name,True,
1883 /* Error - mangle failed ! */
1884 memset(mangled_name,'\0',12);
1886 mangled_name[12] = 0;
1887 status = srvstr_push(base_data, flags2,
1888 p+2, mangled_name, 24,
1889 STR_UPPER|STR_UNICODE, &len);
1890 if (!NT_STATUS_IS_OK(status)) {
1894 memset(p + 2 + len,'\0',24 - len);
1901 status = srvstr_push(base_data, flags2, p,
1902 fname, PTR_DIFF(end_data, p),
1903 STR_TERMINATE_ASCII, &len);
1904 if (!NT_STATUS_IS_OK(status)) {
1910 len = PTR_DIFF(p, pdata);
1911 pad = (len + (align-1)) & ~(align-1);
1913 * offset to the next entry, the caller
1914 * will overwrite it for the last entry
1915 * that's why we always include the padding
1919 * set padding to zero
1922 memset(p, 0, pad - len);
1929 case SMB_FIND_FILE_DIRECTORY_INFO:
1930 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1932 SIVAL(p,0,reskey); p += 4;
1933 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1934 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1936 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1937 SOFF_T(p,0,file_size); p += 8;
1938 SOFF_T(p,0,allocation_size); p += 8;
1939 SIVAL(p,0,mode); p += 4;
1940 status = srvstr_push(base_data, flags2,
1941 p + 4, fname, PTR_DIFF(end_data, p+4),
1942 STR_TERMINATE_ASCII, &len);
1943 if (!NT_STATUS_IS_OK(status)) {
1949 len = PTR_DIFF(p, pdata);
1950 pad = (len + (align-1)) & ~(align-1);
1952 * offset to the next entry, the caller
1953 * will overwrite it for the last entry
1954 * that's why we always include the padding
1958 * set padding to zero
1961 memset(p, 0, pad - len);
1968 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1969 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1971 SIVAL(p,0,reskey); p += 4;
1972 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1973 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1974 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1975 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1976 SOFF_T(p,0,file_size); p += 8;
1977 SOFF_T(p,0,allocation_size); p += 8;
1978 SIVAL(p,0,mode); p += 4;
1979 q = p; p += 4; /* q is placeholder for name length. */
1981 unsigned int ea_size = estimate_ea_size(conn, NULL,
1983 SIVAL(p,0,ea_size); /* Extended attributes */
1986 status = srvstr_push(base_data, flags2, p,
1987 fname, PTR_DIFF(end_data, p),
1988 STR_TERMINATE_ASCII, &len);
1989 if (!NT_STATUS_IS_OK(status)) {
1995 len = PTR_DIFF(p, pdata);
1996 pad = (len + (align-1)) & ~(align-1);
1998 * offset to the next entry, the caller
1999 * will overwrite it for the last entry
2000 * that's why we always include the padding
2004 * set padding to zero
2007 memset(p, 0, pad - len);
2014 case SMB_FIND_FILE_NAMES_INFO:
2015 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2017 SIVAL(p,0,reskey); p += 4;
2019 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2020 acl on a dir (tridge) */
2021 status = srvstr_push(base_data, flags2, p,
2022 fname, PTR_DIFF(end_data, p),
2023 STR_TERMINATE_ASCII, &len);
2024 if (!NT_STATUS_IS_OK(status)) {
2030 len = PTR_DIFF(p, pdata);
2031 pad = (len + (align-1)) & ~(align-1);
2033 * offset to the next entry, the caller
2034 * will overwrite it for the last entry
2035 * that's why we always include the padding
2039 * set padding to zero
2042 memset(p, 0, pad - len);
2049 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2050 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2052 SIVAL(p,0,reskey); p += 4;
2053 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2054 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2055 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2056 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2057 SOFF_T(p,0,file_size); p += 8;
2058 SOFF_T(p,0,allocation_size); p += 8;
2059 SIVAL(p,0,mode); p += 4;
2060 q = p; p += 4; /* q is placeholder for name length. */
2061 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2062 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2064 unsigned int ea_size = estimate_ea_size(conn, NULL,
2066 SIVAL(p,0,ea_size); /* Extended attributes */
2069 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2070 SBVAL(p,0,file_index); p += 8;
2071 status = srvstr_push(base_data, flags2, p,
2072 fname, PTR_DIFF(end_data, p),
2073 STR_TERMINATE_ASCII, &len);
2074 if (!NT_STATUS_IS_OK(status)) {
2080 len = PTR_DIFF(p, pdata);
2081 pad = (len + (align-1)) & ~(align-1);
2083 * offset to the next entry, the caller
2084 * will overwrite it for the last entry
2085 * that's why we always include the padding
2089 * set padding to zero
2092 memset(p, 0, pad - len);
2099 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2100 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2101 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2103 SIVAL(p,0,reskey); p += 4;
2104 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2105 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2106 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2107 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2108 SOFF_T(p,0,file_size); p += 8;
2109 SOFF_T(p,0,allocation_size); p += 8;
2110 SIVAL(p,0,mode); p += 4;
2111 q = p; p += 4; /* q is placeholder for name length */
2112 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2113 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2114 } else if (readdir_attr_data &&
2115 readdir_attr_data->type == RDATTR_AAPL) {
2117 * OS X specific SMB2 extension negotiated via
2118 * AAPL create context: return max_access in
2121 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2123 unsigned int ea_size = estimate_ea_size(conn, NULL,
2125 SIVAL(p,0,ea_size); /* Extended attributes */
2129 if (readdir_attr_data &&
2130 readdir_attr_data->type == RDATTR_AAPL) {
2132 * OS X specific SMB2 extension negotiated via
2133 * AAPL create context: return resource fork
2134 * length and compressed FinderInfo in
2137 * According to documentation short_name_len
2138 * should be 0, but on the wire behaviour
2139 * shows its set to 24 by clients.
2143 /* Resourefork length */
2144 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2146 /* Compressed FinderInfo */
2147 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2148 } else if (!was_8_3 && check_mangled_names) {
2149 char mangled_name[13]; /* mangled 8.3 name. */
2150 if (!name_to_8_3(fname,mangled_name,True,
2152 /* Error - mangle failed ! */
2153 memset(mangled_name,'\0',12);
2155 mangled_name[12] = 0;
2156 status = srvstr_push(base_data, flags2,
2157 p+2, mangled_name, 24,
2158 STR_UPPER|STR_UNICODE, &len);
2159 if (!NT_STATUS_IS_OK(status)) {
2164 memset(p + 2 + len,'\0',24 - len);
2168 /* Clear the short name buffer. This is
2169 * IMPORTANT as not doing so will trigger
2170 * a Win2k client bug. JRA.
2177 if (readdir_attr_data &&
2178 readdir_attr_data->type == RDATTR_AAPL) {
2180 * OS X specific SMB2 extension negotiated via
2181 * AAPL create context: return UNIX mode in
2184 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2185 SSVAL(p, 0, aapl_mode);
2191 SBVAL(p,0,file_index); p += 8;
2192 status = srvstr_push(base_data, flags2, p,
2193 fname, PTR_DIFF(end_data, p),
2194 STR_TERMINATE_ASCII, &len);
2195 if (!NT_STATUS_IS_OK(status)) {
2201 len = PTR_DIFF(p, pdata);
2202 pad = (len + (align-1)) & ~(align-1);
2204 * offset to the next entry, the caller
2205 * will overwrite it for the last entry
2206 * that's why we always include the padding
2210 * set padding to zero
2213 memset(p, 0, pad - len);
2220 /* CIFS UNIX Extension. */
2222 case SMB_FIND_FILE_UNIX:
2223 case SMB_FIND_FILE_UNIX_INFO2:
2225 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2227 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2229 if (info_level == SMB_FIND_FILE_UNIX) {
2230 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2231 p = store_file_unix_basic(conn, p,
2232 NULL, &smb_fname->st);
2233 status = srvstr_push(base_data, flags2, p,
2234 fname, PTR_DIFF(end_data, p),
2235 STR_TERMINATE, &len);
2236 if (!NT_STATUS_IS_OK(status)) {
2240 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2241 p = store_file_unix_basic_info2(conn, p,
2242 NULL, &smb_fname->st);
2245 status = srvstr_push(base_data, flags2, p, fname,
2246 PTR_DIFF(end_data, p), 0, &len);
2247 if (!NT_STATUS_IS_OK(status)) {
2250 SIVAL(nameptr, 0, len);
2255 len = PTR_DIFF(p, pdata);
2256 pad = (len + (align-1)) & ~(align-1);
2258 * offset to the next entry, the caller
2259 * will overwrite it for the last entry
2260 * that's why we always include the padding
2264 * set padding to zero
2267 memset(p, 0, pad - len);
2272 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2277 return NT_STATUS_INVALID_LEVEL;
2280 if (PTR_DIFF(p,pdata) > space_remaining) {
2281 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2282 "(wanted %u, had %d)\n",
2283 (unsigned int)PTR_DIFF(p,pdata),
2285 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2288 /* Setup the last entry pointer, as an offset from base_data */
2289 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2290 /* Advance the data pointer to the next slot */
2293 return NT_STATUS_OK;
2296 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2297 connection_struct *conn,
2298 struct dptr_struct *dirptr,
2300 const char *path_mask,
2303 int requires_resume_key,
2311 int space_remaining,
2312 bool *got_exact_match,
2313 int *_last_entry_off,
2314 struct ea_list *name_list)
2317 const char *mask = NULL;
2318 long prev_dirpos = 0;
2321 struct smb_filename *smb_fname = NULL;
2322 struct smbd_dirptr_lanman2_state state;
2324 uint64_t last_entry_off = 0;
2329 state.info_level = info_level;
2330 state.check_mangled_names = lp_mangled_names(conn->params);
2331 state.has_wild = dptr_has_wild(dirptr);
2332 state.got_exact_match = false;
2334 *got_exact_match = false;
2336 p = strrchr_m(path_mask,'/');
2347 ok = smbd_dirptr_get_entry(ctx,
2353 smbd_dirptr_lanman2_match_fn,
2354 smbd_dirptr_lanman2_mode_fn,
2361 return NT_STATUS_END_OF_FILE;
2364 *got_exact_match = state.got_exact_match;
2366 status = smbd_marshall_dir_entry(ctx,
2371 state.check_mangled_names,
2372 requires_resume_key,
2383 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2384 DEBUG(1,("Conversion error: illegal character: %s\n",
2385 smb_fname_str_dbg(smb_fname)));
2388 TALLOC_FREE(smb_fname);
2389 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2390 dptr_SeekDir(dirptr, prev_dirpos);
2393 if (!NT_STATUS_IS_OK(status)) {
2397 *_last_entry_off = last_entry_off;
2398 return NT_STATUS_OK;
2401 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2402 connection_struct *conn,
2403 struct dptr_struct *dirptr,
2405 const char *path_mask,
2408 bool requires_resume_key,
2414 int space_remaining,
2415 bool *got_exact_match,
2416 int *last_entry_off,
2417 struct ea_list *name_list)
2420 const bool do_pad = true;
2422 if (info_level >= 1 && info_level <= 3) {
2423 /* No alignment on earlier info levels. */
2427 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2428 path_mask, dirtype, info_level,
2429 requires_resume_key, dont_descend, ask_sharemode,
2431 ppdata, base_data, end_data,
2434 last_entry_off, name_list);
2437 /****************************************************************************
2438 Reply to a TRANS2_FINDFIRST.
2439 ****************************************************************************/
2441 static void call_trans2findfirst(connection_struct *conn,
2442 struct smb_request *req,
2443 char **pparams, int total_params,
2444 char **ppdata, int total_data,
2445 unsigned int max_data_bytes)
2447 /* We must be careful here that we don't return more than the
2448 allowed number of data bytes. If this means returning fewer than
2449 maxentries then so be it. We assume that the redirector has
2450 enough room for the fixed number of parameter bytes it has
2452 struct smb_filename *smb_dname = NULL;
2453 char *params = *pparams;
2454 char *pdata = *ppdata;
2458 uint16_t findfirst_flags;
2459 bool close_after_first;
2461 bool requires_resume_key;
2463 char *directory = NULL;
2466 int last_entry_off=0;
2470 bool finished = False;
2471 bool dont_descend = False;
2472 bool out_of_space = False;
2473 int space_remaining;
2474 bool mask_contains_wcard = False;
2475 struct ea_list *ea_list = NULL;
2476 NTSTATUS ntstatus = NT_STATUS_OK;
2477 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2478 TALLOC_CTX *ctx = talloc_tos();
2479 struct dptr_struct *dirptr = NULL;
2480 struct smbd_server_connection *sconn = req->sconn;
2481 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2482 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
2483 bool backup_priv = false;
2484 bool as_root = false;
2486 if (total_params < 13) {
2487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2491 dirtype = SVAL(params,0);
2492 maxentries = SVAL(params,2);
2493 findfirst_flags = SVAL(params,4);
2494 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2495 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2496 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2497 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2498 security_token_has_privilege(get_current_nttok(conn),
2501 info_level = SVAL(params,6);
2503 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2504 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2505 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2507 info_level, max_data_bytes));
2510 /* W2K3 seems to treat zero as 1. */
2514 switch (info_level) {
2515 case SMB_FIND_INFO_STANDARD:
2516 case SMB_FIND_EA_SIZE:
2517 case SMB_FIND_EA_LIST:
2518 case SMB_FIND_FILE_DIRECTORY_INFO:
2519 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2520 case SMB_FIND_FILE_NAMES_INFO:
2521 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2522 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2523 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2525 case SMB_FIND_FILE_UNIX:
2526 case SMB_FIND_FILE_UNIX_INFO2:
2527 /* Always use filesystem for UNIX mtime query. */
2528 ask_sharemode = false;
2529 if (!lp_unix_extensions()) {
2530 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2533 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2536 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2540 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2541 params+12, total_params - 12,
2542 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2543 if (!NT_STATUS_IS_OK(ntstatus)) {
2544 reply_nterror(req, ntstatus);
2551 ntstatus = filename_convert_with_privilege(ctx,
2556 &mask_contains_wcard,
2559 ntstatus = filename_convert(ctx, conn,
2560 req->flags2 & FLAGS2_DFS_PATHNAMES,
2563 &mask_contains_wcard,
2567 if (!NT_STATUS_IS_OK(ntstatus)) {
2568 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2569 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2570 ERRSRV, ERRbadpath);
2573 reply_nterror(req, ntstatus);
2577 mask = smb_dname->original_lcomp;
2579 directory = smb_dname->base_name;
2581 p = strrchr_m(directory,'/');
2583 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2584 if((directory[0] == '.') && (directory[1] == '\0')) {
2585 mask = talloc_strdup(ctx,"*");
2587 reply_nterror(req, NT_STATUS_NO_MEMORY);
2590 mask_contains_wcard = True;
2596 if (p == NULL || p == directory) {
2597 /* Ensure we don't have a directory name of "". */
2598 directory = talloc_strdup(talloc_tos(), ".");
2600 reply_nterror(req, NT_STATUS_NO_MEMORY);
2605 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2607 if (info_level == SMB_FIND_EA_LIST) {
2610 if (total_data < 4) {
2611 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2615 ea_size = IVAL(pdata,0);
2616 if (ea_size != total_data) {
2617 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2618 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2623 if (!lp_ea_support(SNUM(conn))) {
2624 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2628 /* Pull out the list of names. */
2629 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2631 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2636 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2641 *ppdata = (char *)SMB_REALLOC(
2642 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2643 if(*ppdata == NULL ) {
2644 reply_nterror(req, NT_STATUS_NO_MEMORY);
2648 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2650 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2653 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2654 /* Realloc the params space */
2655 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2656 if (*pparams == NULL) {
2657 reply_nterror(req, NT_STATUS_NO_MEMORY);
2662 /* Save the wildcard match and attribs we are using on this directory -
2663 needed as lanman2 assumes these are being saved between calls */
2665 ntstatus = dptr_create(conn,
2673 mask_contains_wcard,
2677 if (!NT_STATUS_IS_OK(ntstatus)) {
2678 reply_nterror(req, ntstatus);
2683 /* Remember this in case we have
2684 to do a findnext. */
2685 dptr_set_priv(dirptr);
2688 dptr_num = dptr_dnum(dirptr);
2689 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2691 /* Initialize per TRANS2_FIND_FIRST operation data */
2692 dptr_init_search_op(dirptr);
2694 /* We don't need to check for VOL here as this is returned by
2695 a different TRANS2 call. */
2697 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2698 directory,lp_dont_descend(ctx, SNUM(conn))));
2699 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2700 dont_descend = True;
2703 space_remaining = max_data_bytes;
2704 out_of_space = False;
2706 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2707 bool got_exact_match = False;
2709 /* this is a heuristic to avoid seeking the dirptr except when
2710 absolutely necessary. It allows for a filename of about 40 chars */
2711 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2712 out_of_space = True;
2715 ntstatus = get_lanman2_dir_entry(ctx,
2719 mask,dirtype,info_level,
2720 requires_resume_key,dont_descend,
2725 &last_entry_off, ea_list);
2726 if (NT_STATUS_EQUAL(ntstatus,
2727 NT_STATUS_ILLEGAL_CHARACTER)) {
2729 * Bad character conversion on name. Ignore this
2734 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2735 out_of_space = true;
2737 finished = !NT_STATUS_IS_OK(ntstatus);
2741 if (!finished && !out_of_space)
2745 * As an optimisation if we know we aren't looking
2746 * for a wildcard name (ie. the name matches the wildcard exactly)
2747 * then we can finish on any (first) match.
2748 * This speeds up large directory searches. JRA.
2754 /* Ensure space_remaining never goes -ve. */
2755 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2756 space_remaining = 0;
2757 out_of_space = true;
2759 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2763 /* Check if we can close the dirptr */
2764 if(close_after_first || (finished && close_if_end)) {
2765 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2766 dptr_close(sconn, &dptr_num);
2770 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2771 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2772 * the protocol level is less than NT1. Tested with smbclient. JRA.
2773 * This should fix the OS/2 client bug #2335.
2776 if(numentries == 0) {
2777 dptr_close(sconn, &dptr_num);
2778 if (get_Protocol() < PROTOCOL_NT1) {
2779 reply_force_doserror(req, ERRDOS, ERRnofiles);
2782 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2783 ERRDOS, ERRbadfile);
2788 /* At this point pdata points to numentries directory entries. */
2790 /* Set up the return parameter block */
2791 SSVAL(params,0,dptr_num);
2792 SSVAL(params,2,numentries);
2793 SSVAL(params,4,finished);
2794 SSVAL(params,6,0); /* Never an EA error */
2795 SSVAL(params,8,last_entry_off);
2797 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2800 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2801 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2803 reply_nterror(req, NT_STATUS_NO_MEMORY);
2807 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2808 smb_fn_name(req->cmd),
2809 mask, directory, dirtype, numentries ) );
2812 * Force a name mangle here to ensure that the
2813 * mask as an 8.3 name is top of the mangled cache.
2814 * The reasons for this are subtle. Don't remove
2815 * this code unless you know what you are doing
2816 * (see PR#13758). JRA.
2819 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2820 char mangled_name[13];
2821 name_to_8_3(mask, mangled_name, True, conn->params);
2829 TALLOC_FREE(smb_dname);
2833 /****************************************************************************
2834 Reply to a TRANS2_FINDNEXT.
2835 ****************************************************************************/
2837 static void call_trans2findnext(connection_struct *conn,
2838 struct smb_request *req,
2839 char **pparams, int total_params,
2840 char **ppdata, int total_data,
2841 unsigned int max_data_bytes)
2843 /* We must be careful here that we don't return more than the
2844 allowed number of data bytes. If this means returning fewer than
2845 maxentries then so be it. We assume that the redirector has
2846 enough room for the fixed number of parameter bytes it has
2848 char *params = *pparams;
2849 char *pdata = *ppdata;
2853 uint16_t info_level;
2854 uint32_t resume_key;
2855 uint16_t findnext_flags;
2856 bool close_after_request;
2858 bool requires_resume_key;
2860 bool mask_contains_wcard = False;
2861 char *resume_name = NULL;
2862 const char *mask = NULL;
2863 const char *directory = NULL;
2867 int i, last_entry_off=0;
2868 bool finished = False;
2869 bool dont_descend = False;
2870 bool out_of_space = False;
2871 int space_remaining;
2872 struct ea_list *ea_list = NULL;
2873 NTSTATUS ntstatus = NT_STATUS_OK;
2874 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2875 TALLOC_CTX *ctx = talloc_tos();
2876 struct dptr_struct *dirptr;
2877 struct smbd_server_connection *sconn = req->sconn;
2878 bool backup_priv = false;
2879 bool as_root = false;
2881 if (total_params < 13) {
2882 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2886 dptr_num = SVAL(params,0);
2887 maxentries = SVAL(params,2);
2888 info_level = SVAL(params,4);
2889 resume_key = IVAL(params,6);
2890 findnext_flags = SVAL(params,10);
2891 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2892 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2893 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2894 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2896 if (!continue_bit) {
2897 /* We only need resume_name if continue_bit is zero. */
2898 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2900 total_params - 12, STR_TERMINATE, &ntstatus,
2901 &mask_contains_wcard);
2902 if (!NT_STATUS_IS_OK(ntstatus)) {
2903 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2904 complain (it thinks we're asking for the directory above the shared
2905 path or an invalid name). Catch this as the resume name is only compared, never used in
2906 a file access. JRA. */
2907 srvstr_pull_talloc(ctx, params, req->flags2,
2908 &resume_name, params+12,
2912 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2913 reply_nterror(req, ntstatus);
2919 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2920 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2921 resume_key = %d resume name = %s continue=%d level = %d\n",
2922 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2923 requires_resume_key, resume_key,
2924 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2927 /* W2K3 seems to treat zero as 1. */
2931 switch (info_level) {
2932 case SMB_FIND_INFO_STANDARD:
2933 case SMB_FIND_EA_SIZE:
2934 case SMB_FIND_EA_LIST:
2935 case SMB_FIND_FILE_DIRECTORY_INFO:
2936 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2937 case SMB_FIND_FILE_NAMES_INFO:
2938 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2939 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2940 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2942 case SMB_FIND_FILE_UNIX:
2943 case SMB_FIND_FILE_UNIX_INFO2:
2944 /* Always use filesystem for UNIX mtime query. */
2945 ask_sharemode = false;
2946 if (!lp_unix_extensions()) {
2947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2952 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2956 if (info_level == SMB_FIND_EA_LIST) {
2959 if (total_data < 4) {
2960 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2964 ea_size = IVAL(pdata,0);
2965 if (ea_size != total_data) {
2966 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2967 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2972 if (!lp_ea_support(SNUM(conn))) {
2973 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2977 /* Pull out the list of names. */
2978 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2985 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2990 *ppdata = (char *)SMB_REALLOC(
2991 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2992 if(*ppdata == NULL) {
2993 reply_nterror(req, NT_STATUS_NO_MEMORY);
2998 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3001 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3004 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3005 /* Realloc the params space */
3006 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3007 if(*pparams == NULL ) {
3008 reply_nterror(req, NT_STATUS_NO_MEMORY);
3014 /* Check that the dptr is valid */
3015 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3016 reply_nterror(req, STATUS_NO_MORE_FILES);
3020 directory = dptr_path(sconn, dptr_num);
3022 /* Get the wildcard mask from the dptr */
3023 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3024 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3025 reply_nterror(req, STATUS_NO_MORE_FILES);
3029 /* Get the attr mask from the dptr */
3030 dirtype = dptr_attr(sconn, dptr_num);
3032 backup_priv = dptr_get_priv(dirptr);
3034 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3035 "backup_priv = %d\n",
3036 dptr_num, mask, dirtype,
3038 dptr_TellDir(dirptr),
3041 /* Initialize per TRANS2_FIND_NEXT operation data */
3042 dptr_init_search_op(dirptr);
3044 /* We don't need to check for VOL here as this is returned by
3045 a different TRANS2 call. */
3047 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3048 directory,lp_dont_descend(ctx, SNUM(conn))));
3049 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3050 dont_descend = True;
3053 space_remaining = max_data_bytes;
3054 out_of_space = False;
3062 * Seek to the correct position. We no longer use the resume key but
3063 * depend on the last file name instead.
3066 if(!continue_bit && resume_name && *resume_name) {
3069 long current_pos = 0;
3071 * Remember, name_to_8_3 is called by
3072 * get_lanman2_dir_entry(), so the resume name
3073 * could be mangled. Ensure we check the unmangled name.
3076 if (mangle_is_mangled(resume_name, conn->params)) {
3077 char *new_resume_name = NULL;
3078 mangle_lookup_name_from_8_3(ctx,
3082 if (new_resume_name) {
3083 resume_name = new_resume_name;
3088 * Fix for NT redirector problem triggered by resume key indexes
3089 * changing between directory scans. We now return a resume key of 0
3090 * and instead look for the filename to continue from (also given
3091 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3092 * findfirst/findnext (as is usual) then the directory pointer
3093 * should already be at the correct place.
3096 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3097 } /* end if resume_name && !continue_bit */
3099 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3100 bool got_exact_match = False;
3102 /* this is a heuristic to avoid seeking the dirptr except when
3103 absolutely necessary. It allows for a filename of about 40 chars */
3104 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3105 out_of_space = True;
3108 ntstatus = get_lanman2_dir_entry(ctx,
3112 mask,dirtype,info_level,
3113 requires_resume_key,dont_descend,
3118 &last_entry_off, ea_list);
3119 if (NT_STATUS_EQUAL(ntstatus,
3120 NT_STATUS_ILLEGAL_CHARACTER)) {
3122 * Bad character conversion on name. Ignore this
3127 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3128 out_of_space = true;
3130 finished = !NT_STATUS_IS_OK(ntstatus);
3134 if (!finished && !out_of_space)
3138 * As an optimisation if we know we aren't looking
3139 * for a wildcard name (ie. the name matches the wildcard exactly)
3140 * then we can finish on any (first) match.
3141 * This speeds up large directory searches. JRA.
3147 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3150 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3151 smb_fn_name(req->cmd),
3152 mask, directory, dirtype, numentries ) );
3154 /* Check if we can close the dirptr */
3155 if(close_after_request || (finished && close_if_end)) {
3156 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3157 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3164 /* Set up the return parameter block */
3165 SSVAL(params,0,numentries);
3166 SSVAL(params,2,finished);
3167 SSVAL(params,4,0); /* Never an EA error */
3168 SSVAL(params,6,last_entry_off);
3170 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3176 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3178 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3182 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3184 SMB_ASSERT(extended_info != NULL);
3186 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3187 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3188 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3189 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3190 #ifdef SAMBA_VERSION_REVISION
3191 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3193 extended_info->samba_subversion = 0;
3194 #ifdef SAMBA_VERSION_RC_RELEASE
3195 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3197 #ifdef SAMBA_VERSION_PRE_RELEASE
3198 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3201 #ifdef SAMBA_VERSION_VENDOR_PATCH
3202 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3204 extended_info->samba_gitcommitdate = 0;
3205 #ifdef SAMBA_VERSION_COMMIT_TIME
3206 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3209 memset(extended_info->samba_version_string, 0,
3210 sizeof(extended_info->samba_version_string));
3212 snprintf (extended_info->samba_version_string,
3213 sizeof(extended_info->samba_version_string),
3214 "%s", samba_version_string());
3217 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3218 connection_struct *conn,
3219 TALLOC_CTX *mem_ctx,
3220 uint16_t info_level,
3222 unsigned int max_data_bytes,
3223 size_t *fixed_portion,
3224 struct smb_filename *fname,
3228 char *pdata, *end_data;
3231 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3232 int snum = SNUM(conn);
3233 const char *fstype = lp_fstype(SNUM(conn));
3234 const char *filename = NULL;
3235 const uint64_t bytes_per_sector = 512;
3236 uint32_t additional_flags = 0;
3237 struct smb_filename smb_fname;
3239 NTSTATUS status = NT_STATUS_OK;
3242 if (fname == NULL || fname->base_name == NULL) {
3245 filename = fname->base_name;
3249 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3250 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3251 "info level (0x%x) on IPC$.\n",
3252 (unsigned int)info_level));
3253 return NT_STATUS_ACCESS_DENIED;
3257 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3259 ZERO_STRUCT(smb_fname);
3260 smb_fname.base_name = discard_const_p(char, filename);
3262 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3263 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3264 return map_nt_error_from_unix(errno);
3269 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3270 return NT_STATUS_INVALID_PARAMETER;
3273 *ppdata = (char *)SMB_REALLOC(
3274 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3275 if (*ppdata == NULL) {
3276 return NT_STATUS_NO_MEMORY;
3280 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3281 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3285 switch (info_level) {
3286 case SMB_INFO_ALLOCATION:
3288 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3290 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3292 if (df_ret == (uint64_t)-1) {
3293 return map_nt_error_from_unix(errno);
3296 block_size = lp_block_size(snum);
3297 if (bsize < block_size) {
3298 uint64_t factor = block_size/bsize;
3303 if (bsize > block_size) {
3304 uint64_t factor = bsize/block_size;
3309 sectors_per_unit = bsize/bytes_per_sector;
3311 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3312 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3313 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3315 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3316 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3317 SIVAL(pdata,l1_cUnit,dsize);
3318 SIVAL(pdata,l1_cUnitAvail,dfree);
3319 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3323 case SMB_INFO_VOLUME:
3324 /* Return volume name */
3326 * Add volume serial number - hash of a combination of
3327 * the called hostname and the service name.
3329 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3331 * Win2k3 and previous mess this up by sending a name length
3332 * one byte short. I believe only older clients (OS/2 Win9x) use
3333 * this call so try fixing this by adding a terminating null to
3334 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3336 status = srvstr_push(
3338 pdata+l2_vol_szVolLabel, vname,
3339 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3340 STR_NOALIGN|STR_TERMINATE, &len);
3341 if (!NT_STATUS_IS_OK(status)) {
3344 SCVAL(pdata,l2_vol_cch,len);
3345 data_len = l2_vol_szVolLabel + len;
3346 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3347 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3348 (unsigned)len, vname));
3351 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3352 case SMB_FS_ATTRIBUTE_INFORMATION:
3354 additional_flags = 0;
3355 #if defined(HAVE_SYS_QUOTAS)
3356 additional_flags |= FILE_VOLUME_QUOTAS;
3359 if(lp_nt_acl_support(SNUM(conn))) {
3360 additional_flags |= FILE_PERSISTENT_ACLS;
3363 /* Capabilities are filled in at connection time through STATVFS call */
3364 additional_flags |= conn->fs_capabilities;
3365 additional_flags |= lp_parm_int(conn->params->service,
3366 "share", "fake_fscaps",
3369 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3370 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3371 additional_flags); /* FS ATTRIBUTES */
3373 SIVAL(pdata,4,255); /* Max filename component length */
3374 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3375 and will think we can't do long filenames */
3376 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3377 PTR_DIFF(end_data, pdata+12),
3379 if (!NT_STATUS_IS_OK(status)) {
3383 data_len = 12 + len;
3384 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3385 /* the client only requested a portion of the
3387 data_len = max_data_bytes;
3388 status = STATUS_BUFFER_OVERFLOW;
3390 *fixed_portion = 16;
3393 case SMB_QUERY_FS_LABEL_INFO:
3394 case SMB_FS_LABEL_INFORMATION:
3395 status = srvstr_push(pdata, flags2, pdata+4, vname,
3396 PTR_DIFF(end_data, pdata+4), 0, &len);
3397 if (!NT_STATUS_IS_OK(status)) {
3404 case SMB_QUERY_FS_VOLUME_INFO:
3405 case SMB_FS_VOLUME_INFORMATION:
3408 * Add volume serial number - hash of a combination of
3409 * the called hostname and the service name.
3411 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3412 (str_checksum(get_local_machine_name())<<16));
3414 /* Max label len is 32 characters. */
3415 status = srvstr_push(pdata, flags2, pdata+18, vname,
3416 PTR_DIFF(end_data, pdata+18),
3418 if (!NT_STATUS_IS_OK(status)) {
3421 SIVAL(pdata,12,len);
3424 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3425 (int)strlen(vname),vname,
3426 lp_servicename(talloc_tos(), snum)));
3427 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3428 /* the client only requested a portion of the
3430 data_len = max_data_bytes;
3431 status = STATUS_BUFFER_OVERFLOW;
3433 *fixed_portion = 24;
3436 case SMB_QUERY_FS_SIZE_INFO:
3437 case SMB_FS_SIZE_INFORMATION:
3439 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3441 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3443 if (df_ret == (uint64_t)-1) {
3444 return map_nt_error_from_unix(errno);
3446 block_size = lp_block_size(snum);
3447 if (bsize < block_size) {
3448 uint64_t factor = block_size/bsize;
3453 if (bsize > block_size) {
3454 uint64_t factor = bsize/block_size;
3459 sectors_per_unit = bsize/bytes_per_sector;
3460 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3461 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3462 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3463 SBIG_UINT(pdata,0,dsize);
3464 SBIG_UINT(pdata,8,dfree);
3465 SIVAL(pdata,16,sectors_per_unit);
3466 SIVAL(pdata,20,bytes_per_sector);
3467 *fixed_portion = 24;
3471 case SMB_FS_FULL_SIZE_INFORMATION:
3473 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3475 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3477 if (df_ret == (uint64_t)-1) {
3478 return map_nt_error_from_unix(errno);
3480 block_size = lp_block_size(snum);
3481 if (bsize < block_size) {
3482 uint64_t factor = block_size/bsize;
3487 if (bsize > block_size) {
3488 uint64_t factor = bsize/block_size;
3493 sectors_per_unit = bsize/bytes_per_sector;
3494 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3495 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3496 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3497 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3498 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3499 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3500 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3501 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3502 *fixed_portion = 32;
3506 case SMB_QUERY_FS_DEVICE_INFO:
3507 case SMB_FS_DEVICE_INFORMATION:
3509 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3511 if (!CAN_WRITE(conn)) {
3512 characteristics |= FILE_READ_ONLY_DEVICE;
3515 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3516 SIVAL(pdata,4,characteristics);
3521 #ifdef HAVE_SYS_QUOTAS
3522 case SMB_FS_QUOTA_INFORMATION:
3524 * what we have to send --metze:
3526 * Unknown1: 24 NULL bytes
3527 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3528 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3529 * Quota Flags: 2 byte :
3530 * Unknown3: 6 NULL bytes
3534 * details for Quota Flags:
3536 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3537 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3538 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3539 * 0x0001 Enable Quotas: enable quota for this fs
3543 /* we need to fake up a fsp here,
3544 * because its not send in this call
3547 SMB_NTQUOTA_STRUCT quotas;
3550 ZERO_STRUCT(quotas);
3553 fsp.fnum = FNUM_FIELD_INVALID;
3556 if (get_current_uid(conn) != 0) {
3557 DEBUG(0,("get_user_quota: access_denied "
3558 "service [%s] user [%s]\n",
3559 lp_servicename(talloc_tos(), SNUM(conn)),
3560 conn->session_info->unix_info->unix_name));
3561 return NT_STATUS_ACCESS_DENIED;
3564 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3565 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3566 return map_nt_error_from_unix(errno);
3571 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3572 lp_servicename(talloc_tos(), SNUM(conn))));
3574 /* Unknown1 24 NULL bytes*/
3575 SBIG_UINT(pdata,0,(uint64_t)0);
3576 SBIG_UINT(pdata,8,(uint64_t)0);
3577 SBIG_UINT(pdata,16,(uint64_t)0);
3579 /* Default Soft Quota 8 bytes */
3580 SBIG_UINT(pdata,24,quotas.softlim);
3582 /* Default Hard Quota 8 bytes */
3583 SBIG_UINT(pdata,32,quotas.hardlim);
3585 /* Quota flag 2 bytes */
3586 SSVAL(pdata,40,quotas.qflags);
3588 /* Unknown3 6 NULL bytes */
3594 #endif /* HAVE_SYS_QUOTAS */
3595 case SMB_FS_OBJECTID_INFORMATION:
3597 unsigned char objid[16];
3598 struct smb_extended_info extended_info;
3599 memcpy(pdata,create_volume_objectid(conn, objid),16);
3600 samba_extended_info_version (&extended_info);
3601 SIVAL(pdata,16,extended_info.samba_magic);
3602 SIVAL(pdata,20,extended_info.samba_version);
3603 SIVAL(pdata,24,extended_info.samba_subversion);
3604 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3605 memcpy(pdata+36,extended_info.samba_version_string,28);
3610 case SMB_FS_SECTOR_SIZE_INFORMATION:
3614 * These values match a physical Windows Server 2012
3615 * share backed by NTFS atop spinning rust.
3617 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3618 /* logical_bytes_per_sector */
3619 SIVAL(pdata, 0, bytes_per_sector);
3620 /* phys_bytes_per_sector_atomic */
3621 SIVAL(pdata, 4, bytes_per_sector);
3622 /* phys_bytes_per_sector_perf */
3623 SIVAL(pdata, 8, bytes_per_sector);
3624 /* fs_effective_phys_bytes_per_sector_atomic */
3625 SIVAL(pdata, 12, bytes_per_sector);
3627 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3628 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3629 /* byte_off_sector_align */
3630 SIVAL(pdata, 20, 0);
3631 /* byte_off_partition_align */
3632 SIVAL(pdata, 24, 0);
3633 *fixed_portion = 28;
3639 * Query the version and capabilities of the CIFS UNIX extensions
3643 case SMB_QUERY_CIFS_UNIX_INFO:
3645 bool large_write = lp_min_receive_file_size() &&
3646 !srv_is_signing_active(xconn);
3647 bool large_read = !srv_is_signing_active(xconn);
3648 int encrypt_caps = 0;
3650 if (!lp_unix_extensions()) {
3651 return NT_STATUS_INVALID_LEVEL;
3654 switch (conn->encrypt_level) {
3655 case SMB_SIGNING_OFF:
3658 case SMB_SIGNING_DESIRED:
3659 case SMB_SIGNING_IF_REQUIRED:
3660 case SMB_SIGNING_DEFAULT:
3661 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3663 case SMB_SIGNING_REQUIRED:
3664 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3665 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3666 large_write = false;
3672 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3673 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3675 /* We have POSIX ACLs, pathname, encryption,
3676 * large read/write, and locking capability. */
3678 SBIG_UINT(pdata,4,((uint64_t)(
3679 CIFS_UNIX_POSIX_ACLS_CAP|
3680 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3681 CIFS_UNIX_FCNTL_LOCKS_CAP|
3682 CIFS_UNIX_EXTATTR_CAP|
3683 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3685 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3687 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3691 case SMB_QUERY_POSIX_FS_INFO:
3694 vfs_statvfs_struct svfs;
3696 if (!lp_unix_extensions()) {
3697 return NT_STATUS_INVALID_LEVEL;
3700 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3704 SIVAL(pdata,0,svfs.OptimalTransferSize);
3705 SIVAL(pdata,4,svfs.BlockSize);
3706 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3707 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3708 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3709 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3710 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3711 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3712 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3714 } else if (rc == EOPNOTSUPP) {
3715 return NT_STATUS_INVALID_LEVEL;
3716 #endif /* EOPNOTSUPP */
3718 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3719 return NT_STATUS_DOS(ERRSRV, ERRerror);
3724 case SMB_QUERY_POSIX_WHOAMI:
3730 if (!lp_unix_extensions()) {
3731 return NT_STATUS_INVALID_LEVEL;
3734 if (max_data_bytes < 40) {
3735 return NT_STATUS_BUFFER_TOO_SMALL;
3738 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3739 flags |= SMB_WHOAMI_GUEST;
3742 /* NOTE: 8 bytes for UID/GID, irrespective of native
3743 * platform size. This matches
3744 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3746 data_len = 4 /* flags */
3753 + 4 /* pad/reserved */
3754 + (conn->session_info->unix_token->ngroups * 8)
3756 + (conn->session_info->security_token->num_sids *
3760 SIVAL(pdata, 0, flags);
3761 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3763 (uint64_t)conn->session_info->unix_token->uid);
3764 SBIG_UINT(pdata, 16,
3765 (uint64_t)conn->session_info->unix_token->gid);
3768 if (data_len >= max_data_bytes) {
3769 /* Potential overflow, skip the GIDs and SIDs. */
3771 SIVAL(pdata, 24, 0); /* num_groups */
3772 SIVAL(pdata, 28, 0); /* num_sids */
3773 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3774 SIVAL(pdata, 36, 0); /* reserved */
3780 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3781 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3783 /* We walk the SID list twice, but this call is fairly
3784 * infrequent, and I don't expect that it's performance
3785 * sensitive -- jpeach
3787 for (i = 0, sid_bytes = 0;
3788 i < conn->session_info->security_token->num_sids; ++i) {
3789 sid_bytes += ndr_size_dom_sid(
3790 &conn->session_info->security_token->sids[i],
3794 /* SID list byte count */
3795 SIVAL(pdata, 32, sid_bytes);
3797 /* 4 bytes pad/reserved - must be zero */
3798 SIVAL(pdata, 36, 0);
3802 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3803 SBIG_UINT(pdata, data_len,
3804 (uint64_t)conn->session_info->unix_token->groups[i]);
3810 i < conn->session_info->security_token->num_sids; ++i) {
3811 int sid_len = ndr_size_dom_sid(
3812 &conn->session_info->security_token->sids[i],
3815 sid_linearize((uint8_t *)(pdata + data_len),
3817 &conn->session_info->security_token->sids[i]);
3818 data_len += sid_len;
3824 case SMB_MAC_QUERY_FS_INFO:
3826 * Thursby MAC extension... ONLY on NTFS filesystems
3827 * once we do streams then we don't need this
3829 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3831 SIVAL(pdata,84,0x100); /* Don't support mac... */
3836 return NT_STATUS_INVALID_LEVEL;
3839 *ret_data_len = data_len;
3843 /****************************************************************************
3844 Reply to a TRANS2_QFSINFO (query filesystem info).
3845 ****************************************************************************/
3847 static void call_trans2qfsinfo(connection_struct *conn,
3848 struct smb_request *req,
3849 char **pparams, int total_params,
3850 char **ppdata, int total_data,
3851 unsigned int max_data_bytes)
3853 char *params = *pparams;
3854 uint16_t info_level;
3856 size_t fixed_portion;
3859 if (total_params < 2) {
3860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3864 info_level = SVAL(params,0);
3866 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3867 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3868 DEBUG(0,("call_trans2qfsinfo: encryption required "
3869 "and info level 0x%x sent.\n",
3870 (unsigned int)info_level));
3871 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3876 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3878 status = smbd_do_qfsinfo(req->xconn, conn, req,
3885 if (!NT_STATUS_IS_OK(status)) {
3886 reply_nterror(req, status);
3890 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3893 DEBUG( 4, ( "%s info_level = %d\n",
3894 smb_fn_name(req->cmd), info_level) );
3899 /****************************************************************************
3900 Reply to a TRANS2_SETFSINFO (set filesystem info).
3901 ****************************************************************************/
3903 static void call_trans2setfsinfo(connection_struct *conn,
3904 struct smb_request *req,
3905 char **pparams, int total_params,
3906 char **ppdata, int total_data,
3907 unsigned int max_data_bytes)
3909 struct smbXsrv_connection *xconn = req->xconn;
3910 char *pdata = *ppdata;
3911 char *params = *pparams;
3912 uint16_t info_level;
3914 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3915 lp_servicename(talloc_tos(), SNUM(conn))));
3918 if (total_params < 4) {
3919 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3925 info_level = SVAL(params,2);
3928 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3929 info_level != SMB_SET_CIFS_UNIX_INFO) {
3930 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3931 "info level (0x%x) on IPC$.\n",
3932 (unsigned int)info_level));
3933 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3938 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3939 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3940 DEBUG(0,("call_trans2setfsinfo: encryption required "
3941 "and info level 0x%x sent.\n",
3942 (unsigned int)info_level));
3943 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3948 switch(info_level) {
3949 case SMB_SET_CIFS_UNIX_INFO:
3950 if (!lp_unix_extensions()) {
3951 DEBUG(2,("call_trans2setfsinfo: "
3952 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3953 "unix extensions off\n"));
3955 NT_STATUS_INVALID_LEVEL);
3959 /* There should be 12 bytes of capabilities set. */
3960 if (total_data < 12) {
3963 NT_STATUS_INVALID_PARAMETER);
3966 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3967 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3968 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3969 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3970 /* Just print these values for now. */
3971 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3972 "major = %u, minor = %u cap_low = 0x%x, "
3974 (unsigned int)xconn->
3975 smb1.unix_info.client_major,
3976 (unsigned int)xconn->
3977 smb1.unix_info.client_minor,
3978 (unsigned int)xconn->
3979 smb1.unix_info.client_cap_low,
3980 (unsigned int)xconn->
3981 smb1.unix_info.client_cap_high));
3983 /* Here is where we must switch to posix pathname processing... */
3984 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3985 lp_set_posix_pathnames();
3986 mangle_change_to_posix();
3989 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3990 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3991 /* Client that knows how to do posix locks,
3992 * but not posix open/mkdir operations. Set a
3993 * default type for read/write checks. */
3995 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4000 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4003 size_t param_len = 0;
4004 size_t data_len = total_data;
4006 if (!lp_unix_extensions()) {
4009 NT_STATUS_INVALID_LEVEL);
4013 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4016 NT_STATUS_NOT_SUPPORTED);
4020 if (xconn->smb1.echo_handler.trusted_fde) {
4021 DEBUG( 2,("call_trans2setfsinfo: "
4022 "request transport encryption disabled"
4023 "with 'fork echo handler = yes'\n"));
4026 NT_STATUS_NOT_SUPPORTED);
4030 DEBUG( 4,("call_trans2setfsinfo: "
4031 "request transport encryption.\n"));
4033 status = srv_request_encryption_setup(conn,
4034 (unsigned char **)ppdata,
4036 (unsigned char **)pparams,
4039 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4040 !NT_STATUS_IS_OK(status)) {
4041 reply_nterror(req, status);
4045 send_trans2_replies(conn, req,
4053 if (NT_STATUS_IS_OK(status)) {
4054 /* Server-side transport
4055 * encryption is now *on*. */
4056 status = srv_encryption_start(conn);
4057 if (!NT_STATUS_IS_OK(status)) {
4058 char *reason = talloc_asprintf(talloc_tos(),
4059 "Failure in setting "
4060 "up encrypted transport: %s",
4062 exit_server_cleanly(reason);
4068 case SMB_FS_QUOTA_INFORMATION:
4070 files_struct *fsp = NULL;
4071 SMB_NTQUOTA_STRUCT quotas;
4073 ZERO_STRUCT(quotas);
4076 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4077 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4078 lp_servicename(talloc_tos(), SNUM(conn)),
4079 conn->session_info->unix_info->unix_name));
4080 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4084 /* note: normally there're 48 bytes,
4085 * but we didn't use the last 6 bytes for now
4088 fsp = file_fsp(req, SVAL(params,0));
4090 if (!check_fsp_ntquota_handle(conn, req,
4092 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4094 req, NT_STATUS_INVALID_HANDLE);
4098 if (total_data < 42) {
4099 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4103 NT_STATUS_INVALID_PARAMETER);
4107 /* unknown_1 24 NULL bytes in pdata*/
4109 /* the soft quotas 8 bytes (uint64_t)*/
4110 quotas.softlim = BVAL(pdata,24);
4112 /* the hard quotas 8 bytes (uint64_t)*/
4113 quotas.hardlim = BVAL(pdata,32);
4115 /* quota_flags 2 bytes **/
4116 quotas.qflags = SVAL(pdata,40);
4118 /* unknown_2 6 NULL bytes follow*/
4120 /* now set the quotas */
4121 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4122 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4123 reply_nterror(req, map_nt_error_from_unix(errno));
4130 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4132 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4138 * sending this reply works fine,
4139 * but I'm not sure it's the same
4140 * like windows do...
4143 reply_outbuf(req, 10, 0);
4146 #if defined(HAVE_POSIX_ACLS)
4147 /****************************************************************************
4148 Utility function to count the number of entries in a POSIX acl.
4149 ****************************************************************************/
4151 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4153 unsigned int ace_count = 0;
4154 int entry_id = SMB_ACL_FIRST_ENTRY;
4155 SMB_ACL_ENTRY_T entry;
4157 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4159 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4160 entry_id = SMB_ACL_NEXT_ENTRY;
4167 /****************************************************************************
4168 Utility function to marshall a POSIX acl into wire format.
4169 ****************************************************************************/
4171 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4173 int entry_id = SMB_ACL_FIRST_ENTRY;
4174 SMB_ACL_ENTRY_T entry;
4176 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4177 SMB_ACL_TAG_T tagtype;
4178 SMB_ACL_PERMSET_T permset;
4179 unsigned char perms = 0;
4180 unsigned int own_grp;
4183 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4184 entry_id = SMB_ACL_NEXT_ENTRY;
4187 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4188 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4192 if (sys_acl_get_permset(entry, &permset) == -1) {
4193 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4197 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4198 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4199 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4201 SCVAL(pdata,1,perms);
4204 case SMB_ACL_USER_OBJ:
4205 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4206 own_grp = (unsigned int)pst->st_ex_uid;
4207 SIVAL(pdata,2,own_grp);
4212 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4214 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4217 own_grp = (unsigned int)*puid;
4218 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4219 SIVAL(pdata,2,own_grp);
4223 case SMB_ACL_GROUP_OBJ:
4224 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4225 own_grp = (unsigned int)pst->st_ex_gid;
4226 SIVAL(pdata,2,own_grp);
4231 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4233 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4236 own_grp = (unsigned int)*pgid;
4237 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4238 SIVAL(pdata,2,own_grp);
4243 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4244 SIVAL(pdata,2,0xFFFFFFFF);
4245 SIVAL(pdata,6,0xFFFFFFFF);
4248 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4249 SIVAL(pdata,2,0xFFFFFFFF);
4250 SIVAL(pdata,6,0xFFFFFFFF);
4253 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4256 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4263 /****************************************************************************
4264 Store the FILE_UNIX_BASIC info.
4265 ****************************************************************************/
4267 static char *store_file_unix_basic(connection_struct *conn,
4270 const SMB_STRUCT_STAT *psbuf)
4272 uint64_t file_index = get_FileIndex(conn, psbuf);
4275 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4276 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4278 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4281 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4284 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4285 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4286 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4289 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4293 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4297 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4300 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4301 devno = psbuf->st_ex_rdev;
4303 devno = psbuf->st_ex_dev;
4306 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4310 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4314 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4317 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4321 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4328 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4329 * the chflags(2) (or equivalent) flags.
4331 * XXX: this really should be behind the VFS interface. To do this, we would
4332 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4333 * Each VFS module could then implement its own mapping as appropriate for the
4334 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4336 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4340 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4344 { UF_IMMUTABLE, EXT_IMMUTABLE },
4348 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4352 { UF_HIDDEN, EXT_HIDDEN },
4355 /* Do not remove. We need to guarantee that this array has at least one
4356 * entry to build on HP-UX.
4362 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4363 uint32_t *smb_fflags, uint32_t *smb_fmask)
4367 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4368 *smb_fmask |= info2_flags_map[i].smb_fflag;
4369 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4370 *smb_fflags |= info2_flags_map[i].smb_fflag;
4375 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4376 const uint32_t smb_fflags,
4377 const uint32_t smb_fmask,
4380 uint32_t max_fmask = 0;
4383 *stat_fflags = psbuf->st_ex_flags;
4385 /* For each flags requested in smb_fmask, check the state of the
4386 * corresponding flag in smb_fflags and set or clear the matching
4390 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4391 max_fmask |= info2_flags_map[i].smb_fflag;
4392 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4393 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4394 *stat_fflags |= info2_flags_map[i].stat_fflag;
4396 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4401 /* If smb_fmask is asking to set any bits that are not supported by
4402 * our flag mappings, we should fail.
4404 if ((smb_fmask & max_fmask) != smb_fmask) {
4412 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4413 * of file flags and birth (create) time.
4415 static char *store_file_unix_basic_info2(connection_struct *conn,
4418 const SMB_STRUCT_STAT *psbuf)
4420 uint32_t file_flags = 0;
4421 uint32_t flags_mask = 0;
4423 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4425 /* Create (birth) time 64 bit */
4426 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4429 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4430 SIVAL(pdata, 0, file_flags); /* flags */
4431 SIVAL(pdata, 4, flags_mask); /* mask */
4437 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4438 const struct stream_struct *streams,
4440 unsigned int max_data_bytes,
4441 unsigned int *data_size)
4444 unsigned int ofs = 0;
4446 if (max_data_bytes < 32) {
4447 return NT_STATUS_INFO_LENGTH_MISMATCH;
4450 for (i = 0; i < num_streams; i++) {
4451 unsigned int next_offset;
4453 smb_ucs2_t *namebuf;
4455 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4456 streams[i].name, &namelen) ||
4459 return NT_STATUS_INVALID_PARAMETER;
4463 * name_buf is now null-terminated, we need to marshall as not
4470 * We cannot overflow ...
4472 if ((ofs + 24 + namelen) > max_data_bytes) {
4473 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4475 TALLOC_FREE(namebuf);
4476 return STATUS_BUFFER_OVERFLOW;
4479 SIVAL(data, ofs+4, namelen);
4480 SOFF_T(data, ofs+8, streams[i].size);
4481 SOFF_T(data, ofs+16, streams[i].alloc_size);
4482 memcpy(data+ofs+24, namebuf, namelen);
4483 TALLOC_FREE(namebuf);
4485 next_offset = ofs + 24 + namelen;
4487 if (i == num_streams-1) {
4488 SIVAL(data, ofs, 0);
4491 unsigned int align = ndr_align_size(next_offset, 8);
4493 if ((next_offset + align) > max_data_bytes) {
4494 DEBUG(10, ("refusing to overflow align "
4495 "reply at stream %u\n",
4497 TALLOC_FREE(namebuf);
4498 return STATUS_BUFFER_OVERFLOW;
4501 memset(data+next_offset, 0, align);
4502 next_offset += align;
4504 SIVAL(data, ofs, next_offset - ofs);
4511 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4515 return NT_STATUS_OK;
4518 /****************************************************************************
4519 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4520 ****************************************************************************/
4522 static void call_trans2qpipeinfo(connection_struct *conn,
4523 struct smb_request *req,
4524 unsigned int tran_call,
4525 char **pparams, int total_params,
4526 char **ppdata, int total_data,
4527 unsigned int max_data_bytes)
4529 char *params = *pparams;
4530 char *pdata = *ppdata;
4531 unsigned int data_size = 0;
4532 unsigned int param_size = 2;
4533 uint16_t info_level;
4537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4541 if (total_params < 4) {
4542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4546 fsp = file_fsp(req, SVAL(params,0));
4547 if (!fsp_is_np(fsp)) {
4548 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4552 info_level = SVAL(params,2);
4554 *pparams = (char *)SMB_REALLOC(*pparams,2);
4555 if (*pparams == NULL) {
4556 reply_nterror(req, NT_STATUS_NO_MEMORY);
4561 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4565 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4566 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4567 if (*ppdata == NULL ) {
4568 reply_nterror(req, NT_STATUS_NO_MEMORY);
4573 switch (info_level) {
4574 case SMB_FILE_STANDARD_INFORMATION:
4576 SOFF_T(pdata,0,4096LL);
4583 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4587 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4593 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4594 TALLOC_CTX *mem_ctx,
4595 uint16_t info_level,
4597 struct smb_filename *smb_fname,
4598 bool delete_pending,
4599 struct timespec write_time_ts,
4600 struct ea_list *ea_list,
4601 int lock_data_count,
4604 unsigned int max_data_bytes,
4605 size_t *fixed_portion,
4607 unsigned int *pdata_size)
4609 char *pdata = *ppdata;
4610 char *dstart, *dend;
4611 unsigned int data_size;
4612 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4613 time_t create_time, mtime, atime, c_time;
4614 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4621 uint64_t file_size = 0;
4623 uint64_t allocation_size = 0;
4624 uint64_t file_index = 0;
4625 uint32_t access_mask = 0;
4628 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4629 return NT_STATUS_INVALID_LEVEL;
4632 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4633 smb_fname_str_dbg(smb_fname),
4635 info_level, max_data_bytes));
4637 mode = dos_mode(conn, smb_fname);
4638 nlink = psbuf->st_ex_nlink;
4640 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4644 if ((nlink > 0) && delete_pending) {
4648 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4649 return NT_STATUS_INVALID_PARAMETER;
4652 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4653 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4654 if (*ppdata == NULL) {
4655 return NT_STATUS_NO_MEMORY;
4659 dend = dstart + data_size - 1;
4661 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4662 update_stat_ex_mtime(psbuf, write_time_ts);
4665 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4666 mtime_ts = psbuf->st_ex_mtime;
4667 atime_ts = psbuf->st_ex_atime;
4668 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4670 if (lp_dos_filetime_resolution(SNUM(conn))) {
4671 dos_filetime_timespec(&create_time_ts);
4672 dos_filetime_timespec(&mtime_ts);
4673 dos_filetime_timespec(&atime_ts);
4674 dos_filetime_timespec(&ctime_ts);
4677 create_time = convert_timespec_to_time_t(create_time_ts);
4678 mtime = convert_timespec_to_time_t(mtime_ts);
4679 atime = convert_timespec_to_time_t(atime_ts);
4680 c_time = convert_timespec_to_time_t(ctime_ts);
4682 p = strrchr_m(smb_fname->base_name,'/');
4684 base_name = smb_fname->base_name;
4688 /* NT expects the name to be in an exact form of the *full*
4689 filename. See the trans2 torture test */
4690 if (ISDOT(base_name)) {
4691 dos_fname = talloc_strdup(mem_ctx, "\\");
4693 return NT_STATUS_NO_MEMORY;
4696 dos_fname = talloc_asprintf(mem_ctx,
4698 smb_fname->base_name);
4700 return NT_STATUS_NO_MEMORY;
4702 if (is_ntfs_stream_smb_fname(smb_fname)) {
4703 dos_fname = talloc_asprintf(dos_fname, "%s",
4704 smb_fname->stream_name);
4706 return NT_STATUS_NO_MEMORY;
4710 string_replace(dos_fname, '/', '\\');
4713 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4716 /* Do we have this path open ? */
4718 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4719 fsp1 = file_find_di_first(conn->sconn, fileid);
4720 if (fsp1 && fsp1->initial_allocation_size) {
4721 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4725 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4726 file_size = get_file_size_stat(psbuf);
4730 pos = fsp->fh->position_information;
4734 access_mask = fsp->access_mask;
4736 /* GENERIC_EXECUTE mapping from Windows */
4737 access_mask = 0x12019F;
4740 /* This should be an index number - looks like
4743 I think this causes us to fail the IFSKIT
4744 BasicFileInformationTest. -tpot */
4745 file_index = get_FileIndex(conn, psbuf);
4749 switch (info_level) {
4750 case SMB_INFO_STANDARD:
4751 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4753 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4754 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4755 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4756 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4757 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4758 SSVAL(pdata,l1_attrFile,mode);
4761 case SMB_INFO_QUERY_EA_SIZE:
4763 unsigned int ea_size =
4764 estimate_ea_size(conn, fsp,
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4768 srv_put_dos_date2(pdata,0,create_time);
4769 srv_put_dos_date2(pdata,4,atime);
4770 srv_put_dos_date2(pdata,8,mtime); /* write time */
4771 SIVAL(pdata,12,(uint32_t)file_size);
4772 SIVAL(pdata,16,(uint32_t)allocation_size);
4773 SSVAL(pdata,20,mode);
4774 SIVAL(pdata,22,ea_size);
4778 case SMB_INFO_IS_NAME_VALID:
4779 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4781 /* os/2 needs this ? really ?*/
4782 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4784 /* This is only reached for qpathinfo */
4788 case SMB_INFO_QUERY_EAS_FROM_LIST:
4790 size_t total_ea_len = 0;
4791 struct ea_list *ea_file_list = NULL;
4792 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4795 get_ea_list_from_file(mem_ctx, conn, fsp,
4797 &total_ea_len, &ea_file_list);
4798 if (!NT_STATUS_IS_OK(status)) {
4802 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4804 if (!ea_list || (total_ea_len > data_size)) {
4806 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4810 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4814 case SMB_INFO_QUERY_ALL_EAS:
4816 /* We have data_size bytes to put EA's into. */
4817 size_t total_ea_len = 0;
4818 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4820 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4822 &total_ea_len, &ea_list);
4823 if (!NT_STATUS_IS_OK(status)) {
4827 if (!ea_list || (total_ea_len > data_size)) {
4829 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4833 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4837 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4839 /* This is FileFullEaInformation - 0xF which maps to
4840 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4842 /* We have data_size bytes to put EA's into. */
4843 size_t total_ea_len = 0;
4844 struct ea_list *ea_file_list = NULL;
4846 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4848 /*TODO: add filtering and index handling */
4851 get_ea_list_from_file(mem_ctx, conn, fsp,
4853 &total_ea_len, &ea_file_list);
4854 if (!NT_STATUS_IS_OK(status)) {
4857 if (!ea_file_list) {
4858 return NT_STATUS_NO_EAS_ON_FILE;
4861 status = fill_ea_chained_buffer(mem_ctx,
4865 conn, ea_file_list);
4866 if (!NT_STATUS_IS_OK(status)) {
4872 case SMB_FILE_BASIC_INFORMATION:
4873 case SMB_QUERY_FILE_BASIC_INFO:
4875 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4876 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4877 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4879 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4883 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4884 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4885 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4886 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4887 SIVAL(pdata,32,mode);
4889 DEBUG(5,("SMB_QFBI - "));
4890 DEBUG(5,("create: %s ", ctime(&create_time)));
4891 DEBUG(5,("access: %s ", ctime(&atime)));
4892 DEBUG(5,("write: %s ", ctime(&mtime)));
4893 DEBUG(5,("change: %s ", ctime(&c_time)));
4894 DEBUG(5,("mode: %x\n", mode));
4895 *fixed_portion = data_size;
4898 case SMB_FILE_STANDARD_INFORMATION:
4899 case SMB_QUERY_FILE_STANDARD_INFO:
4901 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4903 SOFF_T(pdata,0,allocation_size);
4904 SOFF_T(pdata,8,file_size);
4905 SIVAL(pdata,16,nlink);
4906 SCVAL(pdata,20,delete_pending?1:0);
4907 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4908 SSVAL(pdata,22,0); /* Padding. */
4909 *fixed_portion = 24;
4912 case SMB_FILE_EA_INFORMATION:
4913 case SMB_QUERY_FILE_EA_INFO:
4915 unsigned int ea_size =
4916 estimate_ea_size(conn, fsp, smb_fname);
4917 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4920 SIVAL(pdata,0,ea_size);
4924 /* Get the 8.3 name - used if NT SMB was negotiated. */
4925 case SMB_QUERY_FILE_ALT_NAME_INFO:
4926 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4928 char mangled_name[13];
4929 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4930 if (!name_to_8_3(base_name,mangled_name,
4931 True,conn->params)) {
4932 return NT_STATUS_NO_MEMORY;
4934 status = srvstr_push(dstart, flags2,
4935 pdata+4, mangled_name,
4936 PTR_DIFF(dend, pdata+4),
4938 if (!NT_STATUS_IS_OK(status)) {
4941 data_size = 4 + len;
4947 case SMB_QUERY_FILE_NAME_INFO:
4950 this must be *exactly* right for ACLs on mapped drives to work
4952 status = srvstr_push(dstart, flags2,
4954 PTR_DIFF(dend, pdata+4),
4956 if (!NT_STATUS_IS_OK(status)) {
4959 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4960 data_size = 4 + len;
4965 case SMB_FILE_ALLOCATION_INFORMATION:
4966 case SMB_QUERY_FILE_ALLOCATION_INFO:
4967 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4969 SOFF_T(pdata,0,allocation_size);
4972 case SMB_FILE_END_OF_FILE_INFORMATION:
4973 case SMB_QUERY_FILE_END_OF_FILEINFO:
4974 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4976 SOFF_T(pdata,0,file_size);
4979 case SMB_QUERY_FILE_ALL_INFO:
4980 case SMB_FILE_ALL_INFORMATION:
4982 unsigned int ea_size =
4983 estimate_ea_size(conn, fsp, smb_fname);
4984 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4985 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4986 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4987 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4988 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4989 SIVAL(pdata,32,mode);
4990 SIVAL(pdata,36,0); /* padding. */
4992 SOFF_T(pdata,0,allocation_size);
4993 SOFF_T(pdata,8,file_size);
4994 SIVAL(pdata,16,nlink);
4995 SCVAL(pdata,20,delete_pending);
4996 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4999 SIVAL(pdata,0,ea_size);
5000 pdata += 4; /* EA info */
5001 status = srvstr_push(dstart, flags2,
5003 PTR_DIFF(dend, pdata+4),
5005 if (!NT_STATUS_IS_OK(status)) {
5010 data_size = PTR_DIFF(pdata,(*ppdata));
5011 *fixed_portion = 10;
5015 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5017 unsigned int ea_size =
5018 estimate_ea_size(conn, fsp, smb_fname);
5019 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5020 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5021 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5022 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5023 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5024 SIVAL(pdata, 0x20, mode);
5025 SIVAL(pdata, 0x24, 0); /* padding. */
5026 SBVAL(pdata, 0x28, allocation_size);
5027 SBVAL(pdata, 0x30, file_size);
5028 SIVAL(pdata, 0x38, nlink);
5029 SCVAL(pdata, 0x3C, delete_pending);
5030 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5031 SSVAL(pdata, 0x3E, 0); /* padding */
5032 SBVAL(pdata, 0x40, file_index);
5033 SIVAL(pdata, 0x48, ea_size);
5034 SIVAL(pdata, 0x4C, access_mask);
5035 SBVAL(pdata, 0x50, pos);
5036 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5037 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5041 status = srvstr_push(dstart, flags2,
5043 PTR_DIFF(dend, pdata+4),
5045 if (!NT_STATUS_IS_OK(status)) {
5050 data_size = PTR_DIFF(pdata,(*ppdata));
5051 *fixed_portion = 104;
5054 case SMB_FILE_INTERNAL_INFORMATION:
5056 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5057 SBVAL(pdata, 0, file_index);
5062 case SMB_FILE_ACCESS_INFORMATION:
5063 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5064 SIVAL(pdata, 0, access_mask);
5069 case SMB_FILE_NAME_INFORMATION:
5070 /* Pathname with leading '\'. */
5073 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5074 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5075 SIVAL(pdata,0,byte_len);
5076 data_size = 4 + byte_len;
5080 case SMB_FILE_DISPOSITION_INFORMATION:
5081 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5083 SCVAL(pdata,0,delete_pending);
5087 case SMB_FILE_POSITION_INFORMATION:
5088 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5090 SOFF_T(pdata,0,pos);
5094 case SMB_FILE_MODE_INFORMATION:
5095 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5096 SIVAL(pdata,0,mode);
5101 case SMB_FILE_ALIGNMENT_INFORMATION:
5102 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5103 SIVAL(pdata,0,0); /* No alignment needed. */
5109 * NT4 server just returns "invalid query" to this - if we try
5110 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5113 /* The first statement above is false - verified using Thursby
5114 * client against NT4 -- gcolley.
5116 case SMB_QUERY_FILE_STREAM_INFO:
5117 case SMB_FILE_STREAM_INFORMATION: {
5118 unsigned int num_streams = 0;
5119 struct stream_struct *streams = NULL;
5121 DEBUG(10,("smbd_do_qfilepathinfo: "
5122 "SMB_FILE_STREAM_INFORMATION\n"));
5124 if (is_ntfs_stream_smb_fname(smb_fname)) {
5125 return NT_STATUS_INVALID_PARAMETER;
5128 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
5129 talloc_tos(), &num_streams, &streams);
5131 if (!NT_STATUS_IS_OK(status)) {
5132 DEBUG(10, ("could not get stream info: %s\n",
5133 nt_errstr(status)));
5137 status = marshall_stream_info(num_streams, streams,
5138 pdata, max_data_bytes,
5141 if (!NT_STATUS_IS_OK(status)) {
5142 DEBUG(10, ("marshall_stream_info failed: %s\n",
5143 nt_errstr(status)));
5144 TALLOC_FREE(streams);
5148 TALLOC_FREE(streams);
5150 *fixed_portion = 32;
5154 case SMB_QUERY_COMPRESSION_INFO:
5155 case SMB_FILE_COMPRESSION_INFORMATION:
5156 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5157 SOFF_T(pdata,0,file_size);
5158 SIVAL(pdata,8,0); /* ??? */
5159 SIVAL(pdata,12,0); /* ??? */
5161 *fixed_portion = 16;
5164 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5165 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5166 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5167 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5168 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5169 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5170 SOFF_T(pdata,32,allocation_size);
5171 SOFF_T(pdata,40,file_size);
5172 SIVAL(pdata,48,mode);
5173 SIVAL(pdata,52,0); /* ??? */
5175 *fixed_portion = 56;
5178 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5179 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5180 SIVAL(pdata,0,mode);
5187 * CIFS UNIX Extensions.
5190 case SMB_QUERY_FILE_UNIX_BASIC:
5192 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5193 data_size = PTR_DIFF(pdata,(*ppdata));
5195 DEBUG(4,("smbd_do_qfilepathinfo: "
5196 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5197 dump_data(4, (uint8_t *)(*ppdata), data_size);
5201 case SMB_QUERY_FILE_UNIX_INFO2:
5203 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5204 data_size = PTR_DIFF(pdata,(*ppdata));
5208 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5210 for (i=0; i<100; i++)
5211 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5217 case SMB_QUERY_FILE_UNIX_LINK:
5220 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5223 return NT_STATUS_NO_MEMORY;
5226 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5228 if(!S_ISLNK(psbuf->st_ex_mode)) {
5229 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5232 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5234 link_len = SMB_VFS_READLINK(conn,
5235 smb_fname->base_name,
5237 if (link_len == -1) {
5238 return map_nt_error_from_unix(errno);
5240 buffer[link_len] = 0;
5241 status = srvstr_push(dstart, flags2,
5243 PTR_DIFF(dend, pdata),
5244 STR_TERMINATE, &len);
5245 if (!NT_STATUS_IS_OK(status)) {
5249 data_size = PTR_DIFF(pdata,(*ppdata));
5254 #if defined(HAVE_POSIX_ACLS)
5255 case SMB_QUERY_POSIX_ACL:
5257 SMB_ACL_T file_acl = NULL;
5258 SMB_ACL_T def_acl = NULL;
5259 uint16_t num_file_acls = 0;
5260 uint16_t num_def_acls = 0;
5262 if (fsp && fsp->fh->fd != -1) {
5263 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5267 SMB_VFS_SYS_ACL_GET_FILE(conn,
5268 smb_fname->base_name,
5269 SMB_ACL_TYPE_ACCESS,
5273 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5274 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5275 "not implemented on "
5276 "filesystem containing %s\n",
5277 smb_fname->base_name));
5278 return NT_STATUS_NOT_IMPLEMENTED;
5281 if (S_ISDIR(psbuf->st_ex_mode)) {
5282 if (fsp && fsp->is_directory) {
5284 SMB_VFS_SYS_ACL_GET_FILE(
5286 fsp->fsp_name->base_name,
5287 SMB_ACL_TYPE_DEFAULT,
5291 SMB_VFS_SYS_ACL_GET_FILE(
5293 smb_fname->base_name,
5294 SMB_ACL_TYPE_DEFAULT,
5297 def_acl = free_empty_sys_acl(conn, def_acl);
5300 num_file_acls = count_acl_entries(conn, file_acl);
5301 num_def_acls = count_acl_entries(conn, def_acl);
5303 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5304 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5306 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5307 SMB_POSIX_ACL_HEADER_SIZE) ));
5309 TALLOC_FREE(file_acl);
5312 TALLOC_FREE(def_acl);
5314 return NT_STATUS_BUFFER_TOO_SMALL;
5317 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5318 SSVAL(pdata,2,num_file_acls);
5319 SSVAL(pdata,4,num_def_acls);
5320 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5322 TALLOC_FREE(file_acl);
5325 TALLOC_FREE(def_acl);
5327 return NT_STATUS_INTERNAL_ERROR;
5329 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5331 TALLOC_FREE(file_acl);
5334 TALLOC_FREE(def_acl);
5336 return NT_STATUS_INTERNAL_ERROR;
5340 TALLOC_FREE(file_acl);
5343 TALLOC_FREE(def_acl);
5345 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5351 case SMB_QUERY_POSIX_LOCK:
5356 enum brl_type lock_type;
5358 /* We need an open file with a real fd for this. */
5359 if (!fsp || fsp->fh->fd == -1) {
5360 return NT_STATUS_INVALID_LEVEL;
5363 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5364 return NT_STATUS_INVALID_PARAMETER;
5367 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5368 case POSIX_LOCK_TYPE_READ:
5369 lock_type = READ_LOCK;
5371 case POSIX_LOCK_TYPE_WRITE:
5372 lock_type = WRITE_LOCK;
5374 case POSIX_LOCK_TYPE_UNLOCK:
5376 /* There's no point in asking for an unlock... */
5377 return NT_STATUS_INVALID_PARAMETER;
5380 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5381 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5382 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5384 status = query_lock(fsp,
5391 if (ERROR_WAS_LOCK_DENIED(status)) {
5392 /* Here we need to report who has it locked... */
5393 data_size = POSIX_LOCK_DATA_SIZE;
5395 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5396 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5397 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5398 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5399 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5401 } else if (NT_STATUS_IS_OK(status)) {
5402 /* For success we just return a copy of what we sent
5403 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5404 data_size = POSIX_LOCK_DATA_SIZE;
5405 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5406 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5414 return NT_STATUS_INVALID_LEVEL;
5417 *pdata_size = data_size;
5418 return NT_STATUS_OK;
5421 /****************************************************************************
5422 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5423 file name or file id).
5424 ****************************************************************************/
5426 static void call_trans2qfilepathinfo(connection_struct *conn,
5427 struct smb_request *req,
5428 unsigned int tran_call,
5429 char **pparams, int total_params,
5430 char **ppdata, int total_data,
5431 unsigned int max_data_bytes)
5433 char *params = *pparams;
5434 char *pdata = *ppdata;
5435 uint16_t info_level;
5436 unsigned int data_size = 0;
5437 unsigned int param_size = 2;
5438 struct smb_filename *smb_fname = NULL;
5439 bool delete_pending = False;
5440 struct timespec write_time_ts;
5441 files_struct *fsp = NULL;
5442 struct file_id fileid;
5443 struct ea_list *ea_list = NULL;
5444 int lock_data_count = 0;
5445 char *lock_data = NULL;
5446 size_t fixed_portion;
5447 NTSTATUS status = NT_STATUS_OK;
5450 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5454 ZERO_STRUCT(write_time_ts);
5456 if (tran_call == TRANSACT2_QFILEINFO) {
5457 if (total_params < 4) {
5458 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5463 call_trans2qpipeinfo(conn, req, tran_call,
5464 pparams, total_params,
5470 fsp = file_fsp(req, SVAL(params,0));
5471 info_level = SVAL(params,2);
5473 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5475 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5476 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5480 /* Initial check for valid fsp ptr. */
5481 if (!check_fsp_open(conn, req, fsp)) {
5485 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5486 if (smb_fname == NULL) {
5487 reply_nterror(req, NT_STATUS_NO_MEMORY);
5491 if(fsp->fake_file_handle) {
5493 * This is actually for the QUOTA_FAKE_FILE --metze
5496 /* We know this name is ok, it's already passed the checks. */
5498 } else if(fsp->fh->fd == -1) {
5500 * This is actually a QFILEINFO on a directory
5501 * handle (returned from an NT SMB). NT5.0 seems
5502 * to do this call. JRA.
5505 if (INFO_LEVEL_IS_UNIX(info_level)) {
5506 /* Always do lstat for UNIX calls. */
5507 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5508 DEBUG(3,("call_trans2qfilepathinfo: "
5509 "SMB_VFS_LSTAT of %s failed "
5511 smb_fname_str_dbg(smb_fname),
5514 map_nt_error_from_unix(errno));
5517 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5518 DEBUG(3,("call_trans2qfilepathinfo: "
5519 "SMB_VFS_STAT of %s failed (%s)\n",
5520 smb_fname_str_dbg(smb_fname),
5523 map_nt_error_from_unix(errno));
5527 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5528 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5531 * Original code - this is an open file.
5533 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5534 DEBUG(3, ("fstat of %s failed (%s)\n",
5535 fsp_fnum_dbg(fsp), strerror(errno)));
5537 map_nt_error_from_unix(errno));
5540 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5541 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5547 uint32_t ucf_flags = (lp_posix_pathnames() ?
5548 UCF_POSIX_PATHNAMES : 0);
5551 if (total_params < 7) {
5552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5556 info_level = SVAL(params,0);
5558 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5560 if (INFO_LEVEL_IS_UNIX(info_level)) {
5561 if (!lp_unix_extensions()) {
5562 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5565 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5566 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5567 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5568 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5572 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5574 STR_TERMINATE, &status);
5575 if (!NT_STATUS_IS_OK(status)) {
5576 reply_nterror(req, status);
5580 status = filename_convert(req,
5582 req->flags2 & FLAGS2_DFS_PATHNAMES,
5587 if (!NT_STATUS_IS_OK(status)) {
5588 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5589 reply_botherror(req,
5590 NT_STATUS_PATH_NOT_COVERED,
5591 ERRSRV, ERRbadpath);
5594 reply_nterror(req, status);
5598 /* If this is a stream, check if there is a delete_pending. */
5599 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5600 && is_ntfs_stream_smb_fname(smb_fname)) {
5601 struct smb_filename *smb_fname_base;
5603 /* Create an smb_filename with stream_name == NULL. */
5604 smb_fname_base = synthetic_smb_fname(
5605 talloc_tos(), smb_fname->base_name,
5607 if (smb_fname_base == NULL) {
5608 reply_nterror(req, NT_STATUS_NO_MEMORY);
5612 if (INFO_LEVEL_IS_UNIX(info_level)) {
5613 /* Always do lstat for UNIX calls. */
5614 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5615 DEBUG(3,("call_trans2qfilepathinfo: "
5616 "SMB_VFS_LSTAT of %s failed "
5618 smb_fname_str_dbg(smb_fname_base),
5620 TALLOC_FREE(smb_fname_base);
5622 map_nt_error_from_unix(errno));
5626 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5627 DEBUG(3,("call_trans2qfilepathinfo: "
5628 "fileinfo of %s failed "
5630 smb_fname_str_dbg(smb_fname_base),
5632 TALLOC_FREE(smb_fname_base);
5634 map_nt_error_from_unix(errno));
5639 status = file_name_hash(conn,
5640 smb_fname_str_dbg(smb_fname_base),
5642 if (!NT_STATUS_IS_OK(status)) {
5643 TALLOC_FREE(smb_fname_base);
5644 reply_nterror(req, status);
5648 fileid = vfs_file_id_from_sbuf(conn,
5649 &smb_fname_base->st);
5650 TALLOC_FREE(smb_fname_base);
5651 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5652 if (delete_pending) {
5653 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5658 if (INFO_LEVEL_IS_UNIX(info_level)) {
5659 /* Always do lstat for UNIX calls. */
5660 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5661 DEBUG(3,("call_trans2qfilepathinfo: "
5662 "SMB_VFS_LSTAT of %s failed (%s)\n",
5663 smb_fname_str_dbg(smb_fname),
5666 map_nt_error_from_unix(errno));
5671 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5672 DEBUG(3,("call_trans2qfilepathinfo: "
5673 "SMB_VFS_STAT of %s failed (%s)\n",
5674 smb_fname_str_dbg(smb_fname),
5677 map_nt_error_from_unix(errno));
5682 status = file_name_hash(conn,
5683 smb_fname_str_dbg(smb_fname),
5685 if (!NT_STATUS_IS_OK(status)) {
5686 reply_nterror(req, status);
5690 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5691 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5692 if (delete_pending) {
5693 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5698 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5699 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5701 info_level,tran_call,total_data));
5703 /* Pull out any data sent here before we realloc. */
5704 switch (info_level) {
5705 case SMB_INFO_QUERY_EAS_FROM_LIST:
5707 /* Pull any EA list from the data portion. */
5710 if (total_data < 4) {
5712 req, NT_STATUS_INVALID_PARAMETER);
5715 ea_size = IVAL(pdata,0);
5717 if (total_data > 0 && ea_size != total_data) {
5718 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5719 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5721 req, NT_STATUS_INVALID_PARAMETER);
5725 if (!lp_ea_support(SNUM(conn))) {
5726 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5730 /* Pull out the list of names. */
5731 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5734 req, NT_STATUS_INVALID_PARAMETER);
5740 case SMB_QUERY_POSIX_LOCK:
5742 if (fsp == NULL || fsp->fh->fd == -1) {
5743 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5747 if (total_data != POSIX_LOCK_DATA_SIZE) {
5749 req, NT_STATUS_INVALID_PARAMETER);
5753 /* Copy the lock range data. */
5754 lock_data = (char *)talloc_memdup(
5755 req, pdata, total_data);
5757 reply_nterror(req, NT_STATUS_NO_MEMORY);
5760 lock_data_count = total_data;
5766 *pparams = (char *)SMB_REALLOC(*pparams,2);
5767 if (*pparams == NULL) {
5768 reply_nterror(req, NT_STATUS_NO_MEMORY);
5775 * draft-leach-cifs-v1-spec-02.txt
5776 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5779 * The requested information is placed in the Data portion of the
5780 * transaction response. For the information levels greater than 0x100,
5781 * the transaction response has 1 parameter word which should be
5782 * ignored by the client.
5784 * However Windows only follows this rule for the IS_NAME_VALID call.
5786 switch (info_level) {
5787 case SMB_INFO_IS_NAME_VALID:
5792 if ((info_level & 0xFF00) == 0xFF00) {
5794 * We use levels that start with 0xFF00
5795 * internally to represent SMB2 specific levels
5797 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5801 status = smbd_do_qfilepathinfo(conn, req, info_level,
5803 delete_pending, write_time_ts,
5805 lock_data_count, lock_data,
5806 req->flags2, max_data_bytes,
5808 ppdata, &data_size);
5809 if (!NT_STATUS_IS_OK(status)) {
5810 reply_nterror(req, status);
5813 if (fixed_portion > max_data_bytes) {
5814 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5818 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5824 /****************************************************************************
5825 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5827 ****************************************************************************/
5829 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5830 connection_struct *conn,
5831 struct smb_request *req,
5832 bool overwrite_if_exists,
5833 const struct smb_filename *smb_fname_old,
5834 struct smb_filename *smb_fname_new)
5836 NTSTATUS status = NT_STATUS_OK;
5838 /* source must already exist. */
5839 if (!VALID_STAT(smb_fname_old->st)) {
5840 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5843 if (VALID_STAT(smb_fname_new->st)) {
5844 if (overwrite_if_exists) {
5845 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5846 return NT_STATUS_FILE_IS_A_DIRECTORY;
5848 status = unlink_internals(conn,
5850 FILE_ATTRIBUTE_NORMAL,
5853 if (!NT_STATUS_IS_OK(status)) {
5857 /* Disallow if newname already exists. */
5858 return NT_STATUS_OBJECT_NAME_COLLISION;
5862 /* No links from a directory. */
5863 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5864 return NT_STATUS_FILE_IS_A_DIRECTORY;
5867 /* Setting a hardlink to/from a stream isn't currently supported. */
5868 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5869 is_ntfs_stream_smb_fname(smb_fname_new)) {
5870 return NT_STATUS_INVALID_PARAMETER;
5873 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5874 smb_fname_old->base_name, smb_fname_new->base_name));
5876 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5877 smb_fname_new->base_name) != 0) {
5878 status = map_nt_error_from_unix(errno);
5879 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5880 nt_errstr(status), smb_fname_old->base_name,
5881 smb_fname_new->base_name));
5886 /****************************************************************************
5887 Deal with setting the time from any of the setfilepathinfo functions.
5888 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5889 calling this function.
5890 ****************************************************************************/
5892 NTSTATUS smb_set_file_time(connection_struct *conn,
5894 const struct smb_filename *smb_fname,
5895 struct smb_file_time *ft,
5896 bool setting_write_time)
5898 struct smb_filename smb_fname_base;
5900 FILE_NOTIFY_CHANGE_LAST_ACCESS
5901 |FILE_NOTIFY_CHANGE_LAST_WRITE
5902 |FILE_NOTIFY_CHANGE_CREATION;
5904 if (!VALID_STAT(smb_fname->st)) {
5905 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5908 /* get some defaults (no modifications) if any info is zero or -1. */
5909 if (null_timespec(ft->create_time)) {
5910 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5913 if (null_timespec(ft->atime)) {
5914 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5917 if (null_timespec(ft->mtime)) {
5918 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5921 if (!setting_write_time) {
5922 /* ft->mtime comes from change time, not write time. */
5923 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5926 /* Ensure the resolution is the correct for
5927 * what we can store on this filesystem. */
5929 round_timespec(conn->ts_res, &ft->create_time);
5930 round_timespec(conn->ts_res, &ft->ctime);
5931 round_timespec(conn->ts_res, &ft->atime);
5932 round_timespec(conn->ts_res, &ft->mtime);
5934 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5935 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5936 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5937 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5938 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5939 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5940 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5941 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5943 if (setting_write_time) {
5945 * This was a Windows setfileinfo on an open file.
5946 * NT does this a lot. We also need to
5947 * set the time here, as it can be read by
5948 * FindFirst/FindNext and with the patch for bug #2045
5949 * in smbd/fileio.c it ensures that this timestamp is
5950 * kept sticky even after a write. We save the request
5951 * away and will set it on file close and after a write. JRA.
5954 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5955 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5958 if (fsp->base_fsp) {
5959 set_sticky_write_time_fsp(fsp->base_fsp,
5962 set_sticky_write_time_fsp(fsp, ft->mtime);
5965 set_sticky_write_time_path(
5966 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5971 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5973 /* Always call ntimes on the base, even if a stream was passed in. */
5974 smb_fname_base = *smb_fname;
5975 smb_fname_base.stream_name = NULL;
5977 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5978 return map_nt_error_from_unix(errno);
5981 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5982 smb_fname->base_name);
5983 return NT_STATUS_OK;
5986 /****************************************************************************
5987 Deal with setting the dosmode from any of the setfilepathinfo functions.
5988 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5989 done before calling this function.
5990 ****************************************************************************/
5992 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5993 const struct smb_filename *smb_fname,
5996 struct smb_filename *smb_fname_base;
5999 if (!VALID_STAT(smb_fname->st)) {
6000 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6003 /* Always operate on the base_name, even if a stream was passed in. */
6004 smb_fname_base = synthetic_smb_fname(
6005 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
6006 if (smb_fname_base == NULL) {
6007 return NT_STATUS_NO_MEMORY;
6011 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6012 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6014 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6018 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6020 /* check the mode isn't different, before changing it */
6021 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6022 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6023 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6024 (unsigned int)dosmode));
6026 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6028 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6030 smb_fname_str_dbg(smb_fname_base),
6032 status = map_nt_error_from_unix(errno);
6036 status = NT_STATUS_OK;
6038 TALLOC_FREE(smb_fname_base);
6042 /****************************************************************************
6043 Deal with setting the size from any of the setfilepathinfo functions.
6044 ****************************************************************************/
6046 static NTSTATUS smb_set_file_size(connection_struct *conn,
6047 struct smb_request *req,
6049 const struct smb_filename *smb_fname,
6050 const SMB_STRUCT_STAT *psbuf,
6052 bool fail_after_createfile)
6054 NTSTATUS status = NT_STATUS_OK;
6055 struct smb_filename *smb_fname_tmp = NULL;
6056 files_struct *new_fsp = NULL;
6058 if (!VALID_STAT(*psbuf)) {
6059 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6062 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6064 if (size == get_file_size_stat(psbuf)) {
6065 return NT_STATUS_OK;
6068 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6069 smb_fname_str_dbg(smb_fname), (double)size));
6071 if (fsp && fsp->fh->fd != -1) {
6072 /* Handle based call. */
6073 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6074 return NT_STATUS_ACCESS_DENIED;
6077 if (vfs_set_filelen(fsp, size) == -1) {
6078 return map_nt_error_from_unix(errno);
6080 trigger_write_time_update_immediate(fsp);
6081 return NT_STATUS_OK;
6084 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6085 if (smb_fname_tmp == NULL) {
6086 return NT_STATUS_NO_MEMORY;
6089 smb_fname_tmp->st = *psbuf;
6091 status = SMB_VFS_CREATE_FILE(
6094 0, /* root_dir_fid */
6095 smb_fname_tmp, /* fname */
6096 FILE_WRITE_DATA, /* access_mask */
6097 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6099 FILE_OPEN, /* create_disposition*/
6100 0, /* create_options */
6101 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6102 0, /* oplock_request */
6104 0, /* allocation_size */
6105 0, /* private_flags */
6108 &new_fsp, /* result */
6110 NULL, NULL); /* create context */
6112 TALLOC_FREE(smb_fname_tmp);
6114 if (!NT_STATUS_IS_OK(status)) {
6115 /* NB. We check for open_was_deferred in the caller. */
6119 /* See RAW-SFILEINFO-END-OF-FILE */
6120 if (fail_after_createfile) {
6121 close_file(req, new_fsp,NORMAL_CLOSE);
6122 return NT_STATUS_INVALID_LEVEL;
6125 if (vfs_set_filelen(new_fsp, size) == -1) {
6126 status = map_nt_error_from_unix(errno);
6127 close_file(req, new_fsp,NORMAL_CLOSE);
6131 trigger_write_time_update_immediate(new_fsp);
6132 close_file(req, new_fsp,NORMAL_CLOSE);
6133 return NT_STATUS_OK;
6136 /****************************************************************************
6137 Deal with SMB_INFO_SET_EA.
6138 ****************************************************************************/
6140 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6144 const struct smb_filename *smb_fname)
6146 struct ea_list *ea_list = NULL;
6147 TALLOC_CTX *ctx = NULL;
6148 NTSTATUS status = NT_STATUS_OK;
6150 if (total_data < 10) {
6152 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6153 length. They seem to have no effect. Bug #3212. JRA */
6155 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6156 /* We're done. We only get EA info in this call. */
6157 return NT_STATUS_OK;
6160 return NT_STATUS_INVALID_PARAMETER;
6163 if (IVAL(pdata,0) > total_data) {
6164 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6165 IVAL(pdata,0), (unsigned int)total_data));
6166 return NT_STATUS_INVALID_PARAMETER;
6170 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6172 return NT_STATUS_INVALID_PARAMETER;
6175 status = set_ea(conn, fsp, smb_fname, ea_list);
6180 /****************************************************************************
6181 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6182 ****************************************************************************/
6184 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6189 struct ea_list *ea_list = NULL;
6193 return NT_STATUS_INVALID_HANDLE;
6196 if (!lp_ea_support(SNUM(conn))) {
6197 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6198 "EA's not supported.\n",
6199 (unsigned int)total_data));
6200 return NT_STATUS_EAS_NOT_SUPPORTED;
6203 if (total_data < 10) {
6204 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6206 (unsigned int)total_data));
6207 return NT_STATUS_INVALID_PARAMETER;
6210 ea_list = read_nttrans_ea_list(talloc_tos(),
6215 return NT_STATUS_INVALID_PARAMETER;
6218 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6220 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6221 smb_fname_str_dbg(fsp->fsp_name),
6222 nt_errstr(status) ));
6228 /****************************************************************************
6229 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6230 ****************************************************************************/
6232 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6236 struct smb_filename *smb_fname)
6238 NTSTATUS status = NT_STATUS_OK;
6239 bool delete_on_close;
6240 uint32_t dosmode = 0;
6242 if (total_data < 1) {
6243 return NT_STATUS_INVALID_PARAMETER;
6247 return NT_STATUS_INVALID_HANDLE;
6250 delete_on_close = (CVAL(pdata,0) ? True : False);
6251 dosmode = dos_mode(conn, smb_fname);
6253 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6254 "delete_on_close = %u\n",
6255 smb_fname_str_dbg(smb_fname),
6256 (unsigned int)dosmode,
6257 (unsigned int)delete_on_close ));
6259 if (delete_on_close) {
6260 status = can_set_delete_on_close(fsp, dosmode);
6261 if (!NT_STATUS_IS_OK(status)) {
6266 /* The set is across all open files on this dev/inode pair. */
6267 if (!set_delete_on_close(fsp, delete_on_close,
6268 conn->session_info->security_token,
6269 conn->session_info->unix_token)) {
6270 return NT_STATUS_ACCESS_DENIED;
6272 return NT_STATUS_OK;
6275 /****************************************************************************
6276 Deal with SMB_FILE_POSITION_INFORMATION.
6277 ****************************************************************************/
6279 static NTSTATUS smb_file_position_information(connection_struct *conn,
6284 uint64_t position_information;
6286 if (total_data < 8) {
6287 return NT_STATUS_INVALID_PARAMETER;
6291 /* Ignore on pathname based set. */
6292 return NT_STATUS_OK;
6295 position_information = (uint64_t)IVAL(pdata,0);
6296 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6298 DEBUG(10,("smb_file_position_information: Set file position "
6299 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6300 (double)position_information));
6301 fsp->fh->position_information = position_information;
6302 return NT_STATUS_OK;
6305 /****************************************************************************
6306 Deal with SMB_FILE_MODE_INFORMATION.
6307 ****************************************************************************/
6309 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6315 if (total_data < 4) {
6316 return NT_STATUS_INVALID_PARAMETER;
6318 mode = IVAL(pdata,0);
6319 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6320 return NT_STATUS_INVALID_PARAMETER;
6322 return NT_STATUS_OK;
6325 /****************************************************************************
6326 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6327 ****************************************************************************/
6329 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6330 struct smb_request *req,
6333 const struct smb_filename *smb_fname)
6335 char *link_target = NULL;
6336 const char *newname = smb_fname->base_name;
6337 TALLOC_CTX *ctx = talloc_tos();
6339 /* Set a symbolic link. */
6340 /* Don't allow this if follow links is false. */
6342 if (total_data == 0) {
6343 return NT_STATUS_INVALID_PARAMETER;
6346 if (!lp_follow_symlinks(SNUM(conn))) {
6347 return NT_STATUS_ACCESS_DENIED;
6350 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6351 total_data, STR_TERMINATE);
6354 return NT_STATUS_INVALID_PARAMETER;
6357 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6358 newname, link_target ));
6360 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6361 return map_nt_error_from_unix(errno);
6364 return NT_STATUS_OK;
6367 /****************************************************************************
6368 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6369 ****************************************************************************/
6371 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6372 struct smb_request *req,
6373 const char *pdata, int total_data,
6374 struct smb_filename *smb_fname_new)
6376 char *oldname = NULL;
6377 struct smb_filename *smb_fname_old = NULL;
6378 uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
6379 TALLOC_CTX *ctx = talloc_tos();
6380 NTSTATUS status = NT_STATUS_OK;
6382 /* Set a hard link. */
6383 if (total_data == 0) {
6384 return NT_STATUS_INVALID_PARAMETER;
6387 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6388 total_data, STR_TERMINATE, &status);
6389 if (!NT_STATUS_IS_OK(status)) {
6393 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6394 smb_fname_str_dbg(smb_fname_new), oldname));
6396 status = filename_convert(ctx,
6398 req->flags2 & FLAGS2_DFS_PATHNAMES,
6403 if (!NT_STATUS_IS_OK(status)) {
6407 return hardlink_internals(ctx, conn, req, false,
6408 smb_fname_old, smb_fname_new);
6411 /****************************************************************************
6412 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6413 ****************************************************************************/
6415 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6416 struct smb_request *req,
6420 struct smb_filename *smb_fname_src)
6424 char *newname = NULL;
6425 struct smb_filename *smb_fname_dst = NULL;
6426 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6427 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
6428 NTSTATUS status = NT_STATUS_OK;
6429 TALLOC_CTX *ctx = talloc_tos();
6432 return NT_STATUS_INVALID_HANDLE;
6435 if (total_data < 20) {
6436 return NT_STATUS_INVALID_PARAMETER;
6439 overwrite = (CVAL(pdata,0) ? True : False);
6440 len = IVAL(pdata,16);
6442 if (len > (total_data - 20) || (len == 0)) {
6443 return NT_STATUS_INVALID_PARAMETER;
6446 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6447 &pdata[20], len, STR_TERMINATE,
6449 if (!NT_STATUS_IS_OK(status)) {
6453 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6456 status = filename_convert(ctx,
6458 req->flags2 & FLAGS2_DFS_PATHNAMES,
6463 if (!NT_STATUS_IS_OK(status)) {
6467 if (fsp->base_fsp) {
6468 /* newname must be a stream name. */
6469 if (newname[0] != ':') {
6470 return NT_STATUS_NOT_SUPPORTED;
6473 /* Create an smb_fname to call rename_internals_fsp() with. */
6474 smb_fname_dst = synthetic_smb_fname(
6475 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6477 if (smb_fname_dst == NULL) {
6478 status = NT_STATUS_NO_MEMORY;
6483 * Set the original last component, since
6484 * rename_internals_fsp() requires it.
6486 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6488 if (smb_fname_dst->original_lcomp == NULL) {
6489 status = NT_STATUS_NO_MEMORY;
6495 DEBUG(10,("smb2_file_rename_information: "
6496 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6497 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6498 smb_fname_str_dbg(smb_fname_dst)));
6499 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6500 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6504 TALLOC_FREE(smb_fname_dst);
6508 static NTSTATUS smb_file_link_information(connection_struct *conn,
6509 struct smb_request *req,
6513 struct smb_filename *smb_fname_src)
6517 char *newname = NULL;
6518 struct smb_filename *smb_fname_dst = NULL;
6519 NTSTATUS status = NT_STATUS_OK;
6520 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6521 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
6522 TALLOC_CTX *ctx = talloc_tos();
6525 return NT_STATUS_INVALID_HANDLE;
6528 if (total_data < 20) {
6529 return NT_STATUS_INVALID_PARAMETER;
6532 overwrite = (CVAL(pdata,0) ? true : false);
6533 len = IVAL(pdata,16);
6535 if (len > (total_data - 20) || (len == 0)) {
6536 return NT_STATUS_INVALID_PARAMETER;
6539 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6540 &pdata[20], len, STR_TERMINATE,
6542 if (!NT_STATUS_IS_OK(status)) {
6546 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6549 status = filename_convert(ctx,
6551 req->flags2 & FLAGS2_DFS_PATHNAMES,
6556 if (!NT_STATUS_IS_OK(status)) {
6560 if (fsp->base_fsp) {
6561 /* No stream names. */
6562 return NT_STATUS_NOT_SUPPORTED;
6565 DEBUG(10,("smb_file_link_information: "
6566 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6567 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6568 smb_fname_str_dbg(smb_fname_dst)));
6569 status = hardlink_internals(ctx,
6576 TALLOC_FREE(smb_fname_dst);
6580 /****************************************************************************
6581 Deal with SMB_FILE_RENAME_INFORMATION.
6582 ****************************************************************************/
6584 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6585 struct smb_request *req,
6589 struct smb_filename *smb_fname_src)
6594 char *newname = NULL;
6595 struct smb_filename *smb_fname_dst = NULL;
6596 bool dest_has_wcard = False;
6597 NTSTATUS status = NT_STATUS_OK;
6599 TALLOC_CTX *ctx = talloc_tos();
6601 if (total_data < 13) {
6602 return NT_STATUS_INVALID_PARAMETER;
6605 overwrite = (CVAL(pdata,0) ? True : False);
6606 root_fid = IVAL(pdata,4);
6607 len = IVAL(pdata,8);
6609 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6610 return NT_STATUS_INVALID_PARAMETER;
6613 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6616 if (!NT_STATUS_IS_OK(status)) {
6620 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6623 status = resolve_dfspath_wcard(ctx, conn,
6624 req->flags2 & FLAGS2_DFS_PATHNAMES,
6627 !conn->sconn->using_smb2,
6630 if (!NT_STATUS_IS_OK(status)) {
6634 /* Check the new name has no '/' characters. */
6635 if (strchr_m(newname, '/')) {
6636 return NT_STATUS_NOT_SUPPORTED;
6639 if (fsp && fsp->base_fsp) {
6640 /* newname must be a stream name. */
6641 if (newname[0] != ':') {
6642 return NT_STATUS_NOT_SUPPORTED;
6645 /* Create an smb_fname to call rename_internals_fsp() with. */
6646 smb_fname_dst = synthetic_smb_fname(
6647 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6649 if (smb_fname_dst == NULL) {
6650 status = NT_STATUS_NO_MEMORY;
6655 * Set the original last component, since
6656 * rename_internals_fsp() requires it.
6658 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6660 if (smb_fname_dst->original_lcomp == NULL) {
6661 status = NT_STATUS_NO_MEMORY;
6667 * Build up an smb_fname_dst based on the filename passed in.
6668 * We basically just strip off the last component, and put on
6669 * the newname instead.
6671 char *base_name = NULL;
6673 /* newname must *not* be a stream name. */
6674 if (newname[0] == ':') {
6675 return NT_STATUS_NOT_SUPPORTED;
6679 * Strip off the last component (filename) of the path passed
6682 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6684 return NT_STATUS_NO_MEMORY;
6686 p = strrchr_m(base_name, '/');
6690 base_name = talloc_strdup(ctx, "");
6692 return NT_STATUS_NO_MEMORY;
6695 /* Append the new name. */
6696 base_name = talloc_asprintf_append(base_name,
6700 return NT_STATUS_NO_MEMORY;
6703 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6706 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6709 /* If an error we expect this to be
6710 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6712 if (!NT_STATUS_IS_OK(status)) {
6713 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6717 /* Create an smb_fname to call rename_internals_fsp() */
6718 smb_fname_dst = synthetic_smb_fname(
6719 ctx, base_name, NULL, NULL);
6720 if (smb_fname_dst == NULL) {
6721 status = NT_STATUS_NO_MEMORY;
6728 DEBUG(10,("smb_file_rename_information: "
6729 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6730 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6731 smb_fname_str_dbg(smb_fname_dst)));
6732 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6735 DEBUG(10,("smb_file_rename_information: "
6736 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6737 smb_fname_str_dbg(smb_fname_src),
6738 smb_fname_str_dbg(smb_fname_dst)));
6739 status = rename_internals(ctx, conn, req, smb_fname_src,
6740 smb_fname_dst, 0, overwrite, false,
6742 FILE_WRITE_ATTRIBUTES);
6745 TALLOC_FREE(smb_fname_dst);
6749 /****************************************************************************
6750 Deal with SMB_SET_POSIX_ACL.
6751 ****************************************************************************/
6753 #if defined(HAVE_POSIX_ACLS)
6754 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6758 const struct smb_filename *smb_fname)
6760 uint16_t posix_acl_version;
6761 uint16_t num_file_acls;
6762 uint16_t num_def_acls;
6763 bool valid_file_acls = True;
6764 bool valid_def_acls = True;
6766 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6767 return NT_STATUS_INVALID_PARAMETER;
6769 posix_acl_version = SVAL(pdata,0);
6770 num_file_acls = SVAL(pdata,2);
6771 num_def_acls = SVAL(pdata,4);
6773 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6774 valid_file_acls = False;
6778 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6779 valid_def_acls = False;
6783 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6784 return NT_STATUS_INVALID_PARAMETER;
6787 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6788 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6789 return NT_STATUS_INVALID_PARAMETER;
6792 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6793 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6794 (unsigned int)num_file_acls,
6795 (unsigned int)num_def_acls));
6797 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6798 smb_fname->base_name, num_file_acls,
6799 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6800 return map_nt_error_from_unix(errno);
6803 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6804 smb_fname->base_name, &smb_fname->st, num_def_acls,
6805 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6806 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6807 return map_nt_error_from_unix(errno);
6809 return NT_STATUS_OK;
6813 /****************************************************************************
6814 Deal with SMB_SET_POSIX_LOCK.
6815 ****************************************************************************/
6817 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6818 struct smb_request *req,
6826 bool blocking_lock = False;
6827 enum brl_type lock_type;
6829 NTSTATUS status = NT_STATUS_OK;
6831 if (fsp == NULL || fsp->fh->fd == -1) {
6832 return NT_STATUS_INVALID_HANDLE;
6835 if (total_data != POSIX_LOCK_DATA_SIZE) {
6836 return NT_STATUS_INVALID_PARAMETER;
6839 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6840 case POSIX_LOCK_TYPE_READ:
6841 lock_type = READ_LOCK;
6843 case POSIX_LOCK_TYPE_WRITE:
6844 /* Return the right POSIX-mappable error code for files opened read-only. */
6845 if (!fsp->can_write) {
6846 return NT_STATUS_INVALID_HANDLE;
6848 lock_type = WRITE_LOCK;
6850 case POSIX_LOCK_TYPE_UNLOCK:
6851 lock_type = UNLOCK_LOCK;
6854 return NT_STATUS_INVALID_PARAMETER;
6857 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6858 blocking_lock = False;
6859 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6860 blocking_lock = True;
6862 return NT_STATUS_INVALID_PARAMETER;
6865 if (!lp_blocking_locks(SNUM(conn))) {
6866 blocking_lock = False;
6869 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6870 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6871 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6872 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6873 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6875 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6876 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6878 (unsigned int)lock_type,
6879 (unsigned long long)smblctx,
6883 if (lock_type == UNLOCK_LOCK) {
6884 status = do_unlock(req->sconn->msg_ctx,
6891 uint64_t block_smblctx;
6893 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6904 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6906 * A blocking lock was requested. Package up
6907 * this smb into a queued request and push it
6908 * onto the blocking lock queue.
6910 if(push_blocking_lock_request(br_lck,
6913 -1, /* infinite timeout. */
6921 TALLOC_FREE(br_lck);
6925 TALLOC_FREE(br_lck);
6931 /****************************************************************************
6932 Deal with SMB_SET_FILE_BASIC_INFO.
6933 ****************************************************************************/
6935 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6939 const struct smb_filename *smb_fname)
6941 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6942 struct smb_file_time ft;
6943 uint32_t dosmode = 0;
6944 NTSTATUS status = NT_STATUS_OK;
6948 if (total_data < 36) {
6949 return NT_STATUS_INVALID_PARAMETER;
6952 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6953 if (!NT_STATUS_IS_OK(status)) {
6957 /* Set the attributes */
6958 dosmode = IVAL(pdata,32);
6959 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6960 if (!NT_STATUS_IS_OK(status)) {
6965 ft.create_time = interpret_long_date(pdata);
6968 ft.atime = interpret_long_date(pdata+8);
6971 ft.mtime = interpret_long_date(pdata+16);
6974 ft.ctime = interpret_long_date(pdata+24);
6976 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6977 smb_fname_str_dbg(smb_fname)));
6979 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6983 /****************************************************************************
6984 Deal with SMB_INFO_STANDARD.
6985 ****************************************************************************/
6987 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6991 const struct smb_filename *smb_fname)
6994 struct smb_file_time ft;
6998 if (total_data < 12) {
6999 return NT_STATUS_INVALID_PARAMETER;
7003 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7005 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7007 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7009 DEBUG(10,("smb_set_info_standard: file %s\n",
7010 smb_fname_str_dbg(smb_fname)));
7012 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7013 if (!NT_STATUS_IS_OK(status)) {
7017 return smb_set_file_time(conn,
7024 /****************************************************************************
7025 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7026 ****************************************************************************/
7028 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7029 struct smb_request *req,
7033 struct smb_filename *smb_fname)
7035 uint64_t allocation_size = 0;
7036 NTSTATUS status = NT_STATUS_OK;
7037 files_struct *new_fsp = NULL;
7039 if (!VALID_STAT(smb_fname->st)) {
7040 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7043 if (total_data < 8) {
7044 return NT_STATUS_INVALID_PARAMETER;
7047 allocation_size = (uint64_t)IVAL(pdata,0);
7048 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7049 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7050 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7051 (double)allocation_size));
7053 if (allocation_size) {
7054 allocation_size = smb_roundup(conn, allocation_size);
7057 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7058 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7059 (double)allocation_size));
7061 if (fsp && fsp->fh->fd != -1) {
7062 /* Open file handle. */
7063 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7064 return NT_STATUS_ACCESS_DENIED;
7067 /* Only change if needed. */
7068 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7069 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7070 return map_nt_error_from_unix(errno);
7073 /* But always update the time. */
7075 * This is equivalent to a write. Ensure it's seen immediately
7076 * if there are no pending writes.
7078 trigger_write_time_update_immediate(fsp);
7079 return NT_STATUS_OK;
7082 /* Pathname or stat or directory file. */
7083 status = SMB_VFS_CREATE_FILE(
7086 0, /* root_dir_fid */
7087 smb_fname, /* fname */
7088 FILE_WRITE_DATA, /* access_mask */
7089 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7091 FILE_OPEN, /* create_disposition*/
7092 0, /* create_options */
7093 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7094 0, /* oplock_request */
7096 0, /* allocation_size */
7097 0, /* private_flags */
7100 &new_fsp, /* result */
7102 NULL, NULL); /* create context */
7104 if (!NT_STATUS_IS_OK(status)) {
7105 /* NB. We check for open_was_deferred in the caller. */
7109 /* Only change if needed. */
7110 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7111 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7112 status = map_nt_error_from_unix(errno);
7113 close_file(req, new_fsp, NORMAL_CLOSE);
7118 /* Changing the allocation size should set the last mod time. */
7120 * This is equivalent to a write. Ensure it's seen immediately
7121 * if there are no pending writes.
7123 trigger_write_time_update_immediate(new_fsp);
7124 close_file(req, new_fsp, NORMAL_CLOSE);
7125 return NT_STATUS_OK;
7128 /****************************************************************************
7129 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7130 ****************************************************************************/
7132 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7133 struct smb_request *req,
7137 const struct smb_filename *smb_fname,
7138 bool fail_after_createfile)
7142 if (total_data < 8) {
7143 return NT_STATUS_INVALID_PARAMETER;
7146 size = IVAL(pdata,0);
7147 size |= (((off_t)IVAL(pdata,4)) << 32);
7148 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7149 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7152 return smb_set_file_size(conn, req,
7157 fail_after_createfile);
7160 /****************************************************************************
7161 Allow a UNIX info mknod.
7162 ****************************************************************************/
7164 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7167 const struct smb_filename *smb_fname)
7169 uint32_t file_type = IVAL(pdata,56);
7170 #if defined(HAVE_MAKEDEV)
7171 uint32_t dev_major = IVAL(pdata,60);
7172 uint32_t dev_minor = IVAL(pdata,68);
7174 SMB_DEV_T dev = (SMB_DEV_T)0;
7175 uint32_t raw_unixmode = IVAL(pdata,84);
7179 if (total_data < 100) {
7180 return NT_STATUS_INVALID_PARAMETER;
7183 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7184 PERM_NEW_FILE, &unixmode);
7185 if (!NT_STATUS_IS_OK(status)) {
7189 #if defined(HAVE_MAKEDEV)
7190 dev = makedev(dev_major, dev_minor);
7193 switch (file_type) {
7194 #if defined(S_IFIFO)
7195 case UNIX_TYPE_FIFO:
7196 unixmode |= S_IFIFO;
7199 #if defined(S_IFSOCK)
7200 case UNIX_TYPE_SOCKET:
7201 unixmode |= S_IFSOCK;
7204 #if defined(S_IFCHR)
7205 case UNIX_TYPE_CHARDEV:
7206 unixmode |= S_IFCHR;
7209 #if defined(S_IFBLK)
7210 case UNIX_TYPE_BLKDEV:
7211 unixmode |= S_IFBLK;
7215 return NT_STATUS_INVALID_PARAMETER;
7218 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7219 "%.0f mode 0%o for file %s\n", (double)dev,
7220 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7222 /* Ok - do the mknod. */
7223 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7224 return map_nt_error_from_unix(errno);
7227 /* If any of the other "set" calls fail we
7228 * don't want to end up with a half-constructed mknod.
7231 if (lp_inherit_permissions(SNUM(conn))) {
7233 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7235 return NT_STATUS_NO_MEMORY;
7237 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7239 TALLOC_FREE(parent);
7242 return NT_STATUS_OK;
7245 /****************************************************************************
7246 Deal with SMB_SET_FILE_UNIX_BASIC.
7247 ****************************************************************************/
7249 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7250 struct smb_request *req,
7254 const struct smb_filename *smb_fname)
7256 struct smb_file_time ft;
7257 uint32_t raw_unixmode;
7260 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7261 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7262 NTSTATUS status = NT_STATUS_OK;
7263 bool delete_on_fail = False;
7264 enum perm_type ptype;
7265 files_struct *all_fsps = NULL;
7266 bool modify_mtime = true;
7268 struct smb_filename *smb_fname_tmp = NULL;
7269 SMB_STRUCT_STAT sbuf;
7273 if (total_data < 100) {
7274 return NT_STATUS_INVALID_PARAMETER;
7277 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7278 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7279 size=IVAL(pdata,0); /* first 8 Bytes are size */
7280 size |= (((off_t)IVAL(pdata,4)) << 32);
7283 ft.atime = interpret_long_date(pdata+24); /* access_time */
7284 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7285 set_owner = (uid_t)IVAL(pdata,40);
7286 set_grp = (gid_t)IVAL(pdata,48);
7287 raw_unixmode = IVAL(pdata,84);
7289 if (VALID_STAT(smb_fname->st)) {
7290 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7291 ptype = PERM_EXISTING_DIR;
7293 ptype = PERM_EXISTING_FILE;
7296 ptype = PERM_NEW_FILE;
7299 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7301 if (!NT_STATUS_IS_OK(status)) {
7305 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7306 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7307 smb_fname_str_dbg(smb_fname), (double)size,
7308 (unsigned int)set_owner, (unsigned int)set_grp,
7309 (int)raw_unixmode));
7311 sbuf = smb_fname->st;
7313 if (!VALID_STAT(sbuf)) {
7315 * The only valid use of this is to create character and block
7316 * devices, and named pipes. This is deprecated (IMHO) and
7317 * a new info level should be used for mknod. JRA.
7320 status = smb_unix_mknod(conn,
7324 if (!NT_STATUS_IS_OK(status)) {
7328 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7329 if (smb_fname_tmp == NULL) {
7330 return NT_STATUS_NO_MEMORY;
7333 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7334 status = map_nt_error_from_unix(errno);
7335 TALLOC_FREE(smb_fname_tmp);
7336 SMB_VFS_UNLINK(conn, smb_fname);
7340 sbuf = smb_fname_tmp->st;
7341 smb_fname = smb_fname_tmp;
7343 /* Ensure we don't try and change anything else. */
7344 raw_unixmode = SMB_MODE_NO_CHANGE;
7345 size = get_file_size_stat(&sbuf);
7346 ft.atime = sbuf.st_ex_atime;
7347 ft.mtime = sbuf.st_ex_mtime;
7349 * We continue here as we might want to change the
7352 delete_on_fail = True;
7356 /* Horrible backwards compatibility hack as an old server bug
7357 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7361 size = get_file_size_stat(&sbuf);
7366 * Deal with the UNIX specific mode set.
7369 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7372 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7373 "setting mode 0%o for file %s\n",
7374 (unsigned int)unixmode,
7375 smb_fname_str_dbg(smb_fname)));
7376 if (fsp && fsp->fh->fd != -1) {
7377 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7379 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7382 return map_nt_error_from_unix(errno);
7387 * Deal with the UNIX specific uid set.
7390 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7391 (sbuf.st_ex_uid != set_owner)) {
7394 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7395 "changing owner %u for path %s\n",
7396 (unsigned int)set_owner,
7397 smb_fname_str_dbg(smb_fname)));
7399 if (fsp && fsp->fh->fd != -1) {
7400 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7403 * UNIX extensions calls must always operate
7406 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7407 set_owner, (gid_t)-1);
7411 status = map_nt_error_from_unix(errno);
7412 if (delete_on_fail) {
7413 SMB_VFS_UNLINK(conn, smb_fname);
7420 * Deal with the UNIX specific gid set.
7423 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7424 (sbuf.st_ex_gid != set_grp)) {
7427 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7428 "changing group %u for file %s\n",
7429 (unsigned int)set_owner,
7430 smb_fname_str_dbg(smb_fname)));
7431 if (fsp && fsp->fh->fd != -1) {
7432 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7435 * UNIX extensions calls must always operate
7438 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7442 status = map_nt_error_from_unix(errno);
7443 if (delete_on_fail) {
7444 SMB_VFS_UNLINK(conn, smb_fname);
7450 /* Deal with any size changes. */
7452 status = smb_set_file_size(conn, req,
7458 if (!NT_STATUS_IS_OK(status)) {
7462 /* Deal with any time changes. */
7463 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7464 /* No change, don't cancel anything. */
7468 id = vfs_file_id_from_sbuf(conn, &sbuf);
7469 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7470 all_fsps = file_find_di_next(all_fsps)) {
7472 * We're setting the time explicitly for UNIX.
7473 * Cancel any pending changes over all handles.
7475 all_fsps->update_write_time_on_close = false;
7476 TALLOC_FREE(all_fsps->update_write_time_event);
7480 * Override the "setting_write_time"
7481 * parameter here as it almost does what
7482 * we need. Just remember if we modified
7483 * mtime and send the notify ourselves.
7485 if (null_timespec(ft.mtime)) {
7486 modify_mtime = false;
7489 status = smb_set_file_time(conn,
7495 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7496 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7501 /****************************************************************************
7502 Deal with SMB_SET_FILE_UNIX_INFO2.
7503 ****************************************************************************/
7505 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7506 struct smb_request *req,
7510 const struct smb_filename *smb_fname)
7513 uint32_t smb_fflags;
7516 if (total_data < 116) {
7517 return NT_STATUS_INVALID_PARAMETER;
7520 /* Start by setting all the fields that are common between UNIX_BASIC
7523 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7525 if (!NT_STATUS_IS_OK(status)) {
7529 smb_fflags = IVAL(pdata, 108);
7530 smb_fmask = IVAL(pdata, 112);
7532 /* NB: We should only attempt to alter the file flags if the client
7533 * sends a non-zero mask.
7535 if (smb_fmask != 0) {
7536 int stat_fflags = 0;
7538 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7539 smb_fmask, &stat_fflags)) {
7540 /* Client asked to alter a flag we don't understand. */
7541 return NT_STATUS_INVALID_PARAMETER;
7544 if (fsp && fsp->fh->fd != -1) {
7545 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7546 return NT_STATUS_NOT_SUPPORTED;
7548 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7549 stat_fflags) != 0) {
7550 return map_nt_error_from_unix(errno);
7555 /* XXX: need to add support for changing the create_time here. You
7556 * can do this for paths on Darwin with setattrlist(2). The right way
7557 * to hook this up is probably by extending the VFS utimes interface.
7560 return NT_STATUS_OK;
7563 /****************************************************************************
7564 Create a directory with POSIX semantics.
7565 ****************************************************************************/
7567 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7568 struct smb_request *req,
7571 struct smb_filename *smb_fname,
7572 int *pdata_return_size)
7574 NTSTATUS status = NT_STATUS_OK;
7575 uint32_t raw_unixmode = 0;
7576 uint32_t mod_unixmode = 0;
7577 mode_t unixmode = (mode_t)0;
7578 files_struct *fsp = NULL;
7579 uint16_t info_level_return = 0;
7581 char *pdata = *ppdata;
7583 if (total_data < 18) {
7584 return NT_STATUS_INVALID_PARAMETER;
7587 raw_unixmode = IVAL(pdata,8);
7588 /* Next 4 bytes are not yet defined. */
7590 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7591 PERM_NEW_DIR, &unixmode);
7592 if (!NT_STATUS_IS_OK(status)) {
7596 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7598 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7599 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7601 status = SMB_VFS_CREATE_FILE(
7604 0, /* root_dir_fid */
7605 smb_fname, /* fname */
7606 FILE_READ_ATTRIBUTES, /* access_mask */
7607 FILE_SHARE_NONE, /* share_access */
7608 FILE_CREATE, /* create_disposition*/
7609 FILE_DIRECTORY_FILE, /* create_options */
7610 mod_unixmode, /* file_attributes */
7611 0, /* oplock_request */
7613 0, /* allocation_size */
7614 0, /* private_flags */
7619 NULL, NULL); /* create context */
7621 if (NT_STATUS_IS_OK(status)) {
7622 close_file(req, fsp, NORMAL_CLOSE);
7625 info_level_return = SVAL(pdata,16);
7627 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7628 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7629 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7630 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7632 *pdata_return_size = 12;
7635 /* Realloc the data size */
7636 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7637 if (*ppdata == NULL) {
7638 *pdata_return_size = 0;
7639 return NT_STATUS_NO_MEMORY;
7643 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7644 SSVAL(pdata,2,0); /* No fnum. */
7645 SIVAL(pdata,4,info); /* Was directory created. */
7647 switch (info_level_return) {
7648 case SMB_QUERY_FILE_UNIX_BASIC:
7649 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7650 SSVAL(pdata,10,0); /* Padding. */
7651 store_file_unix_basic(conn, pdata + 12, fsp,
7654 case SMB_QUERY_FILE_UNIX_INFO2:
7655 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7656 SSVAL(pdata,10,0); /* Padding. */
7657 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7661 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7662 SSVAL(pdata,10,0); /* Padding. */
7669 /****************************************************************************
7670 Open/Create a file with POSIX semantics.
7671 ****************************************************************************/
7673 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7674 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7676 static NTSTATUS smb_posix_open(connection_struct *conn,
7677 struct smb_request *req,
7680 struct smb_filename *smb_fname,
7681 int *pdata_return_size)
7683 bool extended_oplock_granted = False;
7684 char *pdata = *ppdata;
7686 uint32_t wire_open_mode = 0;
7687 uint32_t raw_unixmode = 0;
7688 uint32_t mod_unixmode = 0;
7689 uint32_t create_disp = 0;
7690 uint32_t access_mask = 0;
7691 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7692 NTSTATUS status = NT_STATUS_OK;
7693 mode_t unixmode = (mode_t)0;
7694 files_struct *fsp = NULL;
7695 int oplock_request = 0;
7697 uint16_t info_level_return = 0;
7699 if (total_data < 18) {
7700 return NT_STATUS_INVALID_PARAMETER;
7703 flags = IVAL(pdata,0);
7704 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7705 if (oplock_request) {
7706 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7709 wire_open_mode = IVAL(pdata,4);
7711 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7712 return smb_posix_mkdir(conn, req,
7719 switch (wire_open_mode & SMB_ACCMODE) {
7721 access_mask = SMB_O_RDONLY_MAPPING;
7724 access_mask = SMB_O_WRONLY_MAPPING;
7727 access_mask = (SMB_O_RDONLY_MAPPING|
7728 SMB_O_WRONLY_MAPPING);
7731 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7732 (unsigned int)wire_open_mode ));
7733 return NT_STATUS_INVALID_PARAMETER;
7736 wire_open_mode &= ~SMB_ACCMODE;
7738 /* First take care of O_CREAT|O_EXCL interactions. */
7739 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7740 case (SMB_O_CREAT | SMB_O_EXCL):
7741 /* File exists fail. File not exist create. */
7742 create_disp = FILE_CREATE;
7745 /* File exists open. File not exist create. */
7746 create_disp = FILE_OPEN_IF;
7749 /* O_EXCL on its own without O_CREAT is undefined.
7750 We deliberately ignore it as some versions of
7751 Linux CIFSFS can send a bare O_EXCL on the
7752 wire which other filesystems in the kernel
7753 ignore. See bug 9519 for details. */
7758 /* File exists open. File not exist fail. */
7759 create_disp = FILE_OPEN;
7762 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7763 (unsigned int)wire_open_mode ));
7764 return NT_STATUS_INVALID_PARAMETER;
7767 /* Next factor in the effects of O_TRUNC. */
7768 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7770 if (wire_open_mode & SMB_O_TRUNC) {
7771 switch (create_disp) {
7773 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7774 /* Leave create_disp alone as
7775 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7777 /* File exists fail. File not exist create. */
7780 /* SMB_O_CREAT | SMB_O_TRUNC */
7781 /* File exists overwrite. File not exist create. */
7782 create_disp = FILE_OVERWRITE_IF;
7786 /* File exists overwrite. File not exist fail. */
7787 create_disp = FILE_OVERWRITE;
7790 /* Cannot get here. */
7791 smb_panic("smb_posix_open: logic error");
7792 return NT_STATUS_INVALID_PARAMETER;
7796 raw_unixmode = IVAL(pdata,8);
7797 /* Next 4 bytes are not yet defined. */
7799 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7800 (VALID_STAT(smb_fname->st) ?
7801 PERM_EXISTING_FILE : PERM_NEW_FILE),
7804 if (!NT_STATUS_IS_OK(status)) {
7808 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7810 if (wire_open_mode & SMB_O_SYNC) {
7811 create_options |= FILE_WRITE_THROUGH;
7813 if (wire_open_mode & SMB_O_APPEND) {
7814 access_mask |= FILE_APPEND_DATA;
7816 if (wire_open_mode & SMB_O_DIRECT) {
7817 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7820 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7821 VALID_STAT_OF_DIR(smb_fname->st)) {
7822 if (access_mask != SMB_O_RDONLY_MAPPING) {
7823 return NT_STATUS_FILE_IS_A_DIRECTORY;
7825 create_options &= ~FILE_NON_DIRECTORY_FILE;
7826 create_options |= FILE_DIRECTORY_FILE;
7829 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7830 smb_fname_str_dbg(smb_fname),
7831 (unsigned int)wire_open_mode,
7832 (unsigned int)unixmode ));
7834 status = SMB_VFS_CREATE_FILE(
7837 0, /* root_dir_fid */
7838 smb_fname, /* fname */
7839 access_mask, /* access_mask */
7840 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7842 create_disp, /* create_disposition*/
7843 create_options, /* create_options */
7844 mod_unixmode, /* file_attributes */
7845 oplock_request, /* oplock_request */
7847 0, /* allocation_size */
7848 0, /* private_flags */
7853 NULL, NULL); /* create context */
7855 if (!NT_STATUS_IS_OK(status)) {
7859 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7860 extended_oplock_granted = True;
7863 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7864 extended_oplock_granted = True;
7867 info_level_return = SVAL(pdata,16);
7869 /* Allocate the correct return size. */
7871 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7872 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7873 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7874 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7876 *pdata_return_size = 12;
7879 /* Realloc the data size */
7880 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7881 if (*ppdata == NULL) {
7882 close_file(req, fsp, ERROR_CLOSE);
7883 *pdata_return_size = 0;
7884 return NT_STATUS_NO_MEMORY;
7888 if (extended_oplock_granted) {
7889 if (flags & REQUEST_BATCH_OPLOCK) {
7890 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7892 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7894 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7895 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7897 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7900 SSVAL(pdata,2,fsp->fnum);
7901 SIVAL(pdata,4,info); /* Was file created etc. */
7903 switch (info_level_return) {
7904 case SMB_QUERY_FILE_UNIX_BASIC:
7905 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7906 SSVAL(pdata,10,0); /* padding. */
7907 store_file_unix_basic(conn, pdata + 12, fsp,
7910 case SMB_QUERY_FILE_UNIX_INFO2:
7911 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7912 SSVAL(pdata,10,0); /* padding. */
7913 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7917 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7918 SSVAL(pdata,10,0); /* padding. */
7921 return NT_STATUS_OK;
7924 /****************************************************************************
7925 Delete a file with POSIX semantics.
7926 ****************************************************************************/
7928 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7929 struct smb_request *req,
7932 struct smb_filename *smb_fname)
7934 NTSTATUS status = NT_STATUS_OK;
7935 files_struct *fsp = NULL;
7939 int create_options = 0;
7941 struct share_mode_lock *lck = NULL;
7943 if (total_data < 2) {
7944 return NT_STATUS_INVALID_PARAMETER;
7947 flags = SVAL(pdata,0);
7949 if (!VALID_STAT(smb_fname->st)) {
7950 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7953 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7954 !VALID_STAT_OF_DIR(smb_fname->st)) {
7955 return NT_STATUS_NOT_A_DIRECTORY;
7958 DEBUG(10,("smb_posix_unlink: %s %s\n",
7959 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7960 smb_fname_str_dbg(smb_fname)));
7962 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7963 create_options |= FILE_DIRECTORY_FILE;
7966 status = SMB_VFS_CREATE_FILE(
7969 0, /* root_dir_fid */
7970 smb_fname, /* fname */
7971 DELETE_ACCESS, /* access_mask */
7972 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7974 FILE_OPEN, /* create_disposition*/
7975 create_options, /* create_options */
7976 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7977 0, /* oplock_request */
7979 0, /* allocation_size */
7980 0, /* private_flags */
7985 NULL, NULL); /* create context */
7987 if (!NT_STATUS_IS_OK(status)) {
7992 * Don't lie to client. If we can't really delete due to
7993 * non-POSIX opens return SHARING_VIOLATION.
7996 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7998 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7999 "lock for file %s\n", fsp_str_dbg(fsp)));
8000 close_file(req, fsp, NORMAL_CLOSE);
8001 return NT_STATUS_INVALID_PARAMETER;
8005 * See if others still have the file open. If this is the case, then
8006 * don't delete. If all opens are POSIX delete we can set the delete
8007 * on close disposition.
8009 for (i=0; i<lck->data->num_share_modes; i++) {
8010 struct share_mode_entry *e = &lck->data->share_modes[i];
8011 if (is_valid_share_mode_entry(e)) {
8012 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8015 if (share_mode_stale_pid(lck->data, i)) {
8018 /* Fail with sharing violation. */
8020 close_file(req, fsp, NORMAL_CLOSE);
8021 return NT_STATUS_SHARING_VIOLATION;
8026 * Set the delete on close.
8028 status = smb_set_file_disposition_info(conn,
8036 if (!NT_STATUS_IS_OK(status)) {
8037 close_file(req, fsp, NORMAL_CLOSE);
8040 return close_file(req, fsp, NORMAL_CLOSE);
8043 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8044 struct smb_request *req,
8045 TALLOC_CTX *mem_ctx,
8046 uint16_t info_level,
8048 struct smb_filename *smb_fname,
8049 char **ppdata, int total_data,
8052 char *pdata = *ppdata;
8053 NTSTATUS status = NT_STATUS_OK;
8054 int data_return_size = 0;
8058 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8059 return NT_STATUS_INVALID_LEVEL;
8062 if (!CAN_WRITE(conn)) {
8063 /* Allow POSIX opens. The open path will deny
8064 * any non-readonly opens. */
8065 if (info_level != SMB_POSIX_PATH_OPEN) {
8066 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8070 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8071 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8073 info_level, total_data));
8075 switch (info_level) {
8077 case SMB_INFO_STANDARD:
8079 status = smb_set_info_standard(conn,
8087 case SMB_INFO_SET_EA:
8089 status = smb_info_set_ea(conn,
8097 case SMB_SET_FILE_BASIC_INFO:
8098 case SMB_FILE_BASIC_INFORMATION:
8100 status = smb_set_file_basic_info(conn,
8108 case SMB_FILE_ALLOCATION_INFORMATION:
8109 case SMB_SET_FILE_ALLOCATION_INFO:
8111 status = smb_set_file_allocation_info(conn, req,
8119 case SMB_FILE_END_OF_FILE_INFORMATION:
8120 case SMB_SET_FILE_END_OF_FILE_INFO:
8123 * XP/Win7 both fail after the createfile with
8124 * SMB_SET_FILE_END_OF_FILE_INFO but not
8125 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8126 * The level is known here, so pass it down
8130 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8132 status = smb_set_file_end_of_file_info(conn, req,
8141 case SMB_FILE_DISPOSITION_INFORMATION:
8142 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8145 /* JRA - We used to just ignore this on a path ?
8146 * Shouldn't this be invalid level on a pathname
8149 if (tran_call != TRANSACT2_SETFILEINFO) {
8150 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8153 status = smb_set_file_disposition_info(conn,
8161 case SMB_FILE_POSITION_INFORMATION:
8163 status = smb_file_position_information(conn,
8170 case SMB_FILE_FULL_EA_INFORMATION:
8172 status = smb_set_file_full_ea_info(conn,
8179 /* From tridge Samba4 :
8180 * MODE_INFORMATION in setfileinfo (I have no
8181 * idea what "mode information" on a file is - it takes a value of 0,
8182 * 2, 4 or 6. What could it be?).
8185 case SMB_FILE_MODE_INFORMATION:
8187 status = smb_file_mode_information(conn,
8194 * CIFS UNIX extensions.
8197 case SMB_SET_FILE_UNIX_BASIC:
8199 status = smb_set_file_unix_basic(conn, req,
8207 case SMB_SET_FILE_UNIX_INFO2:
8209 status = smb_set_file_unix_info2(conn, req,
8217 case SMB_SET_FILE_UNIX_LINK:
8220 /* We must have a pathname for this. */
8221 return NT_STATUS_INVALID_LEVEL;
8223 status = smb_set_file_unix_link(conn, req, pdata,
8224 total_data, smb_fname);
8228 case SMB_SET_FILE_UNIX_HLINK:
8231 /* We must have a pathname for this. */
8232 return NT_STATUS_INVALID_LEVEL;
8234 status = smb_set_file_unix_hlink(conn, req,
8240 case SMB_FILE_RENAME_INFORMATION:
8242 status = smb_file_rename_information(conn, req,
8248 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8250 /* SMB2 rename information. */
8251 status = smb2_file_rename_information(conn, req,
8257 case SMB_FILE_LINK_INFORMATION:
8259 status = smb_file_link_information(conn, req,
8265 #if defined(HAVE_POSIX_ACLS)
8266 case SMB_SET_POSIX_ACL:
8268 status = smb_set_posix_acl(conn,
8277 case SMB_SET_POSIX_LOCK:
8280 return NT_STATUS_INVALID_LEVEL;
8282 status = smb_set_posix_lock(conn, req,
8283 pdata, total_data, fsp);
8287 case SMB_POSIX_PATH_OPEN:
8290 /* We must have a pathname for this. */
8291 return NT_STATUS_INVALID_LEVEL;
8294 status = smb_posix_open(conn, req,
8302 case SMB_POSIX_PATH_UNLINK:
8305 /* We must have a pathname for this. */
8306 return NT_STATUS_INVALID_LEVEL;
8309 status = smb_posix_unlink(conn, req,
8317 return NT_STATUS_INVALID_LEVEL;
8320 if (!NT_STATUS_IS_OK(status)) {
8324 *ret_data_size = data_return_size;
8325 return NT_STATUS_OK;
8328 /****************************************************************************
8329 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8330 ****************************************************************************/
8332 static void call_trans2setfilepathinfo(connection_struct *conn,
8333 struct smb_request *req,
8334 unsigned int tran_call,
8335 char **pparams, int total_params,
8336 char **ppdata, int total_data,
8337 unsigned int max_data_bytes)
8339 char *params = *pparams;
8340 char *pdata = *ppdata;
8341 uint16_t info_level;
8342 struct smb_filename *smb_fname = NULL;
8343 files_struct *fsp = NULL;
8344 NTSTATUS status = NT_STATUS_OK;
8345 int data_return_size = 0;
8348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8352 if (tran_call == TRANSACT2_SETFILEINFO) {
8353 if (total_params < 4) {
8354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8358 fsp = file_fsp(req, SVAL(params,0));
8359 /* Basic check for non-null fsp. */
8360 if (!check_fsp_open(conn, req, fsp)) {
8363 info_level = SVAL(params,2);
8365 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8366 if (smb_fname == NULL) {
8367 reply_nterror(req, NT_STATUS_NO_MEMORY);
8371 if(fsp->fh->fd == -1) {
8373 * This is actually a SETFILEINFO on a directory
8374 * handle (returned from an NT SMB). NT5.0 seems
8375 * to do this call. JRA.
8377 if (INFO_LEVEL_IS_UNIX(info_level)) {
8378 /* Always do lstat for UNIX calls. */
8379 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8380 DEBUG(3,("call_trans2setfilepathinfo: "
8381 "SMB_VFS_LSTAT of %s failed "
8383 smb_fname_str_dbg(smb_fname),
8385 reply_nterror(req, map_nt_error_from_unix(errno));
8389 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8390 DEBUG(3,("call_trans2setfilepathinfo: "
8391 "fileinfo of %s failed (%s)\n",
8392 smb_fname_str_dbg(smb_fname),
8394 reply_nterror(req, map_nt_error_from_unix(errno));
8398 } else if (fsp->print_file) {
8400 * Doing a DELETE_ON_CLOSE should cancel a print job.
8402 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8403 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8405 DEBUG(3,("call_trans2setfilepathinfo: "
8406 "Cancelling print job (%s)\n",
8410 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8416 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8421 * Original code - this is an open file.
8423 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8424 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8425 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8427 reply_nterror(req, map_nt_error_from_unix(errno));
8433 uint32_t ucf_flags = (lp_posix_pathnames() ?
8434 UCF_POSIX_PATHNAMES : 0);
8437 if (total_params < 7) {
8438 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8442 info_level = SVAL(params,0);
8443 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8444 total_params - 6, STR_TERMINATE,
8446 if (!NT_STATUS_IS_OK(status)) {
8447 reply_nterror(req, status);
8451 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8452 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8453 info_level == SMB_FILE_RENAME_INFORMATION ||
8454 info_level == SMB_POSIX_PATH_UNLINK) {
8455 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8458 status = filename_convert(req, conn,
8459 req->flags2 & FLAGS2_DFS_PATHNAMES,
8464 if (!NT_STATUS_IS_OK(status)) {
8465 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8466 reply_botherror(req,
8467 NT_STATUS_PATH_NOT_COVERED,
8468 ERRSRV, ERRbadpath);
8471 reply_nterror(req, status);
8475 if (INFO_LEVEL_IS_UNIX(info_level)) {
8477 * For CIFS UNIX extensions the target name may not exist.
8480 /* Always do lstat for UNIX calls. */
8481 SMB_VFS_LSTAT(conn, smb_fname);
8483 } else if (!VALID_STAT(smb_fname->st) &&
8484 SMB_VFS_STAT(conn, smb_fname)) {
8485 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8487 smb_fname_str_dbg(smb_fname),
8489 reply_nterror(req, map_nt_error_from_unix(errno));
8494 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8495 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8497 info_level,total_data));
8499 /* Realloc the parameter size */
8500 *pparams = (char *)SMB_REALLOC(*pparams,2);
8501 if (*pparams == NULL) {
8502 reply_nterror(req, NT_STATUS_NO_MEMORY);
8509 status = smbd_do_setfilepathinfo(conn, req, req,
8515 if (!NT_STATUS_IS_OK(status)) {
8516 if (open_was_deferred(req->xconn, req->mid)) {
8517 /* We have re-scheduled this call. */
8520 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8521 /* We have re-scheduled this call. */
8524 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8525 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8526 ERRSRV, ERRbadpath);
8529 if (info_level == SMB_POSIX_PATH_OPEN) {
8530 reply_openerror(req, status);
8535 * Invalid EA name needs to return 2 param bytes,
8536 * not a zero-length error packet.
8538 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8539 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8542 reply_nterror(req, status);
8547 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8553 /****************************************************************************
8554 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8555 ****************************************************************************/
8557 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8558 char **pparams, int total_params,
8559 char **ppdata, int total_data,
8560 unsigned int max_data_bytes)
8562 struct smb_filename *smb_dname = NULL;
8563 char *params = *pparams;
8564 char *pdata = *ppdata;
8565 char *directory = NULL;
8566 NTSTATUS status = NT_STATUS_OK;
8567 struct ea_list *ea_list = NULL;
8568 uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
8569 TALLOC_CTX *ctx = talloc_tos();
8571 if (!CAN_WRITE(conn)) {
8572 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8576 if (total_params < 5) {
8577 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8581 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8582 total_params - 4, STR_TERMINATE,
8584 if (!NT_STATUS_IS_OK(status)) {
8585 reply_nterror(req, status);
8589 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8591 status = filename_convert(ctx,
8593 req->flags2 & FLAGS2_DFS_PATHNAMES,
8599 if (!NT_STATUS_IS_OK(status)) {
8600 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8601 reply_botherror(req,
8602 NT_STATUS_PATH_NOT_COVERED,
8603 ERRSRV, ERRbadpath);
8606 reply_nterror(req, status);
8611 * OS/2 workplace shell seems to send SET_EA requests of "null"
8612 * length (4 bytes containing IVAL 4).
8613 * They seem to have no effect. Bug #3212. JRA.
8616 if (total_data && (total_data != 4)) {
8617 /* Any data in this call is an EA list. */
8618 if (total_data < 10) {
8619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8623 if (IVAL(pdata,0) > total_data) {
8624 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8625 IVAL(pdata,0), (unsigned int)total_data));
8626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8630 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8637 if (!lp_ea_support(SNUM(conn))) {
8638 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8642 /* If total_data == 4 Windows doesn't care what values
8643 * are placed in that field, it just ignores them.
8644 * The System i QNTC IBM SMB client puts bad values here,
8645 * so ignore them. */
8647 status = create_directory(conn, req, smb_dname);
8649 if (!NT_STATUS_IS_OK(status)) {
8650 reply_nterror(req, status);
8654 /* Try and set any given EA. */
8656 status = set_ea(conn, NULL, smb_dname, ea_list);
8657 if (!NT_STATUS_IS_OK(status)) {
8658 reply_nterror(req, status);
8663 /* Realloc the parameter and data sizes */
8664 *pparams = (char *)SMB_REALLOC(*pparams,2);
8665 if(*pparams == NULL) {
8666 reply_nterror(req, NT_STATUS_NO_MEMORY);
8673 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8676 TALLOC_FREE(smb_dname);
8680 /****************************************************************************
8681 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8682 We don't actually do this - we just send a null response.
8683 ****************************************************************************/
8685 static void call_trans2findnotifyfirst(connection_struct *conn,
8686 struct smb_request *req,
8687 char **pparams, int total_params,
8688 char **ppdata, int total_data,
8689 unsigned int max_data_bytes)
8691 char *params = *pparams;
8692 uint16_t info_level;
8694 if (total_params < 6) {
8695 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8699 info_level = SVAL(params,4);
8700 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8702 switch (info_level) {
8707 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8711 /* Realloc the parameter and data sizes */
8712 *pparams = (char *)SMB_REALLOC(*pparams,6);
8713 if (*pparams == NULL) {
8714 reply_nterror(req, NT_STATUS_NO_MEMORY);
8719 SSVAL(params,0,fnf_handle);
8720 SSVAL(params,2,0); /* No changes */
8721 SSVAL(params,4,0); /* No EA errors */
8728 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8733 /****************************************************************************
8734 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8735 changes). Currently this does nothing.
8736 ****************************************************************************/
8738 static void call_trans2findnotifynext(connection_struct *conn,
8739 struct smb_request *req,
8740 char **pparams, int total_params,
8741 char **ppdata, int total_data,
8742 unsigned int max_data_bytes)
8744 char *params = *pparams;
8746 DEBUG(3,("call_trans2findnotifynext\n"));
8748 /* Realloc the parameter and data sizes */
8749 *pparams = (char *)SMB_REALLOC(*pparams,4);
8750 if (*pparams == NULL) {
8751 reply_nterror(req, NT_STATUS_NO_MEMORY);
8756 SSVAL(params,0,0); /* No changes */
8757 SSVAL(params,2,0); /* No EA errors */
8759 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8764 /****************************************************************************
8765 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8766 ****************************************************************************/
8768 static void call_trans2getdfsreferral(connection_struct *conn,
8769 struct smb_request *req,
8770 char **pparams, int total_params,
8771 char **ppdata, int total_data,
8772 unsigned int max_data_bytes)
8774 char *params = *pparams;
8775 char *pathname = NULL;
8777 int max_referral_level;
8778 NTSTATUS status = NT_STATUS_OK;
8779 TALLOC_CTX *ctx = talloc_tos();
8781 DEBUG(10,("call_trans2getdfsreferral\n"));
8783 if (total_params < 3) {
8784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8788 max_referral_level = SVAL(params,0);
8790 if(!lp_host_msdfs()) {
8791 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8795 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8796 total_params - 2, STR_TERMINATE);
8798 reply_nterror(req, NT_STATUS_NOT_FOUND);
8801 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8802 ppdata,&status)) < 0) {
8803 reply_nterror(req, status);
8807 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8808 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8809 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8814 #define LMCAT_SPL 0x53
8815 #define LMFUNC_GETJOBID 0x60
8817 /****************************************************************************
8818 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8819 ****************************************************************************/
8821 static void call_trans2ioctl(connection_struct *conn,
8822 struct smb_request *req,
8823 char **pparams, int total_params,
8824 char **ppdata, int total_data,
8825 unsigned int max_data_bytes)
8827 char *pdata = *ppdata;
8828 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8832 /* check for an invalid fid before proceeding */
8835 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8839 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8840 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8841 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8842 if (*ppdata == NULL) {
8843 reply_nterror(req, NT_STATUS_NO_MEMORY);
8848 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8849 CAN ACCEPT THIS IN UNICODE. JRA. */
8852 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8854 status = srvstr_push(pdata, req->flags2, pdata + 2,
8855 lp_netbios_name(), 15,
8856 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
8857 if (!NT_STATUS_IS_OK(status)) {
8858 reply_nterror(req, status);
8861 status = srvstr_push(pdata, req->flags2, pdata+18,
8862 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8863 STR_ASCII|STR_TERMINATE, &len); /* Service name */
8864 if (!NT_STATUS_IS_OK(status)) {
8865 reply_nterror(req, status);
8868 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8873 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8874 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8877 /****************************************************************************
8878 Reply to a SMBfindclose (stop trans2 directory search).
8879 ****************************************************************************/
8881 void reply_findclose(struct smb_request *req)
8884 struct smbd_server_connection *sconn = req->sconn;
8886 START_PROFILE(SMBfindclose);
8889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8890 END_PROFILE(SMBfindclose);
8894 dptr_num = SVALS(req->vwv+0, 0);
8896 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8898 dptr_close(sconn, &dptr_num);
8900 reply_outbuf(req, 0, 0);
8902 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8904 END_PROFILE(SMBfindclose);
8908 /****************************************************************************
8909 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8910 ****************************************************************************/
8912 void reply_findnclose(struct smb_request *req)
8916 START_PROFILE(SMBfindnclose);
8919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8920 END_PROFILE(SMBfindnclose);
8924 dptr_num = SVAL(req->vwv+0, 0);
8926 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8928 /* We never give out valid handles for a
8929 findnotifyfirst - so any dptr_num is ok here.
8932 reply_outbuf(req, 0, 0);
8934 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8936 END_PROFILE(SMBfindnclose);
8940 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8941 struct trans_state *state)
8943 if (get_Protocol() >= PROTOCOL_NT1) {
8944 req->flags2 |= 0x40; /* IS_LONG_NAME */
8945 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8948 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8949 if (state->call != TRANSACT2_QFSINFO &&
8950 state->call != TRANSACT2_SETFSINFO) {
8951 DEBUG(0,("handle_trans2: encryption required "
8953 (unsigned int)state->call));
8954 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8959 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8961 /* Now we must call the relevant TRANS2 function */
8962 switch(state->call) {
8963 case TRANSACT2_OPEN:
8965 START_PROFILE(Trans2_open);
8966 call_trans2open(conn, req,
8967 &state->param, state->total_param,
8968 &state->data, state->total_data,
8969 state->max_data_return);
8970 END_PROFILE(Trans2_open);
8974 case TRANSACT2_FINDFIRST:
8976 START_PROFILE(Trans2_findfirst);
8977 call_trans2findfirst(conn, req,
8978 &state->param, state->total_param,
8979 &state->data, state->total_data,
8980 state->max_data_return);
8981 END_PROFILE(Trans2_findfirst);
8985 case TRANSACT2_FINDNEXT:
8987 START_PROFILE(Trans2_findnext);
8988 call_trans2findnext(conn, req,
8989 &state->param, state->total_param,
8990 &state->data, state->total_data,
8991 state->max_data_return);
8992 END_PROFILE(Trans2_findnext);
8996 case TRANSACT2_QFSINFO:
8998 START_PROFILE(Trans2_qfsinfo);
8999 call_trans2qfsinfo(conn, req,
9000 &state->param, state->total_param,
9001 &state->data, state->total_data,
9002 state->max_data_return);
9003 END_PROFILE(Trans2_qfsinfo);
9007 case TRANSACT2_SETFSINFO:
9009 START_PROFILE(Trans2_setfsinfo);
9010 call_trans2setfsinfo(conn, req,
9011 &state->param, state->total_param,
9012 &state->data, state->total_data,
9013 state->max_data_return);
9014 END_PROFILE(Trans2_setfsinfo);
9018 case TRANSACT2_QPATHINFO:
9019 case TRANSACT2_QFILEINFO:
9021 START_PROFILE(Trans2_qpathinfo);
9022 call_trans2qfilepathinfo(conn, req, state->call,
9023 &state->param, state->total_param,
9024 &state->data, state->total_data,
9025 state->max_data_return);
9026 END_PROFILE(Trans2_qpathinfo);
9030 case TRANSACT2_SETPATHINFO:
9031 case TRANSACT2_SETFILEINFO:
9033 START_PROFILE(Trans2_setpathinfo);
9034 call_trans2setfilepathinfo(conn, req, state->call,
9035 &state->param, state->total_param,
9036 &state->data, state->total_data,
9037 state->max_data_return);
9038 END_PROFILE(Trans2_setpathinfo);
9042 case TRANSACT2_FINDNOTIFYFIRST:
9044 START_PROFILE(Trans2_findnotifyfirst);
9045 call_trans2findnotifyfirst(conn, req,
9046 &state->param, state->total_param,
9047 &state->data, state->total_data,
9048 state->max_data_return);
9049 END_PROFILE(Trans2_findnotifyfirst);
9053 case TRANSACT2_FINDNOTIFYNEXT:
9055 START_PROFILE(Trans2_findnotifynext);
9056 call_trans2findnotifynext(conn, req,
9057 &state->param, state->total_param,
9058 &state->data, state->total_data,
9059 state->max_data_return);
9060 END_PROFILE(Trans2_findnotifynext);
9064 case TRANSACT2_MKDIR:
9066 START_PROFILE(Trans2_mkdir);
9067 call_trans2mkdir(conn, req,
9068 &state->param, state->total_param,
9069 &state->data, state->total_data,
9070 state->max_data_return);
9071 END_PROFILE(Trans2_mkdir);
9075 case TRANSACT2_GET_DFS_REFERRAL:
9077 START_PROFILE(Trans2_get_dfs_referral);
9078 call_trans2getdfsreferral(conn, req,
9079 &state->param, state->total_param,
9080 &state->data, state->total_data,
9081 state->max_data_return);
9082 END_PROFILE(Trans2_get_dfs_referral);
9086 case TRANSACT2_IOCTL:
9088 START_PROFILE(Trans2_ioctl);
9089 call_trans2ioctl(conn, req,
9090 &state->param, state->total_param,
9091 &state->data, state->total_data,
9092 state->max_data_return);
9093 END_PROFILE(Trans2_ioctl);
9098 /* Error in request */
9099 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9100 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9104 /****************************************************************************
9105 Reply to a SMBtrans2.
9106 ****************************************************************************/
9108 void reply_trans2(struct smb_request *req)
9110 connection_struct *conn = req->conn;
9115 unsigned int tran_call;
9116 struct trans_state *state;
9119 START_PROFILE(SMBtrans2);
9121 if (req->wct < 14) {
9122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9123 END_PROFILE(SMBtrans2);
9127 dsoff = SVAL(req->vwv+12, 0);
9128 dscnt = SVAL(req->vwv+11, 0);
9129 psoff = SVAL(req->vwv+10, 0);
9130 pscnt = SVAL(req->vwv+9, 0);
9131 tran_call = SVAL(req->vwv+14, 0);
9133 result = allow_new_trans(conn->pending_trans, req->mid);
9134 if (!NT_STATUS_IS_OK(result)) {
9135 DEBUG(2, ("Got invalid trans2 request: %s\n",
9136 nt_errstr(result)));
9137 reply_nterror(req, result);
9138 END_PROFILE(SMBtrans2);
9143 switch (tran_call) {
9144 /* List the allowed trans2 calls on IPC$ */
9145 case TRANSACT2_OPEN:
9146 case TRANSACT2_GET_DFS_REFERRAL:
9147 case TRANSACT2_QFILEINFO:
9148 case TRANSACT2_QFSINFO:
9149 case TRANSACT2_SETFSINFO:
9152 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9153 END_PROFILE(SMBtrans2);
9158 if ((state = talloc(conn, struct trans_state)) == NULL) {
9159 DEBUG(0, ("talloc failed\n"));
9160 reply_nterror(req, NT_STATUS_NO_MEMORY);
9161 END_PROFILE(SMBtrans2);
9165 state->cmd = SMBtrans2;
9167 state->mid = req->mid;
9168 state->vuid = req->vuid;
9169 state->setup_count = SVAL(req->vwv+13, 0);
9170 state->setup = NULL;
9171 state->total_param = SVAL(req->vwv+0, 0);
9172 state->param = NULL;
9173 state->total_data = SVAL(req->vwv+1, 0);
9175 state->max_param_return = SVAL(req->vwv+2, 0);
9176 state->max_data_return = SVAL(req->vwv+3, 0);
9177 state->max_setup_return = SVAL(req->vwv+4, 0);
9178 state->close_on_completion = BITSETW(req->vwv+5, 0);
9179 state->one_way = BITSETW(req->vwv+5, 1);
9181 state->call = tran_call;
9183 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9184 is so as a sanity check */
9185 if (state->setup_count != 1) {
9187 * Need to have rc=0 for ioctl to get job id for OS/2.
9188 * Network printing will fail if function is not successful.
9189 * Similar function in reply.c will be used if protocol
9190 * is LANMAN1.0 instead of LM1.2X002.
9191 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9192 * outbuf doesn't have to be set(only job id is used).
9194 if ( (state->setup_count == 4)
9195 && (tran_call == TRANSACT2_IOCTL)
9196 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9197 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9198 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9200 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9201 DEBUG(2,("Transaction is %d\n",tran_call));
9203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9204 END_PROFILE(SMBtrans2);
9209 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9212 if (state->total_data) {
9214 if (trans_oob(state->total_data, 0, dscnt)
9215 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9219 /* Can't use talloc here, the core routines do realloc on the
9220 * params and data. */
9221 state->data = (char *)SMB_MALLOC(state->total_data);
9222 if (state->data == NULL) {
9223 DEBUG(0,("reply_trans2: data malloc fail for %u "
9224 "bytes !\n", (unsigned int)state->total_data));
9226 reply_nterror(req, NT_STATUS_NO_MEMORY);
9227 END_PROFILE(SMBtrans2);
9231 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9234 if (state->total_param) {
9236 if (trans_oob(state->total_param, 0, pscnt)
9237 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9241 /* Can't use talloc here, the core routines do realloc on the
9242 * params and data. */
9243 state->param = (char *)SMB_MALLOC(state->total_param);
9244 if (state->param == NULL) {
9245 DEBUG(0,("reply_trans: param malloc fail for %u "
9246 "bytes !\n", (unsigned int)state->total_param));
9247 SAFE_FREE(state->data);
9249 reply_nterror(req, NT_STATUS_NO_MEMORY);
9250 END_PROFILE(SMBtrans2);
9254 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9257 state->received_data = dscnt;
9258 state->received_param = pscnt;
9260 if ((state->received_param == state->total_param) &&
9261 (state->received_data == state->total_data)) {
9263 handle_trans2(conn, req, state);
9265 SAFE_FREE(state->data);
9266 SAFE_FREE(state->param);
9268 END_PROFILE(SMBtrans2);
9272 DLIST_ADD(conn->pending_trans, state);
9274 /* We need to send an interim response then receive the rest
9275 of the parameter/data bytes */
9276 reply_outbuf(req, 0, 0);
9277 show_msg((char *)req->outbuf);
9278 END_PROFILE(SMBtrans2);
9283 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9284 SAFE_FREE(state->data);
9285 SAFE_FREE(state->param);
9287 END_PROFILE(SMBtrans2);
9288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9292 /****************************************************************************
9293 Reply to a SMBtranss2
9294 ****************************************************************************/
9296 void reply_transs2(struct smb_request *req)
9298 connection_struct *conn = req->conn;
9299 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9300 struct trans_state *state;
9302 START_PROFILE(SMBtranss2);
9304 show_msg((const char *)req->inbuf);
9306 /* Windows clients expect all replies to
9307 a transact secondary (SMBtranss2 0x33)
9308 to have a command code of transact
9309 (SMBtrans2 0x32). See bug #8989
9310 and also [MS-CIFS] section 2.2.4.47.2
9313 req->cmd = SMBtrans2;
9316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9317 END_PROFILE(SMBtranss2);
9321 for (state = conn->pending_trans; state != NULL;
9322 state = state->next) {
9323 if (state->mid == req->mid) {
9328 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9330 END_PROFILE(SMBtranss2);
9334 /* Revise state->total_param and state->total_data in case they have
9335 changed downwards */
9337 if (SVAL(req->vwv+0, 0) < state->total_param)
9338 state->total_param = SVAL(req->vwv+0, 0);
9339 if (SVAL(req->vwv+1, 0) < state->total_data)
9340 state->total_data = SVAL(req->vwv+1, 0);
9342 pcnt = SVAL(req->vwv+2, 0);
9343 poff = SVAL(req->vwv+3, 0);
9344 pdisp = SVAL(req->vwv+4, 0);
9346 dcnt = SVAL(req->vwv+5, 0);
9347 doff = SVAL(req->vwv+6, 0);
9348 ddisp = SVAL(req->vwv+7, 0);
9350 state->received_param += pcnt;
9351 state->received_data += dcnt;
9353 if ((state->received_data > state->total_data) ||
9354 (state->received_param > state->total_param))
9358 if (trans_oob(state->total_param, pdisp, pcnt)
9359 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9362 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9366 if (trans_oob(state->total_data, ddisp, dcnt)
9367 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9370 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9373 if ((state->received_param < state->total_param) ||
9374 (state->received_data < state->total_data)) {
9375 END_PROFILE(SMBtranss2);
9379 handle_trans2(conn, req, state);
9381 DLIST_REMOVE(conn->pending_trans, state);
9382 SAFE_FREE(state->data);
9383 SAFE_FREE(state->param);
9386 END_PROFILE(SMBtranss2);
9391 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9392 DLIST_REMOVE(conn->pending_trans, state);
9393 SAFE_FREE(state->data);
9394 SAFE_FREE(state->param);
9396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9397 END_PROFILE(SMBtranss2);