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 TALLOC_CTX *ctx = talloc_tos();
2178 struct smbd_server_connection *sconn = req->sconn;
2179 files_struct *fsp = NULL;
2181 START_PROFILE(SMBfclose);
2183 if (req->posix_pathnames) {
2184 reply_unknown_new(req, req->cmd);
2185 END_PROFILE(SMBfclose);
2189 p = (const char *)req->buf + 1;
2190 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
2192 if (!NT_STATUS_IS_OK(err)) {
2193 reply_nterror(req, err);
2194 END_PROFILE(SMBfclose);
2198 if (smbreq_bufrem(req, p) < 3) {
2199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2200 END_PROFILE(SMBfclose);
2205 status_len = SVAL(p,0);
2208 if (status_len == 0) {
2209 reply_force_doserror(req, ERRSRV, ERRsrverror);
2210 END_PROFILE(SMBfclose);
2214 if (smbreq_bufrem(req, p) < 21) {
2215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2216 END_PROFILE(SMBfclose);
2220 memcpy(status,p,21);
2222 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2224 /* Close the file - we know it's gone */
2225 close_file(NULL, fsp, NORMAL_CLOSE);
2230 reply_outbuf(req, 1, 0);
2231 SSVAL(req->outbuf,smb_vwv0,0);
2233 DEBUG(3,("search close\n"));
2235 END_PROFILE(SMBfclose);
2239 /****************************************************************************
2241 ****************************************************************************/
2243 void reply_open(struct smb_request *req)
2245 connection_struct *conn = req->conn;
2246 struct smb_filename *smb_fname = NULL;
2256 uint32_t access_mask;
2257 uint32_t share_mode;
2258 uint32_t create_disposition;
2259 uint32_t create_options = 0;
2260 uint32_t private_flags = 0;
2263 TALLOC_CTX *ctx = talloc_tos();
2265 START_PROFILE(SMBopen);
2268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2272 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2273 deny_mode = SVAL(req->vwv+0, 0);
2274 dos_attr = SVAL(req->vwv+1, 0);
2276 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2277 STR_TERMINATE, &status);
2278 if (!NT_STATUS_IS_OK(status)) {
2279 reply_nterror(req, status);
2283 if (!map_open_params_to_ntcreate(fname, deny_mode,
2284 OPENX_FILE_EXISTS_OPEN, &access_mask,
2285 &share_mode, &create_disposition,
2286 &create_options, &private_flags)) {
2287 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2291 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2293 status = filename_convert(ctx,
2300 if (!NT_STATUS_IS_OK(status)) {
2301 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2302 reply_botherror(req,
2303 NT_STATUS_PATH_NOT_COVERED,
2304 ERRSRV, ERRbadpath);
2307 reply_nterror(req, status);
2311 status = SMB_VFS_CREATE_FILE(
2314 &conn->cwd_fsp, /* dirfsp */
2315 smb_fname, /* fname */
2316 access_mask, /* access_mask */
2317 share_mode, /* share_access */
2318 create_disposition, /* create_disposition*/
2319 create_options, /* create_options */
2320 dos_attr, /* file_attributes */
2321 oplock_request, /* oplock_request */
2323 0, /* allocation_size */
2329 NULL, NULL); /* create context */
2331 if (!NT_STATUS_IS_OK(status)) {
2332 if (open_was_deferred(req->xconn, req->mid)) {
2333 /* We have re-scheduled this call. */
2337 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2338 reply_openerror(req, status);
2342 fsp = fcb_or_dos_open(
2349 bool ok = defer_smb1_sharing_violation(req);
2353 reply_openerror(req, status);
2358 /* Ensure we're pointing at the correct stat struct. */
2359 TALLOC_FREE(smb_fname);
2360 smb_fname = fsp->fsp_name;
2362 size = smb_fname->st.st_ex_size;
2363 fattr = dos_mode(conn, smb_fname);
2365 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2367 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2368 DEBUG(3,("attempt to open a directory %s\n",
2370 close_file(req, fsp, ERROR_CLOSE);
2371 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2372 ERRDOS, ERRnoaccess);
2376 reply_outbuf(req, 7, 0);
2377 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2378 SSVAL(req->outbuf,smb_vwv1,fattr);
2379 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2380 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2382 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2384 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2385 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2387 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2388 SCVAL(req->outbuf,smb_flg,
2389 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2392 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2393 SCVAL(req->outbuf,smb_flg,
2394 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2397 END_PROFILE(SMBopen);
2401 /****************************************************************************
2402 Reply to an open and X.
2403 ****************************************************************************/
2405 void reply_open_and_X(struct smb_request *req)
2407 connection_struct *conn = req->conn;
2408 struct smb_filename *smb_fname = NULL;
2410 uint16_t open_flags;
2413 /* Breakout the oplock request bits so we can set the
2414 reply bits separately. */
2415 int ex_oplock_request;
2416 int core_oplock_request;
2419 int smb_sattr = SVAL(req->vwv+4, 0);
2420 uint32_t smb_time = make_unix_date3(req->vwv+6);
2428 uint64_t allocation_size;
2429 ssize_t retval = -1;
2430 uint32_t access_mask;
2431 uint32_t share_mode;
2432 uint32_t create_disposition;
2433 uint32_t create_options = 0;
2434 uint32_t private_flags = 0;
2436 TALLOC_CTX *ctx = talloc_tos();
2438 START_PROFILE(SMBopenX);
2440 if (req->wct < 15) {
2441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2445 open_flags = SVAL(req->vwv+2, 0);
2446 deny_mode = SVAL(req->vwv+3, 0);
2447 smb_attr = SVAL(req->vwv+5, 0);
2448 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2449 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2450 oplock_request = ex_oplock_request | core_oplock_request;
2451 smb_ofun = SVAL(req->vwv+8, 0);
2452 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2454 /* If it's an IPC, pass off the pipe handler. */
2456 if (lp_nt_pipe_support()) {
2457 reply_open_pipe_and_X(conn, req);
2459 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2464 /* XXXX we need to handle passed times, sattr and flags */
2465 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2466 STR_TERMINATE, &status);
2467 if (!NT_STATUS_IS_OK(status)) {
2468 reply_nterror(req, status);
2472 if (!map_open_params_to_ntcreate(fname, deny_mode,
2474 &access_mask, &share_mode,
2475 &create_disposition,
2478 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2482 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2484 status = filename_convert(ctx,
2491 if (!NT_STATUS_IS_OK(status)) {
2492 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2493 reply_botherror(req,
2494 NT_STATUS_PATH_NOT_COVERED,
2495 ERRSRV, ERRbadpath);
2498 reply_nterror(req, status);
2502 status = SMB_VFS_CREATE_FILE(
2505 &conn->cwd_fsp, /* dirfsp */
2506 smb_fname, /* fname */
2507 access_mask, /* access_mask */
2508 share_mode, /* share_access */
2509 create_disposition, /* create_disposition*/
2510 create_options, /* create_options */
2511 smb_attr, /* file_attributes */
2512 oplock_request, /* oplock_request */
2514 0, /* allocation_size */
2519 &smb_action, /* pinfo */
2520 NULL, NULL); /* create context */
2522 if (!NT_STATUS_IS_OK(status)) {
2523 if (open_was_deferred(req->xconn, req->mid)) {
2524 /* We have re-scheduled this call. */
2528 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2529 reply_openerror(req, status);
2533 fsp = fcb_or_dos_open(
2540 bool ok = defer_smb1_sharing_violation(req);
2544 reply_openerror(req, status);
2549 smb_action = FILE_WAS_OPENED;
2552 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2553 if the file is truncated or created. */
2554 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2555 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2556 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2557 close_file(req, fsp, ERROR_CLOSE);
2558 reply_nterror(req, NT_STATUS_DISK_FULL);
2561 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2563 close_file(req, fsp, ERROR_CLOSE);
2564 reply_nterror(req, NT_STATUS_DISK_FULL);
2567 status = vfs_stat_fsp(fsp);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 close_file(req, fsp, ERROR_CLOSE);
2570 reply_nterror(req, status);
2575 fattr = dos_mode(conn, fsp->fsp_name);
2576 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2577 close_file(req, fsp, ERROR_CLOSE);
2578 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2581 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2583 /* If the caller set the extended oplock request bit
2584 and we granted one (by whatever means) - set the
2585 correct bit for extended oplock reply.
2588 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2589 smb_action |= EXTENDED_OPLOCK_GRANTED;
2592 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2593 smb_action |= EXTENDED_OPLOCK_GRANTED;
2596 /* If the caller set the core oplock request bit
2597 and we granted one (by whatever means) - set the
2598 correct bit for core oplock reply.
2601 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2602 reply_outbuf(req, 19, 0);
2604 reply_outbuf(req, 15, 0);
2607 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2608 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2610 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2611 SCVAL(req->outbuf, smb_flg,
2612 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2615 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2616 SCVAL(req->outbuf, smb_flg,
2617 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2620 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2621 SSVAL(req->outbuf,smb_vwv3,fattr);
2622 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2623 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2625 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2627 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2628 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2629 SSVAL(req->outbuf,smb_vwv11,smb_action);
2631 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2632 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2636 TALLOC_FREE(smb_fname);
2637 END_PROFILE(SMBopenX);
2641 /****************************************************************************
2642 Reply to a SMBulogoffX.
2643 ****************************************************************************/
2645 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2646 struct smbXsrv_session *session);
2647 static void reply_ulogoffX_done(struct tevent_req *req);
2649 void reply_ulogoffX(struct smb_request *smb1req)
2651 struct timeval now = timeval_current();
2652 struct smbXsrv_session *session = NULL;
2653 struct tevent_req *req;
2657 * Don't setup the profile charge here, take
2658 * it in reply_ulogoffX_done(). Not strictly correct
2659 * but better than the other SMB1 async
2660 * code that double-charges at the moment.
2663 status = smb1srv_session_lookup(smb1req->xconn,
2665 timeval_to_nttime(&now),
2667 if (!NT_STATUS_IS_OK(status)) {
2668 /* Not going async, profile here. */
2669 START_PROFILE(SMBulogoffX);
2670 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2671 (unsigned long long)smb1req->vuid);
2673 smb1req->vuid = UID_FIELD_INVALID;
2674 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2675 END_PROFILE(SMBulogoffX);
2679 req = reply_ulogoffX_send(smb1req, session);
2681 /* Not going async, profile here. */
2682 START_PROFILE(SMBulogoffX);
2683 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2684 END_PROFILE(SMBulogoffX);
2688 /* We're async. This will complete later. */
2689 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2693 struct reply_ulogoffX_state {
2694 struct tevent_queue *wait_queue;
2695 struct smbXsrv_session *session;
2698 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2700 /****************************************************************************
2701 Async SMB1 ulogoffX.
2702 Note, on failure here we deallocate and return NULL to allow the caller to
2703 SMB1 return an error of ERRnomem immediately.
2704 ****************************************************************************/
2706 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2707 struct smbXsrv_session *session)
2709 struct tevent_req *req;
2710 struct reply_ulogoffX_state *state;
2711 struct tevent_req *subreq;
2713 struct smbd_server_connection *sconn = session->client->sconn;
2714 uint64_t vuid = session->global->session_wire_id;
2716 req = tevent_req_create(smb1req, &state,
2717 struct reply_ulogoffX_state);
2721 state->wait_queue = tevent_queue_create(state,
2722 "reply_ulogoffX_wait_queue");
2723 if (tevent_req_nomem(state->wait_queue, req)) {
2727 state->session = session;
2730 * Make sure that no new request will be able to use this session.
2731 * This ensures that once all outstanding fsp->aio_requests
2732 * on this session are done, we are safe to close it.
2734 session->status = NT_STATUS_USER_SESSION_DELETED;
2736 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2737 if (fsp->vuid != vuid) {
2741 * Flag the file as close in progress.
2742 * This will prevent any more IO being
2745 fsp->fsp_flags.closing = true;
2747 if (fsp->num_aio_requests > 0) {
2749 * Now wait until all aio requests on this fsp are
2752 * We don't set a callback, as we just want to block the
2753 * wait queue and the talloc_free() of fsp->aio_request
2754 * will remove the item from the wait queue.
2756 subreq = tevent_queue_wait_send(fsp->aio_requests,
2759 if (tevent_req_nomem(subreq, req)) {
2767 * Now we add our own waiter to the end of the queue,
2768 * this way we get notified when all pending requests are finished
2769 * and reply to the outstanding SMB1 request.
2771 subreq = tevent_queue_wait_send(state,
2774 if (tevent_req_nomem(subreq, req)) {
2780 * We're really going async - move the SMB1 request from
2781 * a talloc stackframe above us to the sconn talloc-context.
2782 * We need this to stick around until the wait_done
2783 * callback is invoked.
2785 smb1req = talloc_move(sconn, &smb1req);
2787 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2792 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2794 struct tevent_req *req = tevent_req_callback_data(
2795 subreq, struct tevent_req);
2797 tevent_queue_wait_recv(subreq);
2798 TALLOC_FREE(subreq);
2799 tevent_req_done(req);
2802 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2804 return tevent_req_simple_recv_ntstatus(req);
2807 static void reply_ulogoffX_done(struct tevent_req *req)
2809 struct smb_request *smb1req = tevent_req_callback_data(
2810 req, struct smb_request);
2811 struct reply_ulogoffX_state *state = tevent_req_data(req,
2812 struct reply_ulogoffX_state);
2813 struct smbXsrv_session *session = state->session;
2817 * Take the profile charge here. Not strictly
2818 * correct but better than the other SMB1 async
2819 * code that double-charges at the moment.
2821 START_PROFILE(SMBulogoffX);
2823 status = reply_ulogoffX_recv(req);
2825 if (!NT_STATUS_IS_OK(status)) {
2826 TALLOC_FREE(smb1req);
2827 END_PROFILE(SMBulogoffX);
2828 exit_server(__location__ ": reply_ulogoffX_recv failed");
2832 status = smbXsrv_session_logoff(session);
2833 if (!NT_STATUS_IS_OK(status)) {
2834 TALLOC_FREE(smb1req);
2835 END_PROFILE(SMBulogoffX);
2836 exit_server(__location__ ": smbXsrv_session_logoff failed");
2840 TALLOC_FREE(session);
2842 reply_outbuf(smb1req, 2, 0);
2843 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2844 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2846 DBG_NOTICE("ulogoffX vuid=%llu\n",
2847 (unsigned long long)smb1req->vuid);
2849 smb1req->vuid = UID_FIELD_INVALID;
2851 * The following call is needed to push the
2852 * reply data back out the socket after async
2853 * return. Plus it frees smb1req.
2855 smb_request_done(smb1req);
2856 END_PROFILE(SMBulogoffX);
2859 /****************************************************************************
2860 Reply to a mknew or a create.
2861 ****************************************************************************/
2863 void reply_mknew(struct smb_request *req)
2865 connection_struct *conn = req->conn;
2866 struct smb_filename *smb_fname = NULL;
2869 struct smb_file_time ft;
2871 int oplock_request = 0;
2873 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2874 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2875 uint32_t create_disposition;
2876 uint32_t create_options = 0;
2878 TALLOC_CTX *ctx = talloc_tos();
2880 START_PROFILE(SMBcreate);
2881 init_smb_file_time(&ft);
2884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2888 fattr = SVAL(req->vwv+0, 0);
2889 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2891 if (req->cmd == SMBmknew) {
2892 /* We should fail if file exists. */
2893 create_disposition = FILE_CREATE;
2895 /* Create if file doesn't exist, truncate if it does. */
2896 create_disposition = FILE_OVERWRITE_IF;
2900 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2902 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2903 STR_TERMINATE, &status);
2904 if (!NT_STATUS_IS_OK(status)) {
2905 reply_nterror(req, status);
2909 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2910 status = filename_convert(ctx,
2917 if (!NT_STATUS_IS_OK(status)) {
2918 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2919 reply_botherror(req,
2920 NT_STATUS_PATH_NOT_COVERED,
2921 ERRSRV, ERRbadpath);
2924 reply_nterror(req, status);
2928 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2929 DEBUG(0,("Attempt to create file (%s) with volid set - "
2930 "please report this\n",
2931 smb_fname_str_dbg(smb_fname)));
2934 status = SMB_VFS_CREATE_FILE(
2937 &conn->cwd_fsp, /* dirfsp */
2938 smb_fname, /* fname */
2939 access_mask, /* access_mask */
2940 share_mode, /* share_access */
2941 create_disposition, /* create_disposition*/
2942 create_options, /* create_options */
2943 fattr, /* file_attributes */
2944 oplock_request, /* oplock_request */
2946 0, /* allocation_size */
2947 0, /* private_flags */
2952 NULL, NULL); /* create context */
2954 if (!NT_STATUS_IS_OK(status)) {
2955 if (open_was_deferred(req->xconn, req->mid)) {
2956 /* We have re-scheduled this call. */
2959 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2960 bool ok = defer_smb1_sharing_violation(req);
2965 reply_openerror(req, status);
2969 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2970 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2971 if (!NT_STATUS_IS_OK(status)) {
2972 END_PROFILE(SMBcreate);
2976 reply_outbuf(req, 1, 0);
2977 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2979 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2980 SCVAL(req->outbuf,smb_flg,
2981 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2984 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2985 SCVAL(req->outbuf,smb_flg,
2986 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2989 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2990 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2991 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2992 (unsigned int)fattr));
2995 TALLOC_FREE(smb_fname);
2996 END_PROFILE(SMBcreate);
3000 /****************************************************************************
3001 Reply to a create temporary file.
3002 ****************************************************************************/
3004 void reply_ctemp(struct smb_request *req)
3006 connection_struct *conn = req->conn;
3007 struct smb_filename *smb_fname = NULL;
3008 char *wire_name = NULL;
3017 TALLOC_CTX *ctx = talloc_tos();
3019 START_PROFILE(SMBctemp);
3022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3026 fattr = SVAL(req->vwv+0, 0);
3027 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
3029 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
3030 STR_TERMINATE, &status);
3031 if (!NT_STATUS_IS_OK(status)) {
3032 reply_nterror(req, status);
3036 for (i = 0; i < 10; i++) {
3038 fname = talloc_asprintf(ctx,
3041 generate_random_str_list(ctx, 5, "0123456789"));
3043 fname = talloc_asprintf(ctx,
3045 generate_random_str_list(ctx, 5, "0123456789"));
3049 reply_nterror(req, NT_STATUS_NO_MEMORY);
3053 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
3054 status = filename_convert(ctx, conn,
3060 if (!NT_STATUS_IS_OK(status)) {
3061 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3062 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3063 ERRSRV, ERRbadpath);
3066 reply_nterror(req, status);
3070 /* Create the file. */
3071 status = SMB_VFS_CREATE_FILE(
3074 &conn->cwd_fsp, /* dirfsp */
3075 smb_fname, /* fname */
3076 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
3077 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
3078 FILE_CREATE, /* create_disposition*/
3079 0, /* create_options */
3080 fattr, /* file_attributes */
3081 oplock_request, /* oplock_request */
3083 0, /* allocation_size */
3084 0, /* private_flags */
3089 NULL, NULL); /* create context */
3091 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3093 TALLOC_FREE(smb_fname);
3097 if (!NT_STATUS_IS_OK(status)) {
3098 if (open_was_deferred(req->xconn, req->mid)) {
3099 /* We have re-scheduled this call. */
3102 if (NT_STATUS_EQUAL(
3103 status, NT_STATUS_SHARING_VIOLATION)) {
3104 bool ok = defer_smb1_sharing_violation(req);
3109 reply_openerror(req, status);
3117 /* Collision after 10 times... */
3118 reply_nterror(req, status);
3122 reply_outbuf(req, 1, 0);
3123 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3125 /* the returned filename is relative to the directory */
3126 s = strrchr_m(fsp->fsp_name->base_name, '/');
3128 s = fsp->fsp_name->base_name;
3134 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3135 thing in the byte section. JRA */
3136 SSVALS(p, 0, -1); /* what is this? not in spec */
3138 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3140 reply_nterror(req, NT_STATUS_NO_MEMORY);
3144 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3145 SCVAL(req->outbuf, smb_flg,
3146 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3149 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3150 SCVAL(req->outbuf, smb_flg,
3151 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3154 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3155 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3156 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
3158 TALLOC_FREE(smb_fname);
3159 TALLOC_FREE(wire_name);
3160 END_PROFILE(SMBctemp);
3164 /*******************************************************************
3165 Check if a user is allowed to rename a file.
3166 ********************************************************************/
3168 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3171 if (!CAN_WRITE(conn)) {
3172 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3175 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3176 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3177 /* Only bother to read the DOS attribute if we might deny the
3178 rename on the grounds of attribute mismatch. */
3179 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3180 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3181 return NT_STATUS_NO_SUCH_FILE;
3185 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3186 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3187 return NT_STATUS_OK;
3190 /* If no pathnames are open below this
3191 directory, allow the rename. */
3193 if (lp_strict_rename(SNUM(conn))) {
3195 * Strict rename, check open file db.
3197 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3198 return NT_STATUS_ACCESS_DENIED;
3200 } else if (file_find_subpath(fsp)) {
3202 * No strict rename, just look in local process.
3204 return NT_STATUS_ACCESS_DENIED;
3206 return NT_STATUS_OK;
3209 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3210 return NT_STATUS_OK;
3213 return NT_STATUS_ACCESS_DENIED;
3216 /*******************************************************************
3217 * unlink a file with all relevant access checks
3218 *******************************************************************/
3220 static NTSTATUS do_unlink(connection_struct *conn,
3221 struct smb_request *req,
3222 struct smb_filename *smb_fname,
3227 uint32_t dirtype_orig = dirtype;
3230 bool posix_paths = (req != NULL && req->posix_pathnames);
3231 struct smb2_create_blobs *posx = NULL;
3233 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3234 smb_fname_str_dbg(smb_fname),
3237 if (!CAN_WRITE(conn)) {
3238 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3242 ret = SMB_VFS_LSTAT(conn, smb_fname);
3244 ret = SMB_VFS_STAT(conn, smb_fname);
3247 return map_nt_error_from_unix(errno);
3250 fattr = dos_mode(conn, smb_fname);
3252 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3253 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3256 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3258 return NT_STATUS_NO_SUCH_FILE;
3261 if (!dir_check_ftype(fattr, dirtype)) {
3262 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3263 return NT_STATUS_FILE_IS_A_DIRECTORY;
3265 return NT_STATUS_NO_SUCH_FILE;
3268 if (dirtype_orig & 0x8000) {
3269 /* These will never be set for POSIX. */
3270 return NT_STATUS_NO_SUCH_FILE;
3274 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3275 return NT_STATUS_FILE_IS_A_DIRECTORY;
3278 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3279 return NT_STATUS_NO_SUCH_FILE;
3282 if (dirtype & 0xFF00) {
3283 /* These will never be set for POSIX. */
3284 return NT_STATUS_NO_SUCH_FILE;
3289 return NT_STATUS_NO_SUCH_FILE;
3292 /* Can't delete a directory. */
3293 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3294 return NT_STATUS_FILE_IS_A_DIRECTORY;
3299 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3300 return NT_STATUS_OBJECT_NAME_INVALID;
3301 #endif /* JRATEST */
3304 status = make_smb2_posix_create_ctx(
3305 talloc_tos(), &posx, 0777);
3306 if (!NT_STATUS_IS_OK(status)) {
3307 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3313 /* On open checks the open itself will check the share mode, so
3314 don't do it here as we'll get it wrong. */
3316 status = SMB_VFS_CREATE_FILE
3319 &conn->cwd_fsp, /* dirfsp */
3320 smb_fname, /* fname */
3321 DELETE_ACCESS, /* access_mask */
3322 FILE_SHARE_NONE, /* share_access */
3323 FILE_OPEN, /* create_disposition*/
3324 FILE_NON_DIRECTORY_FILE, /* create_options */
3325 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3326 0, /* oplock_request */
3328 0, /* allocation_size */
3329 0, /* private_flags */
3334 posx, /* in_context_blobs */
3335 NULL); /* out_context_blobs */
3339 if (!NT_STATUS_IS_OK(status)) {
3340 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3341 nt_errstr(status)));
3345 status = can_set_delete_on_close(fsp, fattr);
3346 if (!NT_STATUS_IS_OK(status)) {
3347 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3349 smb_fname_str_dbg(smb_fname),
3350 nt_errstr(status)));
3351 close_file(req, fsp, NORMAL_CLOSE);
3355 /* The set is across all open files on this dev/inode pair. */
3356 if (!set_delete_on_close(fsp, True,
3357 conn->session_info->security_token,
3358 conn->session_info->unix_token)) {
3359 close_file(req, fsp, NORMAL_CLOSE);
3360 return NT_STATUS_ACCESS_DENIED;
3363 return close_file(req, fsp, NORMAL_CLOSE);
3366 /****************************************************************************
3367 The guts of the unlink command, split out so it may be called by the NT SMB
3369 ****************************************************************************/
3371 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3372 uint32_t dirtype, struct smb_filename *smb_fname)
3374 char *fname_dir = NULL;
3375 char *fname_mask = NULL;
3377 NTSTATUS status = NT_STATUS_OK;
3378 struct smb_filename *smb_fname_dir = NULL;
3379 bool has_wild = false;
3380 TALLOC_CTX *ctx = talloc_tos();
3382 /* Split up the directory from the filename/mask. */
3383 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3384 &fname_dir, &fname_mask);
3385 if (!NT_STATUS_IS_OK(status)) {
3389 if (req != NULL && !req->posix_pathnames) {
3391 * Check the wildcard mask *before*
3392 * unmangling. As mangling is done
3393 * for names that can't be returned
3394 * to Windows the unmangled name may
3395 * contain Windows wildcard characters.
3397 has_wild = ms_has_wild(fname_mask);
3401 * We should only check the mangled cache
3402 * here if unix_convert failed. This means
3403 * that the path in 'mask' doesn't exist
3404 * on the file system and so we need to look
3405 * for a possible mangle. This patch from
3406 * Tine Smukavec <valentin.smukavec@hermes.si>.
3409 if (!VALID_STAT(smb_fname->st) &&
3410 mangle_is_mangled(fname_mask, conn->params)) {
3411 char *new_mask = NULL;
3412 mangle_lookup_name_from_8_3(ctx, fname_mask,
3413 &new_mask, conn->params);
3415 TALLOC_FREE(fname_mask);
3416 fname_mask = new_mask;
3423 * Only one file needs to be unlinked. Append the mask back
3424 * onto the directory.
3426 TALLOC_FREE(smb_fname->base_name);
3427 if (ISDOT(fname_dir)) {
3428 /* Ensure we use canonical names on open. */
3429 smb_fname->base_name = talloc_asprintf(smb_fname,
3433 smb_fname->base_name = talloc_asprintf(smb_fname,
3438 if (!smb_fname->base_name) {
3439 status = NT_STATUS_NO_MEMORY;
3443 dirtype = FILE_ATTRIBUTE_NORMAL;
3446 status = check_name(conn, smb_fname);
3447 if (!NT_STATUS_IS_OK(status)) {
3451 status = do_unlink(conn, req, smb_fname, dirtype);
3452 if (!NT_STATUS_IS_OK(status)) {
3458 struct smb_Dir *dir_hnd = NULL;
3460 const char *dname = NULL;
3461 char *talloced = NULL;
3463 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3464 status = NT_STATUS_OBJECT_NAME_INVALID;
3468 dirtype = FILE_ATTRIBUTE_NORMAL;
3471 if (strequal(fname_mask,"????????.???")) {
3472 TALLOC_FREE(fname_mask);
3473 fname_mask = talloc_strdup(ctx, "*");
3475 status = NT_STATUS_NO_MEMORY;
3480 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3486 if (smb_fname_dir == NULL) {
3487 status = NT_STATUS_NO_MEMORY;
3491 status = check_name(conn, smb_fname_dir);
3492 if (!NT_STATUS_IS_OK(status)) {
3496 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3498 if (dir_hnd == NULL) {
3499 status = map_nt_error_from_unix(errno);
3503 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3504 the pattern matches against the long name, otherwise the short name
3505 We don't implement this yet XXXX
3508 status = NT_STATUS_NO_SUCH_FILE;
3510 while ((dname = ReadDirName(dir_hnd, &offset,
3511 &smb_fname->st, &talloced))) {
3512 TALLOC_CTX *frame = talloc_stackframe();
3514 struct smb_filename *f = NULL;
3516 if (!is_visible_file(conn,
3522 TALLOC_FREE(talloced);
3526 /* Quick check for "." and ".." */
3527 if (ISDOT(dname) || ISDOTDOT(dname)) {
3529 TALLOC_FREE(talloced);
3533 if(!mask_match(dname, fname_mask,
3534 conn->case_sensitive)) {
3536 TALLOC_FREE(talloced);
3540 if (ISDOT(fname_dir)) {
3541 /* Ensure we use canonical names on open. */
3542 p = talloc_asprintf(smb_fname, "%s", dname);
3544 p = talloc_asprintf(smb_fname, "%s/%s",
3548 TALLOC_FREE(dir_hnd);
3549 status = NT_STATUS_NO_MEMORY;
3551 TALLOC_FREE(talloced);
3554 f = synthetic_smb_fname(frame,
3561 TALLOC_FREE(dir_hnd);
3562 status = NT_STATUS_NO_MEMORY;
3564 TALLOC_FREE(talloced);
3568 status = check_name(conn, f);
3569 if (!NT_STATUS_IS_OK(status)) {
3570 TALLOC_FREE(dir_hnd);
3572 TALLOC_FREE(talloced);
3576 status = do_unlink(conn, req, f, dirtype);
3577 if (!NT_STATUS_IS_OK(status)) {
3578 TALLOC_FREE(dir_hnd);
3580 TALLOC_FREE(talloced);
3585 DBG_DEBUG("successful unlink [%s]\n",
3586 smb_fname_str_dbg(f));
3589 TALLOC_FREE(talloced);
3591 TALLOC_FREE(dir_hnd);
3594 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3595 status = map_nt_error_from_unix(errno);
3599 TALLOC_FREE(smb_fname_dir);
3600 TALLOC_FREE(fname_dir);
3601 TALLOC_FREE(fname_mask);
3605 /****************************************************************************
3607 ****************************************************************************/
3609 void reply_unlink(struct smb_request *req)
3611 connection_struct *conn = req->conn;
3613 struct smb_filename *smb_fname = NULL;
3616 bool path_contains_wcard = False;
3617 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3618 ucf_flags_from_smb_request(req);
3619 TALLOC_CTX *ctx = talloc_tos();
3621 START_PROFILE(SMBunlink);
3624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3628 dirtype = SVAL(req->vwv+0, 0);
3630 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3631 STR_TERMINATE, &status,
3632 &path_contains_wcard);
3633 if (!NT_STATUS_IS_OK(status)) {
3634 reply_nterror(req, status);
3638 status = filename_convert(ctx, conn,
3642 &path_contains_wcard,
3644 if (!NT_STATUS_IS_OK(status)) {
3645 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3646 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3647 ERRSRV, ERRbadpath);
3650 reply_nterror(req, status);
3654 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3656 status = unlink_internals(conn, req, dirtype, smb_fname);
3657 if (!NT_STATUS_IS_OK(status)) {
3658 if (open_was_deferred(req->xconn, req->mid)) {
3659 /* We have re-scheduled this call. */
3662 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3663 bool ok = defer_smb1_sharing_violation(req);
3668 reply_nterror(req, status);
3672 reply_outbuf(req, 0, 0);
3674 TALLOC_FREE(smb_fname);
3675 END_PROFILE(SMBunlink);
3679 /****************************************************************************
3681 ****************************************************************************/
3683 static void fail_readraw(void)
3685 const char *errstr = talloc_asprintf(talloc_tos(),
3686 "FAIL ! reply_readbraw: socket write fail (%s)",
3691 exit_server_cleanly(errstr);
3694 /****************************************************************************
3695 Fake (read/write) sendfile. Returns -1 on read or write fail.
3696 ****************************************************************************/
3698 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3699 off_t startpos, size_t nread)
3702 size_t tosend = nread;
3709 bufsize = MIN(nread, 65536);
3711 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3715 while (tosend > 0) {
3719 cur_read = MIN(tosend, bufsize);
3720 ret = read_file(fsp,buf,startpos,cur_read);
3726 /* If we had a short read, fill with zeros. */
3727 if (ret < cur_read) {
3728 memset(buf + ret, '\0', cur_read - ret);
3731 ret = write_data(xconn->transport.sock, buf, cur_read);
3732 if (ret != cur_read) {
3733 int saved_errno = errno;
3735 * Try and give an error message saying what
3738 DEBUG(0, ("write_data failed for client %s. "
3740 smbXsrv_connection_dbg(xconn),
3741 strerror(saved_errno)));
3743 errno = saved_errno;
3747 startpos += cur_read;
3751 return (ssize_t)nread;
3754 /****************************************************************************
3755 Deal with the case of sendfile reading less bytes from the file than
3756 requested. Fill with zeros (all we can do). Returns 0 on success
3757 ****************************************************************************/
3759 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3765 #define SHORT_SEND_BUFSIZE 1024
3766 if (nread < headersize) {
3767 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3768 "header for file %s (%s). Terminating\n",
3769 fsp_str_dbg(fsp), strerror(errno)));
3773 nread -= headersize;
3775 if (nread < smb_maxcnt) {
3776 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3778 DEBUG(0,("sendfile_short_send: malloc failed "
3779 "for file %s (%s). Terminating\n",
3780 fsp_str_dbg(fsp), strerror(errno)));
3784 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3785 "with zeros !\n", fsp_str_dbg(fsp)));
3787 while (nread < smb_maxcnt) {
3789 * We asked for the real file size and told sendfile
3790 * to not go beyond the end of the file. But it can
3791 * happen that in between our fstat call and the
3792 * sendfile call the file was truncated. This is very
3793 * bad because we have already announced the larger
3794 * number of bytes to the client.
3796 * The best we can do now is to send 0-bytes, just as
3797 * a read from a hole in a sparse file would do.
3799 * This should happen rarely enough that I don't care
3800 * about efficiency here :-)
3805 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3806 ret = write_data(xconn->transport.sock, buf, to_write);
3807 if (ret != to_write) {
3808 int saved_errno = errno;
3810 * Try and give an error message saying what
3813 DEBUG(0, ("write_data failed for client %s. "
3815 smbXsrv_connection_dbg(xconn),
3816 strerror(saved_errno)));
3817 errno = saved_errno;
3828 /****************************************************************************
3829 Return a readbraw error (4 bytes of zero).
3830 ****************************************************************************/
3832 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3838 smbd_lock_socket(xconn);
3839 if (write_data(xconn->transport.sock,header,4) != 4) {
3840 int saved_errno = errno;
3842 * Try and give an error message saying what
3845 DEBUG(0, ("write_data failed for client %s. "
3847 smbXsrv_connection_dbg(xconn),
3848 strerror(saved_errno)));
3849 errno = saved_errno;
3853 smbd_unlock_socket(xconn);
3856 /*******************************************************************
3857 Ensure we don't use sendfile if server smb signing is active.
3858 ********************************************************************/
3860 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3862 bool sign_active = false;
3864 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3865 if (get_Protocol() < PROTOCOL_NT1) {
3868 if (signing_state) {
3869 sign_active = smb_signing_is_active(signing_state);
3871 return (lp__use_sendfile(snum) &&
3872 (get_remote_arch() != RA_WIN95) &&
3875 /****************************************************************************
3876 Use sendfile in readbraw.
3877 ****************************************************************************/
3879 static void send_file_readbraw(connection_struct *conn,
3880 struct smb_request *req,
3886 struct smbXsrv_connection *xconn = req->xconn;
3887 char *outbuf = NULL;
3891 * We can only use sendfile on a non-chained packet
3892 * but we can use on a non-oplocked file. tridge proved this
3893 * on a train in Germany :-). JRA.
3894 * reply_readbraw has already checked the length.
3897 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3898 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3899 ssize_t sendfile_read = -1;
3901 DATA_BLOB header_blob;
3903 _smb_setlen(header,nread);
3904 header_blob = data_blob_const(header, 4);
3906 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3907 &header_blob, startpos,
3909 if (sendfile_read == -1) {
3910 /* Returning ENOSYS means no data at all was sent.
3911 * Do this as a normal read. */
3912 if (errno == ENOSYS) {
3913 goto normal_readbraw;
3917 * Special hack for broken Linux with no working sendfile. If we
3918 * return EINTR we sent the header but not the rest of the data.
3919 * Fake this up by doing read/write calls.
3921 if (errno == EINTR) {
3922 /* Ensure we don't do this again. */
3923 set_use_sendfile(SNUM(conn), False);
3924 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3926 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3927 DEBUG(0,("send_file_readbraw: "
3928 "fake_sendfile failed for "
3932 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3937 DEBUG(0,("send_file_readbraw: sendfile failed for "
3938 "file %s (%s). Terminating\n",
3939 fsp_str_dbg(fsp), strerror(errno)));
3940 exit_server_cleanly("send_file_readbraw sendfile failed");
3941 } else if (sendfile_read == 0) {
3943 * Some sendfile implementations return 0 to indicate
3944 * that there was a short read, but nothing was
3945 * actually written to the socket. In this case,
3946 * fallback to the normal read path so the header gets
3947 * the correct byte count.
3949 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3950 "bytes falling back to the normal read: "
3951 "%s\n", fsp_str_dbg(fsp)));
3952 goto normal_readbraw;
3955 /* Deal with possible short send. */
3956 if (sendfile_read != 4+nread) {
3957 ret = sendfile_short_send(xconn, fsp,
3958 sendfile_read, 4, nread);
3968 outbuf = talloc_array(NULL, char, nread+4);
3970 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3971 (unsigned)(nread+4)));
3972 reply_readbraw_error(xconn);
3977 ret = read_file(fsp,outbuf+4,startpos,nread);
3978 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3987 _smb_setlen(outbuf,ret);
3988 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3989 int saved_errno = errno;
3991 * Try and give an error message saying what
3994 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3995 smbXsrv_connection_dbg(xconn),
3996 strerror(saved_errno)));
3997 errno = saved_errno;
4002 TALLOC_FREE(outbuf);
4005 /****************************************************************************
4006 Reply to a readbraw (core+ protocol).
4007 ****************************************************************************/
4009 void reply_readbraw(struct smb_request *req)
4011 connection_struct *conn = req->conn;
4012 struct smbXsrv_connection *xconn = req->xconn;
4013 ssize_t maxcount,mincount;
4017 struct lock_struct lock;
4021 START_PROFILE(SMBreadbraw);
4023 if (srv_is_signing_active(xconn) || req->encrypted) {
4024 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
4025 "raw reads/writes are disallowed.");
4029 reply_readbraw_error(xconn);
4030 END_PROFILE(SMBreadbraw);
4034 if (xconn->smb1.echo_handler.trusted_fde) {
4035 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
4036 "'async smb echo handler = yes'\n"));
4037 reply_readbraw_error(xconn);
4038 END_PROFILE(SMBreadbraw);
4043 * Special check if an oplock break has been issued
4044 * and the readraw request croses on the wire, we must
4045 * return a zero length response here.
4048 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4051 * We have to do a check_fsp by hand here, as
4052 * we must always return 4 zero bytes on error,
4058 conn != fsp->conn ||
4059 req->vuid != fsp->vuid ||
4060 fsp->fsp_flags.is_directory ||
4064 * fsp could be NULL here so use the value from the packet. JRA.
4066 DEBUG(3,("reply_readbraw: fnum %d not valid "
4068 (int)SVAL(req->vwv+0, 0)));
4069 reply_readbraw_error(xconn);
4070 END_PROFILE(SMBreadbraw);
4074 /* Do a "by hand" version of CHECK_READ. */
4075 if (!(fsp->fsp_flags.can_read ||
4076 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
4077 (fsp->access_mask & FILE_EXECUTE)))) {
4078 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4079 (int)SVAL(req->vwv+0, 0)));
4080 reply_readbraw_error(xconn);
4081 END_PROFILE(SMBreadbraw);
4085 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
4086 if(req->wct == 10) {
4088 * This is a large offset (64 bit) read.
4091 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4094 DEBUG(0,("reply_readbraw: negative 64 bit "
4095 "readraw offset (%.0f) !\n",
4096 (double)startpos ));
4097 reply_readbraw_error(xconn);
4098 END_PROFILE(SMBreadbraw);
4103 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4104 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4106 /* ensure we don't overrun the packet size */
4107 maxcount = MIN(65535,maxcount);
4109 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4110 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4113 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4114 reply_readbraw_error(xconn);
4115 END_PROFILE(SMBreadbraw);
4119 status = vfs_stat_fsp(fsp);
4120 if (NT_STATUS_IS_OK(status)) {
4121 size = fsp->fsp_name->st.st_ex_size;
4124 if (startpos >= size) {
4127 nread = MIN(maxcount,(size - startpos));
4130 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4131 if (nread < mincount)
4135 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4136 "min=%lu nread=%lu\n",
4137 fsp_fnum_dbg(fsp), (double)startpos,
4138 (unsigned long)maxcount,
4139 (unsigned long)mincount,
4140 (unsigned long)nread ) );
4142 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4144 DEBUG(5,("reply_readbraw finished\n"));
4146 END_PROFILE(SMBreadbraw);
4151 #define DBGC_CLASS DBGC_LOCKING
4153 /****************************************************************************
4154 Reply to a lockread (core+ protocol).
4155 ****************************************************************************/
4157 static void reply_lockread_locked(struct tevent_req *subreq);
4159 void reply_lockread(struct smb_request *req)
4161 struct tevent_req *subreq = NULL;
4162 connection_struct *conn = req->conn;
4164 struct smbd_lock_element *lck = NULL;
4166 START_PROFILE(SMBlockread);
4169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4170 END_PROFILE(SMBlockread);
4174 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4176 if (!check_fsp(conn, req, fsp)) {
4177 END_PROFILE(SMBlockread);
4181 if (!CHECK_READ(fsp,req)) {
4182 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4183 END_PROFILE(SMBlockread);
4187 lck = talloc(req, struct smbd_lock_element);
4189 reply_nterror(req, NT_STATUS_NO_MEMORY);
4190 END_PROFILE(SMBlockread);
4195 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4196 * protocol request that predates the read/write lock concept.
4197 * Thus instead of asking for a read lock here we need to ask
4198 * for a write lock. JRA.
4199 * Note that the requested lock size is unaffected by max_send.
4202 *lck = (struct smbd_lock_element) {
4203 .req_guid = smbd_request_guid(req, 0),
4204 .smblctx = req->smbpid,
4205 .brltype = WRITE_LOCK,
4206 .count = SVAL(req->vwv+1, 0),
4207 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4210 subreq = smbd_smb1_do_locks_send(
4216 false, /* large_offset */
4220 if (subreq == NULL) {
4221 reply_nterror(req, NT_STATUS_NO_MEMORY);
4222 END_PROFILE(SMBlockread);
4225 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4226 END_PROFILE(SMBlockread);
4229 static void reply_lockread_locked(struct tevent_req *subreq)
4231 struct smb_request *req = NULL;
4237 size_t numtoread, maxtoread;
4238 struct files_struct *fsp = NULL;
4241 START_PROFILE(SMBlockread);
4243 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4246 status = smbd_smb1_do_locks_recv(subreq);
4247 TALLOC_FREE(subreq);
4249 if (!NT_STATUS_IS_OK(status)) {
4250 reply_nterror(req, status);
4254 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4256 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4260 numtoread = SVAL(req->vwv+1, 0);
4261 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4264 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4266 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4268 if (numtoread > maxtoread) {
4269 DBG_WARNING("requested read size (%zu) is greater than "
4270 "maximum allowed (%zu/%d). "
4271 "Returning short read of maximum allowed for "
4272 "compatibility with Windows 2000.\n",
4275 req->xconn->smb1.sessions.max_send);
4276 numtoread = maxtoread;
4279 reply_outbuf(req, 5, numtoread + 3);
4281 data = smb_buf(req->outbuf) + 3;
4283 nread = read_file(fsp,data,startpos,numtoread);
4286 reply_nterror(req, map_nt_error_from_unix(errno));
4290 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4292 SSVAL(req->outbuf,smb_vwv0,nread);
4293 SSVAL(req->outbuf,smb_vwv5,nread+3);
4294 p = smb_buf(req->outbuf);
4295 SCVAL(p,0,0); /* pad byte. */
4298 DEBUG(3,("lockread %s num=%d nread=%d\n",
4299 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4302 ok = srv_send_smb(req->xconn,
4303 (char *)req->outbuf,
4306 IS_CONN_ENCRYPTED(req->conn),
4309 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4312 END_PROFILE(SMBlockread);
4317 #define DBGC_CLASS DBGC_ALL
4319 /****************************************************************************
4321 ****************************************************************************/
4323 void reply_read(struct smb_request *req)
4325 connection_struct *conn = req->conn;
4332 struct lock_struct lock;
4333 struct smbXsrv_connection *xconn = req->xconn;
4335 START_PROFILE(SMBread);
4338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4339 END_PROFILE(SMBread);
4343 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4345 if (!check_fsp(conn, req, fsp)) {
4346 END_PROFILE(SMBread);
4350 if (!CHECK_READ(fsp,req)) {
4351 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4352 END_PROFILE(SMBread);
4356 numtoread = SVAL(req->vwv+1, 0);
4357 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4360 * The requested read size cannot be greater than max_send. JRA.
4362 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4364 if (numtoread > maxtoread) {
4365 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4366 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4367 (unsigned int)numtoread, (unsigned int)maxtoread,
4368 (unsigned int)xconn->smb1.sessions.max_send));
4369 numtoread = maxtoread;
4372 reply_outbuf(req, 5, numtoread+3);
4374 data = smb_buf(req->outbuf) + 3;
4376 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4377 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4380 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4381 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4382 END_PROFILE(SMBread);
4387 nread = read_file(fsp,data,startpos,numtoread);
4390 reply_nterror(req, map_nt_error_from_unix(errno));
4394 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4396 SSVAL(req->outbuf,smb_vwv0,nread);
4397 SSVAL(req->outbuf,smb_vwv5,nread+3);
4398 SCVAL(smb_buf(req->outbuf),0,1);
4399 SSVAL(smb_buf(req->outbuf),1,nread);
4401 DEBUG(3, ("read %s num=%d nread=%d\n",
4402 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4405 END_PROFILE(SMBread);
4409 /****************************************************************************
4411 ****************************************************************************/
4413 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4417 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4420 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4422 SCVAL(outbuf,smb_vwv0,0xFF);
4423 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4424 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4425 SSVAL(outbuf,smb_vwv6,
4426 (smb_wct - 4) /* offset from smb header to wct */
4427 + 1 /* the wct field */
4428 + 12 * sizeof(uint16_t) /* vwv */
4429 + 2 /* the buflen field */
4430 + 1); /* padding byte */
4431 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4432 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4433 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4434 _smb_setlen_large(outbuf,
4435 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4439 /****************************************************************************
4440 Reply to a read and X - possibly using sendfile.
4441 ****************************************************************************/
4443 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4444 files_struct *fsp, off_t startpos,
4447 struct smbXsrv_connection *xconn = req->xconn;
4449 struct lock_struct lock;
4450 int saved_errno = 0;
4453 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4454 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4457 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4458 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4463 * We can only use sendfile on a non-chained packet
4464 * but we can use on a non-oplocked file. tridge proved this
4465 * on a train in Germany :-). JRA.
4468 if (!req_is_in_chain(req) &&
4470 (fsp->base_fsp == NULL) &&
4471 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4472 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4475 status = vfs_stat_fsp(fsp);
4476 if (!NT_STATUS_IS_OK(status)) {
4477 reply_nterror(req, status);
4481 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4482 (startpos > fsp->fsp_name->st.st_ex_size) ||
4483 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4485 * We already know that we would do a short read, so don't
4486 * try the sendfile() path.
4488 goto nosendfile_read;
4492 * Set up the packet header before send. We
4493 * assume here the sendfile will work (get the
4494 * correct amount of data).
4497 header = data_blob_const(headerbuf, sizeof(headerbuf));
4499 construct_reply_common_req(req, (char *)headerbuf);
4500 setup_readX_header((char *)headerbuf, smb_maxcnt);
4502 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4503 startpos, smb_maxcnt);
4505 saved_errno = errno;
4507 /* Returning ENOSYS means no data at all was sent.
4508 Do this as a normal read. */
4509 if (errno == ENOSYS) {
4514 * Special hack for broken Linux with no working sendfile. If we
4515 * return EINTR we sent the header but not the rest of the data.
4516 * Fake this up by doing read/write calls.
4519 if (errno == EINTR) {
4520 /* Ensure we don't do this again. */
4521 set_use_sendfile(SNUM(conn), False);
4522 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4523 nread = fake_sendfile(xconn, fsp, startpos,
4526 saved_errno = errno;
4527 DEBUG(0,("send_file_readX: "
4528 "fake_sendfile failed for "
4529 "file %s (%s) for client %s. "
4532 smbXsrv_connection_dbg(xconn),
4533 strerror(saved_errno)));
4534 errno = saved_errno;
4535 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4537 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4538 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4539 /* No outbuf here means successful sendfile. */
4543 DEBUG(0,("send_file_readX: sendfile failed for file "
4544 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4546 exit_server_cleanly("send_file_readX sendfile failed");
4547 } else if (nread == 0) {
4549 * Some sendfile implementations return 0 to indicate
4550 * that there was a short read, but nothing was
4551 * actually written to the socket. In this case,
4552 * fallback to the normal read path so the header gets
4553 * the correct byte count.
4555 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4556 "falling back to the normal read: %s\n",
4561 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4562 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4564 /* Deal with possible short send. */
4565 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4568 ret = sendfile_short_send(xconn, fsp, nread,
4569 sizeof(headerbuf), smb_maxcnt);
4572 r = "send_file_readX: sendfile_short_send failed";
4573 DEBUG(0,("%s for file %s (%s).\n",
4574 r, fsp_str_dbg(fsp), strerror(errno)));
4575 exit_server_cleanly(r);
4578 /* No outbuf here means successful sendfile. */
4579 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4580 SMB_PERFCOUNT_END(&req->pcd);
4586 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4587 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4590 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4591 (startpos > fsp->fsp_name->st.st_ex_size) ||
4592 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4594 * We already know that we would do a short
4595 * read, so don't try the sendfile() path.
4597 goto nosendfile_read;
4600 construct_reply_common_req(req, (char *)headerbuf);
4601 setup_readX_header((char *)headerbuf, smb_maxcnt);
4603 /* Send out the header. */
4604 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4606 if (ret != sizeof(headerbuf)) {
4607 saved_errno = errno;
4609 * Try and give an error message saying what
4612 DEBUG(0,("send_file_readX: write_data failed for file "
4613 "%s (%s) for client %s. Terminating\n",
4615 smbXsrv_connection_dbg(xconn),
4616 strerror(saved_errno)));
4617 errno = saved_errno;
4618 exit_server_cleanly("send_file_readX sendfile failed");
4620 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4622 saved_errno = errno;
4623 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4624 "%s (%s) for client %s. Terminating\n",
4626 smbXsrv_connection_dbg(xconn),
4627 strerror(saved_errno)));
4628 errno = saved_errno;
4629 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4636 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4637 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4638 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4640 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4641 startpos, smb_maxcnt);
4642 saved_errno = errno;
4645 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4649 setup_readX_header((char *)req->outbuf, nread);
4651 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4652 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4656 TALLOC_FREE(req->outbuf);
4660 /****************************************************************************
4661 Work out how much space we have for a read return.
4662 ****************************************************************************/
4664 static size_t calc_max_read_pdu(const struct smb_request *req)
4666 struct smbXsrv_connection *xconn = req->xconn;
4668 if (xconn->protocol < PROTOCOL_NT1) {
4669 return xconn->smb1.sessions.max_send;
4672 if (!lp_large_readwrite()) {
4673 return xconn->smb1.sessions.max_send;
4676 if (req_is_in_chain(req)) {
4677 return xconn->smb1.sessions.max_send;
4680 if (req->encrypted) {
4682 * Don't take encrypted traffic up to the
4683 * limit. There are padding considerations
4684 * that make that tricky.
4686 return xconn->smb1.sessions.max_send;
4689 if (srv_is_signing_active(xconn)) {
4693 if (!lp_unix_extensions()) {
4698 * We can do ultra-large POSIX reads.
4703 /****************************************************************************
4704 Calculate how big a read can be. Copes with all clients. It's always
4705 safe to return a short read - Windows does this.
4706 ****************************************************************************/
4708 static size_t calc_read_size(const struct smb_request *req,
4712 struct smbXsrv_connection *xconn = req->xconn;
4713 size_t max_pdu = calc_max_read_pdu(req);
4714 size_t total_size = 0;
4715 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4716 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4719 * Windows explicitly ignores upper size of 0xFFFF.
4720 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4721 * We must do the same as these will never fit even in
4722 * an extended size NetBIOS packet.
4724 if (upper_size == 0xFFFF) {
4728 if (xconn->protocol < PROTOCOL_NT1) {
4732 total_size = ((upper_size<<16) | lower_size);
4735 * LARGE_READX test shows it's always safe to return
4736 * a short read. Windows does so.
4738 return MIN(total_size, max_len);
4741 /****************************************************************************
4742 Reply to a read and X.
4743 ****************************************************************************/
4745 void reply_read_and_X(struct smb_request *req)
4747 connection_struct *conn = req->conn;
4752 bool big_readX = False;
4754 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4757 START_PROFILE(SMBreadX);
4759 if ((req->wct != 10) && (req->wct != 12)) {
4760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4764 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4765 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4766 smb_maxcnt = SVAL(req->vwv+5, 0);
4768 /* If it's an IPC, pass off the pipe handler. */
4770 reply_pipe_read_and_X(req);
4771 END_PROFILE(SMBreadX);
4775 if (!check_fsp(conn, req, fsp)) {
4776 END_PROFILE(SMBreadX);
4780 if (!CHECK_READ(fsp,req)) {
4781 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4782 END_PROFILE(SMBreadX);
4786 upper_size = SVAL(req->vwv+7, 0);
4787 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4788 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4790 * This is a heuristic to avoid keeping large
4791 * outgoing buffers around over long-lived aio
4797 if (req->wct == 12) {
4799 * This is a large offset (64 bit) read.
4801 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4806 NTSTATUS status = schedule_aio_read_and_X(conn,
4811 if (NT_STATUS_IS_OK(status)) {
4812 /* Read scheduled - we're done. */
4815 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4816 /* Real error - report to client. */
4817 END_PROFILE(SMBreadX);
4818 reply_nterror(req, status);
4821 /* NT_STATUS_RETRY - fall back to sync read. */
4824 smbd_lock_socket(req->xconn);
4825 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4826 smbd_unlock_socket(req->xconn);
4829 END_PROFILE(SMBreadX);
4833 /****************************************************************************
4834 Error replies to writebraw must have smb_wct == 1. Fix this up.
4835 ****************************************************************************/
4837 void error_to_writebrawerr(struct smb_request *req)
4839 uint8_t *old_outbuf = req->outbuf;
4841 reply_outbuf(req, 1, 0);
4843 memcpy(req->outbuf, old_outbuf, smb_size);
4844 TALLOC_FREE(old_outbuf);
4847 /****************************************************************************
4848 Read 4 bytes of a smb packet and return the smb length of the packet.
4849 Store the result in the buffer. This version of the function will
4850 never return a session keepalive (length of zero).
4851 Timeout is in milliseconds.
4852 ****************************************************************************/
4854 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4857 uint8_t msgtype = NBSSkeepalive;
4859 while (msgtype == NBSSkeepalive) {
4862 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4864 if (!NT_STATUS_IS_OK(status)) {
4865 char addr[INET6_ADDRSTRLEN];
4866 /* Try and give an error message
4867 * saying what client failed. */
4868 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4869 "client %s read error = %s.\n",
4870 get_peer_addr(fd,addr,sizeof(addr)),
4871 nt_errstr(status)));
4875 msgtype = CVAL(inbuf, 0);
4878 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4879 (unsigned long)len));
4881 return NT_STATUS_OK;
4884 /****************************************************************************
4885 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4886 ****************************************************************************/
4888 void reply_writebraw(struct smb_request *req)
4890 connection_struct *conn = req->conn;
4891 struct smbXsrv_connection *xconn = req->xconn;
4894 ssize_t total_written=0;
4895 size_t numtowrite=0;
4898 const char *data=NULL;
4901 struct lock_struct lock;
4904 START_PROFILE(SMBwritebraw);
4907 * If we ever reply with an error, it must have the SMB command
4908 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4911 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4913 if (srv_is_signing_active(xconn)) {
4914 END_PROFILE(SMBwritebraw);
4915 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4916 "raw reads/writes are disallowed.");
4919 if (req->wct < 12) {
4920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4921 error_to_writebrawerr(req);
4922 END_PROFILE(SMBwritebraw);
4926 if (xconn->smb1.echo_handler.trusted_fde) {
4927 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4928 "'async smb echo handler = yes'\n"));
4929 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4930 error_to_writebrawerr(req);
4931 END_PROFILE(SMBwritebraw);
4935 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4936 if (!check_fsp(conn, req, fsp)) {
4937 error_to_writebrawerr(req);
4938 END_PROFILE(SMBwritebraw);
4942 if (!CHECK_WRITE(fsp)) {
4943 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4944 error_to_writebrawerr(req);
4945 END_PROFILE(SMBwritebraw);
4949 tcount = IVAL(req->vwv+1, 0);
4950 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4951 write_through = BITSETW(req->vwv+7,0);
4953 /* We have to deal with slightly different formats depending
4954 on whether we are using the core+ or lanman1.0 protocol */
4956 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4957 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4958 data = smb_buf_const(req->inbuf);
4960 numtowrite = SVAL(req->vwv+10, 0);
4961 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4964 /* Ensure we don't write bytes past the end of this packet. */
4966 * This already protects us against CVE-2017-12163.
4968 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4969 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4970 error_to_writebrawerr(req);
4971 END_PROFILE(SMBwritebraw);
4975 if (!fsp->print_file) {
4976 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4977 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4980 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4981 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4982 error_to_writebrawerr(req);
4983 END_PROFILE(SMBwritebraw);
4989 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4992 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4993 "wrote=%d sync=%d\n",
4994 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4995 (int)nwritten, (int)write_through));
4997 if (nwritten < (ssize_t)numtowrite) {
4998 reply_nterror(req, NT_STATUS_DISK_FULL);
4999 error_to_writebrawerr(req);
5003 total_written = nwritten;
5005 /* Allocate a buffer of 64k + length. */
5006 buf = talloc_array(NULL, char, 65540);
5008 reply_nterror(req, NT_STATUS_NO_MEMORY);
5009 error_to_writebrawerr(req);
5013 /* Return a SMBwritebraw message to the redirector to tell
5014 * it to send more bytes */
5016 memcpy(buf, req->inbuf, smb_size);
5017 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
5018 SCVAL(buf,smb_com,SMBwritebraw);
5019 SSVALS(buf,smb_vwv0,0xFFFF);
5021 if (!srv_send_smb(req->xconn,
5023 false, 0, /* no signing */
5024 IS_CONN_ENCRYPTED(conn),
5026 exit_server_cleanly("reply_writebraw: srv_send_smb "
5030 /* Now read the raw data into the buffer and write it */
5031 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
5033 if (!NT_STATUS_IS_OK(status)) {
5034 exit_server_cleanly("secondary writebraw failed");
5037 /* Set up outbuf to return the correct size */
5038 reply_outbuf(req, 1, 0);
5040 if (numtowrite != 0) {
5042 if (numtowrite > 0xFFFF) {
5043 DEBUG(0,("reply_writebraw: Oversize secondary write "
5044 "raw requested (%u). Terminating\n",
5045 (unsigned int)numtowrite ));
5046 exit_server_cleanly("secondary writebraw failed");
5049 if (tcount > nwritten+numtowrite) {
5050 DEBUG(3,("reply_writebraw: Client overestimated the "
5052 (int)tcount,(int)nwritten,(int)numtowrite));
5055 status = read_data_ntstatus(xconn->transport.sock, buf+4,
5058 if (!NT_STATUS_IS_OK(status)) {
5059 /* Try and give an error message
5060 * saying what client failed. */
5061 DEBUG(0, ("reply_writebraw: Oversize secondary write "
5062 "raw read failed (%s) for client %s. "
5063 "Terminating\n", nt_errstr(status),
5064 smbXsrv_connection_dbg(xconn)));
5065 exit_server_cleanly("secondary writebraw failed");
5069 * We are not vulnerable to CVE-2017-12163
5070 * here as we are guaranteed to have numtowrite
5071 * bytes available - we just read from the client.
5073 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
5074 if (nwritten == -1) {
5076 reply_nterror(req, map_nt_error_from_unix(errno));
5077 error_to_writebrawerr(req);
5081 if (nwritten < (ssize_t)numtowrite) {
5082 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5083 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5087 total_written += nwritten;
5092 SSVAL(req->outbuf,smb_vwv0,total_written);
5094 status = sync_file(conn, fsp, write_through);
5095 if (!NT_STATUS_IS_OK(status)) {
5096 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5097 fsp_str_dbg(fsp), nt_errstr(status)));
5098 reply_nterror(req, status);
5099 error_to_writebrawerr(req);
5103 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5105 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5106 (int)total_written));
5108 /* We won't return a status if write through is not selected - this
5109 * follows what WfWg does */
5110 END_PROFILE(SMBwritebraw);
5112 if (!write_through && total_written==tcount) {
5114 #if RABBIT_PELLET_FIX
5116 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5117 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5120 if (!send_keepalive(xconn->transport.sock)) {
5121 exit_server_cleanly("reply_writebraw: send of "
5122 "keepalive failed");
5125 TALLOC_FREE(req->outbuf);
5130 END_PROFILE(SMBwritebraw);
5135 #define DBGC_CLASS DBGC_LOCKING
5137 /****************************************************************************
5138 Reply to a writeunlock (core+).
5139 ****************************************************************************/
5141 void reply_writeunlock(struct smb_request *req)
5143 connection_struct *conn = req->conn;
5144 ssize_t nwritten = -1;
5149 NTSTATUS status = NT_STATUS_OK;
5151 struct lock_struct lock;
5152 int saved_errno = 0;
5154 START_PROFILE(SMBwriteunlock);
5157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5158 END_PROFILE(SMBwriteunlock);
5162 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5164 if (!check_fsp(conn, req, fsp)) {
5165 END_PROFILE(SMBwriteunlock);
5169 if (!CHECK_WRITE(fsp)) {
5170 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5171 END_PROFILE(SMBwriteunlock);
5175 numtowrite = SVAL(req->vwv+1, 0);
5176 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5177 data = (const char *)req->buf + 3;
5180 * Ensure client isn't asking us to write more than
5181 * they sent. CVE-2017-12163.
5183 remaining = smbreq_bufrem(req, data);
5184 if (numtowrite > remaining) {
5185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5186 END_PROFILE(SMBwriteunlock);
5190 if (!fsp->print_file && numtowrite > 0) {
5191 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5192 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5195 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5196 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5197 END_PROFILE(SMBwriteunlock);
5202 /* The special X/Open SMB protocol handling of
5203 zero length writes is *NOT* done for
5205 if(numtowrite == 0) {
5208 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5209 saved_errno = errno;
5212 status = sync_file(conn, fsp, False /* write through */);
5213 if (!NT_STATUS_IS_OK(status)) {
5214 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5215 fsp_str_dbg(fsp), nt_errstr(status)));
5216 reply_nterror(req, status);
5221 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5225 if((nwritten < numtowrite) && (numtowrite != 0)) {
5226 reply_nterror(req, NT_STATUS_DISK_FULL);
5230 if (numtowrite && !fsp->print_file) {
5231 struct smbd_lock_element l = {
5232 .req_guid = smbd_request_guid(req, 0),
5233 .smblctx = req->smbpid,
5234 .brltype = UNLOCK_LOCK,
5236 .count = numtowrite,
5238 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5239 if (NT_STATUS_V(status)) {
5240 reply_nterror(req, status);
5245 reply_outbuf(req, 1, 0);
5247 SSVAL(req->outbuf,smb_vwv0,nwritten);
5249 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5250 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5253 END_PROFILE(SMBwriteunlock);
5258 #define DBGC_CLASS DBGC_ALL
5260 /****************************************************************************
5262 ****************************************************************************/
5264 void reply_write(struct smb_request *req)
5266 connection_struct *conn = req->conn;
5269 ssize_t nwritten = -1;
5273 struct lock_struct lock;
5275 int saved_errno = 0;
5277 START_PROFILE(SMBwrite);
5280 END_PROFILE(SMBwrite);
5281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5285 /* If it's an IPC, pass off the pipe handler. */
5287 reply_pipe_write(req);
5288 END_PROFILE(SMBwrite);
5292 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5294 if (!check_fsp(conn, req, fsp)) {
5295 END_PROFILE(SMBwrite);
5299 if (!CHECK_WRITE(fsp)) {
5300 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5301 END_PROFILE(SMBwrite);
5305 numtowrite = SVAL(req->vwv+1, 0);
5306 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5307 data = (const char *)req->buf + 3;
5310 * Ensure client isn't asking us to write more than
5311 * they sent. CVE-2017-12163.
5313 remaining = smbreq_bufrem(req, data);
5314 if (numtowrite > remaining) {
5315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5316 END_PROFILE(SMBwrite);
5320 if (!fsp->print_file) {
5321 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5322 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5325 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5326 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5327 END_PROFILE(SMBwrite);
5333 * X/Open SMB protocol says that if smb_vwv1 is
5334 * zero then the file size should be extended or
5335 * truncated to the size given in smb_vwv[2-3].
5338 if(numtowrite == 0) {
5340 * This is actually an allocate call, and set EOF. JRA.
5342 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5344 reply_nterror(req, NT_STATUS_DISK_FULL);
5347 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5349 reply_nterror(req, NT_STATUS_DISK_FULL);
5352 trigger_write_time_update_immediate(fsp);
5354 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5357 status = sync_file(conn, fsp, False);
5358 if (!NT_STATUS_IS_OK(status)) {
5359 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5360 fsp_str_dbg(fsp), nt_errstr(status)));
5361 reply_nterror(req, status);
5366 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5370 if((nwritten == 0) && (numtowrite != 0)) {
5371 reply_nterror(req, NT_STATUS_DISK_FULL);
5375 reply_outbuf(req, 1, 0);
5377 SSVAL(req->outbuf,smb_vwv0,nwritten);
5379 if (nwritten < (ssize_t)numtowrite) {
5380 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5381 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5384 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5387 END_PROFILE(SMBwrite);
5391 /****************************************************************************
5392 Ensure a buffer is a valid writeX for recvfile purposes.
5393 ****************************************************************************/
5395 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5396 (2*14) + /* word count (including bcc) */ \
5399 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5400 const uint8_t *inbuf)
5403 unsigned int doff = 0;
5404 size_t len = smb_len_large(inbuf);
5406 struct smbXsrv_open *op = NULL;
5407 struct files_struct *fsp = NULL;
5410 if (is_encrypted_packet(inbuf)) {
5411 /* Can't do this on encrypted
5416 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5420 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5421 CVAL(inbuf,smb_wct) != 14) {
5422 DEBUG(10,("is_valid_writeX_buffer: chained or "
5423 "invalid word length.\n"));
5427 fnum = SVAL(inbuf, smb_vwv2);
5428 status = smb1srv_open_lookup(xconn,
5432 if (!NT_STATUS_IS_OK(status)) {
5433 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5438 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5441 if (fsp->conn == NULL) {
5442 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5446 if (IS_IPC(fsp->conn)) {
5447 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5450 if (IS_PRINT(fsp->conn)) {
5451 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5454 if (fsp->base_fsp != NULL) {
5455 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5458 doff = SVAL(inbuf,smb_vwv11);
5460 numtowrite = SVAL(inbuf,smb_vwv10);
5462 if (len > doff && len - doff > 0xFFFF) {
5463 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5466 if (numtowrite == 0) {
5467 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5471 /* Ensure the sizes match up. */
5472 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5473 /* no pad byte...old smbclient :-( */
5474 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5476 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5480 if (len - doff != numtowrite) {
5481 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5482 "len = %u, doff = %u, numtowrite = %u\n",
5485 (unsigned int)numtowrite ));
5489 DEBUG(10,("is_valid_writeX_buffer: true "
5490 "len = %u, doff = %u, numtowrite = %u\n",
5493 (unsigned int)numtowrite ));
5498 /****************************************************************************
5499 Reply to a write and X.
5500 ****************************************************************************/
5502 void reply_write_and_X(struct smb_request *req)
5504 connection_struct *conn = req->conn;
5505 struct smbXsrv_connection *xconn = req->xconn;
5507 struct lock_struct lock;
5512 unsigned int smb_doff;
5513 unsigned int smblen;
5516 int saved_errno = 0;
5518 START_PROFILE(SMBwriteX);
5520 if ((req->wct != 12) && (req->wct != 14)) {
5521 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5525 numtowrite = SVAL(req->vwv+10, 0);
5526 smb_doff = SVAL(req->vwv+11, 0);
5527 smblen = smb_len(req->inbuf);
5529 if (req->unread_bytes > 0xFFFF ||
5530 (smblen > smb_doff &&
5531 smblen - smb_doff > 0xFFFF)) {
5532 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5535 if (req->unread_bytes) {
5536 /* Can't do a recvfile write on IPC$ */
5538 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5541 if (numtowrite != req->unread_bytes) {
5542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5547 * This already protects us against CVE-2017-12163.
5549 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5550 smb_doff + numtowrite > smblen) {
5551 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5556 /* If it's an IPC, pass off the pipe handler. */
5558 if (req->unread_bytes) {
5559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5562 reply_pipe_write_and_X(req);
5566 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5567 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5568 write_through = BITSETW(req->vwv+7,0);
5570 if (!check_fsp(conn, req, fsp)) {
5574 if (!CHECK_WRITE(fsp)) {
5575 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5579 data = smb_base(req->inbuf) + smb_doff;
5581 if(req->wct == 14) {
5583 * This is a large offset (64 bit) write.
5585 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5589 /* X/Open SMB protocol says that, unlike SMBwrite
5590 if the length is zero then NO truncation is
5591 done, just a write of zero. To truncate a file,
5594 if(numtowrite == 0) {
5597 if (req->unread_bytes == 0) {
5598 status = schedule_aio_write_and_X(conn,
5605 if (NT_STATUS_IS_OK(status)) {
5606 /* write scheduled - we're done. */
5609 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5610 /* Real error - report to client. */
5611 reply_nterror(req, status);
5614 /* NT_STATUS_RETRY - fall through to sync write. */
5617 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5618 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5621 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5622 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5626 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5627 saved_errno = errno;
5631 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5635 if((nwritten == 0) && (numtowrite != 0)) {
5636 reply_nterror(req, NT_STATUS_DISK_FULL);
5640 reply_outbuf(req, 6, 0);
5641 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5642 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5643 SSVAL(req->outbuf,smb_vwv2,nwritten);
5644 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5646 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5647 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5649 status = sync_file(conn, fsp, write_through);
5650 if (!NT_STATUS_IS_OK(status)) {
5651 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5652 fsp_str_dbg(fsp), nt_errstr(status)));
5653 reply_nterror(req, status);
5657 END_PROFILE(SMBwriteX);
5661 if (req->unread_bytes) {
5662 /* writeX failed. drain socket. */
5663 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5664 req->unread_bytes) {
5665 smb_panic("failed to drain pending bytes");
5667 req->unread_bytes = 0;
5670 END_PROFILE(SMBwriteX);
5674 /****************************************************************************
5676 ****************************************************************************/
5678 void reply_lseek(struct smb_request *req)
5680 connection_struct *conn = req->conn;
5687 START_PROFILE(SMBlseek);
5690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5691 END_PROFILE(SMBlseek);
5695 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5697 if (!check_fsp(conn, req, fsp)) {
5701 mode = SVAL(req->vwv+1, 0) & 3;
5702 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5703 startpos = (off_t)IVALS(req->vwv+2, 0);
5712 res = fsp->fh->pos + startpos;
5723 if (umode == SEEK_END) {
5724 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5725 if(errno == EINVAL) {
5726 off_t current_pos = startpos;
5728 status = vfs_stat_fsp(fsp);
5729 if (!NT_STATUS_IS_OK(status)) {
5730 reply_nterror(req, status);
5731 END_PROFILE(SMBlseek);
5735 current_pos += fsp->fsp_name->st.st_ex_size;
5737 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5742 reply_nterror(req, map_nt_error_from_unix(errno));
5743 END_PROFILE(SMBlseek);
5750 reply_outbuf(req, 2, 0);
5751 SIVAL(req->outbuf,smb_vwv0,res);
5753 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5754 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5756 END_PROFILE(SMBlseek);
5760 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5763 connection_struct *conn = talloc_get_type_abort(
5764 private_data, connection_struct);
5766 if (conn != fsp->conn) {
5769 if (fsp->fh->fd == -1) {
5772 sync_file(conn, fsp, True /* write through */);
5774 if (fsp->fsp_flags.modified) {
5775 trigger_write_time_update_immediate(fsp);
5781 /****************************************************************************
5783 ****************************************************************************/
5785 void reply_flush(struct smb_request *req)
5787 connection_struct *conn = req->conn;
5791 START_PROFILE(SMBflush);
5794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5798 fnum = SVAL(req->vwv+0, 0);
5799 fsp = file_fsp(req, fnum);
5801 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5806 files_forall(req->sconn, file_sync_one_fn, conn);
5808 NTSTATUS status = sync_file(conn, fsp, True);
5809 if (!NT_STATUS_IS_OK(status)) {
5810 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5811 fsp_str_dbg(fsp), nt_errstr(status)));
5812 reply_nterror(req, status);
5813 END_PROFILE(SMBflush);
5816 if (fsp->fsp_flags.modified) {
5817 trigger_write_time_update_immediate(fsp);
5821 reply_outbuf(req, 0, 0);
5823 DEBUG(3,("flush\n"));
5824 END_PROFILE(SMBflush);
5828 /****************************************************************************
5830 conn POINTER CAN BE NULL HERE !
5831 ****************************************************************************/
5833 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5834 static void reply_exit_done(struct tevent_req *req);
5836 void reply_exit(struct smb_request *smb1req)
5838 struct tevent_req *req;
5841 * Don't setup the profile charge here, take
5842 * it in reply_exit_done(). Not strictly correct
5843 * but better than the other SMB1 async
5844 * code that double-charges at the moment.
5846 req = reply_exit_send(smb1req);
5848 /* Not going async, profile here. */
5849 START_PROFILE(SMBexit);
5850 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5851 END_PROFILE(SMBexit);
5855 /* We're async. This will complete later. */
5856 tevent_req_set_callback(req, reply_exit_done, smb1req);
5860 struct reply_exit_state {
5861 struct tevent_queue *wait_queue;
5864 static void reply_exit_wait_done(struct tevent_req *subreq);
5866 /****************************************************************************
5868 Note, on failure here we deallocate and return NULL to allow the caller to
5869 SMB1 return an error of ERRnomem immediately.
5870 ****************************************************************************/
5872 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5874 struct tevent_req *req;
5875 struct reply_exit_state *state;
5876 struct tevent_req *subreq;
5878 struct smbd_server_connection *sconn = smb1req->sconn;
5880 req = tevent_req_create(smb1req, &state,
5881 struct reply_exit_state);
5885 state->wait_queue = tevent_queue_create(state,
5886 "reply_exit_wait_queue");
5887 if (tevent_req_nomem(state->wait_queue, req)) {
5892 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5893 if (fsp->file_pid != smb1req->smbpid) {
5896 if (fsp->vuid != smb1req->vuid) {
5900 * Flag the file as close in progress.
5901 * This will prevent any more IO being
5904 fsp->fsp_flags.closing = true;
5906 if (fsp->num_aio_requests > 0) {
5908 * Now wait until all aio requests on this fsp are
5911 * We don't set a callback, as we just want to block the
5912 * wait queue and the talloc_free() of fsp->aio_request
5913 * will remove the item from the wait queue.
5915 subreq = tevent_queue_wait_send(fsp->aio_requests,
5918 if (tevent_req_nomem(subreq, req)) {
5926 * Now we add our own waiter to the end of the queue,
5927 * this way we get notified when all pending requests are finished
5928 * and reply to the outstanding SMB1 request.
5930 subreq = tevent_queue_wait_send(state,
5933 if (tevent_req_nomem(subreq, req)) {
5939 * We're really going async - move the SMB1 request from
5940 * a talloc stackframe above us to the conn talloc-context.
5941 * We need this to stick around until the wait_done
5942 * callback is invoked.
5944 smb1req = talloc_move(sconn, &smb1req);
5946 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5951 static void reply_exit_wait_done(struct tevent_req *subreq)
5953 struct tevent_req *req = tevent_req_callback_data(
5954 subreq, struct tevent_req);
5956 tevent_queue_wait_recv(subreq);
5957 TALLOC_FREE(subreq);
5958 tevent_req_done(req);
5961 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5963 return tevent_req_simple_recv_ntstatus(req);
5966 static void reply_exit_done(struct tevent_req *req)
5968 struct smb_request *smb1req = tevent_req_callback_data(
5969 req, struct smb_request);
5970 struct smbd_server_connection *sconn = smb1req->sconn;
5971 struct smbXsrv_connection *xconn = smb1req->xconn;
5972 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5973 struct smbXsrv_session *session = NULL;
5974 files_struct *fsp, *next;
5978 * Take the profile charge here. Not strictly
5979 * correct but better than the other SMB1 async
5980 * code that double-charges at the moment.
5982 START_PROFILE(SMBexit);
5984 status = reply_exit_recv(req);
5986 if (!NT_STATUS_IS_OK(status)) {
5987 TALLOC_FREE(smb1req);
5988 END_PROFILE(SMBexit);
5989 exit_server(__location__ ": reply_exit_recv failed");
5994 * Ensure the session is still valid.
5996 status = smb1srv_session_lookup(xconn,
6000 if (!NT_STATUS_IS_OK(status)) {
6001 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6002 smb_request_done(smb1req);
6003 END_PROFILE(SMBexit);
6007 * Ensure the vuid is still valid - no one
6008 * called reply_ulogoffX() in the meantime.
6009 * reply_exit() doesn't have AS_USER set, so
6010 * use set_current_user_info() directly.
6011 * This is the same logic as in switch_message().
6013 if (session->global->auth_session_info != NULL) {
6014 set_current_user_info(
6015 session->global->auth_session_info->unix_info->sanitized_username,
6016 session->global->auth_session_info->unix_info->unix_name,
6017 session->global->auth_session_info->info->domain_name);
6020 /* No more aio - do the actual closes. */
6021 for (fsp = sconn->files; fsp; fsp = next) {
6025 if (fsp->file_pid != smb1req->smbpid) {
6028 if (fsp->vuid != smb1req->vuid) {
6031 if (!fsp->fsp_flags.closing) {
6036 * reply_exit() has the DO_CHDIR flag set.
6038 ok = chdir_current_service(fsp->conn);
6040 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6041 smb_request_done(smb1req);
6042 END_PROFILE(SMBexit);
6044 close_file(NULL, fsp, SHUTDOWN_CLOSE);
6047 reply_outbuf(smb1req, 0, 0);
6049 * The following call is needed to push the
6050 * reply data back out the socket after async
6051 * return. Plus it frees smb1req.
6053 smb_request_done(smb1req);
6054 DBG_INFO("reply_exit complete\n");
6055 END_PROFILE(SMBexit);
6059 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6061 static void reply_close_done(struct tevent_req *req);
6063 void reply_close(struct smb_request *smb1req)
6065 connection_struct *conn = smb1req->conn;
6066 NTSTATUS status = NT_STATUS_OK;
6067 files_struct *fsp = NULL;
6068 START_PROFILE(SMBclose);
6070 if (smb1req->wct < 3) {
6071 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
6072 END_PROFILE(SMBclose);
6076 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
6079 * We can only use check_fsp if we know it's not a directory.
6082 if (!check_fsp_open(conn, smb1req, fsp)) {
6083 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
6084 END_PROFILE(SMBclose);
6088 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6089 fsp->fsp_flags.is_directory ?
6090 "directory" : "file",
6091 fsp->fh->fd, fsp_fnum_dbg(fsp),
6092 conn->num_files_open);
6094 if (!fsp->fsp_flags.is_directory) {
6098 * Take care of any time sent in the close.
6101 t = srv_make_unix_date3(smb1req->vwv+1);
6102 set_close_write_time(fsp, time_t_to_full_timespec(t));
6105 if (fsp->num_aio_requests != 0) {
6106 struct tevent_req *req;
6108 req = reply_close_send(smb1req, fsp);
6110 status = NT_STATUS_NO_MEMORY;
6113 /* We're async. This will complete later. */
6114 tevent_req_set_callback(req, reply_close_done, smb1req);
6115 END_PROFILE(SMBclose);
6120 * close_file() returns the unix errno if an error was detected on
6121 * close - normally this is due to a disk full error. If not then it
6122 * was probably an I/O error.
6125 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6127 if (!NT_STATUS_IS_OK(status)) {
6128 reply_nterror(smb1req, status);
6129 END_PROFILE(SMBclose);
6133 reply_outbuf(smb1req, 0, 0);
6134 END_PROFILE(SMBclose);
6138 struct reply_close_state {
6140 struct tevent_queue *wait_queue;
6143 static void reply_close_wait_done(struct tevent_req *subreq);
6145 /****************************************************************************
6147 Note, on failure here we deallocate and return NULL to allow the caller to
6148 SMB1 return an error of ERRnomem immediately.
6149 ****************************************************************************/
6151 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6154 struct tevent_req *req;
6155 struct reply_close_state *state;
6156 struct tevent_req *subreq;
6157 struct smbd_server_connection *sconn = smb1req->sconn;
6159 req = tevent_req_create(smb1req, &state,
6160 struct reply_close_state);
6164 state->wait_queue = tevent_queue_create(state,
6165 "reply_close_wait_queue");
6166 if (tevent_req_nomem(state->wait_queue, req)) {
6172 * Flag the file as close in progress.
6173 * This will prevent any more IO being
6176 fsp->fsp_flags.closing = true;
6179 * Now wait until all aio requests on this fsp are
6182 * We don't set a callback, as we just want to block the
6183 * wait queue and the talloc_free() of fsp->aio_request
6184 * will remove the item from the wait queue.
6186 subreq = tevent_queue_wait_send(fsp->aio_requests,
6189 if (tevent_req_nomem(subreq, req)) {
6195 * Now we add our own waiter to the end of the queue,
6196 * this way we get notified when all pending requests are finished
6197 * and reply to the outstanding SMB1 request.
6199 subreq = tevent_queue_wait_send(state,
6202 if (tevent_req_nomem(subreq, req)) {
6208 * We're really going async - move the SMB1 request from
6209 * a talloc stackframe above us to the conn talloc-context.
6210 * We need this to stick around until the wait_done
6211 * callback is invoked.
6213 smb1req = talloc_move(sconn, &smb1req);
6215 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6220 static void reply_close_wait_done(struct tevent_req *subreq)
6222 struct tevent_req *req = tevent_req_callback_data(
6223 subreq, struct tevent_req);
6225 tevent_queue_wait_recv(subreq);
6226 TALLOC_FREE(subreq);
6227 tevent_req_done(req);
6230 static NTSTATUS reply_close_recv(struct tevent_req *req)
6232 return tevent_req_simple_recv_ntstatus(req);
6235 static void reply_close_done(struct tevent_req *req)
6237 struct smb_request *smb1req = tevent_req_callback_data(
6238 req, struct smb_request);
6239 struct reply_close_state *state = tevent_req_data(req,
6240 struct reply_close_state);
6243 status = reply_close_recv(req);
6245 if (!NT_STATUS_IS_OK(status)) {
6246 TALLOC_FREE(smb1req);
6247 exit_server(__location__ ": reply_close_recv failed");
6251 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6252 if (NT_STATUS_IS_OK(status)) {
6253 reply_outbuf(smb1req, 0, 0);
6255 reply_nterror(smb1req, status);
6258 * The following call is needed to push the
6259 * reply data back out the socket after async
6260 * return. Plus it frees smb1req.
6262 smb_request_done(smb1req);
6265 /****************************************************************************
6266 Reply to a writeclose (Core+ protocol).
6267 ****************************************************************************/
6269 void reply_writeclose(struct smb_request *req)
6271 connection_struct *conn = req->conn;
6274 ssize_t nwritten = -1;
6275 NTSTATUS close_status = NT_STATUS_OK;
6278 struct timespec mtime;
6280 struct lock_struct lock;
6282 START_PROFILE(SMBwriteclose);
6285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6286 END_PROFILE(SMBwriteclose);
6290 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6292 if (!check_fsp(conn, req, fsp)) {
6293 END_PROFILE(SMBwriteclose);
6296 if (!CHECK_WRITE(fsp)) {
6297 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6298 END_PROFILE(SMBwriteclose);
6302 numtowrite = SVAL(req->vwv+1, 0);
6303 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6304 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6305 data = (const char *)req->buf + 1;
6308 * Ensure client isn't asking us to write more than
6309 * they sent. CVE-2017-12163.
6311 remaining = smbreq_bufrem(req, data);
6312 if (numtowrite > remaining) {
6313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6314 END_PROFILE(SMBwriteclose);
6318 if (fsp->print_file == NULL) {
6319 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6320 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6323 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6324 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6325 END_PROFILE(SMBwriteclose);
6330 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6332 set_close_write_time(fsp, mtime);
6335 * More insanity. W2K only closes the file if writelen > 0.
6339 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6340 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6341 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6344 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6345 "file %s\n", fsp_str_dbg(fsp)));
6346 close_status = close_file(req, fsp, NORMAL_CLOSE);
6350 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6351 reply_nterror(req, NT_STATUS_DISK_FULL);
6355 if(!NT_STATUS_IS_OK(close_status)) {
6356 reply_nterror(req, close_status);
6360 reply_outbuf(req, 1, 0);
6362 SSVAL(req->outbuf,smb_vwv0,nwritten);
6366 END_PROFILE(SMBwriteclose);
6371 #define DBGC_CLASS DBGC_LOCKING
6373 /****************************************************************************
6375 ****************************************************************************/
6377 static void reply_lock_done(struct tevent_req *subreq);
6379 void reply_lock(struct smb_request *req)
6381 struct tevent_req *subreq = NULL;
6382 connection_struct *conn = req->conn;
6384 struct smbd_lock_element *lck = NULL;
6386 START_PROFILE(SMBlock);
6389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6390 END_PROFILE(SMBlock);
6394 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6396 if (!check_fsp(conn, req, fsp)) {
6397 END_PROFILE(SMBlock);
6401 lck = talloc(req, struct smbd_lock_element);
6403 reply_nterror(req, NT_STATUS_NO_MEMORY);
6404 END_PROFILE(SMBlock);
6408 *lck = (struct smbd_lock_element) {
6409 .req_guid = smbd_request_guid(req, 0),
6410 .smblctx = req->smbpid,
6411 .brltype = WRITE_LOCK,
6412 .count = IVAL(req->vwv+1, 0),
6413 .offset = IVAL(req->vwv+3, 0),
6416 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6422 subreq = smbd_smb1_do_locks_send(
6428 false, /* large_offset */
6432 if (subreq == NULL) {
6433 reply_nterror(req, NT_STATUS_NO_MEMORY);
6434 END_PROFILE(SMBlock);
6437 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6438 END_PROFILE(SMBlock);
6441 static void reply_lock_done(struct tevent_req *subreq)
6443 struct smb_request *req = NULL;
6447 START_PROFILE(SMBlock);
6449 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6452 status = smbd_smb1_do_locks_recv(subreq);
6453 TALLOC_FREE(subreq);
6455 if (NT_STATUS_IS_OK(status)) {
6456 reply_outbuf(req, 0, 0);
6458 reply_nterror(req, status);
6461 ok = srv_send_smb(req->xconn,
6462 (char *)req->outbuf,
6465 IS_CONN_ENCRYPTED(req->conn),
6468 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6471 END_PROFILE(SMBlock);
6474 /****************************************************************************
6476 ****************************************************************************/
6478 void reply_unlock(struct smb_request *req)
6480 connection_struct *conn = req->conn;
6483 struct smbd_lock_element lck;
6485 START_PROFILE(SMBunlock);
6488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6489 END_PROFILE(SMBunlock);
6493 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6495 if (!check_fsp(conn, req, fsp)) {
6496 END_PROFILE(SMBunlock);
6500 lck = (struct smbd_lock_element) {
6501 .req_guid = smbd_request_guid(req, 0),
6502 .smblctx = req->smbpid,
6503 .brltype = UNLOCK_LOCK,
6504 .offset = IVAL(req->vwv+3, 0),
6505 .count = IVAL(req->vwv+1, 0),
6508 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6510 if (!NT_STATUS_IS_OK(status)) {
6511 reply_nterror(req, status);
6512 END_PROFILE(SMBunlock);
6516 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6522 reply_outbuf(req, 0, 0);
6524 END_PROFILE(SMBunlock);
6529 #define DBGC_CLASS DBGC_ALL
6531 /****************************************************************************
6533 conn POINTER CAN BE NULL HERE !
6534 ****************************************************************************/
6536 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6537 static void reply_tdis_done(struct tevent_req *req);
6539 void reply_tdis(struct smb_request *smb1req)
6541 connection_struct *conn = smb1req->conn;
6542 struct tevent_req *req;
6545 * Don't setup the profile charge here, take
6546 * it in reply_tdis_done(). Not strictly correct
6547 * but better than the other SMB1 async
6548 * code that double-charges at the moment.
6552 /* Not going async, profile here. */
6553 START_PROFILE(SMBtdis);
6554 DBG_INFO("Invalid connection in tdis\n");
6555 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6556 END_PROFILE(SMBtdis);
6560 req = reply_tdis_send(smb1req);
6562 /* Not going async, profile here. */
6563 START_PROFILE(SMBtdis);
6564 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6565 END_PROFILE(SMBtdis);
6568 /* We're async. This will complete later. */
6569 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6573 struct reply_tdis_state {
6574 struct tevent_queue *wait_queue;
6577 static void reply_tdis_wait_done(struct tevent_req *subreq);
6579 /****************************************************************************
6581 Note, on failure here we deallocate and return NULL to allow the caller to
6582 SMB1 return an error of ERRnomem immediately.
6583 ****************************************************************************/
6585 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6587 struct tevent_req *req;
6588 struct reply_tdis_state *state;
6589 struct tevent_req *subreq;
6590 connection_struct *conn = smb1req->conn;
6593 req = tevent_req_create(smb1req, &state,
6594 struct reply_tdis_state);
6598 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6599 if (tevent_req_nomem(state->wait_queue, req)) {
6605 * Make sure that no new request will be able to use this tcon.
6606 * This ensures that once all outstanding fsp->aio_requests
6607 * on this tcon are done, we are safe to close it.
6609 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6611 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6612 if (fsp->conn != conn) {
6616 * Flag the file as close in progress.
6617 * This will prevent any more IO being
6618 * done on it. Not strictly needed, but
6619 * doesn't hurt to flag it as closing.
6621 fsp->fsp_flags.closing = true;
6623 if (fsp->num_aio_requests > 0) {
6625 * Now wait until all aio requests on this fsp are
6628 * We don't set a callback, as we just want to block the
6629 * wait queue and the talloc_free() of fsp->aio_request
6630 * will remove the item from the wait queue.
6632 subreq = tevent_queue_wait_send(fsp->aio_requests,
6633 conn->sconn->ev_ctx,
6635 if (tevent_req_nomem(subreq, req)) {
6643 * Now we add our own waiter to the end of the queue,
6644 * this way we get notified when all pending requests are finished
6645 * and reply to the outstanding SMB1 request.
6647 subreq = tevent_queue_wait_send(state,
6648 conn->sconn->ev_ctx,
6650 if (tevent_req_nomem(subreq, req)) {
6656 * We're really going async - move the SMB1 request from
6657 * a talloc stackframe above us to the sconn talloc-context.
6658 * We need this to stick around until the wait_done
6659 * callback is invoked.
6661 smb1req = talloc_move(smb1req->sconn, &smb1req);
6663 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6668 static void reply_tdis_wait_done(struct tevent_req *subreq)
6670 struct tevent_req *req = tevent_req_callback_data(
6671 subreq, struct tevent_req);
6673 tevent_queue_wait_recv(subreq);
6674 TALLOC_FREE(subreq);
6675 tevent_req_done(req);
6678 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6680 return tevent_req_simple_recv_ntstatus(req);
6683 static void reply_tdis_done(struct tevent_req *req)
6685 struct smb_request *smb1req = tevent_req_callback_data(
6686 req, struct smb_request);
6688 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6692 * Take the profile charge here. Not strictly
6693 * correct but better than the other SMB1 async
6694 * code that double-charges at the moment.
6696 START_PROFILE(SMBtdis);
6698 status = reply_tdis_recv(req);
6700 if (!NT_STATUS_IS_OK(status)) {
6701 TALLOC_FREE(smb1req);
6702 END_PROFILE(SMBtdis);
6703 exit_server(__location__ ": reply_tdis_recv failed");
6708 * As we've been awoken, we may have changed
6709 * directory in the meantime.
6710 * reply_tdis() has the DO_CHDIR flag set.
6712 ok = chdir_current_service(smb1req->conn);
6714 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6715 smb_request_done(smb1req);
6716 END_PROFILE(SMBtdis);
6719 status = smbXsrv_tcon_disconnect(tcon,
6721 if (!NT_STATUS_IS_OK(status)) {
6722 TALLOC_FREE(smb1req);
6723 END_PROFILE(SMBtdis);
6724 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6728 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6729 smb1req->conn = NULL;
6733 reply_outbuf(smb1req, 0, 0);
6735 * The following call is needed to push the
6736 * reply data back out the socket after async
6737 * return. Plus it frees smb1req.
6739 smb_request_done(smb1req);
6740 END_PROFILE(SMBtdis);
6743 /****************************************************************************
6745 conn POINTER CAN BE NULL HERE !
6746 ****************************************************************************/
6748 void reply_echo(struct smb_request *req)
6750 connection_struct *conn = req->conn;
6751 struct smb_perfcount_data local_pcd;
6752 struct smb_perfcount_data *cur_pcd;
6756 START_PROFILE(SMBecho);
6758 smb_init_perfcount_data(&local_pcd);
6761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6762 END_PROFILE(SMBecho);
6766 smb_reverb = SVAL(req->vwv+0, 0);
6768 reply_outbuf(req, 1, req->buflen);
6770 /* copy any incoming data back out */
6771 if (req->buflen > 0) {
6772 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6775 if (smb_reverb > 100) {
6776 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6780 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6782 /* this makes sure we catch the request pcd */
6783 if (seq_num == smb_reverb) {
6784 cur_pcd = &req->pcd;
6786 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6787 cur_pcd = &local_pcd;
6790 SSVAL(req->outbuf,smb_vwv0,seq_num);
6792 show_msg((char *)req->outbuf);
6793 if (!srv_send_smb(req->xconn,
6794 (char *)req->outbuf,
6795 true, req->seqnum+1,
6796 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6798 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6801 DEBUG(3,("echo %d times\n", smb_reverb));
6803 TALLOC_FREE(req->outbuf);
6805 END_PROFILE(SMBecho);
6809 /****************************************************************************
6810 Reply to a printopen.
6811 ****************************************************************************/
6813 void reply_printopen(struct smb_request *req)
6815 connection_struct *conn = req->conn;
6819 START_PROFILE(SMBsplopen);
6822 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6823 END_PROFILE(SMBsplopen);
6827 if (!CAN_PRINT(conn)) {
6828 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6829 END_PROFILE(SMBsplopen);
6833 status = file_new(req, conn, &fsp);
6834 if(!NT_STATUS_IS_OK(status)) {
6835 reply_nterror(req, status);
6836 END_PROFILE(SMBsplopen);
6840 /* Open for exclusive use, write only. */
6841 status = print_spool_open(fsp, NULL, req->vuid);
6843 if (!NT_STATUS_IS_OK(status)) {
6844 file_free(req, fsp);
6845 reply_nterror(req, status);
6846 END_PROFILE(SMBsplopen);
6850 reply_outbuf(req, 1, 0);
6851 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6853 DEBUG(3,("openprint fd=%d %s\n",
6854 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6856 END_PROFILE(SMBsplopen);
6860 /****************************************************************************
6861 Reply to a printclose.
6862 ****************************************************************************/
6864 void reply_printclose(struct smb_request *req)
6866 connection_struct *conn = req->conn;
6870 START_PROFILE(SMBsplclose);
6873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6874 END_PROFILE(SMBsplclose);
6878 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6880 if (!check_fsp(conn, req, fsp)) {
6881 END_PROFILE(SMBsplclose);
6885 if (!CAN_PRINT(conn)) {
6886 reply_force_doserror(req, ERRSRV, ERRerror);
6887 END_PROFILE(SMBsplclose);
6891 DEBUG(3,("printclose fd=%d %s\n",
6892 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6894 status = close_file(req, fsp, NORMAL_CLOSE);
6896 if(!NT_STATUS_IS_OK(status)) {
6897 reply_nterror(req, status);
6898 END_PROFILE(SMBsplclose);
6902 reply_outbuf(req, 0, 0);
6904 END_PROFILE(SMBsplclose);
6908 /****************************************************************************
6909 Reply to a printqueue.
6910 ****************************************************************************/
6912 void reply_printqueue(struct smb_request *req)
6914 const struct loadparm_substitution *lp_sub =
6915 loadparm_s3_global_substitution();
6916 connection_struct *conn = req->conn;
6920 START_PROFILE(SMBsplretq);
6923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6924 END_PROFILE(SMBsplretq);
6928 max_count = SVAL(req->vwv+0, 0);
6929 start_index = SVAL(req->vwv+1, 0);
6931 /* we used to allow the client to get the cnum wrong, but that
6932 is really quite gross and only worked when there was only
6933 one printer - I think we should now only accept it if they
6934 get it right (tridge) */
6935 if (!CAN_PRINT(conn)) {
6936 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6937 END_PROFILE(SMBsplretq);
6941 reply_outbuf(req, 2, 3);
6942 SSVAL(req->outbuf,smb_vwv0,0);
6943 SSVAL(req->outbuf,smb_vwv1,0);
6944 SCVAL(smb_buf(req->outbuf),0,1);
6945 SSVAL(smb_buf(req->outbuf),1,0);
6947 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6948 start_index, max_count));
6951 TALLOC_CTX *mem_ctx = talloc_tos();
6954 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6955 struct rpc_pipe_client *cli = NULL;
6956 struct dcerpc_binding_handle *b = NULL;
6957 struct policy_handle handle;
6958 struct spoolss_DevmodeContainer devmode_ctr;
6959 union spoolss_JobInfo *info;
6961 uint32_t num_to_get;
6965 ZERO_STRUCT(handle);
6967 status = rpc_pipe_open_interface(mem_ctx,
6970 conn->sconn->remote_address,
6971 conn->sconn->local_address,
6972 conn->sconn->msg_ctx,
6974 if (!NT_STATUS_IS_OK(status)) {
6975 DEBUG(0, ("reply_printqueue: "
6976 "could not connect to spoolss: %s\n",
6977 nt_errstr(status)));
6978 reply_nterror(req, status);
6981 b = cli->binding_handle;
6983 ZERO_STRUCT(devmode_ctr);
6985 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6988 SEC_FLAG_MAXIMUM_ALLOWED,
6991 if (!NT_STATUS_IS_OK(status)) {
6992 reply_nterror(req, status);
6995 if (!W_ERROR_IS_OK(werr)) {
6996 reply_nterror(req, werror_to_ntstatus(werr));
7000 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
7008 if (!W_ERROR_IS_OK(werr)) {
7009 reply_nterror(req, werror_to_ntstatus(werr));
7013 if (max_count > 0) {
7014 first = start_index;
7016 first = start_index + max_count + 1;
7019 if (first >= count) {
7022 num_to_get = first + MIN(ABS(max_count), count - first);
7025 for (i = first; i < num_to_get; i++) {
7028 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
7031 uint16_t qrapjobid = pjobid_to_rap(sharename,
7032 info[i].info2.job_id);
7034 if (info[i].info2.status == JOB_STATUS_PRINTING) {
7040 srv_put_dos_date2(p, 0, qtime);
7041 SCVAL(p, 4, qstatus);
7042 SSVAL(p, 5, qrapjobid);
7043 SIVAL(p, 7, info[i].info2.size);
7045 status = srvstr_push(blob, req->flags2, p+12,
7046 info[i].info2.notify_name, 16, STR_ASCII, &len);
7047 if (!NT_STATUS_IS_OK(status)) {
7048 reply_nterror(req, status);
7051 if (message_push_blob(
7054 blob, sizeof(blob))) == -1) {
7055 reply_nterror(req, NT_STATUS_NO_MEMORY);
7061 SSVAL(req->outbuf,smb_vwv0,count);
7062 SSVAL(req->outbuf,smb_vwv1,
7063 (max_count>0?first+count:first-1));
7064 SCVAL(smb_buf(req->outbuf),0,1);
7065 SSVAL(smb_buf(req->outbuf),1,28*count);
7069 DEBUG(3, ("%u entries returned in queue\n",
7073 if (b && is_valid_policy_hnd(&handle)) {
7074 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
7079 END_PROFILE(SMBsplretq);
7083 /****************************************************************************
7084 Reply to a printwrite.
7085 ****************************************************************************/
7087 void reply_printwrite(struct smb_request *req)
7089 connection_struct *conn = req->conn;
7094 START_PROFILE(SMBsplwr);
7097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7098 END_PROFILE(SMBsplwr);
7102 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7104 if (!check_fsp(conn, req, fsp)) {
7105 END_PROFILE(SMBsplwr);
7109 if (!fsp->print_file) {
7110 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7111 END_PROFILE(SMBsplwr);
7115 if (!CHECK_WRITE(fsp)) {
7116 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7117 END_PROFILE(SMBsplwr);
7121 numtowrite = SVAL(req->buf, 1);
7124 * This already protects us against CVE-2017-12163.
7126 if (req->buflen < numtowrite + 3) {
7127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7128 END_PROFILE(SMBsplwr);
7132 data = (const char *)req->buf + 3;
7134 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7135 reply_nterror(req, map_nt_error_from_unix(errno));
7136 END_PROFILE(SMBsplwr);
7140 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7142 END_PROFILE(SMBsplwr);
7146 /****************************************************************************
7148 ****************************************************************************/
7150 void reply_mkdir(struct smb_request *req)
7152 connection_struct *conn = req->conn;
7153 struct smb_filename *smb_dname = NULL;
7154 char *directory = NULL;
7157 TALLOC_CTX *ctx = talloc_tos();
7159 START_PROFILE(SMBmkdir);
7161 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7162 STR_TERMINATE, &status);
7163 if (!NT_STATUS_IS_OK(status)) {
7164 reply_nterror(req, status);
7168 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7169 status = filename_convert(ctx, conn,
7175 if (!NT_STATUS_IS_OK(status)) {
7176 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7177 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7178 ERRSRV, ERRbadpath);
7181 reply_nterror(req, status);
7185 status = create_directory(conn, req, smb_dname);
7187 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7189 if (!NT_STATUS_IS_OK(status)) {
7191 if (!use_nt_status()
7192 && NT_STATUS_EQUAL(status,
7193 NT_STATUS_OBJECT_NAME_COLLISION)) {
7195 * Yes, in the DOS error code case we get a
7196 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7197 * samba4 torture test.
7199 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7202 reply_nterror(req, status);
7206 reply_outbuf(req, 0, 0);
7208 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7210 TALLOC_FREE(smb_dname);
7211 END_PROFILE(SMBmkdir);
7215 /****************************************************************************
7217 ****************************************************************************/
7219 void reply_rmdir(struct smb_request *req)
7221 connection_struct *conn = req->conn;
7222 struct smb_filename *smb_dname = NULL;
7223 char *directory = NULL;
7225 TALLOC_CTX *ctx = talloc_tos();
7226 files_struct *fsp = NULL;
7228 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7230 START_PROFILE(SMBrmdir);
7232 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7233 STR_TERMINATE, &status);
7234 if (!NT_STATUS_IS_OK(status)) {
7235 reply_nterror(req, status);
7239 status = filename_convert(ctx, conn,
7245 if (!NT_STATUS_IS_OK(status)) {
7246 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7247 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7248 ERRSRV, ERRbadpath);
7251 reply_nterror(req, status);
7255 if (is_ntfs_stream_smb_fname(smb_dname)) {
7256 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7260 status = SMB_VFS_CREATE_FILE(
7263 &conn->cwd_fsp, /* dirfsp */
7264 smb_dname, /* fname */
7265 DELETE_ACCESS, /* access_mask */
7266 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7268 FILE_OPEN, /* create_disposition*/
7269 FILE_DIRECTORY_FILE, /* create_options */
7270 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7271 0, /* oplock_request */
7273 0, /* allocation_size */
7274 0, /* private_flags */
7279 NULL, NULL); /* create context */
7281 if (!NT_STATUS_IS_OK(status)) {
7282 if (open_was_deferred(req->xconn, req->mid)) {
7283 /* We have re-scheduled this call. */
7286 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7287 bool ok = defer_smb1_sharing_violation(req);
7292 reply_nterror(req, status);
7296 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7297 if (!NT_STATUS_IS_OK(status)) {
7298 close_file(req, fsp, ERROR_CLOSE);
7299 reply_nterror(req, status);
7303 if (!set_delete_on_close(fsp, true,
7304 conn->session_info->security_token,
7305 conn->session_info->unix_token)) {
7306 close_file(req, fsp, ERROR_CLOSE);
7307 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7311 status = close_file(req, fsp, NORMAL_CLOSE);
7312 if (!NT_STATUS_IS_OK(status)) {
7313 reply_nterror(req, status);
7315 reply_outbuf(req, 0, 0);
7318 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7320 TALLOC_FREE(smb_dname);
7321 END_PROFILE(SMBrmdir);
7325 /*******************************************************************
7326 Resolve wildcards in a filename rename.
7327 ********************************************************************/
7329 static bool resolve_wildcards(TALLOC_CTX *ctx,
7334 char *name2_copy = NULL;
7339 char *p,*p2, *pname1, *pname2;
7341 name2_copy = talloc_strdup(ctx, name2);
7346 pname1 = strrchr_m(name1,'/');
7347 pname2 = strrchr_m(name2_copy,'/');
7349 if (!pname1 || !pname2) {
7353 /* Truncate the copy of name2 at the last '/' */
7356 /* Now go past the '/' */
7360 root1 = talloc_strdup(ctx, pname1);
7361 root2 = talloc_strdup(ctx, pname2);
7363 if (!root1 || !root2) {
7367 p = strrchr_m(root1,'.');
7370 ext1 = talloc_strdup(ctx, p+1);
7372 ext1 = talloc_strdup(ctx, "");
7374 p = strrchr_m(root2,'.');
7377 ext2 = talloc_strdup(ctx, p+1);
7379 ext2 = talloc_strdup(ctx, "");
7382 if (!ext1 || !ext2) {
7390 /* Hmmm. Should this be mb-aware ? */
7393 } else if (*p2 == '*') {
7395 root2 = talloc_asprintf(ctx, "%s%s",
7414 /* Hmmm. Should this be mb-aware ? */
7417 } else if (*p2 == '*') {
7419 ext2 = talloc_asprintf(ctx, "%s%s",
7435 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7440 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7452 /****************************************************************************
7453 Ensure open files have their names updated. Updated to notify other smbd's
7455 ****************************************************************************/
7457 static void rename_open_files(connection_struct *conn,
7458 struct share_mode_lock *lck,
7460 uint32_t orig_name_hash,
7461 const struct smb_filename *smb_fname_dst)
7464 bool did_rename = False;
7466 uint32_t new_name_hash = 0;
7468 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7469 fsp = file_find_di_next(fsp)) {
7470 struct file_id_buf idbuf;
7471 /* fsp_name is a relative path under the fsp. To change this for other
7472 sharepaths we need to manipulate relative paths. */
7473 /* TODO - create the absolute path and manipulate the newname
7474 relative to the sharepath. */
7475 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7478 if (fsp->name_hash != orig_name_hash) {
7481 DBG_DEBUG("renaming file %s "
7482 "(file_id %s) from %s -> %s\n",
7484 file_id_str_buf(fsp->file_id, &idbuf),
7486 smb_fname_str_dbg(smb_fname_dst));
7488 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7489 if (NT_STATUS_IS_OK(status)) {
7491 new_name_hash = fsp->name_hash;
7496 struct file_id_buf idbuf;
7497 DBG_DEBUG("no open files on file_id %s "
7499 file_id_str_buf(id, &idbuf),
7500 smb_fname_str_dbg(smb_fname_dst));
7503 /* Send messages to all smbd's (not ourself) that the name has changed. */
7504 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7505 orig_name_hash, new_name_hash,
7510 /****************************************************************************
7511 We need to check if the source path is a parent directory of the destination
7512 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7513 refuse the rename with a sharing violation. Under UNIX the above call can
7514 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7515 probably need to check that the client is a Windows one before disallowing
7516 this as a UNIX client (one with UNIX extensions) can know the source is a
7517 symlink and make this decision intelligently. Found by an excellent bug
7518 report from <AndyLiebman@aol.com>.
7519 ****************************************************************************/
7521 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7522 const struct smb_filename *smb_fname_dst)
7524 const char *psrc = smb_fname_src->base_name;
7525 const char *pdst = smb_fname_dst->base_name;
7528 if (psrc[0] == '.' && psrc[1] == '/') {
7531 if (pdst[0] == '.' && pdst[1] == '/') {
7534 if ((slen = strlen(psrc)) > strlen(pdst)) {
7537 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7541 * Do the notify calls from a rename
7544 static void notify_rename(connection_struct *conn, bool is_dir,
7545 const struct smb_filename *smb_fname_src,
7546 const struct smb_filename *smb_fname_dst)
7548 char *parent_dir_src = NULL;
7549 char *parent_dir_dst = NULL;
7552 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7553 : FILE_NOTIFY_CHANGE_FILE_NAME;
7555 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7556 &parent_dir_src, NULL) ||
7557 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7558 &parent_dir_dst, NULL)) {
7562 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7563 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7564 smb_fname_src->base_name);
7565 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7566 smb_fname_dst->base_name);
7569 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7570 smb_fname_src->base_name);
7571 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7572 smb_fname_dst->base_name);
7575 /* this is a strange one. w2k3 gives an additional event for
7576 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7577 files, but not directories */
7579 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7580 FILE_NOTIFY_CHANGE_ATTRIBUTES
7581 |FILE_NOTIFY_CHANGE_CREATION,
7582 smb_fname_dst->base_name);
7585 TALLOC_FREE(parent_dir_src);
7586 TALLOC_FREE(parent_dir_dst);
7589 /****************************************************************************
7590 Returns an error if the parent directory for a filename is open in an
7592 ****************************************************************************/
7594 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7595 const struct smb_filename *smb_fname_dst_in)
7597 struct smb_filename *smb_fname_parent = NULL;
7599 files_struct *fsp = NULL;
7603 ok = parent_smb_fname(talloc_tos(),
7608 return NT_STATUS_NO_MEMORY;
7611 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7613 return map_nt_error_from_unix(errno);
7617 * We're only checking on this smbd here, mostly good
7618 * enough.. and will pass tests.
7621 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7622 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7623 fsp = file_find_di_next(fsp)) {
7624 if (fsp->access_mask & DELETE_ACCESS) {
7625 return NT_STATUS_SHARING_VIOLATION;
7628 return NT_STATUS_OK;
7631 /****************************************************************************
7632 Rename an open file - given an fsp.
7633 ****************************************************************************/
7635 NTSTATUS rename_internals_fsp(connection_struct *conn,
7637 const struct smb_filename *smb_fname_dst_in,
7638 const char *dst_original_lcomp,
7640 bool replace_if_exists)
7642 TALLOC_CTX *ctx = talloc_tos();
7643 struct smb_filename *smb_fname_dst = NULL;
7644 NTSTATUS status = NT_STATUS_OK;
7645 struct share_mode_lock *lck = NULL;
7646 uint32_t access_mask = SEC_DIR_ADD_FILE;
7647 bool dst_exists, old_is_stream, new_is_stream;
7650 status = check_name(conn, smb_fname_dst_in);
7651 if (!NT_STATUS_IS_OK(status)) {
7655 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7656 if (!NT_STATUS_IS_OK(status)) {
7660 if (file_has_open_streams(fsp)) {
7661 return NT_STATUS_ACCESS_DENIED;
7664 /* Make a copy of the dst smb_fname structs */
7666 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7667 if (smb_fname_dst == NULL) {
7668 status = NT_STATUS_NO_MEMORY;
7673 * Check for special case with case preserving and not
7674 * case sensitive. If the new last component differs from the original
7675 * last component only by case, then we should allow
7676 * the rename (user is trying to change the case of the
7679 if (!conn->case_sensitive && conn->case_preserve &&
7680 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7681 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7682 char *fname_dst_parent = NULL;
7683 const char *fname_dst_lcomp = NULL;
7684 char *orig_lcomp_path = NULL;
7685 char *orig_lcomp_stream = NULL;
7689 * Split off the last component of the processed
7690 * destination name. We will compare this to
7691 * the split components of dst_original_lcomp.
7693 if (!parent_dirname(ctx,
7694 smb_fname_dst->base_name,
7696 &fname_dst_lcomp)) {
7697 status = NT_STATUS_NO_MEMORY;
7702 * The dst_original_lcomp component contains
7703 * the last_component of the path + stream
7704 * name (if a stream exists).
7706 * Split off the stream name so we
7707 * can check them separately.
7710 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7711 /* POSIX - no stream component. */
7712 orig_lcomp_path = talloc_strdup(ctx,
7713 dst_original_lcomp);
7714 if (orig_lcomp_path == NULL) {
7718 ok = split_stream_filename(ctx,
7721 &orig_lcomp_stream);
7725 TALLOC_FREE(fname_dst_parent);
7726 status = NT_STATUS_NO_MEMORY;
7730 /* If the base names only differ by case, use original. */
7731 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7734 * Replace the modified last component with the
7737 if (!ISDOT(fname_dst_parent)) {
7738 tmp = talloc_asprintf(smb_fname_dst,
7743 tmp = talloc_strdup(smb_fname_dst,
7747 status = NT_STATUS_NO_MEMORY;
7748 TALLOC_FREE(fname_dst_parent);
7749 TALLOC_FREE(orig_lcomp_path);
7750 TALLOC_FREE(orig_lcomp_stream);
7753 TALLOC_FREE(smb_fname_dst->base_name);
7754 smb_fname_dst->base_name = tmp;
7757 /* If the stream_names only differ by case, use original. */
7758 if(!strcsequal(smb_fname_dst->stream_name,
7759 orig_lcomp_stream)) {
7760 /* Use the original stream. */
7761 char *tmp = talloc_strdup(smb_fname_dst,
7764 status = NT_STATUS_NO_MEMORY;
7765 TALLOC_FREE(fname_dst_parent);
7766 TALLOC_FREE(orig_lcomp_path);
7767 TALLOC_FREE(orig_lcomp_stream);
7770 TALLOC_FREE(smb_fname_dst->stream_name);
7771 smb_fname_dst->stream_name = tmp;
7773 TALLOC_FREE(fname_dst_parent);
7774 TALLOC_FREE(orig_lcomp_path);
7775 TALLOC_FREE(orig_lcomp_stream);
7779 * If the src and dest names are identical - including case,
7780 * don't do the rename, just return success.
7783 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7784 strcsequal(fsp->fsp_name->stream_name,
7785 smb_fname_dst->stream_name)) {
7786 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7787 "- returning success\n",
7788 smb_fname_str_dbg(smb_fname_dst)));
7789 status = NT_STATUS_OK;
7793 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7794 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7796 /* Return the correct error code if both names aren't streams. */
7797 if (!old_is_stream && new_is_stream) {
7798 status = NT_STATUS_OBJECT_NAME_INVALID;
7802 if (old_is_stream && !new_is_stream) {
7803 status = NT_STATUS_INVALID_PARAMETER;
7807 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7809 if(!replace_if_exists && dst_exists) {
7810 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7811 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7812 smb_fname_str_dbg(smb_fname_dst)));
7813 status = NT_STATUS_OBJECT_NAME_COLLISION;
7818 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7819 &smb_fname_dst->st);
7820 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7822 /* The file can be open when renaming a stream */
7823 if (dst_fsp && !new_is_stream) {
7824 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7825 status = NT_STATUS_ACCESS_DENIED;
7830 /* Ensure we have a valid stat struct for the source. */
7831 status = vfs_stat_fsp(fsp);
7832 if (!NT_STATUS_IS_OK(status)) {
7836 status = can_rename(conn, fsp, attrs);
7838 if (!NT_STATUS_IS_OK(status)) {
7839 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7840 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7841 smb_fname_str_dbg(smb_fname_dst)));
7842 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7843 status = NT_STATUS_ACCESS_DENIED;
7847 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7848 status = NT_STATUS_ACCESS_DENIED;
7852 /* Do we have rights to move into the destination ? */
7853 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7854 /* We're moving a directory. */
7855 access_mask = SEC_DIR_ADD_SUBDIR;
7857 status = check_parent_access(conn,
7861 if (!NT_STATUS_IS_OK(status)) {
7862 DBG_INFO("check_parent_access on "
7863 "dst %s returned %s\n",
7864 smb_fname_str_dbg(smb_fname_dst),
7869 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7872 * We have the file open ourselves, so not being able to get the
7873 * corresponding share mode lock is a fatal error.
7876 SMB_ASSERT(lck != NULL);
7878 ret = SMB_VFS_RENAMEAT(conn,
7884 uint32_t create_options = fsp->fh->private_options;
7886 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7887 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7888 smb_fname_str_dbg(smb_fname_dst)));
7890 if (!fsp->fsp_flags.is_directory &&
7891 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7892 (lp_map_archive(SNUM(conn)) ||
7893 lp_store_dos_attributes(SNUM(conn)))) {
7894 /* We must set the archive bit on the newly
7896 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7897 uint32_t old_dosmode = dos_mode(conn,
7899 file_set_dosmode(conn,
7901 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7908 fsp->fsp_flags.is_directory,
7912 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7916 * A rename acts as a new file create w.r.t. allowing an initial delete
7917 * on close, probably because in Windows there is a new handle to the
7918 * new file. If initial delete on close was requested but not
7919 * originally set, we need to set it here. This is probably not 100% correct,
7920 * but will work for the CIFSFS client which in non-posix mode
7921 * depends on these semantics. JRA.
7924 if (create_options & FILE_DELETE_ON_CLOSE) {
7925 status = can_set_delete_on_close(fsp, 0);
7927 if (NT_STATUS_IS_OK(status)) {
7928 /* Note that here we set the *initial* delete on close flag,
7929 * not the regular one. The magic gets handled in close. */
7930 fsp->fsp_flags.initial_delete_on_close = true;
7934 status = NT_STATUS_OK;
7940 if (errno == ENOTDIR || errno == EISDIR) {
7941 status = NT_STATUS_OBJECT_NAME_COLLISION;
7943 status = map_nt_error_from_unix(errno);
7946 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7947 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7948 smb_fname_str_dbg(smb_fname_dst)));
7951 TALLOC_FREE(smb_fname_dst);
7956 /****************************************************************************
7957 The guts of the rename command, split out so it may be called by the NT SMB
7959 ****************************************************************************/
7961 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7962 connection_struct *conn,
7963 struct smb_request *req,
7964 struct smb_filename *smb_fname_src,
7965 struct smb_filename *smb_fname_dst,
7966 const char *dst_original_lcomp,
7968 bool replace_if_exists,
7971 uint32_t access_mask)
7973 char *fname_src_dir = NULL;
7974 struct smb_filename *smb_fname_src_dir = NULL;
7975 char *fname_src_mask = NULL;
7977 NTSTATUS status = NT_STATUS_OK;
7978 struct smb_Dir *dir_hnd = NULL;
7979 const char *dname = NULL;
7980 char *talloced = NULL;
7982 int create_options = 0;
7983 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7984 struct smb2_create_blobs *posx = NULL;
7988 * Split the old name into directory and last component
7989 * strings. Note that unix_convert may have stripped off a
7990 * leading ./ from both name and newname if the rename is
7991 * at the root of the share. We need to make sure either both
7992 * name and newname contain a / character or neither of them do
7993 * as this is checked in resolve_wildcards().
7996 /* Split up the directory from the filename/mask. */
7997 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7998 &fname_src_dir, &fname_src_mask);
7999 if (!NT_STATUS_IS_OK(status)) {
8000 status = NT_STATUS_NO_MEMORY;
8005 * We should only check the mangled cache
8006 * here if unix_convert failed. This means
8007 * that the path in 'mask' doesn't exist
8008 * on the file system and so we need to look
8009 * for a possible mangle. This patch from
8010 * Tine Smukavec <valentin.smukavec@hermes.si>.
8013 if (!VALID_STAT(smb_fname_src->st) &&
8014 mangle_is_mangled(fname_src_mask, conn->params)) {
8015 char *new_mask = NULL;
8016 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
8019 TALLOC_FREE(fname_src_mask);
8020 fname_src_mask = new_mask;
8024 if (posix_pathnames) {
8025 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8026 if (!NT_STATUS_IS_OK(status)) {
8027 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8033 if (!src_has_wild) {
8037 * Only one file needs to be renamed. Append the mask back
8038 * onto the directory.
8040 TALLOC_FREE(smb_fname_src->base_name);
8041 if (ISDOT(fname_src_dir)) {
8042 /* Ensure we use canonical names on open. */
8043 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8047 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8052 if (!smb_fname_src->base_name) {
8053 status = NT_STATUS_NO_MEMORY;
8057 DEBUG(3, ("rename_internals: case_sensitive = %d, "
8058 "case_preserve = %d, short case preserve = %d, "
8059 "directory = %s, newname = %s, "
8060 "last_component_dest = %s\n",
8061 conn->case_sensitive, conn->case_preserve,
8062 conn->short_case_preserve,
8063 smb_fname_str_dbg(smb_fname_src),
8064 smb_fname_str_dbg(smb_fname_dst),
8065 dst_original_lcomp));
8067 /* The dest name still may have wildcards. */
8068 if (dest_has_wild) {
8069 char *fname_dst_mod = NULL;
8070 if (!resolve_wildcards(smb_fname_dst,
8071 smb_fname_src->base_name,
8072 smb_fname_dst->base_name,
8074 DEBUG(6, ("rename_internals: resolve_wildcards "
8076 smb_fname_src->base_name,
8077 smb_fname_dst->base_name));
8078 status = NT_STATUS_NO_MEMORY;
8081 TALLOC_FREE(smb_fname_dst->base_name);
8082 smb_fname_dst->base_name = fname_dst_mod;
8085 ZERO_STRUCT(smb_fname_src->st);
8086 if (posix_pathnames) {
8087 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8089 rc = SMB_VFS_STAT(conn, smb_fname_src);
8092 status = map_nt_error_from_unix_common(errno);
8096 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8097 create_options |= FILE_DIRECTORY_FILE;
8100 status = SMB_VFS_CREATE_FILE(
8103 &conn->cwd_fsp, /* dirfsp */
8104 smb_fname_src, /* fname */
8105 access_mask, /* access_mask */
8106 (FILE_SHARE_READ | /* share_access */
8108 FILE_OPEN, /* create_disposition*/
8109 create_options, /* create_options */
8110 0, /* file_attributes */
8111 0, /* oplock_request */
8113 0, /* allocation_size */
8114 0, /* private_flags */
8119 posx, /* in_context_blobs */
8120 NULL); /* out_context_blobs */
8122 if (!NT_STATUS_IS_OK(status)) {
8123 DEBUG(3, ("Could not open rename source %s: %s\n",
8124 smb_fname_str_dbg(smb_fname_src),
8125 nt_errstr(status)));
8129 status = rename_internals_fsp(conn,
8136 close_file(req, fsp, NORMAL_CLOSE);
8138 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8139 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8140 smb_fname_str_dbg(smb_fname_dst)));
8146 * Wildcards - process each file that matches.
8148 if (strequal(fname_src_mask, "????????.???")) {
8149 TALLOC_FREE(fname_src_mask);
8150 fname_src_mask = talloc_strdup(ctx, "*");
8151 if (!fname_src_mask) {
8152 status = NT_STATUS_NO_MEMORY;
8157 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8161 smb_fname_src->twrp,
8162 smb_fname_src->flags);
8163 if (smb_fname_src_dir == NULL) {
8164 status = NT_STATUS_NO_MEMORY;
8168 status = check_name(conn, smb_fname_src_dir);
8169 if (!NT_STATUS_IS_OK(status)) {
8173 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8175 if (dir_hnd == NULL) {
8176 status = map_nt_error_from_unix(errno);
8180 status = NT_STATUS_NO_SUCH_FILE;
8182 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8183 * - gentest fix. JRA
8186 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8188 files_struct *fsp = NULL;
8189 char *destname = NULL;
8190 bool sysdir_entry = False;
8192 /* Quick check for "." and ".." */
8193 if (ISDOT(dname) || ISDOTDOT(dname)) {
8194 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8195 sysdir_entry = True;
8197 TALLOC_FREE(talloced);
8202 if (!is_visible_file(conn,
8207 TALLOC_FREE(talloced);
8211 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8212 TALLOC_FREE(talloced);
8217 status = NT_STATUS_OBJECT_NAME_INVALID;
8221 TALLOC_FREE(smb_fname_src->base_name);
8222 if (ISDOT(fname_src_dir)) {
8223 /* Ensure we use canonical names on open. */
8224 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8228 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8233 if (!smb_fname_src->base_name) {
8234 status = NT_STATUS_NO_MEMORY;
8238 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8239 smb_fname_dst->base_name,
8241 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8242 smb_fname_src->base_name, destname));
8243 TALLOC_FREE(talloced);
8247 status = NT_STATUS_NO_MEMORY;
8251 TALLOC_FREE(smb_fname_dst->base_name);
8252 smb_fname_dst->base_name = destname;
8254 ZERO_STRUCT(smb_fname_src->st);
8255 if (posix_pathnames) {
8256 SMB_VFS_LSTAT(conn, smb_fname_src);
8258 SMB_VFS_STAT(conn, smb_fname_src);
8263 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8264 create_options |= FILE_DIRECTORY_FILE;
8267 status = SMB_VFS_CREATE_FILE(
8270 &conn->cwd_fsp, /* dirfsp */
8271 smb_fname_src, /* fname */
8272 access_mask, /* access_mask */
8273 (FILE_SHARE_READ | /* share_access */
8275 FILE_OPEN, /* create_disposition*/
8276 create_options, /* create_options */
8277 0, /* file_attributes */
8278 0, /* oplock_request */
8280 0, /* allocation_size */
8281 0, /* private_flags */
8286 posx, /* in_context_blobs */
8287 NULL); /* out_context_blobs */
8289 if (!NT_STATUS_IS_OK(status)) {
8290 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8291 "returned %s rename %s -> %s\n",
8293 smb_fname_str_dbg(smb_fname_src),
8294 smb_fname_str_dbg(smb_fname_dst)));
8298 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8299 if (dst_original_lcomp == NULL) {
8300 status = NT_STATUS_NO_MEMORY;
8304 status = rename_internals_fsp(conn,
8311 close_file(req, fsp, NORMAL_CLOSE);
8313 if (!NT_STATUS_IS_OK(status)) {
8314 DEBUG(3, ("rename_internals_fsp returned %s for "
8315 "rename %s -> %s\n", nt_errstr(status),
8316 smb_fname_str_dbg(smb_fname_src),
8317 smb_fname_str_dbg(smb_fname_dst)));
8323 DEBUG(3,("rename_internals: doing rename on %s -> "
8324 "%s\n", smb_fname_str_dbg(smb_fname_src),
8325 smb_fname_str_dbg(smb_fname_src)));
8326 TALLOC_FREE(talloced);
8328 TALLOC_FREE(dir_hnd);
8330 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8331 status = map_nt_error_from_unix(errno);
8336 TALLOC_FREE(talloced);
8337 TALLOC_FREE(smb_fname_src_dir);
8338 TALLOC_FREE(fname_src_dir);
8339 TALLOC_FREE(fname_src_mask);
8343 /****************************************************************************
8345 ****************************************************************************/
8347 void reply_mv(struct smb_request *req)
8349 connection_struct *conn = req->conn;
8351 char *newname = NULL;
8355 bool src_has_wcard = False;
8356 bool dest_has_wcard = False;
8357 TALLOC_CTX *ctx = talloc_tos();
8358 struct smb_filename *smb_fname_src = NULL;
8359 struct smb_filename *smb_fname_dst = NULL;
8360 const char *dst_original_lcomp = NULL;
8361 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8362 (req->posix_pathnames ?
8363 UCF_UNIX_NAME_LOOKUP :
8364 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8365 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8366 (req->posix_pathnames ?
8368 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8369 bool stream_rename = false;
8371 START_PROFILE(SMBmv);
8374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8378 attrs = SVAL(req->vwv+0, 0);
8380 p = (const char *)req->buf + 1;
8381 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
8382 &status, &src_has_wcard);
8383 if (!NT_STATUS_IS_OK(status)) {
8384 reply_nterror(req, status);
8388 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
8389 &status, &dest_has_wcard);
8390 if (!NT_STATUS_IS_OK(status)) {
8391 reply_nterror(req, status);
8395 if (!req->posix_pathnames) {
8396 /* The newname must begin with a ':' if the
8397 name contains a ':'. */
8398 if (strchr_m(name, ':')) {
8399 if (newname[0] != ':') {
8400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8403 stream_rename = true;
8407 status = filename_convert(ctx,
8415 if (!NT_STATUS_IS_OK(status)) {
8416 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8417 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8418 ERRSRV, ERRbadpath);
8421 reply_nterror(req, status);
8425 status = filename_convert(ctx,
8433 if (!NT_STATUS_IS_OK(status)) {
8434 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8435 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8436 ERRSRV, ERRbadpath);
8439 reply_nterror(req, status);
8443 /* Get the last component of the destination for rename_internals(). */
8444 dst_original_lcomp = get_original_lcomp(ctx,
8448 if (dst_original_lcomp == NULL) {
8449 reply_nterror(req, NT_STATUS_NO_MEMORY);
8453 if (stream_rename) {
8454 /* smb_fname_dst->base_name must be the same as
8455 smb_fname_src->base_name. */
8456 TALLOC_FREE(smb_fname_dst->base_name);
8457 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8458 smb_fname_src->base_name);
8459 if (!smb_fname_dst->base_name) {
8460 reply_nterror(req, NT_STATUS_NO_MEMORY);
8465 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8466 smb_fname_str_dbg(smb_fname_dst)));
8468 status = rename_internals(ctx,
8479 if (!NT_STATUS_IS_OK(status)) {
8480 if (open_was_deferred(req->xconn, req->mid)) {
8481 /* We have re-scheduled this call. */
8484 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8485 bool ok = defer_smb1_sharing_violation(req);
8490 reply_nterror(req, status);
8494 reply_outbuf(req, 0, 0);
8496 TALLOC_FREE(smb_fname_src);
8497 TALLOC_FREE(smb_fname_dst);
8502 /*******************************************************************
8503 Copy a file as part of a reply_copy.
8504 ******************************************************************/
8507 * TODO: check error codes on all callers
8510 NTSTATUS copy_file(TALLOC_CTX *ctx,
8511 connection_struct *conn,
8512 struct smb_filename *smb_fname_src,
8513 struct smb_filename *smb_fname_dst,
8516 bool target_is_directory)
8518 struct smb_filename *smb_fname_dst_tmp = NULL;
8520 files_struct *fsp1,*fsp2;
8522 uint32_t new_create_disposition;
8526 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8527 if (smb_fname_dst_tmp == NULL) {
8528 return NT_STATUS_NO_MEMORY;
8532 * If the target is a directory, extract the last component from the
8533 * src filename and append it to the dst filename
8535 if (target_is_directory) {
8538 /* dest/target can't be a stream if it's a directory. */
8539 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8541 p = strrchr_m(smb_fname_src->base_name,'/');
8545 p = smb_fname_src->base_name;
8547 smb_fname_dst_tmp->base_name =
8548 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8550 if (!smb_fname_dst_tmp->base_name) {
8551 status = NT_STATUS_NO_MEMORY;
8556 status = vfs_file_exist(conn, smb_fname_src);
8557 if (!NT_STATUS_IS_OK(status)) {
8561 if (!target_is_directory && count) {
8562 new_create_disposition = FILE_OPEN;
8564 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8567 &new_create_disposition,
8570 status = NT_STATUS_INVALID_PARAMETER;
8575 /* Open the src file for reading. */
8576 status = SMB_VFS_CREATE_FILE(
8579 &conn->cwd_fsp, /* dirfsp */
8580 smb_fname_src, /* fname */
8581 FILE_GENERIC_READ, /* access_mask */
8582 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8583 FILE_OPEN, /* create_disposition*/
8584 0, /* create_options */
8585 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8586 INTERNAL_OPEN_ONLY, /* oplock_request */
8588 0, /* allocation_size */
8589 0, /* private_flags */
8594 NULL, NULL); /* create context */
8596 if (!NT_STATUS_IS_OK(status)) {
8600 dosattrs = dos_mode(conn, smb_fname_src);
8602 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8603 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8606 /* Open the dst file for writing. */
8607 status = SMB_VFS_CREATE_FILE(
8610 &conn->cwd_fsp, /* dirfsp */
8611 smb_fname_dst, /* fname */
8612 FILE_GENERIC_WRITE, /* access_mask */
8613 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8614 new_create_disposition, /* create_disposition*/
8615 0, /* create_options */
8616 dosattrs, /* file_attributes */
8617 INTERNAL_OPEN_ONLY, /* oplock_request */
8619 0, /* allocation_size */
8620 0, /* private_flags */
8625 NULL, NULL); /* create context */
8627 if (!NT_STATUS_IS_OK(status)) {
8628 close_file(NULL, fsp1, ERROR_CLOSE);
8632 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8633 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8635 DEBUG(0, ("error - vfs lseek returned error %s\n",
8637 status = map_nt_error_from_unix(errno);
8638 close_file(NULL, fsp1, ERROR_CLOSE);
8639 close_file(NULL, fsp2, ERROR_CLOSE);
8644 /* Do the actual copy. */
8645 if (smb_fname_src->st.st_ex_size) {
8646 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8651 close_file(NULL, fsp1, NORMAL_CLOSE);
8653 /* Ensure the modtime is set correctly on the destination file. */
8654 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8657 * As we are opening fsp1 read-only we only expect
8658 * an error on close on fsp2 if we are out of space.
8659 * Thus we don't look at the error return from the
8662 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8664 if (!NT_STATUS_IS_OK(status)) {
8668 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8669 status = NT_STATUS_DISK_FULL;
8673 status = NT_STATUS_OK;
8676 TALLOC_FREE(smb_fname_dst_tmp);
8680 /****************************************************************************
8681 Reply to a file copy.
8682 ****************************************************************************/
8684 void reply_copy(struct smb_request *req)
8686 connection_struct *conn = req->conn;
8687 struct smb_filename *smb_fname_src = NULL;
8688 struct smb_filename *smb_fname_src_dir = NULL;
8689 struct smb_filename *smb_fname_dst = NULL;
8690 char *fname_src = NULL;
8691 char *fname_dst = NULL;
8692 char *fname_src_mask = NULL;
8693 char *fname_src_dir = NULL;
8696 int error = ERRnoaccess;
8700 bool target_is_directory=False;
8701 bool source_has_wild = False;
8702 bool dest_has_wild = False;
8704 uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8705 ucf_flags_from_smb_request(req);
8706 uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8707 ucf_flags_from_smb_request(req);
8708 TALLOC_CTX *ctx = talloc_tos();
8710 START_PROFILE(SMBcopy);
8713 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8717 tid2 = SVAL(req->vwv+0, 0);
8718 ofun = SVAL(req->vwv+1, 0);
8719 flags = SVAL(req->vwv+2, 0);
8721 p = (const char *)req->buf;
8722 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8723 &status, &source_has_wild);
8724 if (!NT_STATUS_IS_OK(status)) {
8725 reply_nterror(req, status);
8728 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8729 &status, &dest_has_wild);
8730 if (!NT_STATUS_IS_OK(status)) {
8731 reply_nterror(req, status);
8735 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8737 if (tid2 != conn->cnum) {
8738 /* can't currently handle inter share copies XXXX */
8739 DEBUG(3,("Rejecting inter-share copy\n"));
8740 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8744 status = filename_convert(ctx, conn,
8750 if (!NT_STATUS_IS_OK(status)) {
8751 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8752 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8753 ERRSRV, ERRbadpath);
8756 reply_nterror(req, status);
8760 status = filename_convert(ctx, conn,
8766 if (!NT_STATUS_IS_OK(status)) {
8767 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8768 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8769 ERRSRV, ERRbadpath);
8772 reply_nterror(req, status);
8776 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8778 if ((flags&1) && target_is_directory) {
8779 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8783 if ((flags&2) && !target_is_directory) {
8784 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8788 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8789 /* wants a tree copy! XXXX */
8790 DEBUG(3,("Rejecting tree copy\n"));
8791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8795 /* Split up the directory from the filename/mask. */
8796 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8797 &fname_src_dir, &fname_src_mask);
8798 if (!NT_STATUS_IS_OK(status)) {
8799 reply_nterror(req, NT_STATUS_NO_MEMORY);
8804 * We should only check the mangled cache
8805 * here if unix_convert failed. This means
8806 * that the path in 'mask' doesn't exist
8807 * on the file system and so we need to look
8808 * for a possible mangle. This patch from
8809 * Tine Smukavec <valentin.smukavec@hermes.si>.
8811 if (!VALID_STAT(smb_fname_src->st) &&
8812 mangle_is_mangled(fname_src_mask, conn->params)) {
8813 char *new_mask = NULL;
8814 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8815 &new_mask, conn->params);
8817 /* Use demangled name if one was successfully found. */
8819 TALLOC_FREE(fname_src_mask);
8820 fname_src_mask = new_mask;
8824 if (!source_has_wild) {
8827 * Only one file needs to be copied. Append the mask back onto
8830 TALLOC_FREE(smb_fname_src->base_name);
8831 if (ISDOT(fname_src_dir)) {
8832 /* Ensure we use canonical names on open. */
8833 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8837 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8842 if (!smb_fname_src->base_name) {
8843 reply_nterror(req, NT_STATUS_NO_MEMORY);
8847 if (dest_has_wild) {
8848 char *fname_dst_mod = NULL;
8849 if (!resolve_wildcards(smb_fname_dst,
8850 smb_fname_src->base_name,
8851 smb_fname_dst->base_name,
8853 reply_nterror(req, NT_STATUS_NO_MEMORY);
8856 TALLOC_FREE(smb_fname_dst->base_name);
8857 smb_fname_dst->base_name = fname_dst_mod;
8860 status = check_name(conn, smb_fname_src);
8861 if (!NT_STATUS_IS_OK(status)) {
8862 reply_nterror(req, status);
8866 status = check_name(conn, smb_fname_dst);
8867 if (!NT_STATUS_IS_OK(status)) {
8868 reply_nterror(req, status);
8872 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8873 ofun, count, target_is_directory);
8875 if(!NT_STATUS_IS_OK(status)) {
8876 reply_nterror(req, status);
8882 struct smb_Dir *dir_hnd = NULL;
8883 const char *dname = NULL;
8884 char *talloced = NULL;
8888 * There is a wildcard that requires us to actually read the
8889 * src dir and copy each file matching the mask to the dst.
8890 * Right now streams won't be copied, but this could
8891 * presumably be added with a nested loop for reach dir entry.
8893 SMB_ASSERT(!smb_fname_src->stream_name);
8894 SMB_ASSERT(!smb_fname_dst->stream_name);
8896 smb_fname_src->stream_name = NULL;
8897 smb_fname_dst->stream_name = NULL;
8899 if (strequal(fname_src_mask,"????????.???")) {
8900 TALLOC_FREE(fname_src_mask);
8901 fname_src_mask = talloc_strdup(ctx, "*");
8902 if (!fname_src_mask) {
8903 reply_nterror(req, NT_STATUS_NO_MEMORY);
8908 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8912 smb_fname_src->twrp,
8913 smb_fname_src->flags);
8914 if (smb_fname_src_dir == NULL) {
8915 reply_nterror(req, NT_STATUS_NO_MEMORY);
8919 status = check_name(conn, smb_fname_src_dir);
8920 if (!NT_STATUS_IS_OK(status)) {
8921 reply_nterror(req, status);
8925 dir_hnd = OpenDir(ctx,
8930 if (dir_hnd == NULL) {
8931 status = map_nt_error_from_unix(errno);
8932 reply_nterror(req, status);
8938 /* Iterate over the src dir copying each entry to the dst. */
8939 while ((dname = ReadDirName(dir_hnd, &offset,
8940 &smb_fname_src->st, &talloced))) {
8941 char *destname = NULL;
8943 if (ISDOT(dname) || ISDOTDOT(dname)) {
8944 TALLOC_FREE(talloced);
8948 if (!is_visible_file(conn,
8953 TALLOC_FREE(talloced);
8957 if(!mask_match(dname, fname_src_mask,
8958 conn->case_sensitive)) {
8959 TALLOC_FREE(talloced);
8963 error = ERRnoaccess;
8965 /* Get the src smb_fname struct setup. */
8966 TALLOC_FREE(smb_fname_src->base_name);
8967 if (ISDOT(fname_src_dir)) {
8968 /* Ensure we use canonical names on open. */
8969 smb_fname_src->base_name =
8970 talloc_asprintf(smb_fname_src, "%s",
8973 smb_fname_src->base_name =
8974 talloc_asprintf(smb_fname_src, "%s/%s",
8975 fname_src_dir, dname);
8978 if (!smb_fname_src->base_name) {
8979 TALLOC_FREE(dir_hnd);
8980 TALLOC_FREE(talloced);
8981 reply_nterror(req, NT_STATUS_NO_MEMORY);
8985 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8986 smb_fname_dst->base_name,
8988 TALLOC_FREE(talloced);
8992 TALLOC_FREE(dir_hnd);
8993 TALLOC_FREE(talloced);
8994 reply_nterror(req, NT_STATUS_NO_MEMORY);
8998 TALLOC_FREE(smb_fname_dst->base_name);
8999 smb_fname_dst->base_name = destname;
9001 status = check_name(conn, smb_fname_src);
9002 if (!NT_STATUS_IS_OK(status)) {
9003 TALLOC_FREE(dir_hnd);
9004 TALLOC_FREE(talloced);
9005 reply_nterror(req, status);
9009 status = check_name(conn, smb_fname_dst);
9010 if (!NT_STATUS_IS_OK(status)) {
9011 TALLOC_FREE(dir_hnd);
9012 TALLOC_FREE(talloced);
9013 reply_nterror(req, status);
9017 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
9018 smb_fname_src->base_name,
9019 smb_fname_dst->base_name));
9021 status = copy_file(ctx, conn, smb_fname_src,
9022 smb_fname_dst, ofun, count,
9023 target_is_directory);
9024 if (NT_STATUS_IS_OK(status)) {
9028 TALLOC_FREE(talloced);
9030 TALLOC_FREE(dir_hnd);
9034 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
9038 reply_outbuf(req, 1, 0);
9039 SSVAL(req->outbuf,smb_vwv0,count);
9041 TALLOC_FREE(smb_fname_src);
9042 TALLOC_FREE(smb_fname_src_dir);
9043 TALLOC_FREE(smb_fname_dst);
9044 TALLOC_FREE(fname_src);
9045 TALLOC_FREE(fname_dst);
9046 TALLOC_FREE(fname_src_mask);
9047 TALLOC_FREE(fname_src_dir);
9049 END_PROFILE(SMBcopy);
9054 #define DBGC_CLASS DBGC_LOCKING
9056 /****************************************************************************
9057 Get a lock pid, dealing with large count requests.
9058 ****************************************************************************/
9060 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
9061 bool large_file_format)
9063 if(!large_file_format)
9064 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9066 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9069 /****************************************************************************
9070 Get a lock count, dealing with large count requests.
9071 ****************************************************************************/
9073 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9074 bool large_file_format)
9078 if(!large_file_format) {
9079 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9082 * No BVAL, this is reversed!
9084 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9085 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9091 /****************************************************************************
9092 Get a lock offset, dealing with large offset requests.
9093 ****************************************************************************/
9095 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9096 bool large_file_format)
9098 uint64_t offset = 0;
9100 if(!large_file_format) {
9101 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9104 * No BVAL, this is reversed!
9106 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9107 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9113 struct smbd_do_unlocking_state {
9114 struct files_struct *fsp;
9115 uint16_t num_ulocks;
9116 struct smbd_lock_element *ulocks;
9117 enum brl_flavour lock_flav;
9121 static void smbd_do_unlocking_fn(
9124 bool *pmodified_dependent,
9127 struct smbd_do_unlocking_state *state = private_data;
9128 struct files_struct *fsp = state->fsp;
9129 enum brl_flavour lock_flav = state->lock_flav;
9132 for (i = 0; i < state->num_ulocks; i++) {
9133 struct smbd_lock_element *e = &state->ulocks[i];
9135 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9136 "pid %"PRIu64", file %s\n",
9142 if (e->brltype != UNLOCK_LOCK) {
9143 /* this can only happen with SMB2 */
9144 state->status = NT_STATUS_INVALID_PARAMETER;
9148 state->status = do_unlock(
9149 fsp, e->smblctx, e->count, e->offset, lock_flav);
9151 DBG_DEBUG("do_unlock returned %s\n",
9152 nt_errstr(state->status));
9154 if (!NT_STATUS_IS_OK(state->status)) {
9159 *pmodified_dependent = true;
9162 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9164 uint16_t num_ulocks,
9165 struct smbd_lock_element *ulocks,
9166 enum brl_flavour lock_flav)
9168 struct smbd_do_unlocking_state state = {
9170 .num_ulocks = num_ulocks,
9172 .lock_flav = lock_flav,
9176 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9178 status = share_mode_do_locked(
9179 fsp->file_id, smbd_do_unlocking_fn, &state);
9181 if (!NT_STATUS_IS_OK(status)) {
9182 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9186 if (!NT_STATUS_IS_OK(state.status)) {
9187 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9189 return state.status;
9192 return NT_STATUS_OK;
9195 /****************************************************************************
9196 Reply to a lockingX request.
9197 ****************************************************************************/
9199 static void reply_lockingx_done(struct tevent_req *subreq);
9201 void reply_lockingX(struct smb_request *req)
9203 connection_struct *conn = req->conn;
9205 unsigned char locktype;
9206 enum brl_type brltype;
9207 unsigned char oplocklevel;
9208 uint16_t num_ulocks;
9210 int32_t lock_timeout;
9212 const uint8_t *data;
9213 bool large_file_format;
9214 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9215 struct smbd_lock_element *locks = NULL;
9216 struct tevent_req *subreq = NULL;
9218 START_PROFILE(SMBlockingX);
9221 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9222 END_PROFILE(SMBlockingX);
9226 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9227 locktype = CVAL(req->vwv+3, 0);
9228 oplocklevel = CVAL(req->vwv+3, 1);
9229 num_ulocks = SVAL(req->vwv+6, 0);
9230 num_locks = SVAL(req->vwv+7, 0);
9231 lock_timeout = IVAL(req->vwv+4, 0);
9232 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9234 if (!check_fsp(conn, req, fsp)) {
9235 END_PROFILE(SMBlockingX);
9241 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9242 /* we don't support these - and CANCEL_LOCK makes w2k
9243 and XP reboot so I don't really want to be
9244 compatible! (tridge) */
9245 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9246 END_PROFILE(SMBlockingX);
9250 /* Check if this is an oplock break on a file
9251 we have granted an oplock on.
9253 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9254 /* Client can insist on breaking to none. */
9255 bool break_to_none = (oplocklevel == 0);
9258 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9259 "for %s\n", (unsigned int)oplocklevel,
9260 fsp_fnum_dbg(fsp)));
9263 * Make sure we have granted an exclusive or batch oplock on
9267 if (fsp->oplock_type == 0) {
9269 /* The Samba4 nbench simulator doesn't understand
9270 the difference between break to level2 and break
9271 to none from level2 - it sends oplock break
9272 replies in both cases. Don't keep logging an error
9273 message here - just ignore it. JRA. */
9275 DEBUG(5,("reply_lockingX: Error : oplock break from "
9276 "client for %s (oplock=%d) and no "
9277 "oplock granted on this file (%s).\n",
9278 fsp_fnum_dbg(fsp), fsp->oplock_type,
9281 /* if this is a pure oplock break request then don't
9283 if (num_locks == 0 && num_ulocks == 0) {
9284 END_PROFILE(SMBlockingX);
9288 END_PROFILE(SMBlockingX);
9289 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9293 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9295 result = remove_oplock(fsp);
9297 result = downgrade_oplock(fsp);
9301 DEBUG(0, ("reply_lockingX: error in removing "
9302 "oplock on file %s\n", fsp_str_dbg(fsp)));
9303 /* Hmmm. Is this panic justified? */
9304 smb_panic("internal tdb error");
9307 /* if this is a pure oplock break request then don't send a
9309 if (num_locks == 0 && num_ulocks == 0) {
9310 /* Sanity check - ensure a pure oplock break is not a
9312 if (CVAL(req->vwv+0, 0) != 0xff) {
9313 DEBUG(0,("reply_lockingX: Error : pure oplock "
9314 "break is a chained %d request !\n",
9315 (unsigned int)CVAL(req->vwv+0, 0)));
9317 END_PROFILE(SMBlockingX);
9323 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9325 END_PROFILE(SMBlockingX);
9329 if (num_ulocks != 0) {
9330 struct smbd_lock_element *ulocks = NULL;
9333 ulocks = talloc_array(
9334 req, struct smbd_lock_element, num_ulocks);
9335 if (ulocks == NULL) {
9336 reply_nterror(req, NT_STATUS_NO_MEMORY);
9337 END_PROFILE(SMBlockingX);
9342 * Data now points at the beginning of the list of
9343 * smb_unlkrng structs
9345 for (i = 0; i < num_ulocks; i++) {
9346 ulocks[i].req_guid = smbd_request_guid(req,
9348 ulocks[i].smblctx = get_lock_pid(
9349 data, i, large_file_format);
9350 ulocks[i].count = get_lock_count(
9351 data, i, large_file_format);
9352 ulocks[i].offset = get_lock_offset(
9353 data, i, large_file_format);
9354 ulocks[i].brltype = UNLOCK_LOCK;
9358 * Unlock cancels pending locks
9361 ok = smbd_smb1_brl_finish_by_lock(
9368 reply_outbuf(req, 2, 0);
9369 SSVAL(req->outbuf, smb_vwv0, 0xff);
9370 SSVAL(req->outbuf, smb_vwv1, 0);
9371 END_PROFILE(SMBlockingX);
9375 status = smbd_do_unlocking(
9376 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9377 TALLOC_FREE(ulocks);
9378 if (!NT_STATUS_IS_OK(status)) {
9379 END_PROFILE(SMBlockingX);
9380 reply_nterror(req, status);
9385 /* Now do any requested locks */
9386 data += ((large_file_format ? 20 : 10)*num_ulocks);
9388 /* Data now points at the beginning of the list
9389 of smb_lkrng structs */
9391 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9392 brltype = READ_LOCK;
9394 brltype = WRITE_LOCK;
9397 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9398 if (locks == NULL) {
9399 reply_nterror(req, NT_STATUS_NO_MEMORY);
9400 END_PROFILE(SMBlockingX);
9404 for (i = 0; i < num_locks; i++) {
9405 locks[i].req_guid = smbd_request_guid(req, i),
9406 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9407 locks[i].count = get_lock_count(data, i, large_file_format);
9408 locks[i].offset = get_lock_offset(data, i, large_file_format);
9409 locks[i].brltype = brltype;
9412 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9416 if (num_locks == 0) {
9417 /* See smbtorture3 lock11 test */
9418 reply_outbuf(req, 2, 0);
9419 /* andx chain ends */
9420 SSVAL(req->outbuf, smb_vwv0, 0xff);
9421 SSVAL(req->outbuf, smb_vwv1, 0);
9422 END_PROFILE(SMBlockingX);
9426 ok = smbd_smb1_brl_finish_by_lock(
9430 locks[0], /* Windows only cancels the first lock */
9431 NT_STATUS_FILE_LOCK_CONFLICT);
9434 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9435 END_PROFILE(SMBlockingX);
9439 reply_outbuf(req, 2, 0);
9440 SSVAL(req->outbuf, smb_vwv0, 0xff);
9441 SSVAL(req->outbuf, smb_vwv1, 0);
9442 END_PROFILE(SMBlockingX);
9446 subreq = smbd_smb1_do_locks_send(
9456 if (subreq == NULL) {
9457 reply_nterror(req, NT_STATUS_NO_MEMORY);
9458 END_PROFILE(SMBlockingX);
9461 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9462 END_PROFILE(SMBlockingX);
9465 static void reply_lockingx_done(struct tevent_req *subreq)
9467 struct smb_request *req = NULL;
9471 START_PROFILE(SMBlockingX);
9473 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9476 status = smbd_smb1_do_locks_recv(subreq);
9477 TALLOC_FREE(subreq);
9479 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9481 if (NT_STATUS_IS_OK(status)) {
9482 reply_outbuf(req, 2, 0);
9483 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9484 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9486 reply_nterror(req, status);
9489 ok = srv_send_smb(req->xconn,
9490 (char *)req->outbuf,
9493 IS_CONN_ENCRYPTED(req->conn),
9496 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9499 END_PROFILE(SMBlockingX);
9503 #define DBGC_CLASS DBGC_ALL
9505 /****************************************************************************
9506 Reply to a SMBreadbmpx (read block multiplex) request.
9507 Always reply with an error, if someone has a platform really needs this,
9508 please contact vl@samba.org
9509 ****************************************************************************/
9511 void reply_readbmpx(struct smb_request *req)
9513 START_PROFILE(SMBreadBmpx);
9514 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9515 END_PROFILE(SMBreadBmpx);
9519 /****************************************************************************
9520 Reply to a SMBreadbs (read block multiplex secondary) request.
9521 Always reply with an error, if someone has a platform really needs this,
9522 please contact vl@samba.org
9523 ****************************************************************************/
9525 void reply_readbs(struct smb_request *req)
9527 START_PROFILE(SMBreadBs);
9528 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9529 END_PROFILE(SMBreadBs);
9533 /****************************************************************************
9534 Reply to a SMBsetattrE.
9535 ****************************************************************************/
9537 void reply_setattrE(struct smb_request *req)
9539 connection_struct *conn = req->conn;
9540 struct smb_file_time ft;
9544 START_PROFILE(SMBsetattrE);
9545 init_smb_file_time(&ft);
9548 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9552 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9554 if(!fsp || (fsp->conn != conn)) {
9555 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9560 * Convert the DOS times into unix times.
9563 ft.atime = time_t_to_full_timespec(
9564 srv_make_unix_date2(req->vwv+3));
9565 ft.mtime = time_t_to_full_timespec(
9566 srv_make_unix_date2(req->vwv+5));
9567 ft.create_time = time_t_to_full_timespec(
9568 srv_make_unix_date2(req->vwv+1));
9570 reply_outbuf(req, 0, 0);
9573 * Patch from Ray Frush <frush@engr.colostate.edu>
9574 * Sometimes times are sent as zero - ignore them.
9577 /* Ensure we have a valid stat struct for the source. */
9578 status = vfs_stat_fsp(fsp);
9579 if (!NT_STATUS_IS_OK(status)) {
9580 reply_nterror(req, status);
9584 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9585 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9589 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9590 if (!NT_STATUS_IS_OK(status)) {
9591 reply_nterror(req, status);
9595 if (fsp->fsp_flags.modified) {
9596 trigger_write_time_update_immediate(fsp);
9599 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9602 (unsigned int)ft.atime.tv_sec,
9603 (unsigned int)ft.mtime.tv_sec,
9604 (unsigned int)ft.create_time.tv_sec
9607 END_PROFILE(SMBsetattrE);
9612 /* Back from the dead for OS/2..... JRA. */
9614 /****************************************************************************
9615 Reply to a SMBwritebmpx (write block multiplex primary) request.
9616 Always reply with an error, if someone has a platform really needs this,
9617 please contact vl@samba.org
9618 ****************************************************************************/
9620 void reply_writebmpx(struct smb_request *req)
9622 START_PROFILE(SMBwriteBmpx);
9623 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9624 END_PROFILE(SMBwriteBmpx);
9628 /****************************************************************************
9629 Reply to a SMBwritebs (write block multiplex secondary) request.
9630 Always reply with an error, if someone has a platform really needs this,
9631 please contact vl@samba.org
9632 ****************************************************************************/
9634 void reply_writebs(struct smb_request *req)
9636 START_PROFILE(SMBwriteBs);
9637 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9638 END_PROFILE(SMBwriteBs);
9642 /****************************************************************************
9643 Reply to a SMBgetattrE.
9644 ****************************************************************************/
9646 void reply_getattrE(struct smb_request *req)
9648 connection_struct *conn = req->conn;
9651 struct timespec create_ts;
9654 START_PROFILE(SMBgetattrE);
9657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9658 END_PROFILE(SMBgetattrE);
9662 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9664 if(!fsp || (fsp->conn != conn)) {
9665 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9666 END_PROFILE(SMBgetattrE);
9670 /* Do an fstat on this file */
9671 status = vfs_stat_fsp(fsp);
9672 if (!NT_STATUS_IS_OK(status)) {
9673 reply_nterror(req, status);
9674 END_PROFILE(SMBgetattrE);
9678 mode = dos_mode(conn, fsp->fsp_name);
9681 * Convert the times into dos times. Set create
9682 * date to be last modify date as UNIX doesn't save
9686 reply_outbuf(req, 11, 0);
9688 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9689 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9690 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9691 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9692 /* Should we check pending modtime here ? JRA */
9693 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9694 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9696 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9697 SIVAL(req->outbuf, smb_vwv6, 0);
9698 SIVAL(req->outbuf, smb_vwv8, 0);
9700 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9701 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9702 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9704 SSVAL(req->outbuf,smb_vwv10, mode);
9706 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9708 END_PROFILE(SMBgetattrE);