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(ctx, req, &path, p, STR_TERMINATE,
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));
2017 dirtype = dptr_attr(sconn, dptr_num);
2020 mask_contains_wcard = dptr_has_wild(fsp->dptr);
2022 DEBUG(4,("dptr_num is %d\n",dptr_num));
2024 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
2025 char buf[DIR_STRUCT_SIZE];
2026 memcpy(buf,status,21);
2027 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
2028 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
2029 reply_nterror(req, NT_STATUS_NO_MEMORY);
2032 dptr_fill(sconn, buf+12,dptr_num);
2033 if (dptr_zero(buf+12) && (status_len==0)) {
2038 if (message_push_blob(&req->outbuf,
2039 data_blob_const(buf, sizeof(buf)))
2041 reply_nterror(req, NT_STATUS_NO_MEMORY);
2046 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
2047 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
2049 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
2051 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2052 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
2053 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
2054 check_descend = True;
2057 for (i=numentries;(i<maxentries) && !finished;i++) {
2058 finished = !get_dir_entry(ctx,
2069 char buf[DIR_STRUCT_SIZE];
2070 memcpy(buf,status,21);
2071 if (!make_dir_struct(ctx,
2077 convert_timespec_to_time_t(date),
2078 !allow_long_path_components)) {
2079 reply_nterror(req, NT_STATUS_NO_MEMORY);
2082 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2085 if (message_push_blob(&req->outbuf,
2086 data_blob_const(buf, sizeof(buf)))
2088 reply_nterror(req, NT_STATUS_NO_MEMORY);
2098 /* If we were called as SMBffirst with smb_search_id == NULL
2099 and no entries were found then return error and close fsp->dptr
2102 if (numentries == 0) {
2105 close_file(NULL, fsp, NORMAL_CLOSE);
2108 } else if(expect_close && status_len == 0) {
2109 /* Close the dptr - we know it's gone */
2112 close_file(NULL, fsp, NORMAL_CLOSE);
2117 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2118 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2120 /* fsp may have been closed above. */
2122 close_file(NULL, fsp, NORMAL_CLOSE);
2127 if ((numentries == 0) && !mask_contains_wcard) {
2128 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2132 SSVAL(req->outbuf,smb_vwv0,numentries);
2133 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2134 SCVAL(smb_buf(req->outbuf),0,5);
2135 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2137 /* The replies here are never long name. */
2138 SSVAL(req->outbuf, smb_flg2,
2139 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2140 if (!allow_long_path_components) {
2141 SSVAL(req->outbuf, smb_flg2,
2142 SVAL(req->outbuf, smb_flg2)
2143 & (~FLAGS2_LONG_PATH_COMPONENTS));
2146 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2147 SSVAL(req->outbuf, smb_flg2,
2148 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2150 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2151 smb_fn_name(req->cmd),
2158 TALLOC_FREE(directory);
2160 TALLOC_FREE(smb_fname);
2161 END_PROFILE(SMBsearch);
2165 /****************************************************************************
2166 Reply to a fclose (stop directory search).
2167 ****************************************************************************/
2169 void reply_fclose(struct smb_request *req)
2177 bool path_contains_wcard = False;
2178 TALLOC_CTX *ctx = talloc_tos();
2179 struct smbd_server_connection *sconn = req->sconn;
2180 files_struct *fsp = NULL;
2182 START_PROFILE(SMBfclose);
2184 if (req->posix_pathnames) {
2185 reply_unknown_new(req, req->cmd);
2186 END_PROFILE(SMBfclose);
2190 p = (const char *)req->buf + 1;
2191 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2192 &err, &path_contains_wcard);
2193 if (!NT_STATUS_IS_OK(err)) {
2194 reply_nterror(req, err);
2195 END_PROFILE(SMBfclose);
2199 if (smbreq_bufrem(req, p) < 3) {
2200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2201 END_PROFILE(SMBfclose);
2206 status_len = SVAL(p,0);
2209 if (status_len == 0) {
2210 reply_force_doserror(req, ERRSRV, ERRsrverror);
2211 END_PROFILE(SMBfclose);
2215 if (smbreq_bufrem(req, p) < 21) {
2216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2217 END_PROFILE(SMBfclose);
2221 memcpy(status,p,21);
2223 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2225 /* Close the file - we know it's gone */
2226 close_file(NULL, fsp, NORMAL_CLOSE);
2231 reply_outbuf(req, 1, 0);
2232 SSVAL(req->outbuf,smb_vwv0,0);
2234 DEBUG(3,("search close\n"));
2236 END_PROFILE(SMBfclose);
2240 /****************************************************************************
2242 ****************************************************************************/
2244 void reply_open(struct smb_request *req)
2246 connection_struct *conn = req->conn;
2247 struct smb_filename *smb_fname = NULL;
2257 uint32_t access_mask;
2258 uint32_t share_mode;
2259 uint32_t create_disposition;
2260 uint32_t create_options = 0;
2261 uint32_t private_flags = 0;
2264 TALLOC_CTX *ctx = talloc_tos();
2266 START_PROFILE(SMBopen);
2269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2273 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2274 deny_mode = SVAL(req->vwv+0, 0);
2275 dos_attr = SVAL(req->vwv+1, 0);
2277 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2278 STR_TERMINATE, &status);
2279 if (!NT_STATUS_IS_OK(status)) {
2280 reply_nterror(req, status);
2284 if (!map_open_params_to_ntcreate(fname, deny_mode,
2285 OPENX_FILE_EXISTS_OPEN, &access_mask,
2286 &share_mode, &create_disposition,
2287 &create_options, &private_flags)) {
2288 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2292 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2294 status = filename_convert(ctx,
2301 if (!NT_STATUS_IS_OK(status)) {
2302 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2303 reply_botherror(req,
2304 NT_STATUS_PATH_NOT_COVERED,
2305 ERRSRV, ERRbadpath);
2308 reply_nterror(req, status);
2312 status = SMB_VFS_CREATE_FILE(
2315 &conn->cwd_fsp, /* dirfsp */
2316 smb_fname, /* fname */
2317 access_mask, /* access_mask */
2318 share_mode, /* share_access */
2319 create_disposition, /* create_disposition*/
2320 create_options, /* create_options */
2321 dos_attr, /* file_attributes */
2322 oplock_request, /* oplock_request */
2324 0, /* allocation_size */
2330 NULL, NULL); /* create context */
2332 if (!NT_STATUS_IS_OK(status)) {
2333 if (open_was_deferred(req->xconn, req->mid)) {
2334 /* We have re-scheduled this call. */
2338 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2339 reply_openerror(req, status);
2343 fsp = fcb_or_dos_open(
2350 bool ok = defer_smb1_sharing_violation(req);
2354 reply_openerror(req, status);
2359 /* Ensure we're pointing at the correct stat struct. */
2360 TALLOC_FREE(smb_fname);
2361 smb_fname = fsp->fsp_name;
2363 size = smb_fname->st.st_ex_size;
2364 fattr = dos_mode(conn, smb_fname);
2366 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2368 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2369 DEBUG(3,("attempt to open a directory %s\n",
2371 close_file(req, fsp, ERROR_CLOSE);
2372 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2373 ERRDOS, ERRnoaccess);
2377 reply_outbuf(req, 7, 0);
2378 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2379 SSVAL(req->outbuf,smb_vwv1,fattr);
2380 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2381 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2383 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2385 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2386 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2388 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2389 SCVAL(req->outbuf,smb_flg,
2390 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2393 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2394 SCVAL(req->outbuf,smb_flg,
2395 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2398 END_PROFILE(SMBopen);
2402 /****************************************************************************
2403 Reply to an open and X.
2404 ****************************************************************************/
2406 void reply_open_and_X(struct smb_request *req)
2408 connection_struct *conn = req->conn;
2409 struct smb_filename *smb_fname = NULL;
2411 uint16_t open_flags;
2414 /* Breakout the oplock request bits so we can set the
2415 reply bits separately. */
2416 int ex_oplock_request;
2417 int core_oplock_request;
2420 int smb_sattr = SVAL(req->vwv+4, 0);
2421 uint32_t smb_time = make_unix_date3(req->vwv+6);
2429 uint64_t allocation_size;
2430 ssize_t retval = -1;
2431 uint32_t access_mask;
2432 uint32_t share_mode;
2433 uint32_t create_disposition;
2434 uint32_t create_options = 0;
2435 uint32_t private_flags = 0;
2437 TALLOC_CTX *ctx = talloc_tos();
2439 START_PROFILE(SMBopenX);
2441 if (req->wct < 15) {
2442 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2446 open_flags = SVAL(req->vwv+2, 0);
2447 deny_mode = SVAL(req->vwv+3, 0);
2448 smb_attr = SVAL(req->vwv+5, 0);
2449 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2450 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2451 oplock_request = ex_oplock_request | core_oplock_request;
2452 smb_ofun = SVAL(req->vwv+8, 0);
2453 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2455 /* If it's an IPC, pass off the pipe handler. */
2457 if (lp_nt_pipe_support()) {
2458 reply_open_pipe_and_X(conn, req);
2460 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2465 /* XXXX we need to handle passed times, sattr and flags */
2466 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2467 STR_TERMINATE, &status);
2468 if (!NT_STATUS_IS_OK(status)) {
2469 reply_nterror(req, status);
2473 if (!map_open_params_to_ntcreate(fname, deny_mode,
2475 &access_mask, &share_mode,
2476 &create_disposition,
2479 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2483 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2485 status = filename_convert(ctx,
2492 if (!NT_STATUS_IS_OK(status)) {
2493 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2494 reply_botherror(req,
2495 NT_STATUS_PATH_NOT_COVERED,
2496 ERRSRV, ERRbadpath);
2499 reply_nterror(req, status);
2503 status = SMB_VFS_CREATE_FILE(
2506 &conn->cwd_fsp, /* dirfsp */
2507 smb_fname, /* fname */
2508 access_mask, /* access_mask */
2509 share_mode, /* share_access */
2510 create_disposition, /* create_disposition*/
2511 create_options, /* create_options */
2512 smb_attr, /* file_attributes */
2513 oplock_request, /* oplock_request */
2515 0, /* allocation_size */
2520 &smb_action, /* pinfo */
2521 NULL, NULL); /* create context */
2523 if (!NT_STATUS_IS_OK(status)) {
2524 if (open_was_deferred(req->xconn, req->mid)) {
2525 /* We have re-scheduled this call. */
2529 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2530 reply_openerror(req, status);
2534 fsp = fcb_or_dos_open(
2541 bool ok = defer_smb1_sharing_violation(req);
2545 reply_openerror(req, status);
2550 smb_action = FILE_WAS_OPENED;
2553 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2554 if the file is truncated or created. */
2555 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2556 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2557 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2558 close_file(req, fsp, ERROR_CLOSE);
2559 reply_nterror(req, NT_STATUS_DISK_FULL);
2562 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2564 close_file(req, fsp, ERROR_CLOSE);
2565 reply_nterror(req, NT_STATUS_DISK_FULL);
2568 status = vfs_stat_fsp(fsp);
2569 if (!NT_STATUS_IS_OK(status)) {
2570 close_file(req, fsp, ERROR_CLOSE);
2571 reply_nterror(req, status);
2576 fattr = dos_mode(conn, fsp->fsp_name);
2577 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2578 close_file(req, fsp, ERROR_CLOSE);
2579 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2582 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2584 /* If the caller set the extended oplock request bit
2585 and we granted one (by whatever means) - set the
2586 correct bit for extended oplock reply.
2589 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2590 smb_action |= EXTENDED_OPLOCK_GRANTED;
2593 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2594 smb_action |= EXTENDED_OPLOCK_GRANTED;
2597 /* If the caller set the core oplock request bit
2598 and we granted one (by whatever means) - set the
2599 correct bit for core oplock reply.
2602 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2603 reply_outbuf(req, 19, 0);
2605 reply_outbuf(req, 15, 0);
2608 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2609 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2611 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2612 SCVAL(req->outbuf, smb_flg,
2613 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2616 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2617 SCVAL(req->outbuf, smb_flg,
2618 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2621 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2622 SSVAL(req->outbuf,smb_vwv3,fattr);
2623 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2624 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2626 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2628 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2629 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2630 SSVAL(req->outbuf,smb_vwv11,smb_action);
2632 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2633 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2637 TALLOC_FREE(smb_fname);
2638 END_PROFILE(SMBopenX);
2642 /****************************************************************************
2643 Reply to a SMBulogoffX.
2644 ****************************************************************************/
2646 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2647 struct smbXsrv_session *session);
2648 static void reply_ulogoffX_done(struct tevent_req *req);
2650 void reply_ulogoffX(struct smb_request *smb1req)
2652 struct timeval now = timeval_current();
2653 struct smbXsrv_session *session = NULL;
2654 struct tevent_req *req;
2658 * Don't setup the profile charge here, take
2659 * it in reply_ulogoffX_done(). Not strictly correct
2660 * but better than the other SMB1 async
2661 * code that double-charges at the moment.
2664 status = smb1srv_session_lookup(smb1req->xconn,
2666 timeval_to_nttime(&now),
2668 if (!NT_STATUS_IS_OK(status)) {
2669 /* Not going async, profile here. */
2670 START_PROFILE(SMBulogoffX);
2671 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2672 (unsigned long long)smb1req->vuid);
2674 smb1req->vuid = UID_FIELD_INVALID;
2675 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2676 END_PROFILE(SMBulogoffX);
2680 req = reply_ulogoffX_send(smb1req, session);
2682 /* Not going async, profile here. */
2683 START_PROFILE(SMBulogoffX);
2684 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2685 END_PROFILE(SMBulogoffX);
2689 /* We're async. This will complete later. */
2690 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2694 struct reply_ulogoffX_state {
2695 struct tevent_queue *wait_queue;
2696 struct smbXsrv_session *session;
2699 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2701 /****************************************************************************
2702 Async SMB1 ulogoffX.
2703 Note, on failure here we deallocate and return NULL to allow the caller to
2704 SMB1 return an error of ERRnomem immediately.
2705 ****************************************************************************/
2707 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2708 struct smbXsrv_session *session)
2710 struct tevent_req *req;
2711 struct reply_ulogoffX_state *state;
2712 struct tevent_req *subreq;
2714 struct smbd_server_connection *sconn = session->client->sconn;
2715 uint64_t vuid = session->global->session_wire_id;
2717 req = tevent_req_create(smb1req, &state,
2718 struct reply_ulogoffX_state);
2722 state->wait_queue = tevent_queue_create(state,
2723 "reply_ulogoffX_wait_queue");
2724 if (tevent_req_nomem(state->wait_queue, req)) {
2728 state->session = session;
2731 * Make sure that no new request will be able to use this session.
2732 * This ensures that once all outstanding fsp->aio_requests
2733 * on this session are done, we are safe to close it.
2735 session->status = NT_STATUS_USER_SESSION_DELETED;
2737 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2738 if (fsp->vuid != vuid) {
2742 * Flag the file as close in progress.
2743 * This will prevent any more IO being
2746 fsp->fsp_flags.closing = true;
2748 if (fsp->num_aio_requests > 0) {
2750 * Now wait until all aio requests on this fsp are
2753 * We don't set a callback, as we just want to block the
2754 * wait queue and the talloc_free() of fsp->aio_request
2755 * will remove the item from the wait queue.
2757 subreq = tevent_queue_wait_send(fsp->aio_requests,
2760 if (tevent_req_nomem(subreq, req)) {
2768 * Now we add our own waiter to the end of the queue,
2769 * this way we get notified when all pending requests are finished
2770 * and reply to the outstanding SMB1 request.
2772 subreq = tevent_queue_wait_send(state,
2775 if (tevent_req_nomem(subreq, req)) {
2781 * We're really going async - move the SMB1 request from
2782 * a talloc stackframe above us to the sconn talloc-context.
2783 * We need this to stick around until the wait_done
2784 * callback is invoked.
2786 smb1req = talloc_move(sconn, &smb1req);
2788 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2793 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2795 struct tevent_req *req = tevent_req_callback_data(
2796 subreq, struct tevent_req);
2798 tevent_queue_wait_recv(subreq);
2799 TALLOC_FREE(subreq);
2800 tevent_req_done(req);
2803 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2805 return tevent_req_simple_recv_ntstatus(req);
2808 static void reply_ulogoffX_done(struct tevent_req *req)
2810 struct smb_request *smb1req = tevent_req_callback_data(
2811 req, struct smb_request);
2812 struct reply_ulogoffX_state *state = tevent_req_data(req,
2813 struct reply_ulogoffX_state);
2814 struct smbXsrv_session *session = state->session;
2818 * Take the profile charge here. Not strictly
2819 * correct but better than the other SMB1 async
2820 * code that double-charges at the moment.
2822 START_PROFILE(SMBulogoffX);
2824 status = reply_ulogoffX_recv(req);
2826 if (!NT_STATUS_IS_OK(status)) {
2827 TALLOC_FREE(smb1req);
2828 END_PROFILE(SMBulogoffX);
2829 exit_server(__location__ ": reply_ulogoffX_recv failed");
2833 status = smbXsrv_session_logoff(session);
2834 if (!NT_STATUS_IS_OK(status)) {
2835 TALLOC_FREE(smb1req);
2836 END_PROFILE(SMBulogoffX);
2837 exit_server(__location__ ": smbXsrv_session_logoff failed");
2841 TALLOC_FREE(session);
2843 reply_outbuf(smb1req, 2, 0);
2844 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2845 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2847 DBG_NOTICE("ulogoffX vuid=%llu\n",
2848 (unsigned long long)smb1req->vuid);
2850 smb1req->vuid = UID_FIELD_INVALID;
2852 * The following call is needed to push the
2853 * reply data back out the socket after async
2854 * return. Plus it frees smb1req.
2856 smb_request_done(smb1req);
2857 END_PROFILE(SMBulogoffX);
2860 /****************************************************************************
2861 Reply to a mknew or a create.
2862 ****************************************************************************/
2864 void reply_mknew(struct smb_request *req)
2866 connection_struct *conn = req->conn;
2867 struct smb_filename *smb_fname = NULL;
2870 struct smb_file_time ft;
2872 int oplock_request = 0;
2874 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2875 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2876 uint32_t create_disposition;
2877 uint32_t create_options = 0;
2879 TALLOC_CTX *ctx = talloc_tos();
2881 START_PROFILE(SMBcreate);
2882 init_smb_file_time(&ft);
2885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2889 fattr = SVAL(req->vwv+0, 0);
2890 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2892 if (req->cmd == SMBmknew) {
2893 /* We should fail if file exists. */
2894 create_disposition = FILE_CREATE;
2896 /* Create if file doesn't exist, truncate if it does. */
2897 create_disposition = FILE_OVERWRITE_IF;
2901 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2903 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2904 STR_TERMINATE, &status);
2905 if (!NT_STATUS_IS_OK(status)) {
2906 reply_nterror(req, status);
2910 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2911 status = filename_convert(ctx,
2918 if (!NT_STATUS_IS_OK(status)) {
2919 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2920 reply_botherror(req,
2921 NT_STATUS_PATH_NOT_COVERED,
2922 ERRSRV, ERRbadpath);
2925 reply_nterror(req, status);
2929 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2930 DEBUG(0,("Attempt to create file (%s) with volid set - "
2931 "please report this\n",
2932 smb_fname_str_dbg(smb_fname)));
2935 status = SMB_VFS_CREATE_FILE(
2938 &conn->cwd_fsp, /* dirfsp */
2939 smb_fname, /* fname */
2940 access_mask, /* access_mask */
2941 share_mode, /* share_access */
2942 create_disposition, /* create_disposition*/
2943 create_options, /* create_options */
2944 fattr, /* file_attributes */
2945 oplock_request, /* oplock_request */
2947 0, /* allocation_size */
2948 0, /* private_flags */
2953 NULL, NULL); /* create context */
2955 if (!NT_STATUS_IS_OK(status)) {
2956 if (open_was_deferred(req->xconn, req->mid)) {
2957 /* We have re-scheduled this call. */
2960 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2961 bool ok = defer_smb1_sharing_violation(req);
2966 reply_openerror(req, status);
2970 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2971 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2972 if (!NT_STATUS_IS_OK(status)) {
2973 END_PROFILE(SMBcreate);
2977 reply_outbuf(req, 1, 0);
2978 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2980 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2981 SCVAL(req->outbuf,smb_flg,
2982 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2985 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2986 SCVAL(req->outbuf,smb_flg,
2987 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2990 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2991 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2992 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2993 (unsigned int)fattr));
2996 TALLOC_FREE(smb_fname);
2997 END_PROFILE(SMBcreate);
3001 /****************************************************************************
3002 Reply to a create temporary file.
3003 ****************************************************************************/
3005 void reply_ctemp(struct smb_request *req)
3007 connection_struct *conn = req->conn;
3008 struct smb_filename *smb_fname = NULL;
3009 char *wire_name = NULL;
3018 TALLOC_CTX *ctx = talloc_tos();
3020 START_PROFILE(SMBctemp);
3023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3027 fattr = SVAL(req->vwv+0, 0);
3028 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
3030 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
3031 STR_TERMINATE, &status);
3032 if (!NT_STATUS_IS_OK(status)) {
3033 reply_nterror(req, status);
3037 for (i = 0; i < 10; i++) {
3039 fname = talloc_asprintf(ctx,
3042 generate_random_str_list(ctx, 5, "0123456789"));
3044 fname = talloc_asprintf(ctx,
3046 generate_random_str_list(ctx, 5, "0123456789"));
3050 reply_nterror(req, NT_STATUS_NO_MEMORY);
3054 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
3055 status = filename_convert(ctx, conn,
3061 if (!NT_STATUS_IS_OK(status)) {
3062 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3063 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3064 ERRSRV, ERRbadpath);
3067 reply_nterror(req, status);
3071 /* Create the file. */
3072 status = SMB_VFS_CREATE_FILE(
3075 &conn->cwd_fsp, /* dirfsp */
3076 smb_fname, /* fname */
3077 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
3078 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
3079 FILE_CREATE, /* create_disposition*/
3080 0, /* create_options */
3081 fattr, /* file_attributes */
3082 oplock_request, /* oplock_request */
3084 0, /* allocation_size */
3085 0, /* private_flags */
3090 NULL, NULL); /* create context */
3092 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3094 TALLOC_FREE(smb_fname);
3098 if (!NT_STATUS_IS_OK(status)) {
3099 if (open_was_deferred(req->xconn, req->mid)) {
3100 /* We have re-scheduled this call. */
3103 if (NT_STATUS_EQUAL(
3104 status, NT_STATUS_SHARING_VIOLATION)) {
3105 bool ok = defer_smb1_sharing_violation(req);
3110 reply_openerror(req, status);
3118 /* Collision after 10 times... */
3119 reply_nterror(req, status);
3123 reply_outbuf(req, 1, 0);
3124 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3126 /* the returned filename is relative to the directory */
3127 s = strrchr_m(fsp->fsp_name->base_name, '/');
3129 s = fsp->fsp_name->base_name;
3135 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3136 thing in the byte section. JRA */
3137 SSVALS(p, 0, -1); /* what is this? not in spec */
3139 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3141 reply_nterror(req, NT_STATUS_NO_MEMORY);
3145 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3146 SCVAL(req->outbuf, smb_flg,
3147 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3150 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3151 SCVAL(req->outbuf, smb_flg,
3152 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3155 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3156 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3157 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
3159 TALLOC_FREE(smb_fname);
3160 TALLOC_FREE(wire_name);
3161 END_PROFILE(SMBctemp);
3165 /*******************************************************************
3166 Check if a user is allowed to rename a file.
3167 ********************************************************************/
3169 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3172 if (!CAN_WRITE(conn)) {
3173 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3176 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3177 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3178 /* Only bother to read the DOS attribute if we might deny the
3179 rename on the grounds of attribute mismatch. */
3180 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3181 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3182 return NT_STATUS_NO_SUCH_FILE;
3186 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3187 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3188 return NT_STATUS_OK;
3191 /* If no pathnames are open below this
3192 directory, allow the rename. */
3194 if (lp_strict_rename(SNUM(conn))) {
3196 * Strict rename, check open file db.
3198 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3199 return NT_STATUS_ACCESS_DENIED;
3201 } else if (file_find_subpath(fsp)) {
3203 * No strict rename, just look in local process.
3205 return NT_STATUS_ACCESS_DENIED;
3207 return NT_STATUS_OK;
3210 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3211 return NT_STATUS_OK;
3214 return NT_STATUS_ACCESS_DENIED;
3217 /*******************************************************************
3218 * unlink a file with all relevant access checks
3219 *******************************************************************/
3221 static NTSTATUS do_unlink(connection_struct *conn,
3222 struct smb_request *req,
3223 struct smb_filename *smb_fname,
3228 uint32_t dirtype_orig = dirtype;
3231 bool posix_paths = (req != NULL && req->posix_pathnames);
3232 struct smb2_create_blobs *posx = NULL;
3234 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3235 smb_fname_str_dbg(smb_fname),
3238 if (!CAN_WRITE(conn)) {
3239 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3243 ret = SMB_VFS_LSTAT(conn, smb_fname);
3245 ret = SMB_VFS_STAT(conn, smb_fname);
3248 return map_nt_error_from_unix(errno);
3251 fattr = dos_mode(conn, smb_fname);
3253 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3254 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3257 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3259 return NT_STATUS_NO_SUCH_FILE;
3262 if (!dir_check_ftype(fattr, dirtype)) {
3263 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3264 return NT_STATUS_FILE_IS_A_DIRECTORY;
3266 return NT_STATUS_NO_SUCH_FILE;
3269 if (dirtype_orig & 0x8000) {
3270 /* These will never be set for POSIX. */
3271 return NT_STATUS_NO_SUCH_FILE;
3275 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3276 return NT_STATUS_FILE_IS_A_DIRECTORY;
3279 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3280 return NT_STATUS_NO_SUCH_FILE;
3283 if (dirtype & 0xFF00) {
3284 /* These will never be set for POSIX. */
3285 return NT_STATUS_NO_SUCH_FILE;
3290 return NT_STATUS_NO_SUCH_FILE;
3293 /* Can't delete a directory. */
3294 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3295 return NT_STATUS_FILE_IS_A_DIRECTORY;
3300 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3301 return NT_STATUS_OBJECT_NAME_INVALID;
3302 #endif /* JRATEST */
3305 status = make_smb2_posix_create_ctx(
3306 talloc_tos(), &posx, 0777);
3307 if (!NT_STATUS_IS_OK(status)) {
3308 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3314 /* On open checks the open itself will check the share mode, so
3315 don't do it here as we'll get it wrong. */
3317 status = SMB_VFS_CREATE_FILE
3320 &conn->cwd_fsp, /* dirfsp */
3321 smb_fname, /* fname */
3322 DELETE_ACCESS, /* access_mask */
3323 FILE_SHARE_NONE, /* share_access */
3324 FILE_OPEN, /* create_disposition*/
3325 FILE_NON_DIRECTORY_FILE, /* create_options */
3326 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3327 0, /* oplock_request */
3329 0, /* allocation_size */
3330 0, /* private_flags */
3335 posx, /* in_context_blobs */
3336 NULL); /* out_context_blobs */
3340 if (!NT_STATUS_IS_OK(status)) {
3341 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3342 nt_errstr(status)));
3346 status = can_set_delete_on_close(fsp, fattr);
3347 if (!NT_STATUS_IS_OK(status)) {
3348 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3350 smb_fname_str_dbg(smb_fname),
3351 nt_errstr(status)));
3352 close_file(req, fsp, NORMAL_CLOSE);
3356 /* The set is across all open files on this dev/inode pair. */
3357 if (!set_delete_on_close(fsp, True,
3358 conn->session_info->security_token,
3359 conn->session_info->unix_token)) {
3360 close_file(req, fsp, NORMAL_CLOSE);
3361 return NT_STATUS_ACCESS_DENIED;
3364 return close_file(req, fsp, NORMAL_CLOSE);
3367 /****************************************************************************
3368 The guts of the unlink command, split out so it may be called by the NT SMB
3370 ****************************************************************************/
3372 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3373 uint32_t dirtype, struct smb_filename *smb_fname,
3376 char *fname_dir = NULL;
3377 char *fname_mask = NULL;
3379 NTSTATUS status = NT_STATUS_OK;
3380 struct smb_filename *smb_fname_dir = NULL;
3381 TALLOC_CTX *ctx = talloc_tos();
3383 /* Split up the directory from the filename/mask. */
3384 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3385 &fname_dir, &fname_mask);
3386 if (!NT_STATUS_IS_OK(status)) {
3391 * We should only check the mangled cache
3392 * here if unix_convert failed. This means
3393 * that the path in 'mask' doesn't exist
3394 * on the file system and so we need to look
3395 * for a possible mangle. This patch from
3396 * Tine Smukavec <valentin.smukavec@hermes.si>.
3399 if (!VALID_STAT(smb_fname->st) &&
3400 mangle_is_mangled(fname_mask, conn->params)) {
3401 char *new_mask = NULL;
3402 mangle_lookup_name_from_8_3(ctx, fname_mask,
3403 &new_mask, conn->params);
3405 TALLOC_FREE(fname_mask);
3406 fname_mask = new_mask;
3413 * Only one file needs to be unlinked. Append the mask back
3414 * onto the directory.
3416 TALLOC_FREE(smb_fname->base_name);
3417 if (ISDOT(fname_dir)) {
3418 /* Ensure we use canonical names on open. */
3419 smb_fname->base_name = talloc_asprintf(smb_fname,
3423 smb_fname->base_name = talloc_asprintf(smb_fname,
3428 if (!smb_fname->base_name) {
3429 status = NT_STATUS_NO_MEMORY;
3433 dirtype = FILE_ATTRIBUTE_NORMAL;
3436 status = check_name(conn, smb_fname);
3437 if (!NT_STATUS_IS_OK(status)) {
3441 status = do_unlink(conn, req, smb_fname, dirtype);
3442 if (!NT_STATUS_IS_OK(status)) {
3448 struct smb_Dir *dir_hnd = NULL;
3450 const char *dname = NULL;
3451 char *talloced = NULL;
3453 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3454 status = NT_STATUS_OBJECT_NAME_INVALID;
3458 dirtype = FILE_ATTRIBUTE_NORMAL;
3461 if (strequal(fname_mask,"????????.???")) {
3462 TALLOC_FREE(fname_mask);
3463 fname_mask = talloc_strdup(ctx, "*");
3465 status = NT_STATUS_NO_MEMORY;
3470 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3476 if (smb_fname_dir == NULL) {
3477 status = NT_STATUS_NO_MEMORY;
3481 status = check_name(conn, smb_fname_dir);
3482 if (!NT_STATUS_IS_OK(status)) {
3486 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3488 if (dir_hnd == NULL) {
3489 status = map_nt_error_from_unix(errno);
3493 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3494 the pattern matches against the long name, otherwise the short name
3495 We don't implement this yet XXXX
3498 status = NT_STATUS_NO_SUCH_FILE;
3500 while ((dname = ReadDirName(dir_hnd, &offset,
3501 &smb_fname->st, &talloced))) {
3502 TALLOC_CTX *frame = talloc_stackframe();
3504 struct smb_filename *f = NULL;
3506 if (!is_visible_file(conn,
3512 TALLOC_FREE(talloced);
3516 /* Quick check for "." and ".." */
3517 if (ISDOT(dname) || ISDOTDOT(dname)) {
3519 TALLOC_FREE(talloced);
3523 if(!mask_match(dname, fname_mask,
3524 conn->case_sensitive)) {
3526 TALLOC_FREE(talloced);
3530 if (ISDOT(fname_dir)) {
3531 /* Ensure we use canonical names on open. */
3532 p = talloc_asprintf(smb_fname, "%s", dname);
3534 p = talloc_asprintf(smb_fname, "%s/%s",
3538 TALLOC_FREE(dir_hnd);
3539 status = NT_STATUS_NO_MEMORY;
3541 TALLOC_FREE(talloced);
3544 f = synthetic_smb_fname(frame,
3551 TALLOC_FREE(dir_hnd);
3552 status = NT_STATUS_NO_MEMORY;
3554 TALLOC_FREE(talloced);
3558 status = check_name(conn, f);
3559 if (!NT_STATUS_IS_OK(status)) {
3560 TALLOC_FREE(dir_hnd);
3562 TALLOC_FREE(talloced);
3566 status = do_unlink(conn, req, f, dirtype);
3567 if (!NT_STATUS_IS_OK(status)) {
3568 TALLOC_FREE(dir_hnd);
3570 TALLOC_FREE(talloced);
3575 DBG_DEBUG("successful unlink [%s]\n",
3576 smb_fname_str_dbg(f));
3579 TALLOC_FREE(talloced);
3581 TALLOC_FREE(dir_hnd);
3584 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3585 status = map_nt_error_from_unix(errno);
3589 TALLOC_FREE(smb_fname_dir);
3590 TALLOC_FREE(fname_dir);
3591 TALLOC_FREE(fname_mask);
3595 /****************************************************************************
3597 ****************************************************************************/
3599 void reply_unlink(struct smb_request *req)
3601 connection_struct *conn = req->conn;
3603 struct smb_filename *smb_fname = NULL;
3606 bool path_contains_wcard = False;
3607 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3608 ucf_flags_from_smb_request(req);
3609 TALLOC_CTX *ctx = talloc_tos();
3611 START_PROFILE(SMBunlink);
3614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3618 dirtype = SVAL(req->vwv+0, 0);
3620 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3621 STR_TERMINATE, &status,
3622 &path_contains_wcard);
3623 if (!NT_STATUS_IS_OK(status)) {
3624 reply_nterror(req, status);
3628 status = filename_convert(ctx, conn,
3632 &path_contains_wcard,
3634 if (!NT_STATUS_IS_OK(status)) {
3635 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3636 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3637 ERRSRV, ERRbadpath);
3640 reply_nterror(req, status);
3644 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3646 status = unlink_internals(conn, req, dirtype, smb_fname,
3647 path_contains_wcard);
3648 if (!NT_STATUS_IS_OK(status)) {
3649 if (open_was_deferred(req->xconn, req->mid)) {
3650 /* We have re-scheduled this call. */
3653 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3654 bool ok = defer_smb1_sharing_violation(req);
3659 reply_nterror(req, status);
3663 reply_outbuf(req, 0, 0);
3665 TALLOC_FREE(smb_fname);
3666 END_PROFILE(SMBunlink);
3670 /****************************************************************************
3672 ****************************************************************************/
3674 static void fail_readraw(void)
3676 const char *errstr = talloc_asprintf(talloc_tos(),
3677 "FAIL ! reply_readbraw: socket write fail (%s)",
3682 exit_server_cleanly(errstr);
3685 /****************************************************************************
3686 Fake (read/write) sendfile. Returns -1 on read or write fail.
3687 ****************************************************************************/
3689 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3690 off_t startpos, size_t nread)
3693 size_t tosend = nread;
3700 bufsize = MIN(nread, 65536);
3702 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3706 while (tosend > 0) {
3710 cur_read = MIN(tosend, bufsize);
3711 ret = read_file(fsp,buf,startpos,cur_read);
3717 /* If we had a short read, fill with zeros. */
3718 if (ret < cur_read) {
3719 memset(buf + ret, '\0', cur_read - ret);
3722 ret = write_data(xconn->transport.sock, buf, cur_read);
3723 if (ret != cur_read) {
3724 int saved_errno = errno;
3726 * Try and give an error message saying what
3729 DEBUG(0, ("write_data failed for client %s. "
3731 smbXsrv_connection_dbg(xconn),
3732 strerror(saved_errno)));
3734 errno = saved_errno;
3738 startpos += cur_read;
3742 return (ssize_t)nread;
3745 /****************************************************************************
3746 Deal with the case of sendfile reading less bytes from the file than
3747 requested. Fill with zeros (all we can do). Returns 0 on success
3748 ****************************************************************************/
3750 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3756 #define SHORT_SEND_BUFSIZE 1024
3757 if (nread < headersize) {
3758 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3759 "header for file %s (%s). Terminating\n",
3760 fsp_str_dbg(fsp), strerror(errno)));
3764 nread -= headersize;
3766 if (nread < smb_maxcnt) {
3767 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3769 DEBUG(0,("sendfile_short_send: malloc failed "
3770 "for file %s (%s). Terminating\n",
3771 fsp_str_dbg(fsp), strerror(errno)));
3775 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3776 "with zeros !\n", fsp_str_dbg(fsp)));
3778 while (nread < smb_maxcnt) {
3780 * We asked for the real file size and told sendfile
3781 * to not go beyond the end of the file. But it can
3782 * happen that in between our fstat call and the
3783 * sendfile call the file was truncated. This is very
3784 * bad because we have already announced the larger
3785 * number of bytes to the client.
3787 * The best we can do now is to send 0-bytes, just as
3788 * a read from a hole in a sparse file would do.
3790 * This should happen rarely enough that I don't care
3791 * about efficiency here :-)
3796 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3797 ret = write_data(xconn->transport.sock, buf, to_write);
3798 if (ret != to_write) {
3799 int saved_errno = errno;
3801 * Try and give an error message saying what
3804 DEBUG(0, ("write_data failed for client %s. "
3806 smbXsrv_connection_dbg(xconn),
3807 strerror(saved_errno)));
3808 errno = saved_errno;
3819 /****************************************************************************
3820 Return a readbraw error (4 bytes of zero).
3821 ****************************************************************************/
3823 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3829 smbd_lock_socket(xconn);
3830 if (write_data(xconn->transport.sock,header,4) != 4) {
3831 int saved_errno = errno;
3833 * Try and give an error message saying what
3836 DEBUG(0, ("write_data failed for client %s. "
3838 smbXsrv_connection_dbg(xconn),
3839 strerror(saved_errno)));
3840 errno = saved_errno;
3844 smbd_unlock_socket(xconn);
3847 /*******************************************************************
3848 Ensure we don't use sendfile if server smb signing is active.
3849 ********************************************************************/
3851 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3853 bool sign_active = false;
3855 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3856 if (get_Protocol() < PROTOCOL_NT1) {
3859 if (signing_state) {
3860 sign_active = smb_signing_is_active(signing_state);
3862 return (lp__use_sendfile(snum) &&
3863 (get_remote_arch() != RA_WIN95) &&
3866 /****************************************************************************
3867 Use sendfile in readbraw.
3868 ****************************************************************************/
3870 static void send_file_readbraw(connection_struct *conn,
3871 struct smb_request *req,
3877 struct smbXsrv_connection *xconn = req->xconn;
3878 char *outbuf = NULL;
3882 * We can only use sendfile on a non-chained packet
3883 * but we can use on a non-oplocked file. tridge proved this
3884 * on a train in Germany :-). JRA.
3885 * reply_readbraw has already checked the length.
3888 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3889 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3890 ssize_t sendfile_read = -1;
3892 DATA_BLOB header_blob;
3894 _smb_setlen(header,nread);
3895 header_blob = data_blob_const(header, 4);
3897 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3898 &header_blob, startpos,
3900 if (sendfile_read == -1) {
3901 /* Returning ENOSYS means no data at all was sent.
3902 * Do this as a normal read. */
3903 if (errno == ENOSYS) {
3904 goto normal_readbraw;
3908 * Special hack for broken Linux with no working sendfile. If we
3909 * return EINTR we sent the header but not the rest of the data.
3910 * Fake this up by doing read/write calls.
3912 if (errno == EINTR) {
3913 /* Ensure we don't do this again. */
3914 set_use_sendfile(SNUM(conn), False);
3915 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3917 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3918 DEBUG(0,("send_file_readbraw: "
3919 "fake_sendfile failed for "
3923 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3928 DEBUG(0,("send_file_readbraw: sendfile failed for "
3929 "file %s (%s). Terminating\n",
3930 fsp_str_dbg(fsp), strerror(errno)));
3931 exit_server_cleanly("send_file_readbraw sendfile failed");
3932 } else if (sendfile_read == 0) {
3934 * Some sendfile implementations return 0 to indicate
3935 * that there was a short read, but nothing was
3936 * actually written to the socket. In this case,
3937 * fallback to the normal read path so the header gets
3938 * the correct byte count.
3940 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3941 "bytes falling back to the normal read: "
3942 "%s\n", fsp_str_dbg(fsp)));
3943 goto normal_readbraw;
3946 /* Deal with possible short send. */
3947 if (sendfile_read != 4+nread) {
3948 ret = sendfile_short_send(xconn, fsp,
3949 sendfile_read, 4, nread);
3959 outbuf = talloc_array(NULL, char, nread+4);
3961 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3962 (unsigned)(nread+4)));
3963 reply_readbraw_error(xconn);
3968 ret = read_file(fsp,outbuf+4,startpos,nread);
3969 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3978 _smb_setlen(outbuf,ret);
3979 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3980 int saved_errno = errno;
3982 * Try and give an error message saying what
3985 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3986 smbXsrv_connection_dbg(xconn),
3987 strerror(saved_errno)));
3988 errno = saved_errno;
3993 TALLOC_FREE(outbuf);
3996 /****************************************************************************
3997 Reply to a readbraw (core+ protocol).
3998 ****************************************************************************/
4000 void reply_readbraw(struct smb_request *req)
4002 connection_struct *conn = req->conn;
4003 struct smbXsrv_connection *xconn = req->xconn;
4004 ssize_t maxcount,mincount;
4008 struct lock_struct lock;
4012 START_PROFILE(SMBreadbraw);
4014 if (srv_is_signing_active(xconn) || req->encrypted) {
4015 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
4016 "raw reads/writes are disallowed.");
4020 reply_readbraw_error(xconn);
4021 END_PROFILE(SMBreadbraw);
4025 if (xconn->smb1.echo_handler.trusted_fde) {
4026 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
4027 "'async smb echo handler = yes'\n"));
4028 reply_readbraw_error(xconn);
4029 END_PROFILE(SMBreadbraw);
4034 * Special check if an oplock break has been issued
4035 * and the readraw request croses on the wire, we must
4036 * return a zero length response here.
4039 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4042 * We have to do a check_fsp by hand here, as
4043 * we must always return 4 zero bytes on error,
4049 conn != fsp->conn ||
4050 req->vuid != fsp->vuid ||
4051 fsp->fsp_flags.is_directory ||
4055 * fsp could be NULL here so use the value from the packet. JRA.
4057 DEBUG(3,("reply_readbraw: fnum %d not valid "
4059 (int)SVAL(req->vwv+0, 0)));
4060 reply_readbraw_error(xconn);
4061 END_PROFILE(SMBreadbraw);
4065 /* Do a "by hand" version of CHECK_READ. */
4066 if (!(fsp->fsp_flags.can_read ||
4067 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
4068 (fsp->access_mask & FILE_EXECUTE)))) {
4069 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4070 (int)SVAL(req->vwv+0, 0)));
4071 reply_readbraw_error(xconn);
4072 END_PROFILE(SMBreadbraw);
4076 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
4077 if(req->wct == 10) {
4079 * This is a large offset (64 bit) read.
4082 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4085 DEBUG(0,("reply_readbraw: negative 64 bit "
4086 "readraw offset (%.0f) !\n",
4087 (double)startpos ));
4088 reply_readbraw_error(xconn);
4089 END_PROFILE(SMBreadbraw);
4094 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4095 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4097 /* ensure we don't overrun the packet size */
4098 maxcount = MIN(65535,maxcount);
4100 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4101 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4104 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4105 reply_readbraw_error(xconn);
4106 END_PROFILE(SMBreadbraw);
4110 status = vfs_stat_fsp(fsp);
4111 if (NT_STATUS_IS_OK(status)) {
4112 size = fsp->fsp_name->st.st_ex_size;
4115 if (startpos >= size) {
4118 nread = MIN(maxcount,(size - startpos));
4121 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4122 if (nread < mincount)
4126 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4127 "min=%lu nread=%lu\n",
4128 fsp_fnum_dbg(fsp), (double)startpos,
4129 (unsigned long)maxcount,
4130 (unsigned long)mincount,
4131 (unsigned long)nread ) );
4133 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4135 DEBUG(5,("reply_readbraw finished\n"));
4137 END_PROFILE(SMBreadbraw);
4142 #define DBGC_CLASS DBGC_LOCKING
4144 /****************************************************************************
4145 Reply to a lockread (core+ protocol).
4146 ****************************************************************************/
4148 static void reply_lockread_locked(struct tevent_req *subreq);
4150 void reply_lockread(struct smb_request *req)
4152 struct tevent_req *subreq = NULL;
4153 connection_struct *conn = req->conn;
4155 struct smbd_lock_element *lck = NULL;
4157 START_PROFILE(SMBlockread);
4160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4161 END_PROFILE(SMBlockread);
4165 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4167 if (!check_fsp(conn, req, fsp)) {
4168 END_PROFILE(SMBlockread);
4172 if (!CHECK_READ(fsp,req)) {
4173 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4174 END_PROFILE(SMBlockread);
4178 lck = talloc(req, struct smbd_lock_element);
4180 reply_nterror(req, NT_STATUS_NO_MEMORY);
4181 END_PROFILE(SMBlockread);
4186 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4187 * protocol request that predates the read/write lock concept.
4188 * Thus instead of asking for a read lock here we need to ask
4189 * for a write lock. JRA.
4190 * Note that the requested lock size is unaffected by max_send.
4193 *lck = (struct smbd_lock_element) {
4194 .req_guid = smbd_request_guid(req, 0),
4195 .smblctx = req->smbpid,
4196 .brltype = WRITE_LOCK,
4197 .count = SVAL(req->vwv+1, 0),
4198 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4201 subreq = smbd_smb1_do_locks_send(
4207 false, /* large_offset */
4211 if (subreq == NULL) {
4212 reply_nterror(req, NT_STATUS_NO_MEMORY);
4213 END_PROFILE(SMBlockread);
4216 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4217 END_PROFILE(SMBlockread);
4220 static void reply_lockread_locked(struct tevent_req *subreq)
4222 struct smb_request *req = NULL;
4228 size_t numtoread, maxtoread;
4229 struct files_struct *fsp = NULL;
4232 START_PROFILE(SMBlockread);
4234 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4237 status = smbd_smb1_do_locks_recv(subreq);
4238 TALLOC_FREE(subreq);
4240 if (!NT_STATUS_IS_OK(status)) {
4241 reply_nterror(req, status);
4245 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4247 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4251 numtoread = SVAL(req->vwv+1, 0);
4252 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4255 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4257 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4259 if (numtoread > maxtoread) {
4260 DBG_WARNING("requested read size (%zu) is greater than "
4261 "maximum allowed (%zu/%d). "
4262 "Returning short read of maximum allowed for "
4263 "compatibility with Windows 2000.\n",
4266 req->xconn->smb1.sessions.max_send);
4267 numtoread = maxtoread;
4270 reply_outbuf(req, 5, numtoread + 3);
4272 data = smb_buf(req->outbuf) + 3;
4274 nread = read_file(fsp,data,startpos,numtoread);
4277 reply_nterror(req, map_nt_error_from_unix(errno));
4281 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4283 SSVAL(req->outbuf,smb_vwv0,nread);
4284 SSVAL(req->outbuf,smb_vwv5,nread+3);
4285 p = smb_buf(req->outbuf);
4286 SCVAL(p,0,0); /* pad byte. */
4289 DEBUG(3,("lockread %s num=%d nread=%d\n",
4290 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4293 ok = srv_send_smb(req->xconn,
4294 (char *)req->outbuf,
4297 IS_CONN_ENCRYPTED(req->conn),
4300 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4303 END_PROFILE(SMBlockread);
4308 #define DBGC_CLASS DBGC_ALL
4310 /****************************************************************************
4312 ****************************************************************************/
4314 void reply_read(struct smb_request *req)
4316 connection_struct *conn = req->conn;
4323 struct lock_struct lock;
4324 struct smbXsrv_connection *xconn = req->xconn;
4326 START_PROFILE(SMBread);
4329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4330 END_PROFILE(SMBread);
4334 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4336 if (!check_fsp(conn, req, fsp)) {
4337 END_PROFILE(SMBread);
4341 if (!CHECK_READ(fsp,req)) {
4342 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4343 END_PROFILE(SMBread);
4347 numtoread = SVAL(req->vwv+1, 0);
4348 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4351 * The requested read size cannot be greater than max_send. JRA.
4353 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4355 if (numtoread > maxtoread) {
4356 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4357 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4358 (unsigned int)numtoread, (unsigned int)maxtoread,
4359 (unsigned int)xconn->smb1.sessions.max_send));
4360 numtoread = maxtoread;
4363 reply_outbuf(req, 5, numtoread+3);
4365 data = smb_buf(req->outbuf) + 3;
4367 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4368 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4371 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4372 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4373 END_PROFILE(SMBread);
4378 nread = read_file(fsp,data,startpos,numtoread);
4381 reply_nterror(req, map_nt_error_from_unix(errno));
4385 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4387 SSVAL(req->outbuf,smb_vwv0,nread);
4388 SSVAL(req->outbuf,smb_vwv5,nread+3);
4389 SCVAL(smb_buf(req->outbuf),0,1);
4390 SSVAL(smb_buf(req->outbuf),1,nread);
4392 DEBUG(3, ("read %s num=%d nread=%d\n",
4393 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4396 END_PROFILE(SMBread);
4400 /****************************************************************************
4402 ****************************************************************************/
4404 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4408 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4411 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4413 SCVAL(outbuf,smb_vwv0,0xFF);
4414 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4415 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4416 SSVAL(outbuf,smb_vwv6,
4417 (smb_wct - 4) /* offset from smb header to wct */
4418 + 1 /* the wct field */
4419 + 12 * sizeof(uint16_t) /* vwv */
4420 + 2 /* the buflen field */
4421 + 1); /* padding byte */
4422 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4423 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4424 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4425 _smb_setlen_large(outbuf,
4426 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4430 /****************************************************************************
4431 Reply to a read and X - possibly using sendfile.
4432 ****************************************************************************/
4434 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4435 files_struct *fsp, off_t startpos,
4438 struct smbXsrv_connection *xconn = req->xconn;
4440 struct lock_struct lock;
4441 int saved_errno = 0;
4444 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4445 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4448 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4449 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4454 * We can only use sendfile on a non-chained packet
4455 * but we can use on a non-oplocked file. tridge proved this
4456 * on a train in Germany :-). JRA.
4459 if (!req_is_in_chain(req) &&
4461 (fsp->base_fsp == NULL) &&
4462 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4463 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4466 status = vfs_stat_fsp(fsp);
4467 if (!NT_STATUS_IS_OK(status)) {
4468 reply_nterror(req, status);
4472 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4473 (startpos > fsp->fsp_name->st.st_ex_size) ||
4474 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4476 * We already know that we would do a short read, so don't
4477 * try the sendfile() path.
4479 goto nosendfile_read;
4483 * Set up the packet header before send. We
4484 * assume here the sendfile will work (get the
4485 * correct amount of data).
4488 header = data_blob_const(headerbuf, sizeof(headerbuf));
4490 construct_reply_common_req(req, (char *)headerbuf);
4491 setup_readX_header((char *)headerbuf, smb_maxcnt);
4493 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4494 startpos, smb_maxcnt);
4496 saved_errno = errno;
4498 /* Returning ENOSYS means no data at all was sent.
4499 Do this as a normal read. */
4500 if (errno == ENOSYS) {
4505 * Special hack for broken Linux with no working sendfile. If we
4506 * return EINTR we sent the header but not the rest of the data.
4507 * Fake this up by doing read/write calls.
4510 if (errno == EINTR) {
4511 /* Ensure we don't do this again. */
4512 set_use_sendfile(SNUM(conn), False);
4513 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4514 nread = fake_sendfile(xconn, fsp, startpos,
4517 saved_errno = errno;
4518 DEBUG(0,("send_file_readX: "
4519 "fake_sendfile failed for "
4520 "file %s (%s) for client %s. "
4523 smbXsrv_connection_dbg(xconn),
4524 strerror(saved_errno)));
4525 errno = saved_errno;
4526 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4528 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4529 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4530 /* No outbuf here means successful sendfile. */
4534 DEBUG(0,("send_file_readX: sendfile failed for file "
4535 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4537 exit_server_cleanly("send_file_readX sendfile failed");
4538 } else if (nread == 0) {
4540 * Some sendfile implementations return 0 to indicate
4541 * that there was a short read, but nothing was
4542 * actually written to the socket. In this case,
4543 * fallback to the normal read path so the header gets
4544 * the correct byte count.
4546 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4547 "falling back to the normal read: %s\n",
4552 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4553 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4555 /* Deal with possible short send. */
4556 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4559 ret = sendfile_short_send(xconn, fsp, nread,
4560 sizeof(headerbuf), smb_maxcnt);
4563 r = "send_file_readX: sendfile_short_send failed";
4564 DEBUG(0,("%s for file %s (%s).\n",
4565 r, fsp_str_dbg(fsp), strerror(errno)));
4566 exit_server_cleanly(r);
4569 /* No outbuf here means successful sendfile. */
4570 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4571 SMB_PERFCOUNT_END(&req->pcd);
4577 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4578 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4581 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4582 (startpos > fsp->fsp_name->st.st_ex_size) ||
4583 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4585 * We already know that we would do a short
4586 * read, so don't try the sendfile() path.
4588 goto nosendfile_read;
4591 construct_reply_common_req(req, (char *)headerbuf);
4592 setup_readX_header((char *)headerbuf, smb_maxcnt);
4594 /* Send out the header. */
4595 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4597 if (ret != sizeof(headerbuf)) {
4598 saved_errno = errno;
4600 * Try and give an error message saying what
4603 DEBUG(0,("send_file_readX: write_data failed for file "
4604 "%s (%s) for client %s. Terminating\n",
4606 smbXsrv_connection_dbg(xconn),
4607 strerror(saved_errno)));
4608 errno = saved_errno;
4609 exit_server_cleanly("send_file_readX sendfile failed");
4611 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4613 saved_errno = errno;
4614 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4615 "%s (%s) for client %s. Terminating\n",
4617 smbXsrv_connection_dbg(xconn),
4618 strerror(saved_errno)));
4619 errno = saved_errno;
4620 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4627 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4628 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4629 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4631 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4632 startpos, smb_maxcnt);
4633 saved_errno = errno;
4636 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4640 setup_readX_header((char *)req->outbuf, nread);
4642 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4643 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4647 TALLOC_FREE(req->outbuf);
4651 /****************************************************************************
4652 Work out how much space we have for a read return.
4653 ****************************************************************************/
4655 static size_t calc_max_read_pdu(const struct smb_request *req)
4657 struct smbXsrv_connection *xconn = req->xconn;
4659 if (xconn->protocol < PROTOCOL_NT1) {
4660 return xconn->smb1.sessions.max_send;
4663 if (!lp_large_readwrite()) {
4664 return xconn->smb1.sessions.max_send;
4667 if (req_is_in_chain(req)) {
4668 return xconn->smb1.sessions.max_send;
4671 if (req->encrypted) {
4673 * Don't take encrypted traffic up to the
4674 * limit. There are padding considerations
4675 * that make that tricky.
4677 return xconn->smb1.sessions.max_send;
4680 if (srv_is_signing_active(xconn)) {
4684 if (!lp_unix_extensions()) {
4689 * We can do ultra-large POSIX reads.
4694 /****************************************************************************
4695 Calculate how big a read can be. Copes with all clients. It's always
4696 safe to return a short read - Windows does this.
4697 ****************************************************************************/
4699 static size_t calc_read_size(const struct smb_request *req,
4703 struct smbXsrv_connection *xconn = req->xconn;
4704 size_t max_pdu = calc_max_read_pdu(req);
4705 size_t total_size = 0;
4706 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4707 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4710 * Windows explicitly ignores upper size of 0xFFFF.
4711 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4712 * We must do the same as these will never fit even in
4713 * an extended size NetBIOS packet.
4715 if (upper_size == 0xFFFF) {
4719 if (xconn->protocol < PROTOCOL_NT1) {
4723 total_size = ((upper_size<<16) | lower_size);
4726 * LARGE_READX test shows it's always safe to return
4727 * a short read. Windows does so.
4729 return MIN(total_size, max_len);
4732 /****************************************************************************
4733 Reply to a read and X.
4734 ****************************************************************************/
4736 void reply_read_and_X(struct smb_request *req)
4738 connection_struct *conn = req->conn;
4743 bool big_readX = False;
4745 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4748 START_PROFILE(SMBreadX);
4750 if ((req->wct != 10) && (req->wct != 12)) {
4751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4755 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4756 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4757 smb_maxcnt = SVAL(req->vwv+5, 0);
4759 /* If it's an IPC, pass off the pipe handler. */
4761 reply_pipe_read_and_X(req);
4762 END_PROFILE(SMBreadX);
4766 if (!check_fsp(conn, req, fsp)) {
4767 END_PROFILE(SMBreadX);
4771 if (!CHECK_READ(fsp,req)) {
4772 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4773 END_PROFILE(SMBreadX);
4777 upper_size = SVAL(req->vwv+7, 0);
4778 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4779 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4781 * This is a heuristic to avoid keeping large
4782 * outgoing buffers around over long-lived aio
4788 if (req->wct == 12) {
4790 * This is a large offset (64 bit) read.
4792 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4797 NTSTATUS status = schedule_aio_read_and_X(conn,
4802 if (NT_STATUS_IS_OK(status)) {
4803 /* Read scheduled - we're done. */
4806 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4807 /* Real error - report to client. */
4808 END_PROFILE(SMBreadX);
4809 reply_nterror(req, status);
4812 /* NT_STATUS_RETRY - fall back to sync read. */
4815 smbd_lock_socket(req->xconn);
4816 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4817 smbd_unlock_socket(req->xconn);
4820 END_PROFILE(SMBreadX);
4824 /****************************************************************************
4825 Error replies to writebraw must have smb_wct == 1. Fix this up.
4826 ****************************************************************************/
4828 void error_to_writebrawerr(struct smb_request *req)
4830 uint8_t *old_outbuf = req->outbuf;
4832 reply_outbuf(req, 1, 0);
4834 memcpy(req->outbuf, old_outbuf, smb_size);
4835 TALLOC_FREE(old_outbuf);
4838 /****************************************************************************
4839 Read 4 bytes of a smb packet and return the smb length of the packet.
4840 Store the result in the buffer. This version of the function will
4841 never return a session keepalive (length of zero).
4842 Timeout is in milliseconds.
4843 ****************************************************************************/
4845 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4848 uint8_t msgtype = NBSSkeepalive;
4850 while (msgtype == NBSSkeepalive) {
4853 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4855 if (!NT_STATUS_IS_OK(status)) {
4856 char addr[INET6_ADDRSTRLEN];
4857 /* Try and give an error message
4858 * saying what client failed. */
4859 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4860 "client %s read error = %s.\n",
4861 get_peer_addr(fd,addr,sizeof(addr)),
4862 nt_errstr(status)));
4866 msgtype = CVAL(inbuf, 0);
4869 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4870 (unsigned long)len));
4872 return NT_STATUS_OK;
4875 /****************************************************************************
4876 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4877 ****************************************************************************/
4879 void reply_writebraw(struct smb_request *req)
4881 connection_struct *conn = req->conn;
4882 struct smbXsrv_connection *xconn = req->xconn;
4885 ssize_t total_written=0;
4886 size_t numtowrite=0;
4889 const char *data=NULL;
4892 struct lock_struct lock;
4895 START_PROFILE(SMBwritebraw);
4898 * If we ever reply with an error, it must have the SMB command
4899 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4902 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4904 if (srv_is_signing_active(xconn)) {
4905 END_PROFILE(SMBwritebraw);
4906 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4907 "raw reads/writes are disallowed.");
4910 if (req->wct < 12) {
4911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4912 error_to_writebrawerr(req);
4913 END_PROFILE(SMBwritebraw);
4917 if (xconn->smb1.echo_handler.trusted_fde) {
4918 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4919 "'async smb echo handler = yes'\n"));
4920 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4921 error_to_writebrawerr(req);
4922 END_PROFILE(SMBwritebraw);
4926 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4927 if (!check_fsp(conn, req, fsp)) {
4928 error_to_writebrawerr(req);
4929 END_PROFILE(SMBwritebraw);
4933 if (!CHECK_WRITE(fsp)) {
4934 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4935 error_to_writebrawerr(req);
4936 END_PROFILE(SMBwritebraw);
4940 tcount = IVAL(req->vwv+1, 0);
4941 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4942 write_through = BITSETW(req->vwv+7,0);
4944 /* We have to deal with slightly different formats depending
4945 on whether we are using the core+ or lanman1.0 protocol */
4947 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4948 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4949 data = smb_buf_const(req->inbuf);
4951 numtowrite = SVAL(req->vwv+10, 0);
4952 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4955 /* Ensure we don't write bytes past the end of this packet. */
4957 * This already protects us against CVE-2017-12163.
4959 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4960 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4961 error_to_writebrawerr(req);
4962 END_PROFILE(SMBwritebraw);
4966 if (!fsp->print_file) {
4967 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4968 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4971 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4972 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4973 error_to_writebrawerr(req);
4974 END_PROFILE(SMBwritebraw);
4980 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4983 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4984 "wrote=%d sync=%d\n",
4985 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4986 (int)nwritten, (int)write_through));
4988 if (nwritten < (ssize_t)numtowrite) {
4989 reply_nterror(req, NT_STATUS_DISK_FULL);
4990 error_to_writebrawerr(req);
4994 total_written = nwritten;
4996 /* Allocate a buffer of 64k + length. */
4997 buf = talloc_array(NULL, char, 65540);
4999 reply_nterror(req, NT_STATUS_NO_MEMORY);
5000 error_to_writebrawerr(req);
5004 /* Return a SMBwritebraw message to the redirector to tell
5005 * it to send more bytes */
5007 memcpy(buf, req->inbuf, smb_size);
5008 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
5009 SCVAL(buf,smb_com,SMBwritebraw);
5010 SSVALS(buf,smb_vwv0,0xFFFF);
5012 if (!srv_send_smb(req->xconn,
5014 false, 0, /* no signing */
5015 IS_CONN_ENCRYPTED(conn),
5017 exit_server_cleanly("reply_writebraw: srv_send_smb "
5021 /* Now read the raw data into the buffer and write it */
5022 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
5024 if (!NT_STATUS_IS_OK(status)) {
5025 exit_server_cleanly("secondary writebraw failed");
5028 /* Set up outbuf to return the correct size */
5029 reply_outbuf(req, 1, 0);
5031 if (numtowrite != 0) {
5033 if (numtowrite > 0xFFFF) {
5034 DEBUG(0,("reply_writebraw: Oversize secondary write "
5035 "raw requested (%u). Terminating\n",
5036 (unsigned int)numtowrite ));
5037 exit_server_cleanly("secondary writebraw failed");
5040 if (tcount > nwritten+numtowrite) {
5041 DEBUG(3,("reply_writebraw: Client overestimated the "
5043 (int)tcount,(int)nwritten,(int)numtowrite));
5046 status = read_data_ntstatus(xconn->transport.sock, buf+4,
5049 if (!NT_STATUS_IS_OK(status)) {
5050 /* Try and give an error message
5051 * saying what client failed. */
5052 DEBUG(0, ("reply_writebraw: Oversize secondary write "
5053 "raw read failed (%s) for client %s. "
5054 "Terminating\n", nt_errstr(status),
5055 smbXsrv_connection_dbg(xconn)));
5056 exit_server_cleanly("secondary writebraw failed");
5060 * We are not vulnerable to CVE-2017-12163
5061 * here as we are guaranteed to have numtowrite
5062 * bytes available - we just read from the client.
5064 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
5065 if (nwritten == -1) {
5067 reply_nterror(req, map_nt_error_from_unix(errno));
5068 error_to_writebrawerr(req);
5072 if (nwritten < (ssize_t)numtowrite) {
5073 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5074 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5078 total_written += nwritten;
5083 SSVAL(req->outbuf,smb_vwv0,total_written);
5085 status = sync_file(conn, fsp, write_through);
5086 if (!NT_STATUS_IS_OK(status)) {
5087 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5088 fsp_str_dbg(fsp), nt_errstr(status)));
5089 reply_nterror(req, status);
5090 error_to_writebrawerr(req);
5094 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5096 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5097 (int)total_written));
5099 /* We won't return a status if write through is not selected - this
5100 * follows what WfWg does */
5101 END_PROFILE(SMBwritebraw);
5103 if (!write_through && total_written==tcount) {
5105 #if RABBIT_PELLET_FIX
5107 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5108 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5111 if (!send_keepalive(xconn->transport.sock)) {
5112 exit_server_cleanly("reply_writebraw: send of "
5113 "keepalive failed");
5116 TALLOC_FREE(req->outbuf);
5121 END_PROFILE(SMBwritebraw);
5126 #define DBGC_CLASS DBGC_LOCKING
5128 /****************************************************************************
5129 Reply to a writeunlock (core+).
5130 ****************************************************************************/
5132 void reply_writeunlock(struct smb_request *req)
5134 connection_struct *conn = req->conn;
5135 ssize_t nwritten = -1;
5140 NTSTATUS status = NT_STATUS_OK;
5142 struct lock_struct lock;
5143 int saved_errno = 0;
5145 START_PROFILE(SMBwriteunlock);
5148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5149 END_PROFILE(SMBwriteunlock);
5153 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5155 if (!check_fsp(conn, req, fsp)) {
5156 END_PROFILE(SMBwriteunlock);
5160 if (!CHECK_WRITE(fsp)) {
5161 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5162 END_PROFILE(SMBwriteunlock);
5166 numtowrite = SVAL(req->vwv+1, 0);
5167 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5168 data = (const char *)req->buf + 3;
5171 * Ensure client isn't asking us to write more than
5172 * they sent. CVE-2017-12163.
5174 remaining = smbreq_bufrem(req, data);
5175 if (numtowrite > remaining) {
5176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5177 END_PROFILE(SMBwriteunlock);
5181 if (!fsp->print_file && numtowrite > 0) {
5182 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5183 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5186 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5187 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5188 END_PROFILE(SMBwriteunlock);
5193 /* The special X/Open SMB protocol handling of
5194 zero length writes is *NOT* done for
5196 if(numtowrite == 0) {
5199 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5200 saved_errno = errno;
5203 status = sync_file(conn, fsp, False /* write through */);
5204 if (!NT_STATUS_IS_OK(status)) {
5205 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5206 fsp_str_dbg(fsp), nt_errstr(status)));
5207 reply_nterror(req, status);
5212 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5216 if((nwritten < numtowrite) && (numtowrite != 0)) {
5217 reply_nterror(req, NT_STATUS_DISK_FULL);
5221 if (numtowrite && !fsp->print_file) {
5222 struct smbd_lock_element l = {
5223 .req_guid = smbd_request_guid(req, 0),
5224 .smblctx = req->smbpid,
5225 .brltype = UNLOCK_LOCK,
5227 .count = numtowrite,
5229 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5230 if (NT_STATUS_V(status)) {
5231 reply_nterror(req, status);
5236 reply_outbuf(req, 1, 0);
5238 SSVAL(req->outbuf,smb_vwv0,nwritten);
5240 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5241 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5244 END_PROFILE(SMBwriteunlock);
5249 #define DBGC_CLASS DBGC_ALL
5251 /****************************************************************************
5253 ****************************************************************************/
5255 void reply_write(struct smb_request *req)
5257 connection_struct *conn = req->conn;
5260 ssize_t nwritten = -1;
5264 struct lock_struct lock;
5266 int saved_errno = 0;
5268 START_PROFILE(SMBwrite);
5271 END_PROFILE(SMBwrite);
5272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5276 /* If it's an IPC, pass off the pipe handler. */
5278 reply_pipe_write(req);
5279 END_PROFILE(SMBwrite);
5283 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5285 if (!check_fsp(conn, req, fsp)) {
5286 END_PROFILE(SMBwrite);
5290 if (!CHECK_WRITE(fsp)) {
5291 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5292 END_PROFILE(SMBwrite);
5296 numtowrite = SVAL(req->vwv+1, 0);
5297 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5298 data = (const char *)req->buf + 3;
5301 * Ensure client isn't asking us to write more than
5302 * they sent. CVE-2017-12163.
5304 remaining = smbreq_bufrem(req, data);
5305 if (numtowrite > remaining) {
5306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5307 END_PROFILE(SMBwrite);
5311 if (!fsp->print_file) {
5312 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5313 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5316 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5317 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5318 END_PROFILE(SMBwrite);
5324 * X/Open SMB protocol says that if smb_vwv1 is
5325 * zero then the file size should be extended or
5326 * truncated to the size given in smb_vwv[2-3].
5329 if(numtowrite == 0) {
5331 * This is actually an allocate call, and set EOF. JRA.
5333 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5335 reply_nterror(req, NT_STATUS_DISK_FULL);
5338 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5340 reply_nterror(req, NT_STATUS_DISK_FULL);
5343 trigger_write_time_update_immediate(fsp);
5345 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5348 status = sync_file(conn, fsp, False);
5349 if (!NT_STATUS_IS_OK(status)) {
5350 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5351 fsp_str_dbg(fsp), nt_errstr(status)));
5352 reply_nterror(req, status);
5357 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5361 if((nwritten == 0) && (numtowrite != 0)) {
5362 reply_nterror(req, NT_STATUS_DISK_FULL);
5366 reply_outbuf(req, 1, 0);
5368 SSVAL(req->outbuf,smb_vwv0,nwritten);
5370 if (nwritten < (ssize_t)numtowrite) {
5371 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5372 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5375 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5378 END_PROFILE(SMBwrite);
5382 /****************************************************************************
5383 Ensure a buffer is a valid writeX for recvfile purposes.
5384 ****************************************************************************/
5386 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5387 (2*14) + /* word count (including bcc) */ \
5390 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5391 const uint8_t *inbuf)
5394 unsigned int doff = 0;
5395 size_t len = smb_len_large(inbuf);
5397 struct smbXsrv_open *op = NULL;
5398 struct files_struct *fsp = NULL;
5401 if (is_encrypted_packet(inbuf)) {
5402 /* Can't do this on encrypted
5407 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5411 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5412 CVAL(inbuf,smb_wct) != 14) {
5413 DEBUG(10,("is_valid_writeX_buffer: chained or "
5414 "invalid word length.\n"));
5418 fnum = SVAL(inbuf, smb_vwv2);
5419 status = smb1srv_open_lookup(xconn,
5423 if (!NT_STATUS_IS_OK(status)) {
5424 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5429 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5432 if (fsp->conn == NULL) {
5433 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5437 if (IS_IPC(fsp->conn)) {
5438 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5441 if (IS_PRINT(fsp->conn)) {
5442 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5445 if (fsp->base_fsp != NULL) {
5446 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5449 doff = SVAL(inbuf,smb_vwv11);
5451 numtowrite = SVAL(inbuf,smb_vwv10);
5453 if (len > doff && len - doff > 0xFFFF) {
5454 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5457 if (numtowrite == 0) {
5458 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5462 /* Ensure the sizes match up. */
5463 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5464 /* no pad byte...old smbclient :-( */
5465 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5467 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5471 if (len - doff != numtowrite) {
5472 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5473 "len = %u, doff = %u, numtowrite = %u\n",
5476 (unsigned int)numtowrite ));
5480 DEBUG(10,("is_valid_writeX_buffer: true "
5481 "len = %u, doff = %u, numtowrite = %u\n",
5484 (unsigned int)numtowrite ));
5489 /****************************************************************************
5490 Reply to a write and X.
5491 ****************************************************************************/
5493 void reply_write_and_X(struct smb_request *req)
5495 connection_struct *conn = req->conn;
5496 struct smbXsrv_connection *xconn = req->xconn;
5498 struct lock_struct lock;
5503 unsigned int smb_doff;
5504 unsigned int smblen;
5507 int saved_errno = 0;
5509 START_PROFILE(SMBwriteX);
5511 if ((req->wct != 12) && (req->wct != 14)) {
5512 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5516 numtowrite = SVAL(req->vwv+10, 0);
5517 smb_doff = SVAL(req->vwv+11, 0);
5518 smblen = smb_len(req->inbuf);
5520 if (req->unread_bytes > 0xFFFF ||
5521 (smblen > smb_doff &&
5522 smblen - smb_doff > 0xFFFF)) {
5523 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5526 if (req->unread_bytes) {
5527 /* Can't do a recvfile write on IPC$ */
5529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5532 if (numtowrite != req->unread_bytes) {
5533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5538 * This already protects us against CVE-2017-12163.
5540 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5541 smb_doff + numtowrite > smblen) {
5542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5547 /* If it's an IPC, pass off the pipe handler. */
5549 if (req->unread_bytes) {
5550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5553 reply_pipe_write_and_X(req);
5557 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5558 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5559 write_through = BITSETW(req->vwv+7,0);
5561 if (!check_fsp(conn, req, fsp)) {
5565 if (!CHECK_WRITE(fsp)) {
5566 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5570 data = smb_base(req->inbuf) + smb_doff;
5572 if(req->wct == 14) {
5574 * This is a large offset (64 bit) write.
5576 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5580 /* X/Open SMB protocol says that, unlike SMBwrite
5581 if the length is zero then NO truncation is
5582 done, just a write of zero. To truncate a file,
5585 if(numtowrite == 0) {
5588 if (req->unread_bytes == 0) {
5589 status = schedule_aio_write_and_X(conn,
5596 if (NT_STATUS_IS_OK(status)) {
5597 /* write scheduled - we're done. */
5600 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5601 /* Real error - report to client. */
5602 reply_nterror(req, status);
5605 /* NT_STATUS_RETRY - fall through to sync write. */
5608 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5609 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5612 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5613 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5617 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5618 saved_errno = errno;
5622 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5626 if((nwritten == 0) && (numtowrite != 0)) {
5627 reply_nterror(req, NT_STATUS_DISK_FULL);
5631 reply_outbuf(req, 6, 0);
5632 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5633 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5634 SSVAL(req->outbuf,smb_vwv2,nwritten);
5635 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5637 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5638 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5640 status = sync_file(conn, fsp, write_through);
5641 if (!NT_STATUS_IS_OK(status)) {
5642 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5643 fsp_str_dbg(fsp), nt_errstr(status)));
5644 reply_nterror(req, status);
5648 END_PROFILE(SMBwriteX);
5652 if (req->unread_bytes) {
5653 /* writeX failed. drain socket. */
5654 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5655 req->unread_bytes) {
5656 smb_panic("failed to drain pending bytes");
5658 req->unread_bytes = 0;
5661 END_PROFILE(SMBwriteX);
5665 /****************************************************************************
5667 ****************************************************************************/
5669 void reply_lseek(struct smb_request *req)
5671 connection_struct *conn = req->conn;
5678 START_PROFILE(SMBlseek);
5681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5682 END_PROFILE(SMBlseek);
5686 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5688 if (!check_fsp(conn, req, fsp)) {
5692 mode = SVAL(req->vwv+1, 0) & 3;
5693 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5694 startpos = (off_t)IVALS(req->vwv+2, 0);
5703 res = fsp->fh->pos + startpos;
5714 if (umode == SEEK_END) {
5715 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5716 if(errno == EINVAL) {
5717 off_t current_pos = startpos;
5719 status = vfs_stat_fsp(fsp);
5720 if (!NT_STATUS_IS_OK(status)) {
5721 reply_nterror(req, status);
5722 END_PROFILE(SMBlseek);
5726 current_pos += fsp->fsp_name->st.st_ex_size;
5728 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5733 reply_nterror(req, map_nt_error_from_unix(errno));
5734 END_PROFILE(SMBlseek);
5741 reply_outbuf(req, 2, 0);
5742 SIVAL(req->outbuf,smb_vwv0,res);
5744 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5745 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5747 END_PROFILE(SMBlseek);
5751 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5754 connection_struct *conn = talloc_get_type_abort(
5755 private_data, connection_struct);
5757 if (conn != fsp->conn) {
5760 if (fsp->fh->fd == -1) {
5763 sync_file(conn, fsp, True /* write through */);
5765 if (fsp->fsp_flags.modified) {
5766 trigger_write_time_update_immediate(fsp);
5772 /****************************************************************************
5774 ****************************************************************************/
5776 void reply_flush(struct smb_request *req)
5778 connection_struct *conn = req->conn;
5782 START_PROFILE(SMBflush);
5785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5789 fnum = SVAL(req->vwv+0, 0);
5790 fsp = file_fsp(req, fnum);
5792 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5797 files_forall(req->sconn, file_sync_one_fn, conn);
5799 NTSTATUS status = sync_file(conn, fsp, True);
5800 if (!NT_STATUS_IS_OK(status)) {
5801 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5802 fsp_str_dbg(fsp), nt_errstr(status)));
5803 reply_nterror(req, status);
5804 END_PROFILE(SMBflush);
5807 if (fsp->fsp_flags.modified) {
5808 trigger_write_time_update_immediate(fsp);
5812 reply_outbuf(req, 0, 0);
5814 DEBUG(3,("flush\n"));
5815 END_PROFILE(SMBflush);
5819 /****************************************************************************
5821 conn POINTER CAN BE NULL HERE !
5822 ****************************************************************************/
5824 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5825 static void reply_exit_done(struct tevent_req *req);
5827 void reply_exit(struct smb_request *smb1req)
5829 struct tevent_req *req;
5832 * Don't setup the profile charge here, take
5833 * it in reply_exit_done(). Not strictly correct
5834 * but better than the other SMB1 async
5835 * code that double-charges at the moment.
5837 req = reply_exit_send(smb1req);
5839 /* Not going async, profile here. */
5840 START_PROFILE(SMBexit);
5841 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5842 END_PROFILE(SMBexit);
5846 /* We're async. This will complete later. */
5847 tevent_req_set_callback(req, reply_exit_done, smb1req);
5851 struct reply_exit_state {
5852 struct tevent_queue *wait_queue;
5855 static void reply_exit_wait_done(struct tevent_req *subreq);
5857 /****************************************************************************
5859 Note, on failure here we deallocate and return NULL to allow the caller to
5860 SMB1 return an error of ERRnomem immediately.
5861 ****************************************************************************/
5863 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5865 struct tevent_req *req;
5866 struct reply_exit_state *state;
5867 struct tevent_req *subreq;
5869 struct smbd_server_connection *sconn = smb1req->sconn;
5871 req = tevent_req_create(smb1req, &state,
5872 struct reply_exit_state);
5876 state->wait_queue = tevent_queue_create(state,
5877 "reply_exit_wait_queue");
5878 if (tevent_req_nomem(state->wait_queue, req)) {
5883 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5884 if (fsp->file_pid != smb1req->smbpid) {
5887 if (fsp->vuid != smb1req->vuid) {
5891 * Flag the file as close in progress.
5892 * This will prevent any more IO being
5895 fsp->fsp_flags.closing = true;
5897 if (fsp->num_aio_requests > 0) {
5899 * Now wait until all aio requests on this fsp are
5902 * We don't set a callback, as we just want to block the
5903 * wait queue and the talloc_free() of fsp->aio_request
5904 * will remove the item from the wait queue.
5906 subreq = tevent_queue_wait_send(fsp->aio_requests,
5909 if (tevent_req_nomem(subreq, req)) {
5917 * Now we add our own waiter to the end of the queue,
5918 * this way we get notified when all pending requests are finished
5919 * and reply to the outstanding SMB1 request.
5921 subreq = tevent_queue_wait_send(state,
5924 if (tevent_req_nomem(subreq, req)) {
5930 * We're really going async - move the SMB1 request from
5931 * a talloc stackframe above us to the conn talloc-context.
5932 * We need this to stick around until the wait_done
5933 * callback is invoked.
5935 smb1req = talloc_move(sconn, &smb1req);
5937 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5942 static void reply_exit_wait_done(struct tevent_req *subreq)
5944 struct tevent_req *req = tevent_req_callback_data(
5945 subreq, struct tevent_req);
5947 tevent_queue_wait_recv(subreq);
5948 TALLOC_FREE(subreq);
5949 tevent_req_done(req);
5952 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5954 return tevent_req_simple_recv_ntstatus(req);
5957 static void reply_exit_done(struct tevent_req *req)
5959 struct smb_request *smb1req = tevent_req_callback_data(
5960 req, struct smb_request);
5961 struct smbd_server_connection *sconn = smb1req->sconn;
5962 struct smbXsrv_connection *xconn = smb1req->xconn;
5963 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5964 struct smbXsrv_session *session = NULL;
5965 files_struct *fsp, *next;
5969 * Take the profile charge here. Not strictly
5970 * correct but better than the other SMB1 async
5971 * code that double-charges at the moment.
5973 START_PROFILE(SMBexit);
5975 status = reply_exit_recv(req);
5977 if (!NT_STATUS_IS_OK(status)) {
5978 TALLOC_FREE(smb1req);
5979 END_PROFILE(SMBexit);
5980 exit_server(__location__ ": reply_exit_recv failed");
5985 * Ensure the session is still valid.
5987 status = smb1srv_session_lookup(xconn,
5991 if (!NT_STATUS_IS_OK(status)) {
5992 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5993 smb_request_done(smb1req);
5994 END_PROFILE(SMBexit);
5998 * Ensure the vuid is still valid - no one
5999 * called reply_ulogoffX() in the meantime.
6000 * reply_exit() doesn't have AS_USER set, so
6001 * use set_current_user_info() directly.
6002 * This is the same logic as in switch_message().
6004 if (session->global->auth_session_info != NULL) {
6005 set_current_user_info(
6006 session->global->auth_session_info->unix_info->sanitized_username,
6007 session->global->auth_session_info->unix_info->unix_name,
6008 session->global->auth_session_info->info->domain_name);
6011 /* No more aio - do the actual closes. */
6012 for (fsp = sconn->files; fsp; fsp = next) {
6016 if (fsp->file_pid != smb1req->smbpid) {
6019 if (fsp->vuid != smb1req->vuid) {
6022 if (!fsp->fsp_flags.closing) {
6027 * reply_exit() has the DO_CHDIR flag set.
6029 ok = chdir_current_service(fsp->conn);
6031 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6032 smb_request_done(smb1req);
6033 END_PROFILE(SMBexit);
6035 close_file(NULL, fsp, SHUTDOWN_CLOSE);
6038 reply_outbuf(smb1req, 0, 0);
6040 * The following call is needed to push the
6041 * reply data back out the socket after async
6042 * return. Plus it frees smb1req.
6044 smb_request_done(smb1req);
6045 DBG_INFO("reply_exit complete\n");
6046 END_PROFILE(SMBexit);
6050 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6052 static void reply_close_done(struct tevent_req *req);
6054 void reply_close(struct smb_request *smb1req)
6056 connection_struct *conn = smb1req->conn;
6057 NTSTATUS status = NT_STATUS_OK;
6058 files_struct *fsp = NULL;
6059 START_PROFILE(SMBclose);
6061 if (smb1req->wct < 3) {
6062 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
6063 END_PROFILE(SMBclose);
6067 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
6070 * We can only use check_fsp if we know it's not a directory.
6073 if (!check_fsp_open(conn, smb1req, fsp)) {
6074 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
6075 END_PROFILE(SMBclose);
6079 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6080 fsp->fsp_flags.is_directory ?
6081 "directory" : "file",
6082 fsp->fh->fd, fsp_fnum_dbg(fsp),
6083 conn->num_files_open);
6085 if (!fsp->fsp_flags.is_directory) {
6089 * Take care of any time sent in the close.
6092 t = srv_make_unix_date3(smb1req->vwv+1);
6093 set_close_write_time(fsp, time_t_to_full_timespec(t));
6096 if (fsp->num_aio_requests != 0) {
6097 struct tevent_req *req;
6099 req = reply_close_send(smb1req, fsp);
6101 status = NT_STATUS_NO_MEMORY;
6104 /* We're async. This will complete later. */
6105 tevent_req_set_callback(req, reply_close_done, smb1req);
6106 END_PROFILE(SMBclose);
6111 * close_file() returns the unix errno if an error was detected on
6112 * close - normally this is due to a disk full error. If not then it
6113 * was probably an I/O error.
6116 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6118 if (!NT_STATUS_IS_OK(status)) {
6119 reply_nterror(smb1req, status);
6120 END_PROFILE(SMBclose);
6124 reply_outbuf(smb1req, 0, 0);
6125 END_PROFILE(SMBclose);
6129 struct reply_close_state {
6131 struct tevent_queue *wait_queue;
6134 static void reply_close_wait_done(struct tevent_req *subreq);
6136 /****************************************************************************
6138 Note, on failure here we deallocate and return NULL to allow the caller to
6139 SMB1 return an error of ERRnomem immediately.
6140 ****************************************************************************/
6142 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6145 struct tevent_req *req;
6146 struct reply_close_state *state;
6147 struct tevent_req *subreq;
6148 struct smbd_server_connection *sconn = smb1req->sconn;
6150 req = tevent_req_create(smb1req, &state,
6151 struct reply_close_state);
6155 state->wait_queue = tevent_queue_create(state,
6156 "reply_close_wait_queue");
6157 if (tevent_req_nomem(state->wait_queue, req)) {
6163 * Flag the file as close in progress.
6164 * This will prevent any more IO being
6167 fsp->fsp_flags.closing = true;
6170 * Now wait until all aio requests on this fsp are
6173 * We don't set a callback, as we just want to block the
6174 * wait queue and the talloc_free() of fsp->aio_request
6175 * will remove the item from the wait queue.
6177 subreq = tevent_queue_wait_send(fsp->aio_requests,
6180 if (tevent_req_nomem(subreq, req)) {
6186 * Now we add our own waiter to the end of the queue,
6187 * this way we get notified when all pending requests are finished
6188 * and reply to the outstanding SMB1 request.
6190 subreq = tevent_queue_wait_send(state,
6193 if (tevent_req_nomem(subreq, req)) {
6199 * We're really going async - move the SMB1 request from
6200 * a talloc stackframe above us to the conn talloc-context.
6201 * We need this to stick around until the wait_done
6202 * callback is invoked.
6204 smb1req = talloc_move(sconn, &smb1req);
6206 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6211 static void reply_close_wait_done(struct tevent_req *subreq)
6213 struct tevent_req *req = tevent_req_callback_data(
6214 subreq, struct tevent_req);
6216 tevent_queue_wait_recv(subreq);
6217 TALLOC_FREE(subreq);
6218 tevent_req_done(req);
6221 static NTSTATUS reply_close_recv(struct tevent_req *req)
6223 return tevent_req_simple_recv_ntstatus(req);
6226 static void reply_close_done(struct tevent_req *req)
6228 struct smb_request *smb1req = tevent_req_callback_data(
6229 req, struct smb_request);
6230 struct reply_close_state *state = tevent_req_data(req,
6231 struct reply_close_state);
6234 status = reply_close_recv(req);
6236 if (!NT_STATUS_IS_OK(status)) {
6237 TALLOC_FREE(smb1req);
6238 exit_server(__location__ ": reply_close_recv failed");
6242 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6243 if (NT_STATUS_IS_OK(status)) {
6244 reply_outbuf(smb1req, 0, 0);
6246 reply_nterror(smb1req, status);
6249 * The following call is needed to push the
6250 * reply data back out the socket after async
6251 * return. Plus it frees smb1req.
6253 smb_request_done(smb1req);
6256 /****************************************************************************
6257 Reply to a writeclose (Core+ protocol).
6258 ****************************************************************************/
6260 void reply_writeclose(struct smb_request *req)
6262 connection_struct *conn = req->conn;
6265 ssize_t nwritten = -1;
6266 NTSTATUS close_status = NT_STATUS_OK;
6269 struct timespec mtime;
6271 struct lock_struct lock;
6273 START_PROFILE(SMBwriteclose);
6276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6277 END_PROFILE(SMBwriteclose);
6281 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6283 if (!check_fsp(conn, req, fsp)) {
6284 END_PROFILE(SMBwriteclose);
6287 if (!CHECK_WRITE(fsp)) {
6288 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6289 END_PROFILE(SMBwriteclose);
6293 numtowrite = SVAL(req->vwv+1, 0);
6294 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6295 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6296 data = (const char *)req->buf + 1;
6299 * Ensure client isn't asking us to write more than
6300 * they sent. CVE-2017-12163.
6302 remaining = smbreq_bufrem(req, data);
6303 if (numtowrite > remaining) {
6304 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6305 END_PROFILE(SMBwriteclose);
6309 if (fsp->print_file == NULL) {
6310 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6311 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6314 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6315 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6316 END_PROFILE(SMBwriteclose);
6321 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6323 set_close_write_time(fsp, mtime);
6326 * More insanity. W2K only closes the file if writelen > 0.
6330 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6331 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6332 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6335 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6336 "file %s\n", fsp_str_dbg(fsp)));
6337 close_status = close_file(req, fsp, NORMAL_CLOSE);
6341 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6342 reply_nterror(req, NT_STATUS_DISK_FULL);
6346 if(!NT_STATUS_IS_OK(close_status)) {
6347 reply_nterror(req, close_status);
6351 reply_outbuf(req, 1, 0);
6353 SSVAL(req->outbuf,smb_vwv0,nwritten);
6357 END_PROFILE(SMBwriteclose);
6362 #define DBGC_CLASS DBGC_LOCKING
6364 /****************************************************************************
6366 ****************************************************************************/
6368 static void reply_lock_done(struct tevent_req *subreq);
6370 void reply_lock(struct smb_request *req)
6372 struct tevent_req *subreq = NULL;
6373 connection_struct *conn = req->conn;
6375 struct smbd_lock_element *lck = NULL;
6377 START_PROFILE(SMBlock);
6380 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6381 END_PROFILE(SMBlock);
6385 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6387 if (!check_fsp(conn, req, fsp)) {
6388 END_PROFILE(SMBlock);
6392 lck = talloc(req, struct smbd_lock_element);
6394 reply_nterror(req, NT_STATUS_NO_MEMORY);
6395 END_PROFILE(SMBlock);
6399 *lck = (struct smbd_lock_element) {
6400 .req_guid = smbd_request_guid(req, 0),
6401 .smblctx = req->smbpid,
6402 .brltype = WRITE_LOCK,
6403 .count = IVAL(req->vwv+1, 0),
6404 .offset = IVAL(req->vwv+3, 0),
6407 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6413 subreq = smbd_smb1_do_locks_send(
6419 false, /* large_offset */
6423 if (subreq == NULL) {
6424 reply_nterror(req, NT_STATUS_NO_MEMORY);
6425 END_PROFILE(SMBlock);
6428 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6429 END_PROFILE(SMBlock);
6432 static void reply_lock_done(struct tevent_req *subreq)
6434 struct smb_request *req = NULL;
6438 START_PROFILE(SMBlock);
6440 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6443 status = smbd_smb1_do_locks_recv(subreq);
6444 TALLOC_FREE(subreq);
6446 if (NT_STATUS_IS_OK(status)) {
6447 reply_outbuf(req, 0, 0);
6449 reply_nterror(req, status);
6452 ok = srv_send_smb(req->xconn,
6453 (char *)req->outbuf,
6456 IS_CONN_ENCRYPTED(req->conn),
6459 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6462 END_PROFILE(SMBlock);
6465 /****************************************************************************
6467 ****************************************************************************/
6469 void reply_unlock(struct smb_request *req)
6471 connection_struct *conn = req->conn;
6474 struct smbd_lock_element lck;
6476 START_PROFILE(SMBunlock);
6479 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6480 END_PROFILE(SMBunlock);
6484 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6486 if (!check_fsp(conn, req, fsp)) {
6487 END_PROFILE(SMBunlock);
6491 lck = (struct smbd_lock_element) {
6492 .req_guid = smbd_request_guid(req, 0),
6493 .smblctx = req->smbpid,
6494 .brltype = UNLOCK_LOCK,
6495 .offset = IVAL(req->vwv+3, 0),
6496 .count = IVAL(req->vwv+1, 0),
6499 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6501 if (!NT_STATUS_IS_OK(status)) {
6502 reply_nterror(req, status);
6503 END_PROFILE(SMBunlock);
6507 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6513 reply_outbuf(req, 0, 0);
6515 END_PROFILE(SMBunlock);
6520 #define DBGC_CLASS DBGC_ALL
6522 /****************************************************************************
6524 conn POINTER CAN BE NULL HERE !
6525 ****************************************************************************/
6527 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6528 static void reply_tdis_done(struct tevent_req *req);
6530 void reply_tdis(struct smb_request *smb1req)
6532 connection_struct *conn = smb1req->conn;
6533 struct tevent_req *req;
6536 * Don't setup the profile charge here, take
6537 * it in reply_tdis_done(). Not strictly correct
6538 * but better than the other SMB1 async
6539 * code that double-charges at the moment.
6543 /* Not going async, profile here. */
6544 START_PROFILE(SMBtdis);
6545 DBG_INFO("Invalid connection in tdis\n");
6546 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6547 END_PROFILE(SMBtdis);
6551 req = reply_tdis_send(smb1req);
6553 /* Not going async, profile here. */
6554 START_PROFILE(SMBtdis);
6555 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6556 END_PROFILE(SMBtdis);
6559 /* We're async. This will complete later. */
6560 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6564 struct reply_tdis_state {
6565 struct tevent_queue *wait_queue;
6568 static void reply_tdis_wait_done(struct tevent_req *subreq);
6570 /****************************************************************************
6572 Note, on failure here we deallocate and return NULL to allow the caller to
6573 SMB1 return an error of ERRnomem immediately.
6574 ****************************************************************************/
6576 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6578 struct tevent_req *req;
6579 struct reply_tdis_state *state;
6580 struct tevent_req *subreq;
6581 connection_struct *conn = smb1req->conn;
6584 req = tevent_req_create(smb1req, &state,
6585 struct reply_tdis_state);
6589 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6590 if (tevent_req_nomem(state->wait_queue, req)) {
6596 * Make sure that no new request will be able to use this tcon.
6597 * This ensures that once all outstanding fsp->aio_requests
6598 * on this tcon are done, we are safe to close it.
6600 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6602 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6603 if (fsp->conn != conn) {
6607 * Flag the file as close in progress.
6608 * This will prevent any more IO being
6609 * done on it. Not strictly needed, but
6610 * doesn't hurt to flag it as closing.
6612 fsp->fsp_flags.closing = true;
6614 if (fsp->num_aio_requests > 0) {
6616 * Now wait until all aio requests on this fsp are
6619 * We don't set a callback, as we just want to block the
6620 * wait queue and the talloc_free() of fsp->aio_request
6621 * will remove the item from the wait queue.
6623 subreq = tevent_queue_wait_send(fsp->aio_requests,
6624 conn->sconn->ev_ctx,
6626 if (tevent_req_nomem(subreq, req)) {
6634 * Now we add our own waiter to the end of the queue,
6635 * this way we get notified when all pending requests are finished
6636 * and reply to the outstanding SMB1 request.
6638 subreq = tevent_queue_wait_send(state,
6639 conn->sconn->ev_ctx,
6641 if (tevent_req_nomem(subreq, req)) {
6647 * We're really going async - move the SMB1 request from
6648 * a talloc stackframe above us to the sconn talloc-context.
6649 * We need this to stick around until the wait_done
6650 * callback is invoked.
6652 smb1req = talloc_move(smb1req->sconn, &smb1req);
6654 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6659 static void reply_tdis_wait_done(struct tevent_req *subreq)
6661 struct tevent_req *req = tevent_req_callback_data(
6662 subreq, struct tevent_req);
6664 tevent_queue_wait_recv(subreq);
6665 TALLOC_FREE(subreq);
6666 tevent_req_done(req);
6669 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6671 return tevent_req_simple_recv_ntstatus(req);
6674 static void reply_tdis_done(struct tevent_req *req)
6676 struct smb_request *smb1req = tevent_req_callback_data(
6677 req, struct smb_request);
6679 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6683 * Take the profile charge here. Not strictly
6684 * correct but better than the other SMB1 async
6685 * code that double-charges at the moment.
6687 START_PROFILE(SMBtdis);
6689 status = reply_tdis_recv(req);
6691 if (!NT_STATUS_IS_OK(status)) {
6692 TALLOC_FREE(smb1req);
6693 END_PROFILE(SMBtdis);
6694 exit_server(__location__ ": reply_tdis_recv failed");
6699 * As we've been awoken, we may have changed
6700 * directory in the meantime.
6701 * reply_tdis() has the DO_CHDIR flag set.
6703 ok = chdir_current_service(smb1req->conn);
6705 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6706 smb_request_done(smb1req);
6707 END_PROFILE(SMBtdis);
6710 status = smbXsrv_tcon_disconnect(tcon,
6712 if (!NT_STATUS_IS_OK(status)) {
6713 TALLOC_FREE(smb1req);
6714 END_PROFILE(SMBtdis);
6715 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6719 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6720 smb1req->conn = NULL;
6724 reply_outbuf(smb1req, 0, 0);
6726 * The following call is needed to push the
6727 * reply data back out the socket after async
6728 * return. Plus it frees smb1req.
6730 smb_request_done(smb1req);
6731 END_PROFILE(SMBtdis);
6734 /****************************************************************************
6736 conn POINTER CAN BE NULL HERE !
6737 ****************************************************************************/
6739 void reply_echo(struct smb_request *req)
6741 connection_struct *conn = req->conn;
6742 struct smb_perfcount_data local_pcd;
6743 struct smb_perfcount_data *cur_pcd;
6747 START_PROFILE(SMBecho);
6749 smb_init_perfcount_data(&local_pcd);
6752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6753 END_PROFILE(SMBecho);
6757 smb_reverb = SVAL(req->vwv+0, 0);
6759 reply_outbuf(req, 1, req->buflen);
6761 /* copy any incoming data back out */
6762 if (req->buflen > 0) {
6763 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6766 if (smb_reverb > 100) {
6767 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6771 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6773 /* this makes sure we catch the request pcd */
6774 if (seq_num == smb_reverb) {
6775 cur_pcd = &req->pcd;
6777 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6778 cur_pcd = &local_pcd;
6781 SSVAL(req->outbuf,smb_vwv0,seq_num);
6783 show_msg((char *)req->outbuf);
6784 if (!srv_send_smb(req->xconn,
6785 (char *)req->outbuf,
6786 true, req->seqnum+1,
6787 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6789 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6792 DEBUG(3,("echo %d times\n", smb_reverb));
6794 TALLOC_FREE(req->outbuf);
6796 END_PROFILE(SMBecho);
6800 /****************************************************************************
6801 Reply to a printopen.
6802 ****************************************************************************/
6804 void reply_printopen(struct smb_request *req)
6806 connection_struct *conn = req->conn;
6810 START_PROFILE(SMBsplopen);
6813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6814 END_PROFILE(SMBsplopen);
6818 if (!CAN_PRINT(conn)) {
6819 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6820 END_PROFILE(SMBsplopen);
6824 status = file_new(req, conn, &fsp);
6825 if(!NT_STATUS_IS_OK(status)) {
6826 reply_nterror(req, status);
6827 END_PROFILE(SMBsplopen);
6831 /* Open for exclusive use, write only. */
6832 status = print_spool_open(fsp, NULL, req->vuid);
6834 if (!NT_STATUS_IS_OK(status)) {
6835 file_free(req, fsp);
6836 reply_nterror(req, status);
6837 END_PROFILE(SMBsplopen);
6841 reply_outbuf(req, 1, 0);
6842 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6844 DEBUG(3,("openprint fd=%d %s\n",
6845 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6847 END_PROFILE(SMBsplopen);
6851 /****************************************************************************
6852 Reply to a printclose.
6853 ****************************************************************************/
6855 void reply_printclose(struct smb_request *req)
6857 connection_struct *conn = req->conn;
6861 START_PROFILE(SMBsplclose);
6864 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6865 END_PROFILE(SMBsplclose);
6869 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6871 if (!check_fsp(conn, req, fsp)) {
6872 END_PROFILE(SMBsplclose);
6876 if (!CAN_PRINT(conn)) {
6877 reply_force_doserror(req, ERRSRV, ERRerror);
6878 END_PROFILE(SMBsplclose);
6882 DEBUG(3,("printclose fd=%d %s\n",
6883 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6885 status = close_file(req, fsp, NORMAL_CLOSE);
6887 if(!NT_STATUS_IS_OK(status)) {
6888 reply_nterror(req, status);
6889 END_PROFILE(SMBsplclose);
6893 reply_outbuf(req, 0, 0);
6895 END_PROFILE(SMBsplclose);
6899 /****************************************************************************
6900 Reply to a printqueue.
6901 ****************************************************************************/
6903 void reply_printqueue(struct smb_request *req)
6905 const struct loadparm_substitution *lp_sub =
6906 loadparm_s3_global_substitution();
6907 connection_struct *conn = req->conn;
6911 START_PROFILE(SMBsplretq);
6914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6915 END_PROFILE(SMBsplretq);
6919 max_count = SVAL(req->vwv+0, 0);
6920 start_index = SVAL(req->vwv+1, 0);
6922 /* we used to allow the client to get the cnum wrong, but that
6923 is really quite gross and only worked when there was only
6924 one printer - I think we should now only accept it if they
6925 get it right (tridge) */
6926 if (!CAN_PRINT(conn)) {
6927 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6928 END_PROFILE(SMBsplretq);
6932 reply_outbuf(req, 2, 3);
6933 SSVAL(req->outbuf,smb_vwv0,0);
6934 SSVAL(req->outbuf,smb_vwv1,0);
6935 SCVAL(smb_buf(req->outbuf),0,1);
6936 SSVAL(smb_buf(req->outbuf),1,0);
6938 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6939 start_index, max_count));
6942 TALLOC_CTX *mem_ctx = talloc_tos();
6945 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6946 struct rpc_pipe_client *cli = NULL;
6947 struct dcerpc_binding_handle *b = NULL;
6948 struct policy_handle handle;
6949 struct spoolss_DevmodeContainer devmode_ctr;
6950 union spoolss_JobInfo *info;
6952 uint32_t num_to_get;
6956 ZERO_STRUCT(handle);
6958 status = rpc_pipe_open_interface(mem_ctx,
6961 conn->sconn->remote_address,
6962 conn->sconn->local_address,
6963 conn->sconn->msg_ctx,
6965 if (!NT_STATUS_IS_OK(status)) {
6966 DEBUG(0, ("reply_printqueue: "
6967 "could not connect to spoolss: %s\n",
6968 nt_errstr(status)));
6969 reply_nterror(req, status);
6972 b = cli->binding_handle;
6974 ZERO_STRUCT(devmode_ctr);
6976 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6979 SEC_FLAG_MAXIMUM_ALLOWED,
6982 if (!NT_STATUS_IS_OK(status)) {
6983 reply_nterror(req, status);
6986 if (!W_ERROR_IS_OK(werr)) {
6987 reply_nterror(req, werror_to_ntstatus(werr));
6991 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6999 if (!W_ERROR_IS_OK(werr)) {
7000 reply_nterror(req, werror_to_ntstatus(werr));
7004 if (max_count > 0) {
7005 first = start_index;
7007 first = start_index + max_count + 1;
7010 if (first >= count) {
7013 num_to_get = first + MIN(ABS(max_count), count - first);
7016 for (i = first; i < num_to_get; i++) {
7019 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
7022 uint16_t qrapjobid = pjobid_to_rap(sharename,
7023 info[i].info2.job_id);
7025 if (info[i].info2.status == JOB_STATUS_PRINTING) {
7031 srv_put_dos_date2(p, 0, qtime);
7032 SCVAL(p, 4, qstatus);
7033 SSVAL(p, 5, qrapjobid);
7034 SIVAL(p, 7, info[i].info2.size);
7036 status = srvstr_push(blob, req->flags2, p+12,
7037 info[i].info2.notify_name, 16, STR_ASCII, &len);
7038 if (!NT_STATUS_IS_OK(status)) {
7039 reply_nterror(req, status);
7042 if (message_push_blob(
7045 blob, sizeof(blob))) == -1) {
7046 reply_nterror(req, NT_STATUS_NO_MEMORY);
7052 SSVAL(req->outbuf,smb_vwv0,count);
7053 SSVAL(req->outbuf,smb_vwv1,
7054 (max_count>0?first+count:first-1));
7055 SCVAL(smb_buf(req->outbuf),0,1);
7056 SSVAL(smb_buf(req->outbuf),1,28*count);
7060 DEBUG(3, ("%u entries returned in queue\n",
7064 if (b && is_valid_policy_hnd(&handle)) {
7065 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
7070 END_PROFILE(SMBsplretq);
7074 /****************************************************************************
7075 Reply to a printwrite.
7076 ****************************************************************************/
7078 void reply_printwrite(struct smb_request *req)
7080 connection_struct *conn = req->conn;
7085 START_PROFILE(SMBsplwr);
7088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7089 END_PROFILE(SMBsplwr);
7093 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7095 if (!check_fsp(conn, req, fsp)) {
7096 END_PROFILE(SMBsplwr);
7100 if (!fsp->print_file) {
7101 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7102 END_PROFILE(SMBsplwr);
7106 if (!CHECK_WRITE(fsp)) {
7107 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7108 END_PROFILE(SMBsplwr);
7112 numtowrite = SVAL(req->buf, 1);
7115 * This already protects us against CVE-2017-12163.
7117 if (req->buflen < numtowrite + 3) {
7118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7119 END_PROFILE(SMBsplwr);
7123 data = (const char *)req->buf + 3;
7125 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7126 reply_nterror(req, map_nt_error_from_unix(errno));
7127 END_PROFILE(SMBsplwr);
7131 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7133 END_PROFILE(SMBsplwr);
7137 /****************************************************************************
7139 ****************************************************************************/
7141 void reply_mkdir(struct smb_request *req)
7143 connection_struct *conn = req->conn;
7144 struct smb_filename *smb_dname = NULL;
7145 char *directory = NULL;
7148 TALLOC_CTX *ctx = talloc_tos();
7150 START_PROFILE(SMBmkdir);
7152 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7153 STR_TERMINATE, &status);
7154 if (!NT_STATUS_IS_OK(status)) {
7155 reply_nterror(req, status);
7159 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7160 status = filename_convert(ctx, conn,
7166 if (!NT_STATUS_IS_OK(status)) {
7167 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7168 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7169 ERRSRV, ERRbadpath);
7172 reply_nterror(req, status);
7176 status = create_directory(conn, req, smb_dname);
7178 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7180 if (!NT_STATUS_IS_OK(status)) {
7182 if (!use_nt_status()
7183 && NT_STATUS_EQUAL(status,
7184 NT_STATUS_OBJECT_NAME_COLLISION)) {
7186 * Yes, in the DOS error code case we get a
7187 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7188 * samba4 torture test.
7190 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7193 reply_nterror(req, status);
7197 reply_outbuf(req, 0, 0);
7199 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7201 TALLOC_FREE(smb_dname);
7202 END_PROFILE(SMBmkdir);
7206 /****************************************************************************
7208 ****************************************************************************/
7210 void reply_rmdir(struct smb_request *req)
7212 connection_struct *conn = req->conn;
7213 struct smb_filename *smb_dname = NULL;
7214 char *directory = NULL;
7216 TALLOC_CTX *ctx = talloc_tos();
7217 files_struct *fsp = NULL;
7219 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7221 START_PROFILE(SMBrmdir);
7223 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7224 STR_TERMINATE, &status);
7225 if (!NT_STATUS_IS_OK(status)) {
7226 reply_nterror(req, status);
7230 status = filename_convert(ctx, conn,
7236 if (!NT_STATUS_IS_OK(status)) {
7237 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7238 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7239 ERRSRV, ERRbadpath);
7242 reply_nterror(req, status);
7246 if (is_ntfs_stream_smb_fname(smb_dname)) {
7247 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7251 status = SMB_VFS_CREATE_FILE(
7254 &conn->cwd_fsp, /* dirfsp */
7255 smb_dname, /* fname */
7256 DELETE_ACCESS, /* access_mask */
7257 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7259 FILE_OPEN, /* create_disposition*/
7260 FILE_DIRECTORY_FILE, /* create_options */
7261 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7262 0, /* oplock_request */
7264 0, /* allocation_size */
7265 0, /* private_flags */
7270 NULL, NULL); /* create context */
7272 if (!NT_STATUS_IS_OK(status)) {
7273 if (open_was_deferred(req->xconn, req->mid)) {
7274 /* We have re-scheduled this call. */
7277 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7278 bool ok = defer_smb1_sharing_violation(req);
7283 reply_nterror(req, status);
7287 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7288 if (!NT_STATUS_IS_OK(status)) {
7289 close_file(req, fsp, ERROR_CLOSE);
7290 reply_nterror(req, status);
7294 if (!set_delete_on_close(fsp, true,
7295 conn->session_info->security_token,
7296 conn->session_info->unix_token)) {
7297 close_file(req, fsp, ERROR_CLOSE);
7298 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7302 status = close_file(req, fsp, NORMAL_CLOSE);
7303 if (!NT_STATUS_IS_OK(status)) {
7304 reply_nterror(req, status);
7306 reply_outbuf(req, 0, 0);
7309 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7311 TALLOC_FREE(smb_dname);
7312 END_PROFILE(SMBrmdir);
7316 /*******************************************************************
7317 Resolve wildcards in a filename rename.
7318 ********************************************************************/
7320 static bool resolve_wildcards(TALLOC_CTX *ctx,
7325 char *name2_copy = NULL;
7330 char *p,*p2, *pname1, *pname2;
7332 name2_copy = talloc_strdup(ctx, name2);
7337 pname1 = strrchr_m(name1,'/');
7338 pname2 = strrchr_m(name2_copy,'/');
7340 if (!pname1 || !pname2) {
7344 /* Truncate the copy of name2 at the last '/' */
7347 /* Now go past the '/' */
7351 root1 = talloc_strdup(ctx, pname1);
7352 root2 = talloc_strdup(ctx, pname2);
7354 if (!root1 || !root2) {
7358 p = strrchr_m(root1,'.');
7361 ext1 = talloc_strdup(ctx, p+1);
7363 ext1 = talloc_strdup(ctx, "");
7365 p = strrchr_m(root2,'.');
7368 ext2 = talloc_strdup(ctx, p+1);
7370 ext2 = talloc_strdup(ctx, "");
7373 if (!ext1 || !ext2) {
7381 /* Hmmm. Should this be mb-aware ? */
7384 } else if (*p2 == '*') {
7386 root2 = talloc_asprintf(ctx, "%s%s",
7405 /* Hmmm. Should this be mb-aware ? */
7408 } else if (*p2 == '*') {
7410 ext2 = talloc_asprintf(ctx, "%s%s",
7426 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7431 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7443 /****************************************************************************
7444 Ensure open files have their names updated. Updated to notify other smbd's
7446 ****************************************************************************/
7448 static void rename_open_files(connection_struct *conn,
7449 struct share_mode_lock *lck,
7451 uint32_t orig_name_hash,
7452 const struct smb_filename *smb_fname_dst)
7455 bool did_rename = False;
7457 uint32_t new_name_hash = 0;
7459 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7460 fsp = file_find_di_next(fsp)) {
7461 struct file_id_buf idbuf;
7462 /* fsp_name is a relative path under the fsp. To change this for other
7463 sharepaths we need to manipulate relative paths. */
7464 /* TODO - create the absolute path and manipulate the newname
7465 relative to the sharepath. */
7466 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7469 if (fsp->name_hash != orig_name_hash) {
7472 DBG_DEBUG("renaming file %s "
7473 "(file_id %s) from %s -> %s\n",
7475 file_id_str_buf(fsp->file_id, &idbuf),
7477 smb_fname_str_dbg(smb_fname_dst));
7479 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7480 if (NT_STATUS_IS_OK(status)) {
7482 new_name_hash = fsp->name_hash;
7487 struct file_id_buf idbuf;
7488 DBG_DEBUG("no open files on file_id %s "
7490 file_id_str_buf(id, &idbuf),
7491 smb_fname_str_dbg(smb_fname_dst));
7494 /* Send messages to all smbd's (not ourself) that the name has changed. */
7495 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7496 orig_name_hash, new_name_hash,
7501 /****************************************************************************
7502 We need to check if the source path is a parent directory of the destination
7503 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7504 refuse the rename with a sharing violation. Under UNIX the above call can
7505 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7506 probably need to check that the client is a Windows one before disallowing
7507 this as a UNIX client (one with UNIX extensions) can know the source is a
7508 symlink and make this decision intelligently. Found by an excellent bug
7509 report from <AndyLiebman@aol.com>.
7510 ****************************************************************************/
7512 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7513 const struct smb_filename *smb_fname_dst)
7515 const char *psrc = smb_fname_src->base_name;
7516 const char *pdst = smb_fname_dst->base_name;
7519 if (psrc[0] == '.' && psrc[1] == '/') {
7522 if (pdst[0] == '.' && pdst[1] == '/') {
7525 if ((slen = strlen(psrc)) > strlen(pdst)) {
7528 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7532 * Do the notify calls from a rename
7535 static void notify_rename(connection_struct *conn, bool is_dir,
7536 const struct smb_filename *smb_fname_src,
7537 const struct smb_filename *smb_fname_dst)
7539 char *parent_dir_src = NULL;
7540 char *parent_dir_dst = NULL;
7543 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7544 : FILE_NOTIFY_CHANGE_FILE_NAME;
7546 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7547 &parent_dir_src, NULL) ||
7548 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7549 &parent_dir_dst, NULL)) {
7553 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7554 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7555 smb_fname_src->base_name);
7556 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7557 smb_fname_dst->base_name);
7560 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7561 smb_fname_src->base_name);
7562 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7563 smb_fname_dst->base_name);
7566 /* this is a strange one. w2k3 gives an additional event for
7567 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7568 files, but not directories */
7570 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7571 FILE_NOTIFY_CHANGE_ATTRIBUTES
7572 |FILE_NOTIFY_CHANGE_CREATION,
7573 smb_fname_dst->base_name);
7576 TALLOC_FREE(parent_dir_src);
7577 TALLOC_FREE(parent_dir_dst);
7580 /****************************************************************************
7581 Returns an error if the parent directory for a filename is open in an
7583 ****************************************************************************/
7585 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7586 const struct smb_filename *smb_fname_dst_in)
7588 struct smb_filename *smb_fname_parent = NULL;
7590 files_struct *fsp = NULL;
7594 ok = parent_smb_fname(talloc_tos(),
7599 return NT_STATUS_NO_MEMORY;
7602 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7604 return map_nt_error_from_unix(errno);
7608 * We're only checking on this smbd here, mostly good
7609 * enough.. and will pass tests.
7612 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7613 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7614 fsp = file_find_di_next(fsp)) {
7615 if (fsp->access_mask & DELETE_ACCESS) {
7616 return NT_STATUS_SHARING_VIOLATION;
7619 return NT_STATUS_OK;
7622 /****************************************************************************
7623 Rename an open file - given an fsp.
7624 ****************************************************************************/
7626 NTSTATUS rename_internals_fsp(connection_struct *conn,
7628 const struct smb_filename *smb_fname_dst_in,
7629 const char *dst_original_lcomp,
7631 bool replace_if_exists)
7633 TALLOC_CTX *ctx = talloc_tos();
7634 struct smb_filename *smb_fname_dst = NULL;
7635 NTSTATUS status = NT_STATUS_OK;
7636 struct share_mode_lock *lck = NULL;
7637 uint32_t access_mask = SEC_DIR_ADD_FILE;
7638 bool dst_exists, old_is_stream, new_is_stream;
7641 status = check_name(conn, smb_fname_dst_in);
7642 if (!NT_STATUS_IS_OK(status)) {
7646 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7647 if (!NT_STATUS_IS_OK(status)) {
7651 if (file_has_open_streams(fsp)) {
7652 return NT_STATUS_ACCESS_DENIED;
7655 /* Make a copy of the dst smb_fname structs */
7657 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7658 if (smb_fname_dst == NULL) {
7659 status = NT_STATUS_NO_MEMORY;
7664 * Check for special case with case preserving and not
7665 * case sensitive. If the new last component differs from the original
7666 * last component only by case, then we should allow
7667 * the rename (user is trying to change the case of the
7670 if (!conn->case_sensitive && conn->case_preserve &&
7671 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7672 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7673 char *fname_dst_parent = NULL;
7674 const char *fname_dst_lcomp = NULL;
7675 char *orig_lcomp_path = NULL;
7676 char *orig_lcomp_stream = NULL;
7680 * Split off the last component of the processed
7681 * destination name. We will compare this to
7682 * the split components of dst_original_lcomp.
7684 if (!parent_dirname(ctx,
7685 smb_fname_dst->base_name,
7687 &fname_dst_lcomp)) {
7688 status = NT_STATUS_NO_MEMORY;
7693 * The dst_original_lcomp component contains
7694 * the last_component of the path + stream
7695 * name (if a stream exists).
7697 * Split off the stream name so we
7698 * can check them separately.
7701 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7702 /* POSIX - no stream component. */
7703 orig_lcomp_path = talloc_strdup(ctx,
7704 dst_original_lcomp);
7705 if (orig_lcomp_path == NULL) {
7709 ok = split_stream_filename(ctx,
7712 &orig_lcomp_stream);
7716 TALLOC_FREE(fname_dst_parent);
7717 status = NT_STATUS_NO_MEMORY;
7721 /* If the base names only differ by case, use original. */
7722 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7725 * Replace the modified last component with the
7728 if (!ISDOT(fname_dst_parent)) {
7729 tmp = talloc_asprintf(smb_fname_dst,
7734 tmp = talloc_strdup(smb_fname_dst,
7738 status = NT_STATUS_NO_MEMORY;
7739 TALLOC_FREE(fname_dst_parent);
7740 TALLOC_FREE(orig_lcomp_path);
7741 TALLOC_FREE(orig_lcomp_stream);
7744 TALLOC_FREE(smb_fname_dst->base_name);
7745 smb_fname_dst->base_name = tmp;
7748 /* If the stream_names only differ by case, use original. */
7749 if(!strcsequal(smb_fname_dst->stream_name,
7750 orig_lcomp_stream)) {
7751 /* Use the original stream. */
7752 char *tmp = talloc_strdup(smb_fname_dst,
7755 status = NT_STATUS_NO_MEMORY;
7756 TALLOC_FREE(fname_dst_parent);
7757 TALLOC_FREE(orig_lcomp_path);
7758 TALLOC_FREE(orig_lcomp_stream);
7761 TALLOC_FREE(smb_fname_dst->stream_name);
7762 smb_fname_dst->stream_name = tmp;
7764 TALLOC_FREE(fname_dst_parent);
7765 TALLOC_FREE(orig_lcomp_path);
7766 TALLOC_FREE(orig_lcomp_stream);
7770 * If the src and dest names are identical - including case,
7771 * don't do the rename, just return success.
7774 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7775 strcsequal(fsp->fsp_name->stream_name,
7776 smb_fname_dst->stream_name)) {
7777 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7778 "- returning success\n",
7779 smb_fname_str_dbg(smb_fname_dst)));
7780 status = NT_STATUS_OK;
7784 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7785 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7787 /* Return the correct error code if both names aren't streams. */
7788 if (!old_is_stream && new_is_stream) {
7789 status = NT_STATUS_OBJECT_NAME_INVALID;
7793 if (old_is_stream && !new_is_stream) {
7794 status = NT_STATUS_INVALID_PARAMETER;
7798 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7800 if(!replace_if_exists && dst_exists) {
7801 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7802 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7803 smb_fname_str_dbg(smb_fname_dst)));
7804 status = NT_STATUS_OBJECT_NAME_COLLISION;
7809 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7810 &smb_fname_dst->st);
7811 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7813 /* The file can be open when renaming a stream */
7814 if (dst_fsp && !new_is_stream) {
7815 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7816 status = NT_STATUS_ACCESS_DENIED;
7821 /* Ensure we have a valid stat struct for the source. */
7822 status = vfs_stat_fsp(fsp);
7823 if (!NT_STATUS_IS_OK(status)) {
7827 status = can_rename(conn, fsp, attrs);
7829 if (!NT_STATUS_IS_OK(status)) {
7830 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7831 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7832 smb_fname_str_dbg(smb_fname_dst)));
7833 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7834 status = NT_STATUS_ACCESS_DENIED;
7838 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7839 status = NT_STATUS_ACCESS_DENIED;
7843 /* Do we have rights to move into the destination ? */
7844 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7845 /* We're moving a directory. */
7846 access_mask = SEC_DIR_ADD_SUBDIR;
7848 status = check_parent_access(conn,
7852 if (!NT_STATUS_IS_OK(status)) {
7853 DBG_INFO("check_parent_access on "
7854 "dst %s returned %s\n",
7855 smb_fname_str_dbg(smb_fname_dst),
7860 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7863 * We have the file open ourselves, so not being able to get the
7864 * corresponding share mode lock is a fatal error.
7867 SMB_ASSERT(lck != NULL);
7869 ret = SMB_VFS_RENAMEAT(conn,
7875 uint32_t create_options = fsp->fh->private_options;
7877 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7878 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7879 smb_fname_str_dbg(smb_fname_dst)));
7881 if (!fsp->fsp_flags.is_directory &&
7882 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7883 (lp_map_archive(SNUM(conn)) ||
7884 lp_store_dos_attributes(SNUM(conn)))) {
7885 /* We must set the archive bit on the newly
7887 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7888 uint32_t old_dosmode = dos_mode(conn,
7890 file_set_dosmode(conn,
7892 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7899 fsp->fsp_flags.is_directory,
7903 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7907 * A rename acts as a new file create w.r.t. allowing an initial delete
7908 * on close, probably because in Windows there is a new handle to the
7909 * new file. If initial delete on close was requested but not
7910 * originally set, we need to set it here. This is probably not 100% correct,
7911 * but will work for the CIFSFS client which in non-posix mode
7912 * depends on these semantics. JRA.
7915 if (create_options & FILE_DELETE_ON_CLOSE) {
7916 status = can_set_delete_on_close(fsp, 0);
7918 if (NT_STATUS_IS_OK(status)) {
7919 /* Note that here we set the *initial* delete on close flag,
7920 * not the regular one. The magic gets handled in close. */
7921 fsp->fsp_flags.initial_delete_on_close = true;
7925 status = NT_STATUS_OK;
7931 if (errno == ENOTDIR || errno == EISDIR) {
7932 status = NT_STATUS_OBJECT_NAME_COLLISION;
7934 status = map_nt_error_from_unix(errno);
7937 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7938 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7939 smb_fname_str_dbg(smb_fname_dst)));
7942 TALLOC_FREE(smb_fname_dst);
7947 /****************************************************************************
7948 The guts of the rename command, split out so it may be called by the NT SMB
7950 ****************************************************************************/
7952 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7953 connection_struct *conn,
7954 struct smb_request *req,
7955 struct smb_filename *smb_fname_src,
7956 struct smb_filename *smb_fname_dst,
7957 const char *dst_original_lcomp,
7959 bool replace_if_exists,
7962 uint32_t access_mask)
7964 char *fname_src_dir = NULL;
7965 struct smb_filename *smb_fname_src_dir = NULL;
7966 char *fname_src_mask = NULL;
7968 NTSTATUS status = NT_STATUS_OK;
7969 struct smb_Dir *dir_hnd = NULL;
7970 const char *dname = NULL;
7971 char *talloced = NULL;
7973 int create_options = 0;
7974 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7975 struct smb2_create_blobs *posx = NULL;
7979 * Split the old name into directory and last component
7980 * strings. Note that unix_convert may have stripped off a
7981 * leading ./ from both name and newname if the rename is
7982 * at the root of the share. We need to make sure either both
7983 * name and newname contain a / character or neither of them do
7984 * as this is checked in resolve_wildcards().
7987 /* Split up the directory from the filename/mask. */
7988 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7989 &fname_src_dir, &fname_src_mask);
7990 if (!NT_STATUS_IS_OK(status)) {
7991 status = NT_STATUS_NO_MEMORY;
7996 * We should only check the mangled cache
7997 * here if unix_convert failed. This means
7998 * that the path in 'mask' doesn't exist
7999 * on the file system and so we need to look
8000 * for a possible mangle. This patch from
8001 * Tine Smukavec <valentin.smukavec@hermes.si>.
8004 if (!VALID_STAT(smb_fname_src->st) &&
8005 mangle_is_mangled(fname_src_mask, conn->params)) {
8006 char *new_mask = NULL;
8007 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
8010 TALLOC_FREE(fname_src_mask);
8011 fname_src_mask = new_mask;
8015 if (posix_pathnames) {
8016 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8017 if (!NT_STATUS_IS_OK(status)) {
8018 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8024 if (!src_has_wild) {
8028 * Only one file needs to be renamed. Append the mask back
8029 * onto the directory.
8031 TALLOC_FREE(smb_fname_src->base_name);
8032 if (ISDOT(fname_src_dir)) {
8033 /* Ensure we use canonical names on open. */
8034 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8038 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8043 if (!smb_fname_src->base_name) {
8044 status = NT_STATUS_NO_MEMORY;
8048 DEBUG(3, ("rename_internals: case_sensitive = %d, "
8049 "case_preserve = %d, short case preserve = %d, "
8050 "directory = %s, newname = %s, "
8051 "last_component_dest = %s\n",
8052 conn->case_sensitive, conn->case_preserve,
8053 conn->short_case_preserve,
8054 smb_fname_str_dbg(smb_fname_src),
8055 smb_fname_str_dbg(smb_fname_dst),
8056 dst_original_lcomp));
8058 /* The dest name still may have wildcards. */
8059 if (dest_has_wild) {
8060 char *fname_dst_mod = NULL;
8061 if (!resolve_wildcards(smb_fname_dst,
8062 smb_fname_src->base_name,
8063 smb_fname_dst->base_name,
8065 DEBUG(6, ("rename_internals: resolve_wildcards "
8067 smb_fname_src->base_name,
8068 smb_fname_dst->base_name));
8069 status = NT_STATUS_NO_MEMORY;
8072 TALLOC_FREE(smb_fname_dst->base_name);
8073 smb_fname_dst->base_name = fname_dst_mod;
8076 ZERO_STRUCT(smb_fname_src->st);
8077 if (posix_pathnames) {
8078 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8080 rc = SMB_VFS_STAT(conn, smb_fname_src);
8083 status = map_nt_error_from_unix_common(errno);
8087 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8088 create_options |= FILE_DIRECTORY_FILE;
8091 status = SMB_VFS_CREATE_FILE(
8094 &conn->cwd_fsp, /* dirfsp */
8095 smb_fname_src, /* fname */
8096 access_mask, /* access_mask */
8097 (FILE_SHARE_READ | /* share_access */
8099 FILE_OPEN, /* create_disposition*/
8100 create_options, /* create_options */
8101 0, /* file_attributes */
8102 0, /* oplock_request */
8104 0, /* allocation_size */
8105 0, /* private_flags */
8110 posx, /* in_context_blobs */
8111 NULL); /* out_context_blobs */
8113 if (!NT_STATUS_IS_OK(status)) {
8114 DEBUG(3, ("Could not open rename source %s: %s\n",
8115 smb_fname_str_dbg(smb_fname_src),
8116 nt_errstr(status)));
8120 status = rename_internals_fsp(conn,
8127 close_file(req, fsp, NORMAL_CLOSE);
8129 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8130 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8131 smb_fname_str_dbg(smb_fname_dst)));
8137 * Wildcards - process each file that matches.
8139 if (strequal(fname_src_mask, "????????.???")) {
8140 TALLOC_FREE(fname_src_mask);
8141 fname_src_mask = talloc_strdup(ctx, "*");
8142 if (!fname_src_mask) {
8143 status = NT_STATUS_NO_MEMORY;
8148 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8152 smb_fname_src->twrp,
8153 smb_fname_src->flags);
8154 if (smb_fname_src_dir == NULL) {
8155 status = NT_STATUS_NO_MEMORY;
8159 status = check_name(conn, smb_fname_src_dir);
8160 if (!NT_STATUS_IS_OK(status)) {
8164 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8166 if (dir_hnd == NULL) {
8167 status = map_nt_error_from_unix(errno);
8171 status = NT_STATUS_NO_SUCH_FILE;
8173 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8174 * - gentest fix. JRA
8177 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8179 files_struct *fsp = NULL;
8180 char *destname = NULL;
8181 bool sysdir_entry = False;
8183 /* Quick check for "." and ".." */
8184 if (ISDOT(dname) || ISDOTDOT(dname)) {
8185 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8186 sysdir_entry = True;
8188 TALLOC_FREE(talloced);
8193 if (!is_visible_file(conn,
8198 TALLOC_FREE(talloced);
8202 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8203 TALLOC_FREE(talloced);
8208 status = NT_STATUS_OBJECT_NAME_INVALID;
8212 TALLOC_FREE(smb_fname_src->base_name);
8213 if (ISDOT(fname_src_dir)) {
8214 /* Ensure we use canonical names on open. */
8215 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8219 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8224 if (!smb_fname_src->base_name) {
8225 status = NT_STATUS_NO_MEMORY;
8229 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8230 smb_fname_dst->base_name,
8232 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8233 smb_fname_src->base_name, destname));
8234 TALLOC_FREE(talloced);
8238 status = NT_STATUS_NO_MEMORY;
8242 TALLOC_FREE(smb_fname_dst->base_name);
8243 smb_fname_dst->base_name = destname;
8245 ZERO_STRUCT(smb_fname_src->st);
8246 if (posix_pathnames) {
8247 SMB_VFS_LSTAT(conn, smb_fname_src);
8249 SMB_VFS_STAT(conn, smb_fname_src);
8254 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8255 create_options |= FILE_DIRECTORY_FILE;
8258 status = SMB_VFS_CREATE_FILE(
8261 &conn->cwd_fsp, /* dirfsp */
8262 smb_fname_src, /* fname */
8263 access_mask, /* access_mask */
8264 (FILE_SHARE_READ | /* share_access */
8266 FILE_OPEN, /* create_disposition*/
8267 create_options, /* create_options */
8268 0, /* file_attributes */
8269 0, /* oplock_request */
8271 0, /* allocation_size */
8272 0, /* private_flags */
8277 posx, /* in_context_blobs */
8278 NULL); /* out_context_blobs */
8280 if (!NT_STATUS_IS_OK(status)) {
8281 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8282 "returned %s rename %s -> %s\n",
8284 smb_fname_str_dbg(smb_fname_src),
8285 smb_fname_str_dbg(smb_fname_dst)));
8289 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8290 if (dst_original_lcomp == NULL) {
8291 status = NT_STATUS_NO_MEMORY;
8295 status = rename_internals_fsp(conn,
8302 close_file(req, fsp, NORMAL_CLOSE);
8304 if (!NT_STATUS_IS_OK(status)) {
8305 DEBUG(3, ("rename_internals_fsp returned %s for "
8306 "rename %s -> %s\n", nt_errstr(status),
8307 smb_fname_str_dbg(smb_fname_src),
8308 smb_fname_str_dbg(smb_fname_dst)));
8314 DEBUG(3,("rename_internals: doing rename on %s -> "
8315 "%s\n", smb_fname_str_dbg(smb_fname_src),
8316 smb_fname_str_dbg(smb_fname_src)));
8317 TALLOC_FREE(talloced);
8319 TALLOC_FREE(dir_hnd);
8321 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8322 status = map_nt_error_from_unix(errno);
8327 TALLOC_FREE(talloced);
8328 TALLOC_FREE(smb_fname_src_dir);
8329 TALLOC_FREE(fname_src_dir);
8330 TALLOC_FREE(fname_src_mask);
8334 /****************************************************************************
8336 ****************************************************************************/
8338 void reply_mv(struct smb_request *req)
8340 connection_struct *conn = req->conn;
8342 char *newname = NULL;
8346 bool src_has_wcard = False;
8347 bool dest_has_wcard = False;
8348 TALLOC_CTX *ctx = talloc_tos();
8349 struct smb_filename *smb_fname_src = NULL;
8350 struct smb_filename *smb_fname_dst = NULL;
8351 const char *dst_original_lcomp = NULL;
8352 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8353 (req->posix_pathnames ?
8354 UCF_UNIX_NAME_LOOKUP :
8355 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8356 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8357 (req->posix_pathnames ?
8359 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8360 bool stream_rename = false;
8362 START_PROFILE(SMBmv);
8365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8369 attrs = SVAL(req->vwv+0, 0);
8371 p = (const char *)req->buf + 1;
8372 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
8373 &status, &src_has_wcard);
8374 if (!NT_STATUS_IS_OK(status)) {
8375 reply_nterror(req, status);
8379 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
8380 &status, &dest_has_wcard);
8381 if (!NT_STATUS_IS_OK(status)) {
8382 reply_nterror(req, status);
8386 if (!req->posix_pathnames) {
8387 /* The newname must begin with a ':' if the
8388 name contains a ':'. */
8389 if (strchr_m(name, ':')) {
8390 if (newname[0] != ':') {
8391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8394 stream_rename = true;
8398 status = filename_convert(ctx,
8406 if (!NT_STATUS_IS_OK(status)) {
8407 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8408 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8409 ERRSRV, ERRbadpath);
8412 reply_nterror(req, status);
8416 status = filename_convert(ctx,
8424 if (!NT_STATUS_IS_OK(status)) {
8425 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8426 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8427 ERRSRV, ERRbadpath);
8430 reply_nterror(req, status);
8434 /* Get the last component of the destination for rename_internals(). */
8435 dst_original_lcomp = get_original_lcomp(ctx,
8439 if (dst_original_lcomp == NULL) {
8440 reply_nterror(req, NT_STATUS_NO_MEMORY);
8444 if (stream_rename) {
8445 /* smb_fname_dst->base_name must be the same as
8446 smb_fname_src->base_name. */
8447 TALLOC_FREE(smb_fname_dst->base_name);
8448 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8449 smb_fname_src->base_name);
8450 if (!smb_fname_dst->base_name) {
8451 reply_nterror(req, NT_STATUS_NO_MEMORY);
8456 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8457 smb_fname_str_dbg(smb_fname_dst)));
8459 status = rename_internals(ctx,
8470 if (!NT_STATUS_IS_OK(status)) {
8471 if (open_was_deferred(req->xconn, req->mid)) {
8472 /* We have re-scheduled this call. */
8475 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8476 bool ok = defer_smb1_sharing_violation(req);
8481 reply_nterror(req, status);
8485 reply_outbuf(req, 0, 0);
8487 TALLOC_FREE(smb_fname_src);
8488 TALLOC_FREE(smb_fname_dst);
8493 /*******************************************************************
8494 Copy a file as part of a reply_copy.
8495 ******************************************************************/
8498 * TODO: check error codes on all callers
8501 NTSTATUS copy_file(TALLOC_CTX *ctx,
8502 connection_struct *conn,
8503 struct smb_filename *smb_fname_src,
8504 struct smb_filename *smb_fname_dst,
8507 bool target_is_directory)
8509 struct smb_filename *smb_fname_dst_tmp = NULL;
8511 files_struct *fsp1,*fsp2;
8513 uint32_t new_create_disposition;
8517 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8518 if (smb_fname_dst_tmp == NULL) {
8519 return NT_STATUS_NO_MEMORY;
8523 * If the target is a directory, extract the last component from the
8524 * src filename and append it to the dst filename
8526 if (target_is_directory) {
8529 /* dest/target can't be a stream if it's a directory. */
8530 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8532 p = strrchr_m(smb_fname_src->base_name,'/');
8536 p = smb_fname_src->base_name;
8538 smb_fname_dst_tmp->base_name =
8539 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8541 if (!smb_fname_dst_tmp->base_name) {
8542 status = NT_STATUS_NO_MEMORY;
8547 status = vfs_file_exist(conn, smb_fname_src);
8548 if (!NT_STATUS_IS_OK(status)) {
8552 if (!target_is_directory && count) {
8553 new_create_disposition = FILE_OPEN;
8555 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8558 &new_create_disposition,
8561 status = NT_STATUS_INVALID_PARAMETER;
8566 /* Open the src file for reading. */
8567 status = SMB_VFS_CREATE_FILE(
8570 &conn->cwd_fsp, /* dirfsp */
8571 smb_fname_src, /* fname */
8572 FILE_GENERIC_READ, /* access_mask */
8573 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8574 FILE_OPEN, /* create_disposition*/
8575 0, /* create_options */
8576 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8577 INTERNAL_OPEN_ONLY, /* oplock_request */
8579 0, /* allocation_size */
8580 0, /* private_flags */
8585 NULL, NULL); /* create context */
8587 if (!NT_STATUS_IS_OK(status)) {
8591 dosattrs = dos_mode(conn, smb_fname_src);
8593 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8594 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8597 /* Open the dst file for writing. */
8598 status = SMB_VFS_CREATE_FILE(
8601 &conn->cwd_fsp, /* dirfsp */
8602 smb_fname_dst, /* fname */
8603 FILE_GENERIC_WRITE, /* access_mask */
8604 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8605 new_create_disposition, /* create_disposition*/
8606 0, /* create_options */
8607 dosattrs, /* file_attributes */
8608 INTERNAL_OPEN_ONLY, /* oplock_request */
8610 0, /* allocation_size */
8611 0, /* private_flags */
8616 NULL, NULL); /* create context */
8618 if (!NT_STATUS_IS_OK(status)) {
8619 close_file(NULL, fsp1, ERROR_CLOSE);
8623 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8624 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8626 DEBUG(0, ("error - vfs lseek returned error %s\n",
8628 status = map_nt_error_from_unix(errno);
8629 close_file(NULL, fsp1, ERROR_CLOSE);
8630 close_file(NULL, fsp2, ERROR_CLOSE);
8635 /* Do the actual copy. */
8636 if (smb_fname_src->st.st_ex_size) {
8637 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8642 close_file(NULL, fsp1, NORMAL_CLOSE);
8644 /* Ensure the modtime is set correctly on the destination file. */
8645 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8648 * As we are opening fsp1 read-only we only expect
8649 * an error on close on fsp2 if we are out of space.
8650 * Thus we don't look at the error return from the
8653 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8655 if (!NT_STATUS_IS_OK(status)) {
8659 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8660 status = NT_STATUS_DISK_FULL;
8664 status = NT_STATUS_OK;
8667 TALLOC_FREE(smb_fname_dst_tmp);
8671 /****************************************************************************
8672 Reply to a file copy.
8673 ****************************************************************************/
8675 void reply_copy(struct smb_request *req)
8677 connection_struct *conn = req->conn;
8678 struct smb_filename *smb_fname_src = NULL;
8679 struct smb_filename *smb_fname_src_dir = NULL;
8680 struct smb_filename *smb_fname_dst = NULL;
8681 char *fname_src = NULL;
8682 char *fname_dst = NULL;
8683 char *fname_src_mask = NULL;
8684 char *fname_src_dir = NULL;
8687 int error = ERRnoaccess;
8691 bool target_is_directory=False;
8692 bool source_has_wild = False;
8693 bool dest_has_wild = False;
8695 uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8696 ucf_flags_from_smb_request(req);
8697 uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8698 ucf_flags_from_smb_request(req);
8699 TALLOC_CTX *ctx = talloc_tos();
8701 START_PROFILE(SMBcopy);
8704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8708 tid2 = SVAL(req->vwv+0, 0);
8709 ofun = SVAL(req->vwv+1, 0);
8710 flags = SVAL(req->vwv+2, 0);
8712 p = (const char *)req->buf;
8713 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8714 &status, &source_has_wild);
8715 if (!NT_STATUS_IS_OK(status)) {
8716 reply_nterror(req, status);
8719 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8720 &status, &dest_has_wild);
8721 if (!NT_STATUS_IS_OK(status)) {
8722 reply_nterror(req, status);
8726 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8728 if (tid2 != conn->cnum) {
8729 /* can't currently handle inter share copies XXXX */
8730 DEBUG(3,("Rejecting inter-share copy\n"));
8731 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8735 status = filename_convert(ctx, conn,
8741 if (!NT_STATUS_IS_OK(status)) {
8742 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8743 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8744 ERRSRV, ERRbadpath);
8747 reply_nterror(req, status);
8751 status = filename_convert(ctx, conn,
8757 if (!NT_STATUS_IS_OK(status)) {
8758 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8759 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8760 ERRSRV, ERRbadpath);
8763 reply_nterror(req, status);
8767 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8769 if ((flags&1) && target_is_directory) {
8770 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8774 if ((flags&2) && !target_is_directory) {
8775 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8779 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8780 /* wants a tree copy! XXXX */
8781 DEBUG(3,("Rejecting tree copy\n"));
8782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8786 /* Split up the directory from the filename/mask. */
8787 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8788 &fname_src_dir, &fname_src_mask);
8789 if (!NT_STATUS_IS_OK(status)) {
8790 reply_nterror(req, NT_STATUS_NO_MEMORY);
8795 * We should only check the mangled cache
8796 * here if unix_convert failed. This means
8797 * that the path in 'mask' doesn't exist
8798 * on the file system and so we need to look
8799 * for a possible mangle. This patch from
8800 * Tine Smukavec <valentin.smukavec@hermes.si>.
8802 if (!VALID_STAT(smb_fname_src->st) &&
8803 mangle_is_mangled(fname_src_mask, conn->params)) {
8804 char *new_mask = NULL;
8805 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8806 &new_mask, conn->params);
8808 /* Use demangled name if one was successfully found. */
8810 TALLOC_FREE(fname_src_mask);
8811 fname_src_mask = new_mask;
8815 if (!source_has_wild) {
8818 * Only one file needs to be copied. Append the mask back onto
8821 TALLOC_FREE(smb_fname_src->base_name);
8822 if (ISDOT(fname_src_dir)) {
8823 /* Ensure we use canonical names on open. */
8824 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8828 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8833 if (!smb_fname_src->base_name) {
8834 reply_nterror(req, NT_STATUS_NO_MEMORY);
8838 if (dest_has_wild) {
8839 char *fname_dst_mod = NULL;
8840 if (!resolve_wildcards(smb_fname_dst,
8841 smb_fname_src->base_name,
8842 smb_fname_dst->base_name,
8844 reply_nterror(req, NT_STATUS_NO_MEMORY);
8847 TALLOC_FREE(smb_fname_dst->base_name);
8848 smb_fname_dst->base_name = fname_dst_mod;
8851 status = check_name(conn, smb_fname_src);
8852 if (!NT_STATUS_IS_OK(status)) {
8853 reply_nterror(req, status);
8857 status = check_name(conn, smb_fname_dst);
8858 if (!NT_STATUS_IS_OK(status)) {
8859 reply_nterror(req, status);
8863 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8864 ofun, count, target_is_directory);
8866 if(!NT_STATUS_IS_OK(status)) {
8867 reply_nterror(req, status);
8873 struct smb_Dir *dir_hnd = NULL;
8874 const char *dname = NULL;
8875 char *talloced = NULL;
8879 * There is a wildcard that requires us to actually read the
8880 * src dir and copy each file matching the mask to the dst.
8881 * Right now streams won't be copied, but this could
8882 * presumably be added with a nested loop for reach dir entry.
8884 SMB_ASSERT(!smb_fname_src->stream_name);
8885 SMB_ASSERT(!smb_fname_dst->stream_name);
8887 smb_fname_src->stream_name = NULL;
8888 smb_fname_dst->stream_name = NULL;
8890 if (strequal(fname_src_mask,"????????.???")) {
8891 TALLOC_FREE(fname_src_mask);
8892 fname_src_mask = talloc_strdup(ctx, "*");
8893 if (!fname_src_mask) {
8894 reply_nterror(req, NT_STATUS_NO_MEMORY);
8899 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8903 smb_fname_src->twrp,
8904 smb_fname_src->flags);
8905 if (smb_fname_src_dir == NULL) {
8906 reply_nterror(req, NT_STATUS_NO_MEMORY);
8910 status = check_name(conn, smb_fname_src_dir);
8911 if (!NT_STATUS_IS_OK(status)) {
8912 reply_nterror(req, status);
8916 dir_hnd = OpenDir(ctx,
8921 if (dir_hnd == NULL) {
8922 status = map_nt_error_from_unix(errno);
8923 reply_nterror(req, status);
8929 /* Iterate over the src dir copying each entry to the dst. */
8930 while ((dname = ReadDirName(dir_hnd, &offset,
8931 &smb_fname_src->st, &talloced))) {
8932 char *destname = NULL;
8934 if (ISDOT(dname) || ISDOTDOT(dname)) {
8935 TALLOC_FREE(talloced);
8939 if (!is_visible_file(conn,
8944 TALLOC_FREE(talloced);
8948 if(!mask_match(dname, fname_src_mask,
8949 conn->case_sensitive)) {
8950 TALLOC_FREE(talloced);
8954 error = ERRnoaccess;
8956 /* Get the src smb_fname struct setup. */
8957 TALLOC_FREE(smb_fname_src->base_name);
8958 if (ISDOT(fname_src_dir)) {
8959 /* Ensure we use canonical names on open. */
8960 smb_fname_src->base_name =
8961 talloc_asprintf(smb_fname_src, "%s",
8964 smb_fname_src->base_name =
8965 talloc_asprintf(smb_fname_src, "%s/%s",
8966 fname_src_dir, dname);
8969 if (!smb_fname_src->base_name) {
8970 TALLOC_FREE(dir_hnd);
8971 TALLOC_FREE(talloced);
8972 reply_nterror(req, NT_STATUS_NO_MEMORY);
8976 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8977 smb_fname_dst->base_name,
8979 TALLOC_FREE(talloced);
8983 TALLOC_FREE(dir_hnd);
8984 TALLOC_FREE(talloced);
8985 reply_nterror(req, NT_STATUS_NO_MEMORY);
8989 TALLOC_FREE(smb_fname_dst->base_name);
8990 smb_fname_dst->base_name = destname;
8992 status = check_name(conn, smb_fname_src);
8993 if (!NT_STATUS_IS_OK(status)) {
8994 TALLOC_FREE(dir_hnd);
8995 TALLOC_FREE(talloced);
8996 reply_nterror(req, status);
9000 status = check_name(conn, smb_fname_dst);
9001 if (!NT_STATUS_IS_OK(status)) {
9002 TALLOC_FREE(dir_hnd);
9003 TALLOC_FREE(talloced);
9004 reply_nterror(req, status);
9008 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
9009 smb_fname_src->base_name,
9010 smb_fname_dst->base_name));
9012 status = copy_file(ctx, conn, smb_fname_src,
9013 smb_fname_dst, ofun, count,
9014 target_is_directory);
9015 if (NT_STATUS_IS_OK(status)) {
9019 TALLOC_FREE(talloced);
9021 TALLOC_FREE(dir_hnd);
9025 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
9029 reply_outbuf(req, 1, 0);
9030 SSVAL(req->outbuf,smb_vwv0,count);
9032 TALLOC_FREE(smb_fname_src);
9033 TALLOC_FREE(smb_fname_src_dir);
9034 TALLOC_FREE(smb_fname_dst);
9035 TALLOC_FREE(fname_src);
9036 TALLOC_FREE(fname_dst);
9037 TALLOC_FREE(fname_src_mask);
9038 TALLOC_FREE(fname_src_dir);
9040 END_PROFILE(SMBcopy);
9045 #define DBGC_CLASS DBGC_LOCKING
9047 /****************************************************************************
9048 Get a lock pid, dealing with large count requests.
9049 ****************************************************************************/
9051 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
9052 bool large_file_format)
9054 if(!large_file_format)
9055 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9057 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9060 /****************************************************************************
9061 Get a lock count, dealing with large count requests.
9062 ****************************************************************************/
9064 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9065 bool large_file_format)
9069 if(!large_file_format) {
9070 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9073 * No BVAL, this is reversed!
9075 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9076 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9082 /****************************************************************************
9083 Get a lock offset, dealing with large offset requests.
9084 ****************************************************************************/
9086 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9087 bool large_file_format)
9089 uint64_t offset = 0;
9091 if(!large_file_format) {
9092 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9095 * No BVAL, this is reversed!
9097 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9098 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9104 struct smbd_do_unlocking_state {
9105 struct files_struct *fsp;
9106 uint16_t num_ulocks;
9107 struct smbd_lock_element *ulocks;
9108 enum brl_flavour lock_flav;
9112 static void smbd_do_unlocking_fn(
9115 bool *pmodified_dependent,
9118 struct smbd_do_unlocking_state *state = private_data;
9119 struct files_struct *fsp = state->fsp;
9120 enum brl_flavour lock_flav = state->lock_flav;
9123 for (i = 0; i < state->num_ulocks; i++) {
9124 struct smbd_lock_element *e = &state->ulocks[i];
9126 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9127 "pid %"PRIu64", file %s\n",
9133 if (e->brltype != UNLOCK_LOCK) {
9134 /* this can only happen with SMB2 */
9135 state->status = NT_STATUS_INVALID_PARAMETER;
9139 state->status = do_unlock(
9140 fsp, e->smblctx, e->count, e->offset, lock_flav);
9142 DBG_DEBUG("do_unlock returned %s\n",
9143 nt_errstr(state->status));
9145 if (!NT_STATUS_IS_OK(state->status)) {
9150 *pmodified_dependent = true;
9153 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9155 uint16_t num_ulocks,
9156 struct smbd_lock_element *ulocks,
9157 enum brl_flavour lock_flav)
9159 struct smbd_do_unlocking_state state = {
9161 .num_ulocks = num_ulocks,
9163 .lock_flav = lock_flav,
9167 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9169 status = share_mode_do_locked(
9170 fsp->file_id, smbd_do_unlocking_fn, &state);
9172 if (!NT_STATUS_IS_OK(status)) {
9173 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9177 if (!NT_STATUS_IS_OK(state.status)) {
9178 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9180 return state.status;
9183 return NT_STATUS_OK;
9186 /****************************************************************************
9187 Reply to a lockingX request.
9188 ****************************************************************************/
9190 static void reply_lockingx_done(struct tevent_req *subreq);
9192 void reply_lockingX(struct smb_request *req)
9194 connection_struct *conn = req->conn;
9196 unsigned char locktype;
9197 enum brl_type brltype;
9198 unsigned char oplocklevel;
9199 uint16_t num_ulocks;
9201 int32_t lock_timeout;
9203 const uint8_t *data;
9204 bool large_file_format;
9205 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9206 struct smbd_lock_element *locks = NULL;
9207 struct tevent_req *subreq = NULL;
9209 START_PROFILE(SMBlockingX);
9212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9213 END_PROFILE(SMBlockingX);
9217 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9218 locktype = CVAL(req->vwv+3, 0);
9219 oplocklevel = CVAL(req->vwv+3, 1);
9220 num_ulocks = SVAL(req->vwv+6, 0);
9221 num_locks = SVAL(req->vwv+7, 0);
9222 lock_timeout = IVAL(req->vwv+4, 0);
9223 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9225 if (!check_fsp(conn, req, fsp)) {
9226 END_PROFILE(SMBlockingX);
9232 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9233 /* we don't support these - and CANCEL_LOCK makes w2k
9234 and XP reboot so I don't really want to be
9235 compatible! (tridge) */
9236 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9237 END_PROFILE(SMBlockingX);
9241 /* Check if this is an oplock break on a file
9242 we have granted an oplock on.
9244 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9245 /* Client can insist on breaking to none. */
9246 bool break_to_none = (oplocklevel == 0);
9249 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9250 "for %s\n", (unsigned int)oplocklevel,
9251 fsp_fnum_dbg(fsp)));
9254 * Make sure we have granted an exclusive or batch oplock on
9258 if (fsp->oplock_type == 0) {
9260 /* The Samba4 nbench simulator doesn't understand
9261 the difference between break to level2 and break
9262 to none from level2 - it sends oplock break
9263 replies in both cases. Don't keep logging an error
9264 message here - just ignore it. JRA. */
9266 DEBUG(5,("reply_lockingX: Error : oplock break from "
9267 "client for %s (oplock=%d) and no "
9268 "oplock granted on this file (%s).\n",
9269 fsp_fnum_dbg(fsp), fsp->oplock_type,
9272 /* if this is a pure oplock break request then don't
9274 if (num_locks == 0 && num_ulocks == 0) {
9275 END_PROFILE(SMBlockingX);
9279 END_PROFILE(SMBlockingX);
9280 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9284 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9286 result = remove_oplock(fsp);
9288 result = downgrade_oplock(fsp);
9292 DEBUG(0, ("reply_lockingX: error in removing "
9293 "oplock on file %s\n", fsp_str_dbg(fsp)));
9294 /* Hmmm. Is this panic justified? */
9295 smb_panic("internal tdb error");
9298 /* if this is a pure oplock break request then don't send a
9300 if (num_locks == 0 && num_ulocks == 0) {
9301 /* Sanity check - ensure a pure oplock break is not a
9303 if (CVAL(req->vwv+0, 0) != 0xff) {
9304 DEBUG(0,("reply_lockingX: Error : pure oplock "
9305 "break is a chained %d request !\n",
9306 (unsigned int)CVAL(req->vwv+0, 0)));
9308 END_PROFILE(SMBlockingX);
9314 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9316 END_PROFILE(SMBlockingX);
9320 if (num_ulocks != 0) {
9321 struct smbd_lock_element *ulocks = NULL;
9324 ulocks = talloc_array(
9325 req, struct smbd_lock_element, num_ulocks);
9326 if (ulocks == NULL) {
9327 reply_nterror(req, NT_STATUS_NO_MEMORY);
9328 END_PROFILE(SMBlockingX);
9333 * Data now points at the beginning of the list of
9334 * smb_unlkrng structs
9336 for (i = 0; i < num_ulocks; i++) {
9337 ulocks[i].req_guid = smbd_request_guid(req,
9339 ulocks[i].smblctx = get_lock_pid(
9340 data, i, large_file_format);
9341 ulocks[i].count = get_lock_count(
9342 data, i, large_file_format);
9343 ulocks[i].offset = get_lock_offset(
9344 data, i, large_file_format);
9345 ulocks[i].brltype = UNLOCK_LOCK;
9349 * Unlock cancels pending locks
9352 ok = smbd_smb1_brl_finish_by_lock(
9359 reply_outbuf(req, 2, 0);
9360 SSVAL(req->outbuf, smb_vwv0, 0xff);
9361 SSVAL(req->outbuf, smb_vwv1, 0);
9362 END_PROFILE(SMBlockingX);
9366 status = smbd_do_unlocking(
9367 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9368 TALLOC_FREE(ulocks);
9369 if (!NT_STATUS_IS_OK(status)) {
9370 END_PROFILE(SMBlockingX);
9371 reply_nterror(req, status);
9376 /* Now do any requested locks */
9377 data += ((large_file_format ? 20 : 10)*num_ulocks);
9379 /* Data now points at the beginning of the list
9380 of smb_lkrng structs */
9382 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9383 brltype = READ_LOCK;
9385 brltype = WRITE_LOCK;
9388 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9389 if (locks == NULL) {
9390 reply_nterror(req, NT_STATUS_NO_MEMORY);
9391 END_PROFILE(SMBlockingX);
9395 for (i = 0; i < num_locks; i++) {
9396 locks[i].req_guid = smbd_request_guid(req, i),
9397 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9398 locks[i].count = get_lock_count(data, i, large_file_format);
9399 locks[i].offset = get_lock_offset(data, i, large_file_format);
9400 locks[i].brltype = brltype;
9403 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9407 if (num_locks == 0) {
9408 /* See smbtorture3 lock11 test */
9409 reply_outbuf(req, 2, 0);
9410 /* andx chain ends */
9411 SSVAL(req->outbuf, smb_vwv0, 0xff);
9412 SSVAL(req->outbuf, smb_vwv1, 0);
9413 END_PROFILE(SMBlockingX);
9417 ok = smbd_smb1_brl_finish_by_lock(
9421 locks[0], /* Windows only cancels the first lock */
9422 NT_STATUS_FILE_LOCK_CONFLICT);
9425 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9426 END_PROFILE(SMBlockingX);
9430 reply_outbuf(req, 2, 0);
9431 SSVAL(req->outbuf, smb_vwv0, 0xff);
9432 SSVAL(req->outbuf, smb_vwv1, 0);
9433 END_PROFILE(SMBlockingX);
9437 subreq = smbd_smb1_do_locks_send(
9447 if (subreq == NULL) {
9448 reply_nterror(req, NT_STATUS_NO_MEMORY);
9449 END_PROFILE(SMBlockingX);
9452 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9453 END_PROFILE(SMBlockingX);
9456 static void reply_lockingx_done(struct tevent_req *subreq)
9458 struct smb_request *req = NULL;
9462 START_PROFILE(SMBlockingX);
9464 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9467 status = smbd_smb1_do_locks_recv(subreq);
9468 TALLOC_FREE(subreq);
9470 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9472 if (NT_STATUS_IS_OK(status)) {
9473 reply_outbuf(req, 2, 0);
9474 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9475 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9477 reply_nterror(req, status);
9480 ok = srv_send_smb(req->xconn,
9481 (char *)req->outbuf,
9484 IS_CONN_ENCRYPTED(req->conn),
9487 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9490 END_PROFILE(SMBlockingX);
9494 #define DBGC_CLASS DBGC_ALL
9496 /****************************************************************************
9497 Reply to a SMBreadbmpx (read block multiplex) request.
9498 Always reply with an error, if someone has a platform really needs this,
9499 please contact vl@samba.org
9500 ****************************************************************************/
9502 void reply_readbmpx(struct smb_request *req)
9504 START_PROFILE(SMBreadBmpx);
9505 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9506 END_PROFILE(SMBreadBmpx);
9510 /****************************************************************************
9511 Reply to a SMBreadbs (read block multiplex secondary) request.
9512 Always reply with an error, if someone has a platform really needs this,
9513 please contact vl@samba.org
9514 ****************************************************************************/
9516 void reply_readbs(struct smb_request *req)
9518 START_PROFILE(SMBreadBs);
9519 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9520 END_PROFILE(SMBreadBs);
9524 /****************************************************************************
9525 Reply to a SMBsetattrE.
9526 ****************************************************************************/
9528 void reply_setattrE(struct smb_request *req)
9530 connection_struct *conn = req->conn;
9531 struct smb_file_time ft;
9535 START_PROFILE(SMBsetattrE);
9536 init_smb_file_time(&ft);
9539 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9543 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9545 if(!fsp || (fsp->conn != conn)) {
9546 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9551 * Convert the DOS times into unix times.
9554 ft.atime = time_t_to_full_timespec(
9555 srv_make_unix_date2(req->vwv+3));
9556 ft.mtime = time_t_to_full_timespec(
9557 srv_make_unix_date2(req->vwv+5));
9558 ft.create_time = time_t_to_full_timespec(
9559 srv_make_unix_date2(req->vwv+1));
9561 reply_outbuf(req, 0, 0);
9564 * Patch from Ray Frush <frush@engr.colostate.edu>
9565 * Sometimes times are sent as zero - ignore them.
9568 /* Ensure we have a valid stat struct for the source. */
9569 status = vfs_stat_fsp(fsp);
9570 if (!NT_STATUS_IS_OK(status)) {
9571 reply_nterror(req, status);
9575 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9576 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9580 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9581 if (!NT_STATUS_IS_OK(status)) {
9582 reply_nterror(req, status);
9586 if (fsp->fsp_flags.modified) {
9587 trigger_write_time_update_immediate(fsp);
9590 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9593 (unsigned int)ft.atime.tv_sec,
9594 (unsigned int)ft.mtime.tv_sec,
9595 (unsigned int)ft.create_time.tv_sec
9598 END_PROFILE(SMBsetattrE);
9603 /* Back from the dead for OS/2..... JRA. */
9605 /****************************************************************************
9606 Reply to a SMBwritebmpx (write block multiplex primary) request.
9607 Always reply with an error, if someone has a platform really needs this,
9608 please contact vl@samba.org
9609 ****************************************************************************/
9611 void reply_writebmpx(struct smb_request *req)
9613 START_PROFILE(SMBwriteBmpx);
9614 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9615 END_PROFILE(SMBwriteBmpx);
9619 /****************************************************************************
9620 Reply to a SMBwritebs (write block multiplex secondary) request.
9621 Always reply with an error, if someone has a platform really needs this,
9622 please contact vl@samba.org
9623 ****************************************************************************/
9625 void reply_writebs(struct smb_request *req)
9627 START_PROFILE(SMBwriteBs);
9628 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9629 END_PROFILE(SMBwriteBs);
9633 /****************************************************************************
9634 Reply to a SMBgetattrE.
9635 ****************************************************************************/
9637 void reply_getattrE(struct smb_request *req)
9639 connection_struct *conn = req->conn;
9642 struct timespec create_ts;
9645 START_PROFILE(SMBgetattrE);
9648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9649 END_PROFILE(SMBgetattrE);
9653 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9655 if(!fsp || (fsp->conn != conn)) {
9656 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9657 END_PROFILE(SMBgetattrE);
9661 /* Do an fstat on this file */
9662 status = vfs_stat_fsp(fsp);
9663 if (!NT_STATUS_IS_OK(status)) {
9664 reply_nterror(req, status);
9665 END_PROFILE(SMBgetattrE);
9669 mode = dos_mode(conn, fsp->fsp_name);
9672 * Convert the times into dos times. Set create
9673 * date to be last modify date as UNIX doesn't save
9677 reply_outbuf(req, 11, 0);
9679 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9680 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9681 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9682 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9683 /* Should we check pending modtime here ? JRA */
9684 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9685 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9687 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9688 SIVAL(req->outbuf, smb_vwv6, 0);
9689 SIVAL(req->outbuf, smb_vwv8, 0);
9691 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9692 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9693 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9695 SSVAL(req->outbuf,smb_vwv10, mode);
9697 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9699 END_PROFILE(SMBgetattrE);