2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/util/tevent_ntstatus.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "librpc/gen_ndr/open_files.h"
48 #include "smb1_utils.h"
49 #include "libcli/smb/smb2_posix.h"
50 #include "lib/util/string_wrappers.h"
52 /****************************************************************************
53 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
54 path or anything including wildcards.
55 We're assuming here that '/' is not the second byte in any multibyte char
56 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
58 ****************************************************************************/
60 /* Custom version for processing POSIX paths. */
61 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
63 static NTSTATUS check_path_syntax_internal(char *path,
65 bool *p_last_component_contains_wcard)
69 NTSTATUS ret = NT_STATUS_OK;
70 bool start_of_name_component = True;
71 bool stream_started = false;
73 *p_last_component_contains_wcard = False;
80 return NT_STATUS_OBJECT_NAME_INVALID;
83 return NT_STATUS_OBJECT_NAME_INVALID;
85 if (strchr_m(&s[1], ':')) {
86 return NT_STATUS_OBJECT_NAME_INVALID;
92 if ((*s == ':') && !posix_path && !stream_started) {
93 if (*p_last_component_contains_wcard) {
94 return NT_STATUS_OBJECT_NAME_INVALID;
96 /* Stream names allow more characters than file names.
97 We're overloading posix_path here to allow a wider
98 range of characters. If stream_started is true this
99 is still a Windows path even if posix_path is true.
102 stream_started = true;
103 start_of_name_component = false;
107 return NT_STATUS_OBJECT_NAME_INVALID;
111 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
113 * Safe to assume is not the second part of a mb char
114 * as this is handled below.
116 /* Eat multiple '/' or '\\' */
117 while (IS_PATH_SEP(*s,posix_path)) {
120 if ((d != path) && (*s != '\0')) {
121 /* We only care about non-leading or trailing '/' or '\\' */
125 start_of_name_component = True;
127 *p_last_component_contains_wcard = False;
131 if (start_of_name_component) {
132 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
133 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
136 * No mb char starts with '.' so we're safe checking the directory separator here.
139 /* If we just added a '/' - delete it */
140 if ((d > path) && (*(d-1) == '/')) {
145 /* Are we at the start ? Can't go back further if so. */
147 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
150 /* Go back one level... */
151 /* We know this is safe as '/' cannot be part of a mb sequence. */
152 /* NOTE - if this assumption is invalid we are not in good shape... */
153 /* Decrement d first as d points to the *next* char to write into. */
154 for (d--; d > path; d--) {
158 s += 2; /* Else go past the .. */
159 /* We're still at the start of a name component, just the previous one. */
162 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
174 if (*s <= 0x1f || *s == '|') {
175 return NT_STATUS_OBJECT_NAME_INVALID;
183 *p_last_component_contains_wcard = True;
192 /* Get the size of the next MB character. */
193 next_codepoint(s,&siz);
211 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
213 return NT_STATUS_INVALID_PARAMETER;
216 start_of_name_component = False;
224 /****************************************************************************
225 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
226 No wildcards allowed.
227 ****************************************************************************/
229 NTSTATUS check_path_syntax(char *path)
232 return check_path_syntax_internal(path, False, &ignore);
235 /****************************************************************************
236 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
237 Wildcards allowed - p_contains_wcard returns true if the last component contained
239 ****************************************************************************/
241 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
243 return check_path_syntax_internal(path, False, p_contains_wcard);
246 /****************************************************************************
247 Check the path for a POSIX client.
248 We're assuming here that '/' is not the second byte in any multibyte char
249 set (a safe assumption).
250 ****************************************************************************/
252 NTSTATUS check_path_syntax_posix(char *path)
255 return check_path_syntax_internal(path, True, &ignore);
258 /****************************************************************************
259 Pull a string and check the path allowing a wildcard - provide for error return.
260 Passes in posix flag.
261 ****************************************************************************/
263 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
264 const char *base_ptr,
270 bool posix_pathnames,
272 bool *contains_wcard)
278 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
282 *err = NT_STATUS_INVALID_PARAMETER;
286 *contains_wcard = False;
288 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
290 * For a DFS path the function parse_dfs_path()
291 * will do the path processing, just make a copy.
297 if (posix_pathnames) {
298 *err = check_path_syntax_posix(*pp_dest);
300 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
306 /****************************************************************************
307 Pull a string and check the path allowing a wildcard - provide for error return.
308 ****************************************************************************/
310 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
311 const char *base_ptr,
318 bool *contains_wcard)
320 return srvstr_get_path_wcard_internal(ctx,
332 /****************************************************************************
333 Pull a string and check the path allowing a wildcard - provide for error return.
334 posix_pathnames version.
335 ****************************************************************************/
337 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
338 const char *base_ptr,
345 bool *contains_wcard)
347 return srvstr_get_path_wcard_internal(ctx,
359 /****************************************************************************
360 Pull a string and check the path - provide for error return.
361 ****************************************************************************/
363 size_t srvstr_get_path(TALLOC_CTX *ctx,
364 const char *base_ptr,
373 return srvstr_get_path_wcard_internal(ctx,
385 /****************************************************************************
386 Pull a string and check the path - provide for error return.
387 posix_pathnames version.
388 ****************************************************************************/
390 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
391 const char *base_ptr,
400 return srvstr_get_path_wcard_internal(ctx,
413 static size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
414 char **pp_dest, const char *src, int flags,
415 NTSTATUS *err, bool *contains_wcard)
417 ssize_t bufrem = smbreq_bufrem(req, src);
420 *err = NT_STATUS_INVALID_PARAMETER;
424 if (req->posix_pathnames) {
425 return srvstr_get_path_wcard_internal(mem_ctx,
426 (const char *)req->inbuf,
436 return srvstr_get_path_wcard_internal(mem_ctx,
437 (const char *)req->inbuf,
449 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
450 char **pp_dest, const char *src, int flags,
454 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
455 flags, err, &ignore);
459 * pull a string from the smb_buf part of a packet. In this case the
460 * string can either be null terminated or it can be terminated by the
461 * end of the smbbuf area
463 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
464 char **dest, const uint8_t *src, int flags)
466 ssize_t bufrem = smbreq_bufrem(req, src);
472 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
476 /****************************************************************************
477 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
478 ****************************************************************************/
480 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
483 if ((fsp == NULL) || (conn == NULL)) {
484 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
487 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
488 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
494 /****************************************************************************
495 Check if we have a correct fsp pointing to a file.
496 ****************************************************************************/
498 bool check_fsp(connection_struct *conn, struct smb_request *req,
501 if (!check_fsp_open(conn, req, fsp)) {
504 if (fsp->fsp_flags.is_directory) {
505 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
508 if (fsp->fh->fd == -1) {
509 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
512 fsp->num_smb_operations++;
516 /****************************************************************************
517 Check if we have a correct fsp pointing to a quota fake file. Replacement for
518 the CHECK_NTQUOTA_HANDLE_OK macro.
519 ****************************************************************************/
521 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
524 if (!check_fsp_open(conn, req, fsp)) {
528 if (fsp->fsp_flags.is_directory) {
532 if (fsp->fake_file_handle == NULL) {
536 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
540 if (fsp->fake_file_handle->private_data == NULL) {
547 /****************************************************************************
548 Return the port number we've bound to on a socket.
549 ****************************************************************************/
551 static int get_socket_port(int fd)
553 struct samba_sockaddr saddr = {
554 .sa_socklen = sizeof(struct sockaddr_storage),
561 if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
562 int level = (errno == ENOTCONN) ? 2 : 0;
563 DEBUG(level, ("getsockname failed. Error was %s\n",
568 #if defined(HAVE_IPV6)
569 if (saddr.u.sa.sa_family == AF_INET6) {
570 return ntohs(saddr.u.in6.sin6_port);
573 if (saddr.u.sa.sa_family == AF_INET) {
574 return ntohs(saddr.u.in.sin_port);
579 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
580 const char *name, int name_type)
583 char *trim_name_type;
584 const char *retarget_parm;
587 int retarget_type = 0x20;
588 int retarget_port = NBT_SMB_PORT;
589 struct sockaddr_storage retarget_addr;
590 struct sockaddr_in *in_addr;
594 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
598 trim_name = talloc_strdup(talloc_tos(), name);
599 if (trim_name == NULL) {
602 trim_char(trim_name, ' ', ' ');
604 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
606 if (trim_name_type == NULL) {
610 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
611 trim_name_type, NULL);
612 if (retarget_parm == NULL) {
613 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
616 if (retarget_parm == NULL) {
620 retarget = talloc_strdup(trim_name, retarget_parm);
621 if (retarget == NULL) {
625 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
627 p = strchr(retarget, ':');
630 retarget_port = atoi(p);
633 p = strchr_m(retarget, '#');
636 if (sscanf(p, "%x", &retarget_type) != 1) {
641 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
643 DEBUG(10, ("could not resolve %s\n", retarget));
647 if (retarget_addr.ss_family != AF_INET) {
648 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
652 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
654 _smb_setlen(outbuf, 6);
655 SCVAL(outbuf, 0, 0x84);
656 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
657 *(uint16_t *)(outbuf+8) = htons(retarget_port);
659 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
661 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
667 TALLOC_FREE(trim_name);
671 static void reply_called_name_not_present(char *outbuf)
673 smb_setlen(outbuf, 1);
674 SCVAL(outbuf, 0, 0x83);
675 SCVAL(outbuf, 4, 0x82);
678 /****************************************************************************
679 Reply to a (netbios-level) special message.
680 ****************************************************************************/
682 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
684 struct smbd_server_connection *sconn = xconn->client->sconn;
685 int msg_type = CVAL(inbuf,0);
686 int msg_flags = CVAL(inbuf,1);
688 * We only really use 4 bytes of the outbuf, but for the smb_setlen
689 * calculation & friends (srv_send_smb uses that) we need the full smb
692 char outbuf[smb_size];
694 memset(outbuf, '\0', sizeof(outbuf));
696 smb_setlen(outbuf,0);
699 case NBSSrequest: /* session request */
701 /* inbuf_size is guarenteed to be at least 4. */
703 int name_type1, name_type2;
704 int name_len1, name_len2;
708 if (xconn->transport.nbt.got_session) {
709 exit_server_cleanly("multiple session request not permitted");
712 SCVAL(outbuf,0,NBSSpositive);
715 /* inbuf_size is guaranteed to be at least 4. */
716 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
717 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
718 DEBUG(0,("Invalid name length in session request\n"));
719 reply_called_name_not_present(outbuf);
722 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
723 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
724 DEBUG(0,("Invalid name length in session request\n"));
725 reply_called_name_not_present(outbuf);
729 name_type1 = name_extract((unsigned char *)inbuf,
730 inbuf_size,(unsigned int)4,name1);
731 name_type2 = name_extract((unsigned char *)inbuf,
732 inbuf_size,(unsigned int)(4 + name_len1),name2);
734 if (name_type1 == -1 || name_type2 == -1) {
735 DEBUG(0,("Invalid name type in session request\n"));
736 reply_called_name_not_present(outbuf);
740 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
741 name1, name_type1, name2, name_type2));
743 if (netbios_session_retarget(xconn, name1, name_type1)) {
744 exit_server_cleanly("retargeted client");
748 * Windows NT/2k uses "*SMBSERVER" and XP uses
749 * "*SMBSERV" arrggg!!!
751 if (strequal(name1, "*SMBSERVER ")
752 || strequal(name1, "*SMBSERV ")) {
755 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
758 exit_server_cleanly("could not allocate raddr");
761 fstrcpy(name1, raddr);
764 set_local_machine_name(name1, True);
765 set_remote_machine_name(name2, True);
767 if (is_ipaddress(sconn->remote_hostname)) {
768 char *p = discard_const_p(char, sconn->remote_hostname);
772 sconn->remote_hostname = talloc_strdup(sconn,
773 get_remote_machine_name());
774 if (sconn->remote_hostname == NULL) {
775 exit_server_cleanly("could not copy remote name");
777 xconn->remote_hostname = sconn->remote_hostname;
780 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
781 get_local_machine_name(), get_remote_machine_name(),
784 if (name_type2 == 'R') {
785 /* We are being asked for a pathworks session ---
787 reply_called_name_not_present(outbuf);
791 reload_services(sconn, conn_snum_used, true);
794 xconn->transport.nbt.got_session = true;
798 case 0x89: /* session keepalive request
799 (some old clients produce this?) */
800 SCVAL(outbuf,0,NBSSkeepalive);
804 case NBSSpositive: /* positive session response */
805 case NBSSnegative: /* negative session response */
806 case NBSSretarget: /* retarget session response */
807 DEBUG(0,("Unexpected session response\n"));
810 case NBSSkeepalive: /* session keepalive */
815 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
816 msg_type, msg_flags));
818 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
819 exit_server_cleanly("reply_special: srv_send_smb failed.");
822 if (CVAL(outbuf, 0) != 0x82) {
823 exit_server_cleanly("invalid netbios session");
828 /****************************************************************************
830 conn POINTER CAN BE NULL HERE !
831 ****************************************************************************/
833 void reply_tcon(struct smb_request *req)
835 connection_struct *conn = req->conn;
837 char *service_buf = NULL;
838 char *password = NULL;
844 TALLOC_CTX *ctx = talloc_tos();
845 struct smbXsrv_connection *xconn = req->xconn;
846 NTTIME now = timeval_to_nttime(&req->request_time);
848 START_PROFILE(SMBtcon);
850 if (req->buflen < 4) {
851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
852 END_PROFILE(SMBtcon);
857 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
859 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
861 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
864 if (service_buf == NULL || password == NULL || dev == NULL) {
865 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
866 END_PROFILE(SMBtcon);
869 p2 = strrchr_m(service_buf,'\\');
873 service = service_buf;
876 conn = make_connection(req, now, service, dev,
877 req->vuid,&nt_status);
881 reply_nterror(req, nt_status);
882 END_PROFILE(SMBtcon);
886 reply_outbuf(req, 2, 0);
887 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
888 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
889 SSVAL(req->outbuf,smb_tid,conn->cnum);
891 DEBUG(3,("tcon service=%s cnum=%d\n",
892 service, conn->cnum));
894 END_PROFILE(SMBtcon);
898 /****************************************************************************
899 Reply to a tcon and X.
900 conn POINTER CAN BE NULL HERE !
901 ****************************************************************************/
903 void reply_tcon_and_X(struct smb_request *req)
905 const struct loadparm_substitution *lp_sub =
906 loadparm_s3_global_substitution();
907 connection_struct *conn = req->conn;
908 const char *service = NULL;
909 TALLOC_CTX *ctx = talloc_tos();
910 /* what the client thinks the device is */
911 char *client_devicetype = NULL;
912 /* what the server tells the client the share represents */
913 const char *server_devicetype;
920 struct smbXsrv_session *session = NULL;
921 NTTIME now = timeval_to_nttime(&req->request_time);
922 bool session_key_updated = false;
923 uint16_t optional_support = 0;
924 struct smbXsrv_connection *xconn = req->xconn;
926 START_PROFILE(SMBtconX);
929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
930 END_PROFILE(SMBtconX);
934 passlen = SVAL(req->vwv+3, 0);
935 tcon_flags = SVAL(req->vwv+2, 0);
937 /* we might have to close an old one */
938 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
939 struct smbXsrv_tcon *tcon;
947 * TODO: cancel all outstanding requests on the tcon
949 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
950 if (!NT_STATUS_IS_OK(status)) {
951 DEBUG(0, ("reply_tcon_and_X: "
952 "smbXsrv_tcon_disconnect() failed: %s\n",
955 * If we hit this case, there is something completely
956 * wrong, so we better disconnect the transport connection.
958 END_PROFILE(SMBtconX);
959 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
965 * This tree id is gone. Make sure we can't re-use it
971 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
972 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
973 END_PROFILE(SMBtconX);
977 if (xconn->smb1.negprot.encrypted_passwords) {
978 p = req->buf + passlen;
980 p = req->buf + passlen + 1;
983 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
987 END_PROFILE(SMBtconX);
992 * the service name can be either: \\server\share
993 * or share directly like on the DELL PowerVault 705
996 q = strchr_m(path+2,'\\');
998 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
999 END_PROFILE(SMBtconX);
1007 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
1008 &client_devicetype, p,
1009 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
1011 if (client_devicetype == NULL) {
1012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1013 END_PROFILE(SMBtconX);
1017 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
1019 nt_status = smb1srv_session_lookup(xconn,
1020 req->vuid, now, &session);
1021 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
1022 reply_force_doserror(req, ERRSRV, ERRbaduid);
1023 END_PROFILE(SMBtconX);
1026 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1027 reply_nterror(req, nt_status);
1028 END_PROFILE(SMBtconX);
1031 if (!NT_STATUS_IS_OK(nt_status)) {
1032 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1033 END_PROFILE(SMBtconX);
1037 if (session->global->auth_session_info == NULL) {
1038 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1039 END_PROFILE(SMBtconX);
1044 * If there is no application key defined yet
1047 * This means we setup the application key on the
1048 * first tcon that happens via the given session.
1050 * Once the application key is defined, it does not
1053 if (session->global->application_key.length == 0 &&
1054 smb2_signing_key_valid(session->global->signing_key))
1056 struct smbXsrv_session *x = session;
1057 struct auth_session_info *session_info =
1058 session->global->auth_session_info;
1059 uint8_t session_key[16];
1061 ZERO_STRUCT(session_key);
1062 memcpy(session_key, x->global->signing_key->blob.data,
1063 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
1066 * The application key is truncated/padded to 16 bytes
1068 x->global->application_key = data_blob_talloc(x->global,
1070 sizeof(session_key));
1071 ZERO_STRUCT(session_key);
1072 if (x->global->application_key.data == NULL) {
1073 reply_nterror(req, NT_STATUS_NO_MEMORY);
1074 END_PROFILE(SMBtconX);
1078 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1081 status = smb_key_derivation(x->global->application_key.data,
1082 x->global->application_key.length,
1083 x->global->application_key.data);
1084 if (!NT_STATUS_IS_OK(status)) {
1085 DBG_ERR("smb_key_derivation failed: %s\n",
1087 END_PROFILE(SMBtconX);
1090 optional_support |= SMB_EXTENDED_SIGNATURES;
1094 * Place the application key into the session_info
1096 data_blob_clear_free(&session_info->session_key);
1097 session_info->session_key = data_blob_dup_talloc(session_info,
1098 x->global->application_key);
1099 if (session_info->session_key.data == NULL) {
1100 data_blob_clear_free(&x->global->application_key);
1101 reply_nterror(req, NT_STATUS_NO_MEMORY);
1102 END_PROFILE(SMBtconX);
1105 session_key_updated = true;
1108 conn = make_connection(req, now, service, client_devicetype,
1109 req->vuid, &nt_status);
1113 if (session_key_updated) {
1114 struct smbXsrv_session *x = session;
1115 struct auth_session_info *session_info =
1116 session->global->auth_session_info;
1117 data_blob_clear_free(&x->global->application_key);
1118 data_blob_clear_free(&session_info->session_key);
1120 reply_nterror(req, nt_status);
1121 END_PROFILE(SMBtconX);
1126 server_devicetype = "IPC";
1127 else if ( IS_PRINT(conn) )
1128 server_devicetype = "LPT1:";
1130 server_devicetype = "A:";
1132 if (get_Protocol() < PROTOCOL_NT1) {
1133 reply_outbuf(req, 2, 0);
1134 if (message_push_string(&req->outbuf, server_devicetype,
1135 STR_TERMINATE|STR_ASCII) == -1) {
1136 reply_nterror(req, NT_STATUS_NO_MEMORY);
1137 END_PROFILE(SMBtconX);
1141 /* NT sets the fstype of IPC$ to the null string */
1142 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1144 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1145 /* Return permissions. */
1149 reply_outbuf(req, 7, 0);
1152 perm1 = FILE_ALL_ACCESS;
1153 perm2 = FILE_ALL_ACCESS;
1155 perm1 = conn->share_access;
1158 SIVAL(req->outbuf, smb_vwv3, perm1);
1159 SIVAL(req->outbuf, smb_vwv5, perm2);
1161 reply_outbuf(req, 3, 0);
1164 if ((message_push_string(&req->outbuf, server_devicetype,
1165 STR_TERMINATE|STR_ASCII) == -1)
1166 || (message_push_string(&req->outbuf, fstype,
1167 STR_TERMINATE) == -1)) {
1168 reply_nterror(req, NT_STATUS_NO_MEMORY);
1169 END_PROFILE(SMBtconX);
1173 /* what does setting this bit do? It is set by NT4 and
1174 may affect the ability to autorun mounted cdroms */
1175 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1177 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1179 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1180 DEBUG(2,("Serving %s as a Dfs root\n",
1181 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1182 optional_support |= SMB_SHARE_IN_DFS;
1185 SSVAL(req->outbuf, smb_vwv2, optional_support);
1188 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1189 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1191 DEBUG(3,("tconX service=%s \n",
1194 /* set the incoming and outgoing tid to the just created one */
1195 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1196 SSVAL(req->outbuf,smb_tid,conn->cnum);
1198 END_PROFILE(SMBtconX);
1200 req->tid = conn->cnum;
1203 /****************************************************************************
1204 Reply to an unknown type.
1205 ****************************************************************************/
1207 void reply_unknown_new(struct smb_request *req, uint8_t type)
1209 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1210 smb_fn_name(type), type, type));
1211 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1215 /****************************************************************************
1217 conn POINTER CAN BE NULL HERE !
1218 ****************************************************************************/
1220 void reply_ioctl(struct smb_request *req)
1222 const struct loadparm_substitution *lp_sub =
1223 loadparm_s3_global_substitution();
1224 connection_struct *conn = req->conn;
1227 uint32_t ioctl_code;
1231 START_PROFILE(SMBioctl);
1234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1235 END_PROFILE(SMBioctl);
1239 device = SVAL(req->vwv+1, 0);
1240 function = SVAL(req->vwv+2, 0);
1241 ioctl_code = (device << 16) + function;
1243 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1245 switch (ioctl_code) {
1246 case IOCTL_QUERY_JOB_INFO:
1250 reply_force_doserror(req, ERRSRV, ERRnosupport);
1251 END_PROFILE(SMBioctl);
1255 reply_outbuf(req, 8, replysize+1);
1256 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1257 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1258 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1259 p = smb_buf(req->outbuf);
1260 memset(p, '\0', replysize+1); /* valgrind-safe. */
1261 p += 1; /* Allow for alignment */
1263 switch (ioctl_code) {
1264 case IOCTL_QUERY_JOB_INFO:
1268 files_struct *fsp = file_fsp(
1269 req, SVAL(req->vwv+0, 0));
1271 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1272 END_PROFILE(SMBioctl);
1276 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1278 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1279 lp_netbios_name(), 15,
1280 STR_TERMINATE|STR_ASCII, &len);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 reply_nterror(req, status);
1283 END_PROFILE(SMBioctl);
1287 status = srvstr_push((char *)req->outbuf, req->flags2,
1289 lp_servicename(talloc_tos(),
1292 13, STR_TERMINATE|STR_ASCII, &len);
1293 if (!NT_STATUS_IS_OK(status)) {
1294 reply_nterror(req, status);
1295 END_PROFILE(SMBioctl);
1299 memset(p+18, 0, 13);
1305 END_PROFILE(SMBioctl);
1309 /****************************************************************************
1310 Strange checkpath NTSTATUS mapping.
1311 ****************************************************************************/
1313 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1315 /* Strange DOS error code semantics only for checkpath... */
1316 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1317 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1318 /* We need to map to ERRbadpath */
1319 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1325 /****************************************************************************
1326 Reply to a checkpath.
1327 ****************************************************************************/
1329 void reply_checkpath(struct smb_request *req)
1331 connection_struct *conn = req->conn;
1332 struct smb_filename *smb_fname = NULL;
1335 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1336 TALLOC_CTX *ctx = talloc_tos();
1338 START_PROFILE(SMBcheckpath);
1340 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1341 STR_TERMINATE, &status);
1343 if (!NT_STATUS_IS_OK(status)) {
1344 status = map_checkpath_error(req->flags2, status);
1345 reply_nterror(req, status);
1346 END_PROFILE(SMBcheckpath);
1350 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1352 status = filename_convert(ctx,
1360 if (!NT_STATUS_IS_OK(status)) {
1361 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1362 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1363 ERRSRV, ERRbadpath);
1364 END_PROFILE(SMBcheckpath);
1370 if (!VALID_STAT(smb_fname->st) &&
1371 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1372 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1373 smb_fname_str_dbg(smb_fname), strerror(errno)));
1374 status = map_nt_error_from_unix(errno);
1378 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1379 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1380 ERRDOS, ERRbadpath);
1384 reply_outbuf(req, 0, 0);
1387 /* We special case this - as when a Windows machine
1388 is parsing a path is steps through the components
1389 one at a time - if a component fails it expects
1390 ERRbadpath, not ERRbadfile.
1392 status = map_checkpath_error(req->flags2, status);
1393 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1395 * Windows returns different error codes if
1396 * the parent directory is valid but not the
1397 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1398 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1399 * if the path is invalid.
1401 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1402 ERRDOS, ERRbadpath);
1406 reply_nterror(req, status);
1409 TALLOC_FREE(smb_fname);
1410 END_PROFILE(SMBcheckpath);
1414 /****************************************************************************
1416 ****************************************************************************/
1418 void reply_getatr(struct smb_request *req)
1420 connection_struct *conn = req->conn;
1421 struct smb_filename *smb_fname = NULL;
1428 TALLOC_CTX *ctx = talloc_tos();
1429 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1431 START_PROFILE(SMBgetatr);
1433 p = (const char *)req->buf + 1;
1434 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1435 if (!NT_STATUS_IS_OK(status)) {
1436 reply_nterror(req, status);
1440 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1441 under WfWg - weird! */
1442 if (*fname == '\0') {
1443 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1444 if (!CAN_WRITE(conn)) {
1445 mode |= FILE_ATTRIBUTE_READONLY;
1450 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1451 status = filename_convert(ctx,
1458 if (!NT_STATUS_IS_OK(status)) {
1459 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1460 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1461 ERRSRV, ERRbadpath);
1464 reply_nterror(req, status);
1467 if (!VALID_STAT(smb_fname->st) &&
1468 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1469 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1470 smb_fname_str_dbg(smb_fname),
1472 reply_nterror(req, map_nt_error_from_unix(errno));
1476 mode = dos_mode(conn, smb_fname);
1477 size = smb_fname->st.st_ex_size;
1479 if (ask_sharemode) {
1480 struct timespec write_time_ts;
1481 struct file_id fileid;
1483 ZERO_STRUCT(write_time_ts);
1484 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1485 get_file_infos(fileid, 0, NULL, &write_time_ts);
1486 if (!is_omit_timespec(&write_time_ts)) {
1487 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1491 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1492 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1497 reply_outbuf(req, 10, 0);
1499 SSVAL(req->outbuf,smb_vwv0,mode);
1500 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1501 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1503 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1505 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1507 if (get_Protocol() >= PROTOCOL_NT1) {
1508 SSVAL(req->outbuf, smb_flg2,
1509 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1512 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1513 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1516 TALLOC_FREE(smb_fname);
1518 END_PROFILE(SMBgetatr);
1522 /****************************************************************************
1524 ****************************************************************************/
1526 void reply_setatr(struct smb_request *req)
1528 struct smb_file_time ft;
1529 connection_struct *conn = req->conn;
1530 struct smb_filename *smb_fname = NULL;
1536 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1537 TALLOC_CTX *ctx = talloc_tos();
1539 START_PROFILE(SMBsetatr);
1540 init_smb_file_time(&ft);
1543 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1547 p = (const char *)req->buf + 1;
1548 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1549 if (!NT_STATUS_IS_OK(status)) {
1550 reply_nterror(req, status);
1554 status = filename_convert(ctx,
1561 if (!NT_STATUS_IS_OK(status)) {
1562 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1563 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1564 ERRSRV, ERRbadpath);
1567 reply_nterror(req, status);
1571 if (ISDOT(smb_fname->base_name)) {
1573 * Not sure here is the right place to catch this
1574 * condition. Might be moved to somewhere else later -- vl
1576 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1580 mode = SVAL(req->vwv+0, 0);
1581 mtime = srv_make_unix_date3(req->vwv+1);
1583 if (mode != FILE_ATTRIBUTE_NORMAL) {
1584 if (VALID_STAT_OF_DIR(smb_fname->st))
1585 mode |= FILE_ATTRIBUTE_DIRECTORY;
1587 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1589 status = smbd_check_access_rights(conn,
1593 FILE_WRITE_ATTRIBUTES);
1594 if (!NT_STATUS_IS_OK(status)) {
1595 reply_nterror(req, status);
1599 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1601 reply_nterror(req, map_nt_error_from_unix(errno));
1606 ft.mtime = time_t_to_full_timespec(mtime);
1608 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1609 if (!NT_STATUS_IS_OK(status)) {
1610 reply_nterror(req, status);
1614 reply_outbuf(req, 0, 0);
1616 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1619 TALLOC_FREE(smb_fname);
1620 END_PROFILE(SMBsetatr);
1624 /****************************************************************************
1626 ****************************************************************************/
1628 void reply_dskattr(struct smb_request *req)
1630 connection_struct *conn = req->conn;
1632 uint64_t dfree,dsize,bsize;
1633 struct smb_filename smb_fname;
1634 START_PROFILE(SMBdskattr);
1636 ZERO_STRUCT(smb_fname);
1637 smb_fname.base_name = discard_const_p(char, ".");
1639 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1640 reply_nterror(req, map_nt_error_from_unix(errno));
1641 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1642 END_PROFILE(SMBdskattr);
1646 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1647 if (ret == (uint64_t)-1) {
1648 reply_nterror(req, map_nt_error_from_unix(errno));
1649 END_PROFILE(SMBdskattr);
1654 * Force max to fit in 16 bit fields.
1656 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1660 if (bsize > (WORDMAX*512)) {
1661 bsize = (WORDMAX*512);
1662 if (dsize > WORDMAX)
1664 if (dfree > WORDMAX)
1670 reply_outbuf(req, 5, 0);
1672 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1673 double total_space, free_space;
1674 /* we need to scale this to a number that DOS6 can handle. We
1675 use floating point so we can handle large drives on systems
1676 that don't have 64 bit integers
1678 we end up displaying a maximum of 2G to DOS systems
1680 total_space = dsize * (double)bsize;
1681 free_space = dfree * (double)bsize;
1683 dsize = (uint64_t)((total_space+63*512) / (64*512));
1684 dfree = (uint64_t)((free_space+63*512) / (64*512));
1686 if (dsize > 0xFFFF) dsize = 0xFFFF;
1687 if (dfree > 0xFFFF) dfree = 0xFFFF;
1689 SSVAL(req->outbuf,smb_vwv0,dsize);
1690 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1691 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1692 SSVAL(req->outbuf,smb_vwv3,dfree);
1694 SSVAL(req->outbuf,smb_vwv0,dsize);
1695 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1696 SSVAL(req->outbuf,smb_vwv2,512);
1697 SSVAL(req->outbuf,smb_vwv3,dfree);
1700 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1702 END_PROFILE(SMBdskattr);
1707 * Utility function to split the filename from the directory.
1709 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1710 char **fname_dir_out,
1711 char **fname_mask_out)
1713 const char *p = NULL;
1714 char *fname_dir = NULL;
1715 char *fname_mask = NULL;
1717 p = strrchr_m(fname_in, '/');
1719 fname_dir = talloc_strdup(ctx, ".");
1720 fname_mask = talloc_strdup(ctx, fname_in);
1722 fname_dir = talloc_strndup(ctx, fname_in,
1723 PTR_DIFF(p, fname_in));
1724 fname_mask = talloc_strdup(ctx, p+1);
1727 if (!fname_dir || !fname_mask) {
1728 TALLOC_FREE(fname_dir);
1729 TALLOC_FREE(fname_mask);
1730 return NT_STATUS_NO_MEMORY;
1733 *fname_dir_out = fname_dir;
1734 *fname_mask_out = fname_mask;
1735 return NT_STATUS_OK;
1738 /****************************************************************************
1740 ****************************************************************************/
1742 static bool make_dir_struct(TALLOC_CTX *ctx,
1752 char *mask2 = talloc_strdup(ctx, mask);
1758 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1762 memset(buf+1,' ',11);
1763 if ((p = strchr_m(mask2,'.')) != NULL) {
1765 push_ascii(buf+1,mask2,8, 0);
1766 push_ascii(buf+9,p+1,3, 0);
1769 push_ascii(buf+1,mask2,11, 0);
1772 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1774 srv_put_dos_date(buf,22,date);
1775 SSVAL(buf,26,size & 0xFFFF);
1776 SSVAL(buf,28,(size >> 16)&0xFFFF);
1777 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1778 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1779 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1780 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1784 /****************************************************************************
1786 Can be called from SMBsearch, SMBffirst or SMBfunique.
1787 ****************************************************************************/
1789 void reply_search(struct smb_request *req)
1791 connection_struct *conn = req->conn;
1794 char *directory = NULL;
1795 struct smb_filename *smb_fname = NULL;
1799 struct timespec date;
1801 unsigned int numentries = 0;
1802 unsigned int maxentries = 0;
1803 bool finished = False;
1808 bool check_descend = False;
1809 bool expect_close = False;
1811 bool mask_contains_wcard = False;
1812 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1813 TALLOC_CTX *ctx = talloc_tos();
1814 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1815 struct smbXsrv_connection *xconn = req->xconn;
1816 struct smbd_server_connection *sconn = req->sconn;
1817 files_struct *fsp = NULL;
1818 const struct loadparm_substitution *lp_sub =
1819 loadparm_s3_global_substitution();
1821 START_PROFILE(SMBsearch);
1824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1828 if (req->posix_pathnames) {
1829 reply_unknown_new(req, req->cmd);
1833 /* If we were called as SMBffirst then we must expect close. */
1834 if(req->cmd == SMBffirst) {
1835 expect_close = True;
1838 reply_outbuf(req, 1, 3);
1839 maxentries = SVAL(req->vwv+0, 0);
1840 dirtype = SVAL(req->vwv+1, 0);
1841 p = (const char *)req->buf + 1;
1842 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1843 &nt_status, &mask_contains_wcard);
1844 if (!NT_STATUS_IS_OK(nt_status)) {
1845 reply_nterror(req, nt_status);
1849 if (smbreq_bufrem(req, p) < 3) {
1850 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1855 status_len = SVAL(p, 0);
1858 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1860 if (status_len == 0) {
1862 struct smb_filename *smb_dname = NULL;
1863 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1864 ucf_flags_from_smb_request(req);
1865 nt_status = filename_convert(ctx, conn,
1871 if (!NT_STATUS_IS_OK(nt_status)) {
1872 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1873 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1874 ERRSRV, ERRbadpath);
1877 reply_nterror(req, nt_status);
1881 directory = smb_fname->base_name;
1883 p = strrchr_m(directory,'/');
1884 if ((p != NULL) && (*directory != '/')) {
1885 mask = talloc_strdup(ctx, p + 1);
1886 directory = talloc_strndup(ctx, directory,
1887 PTR_DIFF(p, directory));
1889 mask = talloc_strdup(ctx, directory);
1890 directory = talloc_strdup(ctx,".");
1894 reply_nterror(req, NT_STATUS_NO_MEMORY);
1898 memset((char *)status,'\0',21);
1899 SCVAL(status,0,(dirtype & 0x1F));
1901 smb_dname = synthetic_smb_fname(talloc_tos(),
1907 if (smb_dname == NULL) {
1908 reply_nterror(req, NT_STATUS_NO_MEMORY);
1913 * As we've cut off the last component from
1914 * smb_fname we need to re-stat smb_dname
1915 * so FILE_OPEN disposition knows the directory
1918 if (req->posix_pathnames) {
1919 ret = SMB_VFS_LSTAT(conn, smb_dname);
1921 ret = SMB_VFS_STAT(conn, smb_dname);
1924 nt_status = map_nt_error_from_unix(errno);
1925 reply_nterror(req, nt_status);
1930 * Open an fsp on this directory for the dptr.
1932 nt_status = SMB_VFS_CREATE_FILE(
1935 &conn->cwd_fsp, /* dirfsp */
1936 smb_dname, /* dname */
1937 FILE_LIST_DIRECTORY, /* access_mask */
1939 FILE_SHARE_WRITE, /* share_access */
1940 FILE_OPEN, /* create_disposition*/
1941 FILE_DIRECTORY_FILE, /* create_options */
1942 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1943 NO_OPLOCK, /* oplock_request */
1945 0, /* allocation_size */
1946 0, /* private_flags */
1951 NULL, /* in_context */
1952 NULL);/* out_context */
1954 if (!NT_STATUS_IS_OK(nt_status)) {
1955 DBG_ERR("failed to open directory %s\n",
1956 smb_fname_str_dbg(smb_dname));
1957 reply_nterror(req, nt_status);
1961 nt_status = dptr_create(conn,
1971 TALLOC_FREE(smb_dname);
1973 if (!NT_STATUS_IS_OK(nt_status)) {
1975 * Use NULL here for the first parameter (req)
1976 * as this is not a client visible handle so
1977 * can'tbe part of an SMB1 chain.
1979 close_file(NULL, fsp, NORMAL_CLOSE);
1981 reply_nterror(req, nt_status);
1985 dptr_num = dptr_dnum(fsp->dptr);
1989 const char *dirpath;
1991 if (smbreq_bufrem(req, p) < 21) {
1992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1996 memcpy(status,p,21);
1997 status_dirtype = CVAL(status,0) & 0x1F;
1998 if (status_dirtype != (dirtype & 0x1F)) {
1999 dirtype = status_dirtype;
2002 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2006 dirpath = dptr_path(sconn, dptr_num);
2007 directory = talloc_strdup(ctx, dirpath);
2009 reply_nterror(req, NT_STATUS_NO_MEMORY);
2013 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
2018 * For a 'continue' search we have no string. So
2019 * check from the initial saved string.
2021 if (!req->posix_pathnames) {
2022 mask_contains_wcard = ms_has_wild(mask);
2024 dirtype = dptr_attr(sconn, dptr_num);
2027 DEBUG(4,("dptr_num is %d\n",dptr_num));
2029 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
2030 char buf[DIR_STRUCT_SIZE];
2031 memcpy(buf,status,21);
2032 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
2033 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
2034 reply_nterror(req, NT_STATUS_NO_MEMORY);
2037 dptr_fill(sconn, buf+12,dptr_num);
2038 if (dptr_zero(buf+12) && (status_len==0)) {
2043 if (message_push_blob(&req->outbuf,
2044 data_blob_const(buf, sizeof(buf)))
2046 reply_nterror(req, NT_STATUS_NO_MEMORY);
2051 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
2052 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
2054 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
2056 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2057 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
2058 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
2059 check_descend = True;
2062 for (i=numentries;(i<maxentries) && !finished;i++) {
2063 finished = !get_dir_entry(ctx,
2074 char buf[DIR_STRUCT_SIZE];
2075 memcpy(buf,status,21);
2076 if (!make_dir_struct(ctx,
2082 convert_timespec_to_time_t(date),
2083 !allow_long_path_components)) {
2084 reply_nterror(req, NT_STATUS_NO_MEMORY);
2087 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2090 if (message_push_blob(&req->outbuf,
2091 data_blob_const(buf, sizeof(buf)))
2093 reply_nterror(req, NT_STATUS_NO_MEMORY);
2103 /* If we were called as SMBffirst with smb_search_id == NULL
2104 and no entries were found then return error and close fsp->dptr
2107 if (numentries == 0) {
2110 close_file(NULL, fsp, NORMAL_CLOSE);
2113 } else if(expect_close && status_len == 0) {
2114 /* Close the dptr - we know it's gone */
2117 close_file(NULL, fsp, NORMAL_CLOSE);
2122 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2123 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2125 /* fsp may have been closed above. */
2127 close_file(NULL, fsp, NORMAL_CLOSE);
2132 if ((numentries == 0) && !mask_contains_wcard) {
2133 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2137 SSVAL(req->outbuf,smb_vwv0,numentries);
2138 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2139 SCVAL(smb_buf(req->outbuf),0,5);
2140 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2142 /* The replies here are never long name. */
2143 SSVAL(req->outbuf, smb_flg2,
2144 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2145 if (!allow_long_path_components) {
2146 SSVAL(req->outbuf, smb_flg2,
2147 SVAL(req->outbuf, smb_flg2)
2148 & (~FLAGS2_LONG_PATH_COMPONENTS));
2151 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2152 SSVAL(req->outbuf, smb_flg2,
2153 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2155 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2156 smb_fn_name(req->cmd),
2163 TALLOC_FREE(directory);
2165 TALLOC_FREE(smb_fname);
2166 END_PROFILE(SMBsearch);
2170 /****************************************************************************
2171 Reply to a fclose (stop directory search).
2172 ****************************************************************************/
2174 void reply_fclose(struct smb_request *req)
2182 bool path_contains_wcard = False;
2183 TALLOC_CTX *ctx = talloc_tos();
2184 struct smbd_server_connection *sconn = req->sconn;
2185 files_struct *fsp = NULL;
2187 START_PROFILE(SMBfclose);
2189 if (req->posix_pathnames) {
2190 reply_unknown_new(req, req->cmd);
2191 END_PROFILE(SMBfclose);
2195 p = (const char *)req->buf + 1;
2196 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2197 &err, &path_contains_wcard);
2198 if (!NT_STATUS_IS_OK(err)) {
2199 reply_nterror(req, err);
2200 END_PROFILE(SMBfclose);
2204 if (smbreq_bufrem(req, p) < 3) {
2205 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2206 END_PROFILE(SMBfclose);
2211 status_len = SVAL(p,0);
2214 if (status_len == 0) {
2215 reply_force_doserror(req, ERRSRV, ERRsrverror);
2216 END_PROFILE(SMBfclose);
2220 if (smbreq_bufrem(req, p) < 21) {
2221 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2222 END_PROFILE(SMBfclose);
2226 memcpy(status,p,21);
2228 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2230 /* Close the file - we know it's gone */
2231 close_file(NULL, fsp, NORMAL_CLOSE);
2236 reply_outbuf(req, 1, 0);
2237 SSVAL(req->outbuf,smb_vwv0,0);
2239 DEBUG(3,("search close\n"));
2241 END_PROFILE(SMBfclose);
2245 /****************************************************************************
2247 ****************************************************************************/
2249 void reply_open(struct smb_request *req)
2251 connection_struct *conn = req->conn;
2252 struct smb_filename *smb_fname = NULL;
2262 uint32_t access_mask;
2263 uint32_t share_mode;
2264 uint32_t create_disposition;
2265 uint32_t create_options = 0;
2266 uint32_t private_flags = 0;
2269 TALLOC_CTX *ctx = talloc_tos();
2271 START_PROFILE(SMBopen);
2274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2278 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2279 deny_mode = SVAL(req->vwv+0, 0);
2280 dos_attr = SVAL(req->vwv+1, 0);
2282 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2283 STR_TERMINATE, &status);
2284 if (!NT_STATUS_IS_OK(status)) {
2285 reply_nterror(req, status);
2289 if (!map_open_params_to_ntcreate(fname, deny_mode,
2290 OPENX_FILE_EXISTS_OPEN, &access_mask,
2291 &share_mode, &create_disposition,
2292 &create_options, &private_flags)) {
2293 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2297 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2299 status = filename_convert(ctx,
2306 if (!NT_STATUS_IS_OK(status)) {
2307 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2308 reply_botherror(req,
2309 NT_STATUS_PATH_NOT_COVERED,
2310 ERRSRV, ERRbadpath);
2313 reply_nterror(req, status);
2317 status = SMB_VFS_CREATE_FILE(
2320 &conn->cwd_fsp, /* dirfsp */
2321 smb_fname, /* fname */
2322 access_mask, /* access_mask */
2323 share_mode, /* share_access */
2324 create_disposition, /* create_disposition*/
2325 create_options, /* create_options */
2326 dos_attr, /* file_attributes */
2327 oplock_request, /* oplock_request */
2329 0, /* allocation_size */
2335 NULL, NULL); /* create context */
2337 if (!NT_STATUS_IS_OK(status)) {
2338 if (open_was_deferred(req->xconn, req->mid)) {
2339 /* We have re-scheduled this call. */
2343 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2344 reply_openerror(req, status);
2348 fsp = fcb_or_dos_open(
2355 bool ok = defer_smb1_sharing_violation(req);
2359 reply_openerror(req, status);
2364 /* Ensure we're pointing at the correct stat struct. */
2365 TALLOC_FREE(smb_fname);
2366 smb_fname = fsp->fsp_name;
2368 size = smb_fname->st.st_ex_size;
2369 fattr = dos_mode(conn, smb_fname);
2371 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2373 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2374 DEBUG(3,("attempt to open a directory %s\n",
2376 close_file(req, fsp, ERROR_CLOSE);
2377 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2378 ERRDOS, ERRnoaccess);
2382 reply_outbuf(req, 7, 0);
2383 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2384 SSVAL(req->outbuf,smb_vwv1,fattr);
2385 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2386 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2388 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2390 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2391 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2393 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2394 SCVAL(req->outbuf,smb_flg,
2395 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2398 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2399 SCVAL(req->outbuf,smb_flg,
2400 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2403 END_PROFILE(SMBopen);
2407 /****************************************************************************
2408 Reply to an open and X.
2409 ****************************************************************************/
2411 void reply_open_and_X(struct smb_request *req)
2413 connection_struct *conn = req->conn;
2414 struct smb_filename *smb_fname = NULL;
2416 uint16_t open_flags;
2419 /* Breakout the oplock request bits so we can set the
2420 reply bits separately. */
2421 int ex_oplock_request;
2422 int core_oplock_request;
2425 int smb_sattr = SVAL(req->vwv+4, 0);
2426 uint32_t smb_time = make_unix_date3(req->vwv+6);
2434 uint64_t allocation_size;
2435 ssize_t retval = -1;
2436 uint32_t access_mask;
2437 uint32_t share_mode;
2438 uint32_t create_disposition;
2439 uint32_t create_options = 0;
2440 uint32_t private_flags = 0;
2442 TALLOC_CTX *ctx = talloc_tos();
2444 START_PROFILE(SMBopenX);
2446 if (req->wct < 15) {
2447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2451 open_flags = SVAL(req->vwv+2, 0);
2452 deny_mode = SVAL(req->vwv+3, 0);
2453 smb_attr = SVAL(req->vwv+5, 0);
2454 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2455 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2456 oplock_request = ex_oplock_request | core_oplock_request;
2457 smb_ofun = SVAL(req->vwv+8, 0);
2458 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2460 /* If it's an IPC, pass off the pipe handler. */
2462 if (lp_nt_pipe_support()) {
2463 reply_open_pipe_and_X(conn, req);
2465 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2470 /* XXXX we need to handle passed times, sattr and flags */
2471 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2472 STR_TERMINATE, &status);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 reply_nterror(req, status);
2478 if (!map_open_params_to_ntcreate(fname, deny_mode,
2480 &access_mask, &share_mode,
2481 &create_disposition,
2484 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2488 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2490 status = filename_convert(ctx,
2497 if (!NT_STATUS_IS_OK(status)) {
2498 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2499 reply_botherror(req,
2500 NT_STATUS_PATH_NOT_COVERED,
2501 ERRSRV, ERRbadpath);
2504 reply_nterror(req, status);
2508 status = SMB_VFS_CREATE_FILE(
2511 &conn->cwd_fsp, /* dirfsp */
2512 smb_fname, /* fname */
2513 access_mask, /* access_mask */
2514 share_mode, /* share_access */
2515 create_disposition, /* create_disposition*/
2516 create_options, /* create_options */
2517 smb_attr, /* file_attributes */
2518 oplock_request, /* oplock_request */
2520 0, /* allocation_size */
2525 &smb_action, /* pinfo */
2526 NULL, NULL); /* create context */
2528 if (!NT_STATUS_IS_OK(status)) {
2529 if (open_was_deferred(req->xconn, req->mid)) {
2530 /* We have re-scheduled this call. */
2534 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2535 reply_openerror(req, status);
2539 fsp = fcb_or_dos_open(
2546 bool ok = defer_smb1_sharing_violation(req);
2550 reply_openerror(req, status);
2555 smb_action = FILE_WAS_OPENED;
2558 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2559 if the file is truncated or created. */
2560 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2561 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2562 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2563 close_file(req, fsp, ERROR_CLOSE);
2564 reply_nterror(req, NT_STATUS_DISK_FULL);
2567 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2569 close_file(req, fsp, ERROR_CLOSE);
2570 reply_nterror(req, NT_STATUS_DISK_FULL);
2573 status = vfs_stat_fsp(fsp);
2574 if (!NT_STATUS_IS_OK(status)) {
2575 close_file(req, fsp, ERROR_CLOSE);
2576 reply_nterror(req, status);
2581 fattr = dos_mode(conn, fsp->fsp_name);
2582 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2583 close_file(req, fsp, ERROR_CLOSE);
2584 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2587 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2589 /* If the caller set the extended oplock request bit
2590 and we granted one (by whatever means) - set the
2591 correct bit for extended oplock reply.
2594 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2595 smb_action |= EXTENDED_OPLOCK_GRANTED;
2598 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2599 smb_action |= EXTENDED_OPLOCK_GRANTED;
2602 /* If the caller set the core oplock request bit
2603 and we granted one (by whatever means) - set the
2604 correct bit for core oplock reply.
2607 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2608 reply_outbuf(req, 19, 0);
2610 reply_outbuf(req, 15, 0);
2613 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2614 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2616 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2617 SCVAL(req->outbuf, smb_flg,
2618 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2621 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2622 SCVAL(req->outbuf, smb_flg,
2623 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2626 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2627 SSVAL(req->outbuf,smb_vwv3,fattr);
2628 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2629 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2631 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2633 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2634 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2635 SSVAL(req->outbuf,smb_vwv11,smb_action);
2637 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2638 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2642 TALLOC_FREE(smb_fname);
2643 END_PROFILE(SMBopenX);
2647 /****************************************************************************
2648 Reply to a SMBulogoffX.
2649 ****************************************************************************/
2651 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2652 struct smbXsrv_session *session);
2653 static void reply_ulogoffX_done(struct tevent_req *req);
2655 void reply_ulogoffX(struct smb_request *smb1req)
2657 struct timeval now = timeval_current();
2658 struct smbXsrv_session *session = NULL;
2659 struct tevent_req *req;
2663 * Don't setup the profile charge here, take
2664 * it in reply_ulogoffX_done(). Not strictly correct
2665 * but better than the other SMB1 async
2666 * code that double-charges at the moment.
2669 status = smb1srv_session_lookup(smb1req->xconn,
2671 timeval_to_nttime(&now),
2673 if (!NT_STATUS_IS_OK(status)) {
2674 /* Not going async, profile here. */
2675 START_PROFILE(SMBulogoffX);
2676 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2677 (unsigned long long)smb1req->vuid);
2679 smb1req->vuid = UID_FIELD_INVALID;
2680 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2681 END_PROFILE(SMBulogoffX);
2685 req = reply_ulogoffX_send(smb1req, session);
2687 /* Not going async, profile here. */
2688 START_PROFILE(SMBulogoffX);
2689 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2690 END_PROFILE(SMBulogoffX);
2694 /* We're async. This will complete later. */
2695 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2699 struct reply_ulogoffX_state {
2700 struct tevent_queue *wait_queue;
2701 struct smbXsrv_session *session;
2704 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2706 /****************************************************************************
2707 Async SMB1 ulogoffX.
2708 Note, on failure here we deallocate and return NULL to allow the caller to
2709 SMB1 return an error of ERRnomem immediately.
2710 ****************************************************************************/
2712 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2713 struct smbXsrv_session *session)
2715 struct tevent_req *req;
2716 struct reply_ulogoffX_state *state;
2717 struct tevent_req *subreq;
2719 struct smbd_server_connection *sconn = session->client->sconn;
2720 uint64_t vuid = session->global->session_wire_id;
2722 req = tevent_req_create(smb1req, &state,
2723 struct reply_ulogoffX_state);
2727 state->wait_queue = tevent_queue_create(state,
2728 "reply_ulogoffX_wait_queue");
2729 if (tevent_req_nomem(state->wait_queue, req)) {
2733 state->session = session;
2736 * Make sure that no new request will be able to use this session.
2737 * This ensures that once all outstanding fsp->aio_requests
2738 * on this session are done, we are safe to close it.
2740 session->status = NT_STATUS_USER_SESSION_DELETED;
2742 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2743 if (fsp->vuid != vuid) {
2747 * Flag the file as close in progress.
2748 * This will prevent any more IO being
2751 fsp->fsp_flags.closing = true;
2753 if (fsp->num_aio_requests > 0) {
2755 * Now wait until all aio requests on this fsp are
2758 * We don't set a callback, as we just want to block the
2759 * wait queue and the talloc_free() of fsp->aio_request
2760 * will remove the item from the wait queue.
2762 subreq = tevent_queue_wait_send(fsp->aio_requests,
2765 if (tevent_req_nomem(subreq, req)) {
2773 * Now we add our own waiter to the end of the queue,
2774 * this way we get notified when all pending requests are finished
2775 * and reply to the outstanding SMB1 request.
2777 subreq = tevent_queue_wait_send(state,
2780 if (tevent_req_nomem(subreq, req)) {
2786 * We're really going async - move the SMB1 request from
2787 * a talloc stackframe above us to the sconn talloc-context.
2788 * We need this to stick around until the wait_done
2789 * callback is invoked.
2791 smb1req = talloc_move(sconn, &smb1req);
2793 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2798 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2800 struct tevent_req *req = tevent_req_callback_data(
2801 subreq, struct tevent_req);
2803 tevent_queue_wait_recv(subreq);
2804 TALLOC_FREE(subreq);
2805 tevent_req_done(req);
2808 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2810 return tevent_req_simple_recv_ntstatus(req);
2813 static void reply_ulogoffX_done(struct tevent_req *req)
2815 struct smb_request *smb1req = tevent_req_callback_data(
2816 req, struct smb_request);
2817 struct reply_ulogoffX_state *state = tevent_req_data(req,
2818 struct reply_ulogoffX_state);
2819 struct smbXsrv_session *session = state->session;
2823 * Take the profile charge here. Not strictly
2824 * correct but better than the other SMB1 async
2825 * code that double-charges at the moment.
2827 START_PROFILE(SMBulogoffX);
2829 status = reply_ulogoffX_recv(req);
2831 if (!NT_STATUS_IS_OK(status)) {
2832 TALLOC_FREE(smb1req);
2833 END_PROFILE(SMBulogoffX);
2834 exit_server(__location__ ": reply_ulogoffX_recv failed");
2838 status = smbXsrv_session_logoff(session);
2839 if (!NT_STATUS_IS_OK(status)) {
2840 TALLOC_FREE(smb1req);
2841 END_PROFILE(SMBulogoffX);
2842 exit_server(__location__ ": smbXsrv_session_logoff failed");
2846 TALLOC_FREE(session);
2848 reply_outbuf(smb1req, 2, 0);
2849 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2850 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2852 DBG_NOTICE("ulogoffX vuid=%llu\n",
2853 (unsigned long long)smb1req->vuid);
2855 smb1req->vuid = UID_FIELD_INVALID;
2857 * The following call is needed to push the
2858 * reply data back out the socket after async
2859 * return. Plus it frees smb1req.
2861 smb_request_done(smb1req);
2862 END_PROFILE(SMBulogoffX);
2865 /****************************************************************************
2866 Reply to a mknew or a create.
2867 ****************************************************************************/
2869 void reply_mknew(struct smb_request *req)
2871 connection_struct *conn = req->conn;
2872 struct smb_filename *smb_fname = NULL;
2875 struct smb_file_time ft;
2877 int oplock_request = 0;
2879 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2880 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2881 uint32_t create_disposition;
2882 uint32_t create_options = 0;
2884 TALLOC_CTX *ctx = talloc_tos();
2886 START_PROFILE(SMBcreate);
2887 init_smb_file_time(&ft);
2890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2894 fattr = SVAL(req->vwv+0, 0);
2895 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2897 if (req->cmd == SMBmknew) {
2898 /* We should fail if file exists. */
2899 create_disposition = FILE_CREATE;
2901 /* Create if file doesn't exist, truncate if it does. */
2902 create_disposition = FILE_OVERWRITE_IF;
2906 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2908 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2909 STR_TERMINATE, &status);
2910 if (!NT_STATUS_IS_OK(status)) {
2911 reply_nterror(req, status);
2915 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2916 status = filename_convert(ctx,
2923 if (!NT_STATUS_IS_OK(status)) {
2924 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2925 reply_botherror(req,
2926 NT_STATUS_PATH_NOT_COVERED,
2927 ERRSRV, ERRbadpath);
2930 reply_nterror(req, status);
2934 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2935 DEBUG(0,("Attempt to create file (%s) with volid set - "
2936 "please report this\n",
2937 smb_fname_str_dbg(smb_fname)));
2940 status = SMB_VFS_CREATE_FILE(
2943 &conn->cwd_fsp, /* dirfsp */
2944 smb_fname, /* fname */
2945 access_mask, /* access_mask */
2946 share_mode, /* share_access */
2947 create_disposition, /* create_disposition*/
2948 create_options, /* create_options */
2949 fattr, /* file_attributes */
2950 oplock_request, /* oplock_request */
2952 0, /* allocation_size */
2953 0, /* private_flags */
2958 NULL, NULL); /* create context */
2960 if (!NT_STATUS_IS_OK(status)) {
2961 if (open_was_deferred(req->xconn, req->mid)) {
2962 /* We have re-scheduled this call. */
2965 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2966 bool ok = defer_smb1_sharing_violation(req);
2971 reply_openerror(req, status);
2975 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2976 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2977 if (!NT_STATUS_IS_OK(status)) {
2978 END_PROFILE(SMBcreate);
2982 reply_outbuf(req, 1, 0);
2983 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2985 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2986 SCVAL(req->outbuf,smb_flg,
2987 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2990 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2991 SCVAL(req->outbuf,smb_flg,
2992 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2995 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2996 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2997 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2998 (unsigned int)fattr));
3001 TALLOC_FREE(smb_fname);
3002 END_PROFILE(SMBcreate);
3006 /****************************************************************************
3007 Reply to a create temporary file.
3008 ****************************************************************************/
3010 void reply_ctemp(struct smb_request *req)
3012 connection_struct *conn = req->conn;
3013 struct smb_filename *smb_fname = NULL;
3014 char *wire_name = NULL;
3023 TALLOC_CTX *ctx = talloc_tos();
3025 START_PROFILE(SMBctemp);
3028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3032 fattr = SVAL(req->vwv+0, 0);
3033 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
3035 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
3036 STR_TERMINATE, &status);
3037 if (!NT_STATUS_IS_OK(status)) {
3038 reply_nterror(req, status);
3042 for (i = 0; i < 10; i++) {
3044 fname = talloc_asprintf(ctx,
3047 generate_random_str_list(ctx, 5, "0123456789"));
3049 fname = talloc_asprintf(ctx,
3051 generate_random_str_list(ctx, 5, "0123456789"));
3055 reply_nterror(req, NT_STATUS_NO_MEMORY);
3059 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
3060 status = filename_convert(ctx, conn,
3066 if (!NT_STATUS_IS_OK(status)) {
3067 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3068 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3069 ERRSRV, ERRbadpath);
3072 reply_nterror(req, status);
3076 /* Create the file. */
3077 status = SMB_VFS_CREATE_FILE(
3080 &conn->cwd_fsp, /* dirfsp */
3081 smb_fname, /* fname */
3082 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
3083 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
3084 FILE_CREATE, /* create_disposition*/
3085 0, /* create_options */
3086 fattr, /* file_attributes */
3087 oplock_request, /* oplock_request */
3089 0, /* allocation_size */
3090 0, /* private_flags */
3095 NULL, NULL); /* create context */
3097 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3099 TALLOC_FREE(smb_fname);
3103 if (!NT_STATUS_IS_OK(status)) {
3104 if (open_was_deferred(req->xconn, req->mid)) {
3105 /* We have re-scheduled this call. */
3108 if (NT_STATUS_EQUAL(
3109 status, NT_STATUS_SHARING_VIOLATION)) {
3110 bool ok = defer_smb1_sharing_violation(req);
3115 reply_openerror(req, status);
3123 /* Collision after 10 times... */
3124 reply_nterror(req, status);
3128 reply_outbuf(req, 1, 0);
3129 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3131 /* the returned filename is relative to the directory */
3132 s = strrchr_m(fsp->fsp_name->base_name, '/');
3134 s = fsp->fsp_name->base_name;
3140 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3141 thing in the byte section. JRA */
3142 SSVALS(p, 0, -1); /* what is this? not in spec */
3144 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3146 reply_nterror(req, NT_STATUS_NO_MEMORY);
3150 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3151 SCVAL(req->outbuf, smb_flg,
3152 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3155 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3156 SCVAL(req->outbuf, smb_flg,
3157 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3160 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3161 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3162 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
3164 TALLOC_FREE(smb_fname);
3165 TALLOC_FREE(wire_name);
3166 END_PROFILE(SMBctemp);
3170 /*******************************************************************
3171 Check if a user is allowed to rename a file.
3172 ********************************************************************/
3174 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3177 if (!CAN_WRITE(conn)) {
3178 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3181 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3182 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3183 /* Only bother to read the DOS attribute if we might deny the
3184 rename on the grounds of attribute mismatch. */
3185 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3186 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3187 return NT_STATUS_NO_SUCH_FILE;
3191 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3192 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3193 return NT_STATUS_OK;
3196 /* If no pathnames are open below this
3197 directory, allow the rename. */
3199 if (lp_strict_rename(SNUM(conn))) {
3201 * Strict rename, check open file db.
3203 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3204 return NT_STATUS_ACCESS_DENIED;
3206 } else if (file_find_subpath(fsp)) {
3208 * No strict rename, just look in local process.
3210 return NT_STATUS_ACCESS_DENIED;
3212 return NT_STATUS_OK;
3215 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3216 return NT_STATUS_OK;
3219 return NT_STATUS_ACCESS_DENIED;
3222 /*******************************************************************
3223 * unlink a file with all relevant access checks
3224 *******************************************************************/
3226 static NTSTATUS do_unlink(connection_struct *conn,
3227 struct smb_request *req,
3228 struct smb_filename *smb_fname,
3233 uint32_t dirtype_orig = dirtype;
3236 bool posix_paths = (req != NULL && req->posix_pathnames);
3237 struct smb2_create_blobs *posx = NULL;
3239 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3240 smb_fname_str_dbg(smb_fname),
3243 if (!CAN_WRITE(conn)) {
3244 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3248 ret = SMB_VFS_LSTAT(conn, smb_fname);
3250 ret = SMB_VFS_STAT(conn, smb_fname);
3253 return map_nt_error_from_unix(errno);
3256 fattr = dos_mode(conn, smb_fname);
3258 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3259 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3262 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3264 return NT_STATUS_NO_SUCH_FILE;
3267 if (!dir_check_ftype(fattr, dirtype)) {
3268 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3269 return NT_STATUS_FILE_IS_A_DIRECTORY;
3271 return NT_STATUS_NO_SUCH_FILE;
3274 if (dirtype_orig & 0x8000) {
3275 /* These will never be set for POSIX. */
3276 return NT_STATUS_NO_SUCH_FILE;
3280 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3281 return NT_STATUS_FILE_IS_A_DIRECTORY;
3284 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3285 return NT_STATUS_NO_SUCH_FILE;
3288 if (dirtype & 0xFF00) {
3289 /* These will never be set for POSIX. */
3290 return NT_STATUS_NO_SUCH_FILE;
3295 return NT_STATUS_NO_SUCH_FILE;
3298 /* Can't delete a directory. */
3299 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3300 return NT_STATUS_FILE_IS_A_DIRECTORY;
3305 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3306 return NT_STATUS_OBJECT_NAME_INVALID;
3307 #endif /* JRATEST */
3310 status = make_smb2_posix_create_ctx(
3311 talloc_tos(), &posx, 0777);
3312 if (!NT_STATUS_IS_OK(status)) {
3313 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3319 /* On open checks the open itself will check the share mode, so
3320 don't do it here as we'll get it wrong. */
3322 status = SMB_VFS_CREATE_FILE
3325 &conn->cwd_fsp, /* dirfsp */
3326 smb_fname, /* fname */
3327 DELETE_ACCESS, /* access_mask */
3328 FILE_SHARE_NONE, /* share_access */
3329 FILE_OPEN, /* create_disposition*/
3330 FILE_NON_DIRECTORY_FILE, /* create_options */
3331 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3332 0, /* oplock_request */
3334 0, /* allocation_size */
3335 0, /* private_flags */
3340 posx, /* in_context_blobs */
3341 NULL); /* out_context_blobs */
3345 if (!NT_STATUS_IS_OK(status)) {
3346 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3347 nt_errstr(status)));
3351 status = can_set_delete_on_close(fsp, fattr);
3352 if (!NT_STATUS_IS_OK(status)) {
3353 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3355 smb_fname_str_dbg(smb_fname),
3356 nt_errstr(status)));
3357 close_file(req, fsp, NORMAL_CLOSE);
3361 /* The set is across all open files on this dev/inode pair. */
3362 if (!set_delete_on_close(fsp, True,
3363 conn->session_info->security_token,
3364 conn->session_info->unix_token)) {
3365 close_file(req, fsp, NORMAL_CLOSE);
3366 return NT_STATUS_ACCESS_DENIED;
3369 return close_file(req, fsp, NORMAL_CLOSE);
3372 /****************************************************************************
3373 The guts of the unlink command, split out so it may be called by the NT SMB
3375 ****************************************************************************/
3377 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3378 uint32_t dirtype, struct smb_filename *smb_fname,
3381 char *fname_dir = NULL;
3382 char *fname_mask = NULL;
3384 NTSTATUS status = NT_STATUS_OK;
3385 struct smb_filename *smb_fname_dir = NULL;
3386 TALLOC_CTX *ctx = talloc_tos();
3388 /* Split up the directory from the filename/mask. */
3389 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3390 &fname_dir, &fname_mask);
3391 if (!NT_STATUS_IS_OK(status)) {
3396 * We should only check the mangled cache
3397 * here if unix_convert failed. This means
3398 * that the path in 'mask' doesn't exist
3399 * on the file system and so we need to look
3400 * for a possible mangle. This patch from
3401 * Tine Smukavec <valentin.smukavec@hermes.si>.
3404 if (!VALID_STAT(smb_fname->st) &&
3405 mangle_is_mangled(fname_mask, conn->params)) {
3406 char *new_mask = NULL;
3407 mangle_lookup_name_from_8_3(ctx, fname_mask,
3408 &new_mask, conn->params);
3410 TALLOC_FREE(fname_mask);
3411 fname_mask = new_mask;
3418 * Only one file needs to be unlinked. Append the mask back
3419 * onto the directory.
3421 TALLOC_FREE(smb_fname->base_name);
3422 if (ISDOT(fname_dir)) {
3423 /* Ensure we use canonical names on open. */
3424 smb_fname->base_name = talloc_asprintf(smb_fname,
3428 smb_fname->base_name = talloc_asprintf(smb_fname,
3433 if (!smb_fname->base_name) {
3434 status = NT_STATUS_NO_MEMORY;
3438 dirtype = FILE_ATTRIBUTE_NORMAL;
3441 status = check_name(conn, smb_fname);
3442 if (!NT_STATUS_IS_OK(status)) {
3446 status = do_unlink(conn, req, smb_fname, dirtype);
3447 if (!NT_STATUS_IS_OK(status)) {
3453 struct smb_Dir *dir_hnd = NULL;
3455 const char *dname = NULL;
3456 char *talloced = NULL;
3458 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3459 status = NT_STATUS_OBJECT_NAME_INVALID;
3463 dirtype = FILE_ATTRIBUTE_NORMAL;
3466 if (strequal(fname_mask,"????????.???")) {
3467 TALLOC_FREE(fname_mask);
3468 fname_mask = talloc_strdup(ctx, "*");
3470 status = NT_STATUS_NO_MEMORY;
3475 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3481 if (smb_fname_dir == NULL) {
3482 status = NT_STATUS_NO_MEMORY;
3486 status = check_name(conn, smb_fname_dir);
3487 if (!NT_STATUS_IS_OK(status)) {
3491 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3493 if (dir_hnd == NULL) {
3494 status = map_nt_error_from_unix(errno);
3498 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3499 the pattern matches against the long name, otherwise the short name
3500 We don't implement this yet XXXX
3503 status = NT_STATUS_NO_SUCH_FILE;
3505 while ((dname = ReadDirName(dir_hnd, &offset,
3506 &smb_fname->st, &talloced))) {
3507 TALLOC_CTX *frame = talloc_stackframe();
3509 struct smb_filename *f = NULL;
3511 if (!is_visible_file(conn,
3517 TALLOC_FREE(talloced);
3521 /* Quick check for "." and ".." */
3522 if (ISDOT(dname) || ISDOTDOT(dname)) {
3524 TALLOC_FREE(talloced);
3528 if(!mask_match(dname, fname_mask,
3529 conn->case_sensitive)) {
3531 TALLOC_FREE(talloced);
3535 if (ISDOT(fname_dir)) {
3536 /* Ensure we use canonical names on open. */
3537 p = talloc_asprintf(smb_fname, "%s", dname);
3539 p = talloc_asprintf(smb_fname, "%s/%s",
3543 TALLOC_FREE(dir_hnd);
3544 status = NT_STATUS_NO_MEMORY;
3546 TALLOC_FREE(talloced);
3549 f = synthetic_smb_fname(frame,
3556 TALLOC_FREE(dir_hnd);
3557 status = NT_STATUS_NO_MEMORY;
3559 TALLOC_FREE(talloced);
3563 status = check_name(conn, f);
3564 if (!NT_STATUS_IS_OK(status)) {
3565 TALLOC_FREE(dir_hnd);
3567 TALLOC_FREE(talloced);
3571 status = do_unlink(conn, req, f, dirtype);
3572 if (!NT_STATUS_IS_OK(status)) {
3573 TALLOC_FREE(dir_hnd);
3575 TALLOC_FREE(talloced);
3580 DBG_DEBUG("successful unlink [%s]\n",
3581 smb_fname_str_dbg(f));
3584 TALLOC_FREE(talloced);
3586 TALLOC_FREE(dir_hnd);
3589 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3590 status = map_nt_error_from_unix(errno);
3594 TALLOC_FREE(smb_fname_dir);
3595 TALLOC_FREE(fname_dir);
3596 TALLOC_FREE(fname_mask);
3600 /****************************************************************************
3602 ****************************************************************************/
3604 void reply_unlink(struct smb_request *req)
3606 connection_struct *conn = req->conn;
3608 struct smb_filename *smb_fname = NULL;
3611 bool path_contains_wcard = False;
3612 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3613 ucf_flags_from_smb_request(req);
3614 TALLOC_CTX *ctx = talloc_tos();
3616 START_PROFILE(SMBunlink);
3619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3623 dirtype = SVAL(req->vwv+0, 0);
3625 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3626 STR_TERMINATE, &status,
3627 &path_contains_wcard);
3628 if (!NT_STATUS_IS_OK(status)) {
3629 reply_nterror(req, status);
3633 status = filename_convert(ctx, conn,
3637 &path_contains_wcard,
3639 if (!NT_STATUS_IS_OK(status)) {
3640 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3641 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3642 ERRSRV, ERRbadpath);
3645 reply_nterror(req, status);
3649 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3651 status = unlink_internals(conn, req, dirtype, smb_fname,
3652 path_contains_wcard);
3653 if (!NT_STATUS_IS_OK(status)) {
3654 if (open_was_deferred(req->xconn, req->mid)) {
3655 /* We have re-scheduled this call. */
3658 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3659 bool ok = defer_smb1_sharing_violation(req);
3664 reply_nterror(req, status);
3668 reply_outbuf(req, 0, 0);
3670 TALLOC_FREE(smb_fname);
3671 END_PROFILE(SMBunlink);
3675 /****************************************************************************
3677 ****************************************************************************/
3679 static void fail_readraw(void)
3681 const char *errstr = talloc_asprintf(talloc_tos(),
3682 "FAIL ! reply_readbraw: socket write fail (%s)",
3687 exit_server_cleanly(errstr);
3690 /****************************************************************************
3691 Fake (read/write) sendfile. Returns -1 on read or write fail.
3692 ****************************************************************************/
3694 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3695 off_t startpos, size_t nread)
3698 size_t tosend = nread;
3705 bufsize = MIN(nread, 65536);
3707 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3711 while (tosend > 0) {
3715 cur_read = MIN(tosend, bufsize);
3716 ret = read_file(fsp,buf,startpos,cur_read);
3722 /* If we had a short read, fill with zeros. */
3723 if (ret < cur_read) {
3724 memset(buf + ret, '\0', cur_read - ret);
3727 ret = write_data(xconn->transport.sock, buf, cur_read);
3728 if (ret != cur_read) {
3729 int saved_errno = errno;
3731 * Try and give an error message saying what
3734 DEBUG(0, ("write_data failed for client %s. "
3736 smbXsrv_connection_dbg(xconn),
3737 strerror(saved_errno)));
3739 errno = saved_errno;
3743 startpos += cur_read;
3747 return (ssize_t)nread;
3750 /****************************************************************************
3751 Deal with the case of sendfile reading less bytes from the file than
3752 requested. Fill with zeros (all we can do). Returns 0 on success
3753 ****************************************************************************/
3755 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3761 #define SHORT_SEND_BUFSIZE 1024
3762 if (nread < headersize) {
3763 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3764 "header for file %s (%s). Terminating\n",
3765 fsp_str_dbg(fsp), strerror(errno)));
3769 nread -= headersize;
3771 if (nread < smb_maxcnt) {
3772 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3774 DEBUG(0,("sendfile_short_send: malloc failed "
3775 "for file %s (%s). Terminating\n",
3776 fsp_str_dbg(fsp), strerror(errno)));
3780 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3781 "with zeros !\n", fsp_str_dbg(fsp)));
3783 while (nread < smb_maxcnt) {
3785 * We asked for the real file size and told sendfile
3786 * to not go beyond the end of the file. But it can
3787 * happen that in between our fstat call and the
3788 * sendfile call the file was truncated. This is very
3789 * bad because we have already announced the larger
3790 * number of bytes to the client.
3792 * The best we can do now is to send 0-bytes, just as
3793 * a read from a hole in a sparse file would do.
3795 * This should happen rarely enough that I don't care
3796 * about efficiency here :-)
3801 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3802 ret = write_data(xconn->transport.sock, buf, to_write);
3803 if (ret != to_write) {
3804 int saved_errno = errno;
3806 * Try and give an error message saying what
3809 DEBUG(0, ("write_data failed for client %s. "
3811 smbXsrv_connection_dbg(xconn),
3812 strerror(saved_errno)));
3813 errno = saved_errno;
3824 /****************************************************************************
3825 Return a readbraw error (4 bytes of zero).
3826 ****************************************************************************/
3828 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3834 smbd_lock_socket(xconn);
3835 if (write_data(xconn->transport.sock,header,4) != 4) {
3836 int saved_errno = errno;
3838 * Try and give an error message saying what
3841 DEBUG(0, ("write_data failed for client %s. "
3843 smbXsrv_connection_dbg(xconn),
3844 strerror(saved_errno)));
3845 errno = saved_errno;
3849 smbd_unlock_socket(xconn);
3852 /*******************************************************************
3853 Ensure we don't use sendfile if server smb signing is active.
3854 ********************************************************************/
3856 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3858 bool sign_active = false;
3860 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3861 if (get_Protocol() < PROTOCOL_NT1) {
3864 if (signing_state) {
3865 sign_active = smb_signing_is_active(signing_state);
3867 return (lp__use_sendfile(snum) &&
3868 (get_remote_arch() != RA_WIN95) &&
3871 /****************************************************************************
3872 Use sendfile in readbraw.
3873 ****************************************************************************/
3875 static void send_file_readbraw(connection_struct *conn,
3876 struct smb_request *req,
3882 struct smbXsrv_connection *xconn = req->xconn;
3883 char *outbuf = NULL;
3887 * We can only use sendfile on a non-chained packet
3888 * but we can use on a non-oplocked file. tridge proved this
3889 * on a train in Germany :-). JRA.
3890 * reply_readbraw has already checked the length.
3893 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3894 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3895 ssize_t sendfile_read = -1;
3897 DATA_BLOB header_blob;
3899 _smb_setlen(header,nread);
3900 header_blob = data_blob_const(header, 4);
3902 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3903 &header_blob, startpos,
3905 if (sendfile_read == -1) {
3906 /* Returning ENOSYS means no data at all was sent.
3907 * Do this as a normal read. */
3908 if (errno == ENOSYS) {
3909 goto normal_readbraw;
3913 * Special hack for broken Linux with no working sendfile. If we
3914 * return EINTR we sent the header but not the rest of the data.
3915 * Fake this up by doing read/write calls.
3917 if (errno == EINTR) {
3918 /* Ensure we don't do this again. */
3919 set_use_sendfile(SNUM(conn), False);
3920 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3922 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3923 DEBUG(0,("send_file_readbraw: "
3924 "fake_sendfile failed for "
3928 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3933 DEBUG(0,("send_file_readbraw: sendfile failed for "
3934 "file %s (%s). Terminating\n",
3935 fsp_str_dbg(fsp), strerror(errno)));
3936 exit_server_cleanly("send_file_readbraw sendfile failed");
3937 } else if (sendfile_read == 0) {
3939 * Some sendfile implementations return 0 to indicate
3940 * that there was a short read, but nothing was
3941 * actually written to the socket. In this case,
3942 * fallback to the normal read path so the header gets
3943 * the correct byte count.
3945 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3946 "bytes falling back to the normal read: "
3947 "%s\n", fsp_str_dbg(fsp)));
3948 goto normal_readbraw;
3951 /* Deal with possible short send. */
3952 if (sendfile_read != 4+nread) {
3953 ret = sendfile_short_send(xconn, fsp,
3954 sendfile_read, 4, nread);
3964 outbuf = talloc_array(NULL, char, nread+4);
3966 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3967 (unsigned)(nread+4)));
3968 reply_readbraw_error(xconn);
3973 ret = read_file(fsp,outbuf+4,startpos,nread);
3974 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3983 _smb_setlen(outbuf,ret);
3984 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3985 int saved_errno = errno;
3987 * Try and give an error message saying what
3990 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3991 smbXsrv_connection_dbg(xconn),
3992 strerror(saved_errno)));
3993 errno = saved_errno;
3998 TALLOC_FREE(outbuf);
4001 /****************************************************************************
4002 Reply to a readbraw (core+ protocol).
4003 ****************************************************************************/
4005 void reply_readbraw(struct smb_request *req)
4007 connection_struct *conn = req->conn;
4008 struct smbXsrv_connection *xconn = req->xconn;
4009 ssize_t maxcount,mincount;
4013 struct lock_struct lock;
4017 START_PROFILE(SMBreadbraw);
4019 if (srv_is_signing_active(xconn) || req->encrypted) {
4020 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
4021 "raw reads/writes are disallowed.");
4025 reply_readbraw_error(xconn);
4026 END_PROFILE(SMBreadbraw);
4030 if (xconn->smb1.echo_handler.trusted_fde) {
4031 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
4032 "'async smb echo handler = yes'\n"));
4033 reply_readbraw_error(xconn);
4034 END_PROFILE(SMBreadbraw);
4039 * Special check if an oplock break has been issued
4040 * and the readraw request croses on the wire, we must
4041 * return a zero length response here.
4044 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4047 * We have to do a check_fsp by hand here, as
4048 * we must always return 4 zero bytes on error,
4054 conn != fsp->conn ||
4055 req->vuid != fsp->vuid ||
4056 fsp->fsp_flags.is_directory ||
4060 * fsp could be NULL here so use the value from the packet. JRA.
4062 DEBUG(3,("reply_readbraw: fnum %d not valid "
4064 (int)SVAL(req->vwv+0, 0)));
4065 reply_readbraw_error(xconn);
4066 END_PROFILE(SMBreadbraw);
4070 /* Do a "by hand" version of CHECK_READ. */
4071 if (!(fsp->fsp_flags.can_read ||
4072 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
4073 (fsp->access_mask & FILE_EXECUTE)))) {
4074 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4075 (int)SVAL(req->vwv+0, 0)));
4076 reply_readbraw_error(xconn);
4077 END_PROFILE(SMBreadbraw);
4081 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
4082 if(req->wct == 10) {
4084 * This is a large offset (64 bit) read.
4087 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4090 DEBUG(0,("reply_readbraw: negative 64 bit "
4091 "readraw offset (%.0f) !\n",
4092 (double)startpos ));
4093 reply_readbraw_error(xconn);
4094 END_PROFILE(SMBreadbraw);
4099 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4100 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4102 /* ensure we don't overrun the packet size */
4103 maxcount = MIN(65535,maxcount);
4105 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4106 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4109 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4110 reply_readbraw_error(xconn);
4111 END_PROFILE(SMBreadbraw);
4115 status = vfs_stat_fsp(fsp);
4116 if (NT_STATUS_IS_OK(status)) {
4117 size = fsp->fsp_name->st.st_ex_size;
4120 if (startpos >= size) {
4123 nread = MIN(maxcount,(size - startpos));
4126 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4127 if (nread < mincount)
4131 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4132 "min=%lu nread=%lu\n",
4133 fsp_fnum_dbg(fsp), (double)startpos,
4134 (unsigned long)maxcount,
4135 (unsigned long)mincount,
4136 (unsigned long)nread ) );
4138 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4140 DEBUG(5,("reply_readbraw finished\n"));
4142 END_PROFILE(SMBreadbraw);
4147 #define DBGC_CLASS DBGC_LOCKING
4149 /****************************************************************************
4150 Reply to a lockread (core+ protocol).
4151 ****************************************************************************/
4153 static void reply_lockread_locked(struct tevent_req *subreq);
4155 void reply_lockread(struct smb_request *req)
4157 struct tevent_req *subreq = NULL;
4158 connection_struct *conn = req->conn;
4160 struct smbd_lock_element *lck = NULL;
4162 START_PROFILE(SMBlockread);
4165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4166 END_PROFILE(SMBlockread);
4170 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4172 if (!check_fsp(conn, req, fsp)) {
4173 END_PROFILE(SMBlockread);
4177 if (!CHECK_READ(fsp,req)) {
4178 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4179 END_PROFILE(SMBlockread);
4183 lck = talloc(req, struct smbd_lock_element);
4185 reply_nterror(req, NT_STATUS_NO_MEMORY);
4186 END_PROFILE(SMBlockread);
4191 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4192 * protocol request that predates the read/write lock concept.
4193 * Thus instead of asking for a read lock here we need to ask
4194 * for a write lock. JRA.
4195 * Note that the requested lock size is unaffected by max_send.
4198 *lck = (struct smbd_lock_element) {
4199 .req_guid = smbd_request_guid(req, 0),
4200 .smblctx = req->smbpid,
4201 .brltype = WRITE_LOCK,
4202 .count = SVAL(req->vwv+1, 0),
4203 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4206 subreq = smbd_smb1_do_locks_send(
4212 false, /* large_offset */
4216 if (subreq == NULL) {
4217 reply_nterror(req, NT_STATUS_NO_MEMORY);
4218 END_PROFILE(SMBlockread);
4221 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4222 END_PROFILE(SMBlockread);
4225 static void reply_lockread_locked(struct tevent_req *subreq)
4227 struct smb_request *req = NULL;
4233 size_t numtoread, maxtoread;
4234 struct files_struct *fsp = NULL;
4237 START_PROFILE(SMBlockread);
4239 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4242 status = smbd_smb1_do_locks_recv(subreq);
4243 TALLOC_FREE(subreq);
4245 if (!NT_STATUS_IS_OK(status)) {
4246 reply_nterror(req, status);
4250 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4252 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4256 numtoread = SVAL(req->vwv+1, 0);
4257 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4260 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4262 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4264 if (numtoread > maxtoread) {
4265 DBG_WARNING("requested read size (%zu) is greater than "
4266 "maximum allowed (%zu/%d). "
4267 "Returning short read of maximum allowed for "
4268 "compatibility with Windows 2000.\n",
4271 req->xconn->smb1.sessions.max_send);
4272 numtoread = maxtoread;
4275 reply_outbuf(req, 5, numtoread + 3);
4277 data = smb_buf(req->outbuf) + 3;
4279 nread = read_file(fsp,data,startpos,numtoread);
4282 reply_nterror(req, map_nt_error_from_unix(errno));
4286 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4288 SSVAL(req->outbuf,smb_vwv0,nread);
4289 SSVAL(req->outbuf,smb_vwv5,nread+3);
4290 p = smb_buf(req->outbuf);
4291 SCVAL(p,0,0); /* pad byte. */
4294 DEBUG(3,("lockread %s num=%d nread=%d\n",
4295 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4298 ok = srv_send_smb(req->xconn,
4299 (char *)req->outbuf,
4302 IS_CONN_ENCRYPTED(req->conn),
4305 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4308 END_PROFILE(SMBlockread);
4313 #define DBGC_CLASS DBGC_ALL
4315 /****************************************************************************
4317 ****************************************************************************/
4319 void reply_read(struct smb_request *req)
4321 connection_struct *conn = req->conn;
4328 struct lock_struct lock;
4329 struct smbXsrv_connection *xconn = req->xconn;
4331 START_PROFILE(SMBread);
4334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4335 END_PROFILE(SMBread);
4339 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4341 if (!check_fsp(conn, req, fsp)) {
4342 END_PROFILE(SMBread);
4346 if (!CHECK_READ(fsp,req)) {
4347 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4348 END_PROFILE(SMBread);
4352 numtoread = SVAL(req->vwv+1, 0);
4353 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4356 * The requested read size cannot be greater than max_send. JRA.
4358 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4360 if (numtoread > maxtoread) {
4361 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4362 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4363 (unsigned int)numtoread, (unsigned int)maxtoread,
4364 (unsigned int)xconn->smb1.sessions.max_send));
4365 numtoread = maxtoread;
4368 reply_outbuf(req, 5, numtoread+3);
4370 data = smb_buf(req->outbuf) + 3;
4372 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4373 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4376 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4377 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4378 END_PROFILE(SMBread);
4383 nread = read_file(fsp,data,startpos,numtoread);
4386 reply_nterror(req, map_nt_error_from_unix(errno));
4390 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4392 SSVAL(req->outbuf,smb_vwv0,nread);
4393 SSVAL(req->outbuf,smb_vwv5,nread+3);
4394 SCVAL(smb_buf(req->outbuf),0,1);
4395 SSVAL(smb_buf(req->outbuf),1,nread);
4397 DEBUG(3, ("read %s num=%d nread=%d\n",
4398 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4401 END_PROFILE(SMBread);
4405 /****************************************************************************
4407 ****************************************************************************/
4409 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4413 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4416 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4418 SCVAL(outbuf,smb_vwv0,0xFF);
4419 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4420 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4421 SSVAL(outbuf,smb_vwv6,
4422 (smb_wct - 4) /* offset from smb header to wct */
4423 + 1 /* the wct field */
4424 + 12 * sizeof(uint16_t) /* vwv */
4425 + 2 /* the buflen field */
4426 + 1); /* padding byte */
4427 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4428 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4429 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4430 _smb_setlen_large(outbuf,
4431 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4435 /****************************************************************************
4436 Reply to a read and X - possibly using sendfile.
4437 ****************************************************************************/
4439 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4440 files_struct *fsp, off_t startpos,
4443 struct smbXsrv_connection *xconn = req->xconn;
4445 struct lock_struct lock;
4446 int saved_errno = 0;
4449 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4450 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4453 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4454 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4459 * We can only use sendfile on a non-chained packet
4460 * but we can use on a non-oplocked file. tridge proved this
4461 * on a train in Germany :-). JRA.
4464 if (!req_is_in_chain(req) &&
4466 (fsp->base_fsp == NULL) &&
4467 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4468 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4471 status = vfs_stat_fsp(fsp);
4472 if (!NT_STATUS_IS_OK(status)) {
4473 reply_nterror(req, status);
4477 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4478 (startpos > fsp->fsp_name->st.st_ex_size) ||
4479 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4481 * We already know that we would do a short read, so don't
4482 * try the sendfile() path.
4484 goto nosendfile_read;
4488 * Set up the packet header before send. We
4489 * assume here the sendfile will work (get the
4490 * correct amount of data).
4493 header = data_blob_const(headerbuf, sizeof(headerbuf));
4495 construct_reply_common_req(req, (char *)headerbuf);
4496 setup_readX_header((char *)headerbuf, smb_maxcnt);
4498 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4499 startpos, smb_maxcnt);
4501 saved_errno = errno;
4503 /* Returning ENOSYS means no data at all was sent.
4504 Do this as a normal read. */
4505 if (errno == ENOSYS) {
4510 * Special hack for broken Linux with no working sendfile. If we
4511 * return EINTR we sent the header but not the rest of the data.
4512 * Fake this up by doing read/write calls.
4515 if (errno == EINTR) {
4516 /* Ensure we don't do this again. */
4517 set_use_sendfile(SNUM(conn), False);
4518 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4519 nread = fake_sendfile(xconn, fsp, startpos,
4522 saved_errno = errno;
4523 DEBUG(0,("send_file_readX: "
4524 "fake_sendfile failed for "
4525 "file %s (%s) for client %s. "
4528 smbXsrv_connection_dbg(xconn),
4529 strerror(saved_errno)));
4530 errno = saved_errno;
4531 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4533 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4534 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4535 /* No outbuf here means successful sendfile. */
4539 DEBUG(0,("send_file_readX: sendfile failed for file "
4540 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4542 exit_server_cleanly("send_file_readX sendfile failed");
4543 } else if (nread == 0) {
4545 * Some sendfile implementations return 0 to indicate
4546 * that there was a short read, but nothing was
4547 * actually written to the socket. In this case,
4548 * fallback to the normal read path so the header gets
4549 * the correct byte count.
4551 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4552 "falling back to the normal read: %s\n",
4557 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4558 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4560 /* Deal with possible short send. */
4561 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4564 ret = sendfile_short_send(xconn, fsp, nread,
4565 sizeof(headerbuf), smb_maxcnt);
4568 r = "send_file_readX: sendfile_short_send failed";
4569 DEBUG(0,("%s for file %s (%s).\n",
4570 r, fsp_str_dbg(fsp), strerror(errno)));
4571 exit_server_cleanly(r);
4574 /* No outbuf here means successful sendfile. */
4575 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4576 SMB_PERFCOUNT_END(&req->pcd);
4582 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4583 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4586 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4587 (startpos > fsp->fsp_name->st.st_ex_size) ||
4588 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4590 * We already know that we would do a short
4591 * read, so don't try the sendfile() path.
4593 goto nosendfile_read;
4596 construct_reply_common_req(req, (char *)headerbuf);
4597 setup_readX_header((char *)headerbuf, smb_maxcnt);
4599 /* Send out the header. */
4600 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4602 if (ret != sizeof(headerbuf)) {
4603 saved_errno = errno;
4605 * Try and give an error message saying what
4608 DEBUG(0,("send_file_readX: write_data failed for file "
4609 "%s (%s) for client %s. Terminating\n",
4611 smbXsrv_connection_dbg(xconn),
4612 strerror(saved_errno)));
4613 errno = saved_errno;
4614 exit_server_cleanly("send_file_readX sendfile failed");
4616 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4618 saved_errno = errno;
4619 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4620 "%s (%s) for client %s. Terminating\n",
4622 smbXsrv_connection_dbg(xconn),
4623 strerror(saved_errno)));
4624 errno = saved_errno;
4625 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4632 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4633 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4634 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4636 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4637 startpos, smb_maxcnt);
4638 saved_errno = errno;
4641 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4645 setup_readX_header((char *)req->outbuf, nread);
4647 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4648 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4652 TALLOC_FREE(req->outbuf);
4656 /****************************************************************************
4657 Work out how much space we have for a read return.
4658 ****************************************************************************/
4660 static size_t calc_max_read_pdu(const struct smb_request *req)
4662 struct smbXsrv_connection *xconn = req->xconn;
4664 if (xconn->protocol < PROTOCOL_NT1) {
4665 return xconn->smb1.sessions.max_send;
4668 if (!lp_large_readwrite()) {
4669 return xconn->smb1.sessions.max_send;
4672 if (req_is_in_chain(req)) {
4673 return xconn->smb1.sessions.max_send;
4676 if (req->encrypted) {
4678 * Don't take encrypted traffic up to the
4679 * limit. There are padding considerations
4680 * that make that tricky.
4682 return xconn->smb1.sessions.max_send;
4685 if (srv_is_signing_active(xconn)) {
4689 if (!lp_unix_extensions()) {
4694 * We can do ultra-large POSIX reads.
4699 /****************************************************************************
4700 Calculate how big a read can be. Copes with all clients. It's always
4701 safe to return a short read - Windows does this.
4702 ****************************************************************************/
4704 static size_t calc_read_size(const struct smb_request *req,
4708 struct smbXsrv_connection *xconn = req->xconn;
4709 size_t max_pdu = calc_max_read_pdu(req);
4710 size_t total_size = 0;
4711 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4712 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4715 * Windows explicitly ignores upper size of 0xFFFF.
4716 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4717 * We must do the same as these will never fit even in
4718 * an extended size NetBIOS packet.
4720 if (upper_size == 0xFFFF) {
4724 if (xconn->protocol < PROTOCOL_NT1) {
4728 total_size = ((upper_size<<16) | lower_size);
4731 * LARGE_READX test shows it's always safe to return
4732 * a short read. Windows does so.
4734 return MIN(total_size, max_len);
4737 /****************************************************************************
4738 Reply to a read and X.
4739 ****************************************************************************/
4741 void reply_read_and_X(struct smb_request *req)
4743 connection_struct *conn = req->conn;
4748 bool big_readX = False;
4750 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4753 START_PROFILE(SMBreadX);
4755 if ((req->wct != 10) && (req->wct != 12)) {
4756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4760 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4761 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4762 smb_maxcnt = SVAL(req->vwv+5, 0);
4764 /* If it's an IPC, pass off the pipe handler. */
4766 reply_pipe_read_and_X(req);
4767 END_PROFILE(SMBreadX);
4771 if (!check_fsp(conn, req, fsp)) {
4772 END_PROFILE(SMBreadX);
4776 if (!CHECK_READ(fsp,req)) {
4777 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4778 END_PROFILE(SMBreadX);
4782 upper_size = SVAL(req->vwv+7, 0);
4783 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4784 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4786 * This is a heuristic to avoid keeping large
4787 * outgoing buffers around over long-lived aio
4793 if (req->wct == 12) {
4795 * This is a large offset (64 bit) read.
4797 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4802 NTSTATUS status = schedule_aio_read_and_X(conn,
4807 if (NT_STATUS_IS_OK(status)) {
4808 /* Read scheduled - we're done. */
4811 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4812 /* Real error - report to client. */
4813 END_PROFILE(SMBreadX);
4814 reply_nterror(req, status);
4817 /* NT_STATUS_RETRY - fall back to sync read. */
4820 smbd_lock_socket(req->xconn);
4821 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4822 smbd_unlock_socket(req->xconn);
4825 END_PROFILE(SMBreadX);
4829 /****************************************************************************
4830 Error replies to writebraw must have smb_wct == 1. Fix this up.
4831 ****************************************************************************/
4833 void error_to_writebrawerr(struct smb_request *req)
4835 uint8_t *old_outbuf = req->outbuf;
4837 reply_outbuf(req, 1, 0);
4839 memcpy(req->outbuf, old_outbuf, smb_size);
4840 TALLOC_FREE(old_outbuf);
4843 /****************************************************************************
4844 Read 4 bytes of a smb packet and return the smb length of the packet.
4845 Store the result in the buffer. This version of the function will
4846 never return a session keepalive (length of zero).
4847 Timeout is in milliseconds.
4848 ****************************************************************************/
4850 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4853 uint8_t msgtype = NBSSkeepalive;
4855 while (msgtype == NBSSkeepalive) {
4858 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4860 if (!NT_STATUS_IS_OK(status)) {
4861 char addr[INET6_ADDRSTRLEN];
4862 /* Try and give an error message
4863 * saying what client failed. */
4864 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4865 "client %s read error = %s.\n",
4866 get_peer_addr(fd,addr,sizeof(addr)),
4867 nt_errstr(status)));
4871 msgtype = CVAL(inbuf, 0);
4874 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4875 (unsigned long)len));
4877 return NT_STATUS_OK;
4880 /****************************************************************************
4881 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4882 ****************************************************************************/
4884 void reply_writebraw(struct smb_request *req)
4886 connection_struct *conn = req->conn;
4887 struct smbXsrv_connection *xconn = req->xconn;
4890 ssize_t total_written=0;
4891 size_t numtowrite=0;
4894 const char *data=NULL;
4897 struct lock_struct lock;
4900 START_PROFILE(SMBwritebraw);
4903 * If we ever reply with an error, it must have the SMB command
4904 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4907 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4909 if (srv_is_signing_active(xconn)) {
4910 END_PROFILE(SMBwritebraw);
4911 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4912 "raw reads/writes are disallowed.");
4915 if (req->wct < 12) {
4916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4917 error_to_writebrawerr(req);
4918 END_PROFILE(SMBwritebraw);
4922 if (xconn->smb1.echo_handler.trusted_fde) {
4923 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4924 "'async smb echo handler = yes'\n"));
4925 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4926 error_to_writebrawerr(req);
4927 END_PROFILE(SMBwritebraw);
4931 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4932 if (!check_fsp(conn, req, fsp)) {
4933 error_to_writebrawerr(req);
4934 END_PROFILE(SMBwritebraw);
4938 if (!CHECK_WRITE(fsp)) {
4939 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4940 error_to_writebrawerr(req);
4941 END_PROFILE(SMBwritebraw);
4945 tcount = IVAL(req->vwv+1, 0);
4946 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4947 write_through = BITSETW(req->vwv+7,0);
4949 /* We have to deal with slightly different formats depending
4950 on whether we are using the core+ or lanman1.0 protocol */
4952 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4953 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4954 data = smb_buf_const(req->inbuf);
4956 numtowrite = SVAL(req->vwv+10, 0);
4957 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4960 /* Ensure we don't write bytes past the end of this packet. */
4962 * This already protects us against CVE-2017-12163.
4964 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4966 error_to_writebrawerr(req);
4967 END_PROFILE(SMBwritebraw);
4971 if (!fsp->print_file) {
4972 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4973 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4976 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4977 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4978 error_to_writebrawerr(req);
4979 END_PROFILE(SMBwritebraw);
4985 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4988 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4989 "wrote=%d sync=%d\n",
4990 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4991 (int)nwritten, (int)write_through));
4993 if (nwritten < (ssize_t)numtowrite) {
4994 reply_nterror(req, NT_STATUS_DISK_FULL);
4995 error_to_writebrawerr(req);
4999 total_written = nwritten;
5001 /* Allocate a buffer of 64k + length. */
5002 buf = talloc_array(NULL, char, 65540);
5004 reply_nterror(req, NT_STATUS_NO_MEMORY);
5005 error_to_writebrawerr(req);
5009 /* Return a SMBwritebraw message to the redirector to tell
5010 * it to send more bytes */
5012 memcpy(buf, req->inbuf, smb_size);
5013 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
5014 SCVAL(buf,smb_com,SMBwritebraw);
5015 SSVALS(buf,smb_vwv0,0xFFFF);
5017 if (!srv_send_smb(req->xconn,
5019 false, 0, /* no signing */
5020 IS_CONN_ENCRYPTED(conn),
5022 exit_server_cleanly("reply_writebraw: srv_send_smb "
5026 /* Now read the raw data into the buffer and write it */
5027 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
5029 if (!NT_STATUS_IS_OK(status)) {
5030 exit_server_cleanly("secondary writebraw failed");
5033 /* Set up outbuf to return the correct size */
5034 reply_outbuf(req, 1, 0);
5036 if (numtowrite != 0) {
5038 if (numtowrite > 0xFFFF) {
5039 DEBUG(0,("reply_writebraw: Oversize secondary write "
5040 "raw requested (%u). Terminating\n",
5041 (unsigned int)numtowrite ));
5042 exit_server_cleanly("secondary writebraw failed");
5045 if (tcount > nwritten+numtowrite) {
5046 DEBUG(3,("reply_writebraw: Client overestimated the "
5048 (int)tcount,(int)nwritten,(int)numtowrite));
5051 status = read_data_ntstatus(xconn->transport.sock, buf+4,
5054 if (!NT_STATUS_IS_OK(status)) {
5055 /* Try and give an error message
5056 * saying what client failed. */
5057 DEBUG(0, ("reply_writebraw: Oversize secondary write "
5058 "raw read failed (%s) for client %s. "
5059 "Terminating\n", nt_errstr(status),
5060 smbXsrv_connection_dbg(xconn)));
5061 exit_server_cleanly("secondary writebraw failed");
5065 * We are not vulnerable to CVE-2017-12163
5066 * here as we are guaranteed to have numtowrite
5067 * bytes available - we just read from the client.
5069 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
5070 if (nwritten == -1) {
5072 reply_nterror(req, map_nt_error_from_unix(errno));
5073 error_to_writebrawerr(req);
5077 if (nwritten < (ssize_t)numtowrite) {
5078 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5079 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5083 total_written += nwritten;
5088 SSVAL(req->outbuf,smb_vwv0,total_written);
5090 status = sync_file(conn, fsp, write_through);
5091 if (!NT_STATUS_IS_OK(status)) {
5092 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5093 fsp_str_dbg(fsp), nt_errstr(status)));
5094 reply_nterror(req, status);
5095 error_to_writebrawerr(req);
5099 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5101 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5102 (int)total_written));
5104 /* We won't return a status if write through is not selected - this
5105 * follows what WfWg does */
5106 END_PROFILE(SMBwritebraw);
5108 if (!write_through && total_written==tcount) {
5110 #if RABBIT_PELLET_FIX
5112 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5113 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5116 if (!send_keepalive(xconn->transport.sock)) {
5117 exit_server_cleanly("reply_writebraw: send of "
5118 "keepalive failed");
5121 TALLOC_FREE(req->outbuf);
5126 END_PROFILE(SMBwritebraw);
5131 #define DBGC_CLASS DBGC_LOCKING
5133 /****************************************************************************
5134 Reply to a writeunlock (core+).
5135 ****************************************************************************/
5137 void reply_writeunlock(struct smb_request *req)
5139 connection_struct *conn = req->conn;
5140 ssize_t nwritten = -1;
5145 NTSTATUS status = NT_STATUS_OK;
5147 struct lock_struct lock;
5148 int saved_errno = 0;
5150 START_PROFILE(SMBwriteunlock);
5153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5154 END_PROFILE(SMBwriteunlock);
5158 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5160 if (!check_fsp(conn, req, fsp)) {
5161 END_PROFILE(SMBwriteunlock);
5165 if (!CHECK_WRITE(fsp)) {
5166 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5167 END_PROFILE(SMBwriteunlock);
5171 numtowrite = SVAL(req->vwv+1, 0);
5172 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5173 data = (const char *)req->buf + 3;
5176 * Ensure client isn't asking us to write more than
5177 * they sent. CVE-2017-12163.
5179 remaining = smbreq_bufrem(req, data);
5180 if (numtowrite > remaining) {
5181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5182 END_PROFILE(SMBwriteunlock);
5186 if (!fsp->print_file && numtowrite > 0) {
5187 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5188 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5191 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5192 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5193 END_PROFILE(SMBwriteunlock);
5198 /* The special X/Open SMB protocol handling of
5199 zero length writes is *NOT* done for
5201 if(numtowrite == 0) {
5204 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5205 saved_errno = errno;
5208 status = sync_file(conn, fsp, False /* write through */);
5209 if (!NT_STATUS_IS_OK(status)) {
5210 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5211 fsp_str_dbg(fsp), nt_errstr(status)));
5212 reply_nterror(req, status);
5217 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5221 if((nwritten < numtowrite) && (numtowrite != 0)) {
5222 reply_nterror(req, NT_STATUS_DISK_FULL);
5226 if (numtowrite && !fsp->print_file) {
5227 struct smbd_lock_element l = {
5228 .req_guid = smbd_request_guid(req, 0),
5229 .smblctx = req->smbpid,
5230 .brltype = UNLOCK_LOCK,
5232 .count = numtowrite,
5234 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5235 if (NT_STATUS_V(status)) {
5236 reply_nterror(req, status);
5241 reply_outbuf(req, 1, 0);
5243 SSVAL(req->outbuf,smb_vwv0,nwritten);
5245 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5246 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5249 END_PROFILE(SMBwriteunlock);
5254 #define DBGC_CLASS DBGC_ALL
5256 /****************************************************************************
5258 ****************************************************************************/
5260 void reply_write(struct smb_request *req)
5262 connection_struct *conn = req->conn;
5265 ssize_t nwritten = -1;
5269 struct lock_struct lock;
5271 int saved_errno = 0;
5273 START_PROFILE(SMBwrite);
5276 END_PROFILE(SMBwrite);
5277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5281 /* If it's an IPC, pass off the pipe handler. */
5283 reply_pipe_write(req);
5284 END_PROFILE(SMBwrite);
5288 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5290 if (!check_fsp(conn, req, fsp)) {
5291 END_PROFILE(SMBwrite);
5295 if (!CHECK_WRITE(fsp)) {
5296 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5297 END_PROFILE(SMBwrite);
5301 numtowrite = SVAL(req->vwv+1, 0);
5302 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5303 data = (const char *)req->buf + 3;
5306 * Ensure client isn't asking us to write more than
5307 * they sent. CVE-2017-12163.
5309 remaining = smbreq_bufrem(req, data);
5310 if (numtowrite > remaining) {
5311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5312 END_PROFILE(SMBwrite);
5316 if (!fsp->print_file) {
5317 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5318 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5321 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5322 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5323 END_PROFILE(SMBwrite);
5329 * X/Open SMB protocol says that if smb_vwv1 is
5330 * zero then the file size should be extended or
5331 * truncated to the size given in smb_vwv[2-3].
5334 if(numtowrite == 0) {
5336 * This is actually an allocate call, and set EOF. JRA.
5338 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5340 reply_nterror(req, NT_STATUS_DISK_FULL);
5343 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5345 reply_nterror(req, NT_STATUS_DISK_FULL);
5348 trigger_write_time_update_immediate(fsp);
5350 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5353 status = sync_file(conn, fsp, False);
5354 if (!NT_STATUS_IS_OK(status)) {
5355 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5356 fsp_str_dbg(fsp), nt_errstr(status)));
5357 reply_nterror(req, status);
5362 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5366 if((nwritten == 0) && (numtowrite != 0)) {
5367 reply_nterror(req, NT_STATUS_DISK_FULL);
5371 reply_outbuf(req, 1, 0);
5373 SSVAL(req->outbuf,smb_vwv0,nwritten);
5375 if (nwritten < (ssize_t)numtowrite) {
5376 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5377 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5380 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5383 END_PROFILE(SMBwrite);
5387 /****************************************************************************
5388 Ensure a buffer is a valid writeX for recvfile purposes.
5389 ****************************************************************************/
5391 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5392 (2*14) + /* word count (including bcc) */ \
5395 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5396 const uint8_t *inbuf)
5399 unsigned int doff = 0;
5400 size_t len = smb_len_large(inbuf);
5402 struct smbXsrv_open *op = NULL;
5403 struct files_struct *fsp = NULL;
5406 if (is_encrypted_packet(inbuf)) {
5407 /* Can't do this on encrypted
5412 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5416 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5417 CVAL(inbuf,smb_wct) != 14) {
5418 DEBUG(10,("is_valid_writeX_buffer: chained or "
5419 "invalid word length.\n"));
5423 fnum = SVAL(inbuf, smb_vwv2);
5424 status = smb1srv_open_lookup(xconn,
5428 if (!NT_STATUS_IS_OK(status)) {
5429 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5434 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5437 if (fsp->conn == NULL) {
5438 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5442 if (IS_IPC(fsp->conn)) {
5443 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5446 if (IS_PRINT(fsp->conn)) {
5447 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5450 if (fsp->base_fsp != NULL) {
5451 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5454 doff = SVAL(inbuf,smb_vwv11);
5456 numtowrite = SVAL(inbuf,smb_vwv10);
5458 if (len > doff && len - doff > 0xFFFF) {
5459 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5462 if (numtowrite == 0) {
5463 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5467 /* Ensure the sizes match up. */
5468 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5469 /* no pad byte...old smbclient :-( */
5470 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5472 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5476 if (len - doff != numtowrite) {
5477 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5478 "len = %u, doff = %u, numtowrite = %u\n",
5481 (unsigned int)numtowrite ));
5485 DEBUG(10,("is_valid_writeX_buffer: true "
5486 "len = %u, doff = %u, numtowrite = %u\n",
5489 (unsigned int)numtowrite ));
5494 /****************************************************************************
5495 Reply to a write and X.
5496 ****************************************************************************/
5498 void reply_write_and_X(struct smb_request *req)
5500 connection_struct *conn = req->conn;
5501 struct smbXsrv_connection *xconn = req->xconn;
5503 struct lock_struct lock;
5508 unsigned int smb_doff;
5509 unsigned int smblen;
5512 int saved_errno = 0;
5514 START_PROFILE(SMBwriteX);
5516 if ((req->wct != 12) && (req->wct != 14)) {
5517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5521 numtowrite = SVAL(req->vwv+10, 0);
5522 smb_doff = SVAL(req->vwv+11, 0);
5523 smblen = smb_len(req->inbuf);
5525 if (req->unread_bytes > 0xFFFF ||
5526 (smblen > smb_doff &&
5527 smblen - smb_doff > 0xFFFF)) {
5528 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5531 if (req->unread_bytes) {
5532 /* Can't do a recvfile write on IPC$ */
5534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5537 if (numtowrite != req->unread_bytes) {
5538 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5543 * This already protects us against CVE-2017-12163.
5545 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5546 smb_doff + numtowrite > smblen) {
5547 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5552 /* If it's an IPC, pass off the pipe handler. */
5554 if (req->unread_bytes) {
5555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5558 reply_pipe_write_and_X(req);
5562 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5563 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5564 write_through = BITSETW(req->vwv+7,0);
5566 if (!check_fsp(conn, req, fsp)) {
5570 if (!CHECK_WRITE(fsp)) {
5571 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5575 data = smb_base(req->inbuf) + smb_doff;
5577 if(req->wct == 14) {
5579 * This is a large offset (64 bit) write.
5581 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5585 /* X/Open SMB protocol says that, unlike SMBwrite
5586 if the length is zero then NO truncation is
5587 done, just a write of zero. To truncate a file,
5590 if(numtowrite == 0) {
5593 if (req->unread_bytes == 0) {
5594 status = schedule_aio_write_and_X(conn,
5601 if (NT_STATUS_IS_OK(status)) {
5602 /* write scheduled - we're done. */
5605 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5606 /* Real error - report to client. */
5607 reply_nterror(req, status);
5610 /* NT_STATUS_RETRY - fall through to sync write. */
5613 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5614 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5617 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5618 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5622 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5623 saved_errno = errno;
5627 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5631 if((nwritten == 0) && (numtowrite != 0)) {
5632 reply_nterror(req, NT_STATUS_DISK_FULL);
5636 reply_outbuf(req, 6, 0);
5637 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5638 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5639 SSVAL(req->outbuf,smb_vwv2,nwritten);
5640 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5642 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5643 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5645 status = sync_file(conn, fsp, write_through);
5646 if (!NT_STATUS_IS_OK(status)) {
5647 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5648 fsp_str_dbg(fsp), nt_errstr(status)));
5649 reply_nterror(req, status);
5653 END_PROFILE(SMBwriteX);
5657 if (req->unread_bytes) {
5658 /* writeX failed. drain socket. */
5659 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5660 req->unread_bytes) {
5661 smb_panic("failed to drain pending bytes");
5663 req->unread_bytes = 0;
5666 END_PROFILE(SMBwriteX);
5670 /****************************************************************************
5672 ****************************************************************************/
5674 void reply_lseek(struct smb_request *req)
5676 connection_struct *conn = req->conn;
5683 START_PROFILE(SMBlseek);
5686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5687 END_PROFILE(SMBlseek);
5691 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5693 if (!check_fsp(conn, req, fsp)) {
5697 mode = SVAL(req->vwv+1, 0) & 3;
5698 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5699 startpos = (off_t)IVALS(req->vwv+2, 0);
5708 res = fsp->fh->pos + startpos;
5719 if (umode == SEEK_END) {
5720 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5721 if(errno == EINVAL) {
5722 off_t current_pos = startpos;
5724 status = vfs_stat_fsp(fsp);
5725 if (!NT_STATUS_IS_OK(status)) {
5726 reply_nterror(req, status);
5727 END_PROFILE(SMBlseek);
5731 current_pos += fsp->fsp_name->st.st_ex_size;
5733 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5738 reply_nterror(req, map_nt_error_from_unix(errno));
5739 END_PROFILE(SMBlseek);
5746 reply_outbuf(req, 2, 0);
5747 SIVAL(req->outbuf,smb_vwv0,res);
5749 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5750 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5752 END_PROFILE(SMBlseek);
5756 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5759 connection_struct *conn = talloc_get_type_abort(
5760 private_data, connection_struct);
5762 if (conn != fsp->conn) {
5765 if (fsp->fh->fd == -1) {
5768 sync_file(conn, fsp, True /* write through */);
5770 if (fsp->fsp_flags.modified) {
5771 trigger_write_time_update_immediate(fsp);
5777 /****************************************************************************
5779 ****************************************************************************/
5781 void reply_flush(struct smb_request *req)
5783 connection_struct *conn = req->conn;
5787 START_PROFILE(SMBflush);
5790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5794 fnum = SVAL(req->vwv+0, 0);
5795 fsp = file_fsp(req, fnum);
5797 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5802 files_forall(req->sconn, file_sync_one_fn, conn);
5804 NTSTATUS status = sync_file(conn, fsp, True);
5805 if (!NT_STATUS_IS_OK(status)) {
5806 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5807 fsp_str_dbg(fsp), nt_errstr(status)));
5808 reply_nterror(req, status);
5809 END_PROFILE(SMBflush);
5812 if (fsp->fsp_flags.modified) {
5813 trigger_write_time_update_immediate(fsp);
5817 reply_outbuf(req, 0, 0);
5819 DEBUG(3,("flush\n"));
5820 END_PROFILE(SMBflush);
5824 /****************************************************************************
5826 conn POINTER CAN BE NULL HERE !
5827 ****************************************************************************/
5829 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5830 static void reply_exit_done(struct tevent_req *req);
5832 void reply_exit(struct smb_request *smb1req)
5834 struct tevent_req *req;
5837 * Don't setup the profile charge here, take
5838 * it in reply_exit_done(). Not strictly correct
5839 * but better than the other SMB1 async
5840 * code that double-charges at the moment.
5842 req = reply_exit_send(smb1req);
5844 /* Not going async, profile here. */
5845 START_PROFILE(SMBexit);
5846 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5847 END_PROFILE(SMBexit);
5851 /* We're async. This will complete later. */
5852 tevent_req_set_callback(req, reply_exit_done, smb1req);
5856 struct reply_exit_state {
5857 struct tevent_queue *wait_queue;
5860 static void reply_exit_wait_done(struct tevent_req *subreq);
5862 /****************************************************************************
5864 Note, on failure here we deallocate and return NULL to allow the caller to
5865 SMB1 return an error of ERRnomem immediately.
5866 ****************************************************************************/
5868 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5870 struct tevent_req *req;
5871 struct reply_exit_state *state;
5872 struct tevent_req *subreq;
5874 struct smbd_server_connection *sconn = smb1req->sconn;
5876 req = tevent_req_create(smb1req, &state,
5877 struct reply_exit_state);
5881 state->wait_queue = tevent_queue_create(state,
5882 "reply_exit_wait_queue");
5883 if (tevent_req_nomem(state->wait_queue, req)) {
5888 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5889 if (fsp->file_pid != smb1req->smbpid) {
5892 if (fsp->vuid != smb1req->vuid) {
5896 * Flag the file as close in progress.
5897 * This will prevent any more IO being
5900 fsp->fsp_flags.closing = true;
5902 if (fsp->num_aio_requests > 0) {
5904 * Now wait until all aio requests on this fsp are
5907 * We don't set a callback, as we just want to block the
5908 * wait queue and the talloc_free() of fsp->aio_request
5909 * will remove the item from the wait queue.
5911 subreq = tevent_queue_wait_send(fsp->aio_requests,
5914 if (tevent_req_nomem(subreq, req)) {
5922 * Now we add our own waiter to the end of the queue,
5923 * this way we get notified when all pending requests are finished
5924 * and reply to the outstanding SMB1 request.
5926 subreq = tevent_queue_wait_send(state,
5929 if (tevent_req_nomem(subreq, req)) {
5935 * We're really going async - move the SMB1 request from
5936 * a talloc stackframe above us to the conn talloc-context.
5937 * We need this to stick around until the wait_done
5938 * callback is invoked.
5940 smb1req = talloc_move(sconn, &smb1req);
5942 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5947 static void reply_exit_wait_done(struct tevent_req *subreq)
5949 struct tevent_req *req = tevent_req_callback_data(
5950 subreq, struct tevent_req);
5952 tevent_queue_wait_recv(subreq);
5953 TALLOC_FREE(subreq);
5954 tevent_req_done(req);
5957 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5959 return tevent_req_simple_recv_ntstatus(req);
5962 static void reply_exit_done(struct tevent_req *req)
5964 struct smb_request *smb1req = tevent_req_callback_data(
5965 req, struct smb_request);
5966 struct smbd_server_connection *sconn = smb1req->sconn;
5967 struct smbXsrv_connection *xconn = smb1req->xconn;
5968 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5969 struct smbXsrv_session *session = NULL;
5970 files_struct *fsp, *next;
5974 * Take the profile charge here. Not strictly
5975 * correct but better than the other SMB1 async
5976 * code that double-charges at the moment.
5978 START_PROFILE(SMBexit);
5980 status = reply_exit_recv(req);
5982 if (!NT_STATUS_IS_OK(status)) {
5983 TALLOC_FREE(smb1req);
5984 END_PROFILE(SMBexit);
5985 exit_server(__location__ ": reply_exit_recv failed");
5990 * Ensure the session is still valid.
5992 status = smb1srv_session_lookup(xconn,
5996 if (!NT_STATUS_IS_OK(status)) {
5997 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5998 smb_request_done(smb1req);
5999 END_PROFILE(SMBexit);
6003 * Ensure the vuid is still valid - no one
6004 * called reply_ulogoffX() in the meantime.
6005 * reply_exit() doesn't have AS_USER set, so
6006 * use set_current_user_info() directly.
6007 * This is the same logic as in switch_message().
6009 if (session->global->auth_session_info != NULL) {
6010 set_current_user_info(
6011 session->global->auth_session_info->unix_info->sanitized_username,
6012 session->global->auth_session_info->unix_info->unix_name,
6013 session->global->auth_session_info->info->domain_name);
6016 /* No more aio - do the actual closes. */
6017 for (fsp = sconn->files; fsp; fsp = next) {
6021 if (fsp->file_pid != smb1req->smbpid) {
6024 if (fsp->vuid != smb1req->vuid) {
6027 if (!fsp->fsp_flags.closing) {
6032 * reply_exit() has the DO_CHDIR flag set.
6034 ok = chdir_current_service(fsp->conn);
6036 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6037 smb_request_done(smb1req);
6038 END_PROFILE(SMBexit);
6040 close_file(NULL, fsp, SHUTDOWN_CLOSE);
6043 reply_outbuf(smb1req, 0, 0);
6045 * The following call is needed to push the
6046 * reply data back out the socket after async
6047 * return. Plus it frees smb1req.
6049 smb_request_done(smb1req);
6050 DBG_INFO("reply_exit complete\n");
6051 END_PROFILE(SMBexit);
6055 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6057 static void reply_close_done(struct tevent_req *req);
6059 void reply_close(struct smb_request *smb1req)
6061 connection_struct *conn = smb1req->conn;
6062 NTSTATUS status = NT_STATUS_OK;
6063 files_struct *fsp = NULL;
6064 START_PROFILE(SMBclose);
6066 if (smb1req->wct < 3) {
6067 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
6068 END_PROFILE(SMBclose);
6072 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
6075 * We can only use check_fsp if we know it's not a directory.
6078 if (!check_fsp_open(conn, smb1req, fsp)) {
6079 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
6080 END_PROFILE(SMBclose);
6084 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6085 fsp->fsp_flags.is_directory ?
6086 "directory" : "file",
6087 fsp->fh->fd, fsp_fnum_dbg(fsp),
6088 conn->num_files_open);
6090 if (!fsp->fsp_flags.is_directory) {
6094 * Take care of any time sent in the close.
6097 t = srv_make_unix_date3(smb1req->vwv+1);
6098 set_close_write_time(fsp, time_t_to_full_timespec(t));
6101 if (fsp->num_aio_requests != 0) {
6102 struct tevent_req *req;
6104 req = reply_close_send(smb1req, fsp);
6106 status = NT_STATUS_NO_MEMORY;
6109 /* We're async. This will complete later. */
6110 tevent_req_set_callback(req, reply_close_done, smb1req);
6111 END_PROFILE(SMBclose);
6116 * close_file() returns the unix errno if an error was detected on
6117 * close - normally this is due to a disk full error. If not then it
6118 * was probably an I/O error.
6121 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6123 if (!NT_STATUS_IS_OK(status)) {
6124 reply_nterror(smb1req, status);
6125 END_PROFILE(SMBclose);
6129 reply_outbuf(smb1req, 0, 0);
6130 END_PROFILE(SMBclose);
6134 struct reply_close_state {
6136 struct tevent_queue *wait_queue;
6139 static void reply_close_wait_done(struct tevent_req *subreq);
6141 /****************************************************************************
6143 Note, on failure here we deallocate and return NULL to allow the caller to
6144 SMB1 return an error of ERRnomem immediately.
6145 ****************************************************************************/
6147 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6150 struct tevent_req *req;
6151 struct reply_close_state *state;
6152 struct tevent_req *subreq;
6153 struct smbd_server_connection *sconn = smb1req->sconn;
6155 req = tevent_req_create(smb1req, &state,
6156 struct reply_close_state);
6160 state->wait_queue = tevent_queue_create(state,
6161 "reply_close_wait_queue");
6162 if (tevent_req_nomem(state->wait_queue, req)) {
6168 * Flag the file as close in progress.
6169 * This will prevent any more IO being
6172 fsp->fsp_flags.closing = true;
6175 * Now wait until all aio requests on this fsp are
6178 * We don't set a callback, as we just want to block the
6179 * wait queue and the talloc_free() of fsp->aio_request
6180 * will remove the item from the wait queue.
6182 subreq = tevent_queue_wait_send(fsp->aio_requests,
6185 if (tevent_req_nomem(subreq, req)) {
6191 * Now we add our own waiter to the end of the queue,
6192 * this way we get notified when all pending requests are finished
6193 * and reply to the outstanding SMB1 request.
6195 subreq = tevent_queue_wait_send(state,
6198 if (tevent_req_nomem(subreq, req)) {
6204 * We're really going async - move the SMB1 request from
6205 * a talloc stackframe above us to the conn talloc-context.
6206 * We need this to stick around until the wait_done
6207 * callback is invoked.
6209 smb1req = talloc_move(sconn, &smb1req);
6211 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6216 static void reply_close_wait_done(struct tevent_req *subreq)
6218 struct tevent_req *req = tevent_req_callback_data(
6219 subreq, struct tevent_req);
6221 tevent_queue_wait_recv(subreq);
6222 TALLOC_FREE(subreq);
6223 tevent_req_done(req);
6226 static NTSTATUS reply_close_recv(struct tevent_req *req)
6228 return tevent_req_simple_recv_ntstatus(req);
6231 static void reply_close_done(struct tevent_req *req)
6233 struct smb_request *smb1req = tevent_req_callback_data(
6234 req, struct smb_request);
6235 struct reply_close_state *state = tevent_req_data(req,
6236 struct reply_close_state);
6239 status = reply_close_recv(req);
6241 if (!NT_STATUS_IS_OK(status)) {
6242 TALLOC_FREE(smb1req);
6243 exit_server(__location__ ": reply_close_recv failed");
6247 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6248 if (NT_STATUS_IS_OK(status)) {
6249 reply_outbuf(smb1req, 0, 0);
6251 reply_nterror(smb1req, status);
6254 * The following call is needed to push the
6255 * reply data back out the socket after async
6256 * return. Plus it frees smb1req.
6258 smb_request_done(smb1req);
6261 /****************************************************************************
6262 Reply to a writeclose (Core+ protocol).
6263 ****************************************************************************/
6265 void reply_writeclose(struct smb_request *req)
6267 connection_struct *conn = req->conn;
6270 ssize_t nwritten = -1;
6271 NTSTATUS close_status = NT_STATUS_OK;
6274 struct timespec mtime;
6276 struct lock_struct lock;
6278 START_PROFILE(SMBwriteclose);
6281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6282 END_PROFILE(SMBwriteclose);
6286 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6288 if (!check_fsp(conn, req, fsp)) {
6289 END_PROFILE(SMBwriteclose);
6292 if (!CHECK_WRITE(fsp)) {
6293 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6294 END_PROFILE(SMBwriteclose);
6298 numtowrite = SVAL(req->vwv+1, 0);
6299 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6300 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6301 data = (const char *)req->buf + 1;
6304 * Ensure client isn't asking us to write more than
6305 * they sent. CVE-2017-12163.
6307 remaining = smbreq_bufrem(req, data);
6308 if (numtowrite > remaining) {
6309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6310 END_PROFILE(SMBwriteclose);
6314 if (fsp->print_file == NULL) {
6315 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6316 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6319 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6320 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6321 END_PROFILE(SMBwriteclose);
6326 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6328 set_close_write_time(fsp, mtime);
6331 * More insanity. W2K only closes the file if writelen > 0.
6335 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6336 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6337 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6340 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6341 "file %s\n", fsp_str_dbg(fsp)));
6342 close_status = close_file(req, fsp, NORMAL_CLOSE);
6346 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6347 reply_nterror(req, NT_STATUS_DISK_FULL);
6351 if(!NT_STATUS_IS_OK(close_status)) {
6352 reply_nterror(req, close_status);
6356 reply_outbuf(req, 1, 0);
6358 SSVAL(req->outbuf,smb_vwv0,nwritten);
6362 END_PROFILE(SMBwriteclose);
6367 #define DBGC_CLASS DBGC_LOCKING
6369 /****************************************************************************
6371 ****************************************************************************/
6373 static void reply_lock_done(struct tevent_req *subreq);
6375 void reply_lock(struct smb_request *req)
6377 struct tevent_req *subreq = NULL;
6378 connection_struct *conn = req->conn;
6380 struct smbd_lock_element *lck = NULL;
6382 START_PROFILE(SMBlock);
6385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6386 END_PROFILE(SMBlock);
6390 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6392 if (!check_fsp(conn, req, fsp)) {
6393 END_PROFILE(SMBlock);
6397 lck = talloc(req, struct smbd_lock_element);
6399 reply_nterror(req, NT_STATUS_NO_MEMORY);
6400 END_PROFILE(SMBlock);
6404 *lck = (struct smbd_lock_element) {
6405 .req_guid = smbd_request_guid(req, 0),
6406 .smblctx = req->smbpid,
6407 .brltype = WRITE_LOCK,
6408 .count = IVAL(req->vwv+1, 0),
6409 .offset = IVAL(req->vwv+3, 0),
6412 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6418 subreq = smbd_smb1_do_locks_send(
6424 false, /* large_offset */
6428 if (subreq == NULL) {
6429 reply_nterror(req, NT_STATUS_NO_MEMORY);
6430 END_PROFILE(SMBlock);
6433 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6434 END_PROFILE(SMBlock);
6437 static void reply_lock_done(struct tevent_req *subreq)
6439 struct smb_request *req = NULL;
6443 START_PROFILE(SMBlock);
6445 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6448 status = smbd_smb1_do_locks_recv(subreq);
6449 TALLOC_FREE(subreq);
6451 if (NT_STATUS_IS_OK(status)) {
6452 reply_outbuf(req, 0, 0);
6454 reply_nterror(req, status);
6457 ok = srv_send_smb(req->xconn,
6458 (char *)req->outbuf,
6461 IS_CONN_ENCRYPTED(req->conn),
6464 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6467 END_PROFILE(SMBlock);
6470 /****************************************************************************
6472 ****************************************************************************/
6474 void reply_unlock(struct smb_request *req)
6476 connection_struct *conn = req->conn;
6479 struct smbd_lock_element lck;
6481 START_PROFILE(SMBunlock);
6484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6485 END_PROFILE(SMBunlock);
6489 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6491 if (!check_fsp(conn, req, fsp)) {
6492 END_PROFILE(SMBunlock);
6496 lck = (struct smbd_lock_element) {
6497 .req_guid = smbd_request_guid(req, 0),
6498 .smblctx = req->smbpid,
6499 .brltype = UNLOCK_LOCK,
6500 .offset = IVAL(req->vwv+3, 0),
6501 .count = IVAL(req->vwv+1, 0),
6504 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6506 if (!NT_STATUS_IS_OK(status)) {
6507 reply_nterror(req, status);
6508 END_PROFILE(SMBunlock);
6512 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6518 reply_outbuf(req, 0, 0);
6520 END_PROFILE(SMBunlock);
6525 #define DBGC_CLASS DBGC_ALL
6527 /****************************************************************************
6529 conn POINTER CAN BE NULL HERE !
6530 ****************************************************************************/
6532 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6533 static void reply_tdis_done(struct tevent_req *req);
6535 void reply_tdis(struct smb_request *smb1req)
6537 connection_struct *conn = smb1req->conn;
6538 struct tevent_req *req;
6541 * Don't setup the profile charge here, take
6542 * it in reply_tdis_done(). Not strictly correct
6543 * but better than the other SMB1 async
6544 * code that double-charges at the moment.
6548 /* Not going async, profile here. */
6549 START_PROFILE(SMBtdis);
6550 DBG_INFO("Invalid connection in tdis\n");
6551 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6552 END_PROFILE(SMBtdis);
6556 req = reply_tdis_send(smb1req);
6558 /* Not going async, profile here. */
6559 START_PROFILE(SMBtdis);
6560 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6561 END_PROFILE(SMBtdis);
6564 /* We're async. This will complete later. */
6565 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6569 struct reply_tdis_state {
6570 struct tevent_queue *wait_queue;
6573 static void reply_tdis_wait_done(struct tevent_req *subreq);
6575 /****************************************************************************
6577 Note, on failure here we deallocate and return NULL to allow the caller to
6578 SMB1 return an error of ERRnomem immediately.
6579 ****************************************************************************/
6581 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6583 struct tevent_req *req;
6584 struct reply_tdis_state *state;
6585 struct tevent_req *subreq;
6586 connection_struct *conn = smb1req->conn;
6589 req = tevent_req_create(smb1req, &state,
6590 struct reply_tdis_state);
6594 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6595 if (tevent_req_nomem(state->wait_queue, req)) {
6601 * Make sure that no new request will be able to use this tcon.
6602 * This ensures that once all outstanding fsp->aio_requests
6603 * on this tcon are done, we are safe to close it.
6605 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6607 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6608 if (fsp->conn != conn) {
6612 * Flag the file as close in progress.
6613 * This will prevent any more IO being
6614 * done on it. Not strictly needed, but
6615 * doesn't hurt to flag it as closing.
6617 fsp->fsp_flags.closing = true;
6619 if (fsp->num_aio_requests > 0) {
6621 * Now wait until all aio requests on this fsp are
6624 * We don't set a callback, as we just want to block the
6625 * wait queue and the talloc_free() of fsp->aio_request
6626 * will remove the item from the wait queue.
6628 subreq = tevent_queue_wait_send(fsp->aio_requests,
6629 conn->sconn->ev_ctx,
6631 if (tevent_req_nomem(subreq, req)) {
6639 * Now we add our own waiter to the end of the queue,
6640 * this way we get notified when all pending requests are finished
6641 * and reply to the outstanding SMB1 request.
6643 subreq = tevent_queue_wait_send(state,
6644 conn->sconn->ev_ctx,
6646 if (tevent_req_nomem(subreq, req)) {
6652 * We're really going async - move the SMB1 request from
6653 * a talloc stackframe above us to the sconn talloc-context.
6654 * We need this to stick around until the wait_done
6655 * callback is invoked.
6657 smb1req = talloc_move(smb1req->sconn, &smb1req);
6659 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6664 static void reply_tdis_wait_done(struct tevent_req *subreq)
6666 struct tevent_req *req = tevent_req_callback_data(
6667 subreq, struct tevent_req);
6669 tevent_queue_wait_recv(subreq);
6670 TALLOC_FREE(subreq);
6671 tevent_req_done(req);
6674 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6676 return tevent_req_simple_recv_ntstatus(req);
6679 static void reply_tdis_done(struct tevent_req *req)
6681 struct smb_request *smb1req = tevent_req_callback_data(
6682 req, struct smb_request);
6684 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6688 * Take the profile charge here. Not strictly
6689 * correct but better than the other SMB1 async
6690 * code that double-charges at the moment.
6692 START_PROFILE(SMBtdis);
6694 status = reply_tdis_recv(req);
6696 if (!NT_STATUS_IS_OK(status)) {
6697 TALLOC_FREE(smb1req);
6698 END_PROFILE(SMBtdis);
6699 exit_server(__location__ ": reply_tdis_recv failed");
6704 * As we've been awoken, we may have changed
6705 * directory in the meantime.
6706 * reply_tdis() has the DO_CHDIR flag set.
6708 ok = chdir_current_service(smb1req->conn);
6710 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6711 smb_request_done(smb1req);
6712 END_PROFILE(SMBtdis);
6715 status = smbXsrv_tcon_disconnect(tcon,
6717 if (!NT_STATUS_IS_OK(status)) {
6718 TALLOC_FREE(smb1req);
6719 END_PROFILE(SMBtdis);
6720 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6724 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6725 smb1req->conn = NULL;
6729 reply_outbuf(smb1req, 0, 0);
6731 * The following call is needed to push the
6732 * reply data back out the socket after async
6733 * return. Plus it frees smb1req.
6735 smb_request_done(smb1req);
6736 END_PROFILE(SMBtdis);
6739 /****************************************************************************
6741 conn POINTER CAN BE NULL HERE !
6742 ****************************************************************************/
6744 void reply_echo(struct smb_request *req)
6746 connection_struct *conn = req->conn;
6747 struct smb_perfcount_data local_pcd;
6748 struct smb_perfcount_data *cur_pcd;
6752 START_PROFILE(SMBecho);
6754 smb_init_perfcount_data(&local_pcd);
6757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6758 END_PROFILE(SMBecho);
6762 smb_reverb = SVAL(req->vwv+0, 0);
6764 reply_outbuf(req, 1, req->buflen);
6766 /* copy any incoming data back out */
6767 if (req->buflen > 0) {
6768 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6771 if (smb_reverb > 100) {
6772 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6776 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6778 /* this makes sure we catch the request pcd */
6779 if (seq_num == smb_reverb) {
6780 cur_pcd = &req->pcd;
6782 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6783 cur_pcd = &local_pcd;
6786 SSVAL(req->outbuf,smb_vwv0,seq_num);
6788 show_msg((char *)req->outbuf);
6789 if (!srv_send_smb(req->xconn,
6790 (char *)req->outbuf,
6791 true, req->seqnum+1,
6792 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6794 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6797 DEBUG(3,("echo %d times\n", smb_reverb));
6799 TALLOC_FREE(req->outbuf);
6801 END_PROFILE(SMBecho);
6805 /****************************************************************************
6806 Reply to a printopen.
6807 ****************************************************************************/
6809 void reply_printopen(struct smb_request *req)
6811 connection_struct *conn = req->conn;
6815 START_PROFILE(SMBsplopen);
6818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6819 END_PROFILE(SMBsplopen);
6823 if (!CAN_PRINT(conn)) {
6824 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6825 END_PROFILE(SMBsplopen);
6829 status = file_new(req, conn, &fsp);
6830 if(!NT_STATUS_IS_OK(status)) {
6831 reply_nterror(req, status);
6832 END_PROFILE(SMBsplopen);
6836 /* Open for exclusive use, write only. */
6837 status = print_spool_open(fsp, NULL, req->vuid);
6839 if (!NT_STATUS_IS_OK(status)) {
6840 file_free(req, fsp);
6841 reply_nterror(req, status);
6842 END_PROFILE(SMBsplopen);
6846 reply_outbuf(req, 1, 0);
6847 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6849 DEBUG(3,("openprint fd=%d %s\n",
6850 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6852 END_PROFILE(SMBsplopen);
6856 /****************************************************************************
6857 Reply to a printclose.
6858 ****************************************************************************/
6860 void reply_printclose(struct smb_request *req)
6862 connection_struct *conn = req->conn;
6866 START_PROFILE(SMBsplclose);
6869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6870 END_PROFILE(SMBsplclose);
6874 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6876 if (!check_fsp(conn, req, fsp)) {
6877 END_PROFILE(SMBsplclose);
6881 if (!CAN_PRINT(conn)) {
6882 reply_force_doserror(req, ERRSRV, ERRerror);
6883 END_PROFILE(SMBsplclose);
6887 DEBUG(3,("printclose fd=%d %s\n",
6888 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6890 status = close_file(req, fsp, NORMAL_CLOSE);
6892 if(!NT_STATUS_IS_OK(status)) {
6893 reply_nterror(req, status);
6894 END_PROFILE(SMBsplclose);
6898 reply_outbuf(req, 0, 0);
6900 END_PROFILE(SMBsplclose);
6904 /****************************************************************************
6905 Reply to a printqueue.
6906 ****************************************************************************/
6908 void reply_printqueue(struct smb_request *req)
6910 const struct loadparm_substitution *lp_sub =
6911 loadparm_s3_global_substitution();
6912 connection_struct *conn = req->conn;
6916 START_PROFILE(SMBsplretq);
6919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6920 END_PROFILE(SMBsplretq);
6924 max_count = SVAL(req->vwv+0, 0);
6925 start_index = SVAL(req->vwv+1, 0);
6927 /* we used to allow the client to get the cnum wrong, but that
6928 is really quite gross and only worked when there was only
6929 one printer - I think we should now only accept it if they
6930 get it right (tridge) */
6931 if (!CAN_PRINT(conn)) {
6932 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6933 END_PROFILE(SMBsplretq);
6937 reply_outbuf(req, 2, 3);
6938 SSVAL(req->outbuf,smb_vwv0,0);
6939 SSVAL(req->outbuf,smb_vwv1,0);
6940 SCVAL(smb_buf(req->outbuf),0,1);
6941 SSVAL(smb_buf(req->outbuf),1,0);
6943 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6944 start_index, max_count));
6947 TALLOC_CTX *mem_ctx = talloc_tos();
6950 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6951 struct rpc_pipe_client *cli = NULL;
6952 struct dcerpc_binding_handle *b = NULL;
6953 struct policy_handle handle;
6954 struct spoolss_DevmodeContainer devmode_ctr;
6955 union spoolss_JobInfo *info;
6957 uint32_t num_to_get;
6961 ZERO_STRUCT(handle);
6963 status = rpc_pipe_open_interface(mem_ctx,
6966 conn->sconn->remote_address,
6967 conn->sconn->local_address,
6968 conn->sconn->msg_ctx,
6970 if (!NT_STATUS_IS_OK(status)) {
6971 DEBUG(0, ("reply_printqueue: "
6972 "could not connect to spoolss: %s\n",
6973 nt_errstr(status)));
6974 reply_nterror(req, status);
6977 b = cli->binding_handle;
6979 ZERO_STRUCT(devmode_ctr);
6981 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6984 SEC_FLAG_MAXIMUM_ALLOWED,
6987 if (!NT_STATUS_IS_OK(status)) {
6988 reply_nterror(req, status);
6991 if (!W_ERROR_IS_OK(werr)) {
6992 reply_nterror(req, werror_to_ntstatus(werr));
6996 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
7004 if (!W_ERROR_IS_OK(werr)) {
7005 reply_nterror(req, werror_to_ntstatus(werr));
7009 if (max_count > 0) {
7010 first = start_index;
7012 first = start_index + max_count + 1;
7015 if (first >= count) {
7018 num_to_get = first + MIN(ABS(max_count), count - first);
7021 for (i = first; i < num_to_get; i++) {
7024 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
7027 uint16_t qrapjobid = pjobid_to_rap(sharename,
7028 info[i].info2.job_id);
7030 if (info[i].info2.status == JOB_STATUS_PRINTING) {
7036 srv_put_dos_date2(p, 0, qtime);
7037 SCVAL(p, 4, qstatus);
7038 SSVAL(p, 5, qrapjobid);
7039 SIVAL(p, 7, info[i].info2.size);
7041 status = srvstr_push(blob, req->flags2, p+12,
7042 info[i].info2.notify_name, 16, STR_ASCII, &len);
7043 if (!NT_STATUS_IS_OK(status)) {
7044 reply_nterror(req, status);
7047 if (message_push_blob(
7050 blob, sizeof(blob))) == -1) {
7051 reply_nterror(req, NT_STATUS_NO_MEMORY);
7057 SSVAL(req->outbuf,smb_vwv0,count);
7058 SSVAL(req->outbuf,smb_vwv1,
7059 (max_count>0?first+count:first-1));
7060 SCVAL(smb_buf(req->outbuf),0,1);
7061 SSVAL(smb_buf(req->outbuf),1,28*count);
7065 DEBUG(3, ("%u entries returned in queue\n",
7069 if (b && is_valid_policy_hnd(&handle)) {
7070 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
7075 END_PROFILE(SMBsplretq);
7079 /****************************************************************************
7080 Reply to a printwrite.
7081 ****************************************************************************/
7083 void reply_printwrite(struct smb_request *req)
7085 connection_struct *conn = req->conn;
7090 START_PROFILE(SMBsplwr);
7093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7094 END_PROFILE(SMBsplwr);
7098 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7100 if (!check_fsp(conn, req, fsp)) {
7101 END_PROFILE(SMBsplwr);
7105 if (!fsp->print_file) {
7106 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7107 END_PROFILE(SMBsplwr);
7111 if (!CHECK_WRITE(fsp)) {
7112 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7113 END_PROFILE(SMBsplwr);
7117 numtowrite = SVAL(req->buf, 1);
7120 * This already protects us against CVE-2017-12163.
7122 if (req->buflen < numtowrite + 3) {
7123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7124 END_PROFILE(SMBsplwr);
7128 data = (const char *)req->buf + 3;
7130 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7131 reply_nterror(req, map_nt_error_from_unix(errno));
7132 END_PROFILE(SMBsplwr);
7136 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7138 END_PROFILE(SMBsplwr);
7142 /****************************************************************************
7144 ****************************************************************************/
7146 void reply_mkdir(struct smb_request *req)
7148 connection_struct *conn = req->conn;
7149 struct smb_filename *smb_dname = NULL;
7150 char *directory = NULL;
7153 TALLOC_CTX *ctx = talloc_tos();
7155 START_PROFILE(SMBmkdir);
7157 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7158 STR_TERMINATE, &status);
7159 if (!NT_STATUS_IS_OK(status)) {
7160 reply_nterror(req, status);
7164 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7165 status = filename_convert(ctx, conn,
7171 if (!NT_STATUS_IS_OK(status)) {
7172 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7173 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7174 ERRSRV, ERRbadpath);
7177 reply_nterror(req, status);
7181 status = create_directory(conn, req, smb_dname);
7183 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7185 if (!NT_STATUS_IS_OK(status)) {
7187 if (!use_nt_status()
7188 && NT_STATUS_EQUAL(status,
7189 NT_STATUS_OBJECT_NAME_COLLISION)) {
7191 * Yes, in the DOS error code case we get a
7192 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7193 * samba4 torture test.
7195 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7198 reply_nterror(req, status);
7202 reply_outbuf(req, 0, 0);
7204 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7206 TALLOC_FREE(smb_dname);
7207 END_PROFILE(SMBmkdir);
7211 /****************************************************************************
7213 ****************************************************************************/
7215 void reply_rmdir(struct smb_request *req)
7217 connection_struct *conn = req->conn;
7218 struct smb_filename *smb_dname = NULL;
7219 char *directory = NULL;
7221 TALLOC_CTX *ctx = talloc_tos();
7222 files_struct *fsp = NULL;
7224 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7226 START_PROFILE(SMBrmdir);
7228 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7229 STR_TERMINATE, &status);
7230 if (!NT_STATUS_IS_OK(status)) {
7231 reply_nterror(req, status);
7235 status = filename_convert(ctx, conn,
7241 if (!NT_STATUS_IS_OK(status)) {
7242 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7243 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7244 ERRSRV, ERRbadpath);
7247 reply_nterror(req, status);
7251 if (is_ntfs_stream_smb_fname(smb_dname)) {
7252 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7256 status = SMB_VFS_CREATE_FILE(
7259 &conn->cwd_fsp, /* dirfsp */
7260 smb_dname, /* fname */
7261 DELETE_ACCESS, /* access_mask */
7262 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7264 FILE_OPEN, /* create_disposition*/
7265 FILE_DIRECTORY_FILE, /* create_options */
7266 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7267 0, /* oplock_request */
7269 0, /* allocation_size */
7270 0, /* private_flags */
7275 NULL, NULL); /* create context */
7277 if (!NT_STATUS_IS_OK(status)) {
7278 if (open_was_deferred(req->xconn, req->mid)) {
7279 /* We have re-scheduled this call. */
7282 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7283 bool ok = defer_smb1_sharing_violation(req);
7288 reply_nterror(req, status);
7292 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7293 if (!NT_STATUS_IS_OK(status)) {
7294 close_file(req, fsp, ERROR_CLOSE);
7295 reply_nterror(req, status);
7299 if (!set_delete_on_close(fsp, true,
7300 conn->session_info->security_token,
7301 conn->session_info->unix_token)) {
7302 close_file(req, fsp, ERROR_CLOSE);
7303 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7307 status = close_file(req, fsp, NORMAL_CLOSE);
7308 if (!NT_STATUS_IS_OK(status)) {
7309 reply_nterror(req, status);
7311 reply_outbuf(req, 0, 0);
7314 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7316 TALLOC_FREE(smb_dname);
7317 END_PROFILE(SMBrmdir);
7321 /*******************************************************************
7322 Resolve wildcards in a filename rename.
7323 ********************************************************************/
7325 static bool resolve_wildcards(TALLOC_CTX *ctx,
7330 char *name2_copy = NULL;
7335 char *p,*p2, *pname1, *pname2;
7337 name2_copy = talloc_strdup(ctx, name2);
7342 pname1 = strrchr_m(name1,'/');
7343 pname2 = strrchr_m(name2_copy,'/');
7345 if (!pname1 || !pname2) {
7349 /* Truncate the copy of name2 at the last '/' */
7352 /* Now go past the '/' */
7356 root1 = talloc_strdup(ctx, pname1);
7357 root2 = talloc_strdup(ctx, pname2);
7359 if (!root1 || !root2) {
7363 p = strrchr_m(root1,'.');
7366 ext1 = talloc_strdup(ctx, p+1);
7368 ext1 = talloc_strdup(ctx, "");
7370 p = strrchr_m(root2,'.');
7373 ext2 = talloc_strdup(ctx, p+1);
7375 ext2 = talloc_strdup(ctx, "");
7378 if (!ext1 || !ext2) {
7386 /* Hmmm. Should this be mb-aware ? */
7389 } else if (*p2 == '*') {
7391 root2 = talloc_asprintf(ctx, "%s%s",
7410 /* Hmmm. Should this be mb-aware ? */
7413 } else if (*p2 == '*') {
7415 ext2 = talloc_asprintf(ctx, "%s%s",
7431 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7436 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7448 /****************************************************************************
7449 Ensure open files have their names updated. Updated to notify other smbd's
7451 ****************************************************************************/
7453 static void rename_open_files(connection_struct *conn,
7454 struct share_mode_lock *lck,
7456 uint32_t orig_name_hash,
7457 const struct smb_filename *smb_fname_dst)
7460 bool did_rename = False;
7462 uint32_t new_name_hash = 0;
7464 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7465 fsp = file_find_di_next(fsp)) {
7466 struct file_id_buf idbuf;
7467 /* fsp_name is a relative path under the fsp. To change this for other
7468 sharepaths we need to manipulate relative paths. */
7469 /* TODO - create the absolute path and manipulate the newname
7470 relative to the sharepath. */
7471 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7474 if (fsp->name_hash != orig_name_hash) {
7477 DBG_DEBUG("renaming file %s "
7478 "(file_id %s) from %s -> %s\n",
7480 file_id_str_buf(fsp->file_id, &idbuf),
7482 smb_fname_str_dbg(smb_fname_dst));
7484 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7485 if (NT_STATUS_IS_OK(status)) {
7487 new_name_hash = fsp->name_hash;
7492 struct file_id_buf idbuf;
7493 DBG_DEBUG("no open files on file_id %s "
7495 file_id_str_buf(id, &idbuf),
7496 smb_fname_str_dbg(smb_fname_dst));
7499 /* Send messages to all smbd's (not ourself) that the name has changed. */
7500 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7501 orig_name_hash, new_name_hash,
7506 /****************************************************************************
7507 We need to check if the source path is a parent directory of the destination
7508 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7509 refuse the rename with a sharing violation. Under UNIX the above call can
7510 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7511 probably need to check that the client is a Windows one before disallowing
7512 this as a UNIX client (one with UNIX extensions) can know the source is a
7513 symlink and make this decision intelligently. Found by an excellent bug
7514 report from <AndyLiebman@aol.com>.
7515 ****************************************************************************/
7517 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7518 const struct smb_filename *smb_fname_dst)
7520 const char *psrc = smb_fname_src->base_name;
7521 const char *pdst = smb_fname_dst->base_name;
7524 if (psrc[0] == '.' && psrc[1] == '/') {
7527 if (pdst[0] == '.' && pdst[1] == '/') {
7530 if ((slen = strlen(psrc)) > strlen(pdst)) {
7533 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7537 * Do the notify calls from a rename
7540 static void notify_rename(connection_struct *conn, bool is_dir,
7541 const struct smb_filename *smb_fname_src,
7542 const struct smb_filename *smb_fname_dst)
7544 char *parent_dir_src = NULL;
7545 char *parent_dir_dst = NULL;
7548 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7549 : FILE_NOTIFY_CHANGE_FILE_NAME;
7551 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7552 &parent_dir_src, NULL) ||
7553 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7554 &parent_dir_dst, NULL)) {
7558 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7559 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7560 smb_fname_src->base_name);
7561 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7562 smb_fname_dst->base_name);
7565 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7566 smb_fname_src->base_name);
7567 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7568 smb_fname_dst->base_name);
7571 /* this is a strange one. w2k3 gives an additional event for
7572 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7573 files, but not directories */
7575 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7576 FILE_NOTIFY_CHANGE_ATTRIBUTES
7577 |FILE_NOTIFY_CHANGE_CREATION,
7578 smb_fname_dst->base_name);
7581 TALLOC_FREE(parent_dir_src);
7582 TALLOC_FREE(parent_dir_dst);
7585 /****************************************************************************
7586 Returns an error if the parent directory for a filename is open in an
7588 ****************************************************************************/
7590 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7591 const struct smb_filename *smb_fname_dst_in)
7593 struct smb_filename *smb_fname_parent = NULL;
7595 files_struct *fsp = NULL;
7599 ok = parent_smb_fname(talloc_tos(),
7604 return NT_STATUS_NO_MEMORY;
7607 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7609 return map_nt_error_from_unix(errno);
7613 * We're only checking on this smbd here, mostly good
7614 * enough.. and will pass tests.
7617 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7618 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7619 fsp = file_find_di_next(fsp)) {
7620 if (fsp->access_mask & DELETE_ACCESS) {
7621 return NT_STATUS_SHARING_VIOLATION;
7624 return NT_STATUS_OK;
7627 /****************************************************************************
7628 Rename an open file - given an fsp.
7629 ****************************************************************************/
7631 NTSTATUS rename_internals_fsp(connection_struct *conn,
7633 const struct smb_filename *smb_fname_dst_in,
7634 const char *dst_original_lcomp,
7636 bool replace_if_exists)
7638 TALLOC_CTX *ctx = talloc_tos();
7639 struct smb_filename *smb_fname_dst = NULL;
7640 NTSTATUS status = NT_STATUS_OK;
7641 struct share_mode_lock *lck = NULL;
7642 uint32_t access_mask = SEC_DIR_ADD_FILE;
7643 bool dst_exists, old_is_stream, new_is_stream;
7646 status = check_name(conn, smb_fname_dst_in);
7647 if (!NT_STATUS_IS_OK(status)) {
7651 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7652 if (!NT_STATUS_IS_OK(status)) {
7656 if (file_has_open_streams(fsp)) {
7657 return NT_STATUS_ACCESS_DENIED;
7660 /* Make a copy of the dst smb_fname structs */
7662 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7663 if (smb_fname_dst == NULL) {
7664 status = NT_STATUS_NO_MEMORY;
7669 * Check for special case with case preserving and not
7670 * case sensitive. If the new last component differs from the original
7671 * last component only by case, then we should allow
7672 * the rename (user is trying to change the case of the
7675 if (!conn->case_sensitive && conn->case_preserve &&
7676 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7677 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7678 char *fname_dst_parent = NULL;
7679 const char *fname_dst_lcomp = NULL;
7680 char *orig_lcomp_path = NULL;
7681 char *orig_lcomp_stream = NULL;
7685 * Split off the last component of the processed
7686 * destination name. We will compare this to
7687 * the split components of dst_original_lcomp.
7689 if (!parent_dirname(ctx,
7690 smb_fname_dst->base_name,
7692 &fname_dst_lcomp)) {
7693 status = NT_STATUS_NO_MEMORY;
7698 * The dst_original_lcomp component contains
7699 * the last_component of the path + stream
7700 * name (if a stream exists).
7702 * Split off the stream name so we
7703 * can check them separately.
7706 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7707 /* POSIX - no stream component. */
7708 orig_lcomp_path = talloc_strdup(ctx,
7709 dst_original_lcomp);
7710 if (orig_lcomp_path == NULL) {
7714 ok = split_stream_filename(ctx,
7717 &orig_lcomp_stream);
7721 TALLOC_FREE(fname_dst_parent);
7722 status = NT_STATUS_NO_MEMORY;
7726 /* If the base names only differ by case, use original. */
7727 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7730 * Replace the modified last component with the
7733 if (!ISDOT(fname_dst_parent)) {
7734 tmp = talloc_asprintf(smb_fname_dst,
7739 tmp = talloc_strdup(smb_fname_dst,
7743 status = NT_STATUS_NO_MEMORY;
7744 TALLOC_FREE(fname_dst_parent);
7745 TALLOC_FREE(orig_lcomp_path);
7746 TALLOC_FREE(orig_lcomp_stream);
7749 TALLOC_FREE(smb_fname_dst->base_name);
7750 smb_fname_dst->base_name = tmp;
7753 /* If the stream_names only differ by case, use original. */
7754 if(!strcsequal(smb_fname_dst->stream_name,
7755 orig_lcomp_stream)) {
7756 /* Use the original stream. */
7757 char *tmp = talloc_strdup(smb_fname_dst,
7760 status = NT_STATUS_NO_MEMORY;
7761 TALLOC_FREE(fname_dst_parent);
7762 TALLOC_FREE(orig_lcomp_path);
7763 TALLOC_FREE(orig_lcomp_stream);
7766 TALLOC_FREE(smb_fname_dst->stream_name);
7767 smb_fname_dst->stream_name = tmp;
7769 TALLOC_FREE(fname_dst_parent);
7770 TALLOC_FREE(orig_lcomp_path);
7771 TALLOC_FREE(orig_lcomp_stream);
7775 * If the src and dest names are identical - including case,
7776 * don't do the rename, just return success.
7779 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7780 strcsequal(fsp->fsp_name->stream_name,
7781 smb_fname_dst->stream_name)) {
7782 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7783 "- returning success\n",
7784 smb_fname_str_dbg(smb_fname_dst)));
7785 status = NT_STATUS_OK;
7789 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7790 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7792 /* Return the correct error code if both names aren't streams. */
7793 if (!old_is_stream && new_is_stream) {
7794 status = NT_STATUS_OBJECT_NAME_INVALID;
7798 if (old_is_stream && !new_is_stream) {
7799 status = NT_STATUS_INVALID_PARAMETER;
7803 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7805 if(!replace_if_exists && dst_exists) {
7806 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7807 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7808 smb_fname_str_dbg(smb_fname_dst)));
7809 status = NT_STATUS_OBJECT_NAME_COLLISION;
7814 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7815 &smb_fname_dst->st);
7816 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7818 /* The file can be open when renaming a stream */
7819 if (dst_fsp && !new_is_stream) {
7820 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7821 status = NT_STATUS_ACCESS_DENIED;
7826 /* Ensure we have a valid stat struct for the source. */
7827 status = vfs_stat_fsp(fsp);
7828 if (!NT_STATUS_IS_OK(status)) {
7832 status = can_rename(conn, fsp, attrs);
7834 if (!NT_STATUS_IS_OK(status)) {
7835 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7836 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7837 smb_fname_str_dbg(smb_fname_dst)));
7838 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7839 status = NT_STATUS_ACCESS_DENIED;
7843 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7844 status = NT_STATUS_ACCESS_DENIED;
7848 /* Do we have rights to move into the destination ? */
7849 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7850 /* We're moving a directory. */
7851 access_mask = SEC_DIR_ADD_SUBDIR;
7853 status = check_parent_access(conn,
7857 if (!NT_STATUS_IS_OK(status)) {
7858 DBG_INFO("check_parent_access on "
7859 "dst %s returned %s\n",
7860 smb_fname_str_dbg(smb_fname_dst),
7865 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7868 * We have the file open ourselves, so not being able to get the
7869 * corresponding share mode lock is a fatal error.
7872 SMB_ASSERT(lck != NULL);
7874 ret = SMB_VFS_RENAMEAT(conn,
7880 uint32_t create_options = fsp->fh->private_options;
7882 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7883 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7884 smb_fname_str_dbg(smb_fname_dst)));
7886 if (!fsp->fsp_flags.is_directory &&
7887 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7888 (lp_map_archive(SNUM(conn)) ||
7889 lp_store_dos_attributes(SNUM(conn)))) {
7890 /* We must set the archive bit on the newly
7892 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7893 uint32_t old_dosmode = dos_mode(conn,
7895 file_set_dosmode(conn,
7897 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7904 fsp->fsp_flags.is_directory,
7908 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7912 * A rename acts as a new file create w.r.t. allowing an initial delete
7913 * on close, probably because in Windows there is a new handle to the
7914 * new file. If initial delete on close was requested but not
7915 * originally set, we need to set it here. This is probably not 100% correct,
7916 * but will work for the CIFSFS client which in non-posix mode
7917 * depends on these semantics. JRA.
7920 if (create_options & FILE_DELETE_ON_CLOSE) {
7921 status = can_set_delete_on_close(fsp, 0);
7923 if (NT_STATUS_IS_OK(status)) {
7924 /* Note that here we set the *initial* delete on close flag,
7925 * not the regular one. The magic gets handled in close. */
7926 fsp->fsp_flags.initial_delete_on_close = true;
7930 status = NT_STATUS_OK;
7936 if (errno == ENOTDIR || errno == EISDIR) {
7937 status = NT_STATUS_OBJECT_NAME_COLLISION;
7939 status = map_nt_error_from_unix(errno);
7942 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7943 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7944 smb_fname_str_dbg(smb_fname_dst)));
7947 TALLOC_FREE(smb_fname_dst);
7952 /****************************************************************************
7953 The guts of the rename command, split out so it may be called by the NT SMB
7955 ****************************************************************************/
7957 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7958 connection_struct *conn,
7959 struct smb_request *req,
7960 struct smb_filename *smb_fname_src,
7961 struct smb_filename *smb_fname_dst,
7962 const char *dst_original_lcomp,
7964 bool replace_if_exists,
7967 uint32_t access_mask)
7969 char *fname_src_dir = NULL;
7970 struct smb_filename *smb_fname_src_dir = NULL;
7971 char *fname_src_mask = NULL;
7973 NTSTATUS status = NT_STATUS_OK;
7974 struct smb_Dir *dir_hnd = NULL;
7975 const char *dname = NULL;
7976 char *talloced = NULL;
7978 int create_options = 0;
7979 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7980 struct smb2_create_blobs *posx = NULL;
7984 * Split the old name into directory and last component
7985 * strings. Note that unix_convert may have stripped off a
7986 * leading ./ from both name and newname if the rename is
7987 * at the root of the share. We need to make sure either both
7988 * name and newname contain a / character or neither of them do
7989 * as this is checked in resolve_wildcards().
7992 /* Split up the directory from the filename/mask. */
7993 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7994 &fname_src_dir, &fname_src_mask);
7995 if (!NT_STATUS_IS_OK(status)) {
7996 status = NT_STATUS_NO_MEMORY;
8001 * We should only check the mangled cache
8002 * here if unix_convert failed. This means
8003 * that the path in 'mask' doesn't exist
8004 * on the file system and so we need to look
8005 * for a possible mangle. This patch from
8006 * Tine Smukavec <valentin.smukavec@hermes.si>.
8009 if (!VALID_STAT(smb_fname_src->st) &&
8010 mangle_is_mangled(fname_src_mask, conn->params)) {
8011 char *new_mask = NULL;
8012 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
8015 TALLOC_FREE(fname_src_mask);
8016 fname_src_mask = new_mask;
8020 if (posix_pathnames) {
8021 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8022 if (!NT_STATUS_IS_OK(status)) {
8023 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8029 if (!src_has_wild) {
8033 * Only one file needs to be renamed. Append the mask back
8034 * onto the directory.
8036 TALLOC_FREE(smb_fname_src->base_name);
8037 if (ISDOT(fname_src_dir)) {
8038 /* Ensure we use canonical names on open. */
8039 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8043 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8048 if (!smb_fname_src->base_name) {
8049 status = NT_STATUS_NO_MEMORY;
8053 DEBUG(3, ("rename_internals: case_sensitive = %d, "
8054 "case_preserve = %d, short case preserve = %d, "
8055 "directory = %s, newname = %s, "
8056 "last_component_dest = %s\n",
8057 conn->case_sensitive, conn->case_preserve,
8058 conn->short_case_preserve,
8059 smb_fname_str_dbg(smb_fname_src),
8060 smb_fname_str_dbg(smb_fname_dst),
8061 dst_original_lcomp));
8063 /* The dest name still may have wildcards. */
8064 if (dest_has_wild) {
8065 char *fname_dst_mod = NULL;
8066 if (!resolve_wildcards(smb_fname_dst,
8067 smb_fname_src->base_name,
8068 smb_fname_dst->base_name,
8070 DEBUG(6, ("rename_internals: resolve_wildcards "
8072 smb_fname_src->base_name,
8073 smb_fname_dst->base_name));
8074 status = NT_STATUS_NO_MEMORY;
8077 TALLOC_FREE(smb_fname_dst->base_name);
8078 smb_fname_dst->base_name = fname_dst_mod;
8081 ZERO_STRUCT(smb_fname_src->st);
8082 if (posix_pathnames) {
8083 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8085 rc = SMB_VFS_STAT(conn, smb_fname_src);
8088 status = map_nt_error_from_unix_common(errno);
8092 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8093 create_options |= FILE_DIRECTORY_FILE;
8096 status = SMB_VFS_CREATE_FILE(
8099 &conn->cwd_fsp, /* dirfsp */
8100 smb_fname_src, /* fname */
8101 access_mask, /* access_mask */
8102 (FILE_SHARE_READ | /* share_access */
8104 FILE_OPEN, /* create_disposition*/
8105 create_options, /* create_options */
8106 0, /* file_attributes */
8107 0, /* oplock_request */
8109 0, /* allocation_size */
8110 0, /* private_flags */
8115 posx, /* in_context_blobs */
8116 NULL); /* out_context_blobs */
8118 if (!NT_STATUS_IS_OK(status)) {
8119 DEBUG(3, ("Could not open rename source %s: %s\n",
8120 smb_fname_str_dbg(smb_fname_src),
8121 nt_errstr(status)));
8125 status = rename_internals_fsp(conn,
8132 close_file(req, fsp, NORMAL_CLOSE);
8134 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8135 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8136 smb_fname_str_dbg(smb_fname_dst)));
8142 * Wildcards - process each file that matches.
8144 if (strequal(fname_src_mask, "????????.???")) {
8145 TALLOC_FREE(fname_src_mask);
8146 fname_src_mask = talloc_strdup(ctx, "*");
8147 if (!fname_src_mask) {
8148 status = NT_STATUS_NO_MEMORY;
8153 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8157 smb_fname_src->twrp,
8158 smb_fname_src->flags);
8159 if (smb_fname_src_dir == NULL) {
8160 status = NT_STATUS_NO_MEMORY;
8164 status = check_name(conn, smb_fname_src_dir);
8165 if (!NT_STATUS_IS_OK(status)) {
8169 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8171 if (dir_hnd == NULL) {
8172 status = map_nt_error_from_unix(errno);
8176 status = NT_STATUS_NO_SUCH_FILE;
8178 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8179 * - gentest fix. JRA
8182 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8184 files_struct *fsp = NULL;
8185 char *destname = NULL;
8186 bool sysdir_entry = False;
8188 /* Quick check for "." and ".." */
8189 if (ISDOT(dname) || ISDOTDOT(dname)) {
8190 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8191 sysdir_entry = True;
8193 TALLOC_FREE(talloced);
8198 if (!is_visible_file(conn,
8203 TALLOC_FREE(talloced);
8207 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8208 TALLOC_FREE(talloced);
8213 status = NT_STATUS_OBJECT_NAME_INVALID;
8217 TALLOC_FREE(smb_fname_src->base_name);
8218 if (ISDOT(fname_src_dir)) {
8219 /* Ensure we use canonical names on open. */
8220 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8224 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8229 if (!smb_fname_src->base_name) {
8230 status = NT_STATUS_NO_MEMORY;
8234 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8235 smb_fname_dst->base_name,
8237 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8238 smb_fname_src->base_name, destname));
8239 TALLOC_FREE(talloced);
8243 status = NT_STATUS_NO_MEMORY;
8247 TALLOC_FREE(smb_fname_dst->base_name);
8248 smb_fname_dst->base_name = destname;
8250 ZERO_STRUCT(smb_fname_src->st);
8251 if (posix_pathnames) {
8252 SMB_VFS_LSTAT(conn, smb_fname_src);
8254 SMB_VFS_STAT(conn, smb_fname_src);
8259 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8260 create_options |= FILE_DIRECTORY_FILE;
8263 status = SMB_VFS_CREATE_FILE(
8266 &conn->cwd_fsp, /* dirfsp */
8267 smb_fname_src, /* fname */
8268 access_mask, /* access_mask */
8269 (FILE_SHARE_READ | /* share_access */
8271 FILE_OPEN, /* create_disposition*/
8272 create_options, /* create_options */
8273 0, /* file_attributes */
8274 0, /* oplock_request */
8276 0, /* allocation_size */
8277 0, /* private_flags */
8282 posx, /* in_context_blobs */
8283 NULL); /* out_context_blobs */
8285 if (!NT_STATUS_IS_OK(status)) {
8286 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8287 "returned %s rename %s -> %s\n",
8289 smb_fname_str_dbg(smb_fname_src),
8290 smb_fname_str_dbg(smb_fname_dst)));
8294 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8295 if (dst_original_lcomp == NULL) {
8296 status = NT_STATUS_NO_MEMORY;
8300 status = rename_internals_fsp(conn,
8307 close_file(req, fsp, NORMAL_CLOSE);
8309 if (!NT_STATUS_IS_OK(status)) {
8310 DEBUG(3, ("rename_internals_fsp returned %s for "
8311 "rename %s -> %s\n", nt_errstr(status),
8312 smb_fname_str_dbg(smb_fname_src),
8313 smb_fname_str_dbg(smb_fname_dst)));
8319 DEBUG(3,("rename_internals: doing rename on %s -> "
8320 "%s\n", smb_fname_str_dbg(smb_fname_src),
8321 smb_fname_str_dbg(smb_fname_src)));
8322 TALLOC_FREE(talloced);
8324 TALLOC_FREE(dir_hnd);
8326 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8327 status = map_nt_error_from_unix(errno);
8332 TALLOC_FREE(talloced);
8333 TALLOC_FREE(smb_fname_src_dir);
8334 TALLOC_FREE(fname_src_dir);
8335 TALLOC_FREE(fname_src_mask);
8339 /****************************************************************************
8341 ****************************************************************************/
8343 void reply_mv(struct smb_request *req)
8345 connection_struct *conn = req->conn;
8347 char *newname = NULL;
8351 bool src_has_wcard = False;
8352 bool dest_has_wcard = False;
8353 TALLOC_CTX *ctx = talloc_tos();
8354 struct smb_filename *smb_fname_src = NULL;
8355 struct smb_filename *smb_fname_dst = NULL;
8356 const char *dst_original_lcomp = NULL;
8357 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8358 (req->posix_pathnames ?
8359 UCF_UNIX_NAME_LOOKUP :
8360 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8361 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8362 (req->posix_pathnames ?
8364 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8365 bool stream_rename = false;
8367 START_PROFILE(SMBmv);
8370 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8374 attrs = SVAL(req->vwv+0, 0);
8376 p = (const char *)req->buf + 1;
8377 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
8378 &status, &src_has_wcard);
8379 if (!NT_STATUS_IS_OK(status)) {
8380 reply_nterror(req, status);
8384 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
8385 &status, &dest_has_wcard);
8386 if (!NT_STATUS_IS_OK(status)) {
8387 reply_nterror(req, status);
8391 if (!req->posix_pathnames) {
8392 /* The newname must begin with a ':' if the
8393 name contains a ':'. */
8394 if (strchr_m(name, ':')) {
8395 if (newname[0] != ':') {
8396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8399 stream_rename = true;
8403 status = filename_convert(ctx,
8411 if (!NT_STATUS_IS_OK(status)) {
8412 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8413 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8414 ERRSRV, ERRbadpath);
8417 reply_nterror(req, status);
8421 status = filename_convert(ctx,
8429 if (!NT_STATUS_IS_OK(status)) {
8430 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8431 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8432 ERRSRV, ERRbadpath);
8435 reply_nterror(req, status);
8439 /* Get the last component of the destination for rename_internals(). */
8440 dst_original_lcomp = get_original_lcomp(ctx,
8444 if (dst_original_lcomp == NULL) {
8445 reply_nterror(req, NT_STATUS_NO_MEMORY);
8449 if (stream_rename) {
8450 /* smb_fname_dst->base_name must be the same as
8451 smb_fname_src->base_name. */
8452 TALLOC_FREE(smb_fname_dst->base_name);
8453 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8454 smb_fname_src->base_name);
8455 if (!smb_fname_dst->base_name) {
8456 reply_nterror(req, NT_STATUS_NO_MEMORY);
8461 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8462 smb_fname_str_dbg(smb_fname_dst)));
8464 status = rename_internals(ctx,
8475 if (!NT_STATUS_IS_OK(status)) {
8476 if (open_was_deferred(req->xconn, req->mid)) {
8477 /* We have re-scheduled this call. */
8480 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8481 bool ok = defer_smb1_sharing_violation(req);
8486 reply_nterror(req, status);
8490 reply_outbuf(req, 0, 0);
8492 TALLOC_FREE(smb_fname_src);
8493 TALLOC_FREE(smb_fname_dst);
8498 /*******************************************************************
8499 Copy a file as part of a reply_copy.
8500 ******************************************************************/
8503 * TODO: check error codes on all callers
8506 NTSTATUS copy_file(TALLOC_CTX *ctx,
8507 connection_struct *conn,
8508 struct smb_filename *smb_fname_src,
8509 struct smb_filename *smb_fname_dst,
8512 bool target_is_directory)
8514 struct smb_filename *smb_fname_dst_tmp = NULL;
8516 files_struct *fsp1,*fsp2;
8518 uint32_t new_create_disposition;
8522 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8523 if (smb_fname_dst_tmp == NULL) {
8524 return NT_STATUS_NO_MEMORY;
8528 * If the target is a directory, extract the last component from the
8529 * src filename and append it to the dst filename
8531 if (target_is_directory) {
8534 /* dest/target can't be a stream if it's a directory. */
8535 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8537 p = strrchr_m(smb_fname_src->base_name,'/');
8541 p = smb_fname_src->base_name;
8543 smb_fname_dst_tmp->base_name =
8544 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8546 if (!smb_fname_dst_tmp->base_name) {
8547 status = NT_STATUS_NO_MEMORY;
8552 status = vfs_file_exist(conn, smb_fname_src);
8553 if (!NT_STATUS_IS_OK(status)) {
8557 if (!target_is_directory && count) {
8558 new_create_disposition = FILE_OPEN;
8560 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8563 &new_create_disposition,
8566 status = NT_STATUS_INVALID_PARAMETER;
8571 /* Open the src file for reading. */
8572 status = SMB_VFS_CREATE_FILE(
8575 &conn->cwd_fsp, /* dirfsp */
8576 smb_fname_src, /* fname */
8577 FILE_GENERIC_READ, /* access_mask */
8578 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8579 FILE_OPEN, /* create_disposition*/
8580 0, /* create_options */
8581 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8582 INTERNAL_OPEN_ONLY, /* oplock_request */
8584 0, /* allocation_size */
8585 0, /* private_flags */
8590 NULL, NULL); /* create context */
8592 if (!NT_STATUS_IS_OK(status)) {
8596 dosattrs = dos_mode(conn, smb_fname_src);
8598 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8599 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8602 /* Open the dst file for writing. */
8603 status = SMB_VFS_CREATE_FILE(
8606 &conn->cwd_fsp, /* dirfsp */
8607 smb_fname_dst, /* fname */
8608 FILE_GENERIC_WRITE, /* access_mask */
8609 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8610 new_create_disposition, /* create_disposition*/
8611 0, /* create_options */
8612 dosattrs, /* file_attributes */
8613 INTERNAL_OPEN_ONLY, /* oplock_request */
8615 0, /* allocation_size */
8616 0, /* private_flags */
8621 NULL, NULL); /* create context */
8623 if (!NT_STATUS_IS_OK(status)) {
8624 close_file(NULL, fsp1, ERROR_CLOSE);
8628 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8629 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8631 DEBUG(0, ("error - vfs lseek returned error %s\n",
8633 status = map_nt_error_from_unix(errno);
8634 close_file(NULL, fsp1, ERROR_CLOSE);
8635 close_file(NULL, fsp2, ERROR_CLOSE);
8640 /* Do the actual copy. */
8641 if (smb_fname_src->st.st_ex_size) {
8642 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8647 close_file(NULL, fsp1, NORMAL_CLOSE);
8649 /* Ensure the modtime is set correctly on the destination file. */
8650 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8653 * As we are opening fsp1 read-only we only expect
8654 * an error on close on fsp2 if we are out of space.
8655 * Thus we don't look at the error return from the
8658 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8660 if (!NT_STATUS_IS_OK(status)) {
8664 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8665 status = NT_STATUS_DISK_FULL;
8669 status = NT_STATUS_OK;
8672 TALLOC_FREE(smb_fname_dst_tmp);
8676 /****************************************************************************
8677 Reply to a file copy.
8678 ****************************************************************************/
8680 void reply_copy(struct smb_request *req)
8682 connection_struct *conn = req->conn;
8683 struct smb_filename *smb_fname_src = NULL;
8684 struct smb_filename *smb_fname_src_dir = NULL;
8685 struct smb_filename *smb_fname_dst = NULL;
8686 char *fname_src = NULL;
8687 char *fname_dst = NULL;
8688 char *fname_src_mask = NULL;
8689 char *fname_src_dir = NULL;
8692 int error = ERRnoaccess;
8696 bool target_is_directory=False;
8697 bool source_has_wild = False;
8698 bool dest_has_wild = False;
8700 uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8701 ucf_flags_from_smb_request(req);
8702 uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8703 ucf_flags_from_smb_request(req);
8704 TALLOC_CTX *ctx = talloc_tos();
8706 START_PROFILE(SMBcopy);
8709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8713 tid2 = SVAL(req->vwv+0, 0);
8714 ofun = SVAL(req->vwv+1, 0);
8715 flags = SVAL(req->vwv+2, 0);
8717 p = (const char *)req->buf;
8718 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8719 &status, &source_has_wild);
8720 if (!NT_STATUS_IS_OK(status)) {
8721 reply_nterror(req, status);
8724 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8725 &status, &dest_has_wild);
8726 if (!NT_STATUS_IS_OK(status)) {
8727 reply_nterror(req, status);
8731 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8733 if (tid2 != conn->cnum) {
8734 /* can't currently handle inter share copies XXXX */
8735 DEBUG(3,("Rejecting inter-share copy\n"));
8736 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8740 status = filename_convert(ctx, conn,
8746 if (!NT_STATUS_IS_OK(status)) {
8747 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8748 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8749 ERRSRV, ERRbadpath);
8752 reply_nterror(req, status);
8756 status = filename_convert(ctx, conn,
8762 if (!NT_STATUS_IS_OK(status)) {
8763 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8764 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8765 ERRSRV, ERRbadpath);
8768 reply_nterror(req, status);
8772 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8774 if ((flags&1) && target_is_directory) {
8775 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8779 if ((flags&2) && !target_is_directory) {
8780 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8784 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8785 /* wants a tree copy! XXXX */
8786 DEBUG(3,("Rejecting tree copy\n"));
8787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8791 /* Split up the directory from the filename/mask. */
8792 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8793 &fname_src_dir, &fname_src_mask);
8794 if (!NT_STATUS_IS_OK(status)) {
8795 reply_nterror(req, NT_STATUS_NO_MEMORY);
8800 * We should only check the mangled cache
8801 * here if unix_convert failed. This means
8802 * that the path in 'mask' doesn't exist
8803 * on the file system and so we need to look
8804 * for a possible mangle. This patch from
8805 * Tine Smukavec <valentin.smukavec@hermes.si>.
8807 if (!VALID_STAT(smb_fname_src->st) &&
8808 mangle_is_mangled(fname_src_mask, conn->params)) {
8809 char *new_mask = NULL;
8810 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8811 &new_mask, conn->params);
8813 /* Use demangled name if one was successfully found. */
8815 TALLOC_FREE(fname_src_mask);
8816 fname_src_mask = new_mask;
8820 if (!source_has_wild) {
8823 * Only one file needs to be copied. Append the mask back onto
8826 TALLOC_FREE(smb_fname_src->base_name);
8827 if (ISDOT(fname_src_dir)) {
8828 /* Ensure we use canonical names on open. */
8829 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8833 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8838 if (!smb_fname_src->base_name) {
8839 reply_nterror(req, NT_STATUS_NO_MEMORY);
8843 if (dest_has_wild) {
8844 char *fname_dst_mod = NULL;
8845 if (!resolve_wildcards(smb_fname_dst,
8846 smb_fname_src->base_name,
8847 smb_fname_dst->base_name,
8849 reply_nterror(req, NT_STATUS_NO_MEMORY);
8852 TALLOC_FREE(smb_fname_dst->base_name);
8853 smb_fname_dst->base_name = fname_dst_mod;
8856 status = check_name(conn, smb_fname_src);
8857 if (!NT_STATUS_IS_OK(status)) {
8858 reply_nterror(req, status);
8862 status = check_name(conn, smb_fname_dst);
8863 if (!NT_STATUS_IS_OK(status)) {
8864 reply_nterror(req, status);
8868 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8869 ofun, count, target_is_directory);
8871 if(!NT_STATUS_IS_OK(status)) {
8872 reply_nterror(req, status);
8878 struct smb_Dir *dir_hnd = NULL;
8879 const char *dname = NULL;
8880 char *talloced = NULL;
8884 * There is a wildcard that requires us to actually read the
8885 * src dir and copy each file matching the mask to the dst.
8886 * Right now streams won't be copied, but this could
8887 * presumably be added with a nested loop for reach dir entry.
8889 SMB_ASSERT(!smb_fname_src->stream_name);
8890 SMB_ASSERT(!smb_fname_dst->stream_name);
8892 smb_fname_src->stream_name = NULL;
8893 smb_fname_dst->stream_name = NULL;
8895 if (strequal(fname_src_mask,"????????.???")) {
8896 TALLOC_FREE(fname_src_mask);
8897 fname_src_mask = talloc_strdup(ctx, "*");
8898 if (!fname_src_mask) {
8899 reply_nterror(req, NT_STATUS_NO_MEMORY);
8904 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8908 smb_fname_src->twrp,
8909 smb_fname_src->flags);
8910 if (smb_fname_src_dir == NULL) {
8911 reply_nterror(req, NT_STATUS_NO_MEMORY);
8915 status = check_name(conn, smb_fname_src_dir);
8916 if (!NT_STATUS_IS_OK(status)) {
8917 reply_nterror(req, status);
8921 dir_hnd = OpenDir(ctx,
8926 if (dir_hnd == NULL) {
8927 status = map_nt_error_from_unix(errno);
8928 reply_nterror(req, status);
8934 /* Iterate over the src dir copying each entry to the dst. */
8935 while ((dname = ReadDirName(dir_hnd, &offset,
8936 &smb_fname_src->st, &talloced))) {
8937 char *destname = NULL;
8939 if (ISDOT(dname) || ISDOTDOT(dname)) {
8940 TALLOC_FREE(talloced);
8944 if (!is_visible_file(conn,
8949 TALLOC_FREE(talloced);
8953 if(!mask_match(dname, fname_src_mask,
8954 conn->case_sensitive)) {
8955 TALLOC_FREE(talloced);
8959 error = ERRnoaccess;
8961 /* Get the src smb_fname struct setup. */
8962 TALLOC_FREE(smb_fname_src->base_name);
8963 if (ISDOT(fname_src_dir)) {
8964 /* Ensure we use canonical names on open. */
8965 smb_fname_src->base_name =
8966 talloc_asprintf(smb_fname_src, "%s",
8969 smb_fname_src->base_name =
8970 talloc_asprintf(smb_fname_src, "%s/%s",
8971 fname_src_dir, dname);
8974 if (!smb_fname_src->base_name) {
8975 TALLOC_FREE(dir_hnd);
8976 TALLOC_FREE(talloced);
8977 reply_nterror(req, NT_STATUS_NO_MEMORY);
8981 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8982 smb_fname_dst->base_name,
8984 TALLOC_FREE(talloced);
8988 TALLOC_FREE(dir_hnd);
8989 TALLOC_FREE(talloced);
8990 reply_nterror(req, NT_STATUS_NO_MEMORY);
8994 TALLOC_FREE(smb_fname_dst->base_name);
8995 smb_fname_dst->base_name = destname;
8997 status = check_name(conn, smb_fname_src);
8998 if (!NT_STATUS_IS_OK(status)) {
8999 TALLOC_FREE(dir_hnd);
9000 TALLOC_FREE(talloced);
9001 reply_nterror(req, status);
9005 status = check_name(conn, smb_fname_dst);
9006 if (!NT_STATUS_IS_OK(status)) {
9007 TALLOC_FREE(dir_hnd);
9008 TALLOC_FREE(talloced);
9009 reply_nterror(req, status);
9013 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
9014 smb_fname_src->base_name,
9015 smb_fname_dst->base_name));
9017 status = copy_file(ctx, conn, smb_fname_src,
9018 smb_fname_dst, ofun, count,
9019 target_is_directory);
9020 if (NT_STATUS_IS_OK(status)) {
9024 TALLOC_FREE(talloced);
9026 TALLOC_FREE(dir_hnd);
9030 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
9034 reply_outbuf(req, 1, 0);
9035 SSVAL(req->outbuf,smb_vwv0,count);
9037 TALLOC_FREE(smb_fname_src);
9038 TALLOC_FREE(smb_fname_src_dir);
9039 TALLOC_FREE(smb_fname_dst);
9040 TALLOC_FREE(fname_src);
9041 TALLOC_FREE(fname_dst);
9042 TALLOC_FREE(fname_src_mask);
9043 TALLOC_FREE(fname_src_dir);
9045 END_PROFILE(SMBcopy);
9050 #define DBGC_CLASS DBGC_LOCKING
9052 /****************************************************************************
9053 Get a lock pid, dealing with large count requests.
9054 ****************************************************************************/
9056 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
9057 bool large_file_format)
9059 if(!large_file_format)
9060 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9062 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9065 /****************************************************************************
9066 Get a lock count, dealing with large count requests.
9067 ****************************************************************************/
9069 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9070 bool large_file_format)
9074 if(!large_file_format) {
9075 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9078 * No BVAL, this is reversed!
9080 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9081 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9087 /****************************************************************************
9088 Get a lock offset, dealing with large offset requests.
9089 ****************************************************************************/
9091 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9092 bool large_file_format)
9094 uint64_t offset = 0;
9096 if(!large_file_format) {
9097 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9100 * No BVAL, this is reversed!
9102 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9103 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9109 struct smbd_do_unlocking_state {
9110 struct files_struct *fsp;
9111 uint16_t num_ulocks;
9112 struct smbd_lock_element *ulocks;
9113 enum brl_flavour lock_flav;
9117 static void smbd_do_unlocking_fn(
9120 bool *pmodified_dependent,
9123 struct smbd_do_unlocking_state *state = private_data;
9124 struct files_struct *fsp = state->fsp;
9125 enum brl_flavour lock_flav = state->lock_flav;
9128 for (i = 0; i < state->num_ulocks; i++) {
9129 struct smbd_lock_element *e = &state->ulocks[i];
9131 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9132 "pid %"PRIu64", file %s\n",
9138 if (e->brltype != UNLOCK_LOCK) {
9139 /* this can only happen with SMB2 */
9140 state->status = NT_STATUS_INVALID_PARAMETER;
9144 state->status = do_unlock(
9145 fsp, e->smblctx, e->count, e->offset, lock_flav);
9147 DBG_DEBUG("do_unlock returned %s\n",
9148 nt_errstr(state->status));
9150 if (!NT_STATUS_IS_OK(state->status)) {
9155 *pmodified_dependent = true;
9158 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9160 uint16_t num_ulocks,
9161 struct smbd_lock_element *ulocks,
9162 enum brl_flavour lock_flav)
9164 struct smbd_do_unlocking_state state = {
9166 .num_ulocks = num_ulocks,
9168 .lock_flav = lock_flav,
9172 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9174 status = share_mode_do_locked(
9175 fsp->file_id, smbd_do_unlocking_fn, &state);
9177 if (!NT_STATUS_IS_OK(status)) {
9178 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9182 if (!NT_STATUS_IS_OK(state.status)) {
9183 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9185 return state.status;
9188 return NT_STATUS_OK;
9191 /****************************************************************************
9192 Reply to a lockingX request.
9193 ****************************************************************************/
9195 static void reply_lockingx_done(struct tevent_req *subreq);
9197 void reply_lockingX(struct smb_request *req)
9199 connection_struct *conn = req->conn;
9201 unsigned char locktype;
9202 enum brl_type brltype;
9203 unsigned char oplocklevel;
9204 uint16_t num_ulocks;
9206 int32_t lock_timeout;
9208 const uint8_t *data;
9209 bool large_file_format;
9210 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9211 struct smbd_lock_element *locks = NULL;
9212 struct tevent_req *subreq = NULL;
9214 START_PROFILE(SMBlockingX);
9217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9218 END_PROFILE(SMBlockingX);
9222 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9223 locktype = CVAL(req->vwv+3, 0);
9224 oplocklevel = CVAL(req->vwv+3, 1);
9225 num_ulocks = SVAL(req->vwv+6, 0);
9226 num_locks = SVAL(req->vwv+7, 0);
9227 lock_timeout = IVAL(req->vwv+4, 0);
9228 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9230 if (!check_fsp(conn, req, fsp)) {
9231 END_PROFILE(SMBlockingX);
9237 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9238 /* we don't support these - and CANCEL_LOCK makes w2k
9239 and XP reboot so I don't really want to be
9240 compatible! (tridge) */
9241 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9242 END_PROFILE(SMBlockingX);
9246 /* Check if this is an oplock break on a file
9247 we have granted an oplock on.
9249 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9250 /* Client can insist on breaking to none. */
9251 bool break_to_none = (oplocklevel == 0);
9254 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9255 "for %s\n", (unsigned int)oplocklevel,
9256 fsp_fnum_dbg(fsp)));
9259 * Make sure we have granted an exclusive or batch oplock on
9263 if (fsp->oplock_type == 0) {
9265 /* The Samba4 nbench simulator doesn't understand
9266 the difference between break to level2 and break
9267 to none from level2 - it sends oplock break
9268 replies in both cases. Don't keep logging an error
9269 message here - just ignore it. JRA. */
9271 DEBUG(5,("reply_lockingX: Error : oplock break from "
9272 "client for %s (oplock=%d) and no "
9273 "oplock granted on this file (%s).\n",
9274 fsp_fnum_dbg(fsp), fsp->oplock_type,
9277 /* if this is a pure oplock break request then don't
9279 if (num_locks == 0 && num_ulocks == 0) {
9280 END_PROFILE(SMBlockingX);
9284 END_PROFILE(SMBlockingX);
9285 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9289 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9291 result = remove_oplock(fsp);
9293 result = downgrade_oplock(fsp);
9297 DEBUG(0, ("reply_lockingX: error in removing "
9298 "oplock on file %s\n", fsp_str_dbg(fsp)));
9299 /* Hmmm. Is this panic justified? */
9300 smb_panic("internal tdb error");
9303 /* if this is a pure oplock break request then don't send a
9305 if (num_locks == 0 && num_ulocks == 0) {
9306 /* Sanity check - ensure a pure oplock break is not a
9308 if (CVAL(req->vwv+0, 0) != 0xff) {
9309 DEBUG(0,("reply_lockingX: Error : pure oplock "
9310 "break is a chained %d request !\n",
9311 (unsigned int)CVAL(req->vwv+0, 0)));
9313 END_PROFILE(SMBlockingX);
9319 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9321 END_PROFILE(SMBlockingX);
9325 if (num_ulocks != 0) {
9326 struct smbd_lock_element *ulocks = NULL;
9329 ulocks = talloc_array(
9330 req, struct smbd_lock_element, num_ulocks);
9331 if (ulocks == NULL) {
9332 reply_nterror(req, NT_STATUS_NO_MEMORY);
9333 END_PROFILE(SMBlockingX);
9338 * Data now points at the beginning of the list of
9339 * smb_unlkrng structs
9341 for (i = 0; i < num_ulocks; i++) {
9342 ulocks[i].req_guid = smbd_request_guid(req,
9344 ulocks[i].smblctx = get_lock_pid(
9345 data, i, large_file_format);
9346 ulocks[i].count = get_lock_count(
9347 data, i, large_file_format);
9348 ulocks[i].offset = get_lock_offset(
9349 data, i, large_file_format);
9350 ulocks[i].brltype = UNLOCK_LOCK;
9354 * Unlock cancels pending locks
9357 ok = smbd_smb1_brl_finish_by_lock(
9364 reply_outbuf(req, 2, 0);
9365 SSVAL(req->outbuf, smb_vwv0, 0xff);
9366 SSVAL(req->outbuf, smb_vwv1, 0);
9367 END_PROFILE(SMBlockingX);
9371 status = smbd_do_unlocking(
9372 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9373 TALLOC_FREE(ulocks);
9374 if (!NT_STATUS_IS_OK(status)) {
9375 END_PROFILE(SMBlockingX);
9376 reply_nterror(req, status);
9381 /* Now do any requested locks */
9382 data += ((large_file_format ? 20 : 10)*num_ulocks);
9384 /* Data now points at the beginning of the list
9385 of smb_lkrng structs */
9387 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9388 brltype = READ_LOCK;
9390 brltype = WRITE_LOCK;
9393 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9394 if (locks == NULL) {
9395 reply_nterror(req, NT_STATUS_NO_MEMORY);
9396 END_PROFILE(SMBlockingX);
9400 for (i = 0; i < num_locks; i++) {
9401 locks[i].req_guid = smbd_request_guid(req, i),
9402 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9403 locks[i].count = get_lock_count(data, i, large_file_format);
9404 locks[i].offset = get_lock_offset(data, i, large_file_format);
9405 locks[i].brltype = brltype;
9408 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9412 if (num_locks == 0) {
9413 /* See smbtorture3 lock11 test */
9414 reply_outbuf(req, 2, 0);
9415 /* andx chain ends */
9416 SSVAL(req->outbuf, smb_vwv0, 0xff);
9417 SSVAL(req->outbuf, smb_vwv1, 0);
9418 END_PROFILE(SMBlockingX);
9422 ok = smbd_smb1_brl_finish_by_lock(
9426 locks[0], /* Windows only cancels the first lock */
9427 NT_STATUS_FILE_LOCK_CONFLICT);
9430 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9431 END_PROFILE(SMBlockingX);
9435 reply_outbuf(req, 2, 0);
9436 SSVAL(req->outbuf, smb_vwv0, 0xff);
9437 SSVAL(req->outbuf, smb_vwv1, 0);
9438 END_PROFILE(SMBlockingX);
9442 subreq = smbd_smb1_do_locks_send(
9452 if (subreq == NULL) {
9453 reply_nterror(req, NT_STATUS_NO_MEMORY);
9454 END_PROFILE(SMBlockingX);
9457 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9458 END_PROFILE(SMBlockingX);
9461 static void reply_lockingx_done(struct tevent_req *subreq)
9463 struct smb_request *req = NULL;
9467 START_PROFILE(SMBlockingX);
9469 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9472 status = smbd_smb1_do_locks_recv(subreq);
9473 TALLOC_FREE(subreq);
9475 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9477 if (NT_STATUS_IS_OK(status)) {
9478 reply_outbuf(req, 2, 0);
9479 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9480 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9482 reply_nterror(req, status);
9485 ok = srv_send_smb(req->xconn,
9486 (char *)req->outbuf,
9489 IS_CONN_ENCRYPTED(req->conn),
9492 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9495 END_PROFILE(SMBlockingX);
9499 #define DBGC_CLASS DBGC_ALL
9501 /****************************************************************************
9502 Reply to a SMBreadbmpx (read block multiplex) request.
9503 Always reply with an error, if someone has a platform really needs this,
9504 please contact vl@samba.org
9505 ****************************************************************************/
9507 void reply_readbmpx(struct smb_request *req)
9509 START_PROFILE(SMBreadBmpx);
9510 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9511 END_PROFILE(SMBreadBmpx);
9515 /****************************************************************************
9516 Reply to a SMBreadbs (read block multiplex secondary) request.
9517 Always reply with an error, if someone has a platform really needs this,
9518 please contact vl@samba.org
9519 ****************************************************************************/
9521 void reply_readbs(struct smb_request *req)
9523 START_PROFILE(SMBreadBs);
9524 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9525 END_PROFILE(SMBreadBs);
9529 /****************************************************************************
9530 Reply to a SMBsetattrE.
9531 ****************************************************************************/
9533 void reply_setattrE(struct smb_request *req)
9535 connection_struct *conn = req->conn;
9536 struct smb_file_time ft;
9540 START_PROFILE(SMBsetattrE);
9541 init_smb_file_time(&ft);
9544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9548 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9550 if(!fsp || (fsp->conn != conn)) {
9551 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9556 * Convert the DOS times into unix times.
9559 ft.atime = time_t_to_full_timespec(
9560 srv_make_unix_date2(req->vwv+3));
9561 ft.mtime = time_t_to_full_timespec(
9562 srv_make_unix_date2(req->vwv+5));
9563 ft.create_time = time_t_to_full_timespec(
9564 srv_make_unix_date2(req->vwv+1));
9566 reply_outbuf(req, 0, 0);
9569 * Patch from Ray Frush <frush@engr.colostate.edu>
9570 * Sometimes times are sent as zero - ignore them.
9573 /* Ensure we have a valid stat struct for the source. */
9574 status = vfs_stat_fsp(fsp);
9575 if (!NT_STATUS_IS_OK(status)) {
9576 reply_nterror(req, status);
9580 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9581 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9585 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9586 if (!NT_STATUS_IS_OK(status)) {
9587 reply_nterror(req, status);
9591 if (fsp->fsp_flags.modified) {
9592 trigger_write_time_update_immediate(fsp);
9595 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9598 (unsigned int)ft.atime.tv_sec,
9599 (unsigned int)ft.mtime.tv_sec,
9600 (unsigned int)ft.create_time.tv_sec
9603 END_PROFILE(SMBsetattrE);
9608 /* Back from the dead for OS/2..... JRA. */
9610 /****************************************************************************
9611 Reply to a SMBwritebmpx (write block multiplex primary) request.
9612 Always reply with an error, if someone has a platform really needs this,
9613 please contact vl@samba.org
9614 ****************************************************************************/
9616 void reply_writebmpx(struct smb_request *req)
9618 START_PROFILE(SMBwriteBmpx);
9619 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9620 END_PROFILE(SMBwriteBmpx);
9624 /****************************************************************************
9625 Reply to a SMBwritebs (write block multiplex secondary) request.
9626 Always reply with an error, if someone has a platform really needs this,
9627 please contact vl@samba.org
9628 ****************************************************************************/
9630 void reply_writebs(struct smb_request *req)
9632 START_PROFILE(SMBwriteBs);
9633 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9634 END_PROFILE(SMBwriteBs);
9638 /****************************************************************************
9639 Reply to a SMBgetattrE.
9640 ****************************************************************************/
9642 void reply_getattrE(struct smb_request *req)
9644 connection_struct *conn = req->conn;
9647 struct timespec create_ts;
9650 START_PROFILE(SMBgetattrE);
9653 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9654 END_PROFILE(SMBgetattrE);
9658 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9660 if(!fsp || (fsp->conn != conn)) {
9661 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9662 END_PROFILE(SMBgetattrE);
9666 /* Do an fstat on this file */
9667 status = vfs_stat_fsp(fsp);
9668 if (!NT_STATUS_IS_OK(status)) {
9669 reply_nterror(req, status);
9670 END_PROFILE(SMBgetattrE);
9674 mode = dos_mode(conn, fsp->fsp_name);
9677 * Convert the times into dos times. Set create
9678 * date to be last modify date as UNIX doesn't save
9682 reply_outbuf(req, 11, 0);
9684 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9685 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9686 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9687 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9688 /* Should we check pending modtime here ? JRA */
9689 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9690 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9692 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9693 SIVAL(req->outbuf, smb_vwv6, 0);
9694 SIVAL(req->outbuf, smb_vwv8, 0);
9696 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9697 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9698 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9700 SSVAL(req->outbuf,smb_vwv10, mode);
9702 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9704 END_PROFILE(SMBgetattrE);