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 "locking/share_mode_lock.h"
32 #include "smbd/smbd.h"
33 #include "smbd/globals.h"
34 #include "fake_file.h"
35 #include "rpc_client/rpc_client.h"
36 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
37 #include "rpc_client/cli_spoolss.h"
38 #include "rpc_client/init_spoolss.h"
39 #include "rpc_server/rpc_ncacn_np.h"
40 #include "libcli/security/security.h"
41 #include "libsmb/nmblib.h"
43 #include "smbprofile.h"
44 #include "../lib/tsocket/tsocket.h"
45 #include "lib/util/tevent_ntstatus.h"
46 #include "libcli/smb/smb_signing.h"
47 #include "lib/util/sys_rw_data.h"
48 #include "librpc/gen_ndr/open_files.h"
49 #include "smb1_utils.h"
50 #include "libcli/smb/smb2_posix.h"
51 #include "lib/util/string_wrappers.h"
53 /****************************************************************************
54 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
55 path or anything including wildcards.
56 We're assuming here that '/' is not the second byte in any multibyte char
57 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
59 ****************************************************************************/
61 /* Custom version for processing POSIX paths. */
62 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
64 static NTSTATUS check_path_syntax_internal(char *path,
69 NTSTATUS ret = NT_STATUS_OK;
70 bool start_of_name_component = True;
71 bool stream_started = false;
72 bool last_component_contains_wcard = false;
79 return NT_STATUS_OBJECT_NAME_INVALID;
82 return NT_STATUS_OBJECT_NAME_INVALID;
84 if (strchr_m(&s[1], ':')) {
85 return NT_STATUS_OBJECT_NAME_INVALID;
91 if ((*s == ':') && !posix_path && !stream_started) {
92 if (last_component_contains_wcard) {
93 return NT_STATUS_OBJECT_NAME_INVALID;
95 /* Stream names allow more characters than file names.
96 We're overloading posix_path here to allow a wider
97 range of characters. If stream_started is true this
98 is still a Windows path even if posix_path is true.
101 stream_started = true;
102 start_of_name_component = false;
106 return NT_STATUS_OBJECT_NAME_INVALID;
110 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
112 * Safe to assume is not the second part of a mb char
113 * as this is handled below.
115 /* Eat multiple '/' or '\\' */
116 while (IS_PATH_SEP(*s,posix_path)) {
119 if ((d != path) && (*s != '\0')) {
120 /* We only care about non-leading or trailing '/' or '\\' */
124 start_of_name_component = True;
126 last_component_contains_wcard = false;
130 if (start_of_name_component) {
131 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
132 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
135 * No mb char starts with '.' so we're safe checking the directory separator here.
138 /* If we just added a '/' - delete it */
139 if ((d > path) && (*(d-1) == '/')) {
144 /* Are we at the start ? Can't go back further if so. */
146 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
149 /* Go back one level... */
150 /* We know this is safe as '/' cannot be part of a mb sequence. */
151 /* NOTE - if this assumption is invalid we are not in good shape... */
152 /* Decrement d first as d points to the *next* char to write into. */
153 for (d--; d > path; d--) {
157 s += 2; /* Else go past the .. */
158 /* We're still at the start of a name component, just the previous one. */
161 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
173 if (*s <= 0x1f || *s == '|') {
174 return NT_STATUS_OBJECT_NAME_INVALID;
182 last_component_contains_wcard = true;
191 /* Get the size of the next MB character. */
192 next_codepoint(s,&siz);
210 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
212 return NT_STATUS_INVALID_PARAMETER;
215 start_of_name_component = False;
223 /****************************************************************************
224 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
225 No wildcards allowed.
226 ****************************************************************************/
228 NTSTATUS check_path_syntax(char *path)
230 return check_path_syntax_internal(path, false);
233 /****************************************************************************
234 Check the path for a POSIX client.
235 We're assuming here that '/' is not the second byte in any multibyte char
236 set (a safe assumption).
237 ****************************************************************************/
239 NTSTATUS check_path_syntax_posix(char *path)
241 return check_path_syntax_internal(path, true);
244 /****************************************************************************
245 Pull a string and check the path allowing a wildcard - provide for error return.
246 Passes in posix flag.
247 ****************************************************************************/
249 static size_t srvstr_get_path_internal(TALLOC_CTX *ctx,
250 const char *base_ptr,
256 bool posix_pathnames,
263 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
267 *err = NT_STATUS_INVALID_PARAMETER;
271 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
273 * For a DFS path the function parse_dfs_path()
274 * will do the path processing, just make a copy.
280 if (posix_pathnames) {
281 *err = check_path_syntax_posix(*pp_dest);
283 *err = check_path_syntax(*pp_dest);
289 /****************************************************************************
290 Pull a string and check the path - provide for error return.
291 ****************************************************************************/
293 size_t srvstr_get_path(TALLOC_CTX *ctx,
294 const char *base_ptr,
302 return srvstr_get_path_internal(ctx,
313 /****************************************************************************
314 Pull a string and check the path - provide for error return.
315 posix_pathnames version.
316 ****************************************************************************/
318 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
319 const char *base_ptr,
327 return srvstr_get_path_internal(ctx,
339 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
340 char **pp_dest, const char *src, int flags,
343 ssize_t bufrem = smbreq_bufrem(req, src);
346 *err = NT_STATUS_INVALID_PARAMETER;
350 if (req->posix_pathnames) {
351 return srvstr_get_path_internal(mem_ctx,
352 (const char *)req->inbuf,
361 return srvstr_get_path_internal(mem_ctx,
362 (const char *)req->inbuf,
374 * pull a string from the smb_buf part of a packet. In this case the
375 * string can either be null terminated or it can be terminated by the
376 * end of the smbbuf area
378 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
379 char **dest, const uint8_t *src, int flags)
381 ssize_t bufrem = smbreq_bufrem(req, src);
387 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
391 /****************************************************************************
392 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
393 ****************************************************************************/
395 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
398 if ((fsp == NULL) || (conn == NULL)) {
399 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
402 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
403 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
409 /****************************************************************************
410 Check if we have a correct fsp pointing to a file.
411 ****************************************************************************/
413 bool check_fsp(connection_struct *conn, struct smb_request *req,
416 if (!check_fsp_open(conn, req, fsp)) {
419 if (fsp->fsp_flags.is_directory) {
420 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
423 if (fsp_get_pathref_fd(fsp) == -1) {
424 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
427 fsp->num_smb_operations++;
431 /****************************************************************************
432 Check if we have a correct fsp pointing to a quota fake file. Replacement for
433 the CHECK_NTQUOTA_HANDLE_OK macro.
434 ****************************************************************************/
436 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
439 if (!check_fsp_open(conn, req, fsp)) {
443 if (fsp->fsp_flags.is_directory) {
447 if (fsp->fake_file_handle == NULL) {
451 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
455 if (fsp->fake_file_handle->private_data == NULL) {
462 /****************************************************************************
463 Return the port number we've bound to on a socket.
464 ****************************************************************************/
466 static int get_socket_port(int fd)
468 struct samba_sockaddr saddr = {
469 .sa_socklen = sizeof(struct sockaddr_storage),
476 if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
477 int level = (errno == ENOTCONN) ? 2 : 0;
478 DEBUG(level, ("getsockname failed. Error was %s\n",
483 #if defined(HAVE_IPV6)
484 if (saddr.u.sa.sa_family == AF_INET6) {
485 return ntohs(saddr.u.in6.sin6_port);
488 if (saddr.u.sa.sa_family == AF_INET) {
489 return ntohs(saddr.u.in.sin_port);
494 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
495 const char *name, int name_type)
498 char *trim_name_type;
499 const char *retarget_parm;
502 int retarget_type = 0x20;
503 int retarget_port = NBT_SMB_PORT;
504 struct sockaddr_storage retarget_addr;
505 struct sockaddr_in *in_addr;
509 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
513 trim_name = talloc_strdup(talloc_tos(), name);
514 if (trim_name == NULL) {
517 trim_char(trim_name, ' ', ' ');
519 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
521 if (trim_name_type == NULL) {
525 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
526 trim_name_type, NULL);
527 if (retarget_parm == NULL) {
528 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
531 if (retarget_parm == NULL) {
535 retarget = talloc_strdup(trim_name, retarget_parm);
536 if (retarget == NULL) {
540 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
542 p = strchr(retarget, ':');
545 retarget_port = atoi(p);
548 p = strchr_m(retarget, '#');
551 if (sscanf(p, "%x", &retarget_type) != 1) {
556 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
558 DEBUG(10, ("could not resolve %s\n", retarget));
562 if (retarget_addr.ss_family != AF_INET) {
563 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
567 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
569 _smb_setlen(outbuf, 6);
570 SCVAL(outbuf, 0, 0x84);
571 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
572 *(uint16_t *)(outbuf+8) = htons(retarget_port);
574 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
576 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
582 TALLOC_FREE(trim_name);
586 static void reply_called_name_not_present(char *outbuf)
588 smb_setlen(outbuf, 1);
589 SCVAL(outbuf, 0, 0x83);
590 SCVAL(outbuf, 4, 0x82);
593 /****************************************************************************
594 Reply to a (netbios-level) special message.
595 ****************************************************************************/
597 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
599 struct smbd_server_connection *sconn = xconn->client->sconn;
600 int msg_type = CVAL(inbuf,0);
601 int msg_flags = CVAL(inbuf,1);
603 * We only really use 4 bytes of the outbuf, but for the smb_setlen
604 * calculation & friends (srv_send_smb uses that) we need the full smb
607 char outbuf[smb_size];
609 memset(outbuf, '\0', sizeof(outbuf));
611 smb_setlen(outbuf,0);
614 case NBSSrequest: /* session request */
616 /* inbuf_size is guarenteed to be at least 4. */
618 int name_type1, name_type2;
619 int name_len1, name_len2;
623 if (xconn->transport.nbt.got_session) {
624 exit_server_cleanly("multiple session request not permitted");
627 SCVAL(outbuf,0,NBSSpositive);
630 /* inbuf_size is guaranteed to be at least 4. */
631 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
632 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
633 DEBUG(0,("Invalid name length in session request\n"));
634 reply_called_name_not_present(outbuf);
637 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
638 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
639 DEBUG(0,("Invalid name length in session request\n"));
640 reply_called_name_not_present(outbuf);
644 name_type1 = name_extract((unsigned char *)inbuf,
645 inbuf_size,(unsigned int)4,name1);
646 name_type2 = name_extract((unsigned char *)inbuf,
647 inbuf_size,(unsigned int)(4 + name_len1),name2);
649 if (name_type1 == -1 || name_type2 == -1) {
650 DEBUG(0,("Invalid name type in session request\n"));
651 reply_called_name_not_present(outbuf);
655 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
656 name1, name_type1, name2, name_type2));
658 if (netbios_session_retarget(xconn, name1, name_type1)) {
659 exit_server_cleanly("retargeted client");
663 * Windows NT/2k uses "*SMBSERVER" and XP uses
664 * "*SMBSERV" arrggg!!!
666 if (strequal(name1, "*SMBSERVER ")
667 || strequal(name1, "*SMBSERV ")) {
670 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
673 exit_server_cleanly("could not allocate raddr");
676 fstrcpy(name1, raddr);
679 set_local_machine_name(name1, True);
680 set_remote_machine_name(name2, True);
682 if (is_ipaddress(sconn->remote_hostname)) {
683 char *p = discard_const_p(char, sconn->remote_hostname);
687 sconn->remote_hostname = talloc_strdup(sconn,
688 get_remote_machine_name());
689 if (sconn->remote_hostname == NULL) {
690 exit_server_cleanly("could not copy remote name");
692 xconn->remote_hostname = sconn->remote_hostname;
695 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
696 get_local_machine_name(), get_remote_machine_name(),
699 if (name_type2 == 'R') {
700 /* We are being asked for a pathworks session ---
702 reply_called_name_not_present(outbuf);
706 reload_services(sconn, conn_snum_used, true);
709 xconn->transport.nbt.got_session = true;
713 case 0x89: /* session keepalive request
714 (some old clients produce this?) */
715 SCVAL(outbuf,0,NBSSkeepalive);
719 case NBSSpositive: /* positive session response */
720 case NBSSnegative: /* negative session response */
721 case NBSSretarget: /* retarget session response */
722 DEBUG(0,("Unexpected session response\n"));
725 case NBSSkeepalive: /* session keepalive */
730 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
731 msg_type, msg_flags));
733 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
734 exit_server_cleanly("reply_special: srv_send_smb failed.");
737 if (CVAL(outbuf, 0) != 0x82) {
738 exit_server_cleanly("invalid netbios session");
743 /****************************************************************************
745 conn POINTER CAN BE NULL HERE !
746 ****************************************************************************/
748 void reply_tcon(struct smb_request *req)
750 connection_struct *conn = req->conn;
752 char *service_buf = NULL;
753 char *password = NULL;
759 TALLOC_CTX *ctx = talloc_tos();
760 struct smbXsrv_connection *xconn = req->xconn;
761 NTTIME now = timeval_to_nttime(&req->request_time);
763 START_PROFILE(SMBtcon);
765 if (req->buflen < 4) {
766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
767 END_PROFILE(SMBtcon);
772 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
774 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
776 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
779 if (service_buf == NULL || password == NULL || dev == NULL) {
780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
781 END_PROFILE(SMBtcon);
784 p2 = strrchr_m(service_buf,'\\');
788 service = service_buf;
791 conn = make_connection(req, now, service, dev,
792 req->vuid,&nt_status);
796 reply_nterror(req, nt_status);
797 END_PROFILE(SMBtcon);
801 reply_outbuf(req, 2, 0);
802 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
803 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
804 SSVAL(req->outbuf,smb_tid,conn->cnum);
806 DEBUG(3,("tcon service=%s cnum=%d\n",
807 service, conn->cnum));
809 END_PROFILE(SMBtcon);
813 /****************************************************************************
814 Reply to a tcon and X.
815 conn POINTER CAN BE NULL HERE !
816 ****************************************************************************/
818 void reply_tcon_and_X(struct smb_request *req)
820 const struct loadparm_substitution *lp_sub =
821 loadparm_s3_global_substitution();
822 connection_struct *conn = req->conn;
823 const char *service = NULL;
824 TALLOC_CTX *ctx = talloc_tos();
825 /* what the client thinks the device is */
826 char *client_devicetype = NULL;
827 /* what the server tells the client the share represents */
828 const char *server_devicetype;
835 struct smbXsrv_session *session = NULL;
836 NTTIME now = timeval_to_nttime(&req->request_time);
837 bool session_key_updated = false;
838 uint16_t optional_support = 0;
839 struct smbXsrv_connection *xconn = req->xconn;
841 START_PROFILE(SMBtconX);
844 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
845 END_PROFILE(SMBtconX);
849 passlen = SVAL(req->vwv+3, 0);
850 tcon_flags = SVAL(req->vwv+2, 0);
852 /* we might have to close an old one */
853 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
854 struct smbXsrv_tcon *tcon;
862 * TODO: cancel all outstanding requests on the tcon
864 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
865 if (!NT_STATUS_IS_OK(status)) {
866 DEBUG(0, ("reply_tcon_and_X: "
867 "smbXsrv_tcon_disconnect() failed: %s\n",
870 * If we hit this case, there is something completely
871 * wrong, so we better disconnect the transport connection.
873 END_PROFILE(SMBtconX);
874 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
880 * This tree id is gone. Make sure we can't re-use it
886 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
887 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
888 END_PROFILE(SMBtconX);
892 if (xconn->smb1.negprot.encrypted_passwords) {
893 p = req->buf + passlen;
895 p = req->buf + passlen + 1;
898 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
902 END_PROFILE(SMBtconX);
907 * the service name can be either: \\server\share
908 * or share directly like on the DELL PowerVault 705
911 q = strchr_m(path+2,'\\');
913 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
914 END_PROFILE(SMBtconX);
922 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
923 &client_devicetype, p,
924 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
926 if (client_devicetype == NULL) {
927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
928 END_PROFILE(SMBtconX);
932 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
934 nt_status = smb1srv_session_lookup(xconn,
935 req->vuid, now, &session);
936 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
937 reply_force_doserror(req, ERRSRV, ERRbaduid);
938 END_PROFILE(SMBtconX);
941 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
942 reply_nterror(req, nt_status);
943 END_PROFILE(SMBtconX);
946 if (!NT_STATUS_IS_OK(nt_status)) {
947 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
948 END_PROFILE(SMBtconX);
952 if (session->global->auth_session_info == NULL) {
953 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
954 END_PROFILE(SMBtconX);
959 * If there is no application key defined yet
962 * This means we setup the application key on the
963 * first tcon that happens via the given session.
965 * Once the application key is defined, it does not
968 if (session->global->application_key.length == 0 &&
969 smb2_signing_key_valid(session->global->signing_key))
971 struct smbXsrv_session *x = session;
972 struct auth_session_info *session_info =
973 session->global->auth_session_info;
974 uint8_t session_key[16];
976 ZERO_STRUCT(session_key);
977 memcpy(session_key, x->global->signing_key->blob.data,
978 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
981 * The application key is truncated/padded to 16 bytes
983 x->global->application_key = data_blob_talloc(x->global,
985 sizeof(session_key));
986 ZERO_STRUCT(session_key);
987 if (x->global->application_key.data == NULL) {
988 reply_nterror(req, NT_STATUS_NO_MEMORY);
989 END_PROFILE(SMBtconX);
993 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
996 status = smb_key_derivation(x->global->application_key.data,
997 x->global->application_key.length,
998 x->global->application_key.data);
999 if (!NT_STATUS_IS_OK(status)) {
1000 DBG_ERR("smb_key_derivation failed: %s\n",
1002 END_PROFILE(SMBtconX);
1005 optional_support |= SMB_EXTENDED_SIGNATURES;
1009 * Place the application key into the session_info
1011 data_blob_clear_free(&session_info->session_key);
1012 session_info->session_key = data_blob_dup_talloc(session_info,
1013 x->global->application_key);
1014 if (session_info->session_key.data == NULL) {
1015 data_blob_clear_free(&x->global->application_key);
1016 reply_nterror(req, NT_STATUS_NO_MEMORY);
1017 END_PROFILE(SMBtconX);
1020 session_key_updated = true;
1023 conn = make_connection(req, now, service, client_devicetype,
1024 req->vuid, &nt_status);
1028 if (session_key_updated) {
1029 struct smbXsrv_session *x = session;
1030 struct auth_session_info *session_info =
1031 session->global->auth_session_info;
1032 data_blob_clear_free(&x->global->application_key);
1033 data_blob_clear_free(&session_info->session_key);
1035 reply_nterror(req, nt_status);
1036 END_PROFILE(SMBtconX);
1041 server_devicetype = "IPC";
1042 else if ( IS_PRINT(conn) )
1043 server_devicetype = "LPT1:";
1045 server_devicetype = "A:";
1047 if (get_Protocol() < PROTOCOL_NT1) {
1048 reply_outbuf(req, 2, 0);
1049 if (message_push_string(&req->outbuf, server_devicetype,
1050 STR_TERMINATE|STR_ASCII) == -1) {
1051 reply_nterror(req, NT_STATUS_NO_MEMORY);
1052 END_PROFILE(SMBtconX);
1056 /* NT sets the fstype of IPC$ to the null string */
1057 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1059 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1060 /* Return permissions. */
1064 reply_outbuf(req, 7, 0);
1067 perm1 = FILE_ALL_ACCESS;
1068 perm2 = FILE_ALL_ACCESS;
1070 perm1 = conn->share_access;
1073 SIVAL(req->outbuf, smb_vwv3, perm1);
1074 SIVAL(req->outbuf, smb_vwv5, perm2);
1076 reply_outbuf(req, 3, 0);
1079 if ((message_push_string(&req->outbuf, server_devicetype,
1080 STR_TERMINATE|STR_ASCII) == -1)
1081 || (message_push_string(&req->outbuf, fstype,
1082 STR_TERMINATE) == -1)) {
1083 reply_nterror(req, NT_STATUS_NO_MEMORY);
1084 END_PROFILE(SMBtconX);
1088 /* what does setting this bit do? It is set by NT4 and
1089 may affect the ability to autorun mounted cdroms */
1090 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1092 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1094 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1095 DEBUG(2,("Serving %s as a Dfs root\n",
1096 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1097 optional_support |= SMB_SHARE_IN_DFS;
1100 SSVAL(req->outbuf, smb_vwv2, optional_support);
1103 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1104 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1106 DEBUG(3,("tconX service=%s \n",
1109 /* set the incoming and outgoing tid to the just created one */
1110 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1111 SSVAL(req->outbuf,smb_tid,conn->cnum);
1113 END_PROFILE(SMBtconX);
1115 req->tid = conn->cnum;
1118 /****************************************************************************
1119 Reply to an unknown type.
1120 ****************************************************************************/
1122 void reply_unknown_new(struct smb_request *req, uint8_t type)
1124 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1125 smb_fn_name(type), type, type));
1126 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1130 /****************************************************************************
1132 conn POINTER CAN BE NULL HERE !
1133 ****************************************************************************/
1135 void reply_ioctl(struct smb_request *req)
1137 const struct loadparm_substitution *lp_sub =
1138 loadparm_s3_global_substitution();
1139 connection_struct *conn = req->conn;
1142 uint32_t ioctl_code;
1146 START_PROFILE(SMBioctl);
1149 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1150 END_PROFILE(SMBioctl);
1154 device = SVAL(req->vwv+1, 0);
1155 function = SVAL(req->vwv+2, 0);
1156 ioctl_code = (device << 16) + function;
1158 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1160 switch (ioctl_code) {
1161 case IOCTL_QUERY_JOB_INFO:
1165 reply_force_doserror(req, ERRSRV, ERRnosupport);
1166 END_PROFILE(SMBioctl);
1170 reply_outbuf(req, 8, replysize+1);
1171 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1172 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1173 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1174 p = smb_buf(req->outbuf);
1175 memset(p, '\0', replysize+1); /* valgrind-safe. */
1176 p += 1; /* Allow for alignment */
1178 switch (ioctl_code) {
1179 case IOCTL_QUERY_JOB_INFO:
1183 files_struct *fsp = file_fsp(
1184 req, SVAL(req->vwv+0, 0));
1186 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1187 END_PROFILE(SMBioctl);
1191 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1193 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1194 lp_netbios_name(), 15,
1195 STR_TERMINATE|STR_ASCII, &len);
1196 if (!NT_STATUS_IS_OK(status)) {
1197 reply_nterror(req, status);
1198 END_PROFILE(SMBioctl);
1202 status = srvstr_push((char *)req->outbuf, req->flags2,
1204 lp_servicename(talloc_tos(),
1207 13, STR_TERMINATE|STR_ASCII, &len);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 reply_nterror(req, status);
1210 END_PROFILE(SMBioctl);
1214 memset(p+18, 0, 13);
1220 END_PROFILE(SMBioctl);
1224 /****************************************************************************
1225 Strange checkpath NTSTATUS mapping.
1226 ****************************************************************************/
1228 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1230 /* Strange DOS error code semantics only for checkpath... */
1231 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1232 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1233 /* We need to map to ERRbadpath */
1234 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1240 /****************************************************************************
1241 Reply to a checkpath.
1242 ****************************************************************************/
1244 void reply_checkpath(struct smb_request *req)
1246 connection_struct *conn = req->conn;
1247 struct smb_filename *smb_fname = NULL;
1250 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1251 TALLOC_CTX *ctx = talloc_tos();
1253 START_PROFILE(SMBcheckpath);
1255 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1256 STR_TERMINATE, &status);
1258 if (!NT_STATUS_IS_OK(status)) {
1259 status = map_checkpath_error(req->flags2, status);
1260 reply_nterror(req, status);
1261 END_PROFILE(SMBcheckpath);
1265 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1267 status = filename_convert(ctx,
1274 if (!NT_STATUS_IS_OK(status)) {
1275 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1276 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1277 ERRSRV, ERRbadpath);
1278 END_PROFILE(SMBcheckpath);
1284 if (!VALID_STAT(smb_fname->st) &&
1285 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1286 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1287 smb_fname_str_dbg(smb_fname), strerror(errno)));
1288 status = map_nt_error_from_unix(errno);
1292 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1293 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1294 ERRDOS, ERRbadpath);
1298 reply_outbuf(req, 0, 0);
1301 /* We special case this - as when a Windows machine
1302 is parsing a path is steps through the components
1303 one at a time - if a component fails it expects
1304 ERRbadpath, not ERRbadfile.
1306 status = map_checkpath_error(req->flags2, status);
1307 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1309 * Windows returns different error codes if
1310 * the parent directory is valid but not the
1311 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1312 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1313 * if the path is invalid.
1315 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1316 ERRDOS, ERRbadpath);
1320 reply_nterror(req, status);
1323 TALLOC_FREE(smb_fname);
1324 END_PROFILE(SMBcheckpath);
1328 /****************************************************************************
1330 ****************************************************************************/
1332 void reply_getatr(struct smb_request *req)
1334 connection_struct *conn = req->conn;
1335 struct smb_filename *smb_fname = NULL;
1342 TALLOC_CTX *ctx = talloc_tos();
1343 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1345 START_PROFILE(SMBgetatr);
1347 p = (const char *)req->buf + 1;
1348 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1349 if (!NT_STATUS_IS_OK(status)) {
1350 reply_nterror(req, status);
1354 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1355 under WfWg - weird! */
1356 if (*fname == '\0') {
1357 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1358 if (!CAN_WRITE(conn)) {
1359 mode |= FILE_ATTRIBUTE_READONLY;
1364 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1365 status = filename_convert(ctx,
1371 if (!NT_STATUS_IS_OK(status)) {
1372 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1373 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1374 ERRSRV, ERRbadpath);
1377 reply_nterror(req, status);
1380 if (!VALID_STAT(smb_fname->st) &&
1381 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1382 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1383 smb_fname_str_dbg(smb_fname),
1385 reply_nterror(req, map_nt_error_from_unix(errno));
1389 mode = dos_mode(conn, smb_fname);
1390 size = smb_fname->st.st_ex_size;
1392 if (ask_sharemode) {
1393 struct timespec write_time_ts;
1394 struct file_id fileid;
1396 ZERO_STRUCT(write_time_ts);
1397 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1398 get_file_infos(fileid, 0, NULL, &write_time_ts);
1399 if (!is_omit_timespec(&write_time_ts)) {
1400 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1404 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1405 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1410 reply_outbuf(req, 10, 0);
1412 SSVAL(req->outbuf,smb_vwv0,mode);
1413 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1414 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1416 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1418 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1420 if (get_Protocol() >= PROTOCOL_NT1) {
1421 SSVAL(req->outbuf, smb_flg2,
1422 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1425 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1426 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1429 TALLOC_FREE(smb_fname);
1431 END_PROFILE(SMBgetatr);
1435 /****************************************************************************
1437 ****************************************************************************/
1439 void reply_setatr(struct smb_request *req)
1441 struct smb_file_time ft;
1442 connection_struct *conn = req->conn;
1443 struct smb_filename *smb_fname = NULL;
1449 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1450 TALLOC_CTX *ctx = talloc_tos();
1452 START_PROFILE(SMBsetatr);
1453 init_smb_file_time(&ft);
1456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1460 p = (const char *)req->buf + 1;
1461 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1462 if (!NT_STATUS_IS_OK(status)) {
1463 reply_nterror(req, status);
1467 status = filename_convert(ctx,
1473 if (!NT_STATUS_IS_OK(status)) {
1474 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1475 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1476 ERRSRV, ERRbadpath);
1479 reply_nterror(req, status);
1483 if (ISDOT(smb_fname->base_name)) {
1485 * Not sure here is the right place to catch this
1486 * condition. Might be moved to somewhere else later -- vl
1488 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1492 mode = SVAL(req->vwv+0, 0);
1493 mtime = srv_make_unix_date3(req->vwv+1);
1495 if (mode != FILE_ATTRIBUTE_NORMAL) {
1496 if (VALID_STAT_OF_DIR(smb_fname->st))
1497 mode |= FILE_ATTRIBUTE_DIRECTORY;
1499 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1501 status = smbd_check_access_rights(conn,
1505 FILE_WRITE_ATTRIBUTES);
1506 if (!NT_STATUS_IS_OK(status)) {
1507 reply_nterror(req, status);
1511 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1513 reply_nterror(req, map_nt_error_from_unix(errno));
1518 ft.mtime = time_t_to_full_timespec(mtime);
1520 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1521 if (!NT_STATUS_IS_OK(status)) {
1522 reply_nterror(req, status);
1526 reply_outbuf(req, 0, 0);
1528 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1531 TALLOC_FREE(smb_fname);
1532 END_PROFILE(SMBsetatr);
1536 /****************************************************************************
1538 ****************************************************************************/
1540 void reply_dskattr(struct smb_request *req)
1542 connection_struct *conn = req->conn;
1544 uint64_t dfree,dsize,bsize;
1545 struct smb_filename smb_fname;
1546 START_PROFILE(SMBdskattr);
1548 ZERO_STRUCT(smb_fname);
1549 smb_fname.base_name = discard_const_p(char, ".");
1551 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1552 reply_nterror(req, map_nt_error_from_unix(errno));
1553 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1554 END_PROFILE(SMBdskattr);
1558 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1559 if (ret == (uint64_t)-1) {
1560 reply_nterror(req, map_nt_error_from_unix(errno));
1561 END_PROFILE(SMBdskattr);
1566 * Force max to fit in 16 bit fields.
1568 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1572 if (bsize > (WORDMAX*512)) {
1573 bsize = (WORDMAX*512);
1574 if (dsize > WORDMAX)
1576 if (dfree > WORDMAX)
1582 reply_outbuf(req, 5, 0);
1584 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1585 double total_space, free_space;
1586 /* we need to scale this to a number that DOS6 can handle. We
1587 use floating point so we can handle large drives on systems
1588 that don't have 64 bit integers
1590 we end up displaying a maximum of 2G to DOS systems
1592 total_space = dsize * (double)bsize;
1593 free_space = dfree * (double)bsize;
1595 dsize = (uint64_t)((total_space+63*512) / (64*512));
1596 dfree = (uint64_t)((free_space+63*512) / (64*512));
1598 if (dsize > 0xFFFF) dsize = 0xFFFF;
1599 if (dfree > 0xFFFF) dfree = 0xFFFF;
1601 SSVAL(req->outbuf,smb_vwv0,dsize);
1602 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1603 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1604 SSVAL(req->outbuf,smb_vwv3,dfree);
1606 SSVAL(req->outbuf,smb_vwv0,dsize);
1607 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1608 SSVAL(req->outbuf,smb_vwv2,512);
1609 SSVAL(req->outbuf,smb_vwv3,dfree);
1612 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1614 END_PROFILE(SMBdskattr);
1619 * Utility function to split the filename from the directory.
1621 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1622 char **fname_dir_out,
1623 char **fname_mask_out)
1625 const char *p = NULL;
1626 char *fname_dir = NULL;
1627 char *fname_mask = NULL;
1629 p = strrchr_m(fname_in, '/');
1631 fname_dir = talloc_strdup(ctx, ".");
1632 fname_mask = talloc_strdup(ctx, fname_in);
1634 fname_dir = talloc_strndup(ctx, fname_in,
1635 PTR_DIFF(p, fname_in));
1636 fname_mask = talloc_strdup(ctx, p+1);
1639 if (!fname_dir || !fname_mask) {
1640 TALLOC_FREE(fname_dir);
1641 TALLOC_FREE(fname_mask);
1642 return NT_STATUS_NO_MEMORY;
1645 *fname_dir_out = fname_dir;
1646 *fname_mask_out = fname_mask;
1647 return NT_STATUS_OK;
1650 /****************************************************************************
1652 ****************************************************************************/
1654 static bool make_dir_struct(TALLOC_CTX *ctx,
1664 char *mask2 = talloc_strdup(ctx, mask);
1670 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1674 memset(buf+1,' ',11);
1675 if ((p = strchr_m(mask2,'.')) != NULL) {
1677 push_ascii(buf+1,mask2,8, 0);
1678 push_ascii(buf+9,p+1,3, 0);
1681 push_ascii(buf+1,mask2,11, 0);
1684 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1686 srv_put_dos_date(buf,22,date);
1687 SSVAL(buf,26,size & 0xFFFF);
1688 SSVAL(buf,28,(size >> 16)&0xFFFF);
1689 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1690 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1691 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1692 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1696 /****************************************************************************
1698 Can be called from SMBsearch, SMBffirst or SMBfunique.
1699 ****************************************************************************/
1701 void reply_search(struct smb_request *req)
1703 connection_struct *conn = req->conn;
1706 char *directory = NULL;
1707 struct smb_filename *smb_fname = NULL;
1711 struct timespec date;
1713 unsigned int numentries = 0;
1714 unsigned int maxentries = 0;
1715 bool finished = False;
1720 bool check_descend = False;
1721 bool expect_close = False;
1723 bool mask_contains_wcard = False;
1724 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1725 TALLOC_CTX *ctx = talloc_tos();
1726 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1727 struct smbXsrv_connection *xconn = req->xconn;
1728 struct smbd_server_connection *sconn = req->sconn;
1729 files_struct *fsp = NULL;
1730 const struct loadparm_substitution *lp_sub =
1731 loadparm_s3_global_substitution();
1733 START_PROFILE(SMBsearch);
1736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1740 if (req->posix_pathnames) {
1741 reply_unknown_new(req, req->cmd);
1745 /* If we were called as SMBffirst then we must expect close. */
1746 if(req->cmd == SMBffirst) {
1747 expect_close = True;
1750 reply_outbuf(req, 1, 3);
1751 maxentries = SVAL(req->vwv+0, 0);
1752 dirtype = SVAL(req->vwv+1, 0);
1753 p = (const char *)req->buf + 1;
1754 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1756 if (!NT_STATUS_IS_OK(nt_status)) {
1757 reply_nterror(req, nt_status);
1761 if (smbreq_bufrem(req, p) < 3) {
1762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1767 status_len = SVAL(p, 0);
1770 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1772 if (status_len == 0) {
1774 struct smb_filename *smb_dname = NULL;
1775 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1776 ucf_flags_from_smb_request(req);
1777 nt_status = filename_convert(ctx, conn,
1782 if (!NT_STATUS_IS_OK(nt_status)) {
1783 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1784 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1785 ERRSRV, ERRbadpath);
1788 reply_nterror(req, nt_status);
1792 directory = smb_fname->base_name;
1794 p = strrchr_m(directory,'/');
1795 if ((p != NULL) && (*directory != '/')) {
1796 mask = talloc_strdup(ctx, p + 1);
1797 directory = talloc_strndup(ctx, directory,
1798 PTR_DIFF(p, directory));
1800 mask = talloc_strdup(ctx, directory);
1801 directory = talloc_strdup(ctx,".");
1805 reply_nterror(req, NT_STATUS_NO_MEMORY);
1809 memset((char *)status,'\0',21);
1810 SCVAL(status,0,(dirtype & 0x1F));
1812 smb_dname = synthetic_smb_fname(talloc_tos(),
1818 if (smb_dname == NULL) {
1819 reply_nterror(req, NT_STATUS_NO_MEMORY);
1824 * As we've cut off the last component from
1825 * smb_fname we need to re-stat smb_dname
1826 * so FILE_OPEN disposition knows the directory
1829 ret = vfs_stat(conn, smb_dname);
1831 nt_status = map_nt_error_from_unix(errno);
1832 reply_nterror(req, nt_status);
1836 nt_status = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
1837 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_STOPPED_ON_SYMLINK)) {
1838 nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1840 if (!NT_STATUS_IS_OK(nt_status)) {
1841 reply_nterror(req, nt_status);
1846 * Open an fsp on this directory for the dptr.
1848 nt_status = SMB_VFS_CREATE_FILE(
1851 smb_dname, /* dname */
1852 FILE_LIST_DIRECTORY, /* access_mask */
1854 FILE_SHARE_WRITE, /* share_access */
1855 FILE_OPEN, /* create_disposition*/
1856 FILE_DIRECTORY_FILE, /* create_options */
1857 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1858 NO_OPLOCK, /* oplock_request */
1860 0, /* allocation_size */
1861 0, /* private_flags */
1866 NULL, /* in_context */
1867 NULL);/* out_context */
1869 if (!NT_STATUS_IS_OK(nt_status)) {
1870 DBG_ERR("failed to open directory %s\n",
1871 smb_fname_str_dbg(smb_dname));
1872 reply_nterror(req, nt_status);
1876 nt_status = dptr_create(conn,
1886 TALLOC_FREE(smb_dname);
1888 if (!NT_STATUS_IS_OK(nt_status)) {
1890 * Use NULL here for the first parameter (req)
1891 * as this is not a client visible handle so
1892 * can'tbe part of an SMB1 chain.
1894 close_file(NULL, fsp, NORMAL_CLOSE);
1896 reply_nterror(req, nt_status);
1900 dptr_num = dptr_dnum(fsp->dptr);
1904 const char *dirpath;
1906 if (smbreq_bufrem(req, p) < 21) {
1907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1911 memcpy(status,p,21);
1912 status_dirtype = CVAL(status,0) & 0x1F;
1913 if (status_dirtype != (dirtype & 0x1F)) {
1914 dirtype = status_dirtype;
1917 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1921 dirpath = dptr_path(sconn, dptr_num);
1922 directory = talloc_strdup(ctx, dirpath);
1924 reply_nterror(req, NT_STATUS_NO_MEMORY);
1928 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1932 dirtype = dptr_attr(sconn, dptr_num);
1935 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1937 DEBUG(4,("dptr_num is %d\n",dptr_num));
1939 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1940 char buf[DIR_STRUCT_SIZE];
1941 memcpy(buf,status,21);
1942 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1943 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1944 reply_nterror(req, NT_STATUS_NO_MEMORY);
1947 dptr_fill(sconn, buf+12,dptr_num);
1948 if (dptr_zero(buf+12) && (status_len==0)) {
1953 if (message_push_blob(&req->outbuf,
1954 data_blob_const(buf, sizeof(buf)))
1956 reply_nterror(req, NT_STATUS_NO_MEMORY);
1961 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1962 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1964 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1966 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1967 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1968 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1969 check_descend = True;
1972 for (i=numentries;(i<maxentries) && !finished;i++) {
1973 finished = !get_dir_entry(ctx,
1984 char buf[DIR_STRUCT_SIZE];
1985 memcpy(buf,status,21);
1986 if (!make_dir_struct(ctx,
1992 convert_timespec_to_time_t(date),
1993 !allow_long_path_components)) {
1994 reply_nterror(req, NT_STATUS_NO_MEMORY);
1997 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2000 if (message_push_blob(&req->outbuf,
2001 data_blob_const(buf, sizeof(buf)))
2003 reply_nterror(req, NT_STATUS_NO_MEMORY);
2013 /* If we were called as SMBffirst with smb_search_id == NULL
2014 and no entries were found then return error and close fsp->dptr
2017 if (numentries == 0) {
2020 close_file(NULL, fsp, NORMAL_CLOSE);
2023 } else if(expect_close && status_len == 0) {
2024 /* Close the dptr - we know it's gone */
2027 close_file(NULL, fsp, NORMAL_CLOSE);
2032 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2033 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2035 /* fsp may have been closed above. */
2037 close_file(NULL, fsp, NORMAL_CLOSE);
2042 if ((numentries == 0) && !mask_contains_wcard) {
2043 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2047 SSVAL(req->outbuf,smb_vwv0,numentries);
2048 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2049 SCVAL(smb_buf(req->outbuf),0,5);
2050 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2052 /* The replies here are never long name. */
2053 SSVAL(req->outbuf, smb_flg2,
2054 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2055 if (!allow_long_path_components) {
2056 SSVAL(req->outbuf, smb_flg2,
2057 SVAL(req->outbuf, smb_flg2)
2058 & (~FLAGS2_LONG_PATH_COMPONENTS));
2061 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2062 SSVAL(req->outbuf, smb_flg2,
2063 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2065 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2066 smb_fn_name(req->cmd),
2073 TALLOC_FREE(directory);
2075 TALLOC_FREE(smb_fname);
2076 END_PROFILE(SMBsearch);
2080 /****************************************************************************
2081 Reply to a fclose (stop directory search).
2082 ****************************************************************************/
2084 void reply_fclose(struct smb_request *req)
2092 TALLOC_CTX *ctx = talloc_tos();
2093 struct smbd_server_connection *sconn = req->sconn;
2094 files_struct *fsp = NULL;
2096 START_PROFILE(SMBfclose);
2098 if (req->posix_pathnames) {
2099 reply_unknown_new(req, req->cmd);
2100 END_PROFILE(SMBfclose);
2104 p = (const char *)req->buf + 1;
2105 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
2107 if (!NT_STATUS_IS_OK(err)) {
2108 reply_nterror(req, err);
2109 END_PROFILE(SMBfclose);
2113 if (smbreq_bufrem(req, p) < 3) {
2114 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2115 END_PROFILE(SMBfclose);
2120 status_len = SVAL(p,0);
2123 if (status_len == 0) {
2124 reply_force_doserror(req, ERRSRV, ERRsrverror);
2125 END_PROFILE(SMBfclose);
2129 if (smbreq_bufrem(req, p) < 21) {
2130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2131 END_PROFILE(SMBfclose);
2135 memcpy(status,p,21);
2137 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2139 /* Close the file - we know it's gone */
2140 close_file(NULL, fsp, NORMAL_CLOSE);
2145 reply_outbuf(req, 1, 0);
2146 SSVAL(req->outbuf,smb_vwv0,0);
2148 DEBUG(3,("search close\n"));
2150 END_PROFILE(SMBfclose);
2154 /****************************************************************************
2156 ****************************************************************************/
2158 void reply_open(struct smb_request *req)
2160 connection_struct *conn = req->conn;
2161 struct smb_filename *smb_fname = NULL;
2171 uint32_t access_mask;
2172 uint32_t share_mode;
2173 uint32_t create_disposition;
2174 uint32_t create_options = 0;
2175 uint32_t private_flags = 0;
2178 TALLOC_CTX *ctx = talloc_tos();
2180 START_PROFILE(SMBopen);
2183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2187 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2188 deny_mode = SVAL(req->vwv+0, 0);
2189 dos_attr = SVAL(req->vwv+1, 0);
2191 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2192 STR_TERMINATE, &status);
2193 if (!NT_STATUS_IS_OK(status)) {
2194 reply_nterror(req, status);
2198 if (!map_open_params_to_ntcreate(fname, deny_mode,
2199 OPENX_FILE_EXISTS_OPEN, &access_mask,
2200 &share_mode, &create_disposition,
2201 &create_options, &private_flags)) {
2202 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2206 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2208 status = filename_convert(ctx,
2214 if (!NT_STATUS_IS_OK(status)) {
2215 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2216 reply_botherror(req,
2217 NT_STATUS_PATH_NOT_COVERED,
2218 ERRSRV, ERRbadpath);
2221 reply_nterror(req, status);
2225 status = SMB_VFS_CREATE_FILE(
2228 smb_fname, /* fname */
2229 access_mask, /* access_mask */
2230 share_mode, /* share_access */
2231 create_disposition, /* create_disposition*/
2232 create_options, /* create_options */
2233 dos_attr, /* file_attributes */
2234 oplock_request, /* oplock_request */
2236 0, /* allocation_size */
2242 NULL, NULL); /* create context */
2244 if (!NT_STATUS_IS_OK(status)) {
2245 if (open_was_deferred(req->xconn, req->mid)) {
2246 /* We have re-scheduled this call. */
2250 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2251 reply_openerror(req, status);
2255 fsp = fcb_or_dos_open(
2262 bool ok = defer_smb1_sharing_violation(req);
2266 reply_openerror(req, status);
2271 /* Ensure we're pointing at the correct stat struct. */
2272 TALLOC_FREE(smb_fname);
2273 smb_fname = fsp->fsp_name;
2275 size = smb_fname->st.st_ex_size;
2276 fattr = dos_mode(conn, smb_fname);
2278 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2280 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2281 DEBUG(3,("attempt to open a directory %s\n",
2283 close_file(req, fsp, ERROR_CLOSE);
2284 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2285 ERRDOS, ERRnoaccess);
2289 reply_outbuf(req, 7, 0);
2290 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2291 SSVAL(req->outbuf,smb_vwv1,fattr);
2292 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2293 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2295 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2297 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2298 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2300 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2301 SCVAL(req->outbuf,smb_flg,
2302 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2305 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2306 SCVAL(req->outbuf,smb_flg,
2307 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2310 END_PROFILE(SMBopen);
2314 /****************************************************************************
2315 Reply to an open and X.
2316 ****************************************************************************/
2318 void reply_open_and_X(struct smb_request *req)
2320 connection_struct *conn = req->conn;
2321 struct smb_filename *smb_fname = NULL;
2323 uint16_t open_flags;
2326 /* Breakout the oplock request bits so we can set the
2327 reply bits separately. */
2328 int ex_oplock_request;
2329 int core_oplock_request;
2332 int smb_sattr = SVAL(req->vwv+4, 0);
2333 uint32_t smb_time = make_unix_date3(req->vwv+6);
2341 uint64_t allocation_size;
2342 ssize_t retval = -1;
2343 uint32_t access_mask;
2344 uint32_t share_mode;
2345 uint32_t create_disposition;
2346 uint32_t create_options = 0;
2347 uint32_t private_flags = 0;
2349 TALLOC_CTX *ctx = talloc_tos();
2351 START_PROFILE(SMBopenX);
2353 if (req->wct < 15) {
2354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2358 open_flags = SVAL(req->vwv+2, 0);
2359 deny_mode = SVAL(req->vwv+3, 0);
2360 smb_attr = SVAL(req->vwv+5, 0);
2361 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2362 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2363 oplock_request = ex_oplock_request | core_oplock_request;
2364 smb_ofun = SVAL(req->vwv+8, 0);
2365 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2367 /* If it's an IPC, pass off the pipe handler. */
2369 if (lp_nt_pipe_support()) {
2370 reply_open_pipe_and_X(conn, req);
2372 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2377 /* XXXX we need to handle passed times, sattr and flags */
2378 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2379 STR_TERMINATE, &status);
2380 if (!NT_STATUS_IS_OK(status)) {
2381 reply_nterror(req, status);
2385 if (!map_open_params_to_ntcreate(fname, deny_mode,
2387 &access_mask, &share_mode,
2388 &create_disposition,
2391 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2395 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2397 status = filename_convert(ctx,
2403 if (!NT_STATUS_IS_OK(status)) {
2404 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2405 reply_botherror(req,
2406 NT_STATUS_PATH_NOT_COVERED,
2407 ERRSRV, ERRbadpath);
2410 reply_nterror(req, status);
2414 status = SMB_VFS_CREATE_FILE(
2417 smb_fname, /* fname */
2418 access_mask, /* access_mask */
2419 share_mode, /* share_access */
2420 create_disposition, /* create_disposition*/
2421 create_options, /* create_options */
2422 smb_attr, /* file_attributes */
2423 oplock_request, /* oplock_request */
2425 0, /* allocation_size */
2430 &smb_action, /* pinfo */
2431 NULL, NULL); /* create context */
2433 if (!NT_STATUS_IS_OK(status)) {
2434 if (open_was_deferred(req->xconn, req->mid)) {
2435 /* We have re-scheduled this call. */
2439 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2440 reply_openerror(req, status);
2444 fsp = fcb_or_dos_open(
2451 bool ok = defer_smb1_sharing_violation(req);
2455 reply_openerror(req, status);
2460 smb_action = FILE_WAS_OPENED;
2463 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2464 if the file is truncated or created. */
2465 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2466 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2467 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2468 close_file(req, fsp, ERROR_CLOSE);
2469 reply_nterror(req, NT_STATUS_DISK_FULL);
2472 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2474 close_file(req, fsp, ERROR_CLOSE);
2475 reply_nterror(req, NT_STATUS_DISK_FULL);
2478 status = vfs_stat_fsp(fsp);
2479 if (!NT_STATUS_IS_OK(status)) {
2480 close_file(req, fsp, ERROR_CLOSE);
2481 reply_nterror(req, status);
2486 fattr = dos_mode(conn, fsp->fsp_name);
2487 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2488 close_file(req, fsp, ERROR_CLOSE);
2489 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2492 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2494 /* If the caller set the extended oplock request bit
2495 and we granted one (by whatever means) - set the
2496 correct bit for extended oplock reply.
2499 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2500 smb_action |= EXTENDED_OPLOCK_GRANTED;
2503 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2504 smb_action |= EXTENDED_OPLOCK_GRANTED;
2507 /* If the caller set the core oplock request bit
2508 and we granted one (by whatever means) - set the
2509 correct bit for core oplock reply.
2512 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2513 reply_outbuf(req, 19, 0);
2515 reply_outbuf(req, 15, 0);
2518 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2519 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2521 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2522 SCVAL(req->outbuf, smb_flg,
2523 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2526 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2527 SCVAL(req->outbuf, smb_flg,
2528 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2531 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2532 SSVAL(req->outbuf,smb_vwv3,fattr);
2533 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2534 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2536 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2538 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2539 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2540 SSVAL(req->outbuf,smb_vwv11,smb_action);
2542 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2543 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2547 TALLOC_FREE(smb_fname);
2548 END_PROFILE(SMBopenX);
2552 /****************************************************************************
2553 Reply to a SMBulogoffX.
2554 ****************************************************************************/
2556 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2557 struct smbXsrv_session *session);
2558 static void reply_ulogoffX_done(struct tevent_req *req);
2560 void reply_ulogoffX(struct smb_request *smb1req)
2562 struct timeval now = timeval_current();
2563 struct smbXsrv_session *session = NULL;
2564 struct tevent_req *req;
2568 * Don't setup the profile charge here, take
2569 * it in reply_ulogoffX_done(). Not strictly correct
2570 * but better than the other SMB1 async
2571 * code that double-charges at the moment.
2574 status = smb1srv_session_lookup(smb1req->xconn,
2576 timeval_to_nttime(&now),
2578 if (!NT_STATUS_IS_OK(status)) {
2579 /* Not going async, profile here. */
2580 START_PROFILE(SMBulogoffX);
2581 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2582 (unsigned long long)smb1req->vuid);
2584 smb1req->vuid = UID_FIELD_INVALID;
2585 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2586 END_PROFILE(SMBulogoffX);
2590 req = reply_ulogoffX_send(smb1req, session);
2592 /* Not going async, profile here. */
2593 START_PROFILE(SMBulogoffX);
2594 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2595 END_PROFILE(SMBulogoffX);
2599 /* We're async. This will complete later. */
2600 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2604 struct reply_ulogoffX_state {
2605 struct tevent_queue *wait_queue;
2606 struct smbXsrv_session *session;
2609 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2611 /****************************************************************************
2612 Async SMB1 ulogoffX.
2613 Note, on failure here we deallocate and return NULL to allow the caller to
2614 SMB1 return an error of ERRnomem immediately.
2615 ****************************************************************************/
2617 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2618 struct smbXsrv_session *session)
2620 struct tevent_req *req;
2621 struct reply_ulogoffX_state *state;
2622 struct tevent_req *subreq;
2624 struct smbd_server_connection *sconn = session->client->sconn;
2625 uint64_t vuid = session->global->session_wire_id;
2627 req = tevent_req_create(smb1req, &state,
2628 struct reply_ulogoffX_state);
2632 state->wait_queue = tevent_queue_create(state,
2633 "reply_ulogoffX_wait_queue");
2634 if (tevent_req_nomem(state->wait_queue, req)) {
2638 state->session = session;
2641 * Make sure that no new request will be able to use this session.
2642 * This ensures that once all outstanding fsp->aio_requests
2643 * on this session are done, we are safe to close it.
2645 session->status = NT_STATUS_USER_SESSION_DELETED;
2647 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2648 if (fsp->vuid != vuid) {
2652 * Flag the file as close in progress.
2653 * This will prevent any more IO being
2656 fsp->fsp_flags.closing = true;
2658 if (fsp->num_aio_requests > 0) {
2660 * Now wait until all aio requests on this fsp are
2663 * We don't set a callback, as we just want to block the
2664 * wait queue and the talloc_free() of fsp->aio_request
2665 * will remove the item from the wait queue.
2667 subreq = tevent_queue_wait_send(fsp->aio_requests,
2670 if (tevent_req_nomem(subreq, req)) {
2678 * Now we add our own waiter to the end of the queue,
2679 * this way we get notified when all pending requests are finished
2680 * and reply to the outstanding SMB1 request.
2682 subreq = tevent_queue_wait_send(state,
2685 if (tevent_req_nomem(subreq, req)) {
2691 * We're really going async - move the SMB1 request from
2692 * a talloc stackframe above us to the sconn talloc-context.
2693 * We need this to stick around until the wait_done
2694 * callback is invoked.
2696 smb1req = talloc_move(sconn, &smb1req);
2698 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2703 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2705 struct tevent_req *req = tevent_req_callback_data(
2706 subreq, struct tevent_req);
2708 tevent_queue_wait_recv(subreq);
2709 TALLOC_FREE(subreq);
2710 tevent_req_done(req);
2713 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2715 return tevent_req_simple_recv_ntstatus(req);
2718 static void reply_ulogoffX_done(struct tevent_req *req)
2720 struct smb_request *smb1req = tevent_req_callback_data(
2721 req, struct smb_request);
2722 struct reply_ulogoffX_state *state = tevent_req_data(req,
2723 struct reply_ulogoffX_state);
2724 struct smbXsrv_session *session = state->session;
2728 * Take the profile charge here. Not strictly
2729 * correct but better than the other SMB1 async
2730 * code that double-charges at the moment.
2732 START_PROFILE(SMBulogoffX);
2734 status = reply_ulogoffX_recv(req);
2736 if (!NT_STATUS_IS_OK(status)) {
2737 TALLOC_FREE(smb1req);
2738 END_PROFILE(SMBulogoffX);
2739 exit_server(__location__ ": reply_ulogoffX_recv failed");
2743 status = smbXsrv_session_logoff(session);
2744 if (!NT_STATUS_IS_OK(status)) {
2745 TALLOC_FREE(smb1req);
2746 END_PROFILE(SMBulogoffX);
2747 exit_server(__location__ ": smbXsrv_session_logoff failed");
2751 TALLOC_FREE(session);
2753 reply_outbuf(smb1req, 2, 0);
2754 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2755 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2757 DBG_NOTICE("ulogoffX vuid=%llu\n",
2758 (unsigned long long)smb1req->vuid);
2760 smb1req->vuid = UID_FIELD_INVALID;
2762 * The following call is needed to push the
2763 * reply data back out the socket after async
2764 * return. Plus it frees smb1req.
2766 smb_request_done(smb1req);
2767 END_PROFILE(SMBulogoffX);
2770 /****************************************************************************
2771 Reply to a mknew or a create.
2772 ****************************************************************************/
2774 void reply_mknew(struct smb_request *req)
2776 connection_struct *conn = req->conn;
2777 struct smb_filename *smb_fname = NULL;
2780 struct smb_file_time ft;
2782 int oplock_request = 0;
2784 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2785 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2786 uint32_t create_disposition;
2787 uint32_t create_options = 0;
2789 TALLOC_CTX *ctx = talloc_tos();
2791 START_PROFILE(SMBcreate);
2792 init_smb_file_time(&ft);
2795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2799 fattr = SVAL(req->vwv+0, 0);
2800 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2802 if (req->cmd == SMBmknew) {
2803 /* We should fail if file exists. */
2804 create_disposition = FILE_CREATE;
2806 /* Create if file doesn't exist, truncate if it does. */
2807 create_disposition = FILE_OVERWRITE_IF;
2811 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2813 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2814 STR_TERMINATE, &status);
2815 if (!NT_STATUS_IS_OK(status)) {
2816 reply_nterror(req, status);
2820 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2821 status = filename_convert(ctx,
2827 if (!NT_STATUS_IS_OK(status)) {
2828 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2829 reply_botherror(req,
2830 NT_STATUS_PATH_NOT_COVERED,
2831 ERRSRV, ERRbadpath);
2834 reply_nterror(req, status);
2838 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2839 DEBUG(0,("Attempt to create file (%s) with volid set - "
2840 "please report this\n",
2841 smb_fname_str_dbg(smb_fname)));
2844 status = SMB_VFS_CREATE_FILE(
2847 smb_fname, /* fname */
2848 access_mask, /* access_mask */
2849 share_mode, /* share_access */
2850 create_disposition, /* create_disposition*/
2851 create_options, /* create_options */
2852 fattr, /* file_attributes */
2853 oplock_request, /* oplock_request */
2855 0, /* allocation_size */
2856 0, /* private_flags */
2861 NULL, NULL); /* create context */
2863 if (!NT_STATUS_IS_OK(status)) {
2864 if (open_was_deferred(req->xconn, req->mid)) {
2865 /* We have re-scheduled this call. */
2868 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2869 bool ok = defer_smb1_sharing_violation(req);
2874 reply_openerror(req, status);
2878 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2879 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2880 if (!NT_STATUS_IS_OK(status)) {
2881 END_PROFILE(SMBcreate);
2885 reply_outbuf(req, 1, 0);
2886 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2888 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2889 SCVAL(req->outbuf,smb_flg,
2890 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2893 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2894 SCVAL(req->outbuf,smb_flg,
2895 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2898 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2899 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2900 smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2901 (unsigned int)fattr));
2904 TALLOC_FREE(smb_fname);
2905 END_PROFILE(SMBcreate);
2909 /****************************************************************************
2910 Reply to a create temporary file.
2911 ****************************************************************************/
2913 void reply_ctemp(struct smb_request *req)
2915 connection_struct *conn = req->conn;
2916 struct smb_filename *smb_fname = NULL;
2917 char *wire_name = NULL;
2926 TALLOC_CTX *ctx = talloc_tos();
2928 START_PROFILE(SMBctemp);
2931 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2935 fattr = SVAL(req->vwv+0, 0);
2936 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2938 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2939 STR_TERMINATE, &status);
2940 if (!NT_STATUS_IS_OK(status)) {
2941 reply_nterror(req, status);
2945 for (i = 0; i < 10; i++) {
2947 fname = talloc_asprintf(ctx,
2950 generate_random_str_list(ctx, 5, "0123456789"));
2952 fname = talloc_asprintf(ctx,
2954 generate_random_str_list(ctx, 5, "0123456789"));
2958 reply_nterror(req, NT_STATUS_NO_MEMORY);
2962 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2963 status = filename_convert(ctx, conn,
2968 if (!NT_STATUS_IS_OK(status)) {
2969 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2970 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2971 ERRSRV, ERRbadpath);
2974 reply_nterror(req, status);
2978 /* Create the file. */
2979 status = SMB_VFS_CREATE_FILE(
2982 smb_fname, /* fname */
2983 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2984 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2985 FILE_CREATE, /* create_disposition*/
2986 0, /* create_options */
2987 fattr, /* file_attributes */
2988 oplock_request, /* oplock_request */
2990 0, /* allocation_size */
2991 0, /* private_flags */
2996 NULL, NULL); /* create context */
2998 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3000 TALLOC_FREE(smb_fname);
3004 if (!NT_STATUS_IS_OK(status)) {
3005 if (open_was_deferred(req->xconn, req->mid)) {
3006 /* We have re-scheduled this call. */
3009 if (NT_STATUS_EQUAL(
3010 status, NT_STATUS_SHARING_VIOLATION)) {
3011 bool ok = defer_smb1_sharing_violation(req);
3016 reply_openerror(req, status);
3024 /* Collision after 10 times... */
3025 reply_nterror(req, status);
3029 reply_outbuf(req, 1, 0);
3030 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3032 /* the returned filename is relative to the directory */
3033 s = strrchr_m(fsp->fsp_name->base_name, '/');
3035 s = fsp->fsp_name->base_name;
3041 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3042 thing in the byte section. JRA */
3043 SSVALS(p, 0, -1); /* what is this? not in spec */
3045 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3047 reply_nterror(req, NT_STATUS_NO_MEMORY);
3051 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3052 SCVAL(req->outbuf, smb_flg,
3053 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3056 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3057 SCVAL(req->outbuf, smb_flg,
3058 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3061 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3062 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3063 fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
3065 TALLOC_FREE(smb_fname);
3066 TALLOC_FREE(wire_name);
3067 END_PROFILE(SMBctemp);
3071 /*******************************************************************
3072 Check if a user is allowed to rename a file.
3073 ********************************************************************/
3075 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3078 if (!CAN_WRITE(conn)) {
3079 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3082 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3083 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3084 /* Only bother to read the DOS attribute if we might deny the
3085 rename on the grounds of attribute mismatch. */
3086 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3087 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3088 return NT_STATUS_NO_SUCH_FILE;
3092 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3093 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3094 return NT_STATUS_OK;
3097 /* If no pathnames are open below this
3098 directory, allow the rename. */
3100 if (lp_strict_rename(SNUM(conn))) {
3102 * Strict rename, check open file db.
3104 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3105 return NT_STATUS_ACCESS_DENIED;
3107 } else if (file_find_subpath(fsp)) {
3109 * No strict rename, just look in local process.
3111 return NT_STATUS_ACCESS_DENIED;
3113 return NT_STATUS_OK;
3116 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3117 return NT_STATUS_OK;
3120 return NT_STATUS_ACCESS_DENIED;
3123 /*******************************************************************
3124 * unlink a file with all relevant access checks
3125 *******************************************************************/
3127 static NTSTATUS do_unlink(connection_struct *conn,
3128 struct smb_request *req,
3129 struct smb_filename *smb_fname,
3134 uint32_t dirtype_orig = dirtype;
3137 struct smb2_create_blobs *posx = NULL;
3139 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3140 smb_fname_str_dbg(smb_fname),
3143 if (!CAN_WRITE(conn)) {
3144 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3147 ret = vfs_stat(conn, smb_fname);
3149 return map_nt_error_from_unix(errno);
3152 fattr = dos_mode(conn, smb_fname);
3154 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3155 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3158 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3160 return NT_STATUS_NO_SUCH_FILE;
3163 if (!dir_check_ftype(fattr, dirtype)) {
3164 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3165 return NT_STATUS_FILE_IS_A_DIRECTORY;
3167 return NT_STATUS_NO_SUCH_FILE;
3170 if (dirtype_orig & 0x8000) {
3171 /* These will never be set for POSIX. */
3172 return NT_STATUS_NO_SUCH_FILE;
3176 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3177 return NT_STATUS_FILE_IS_A_DIRECTORY;
3180 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3181 return NT_STATUS_NO_SUCH_FILE;
3184 if (dirtype & 0xFF00) {
3185 /* These will never be set for POSIX. */
3186 return NT_STATUS_NO_SUCH_FILE;
3191 return NT_STATUS_NO_SUCH_FILE;
3194 /* Can't delete a directory. */
3195 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3196 return NT_STATUS_FILE_IS_A_DIRECTORY;
3201 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3202 return NT_STATUS_OBJECT_NAME_INVALID;
3203 #endif /* JRATEST */
3205 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
3206 status = make_smb2_posix_create_ctx(
3207 talloc_tos(), &posx, 0777);
3208 if (!NT_STATUS_IS_OK(status)) {
3209 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3215 /* On open checks the open itself will check the share mode, so
3216 don't do it here as we'll get it wrong. */
3218 status = SMB_VFS_CREATE_FILE
3221 smb_fname, /* fname */
3222 DELETE_ACCESS, /* access_mask */
3223 FILE_SHARE_NONE, /* share_access */
3224 FILE_OPEN, /* create_disposition*/
3225 FILE_NON_DIRECTORY_FILE, /* create_options */
3226 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3227 0, /* oplock_request */
3229 0, /* allocation_size */
3230 0, /* private_flags */
3235 posx, /* in_context_blobs */
3236 NULL); /* out_context_blobs */
3240 if (!NT_STATUS_IS_OK(status)) {
3241 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3242 nt_errstr(status)));
3246 status = can_set_delete_on_close(fsp, fattr);
3247 if (!NT_STATUS_IS_OK(status)) {
3248 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3250 smb_fname_str_dbg(smb_fname),
3251 nt_errstr(status)));
3252 close_file(req, fsp, NORMAL_CLOSE);
3256 /* The set is across all open files on this dev/inode pair. */
3257 if (!set_delete_on_close(fsp, True,
3258 conn->session_info->security_token,
3259 conn->session_info->unix_token)) {
3260 close_file(req, fsp, NORMAL_CLOSE);
3261 return NT_STATUS_ACCESS_DENIED;
3264 return close_file(req, fsp, NORMAL_CLOSE);
3267 /****************************************************************************
3268 The guts of the unlink command, split out so it may be called by the NT SMB
3270 ****************************************************************************/
3272 NTSTATUS unlink_internals(connection_struct *conn,
3273 struct smb_request *req,
3275 struct smb_filename *smb_fname,
3278 char *fname_dir = NULL;
3279 char *fname_mask = NULL;
3281 NTSTATUS status = NT_STATUS_OK;
3282 struct smb_filename *smb_fname_dir = NULL;
3283 TALLOC_CTX *ctx = talloc_tos();
3285 /* Split up the directory from the filename/mask. */
3286 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3287 &fname_dir, &fname_mask);
3288 if (!NT_STATUS_IS_OK(status)) {
3293 * We should only check the mangled cache
3294 * here if unix_convert failed. This means
3295 * that the path in 'mask' doesn't exist
3296 * on the file system and so we need to look
3297 * for a possible mangle. This patch from
3298 * Tine Smukavec <valentin.smukavec@hermes.si>.
3301 if (!VALID_STAT(smb_fname->st) &&
3302 mangle_is_mangled(fname_mask, conn->params)) {
3303 char *new_mask = NULL;
3304 mangle_lookup_name_from_8_3(ctx, fname_mask,
3305 &new_mask, conn->params);
3307 TALLOC_FREE(fname_mask);
3308 fname_mask = new_mask;
3315 * Only one file needs to be unlinked. Append the mask back
3316 * onto the directory.
3318 TALLOC_FREE(smb_fname->base_name);
3319 if (ISDOT(fname_dir)) {
3320 /* Ensure we use canonical names on open. */
3321 smb_fname->base_name = talloc_asprintf(smb_fname,
3325 smb_fname->base_name = talloc_asprintf(smb_fname,
3330 if (!smb_fname->base_name) {
3331 status = NT_STATUS_NO_MEMORY;
3335 dirtype = FILE_ATTRIBUTE_NORMAL;
3338 status = check_name(conn, smb_fname);
3339 if (!NT_STATUS_IS_OK(status)) {
3343 status = do_unlink(conn, req, smb_fname, dirtype);
3344 if (!NT_STATUS_IS_OK(status)) {
3350 struct smb_Dir *dir_hnd = NULL;
3352 const char *dname = NULL;
3353 char *talloced = NULL;
3355 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3356 status = NT_STATUS_OBJECT_NAME_INVALID;
3360 dirtype = FILE_ATTRIBUTE_NORMAL;
3363 if (strequal(fname_mask,"????????.???")) {
3364 TALLOC_FREE(fname_mask);
3365 fname_mask = talloc_strdup(ctx, "*");
3367 status = NT_STATUS_NO_MEMORY;
3372 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3378 if (smb_fname_dir == NULL) {
3379 status = NT_STATUS_NO_MEMORY;
3383 status = check_name(conn, smb_fname_dir);
3384 if (!NT_STATUS_IS_OK(status)) {
3388 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3390 if (dir_hnd == NULL) {
3391 status = map_nt_error_from_unix(errno);
3395 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3396 the pattern matches against the long name, otherwise the short name
3397 We don't implement this yet XXXX
3400 status = NT_STATUS_NO_SUCH_FILE;
3402 while ((dname = ReadDirName(dir_hnd, &offset,
3403 &smb_fname->st, &talloced))) {
3404 TALLOC_CTX *frame = talloc_stackframe();
3406 struct smb_filename *f = NULL;
3408 if (!is_visible_file(conn,
3414 TALLOC_FREE(talloced);
3418 /* Quick check for "." and ".." */
3419 if (ISDOT(dname) || ISDOTDOT(dname)) {
3421 TALLOC_FREE(talloced);
3425 if(!mask_match(dname, fname_mask,
3426 conn->case_sensitive)) {
3428 TALLOC_FREE(talloced);
3432 if (ISDOT(fname_dir)) {
3433 /* Ensure we use canonical names on open. */
3434 p = talloc_asprintf(smb_fname, "%s", dname);
3436 p = talloc_asprintf(smb_fname, "%s/%s",
3440 TALLOC_FREE(dir_hnd);
3441 status = NT_STATUS_NO_MEMORY;
3443 TALLOC_FREE(talloced);
3446 f = synthetic_smb_fname(frame,
3453 TALLOC_FREE(dir_hnd);
3454 status = NT_STATUS_NO_MEMORY;
3456 TALLOC_FREE(talloced);
3460 status = openat_pathref_fsp(conn->cwd_fsp, f);
3461 if (!NT_STATUS_IS_OK(status) &&
3462 !NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK))
3464 TALLOC_FREE(dir_hnd);
3466 TALLOC_FREE(talloced);
3470 status = check_name(conn, f);
3471 if (!NT_STATUS_IS_OK(status)) {
3472 TALLOC_FREE(dir_hnd);
3474 TALLOC_FREE(talloced);
3478 status = do_unlink(conn, req, f, dirtype);
3479 if (!NT_STATUS_IS_OK(status)) {
3480 TALLOC_FREE(dir_hnd);
3482 TALLOC_FREE(talloced);
3487 DBG_DEBUG("successful unlink [%s]\n",
3488 smb_fname_str_dbg(f));
3491 TALLOC_FREE(talloced);
3493 TALLOC_FREE(dir_hnd);
3496 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3497 status = map_nt_error_from_unix(errno);
3501 TALLOC_FREE(smb_fname_dir);
3502 TALLOC_FREE(fname_dir);
3503 TALLOC_FREE(fname_mask);
3507 /****************************************************************************
3509 ****************************************************************************/
3511 void reply_unlink(struct smb_request *req)
3513 connection_struct *conn = req->conn;
3515 struct smb_filename *smb_fname = NULL;
3518 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3519 ucf_flags_from_smb_request(req);
3520 TALLOC_CTX *ctx = talloc_tos();
3521 bool has_wild = false;
3523 START_PROFILE(SMBunlink);
3526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3530 dirtype = SVAL(req->vwv+0, 0);
3532 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
3533 STR_TERMINATE, &status);
3534 if (!NT_STATUS_IS_OK(status)) {
3535 reply_nterror(req, status);
3539 status = filename_convert(ctx, conn,
3544 if (!NT_STATUS_IS_OK(status)) {
3545 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3546 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3547 ERRSRV, ERRbadpath);
3550 reply_nterror(req, status);
3554 if (req != NULL && !req->posix_pathnames) {
3555 char *lcomp = get_original_lcomp(ctx,
3559 if (lcomp == NULL) {
3560 reply_nterror(req, NT_STATUS_NO_MEMORY);
3563 has_wild = ms_has_wild(lcomp);
3567 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3569 status = unlink_internals(conn, req, dirtype, smb_fname, has_wild);
3570 if (!NT_STATUS_IS_OK(status)) {
3571 if (open_was_deferred(req->xconn, req->mid)) {
3572 /* We have re-scheduled this call. */
3575 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3576 bool ok = defer_smb1_sharing_violation(req);
3581 reply_nterror(req, status);
3585 reply_outbuf(req, 0, 0);
3587 TALLOC_FREE(smb_fname);
3588 END_PROFILE(SMBunlink);
3592 /****************************************************************************
3594 ****************************************************************************/
3596 static void fail_readraw(void)
3598 const char *errstr = talloc_asprintf(talloc_tos(),
3599 "FAIL ! reply_readbraw: socket write fail (%s)",
3604 exit_server_cleanly(errstr);
3607 /****************************************************************************
3608 Fake (read/write) sendfile. Returns -1 on read or write fail.
3609 ****************************************************************************/
3611 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3612 off_t startpos, size_t nread)
3615 size_t tosend = nread;
3622 bufsize = MIN(nread, 65536);
3624 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3628 while (tosend > 0) {
3632 cur_read = MIN(tosend, bufsize);
3633 ret = read_file(fsp,buf,startpos,cur_read);
3639 /* If we had a short read, fill with zeros. */
3640 if (ret < cur_read) {
3641 memset(buf + ret, '\0', cur_read - ret);
3644 ret = write_data(xconn->transport.sock, buf, cur_read);
3645 if (ret != cur_read) {
3646 int saved_errno = errno;
3648 * Try and give an error message saying what
3651 DEBUG(0, ("write_data failed for client %s. "
3653 smbXsrv_connection_dbg(xconn),
3654 strerror(saved_errno)));
3656 errno = saved_errno;
3660 startpos += cur_read;
3664 return (ssize_t)nread;
3667 /****************************************************************************
3668 Deal with the case of sendfile reading less bytes from the file than
3669 requested. Fill with zeros (all we can do). Returns 0 on success
3670 ****************************************************************************/
3672 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3678 #define SHORT_SEND_BUFSIZE 1024
3679 if (nread < headersize) {
3680 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3681 "header for file %s (%s). Terminating\n",
3682 fsp_str_dbg(fsp), strerror(errno)));
3686 nread -= headersize;
3688 if (nread < smb_maxcnt) {
3689 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3691 DEBUG(0,("sendfile_short_send: malloc failed "
3692 "for file %s (%s). Terminating\n",
3693 fsp_str_dbg(fsp), strerror(errno)));
3697 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3698 "with zeros !\n", fsp_str_dbg(fsp)));
3700 while (nread < smb_maxcnt) {
3702 * We asked for the real file size and told sendfile
3703 * to not go beyond the end of the file. But it can
3704 * happen that in between our fstat call and the
3705 * sendfile call the file was truncated. This is very
3706 * bad because we have already announced the larger
3707 * number of bytes to the client.
3709 * The best we can do now is to send 0-bytes, just as
3710 * a read from a hole in a sparse file would do.
3712 * This should happen rarely enough that I don't care
3713 * about efficiency here :-)
3718 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3719 ret = write_data(xconn->transport.sock, buf, to_write);
3720 if (ret != to_write) {
3721 int saved_errno = errno;
3723 * Try and give an error message saying what
3726 DEBUG(0, ("write_data failed for client %s. "
3728 smbXsrv_connection_dbg(xconn),
3729 strerror(saved_errno)));
3730 errno = saved_errno;
3741 /****************************************************************************
3742 Return a readbraw error (4 bytes of zero).
3743 ****************************************************************************/
3745 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3751 smbd_lock_socket(xconn);
3752 if (write_data(xconn->transport.sock,header,4) != 4) {
3753 int saved_errno = errno;
3755 * Try and give an error message saying what
3758 DEBUG(0, ("write_data failed for client %s. "
3760 smbXsrv_connection_dbg(xconn),
3761 strerror(saved_errno)));
3762 errno = saved_errno;
3766 smbd_unlock_socket(xconn);
3769 /*******************************************************************
3770 Ensure we don't use sendfile if server smb signing is active.
3771 ********************************************************************/
3773 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3775 bool sign_active = false;
3777 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3778 if (get_Protocol() < PROTOCOL_NT1) {
3781 if (signing_state) {
3782 sign_active = smb_signing_is_active(signing_state);
3784 return (lp__use_sendfile(snum) &&
3785 (get_remote_arch() != RA_WIN95) &&
3788 /****************************************************************************
3789 Use sendfile in readbraw.
3790 ****************************************************************************/
3792 static void send_file_readbraw(connection_struct *conn,
3793 struct smb_request *req,
3799 struct smbXsrv_connection *xconn = req->xconn;
3800 char *outbuf = NULL;
3804 * We can only use sendfile on a non-chained packet
3805 * but we can use on a non-oplocked file. tridge proved this
3806 * on a train in Germany :-). JRA.
3807 * reply_readbraw has already checked the length.
3810 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3811 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3812 ssize_t sendfile_read = -1;
3814 DATA_BLOB header_blob;
3816 _smb_setlen(header,nread);
3817 header_blob = data_blob_const(header, 4);
3819 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3820 &header_blob, startpos,
3822 if (sendfile_read == -1) {
3823 /* Returning ENOSYS means no data at all was sent.
3824 * Do this as a normal read. */
3825 if (errno == ENOSYS) {
3826 goto normal_readbraw;
3830 * Special hack for broken Linux with no working sendfile. If we
3831 * return EINTR we sent the header but not the rest of the data.
3832 * Fake this up by doing read/write calls.
3834 if (errno == EINTR) {
3835 /* Ensure we don't do this again. */
3836 set_use_sendfile(SNUM(conn), False);
3837 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3839 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3840 DEBUG(0,("send_file_readbraw: "
3841 "fake_sendfile failed for "
3845 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3850 DEBUG(0,("send_file_readbraw: sendfile failed for "
3851 "file %s (%s). Terminating\n",
3852 fsp_str_dbg(fsp), strerror(errno)));
3853 exit_server_cleanly("send_file_readbraw sendfile failed");
3854 } else if (sendfile_read == 0) {
3856 * Some sendfile implementations return 0 to indicate
3857 * that there was a short read, but nothing was
3858 * actually written to the socket. In this case,
3859 * fallback to the normal read path so the header gets
3860 * the correct byte count.
3862 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3863 "bytes falling back to the normal read: "
3864 "%s\n", fsp_str_dbg(fsp)));
3865 goto normal_readbraw;
3868 /* Deal with possible short send. */
3869 if (sendfile_read != 4+nread) {
3870 ret = sendfile_short_send(xconn, fsp,
3871 sendfile_read, 4, nread);
3881 outbuf = talloc_array(NULL, char, nread+4);
3883 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3884 (unsigned)(nread+4)));
3885 reply_readbraw_error(xconn);
3890 ret = read_file(fsp,outbuf+4,startpos,nread);
3891 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3900 _smb_setlen(outbuf,ret);
3901 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3902 int saved_errno = errno;
3904 * Try and give an error message saying what
3907 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3908 smbXsrv_connection_dbg(xconn),
3909 strerror(saved_errno)));
3910 errno = saved_errno;
3915 TALLOC_FREE(outbuf);
3918 /****************************************************************************
3919 Reply to a readbraw (core+ protocol).
3920 ****************************************************************************/
3922 void reply_readbraw(struct smb_request *req)
3924 connection_struct *conn = req->conn;
3925 struct smbXsrv_connection *xconn = req->xconn;
3926 ssize_t maxcount,mincount;
3930 struct lock_struct lock;
3934 START_PROFILE(SMBreadbraw);
3936 if (srv_is_signing_active(xconn) || req->encrypted) {
3937 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3938 "raw reads/writes are disallowed.");
3942 reply_readbraw_error(xconn);
3943 END_PROFILE(SMBreadbraw);
3947 if (xconn->smb1.echo_handler.trusted_fde) {
3948 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3949 "'async smb echo handler = yes'\n"));
3950 reply_readbraw_error(xconn);
3951 END_PROFILE(SMBreadbraw);
3956 * Special check if an oplock break has been issued
3957 * and the readraw request croses on the wire, we must
3958 * return a zero length response here.
3961 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3964 * We have to do a check_fsp by hand here, as
3965 * we must always return 4 zero bytes on error,
3971 conn != fsp->conn ||
3972 req->vuid != fsp->vuid ||
3973 fsp->fsp_flags.is_directory ||
3974 fsp_get_io_fd(fsp) == -1)
3977 * fsp could be NULL here so use the value from the packet. JRA.
3979 DEBUG(3,("reply_readbraw: fnum %d not valid "
3981 (int)SVAL(req->vwv+0, 0)));
3982 reply_readbraw_error(xconn);
3983 END_PROFILE(SMBreadbraw);
3987 /* Do a "by hand" version of CHECK_READ. */
3988 if (!(fsp->fsp_flags.can_read ||
3989 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3990 (fsp->access_mask & FILE_EXECUTE)))) {
3991 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3992 (int)SVAL(req->vwv+0, 0)));
3993 reply_readbraw_error(xconn);
3994 END_PROFILE(SMBreadbraw);
3998 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3999 if(req->wct == 10) {
4001 * This is a large offset (64 bit) read.
4004 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4007 DEBUG(0,("reply_readbraw: negative 64 bit "
4008 "readraw offset (%.0f) !\n",
4009 (double)startpos ));
4010 reply_readbraw_error(xconn);
4011 END_PROFILE(SMBreadbraw);
4016 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4017 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4019 /* ensure we don't overrun the packet size */
4020 maxcount = MIN(65535,maxcount);
4022 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4023 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4026 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4027 reply_readbraw_error(xconn);
4028 END_PROFILE(SMBreadbraw);
4032 status = vfs_stat_fsp(fsp);
4033 if (NT_STATUS_IS_OK(status)) {
4034 size = fsp->fsp_name->st.st_ex_size;
4037 if (startpos >= size) {
4040 nread = MIN(maxcount,(size - startpos));
4043 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4044 if (nread < mincount)
4048 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4049 "min=%lu nread=%lu\n",
4050 fsp_fnum_dbg(fsp), (double)startpos,
4051 (unsigned long)maxcount,
4052 (unsigned long)mincount,
4053 (unsigned long)nread ) );
4055 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4057 DEBUG(5,("reply_readbraw finished\n"));
4059 END_PROFILE(SMBreadbraw);
4064 #define DBGC_CLASS DBGC_LOCKING
4066 /****************************************************************************
4067 Reply to a lockread (core+ protocol).
4068 ****************************************************************************/
4070 static void reply_lockread_locked(struct tevent_req *subreq);
4072 void reply_lockread(struct smb_request *req)
4074 struct tevent_req *subreq = NULL;
4075 connection_struct *conn = req->conn;
4077 struct smbd_lock_element *lck = NULL;
4079 START_PROFILE(SMBlockread);
4082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4083 END_PROFILE(SMBlockread);
4087 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4089 if (!check_fsp(conn, req, fsp)) {
4090 END_PROFILE(SMBlockread);
4094 if (!CHECK_READ(fsp,req)) {
4095 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4096 END_PROFILE(SMBlockread);
4100 lck = talloc(req, struct smbd_lock_element);
4102 reply_nterror(req, NT_STATUS_NO_MEMORY);
4103 END_PROFILE(SMBlockread);
4108 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4109 * protocol request that predates the read/write lock concept.
4110 * Thus instead of asking for a read lock here we need to ask
4111 * for a write lock. JRA.
4112 * Note that the requested lock size is unaffected by max_send.
4115 *lck = (struct smbd_lock_element) {
4116 .req_guid = smbd_request_guid(req, 0),
4117 .smblctx = req->smbpid,
4118 .brltype = WRITE_LOCK,
4119 .count = SVAL(req->vwv+1, 0),
4120 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4123 subreq = smbd_smb1_do_locks_send(
4129 false, /* large_offset */
4133 if (subreq == NULL) {
4134 reply_nterror(req, NT_STATUS_NO_MEMORY);
4135 END_PROFILE(SMBlockread);
4138 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4139 END_PROFILE(SMBlockread);
4142 static void reply_lockread_locked(struct tevent_req *subreq)
4144 struct smb_request *req = NULL;
4150 size_t numtoread, maxtoread;
4151 struct files_struct *fsp = NULL;
4154 START_PROFILE(SMBlockread);
4156 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4159 status = smbd_smb1_do_locks_recv(subreq);
4160 TALLOC_FREE(subreq);
4162 if (!NT_STATUS_IS_OK(status)) {
4163 reply_nterror(req, status);
4167 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4169 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4173 numtoread = SVAL(req->vwv+1, 0);
4174 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4177 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4179 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4181 if (numtoread > maxtoread) {
4182 DBG_WARNING("requested read size (%zu) is greater than "
4183 "maximum allowed (%zu/%d). "
4184 "Returning short read of maximum allowed for "
4185 "compatibility with Windows 2000.\n",
4188 req->xconn->smb1.sessions.max_send);
4189 numtoread = maxtoread;
4192 reply_outbuf(req, 5, numtoread + 3);
4194 data = smb_buf(req->outbuf) + 3;
4196 nread = read_file(fsp,data,startpos,numtoread);
4199 reply_nterror(req, map_nt_error_from_unix(errno));
4203 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4205 SSVAL(req->outbuf,smb_vwv0,nread);
4206 SSVAL(req->outbuf,smb_vwv5,nread+3);
4207 p = smb_buf(req->outbuf);
4208 SCVAL(p,0,0); /* pad byte. */
4211 DEBUG(3,("lockread %s num=%d nread=%d\n",
4212 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4215 ok = srv_send_smb(req->xconn,
4216 (char *)req->outbuf,
4219 IS_CONN_ENCRYPTED(req->conn),
4222 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4225 END_PROFILE(SMBlockread);
4230 #define DBGC_CLASS DBGC_ALL
4232 /****************************************************************************
4234 ****************************************************************************/
4236 void reply_read(struct smb_request *req)
4238 connection_struct *conn = req->conn;
4245 struct lock_struct lock;
4246 struct smbXsrv_connection *xconn = req->xconn;
4248 START_PROFILE(SMBread);
4251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4252 END_PROFILE(SMBread);
4256 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4258 if (!check_fsp(conn, req, fsp)) {
4259 END_PROFILE(SMBread);
4263 if (!CHECK_READ(fsp,req)) {
4264 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4265 END_PROFILE(SMBread);
4269 numtoread = SVAL(req->vwv+1, 0);
4270 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4273 * The requested read size cannot be greater than max_send. JRA.
4275 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4277 if (numtoread > maxtoread) {
4278 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4279 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4280 (unsigned int)numtoread, (unsigned int)maxtoread,
4281 (unsigned int)xconn->smb1.sessions.max_send));
4282 numtoread = maxtoread;
4285 reply_outbuf(req, 5, numtoread+3);
4287 data = smb_buf(req->outbuf) + 3;
4289 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4290 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4293 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4294 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4295 END_PROFILE(SMBread);
4300 nread = read_file(fsp,data,startpos,numtoread);
4303 reply_nterror(req, map_nt_error_from_unix(errno));
4307 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4309 SSVAL(req->outbuf,smb_vwv0,nread);
4310 SSVAL(req->outbuf,smb_vwv5,nread+3);
4311 SCVAL(smb_buf(req->outbuf),0,1);
4312 SSVAL(smb_buf(req->outbuf),1,nread);
4314 DEBUG(3, ("read %s num=%d nread=%d\n",
4315 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4318 END_PROFILE(SMBread);
4322 /****************************************************************************
4324 ****************************************************************************/
4326 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4330 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4333 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4335 SCVAL(outbuf,smb_vwv0,0xFF);
4336 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4337 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4338 SSVAL(outbuf,smb_vwv6,
4339 (smb_wct - 4) /* offset from smb header to wct */
4340 + 1 /* the wct field */
4341 + 12 * sizeof(uint16_t) /* vwv */
4342 + 2 /* the buflen field */
4343 + 1); /* padding byte */
4344 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4345 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4346 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4347 _smb_setlen_large(outbuf,
4348 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4352 /****************************************************************************
4353 Reply to a read and X - possibly using sendfile.
4354 ****************************************************************************/
4356 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4357 files_struct *fsp, off_t startpos,
4360 struct smbXsrv_connection *xconn = req->xconn;
4362 struct lock_struct lock;
4363 int saved_errno = 0;
4366 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4367 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4370 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4371 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4376 * We can only use sendfile on a non-chained packet
4377 * but we can use on a non-oplocked file. tridge proved this
4378 * on a train in Germany :-). JRA.
4381 if (!req_is_in_chain(req) &&
4383 (fsp->base_fsp == NULL) &&
4384 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4385 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4388 status = vfs_stat_fsp(fsp);
4389 if (!NT_STATUS_IS_OK(status)) {
4390 reply_nterror(req, status);
4394 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4395 (startpos > fsp->fsp_name->st.st_ex_size) ||
4396 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4398 * We already know that we would do a short read, so don't
4399 * try the sendfile() path.
4401 goto nosendfile_read;
4405 * Set up the packet header before send. We
4406 * assume here the sendfile will work (get the
4407 * correct amount of data).
4410 header = data_blob_const(headerbuf, sizeof(headerbuf));
4412 construct_reply_common_req(req, (char *)headerbuf);
4413 setup_readX_header((char *)headerbuf, smb_maxcnt);
4415 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4416 startpos, smb_maxcnt);
4418 saved_errno = errno;
4420 /* Returning ENOSYS means no data at all was sent.
4421 Do this as a normal read. */
4422 if (errno == ENOSYS) {
4427 * Special hack for broken Linux with no working sendfile. If we
4428 * return EINTR we sent the header but not the rest of the data.
4429 * Fake this up by doing read/write calls.
4432 if (errno == EINTR) {
4433 /* Ensure we don't do this again. */
4434 set_use_sendfile(SNUM(conn), False);
4435 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4436 nread = fake_sendfile(xconn, fsp, startpos,
4439 saved_errno = errno;
4440 DEBUG(0,("send_file_readX: "
4441 "fake_sendfile failed for "
4442 "file %s (%s) for client %s. "
4445 smbXsrv_connection_dbg(xconn),
4446 strerror(saved_errno)));
4447 errno = saved_errno;
4448 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4450 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4451 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4452 /* No outbuf here means successful sendfile. */
4456 DEBUG(0,("send_file_readX: sendfile failed for file "
4457 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4459 exit_server_cleanly("send_file_readX sendfile failed");
4460 } else if (nread == 0) {
4462 * Some sendfile implementations return 0 to indicate
4463 * that there was a short read, but nothing was
4464 * actually written to the socket. In this case,
4465 * fallback to the normal read path so the header gets
4466 * the correct byte count.
4468 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4469 "falling back to the normal read: %s\n",
4474 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4475 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4477 /* Deal with possible short send. */
4478 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4481 ret = sendfile_short_send(xconn, fsp, nread,
4482 sizeof(headerbuf), smb_maxcnt);
4485 r = "send_file_readX: sendfile_short_send failed";
4486 DEBUG(0,("%s for file %s (%s).\n",
4487 r, fsp_str_dbg(fsp), strerror(errno)));
4488 exit_server_cleanly(r);
4491 /* No outbuf here means successful sendfile. */
4492 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4493 SMB_PERFCOUNT_END(&req->pcd);
4499 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4500 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4503 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4504 (startpos > fsp->fsp_name->st.st_ex_size) ||
4505 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4507 * We already know that we would do a short
4508 * read, so don't try the sendfile() path.
4510 goto nosendfile_read;
4513 construct_reply_common_req(req, (char *)headerbuf);
4514 setup_readX_header((char *)headerbuf, smb_maxcnt);
4516 /* Send out the header. */
4517 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4519 if (ret != sizeof(headerbuf)) {
4520 saved_errno = errno;
4522 * Try and give an error message saying what
4525 DEBUG(0,("send_file_readX: write_data failed for file "
4526 "%s (%s) for client %s. Terminating\n",
4528 smbXsrv_connection_dbg(xconn),
4529 strerror(saved_errno)));
4530 errno = saved_errno;
4531 exit_server_cleanly("send_file_readX sendfile failed");
4533 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4535 saved_errno = errno;
4536 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4537 "%s (%s) for client %s. Terminating\n",
4539 smbXsrv_connection_dbg(xconn),
4540 strerror(saved_errno)));
4541 errno = saved_errno;
4542 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4549 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4550 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4551 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4553 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4554 startpos, smb_maxcnt);
4555 saved_errno = errno;
4558 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4562 setup_readX_header((char *)req->outbuf, nread);
4564 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4565 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4569 TALLOC_FREE(req->outbuf);
4573 /****************************************************************************
4574 Work out how much space we have for a read return.
4575 ****************************************************************************/
4577 static size_t calc_max_read_pdu(const struct smb_request *req)
4579 struct smbXsrv_connection *xconn = req->xconn;
4581 if (xconn->protocol < PROTOCOL_NT1) {
4582 return xconn->smb1.sessions.max_send;
4585 if (!lp_large_readwrite()) {
4586 return xconn->smb1.sessions.max_send;
4589 if (req_is_in_chain(req)) {
4590 return xconn->smb1.sessions.max_send;
4593 if (req->encrypted) {
4595 * Don't take encrypted traffic up to the
4596 * limit. There are padding considerations
4597 * that make that tricky.
4599 return xconn->smb1.sessions.max_send;
4602 if (srv_is_signing_active(xconn)) {
4606 if (!lp_unix_extensions()) {
4611 * We can do ultra-large POSIX reads.
4616 /****************************************************************************
4617 Calculate how big a read can be. Copes with all clients. It's always
4618 safe to return a short read - Windows does this.
4619 ****************************************************************************/
4621 static size_t calc_read_size(const struct smb_request *req,
4625 struct smbXsrv_connection *xconn = req->xconn;
4626 size_t max_pdu = calc_max_read_pdu(req);
4627 size_t total_size = 0;
4628 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4629 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4632 * Windows explicitly ignores upper size of 0xFFFF.
4633 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4634 * We must do the same as these will never fit even in
4635 * an extended size NetBIOS packet.
4637 if (upper_size == 0xFFFF) {
4641 if (xconn->protocol < PROTOCOL_NT1) {
4645 total_size = ((upper_size<<16) | lower_size);
4648 * LARGE_READX test shows it's always safe to return
4649 * a short read. Windows does so.
4651 return MIN(total_size, max_len);
4654 /****************************************************************************
4655 Reply to a read and X.
4656 ****************************************************************************/
4658 void reply_read_and_X(struct smb_request *req)
4660 connection_struct *conn = req->conn;
4665 bool big_readX = False;
4667 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4670 START_PROFILE(SMBreadX);
4672 if ((req->wct != 10) && (req->wct != 12)) {
4673 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4677 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4678 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4679 smb_maxcnt = SVAL(req->vwv+5, 0);
4681 /* If it's an IPC, pass off the pipe handler. */
4683 reply_pipe_read_and_X(req);
4684 END_PROFILE(SMBreadX);
4688 if (!check_fsp(conn, req, fsp)) {
4689 END_PROFILE(SMBreadX);
4693 if (!CHECK_READ(fsp,req)) {
4694 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4695 END_PROFILE(SMBreadX);
4699 upper_size = SVAL(req->vwv+7, 0);
4700 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4701 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4703 * This is a heuristic to avoid keeping large
4704 * outgoing buffers around over long-lived aio
4710 if (req->wct == 12) {
4712 * This is a large offset (64 bit) read.
4714 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4719 NTSTATUS status = schedule_aio_read_and_X(conn,
4724 if (NT_STATUS_IS_OK(status)) {
4725 /* Read scheduled - we're done. */
4728 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4729 /* Real error - report to client. */
4730 END_PROFILE(SMBreadX);
4731 reply_nterror(req, status);
4734 /* NT_STATUS_RETRY - fall back to sync read. */
4737 smbd_lock_socket(req->xconn);
4738 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4739 smbd_unlock_socket(req->xconn);
4742 END_PROFILE(SMBreadX);
4746 /****************************************************************************
4747 Error replies to writebraw must have smb_wct == 1. Fix this up.
4748 ****************************************************************************/
4750 void error_to_writebrawerr(struct smb_request *req)
4752 uint8_t *old_outbuf = req->outbuf;
4754 reply_outbuf(req, 1, 0);
4756 memcpy(req->outbuf, old_outbuf, smb_size);
4757 TALLOC_FREE(old_outbuf);
4760 /****************************************************************************
4761 Read 4 bytes of a smb packet and return the smb length of the packet.
4762 Store the result in the buffer. This version of the function will
4763 never return a session keepalive (length of zero).
4764 Timeout is in milliseconds.
4765 ****************************************************************************/
4767 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4770 uint8_t msgtype = NBSSkeepalive;
4772 while (msgtype == NBSSkeepalive) {
4775 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4777 if (!NT_STATUS_IS_OK(status)) {
4778 char addr[INET6_ADDRSTRLEN];
4779 /* Try and give an error message
4780 * saying what client failed. */
4781 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4782 "client %s read error = %s.\n",
4783 get_peer_addr(fd,addr,sizeof(addr)),
4784 nt_errstr(status)));
4788 msgtype = CVAL(inbuf, 0);
4791 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4792 (unsigned long)len));
4794 return NT_STATUS_OK;
4797 /****************************************************************************
4798 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4799 ****************************************************************************/
4801 void reply_writebraw(struct smb_request *req)
4803 connection_struct *conn = req->conn;
4804 struct smbXsrv_connection *xconn = req->xconn;
4807 ssize_t total_written=0;
4808 size_t numtowrite=0;
4811 const char *data=NULL;
4814 struct lock_struct lock;
4817 START_PROFILE(SMBwritebraw);
4820 * If we ever reply with an error, it must have the SMB command
4821 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4824 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4826 if (srv_is_signing_active(xconn)) {
4827 END_PROFILE(SMBwritebraw);
4828 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4829 "raw reads/writes are disallowed.");
4832 if (req->wct < 12) {
4833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4834 error_to_writebrawerr(req);
4835 END_PROFILE(SMBwritebraw);
4839 if (xconn->smb1.echo_handler.trusted_fde) {
4840 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4841 "'async smb echo handler = yes'\n"));
4842 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4843 error_to_writebrawerr(req);
4844 END_PROFILE(SMBwritebraw);
4848 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4849 if (!check_fsp(conn, req, fsp)) {
4850 error_to_writebrawerr(req);
4851 END_PROFILE(SMBwritebraw);
4855 if (!CHECK_WRITE(fsp)) {
4856 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4857 error_to_writebrawerr(req);
4858 END_PROFILE(SMBwritebraw);
4862 tcount = IVAL(req->vwv+1, 0);
4863 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4864 write_through = BITSETW(req->vwv+7,0);
4866 /* We have to deal with slightly different formats depending
4867 on whether we are using the core+ or lanman1.0 protocol */
4869 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4870 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4871 data = smb_buf_const(req->inbuf);
4873 numtowrite = SVAL(req->vwv+10, 0);
4874 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4877 /* Ensure we don't write bytes past the end of this packet. */
4879 * This already protects us against CVE-2017-12163.
4881 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4882 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4883 error_to_writebrawerr(req);
4884 END_PROFILE(SMBwritebraw);
4888 if (!fsp->print_file) {
4889 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4890 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4893 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4894 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4895 error_to_writebrawerr(req);
4896 END_PROFILE(SMBwritebraw);
4902 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4905 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4906 "wrote=%d sync=%d\n",
4907 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4908 (int)nwritten, (int)write_through));
4910 if (nwritten < (ssize_t)numtowrite) {
4911 reply_nterror(req, NT_STATUS_DISK_FULL);
4912 error_to_writebrawerr(req);
4916 total_written = nwritten;
4918 /* Allocate a buffer of 64k + length. */
4919 buf = talloc_array(NULL, char, 65540);
4921 reply_nterror(req, NT_STATUS_NO_MEMORY);
4922 error_to_writebrawerr(req);
4926 /* Return a SMBwritebraw message to the redirector to tell
4927 * it to send more bytes */
4929 memcpy(buf, req->inbuf, smb_size);
4930 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4931 SCVAL(buf,smb_com,SMBwritebraw);
4932 SSVALS(buf,smb_vwv0,0xFFFF);
4934 if (!srv_send_smb(req->xconn,
4936 false, 0, /* no signing */
4937 IS_CONN_ENCRYPTED(conn),
4939 exit_server_cleanly("reply_writebraw: srv_send_smb "
4943 /* Now read the raw data into the buffer and write it */
4944 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4946 if (!NT_STATUS_IS_OK(status)) {
4947 exit_server_cleanly("secondary writebraw failed");
4950 /* Set up outbuf to return the correct size */
4951 reply_outbuf(req, 1, 0);
4953 if (numtowrite != 0) {
4955 if (numtowrite > 0xFFFF) {
4956 DEBUG(0,("reply_writebraw: Oversize secondary write "
4957 "raw requested (%u). Terminating\n",
4958 (unsigned int)numtowrite ));
4959 exit_server_cleanly("secondary writebraw failed");
4962 if (tcount > nwritten+numtowrite) {
4963 DEBUG(3,("reply_writebraw: Client overestimated the "
4965 (int)tcount,(int)nwritten,(int)numtowrite));
4968 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4971 if (!NT_STATUS_IS_OK(status)) {
4972 /* Try and give an error message
4973 * saying what client failed. */
4974 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4975 "raw read failed (%s) for client %s. "
4976 "Terminating\n", nt_errstr(status),
4977 smbXsrv_connection_dbg(xconn)));
4978 exit_server_cleanly("secondary writebraw failed");
4982 * We are not vulnerable to CVE-2017-12163
4983 * here as we are guaranteed to have numtowrite
4984 * bytes available - we just read from the client.
4986 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4987 if (nwritten == -1) {
4989 reply_nterror(req, map_nt_error_from_unix(errno));
4990 error_to_writebrawerr(req);
4994 if (nwritten < (ssize_t)numtowrite) {
4995 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4996 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5000 total_written += nwritten;
5005 SSVAL(req->outbuf,smb_vwv0,total_written);
5007 status = sync_file(conn, fsp, write_through);
5008 if (!NT_STATUS_IS_OK(status)) {
5009 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5010 fsp_str_dbg(fsp), nt_errstr(status)));
5011 reply_nterror(req, status);
5012 error_to_writebrawerr(req);
5016 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5018 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5019 (int)total_written));
5021 /* We won't return a status if write through is not selected - this
5022 * follows what WfWg does */
5023 END_PROFILE(SMBwritebraw);
5025 if (!write_through && total_written==tcount) {
5027 #if RABBIT_PELLET_FIX
5029 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5030 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5033 if (!send_keepalive(xconn->transport.sock)) {
5034 exit_server_cleanly("reply_writebraw: send of "
5035 "keepalive failed");
5038 TALLOC_FREE(req->outbuf);
5043 END_PROFILE(SMBwritebraw);
5048 #define DBGC_CLASS DBGC_LOCKING
5050 /****************************************************************************
5051 Reply to a writeunlock (core+).
5052 ****************************************************************************/
5054 void reply_writeunlock(struct smb_request *req)
5056 connection_struct *conn = req->conn;
5057 ssize_t nwritten = -1;
5062 NTSTATUS status = NT_STATUS_OK;
5064 struct lock_struct lock;
5065 int saved_errno = 0;
5067 START_PROFILE(SMBwriteunlock);
5070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5071 END_PROFILE(SMBwriteunlock);
5075 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5077 if (!check_fsp(conn, req, fsp)) {
5078 END_PROFILE(SMBwriteunlock);
5082 if (!CHECK_WRITE(fsp)) {
5083 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5084 END_PROFILE(SMBwriteunlock);
5088 numtowrite = SVAL(req->vwv+1, 0);
5089 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5090 data = (const char *)req->buf + 3;
5093 * Ensure client isn't asking us to write more than
5094 * they sent. CVE-2017-12163.
5096 remaining = smbreq_bufrem(req, data);
5097 if (numtowrite > remaining) {
5098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5099 END_PROFILE(SMBwriteunlock);
5103 if (!fsp->print_file && numtowrite > 0) {
5104 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5105 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5108 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5109 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5110 END_PROFILE(SMBwriteunlock);
5115 /* The special X/Open SMB protocol handling of
5116 zero length writes is *NOT* done for
5118 if(numtowrite == 0) {
5121 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5122 saved_errno = errno;
5125 status = sync_file(conn, fsp, False /* write through */);
5126 if (!NT_STATUS_IS_OK(status)) {
5127 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5128 fsp_str_dbg(fsp), nt_errstr(status)));
5129 reply_nterror(req, status);
5134 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5138 if((nwritten < numtowrite) && (numtowrite != 0)) {
5139 reply_nterror(req, NT_STATUS_DISK_FULL);
5143 if (numtowrite && !fsp->print_file) {
5144 struct smbd_lock_element l = {
5145 .req_guid = smbd_request_guid(req, 0),
5146 .smblctx = req->smbpid,
5147 .brltype = UNLOCK_LOCK,
5149 .count = numtowrite,
5151 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5152 if (NT_STATUS_V(status)) {
5153 reply_nterror(req, status);
5158 reply_outbuf(req, 1, 0);
5160 SSVAL(req->outbuf,smb_vwv0,nwritten);
5162 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5163 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5166 END_PROFILE(SMBwriteunlock);
5171 #define DBGC_CLASS DBGC_ALL
5173 /****************************************************************************
5175 ****************************************************************************/
5177 void reply_write(struct smb_request *req)
5179 connection_struct *conn = req->conn;
5182 ssize_t nwritten = -1;
5186 struct lock_struct lock;
5188 int saved_errno = 0;
5190 START_PROFILE(SMBwrite);
5193 END_PROFILE(SMBwrite);
5194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5198 /* If it's an IPC, pass off the pipe handler. */
5200 reply_pipe_write(req);
5201 END_PROFILE(SMBwrite);
5205 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5207 if (!check_fsp(conn, req, fsp)) {
5208 END_PROFILE(SMBwrite);
5212 if (!CHECK_WRITE(fsp)) {
5213 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5214 END_PROFILE(SMBwrite);
5218 numtowrite = SVAL(req->vwv+1, 0);
5219 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5220 data = (const char *)req->buf + 3;
5223 * Ensure client isn't asking us to write more than
5224 * they sent. CVE-2017-12163.
5226 remaining = smbreq_bufrem(req, data);
5227 if (numtowrite > remaining) {
5228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5229 END_PROFILE(SMBwrite);
5233 if (!fsp->print_file) {
5234 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5235 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5238 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5239 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5240 END_PROFILE(SMBwrite);
5246 * X/Open SMB protocol says that if smb_vwv1 is
5247 * zero then the file size should be extended or
5248 * truncated to the size given in smb_vwv[2-3].
5251 if(numtowrite == 0) {
5253 * This is actually an allocate call, and set EOF. JRA.
5255 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5257 reply_nterror(req, NT_STATUS_DISK_FULL);
5260 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5262 reply_nterror(req, NT_STATUS_DISK_FULL);
5265 trigger_write_time_update_immediate(fsp);
5267 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5270 status = sync_file(conn, fsp, False);
5271 if (!NT_STATUS_IS_OK(status)) {
5272 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5273 fsp_str_dbg(fsp), nt_errstr(status)));
5274 reply_nterror(req, status);
5279 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5283 if((nwritten == 0) && (numtowrite != 0)) {
5284 reply_nterror(req, NT_STATUS_DISK_FULL);
5288 reply_outbuf(req, 1, 0);
5290 SSVAL(req->outbuf,smb_vwv0,nwritten);
5292 if (nwritten < (ssize_t)numtowrite) {
5293 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5294 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5297 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5300 END_PROFILE(SMBwrite);
5304 /****************************************************************************
5305 Ensure a buffer is a valid writeX for recvfile purposes.
5306 ****************************************************************************/
5308 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5309 (2*14) + /* word count (including bcc) */ \
5312 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5313 const uint8_t *inbuf)
5316 unsigned int doff = 0;
5317 size_t len = smb_len_large(inbuf);
5319 struct smbXsrv_open *op = NULL;
5320 struct files_struct *fsp = NULL;
5323 if (is_encrypted_packet(inbuf)) {
5324 /* Can't do this on encrypted
5329 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5333 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5334 CVAL(inbuf,smb_wct) != 14) {
5335 DEBUG(10,("is_valid_writeX_buffer: chained or "
5336 "invalid word length.\n"));
5340 fnum = SVAL(inbuf, smb_vwv2);
5341 status = smb1srv_open_lookup(xconn,
5345 if (!NT_STATUS_IS_OK(status)) {
5346 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5351 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5354 if (fsp->conn == NULL) {
5355 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5359 if (IS_IPC(fsp->conn)) {
5360 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5363 if (IS_PRINT(fsp->conn)) {
5364 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5367 if (fsp->base_fsp != NULL) {
5368 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5371 doff = SVAL(inbuf,smb_vwv11);
5373 numtowrite = SVAL(inbuf,smb_vwv10);
5375 if (len > doff && len - doff > 0xFFFF) {
5376 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5379 if (numtowrite == 0) {
5380 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5384 /* Ensure the sizes match up. */
5385 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5386 /* no pad byte...old smbclient :-( */
5387 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5389 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5393 if (len - doff != numtowrite) {
5394 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5395 "len = %u, doff = %u, numtowrite = %u\n",
5398 (unsigned int)numtowrite ));
5402 DEBUG(10,("is_valid_writeX_buffer: true "
5403 "len = %u, doff = %u, numtowrite = %u\n",
5406 (unsigned int)numtowrite ));
5411 /****************************************************************************
5412 Reply to a write and X.
5413 ****************************************************************************/
5415 void reply_write_and_X(struct smb_request *req)
5417 connection_struct *conn = req->conn;
5418 struct smbXsrv_connection *xconn = req->xconn;
5420 struct lock_struct lock;
5425 unsigned int smb_doff;
5426 unsigned int smblen;
5429 int saved_errno = 0;
5431 START_PROFILE(SMBwriteX);
5433 if ((req->wct != 12) && (req->wct != 14)) {
5434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5438 numtowrite = SVAL(req->vwv+10, 0);
5439 smb_doff = SVAL(req->vwv+11, 0);
5440 smblen = smb_len(req->inbuf);
5442 if (req->unread_bytes > 0xFFFF ||
5443 (smblen > smb_doff &&
5444 smblen - smb_doff > 0xFFFF)) {
5445 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5448 if (req->unread_bytes) {
5449 /* Can't do a recvfile write on IPC$ */
5451 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5454 if (numtowrite != req->unread_bytes) {
5455 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5460 * This already protects us against CVE-2017-12163.
5462 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5463 smb_doff + numtowrite > smblen) {
5464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5469 /* If it's an IPC, pass off the pipe handler. */
5471 if (req->unread_bytes) {
5472 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5475 reply_pipe_write_and_X(req);
5479 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5480 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5481 write_through = BITSETW(req->vwv+7,0);
5483 if (!check_fsp(conn, req, fsp)) {
5487 if (!CHECK_WRITE(fsp)) {
5488 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5492 data = smb_base(req->inbuf) + smb_doff;
5494 if(req->wct == 14) {
5496 * This is a large offset (64 bit) write.
5498 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5502 /* X/Open SMB protocol says that, unlike SMBwrite
5503 if the length is zero then NO truncation is
5504 done, just a write of zero. To truncate a file,
5507 if(numtowrite == 0) {
5510 if (req->unread_bytes == 0) {
5511 status = schedule_aio_write_and_X(conn,
5518 if (NT_STATUS_IS_OK(status)) {
5519 /* write scheduled - we're done. */
5522 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5523 /* Real error - report to client. */
5524 reply_nterror(req, status);
5527 /* NT_STATUS_RETRY - fall through to sync write. */
5530 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5531 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5534 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5535 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5539 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5540 saved_errno = errno;
5544 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5548 if((nwritten == 0) && (numtowrite != 0)) {
5549 reply_nterror(req, NT_STATUS_DISK_FULL);
5553 reply_outbuf(req, 6, 0);
5554 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5555 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5556 SSVAL(req->outbuf,smb_vwv2,nwritten);
5557 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5559 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5560 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5562 status = sync_file(conn, fsp, write_through);
5563 if (!NT_STATUS_IS_OK(status)) {
5564 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5565 fsp_str_dbg(fsp), nt_errstr(status)));
5566 reply_nterror(req, status);
5570 END_PROFILE(SMBwriteX);
5574 if (req->unread_bytes) {
5575 /* writeX failed. drain socket. */
5576 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5577 req->unread_bytes) {
5578 smb_panic("failed to drain pending bytes");
5580 req->unread_bytes = 0;
5583 END_PROFILE(SMBwriteX);
5587 /****************************************************************************
5589 ****************************************************************************/
5591 void reply_lseek(struct smb_request *req)
5593 connection_struct *conn = req->conn;
5600 START_PROFILE(SMBlseek);
5603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5604 END_PROFILE(SMBlseek);
5608 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5610 if (!check_fsp(conn, req, fsp)) {
5614 mode = SVAL(req->vwv+1, 0) & 3;
5615 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5616 startpos = (off_t)IVALS(req->vwv+2, 0);
5625 res = fh_get_pos(fsp->fh) + startpos;
5636 if (umode == SEEK_END) {
5637 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5638 if(errno == EINVAL) {
5639 off_t current_pos = startpos;
5641 status = vfs_stat_fsp(fsp);
5642 if (!NT_STATUS_IS_OK(status)) {
5643 reply_nterror(req, status);
5644 END_PROFILE(SMBlseek);
5648 current_pos += fsp->fsp_name->st.st_ex_size;
5650 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5655 reply_nterror(req, map_nt_error_from_unix(errno));
5656 END_PROFILE(SMBlseek);
5661 fh_set_pos(fsp->fh, res);
5663 reply_outbuf(req, 2, 0);
5664 SIVAL(req->outbuf,smb_vwv0,res);
5666 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5667 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5669 END_PROFILE(SMBlseek);
5673 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5676 connection_struct *conn = talloc_get_type_abort(
5677 private_data, connection_struct);
5679 if (conn != fsp->conn) {
5682 if (fsp_get_io_fd(fsp) == -1) {
5685 sync_file(conn, fsp, True /* write through */);
5687 if (fsp->fsp_flags.modified) {
5688 trigger_write_time_update_immediate(fsp);
5694 /****************************************************************************
5696 ****************************************************************************/
5698 void reply_flush(struct smb_request *req)
5700 connection_struct *conn = req->conn;
5704 START_PROFILE(SMBflush);
5707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5711 fnum = SVAL(req->vwv+0, 0);
5712 fsp = file_fsp(req, fnum);
5714 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5719 files_forall(req->sconn, file_sync_one_fn, conn);
5721 NTSTATUS status = sync_file(conn, fsp, True);
5722 if (!NT_STATUS_IS_OK(status)) {
5723 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5724 fsp_str_dbg(fsp), nt_errstr(status)));
5725 reply_nterror(req, status);
5726 END_PROFILE(SMBflush);
5729 if (fsp->fsp_flags.modified) {
5730 trigger_write_time_update_immediate(fsp);
5734 reply_outbuf(req, 0, 0);
5736 DEBUG(3,("flush\n"));
5737 END_PROFILE(SMBflush);
5741 /****************************************************************************
5743 conn POINTER CAN BE NULL HERE !
5744 ****************************************************************************/
5746 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5747 static void reply_exit_done(struct tevent_req *req);
5749 void reply_exit(struct smb_request *smb1req)
5751 struct tevent_req *req;
5754 * Don't setup the profile charge here, take
5755 * it in reply_exit_done(). Not strictly correct
5756 * but better than the other SMB1 async
5757 * code that double-charges at the moment.
5759 req = reply_exit_send(smb1req);
5761 /* Not going async, profile here. */
5762 START_PROFILE(SMBexit);
5763 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5764 END_PROFILE(SMBexit);
5768 /* We're async. This will complete later. */
5769 tevent_req_set_callback(req, reply_exit_done, smb1req);
5773 struct reply_exit_state {
5774 struct tevent_queue *wait_queue;
5777 static void reply_exit_wait_done(struct tevent_req *subreq);
5779 /****************************************************************************
5781 Note, on failure here we deallocate and return NULL to allow the caller to
5782 SMB1 return an error of ERRnomem immediately.
5783 ****************************************************************************/
5785 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5787 struct tevent_req *req;
5788 struct reply_exit_state *state;
5789 struct tevent_req *subreq;
5791 struct smbd_server_connection *sconn = smb1req->sconn;
5793 req = tevent_req_create(smb1req, &state,
5794 struct reply_exit_state);
5798 state->wait_queue = tevent_queue_create(state,
5799 "reply_exit_wait_queue");
5800 if (tevent_req_nomem(state->wait_queue, req)) {
5805 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5806 if (fsp->file_pid != smb1req->smbpid) {
5809 if (fsp->vuid != smb1req->vuid) {
5813 * Flag the file as close in progress.
5814 * This will prevent any more IO being
5817 fsp->fsp_flags.closing = true;
5819 if (fsp->num_aio_requests > 0) {
5821 * Now wait until all aio requests on this fsp are
5824 * We don't set a callback, as we just want to block the
5825 * wait queue and the talloc_free() of fsp->aio_request
5826 * will remove the item from the wait queue.
5828 subreq = tevent_queue_wait_send(fsp->aio_requests,
5831 if (tevent_req_nomem(subreq, req)) {
5839 * Now we add our own waiter to the end of the queue,
5840 * this way we get notified when all pending requests are finished
5841 * and reply to the outstanding SMB1 request.
5843 subreq = tevent_queue_wait_send(state,
5846 if (tevent_req_nomem(subreq, req)) {
5852 * We're really going async - move the SMB1 request from
5853 * a talloc stackframe above us to the conn talloc-context.
5854 * We need this to stick around until the wait_done
5855 * callback is invoked.
5857 smb1req = talloc_move(sconn, &smb1req);
5859 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5864 static void reply_exit_wait_done(struct tevent_req *subreq)
5866 struct tevent_req *req = tevent_req_callback_data(
5867 subreq, struct tevent_req);
5869 tevent_queue_wait_recv(subreq);
5870 TALLOC_FREE(subreq);
5871 tevent_req_done(req);
5874 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5876 return tevent_req_simple_recv_ntstatus(req);
5879 static void reply_exit_done(struct tevent_req *req)
5881 struct smb_request *smb1req = tevent_req_callback_data(
5882 req, struct smb_request);
5883 struct smbd_server_connection *sconn = smb1req->sconn;
5884 struct smbXsrv_connection *xconn = smb1req->xconn;
5885 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5886 struct smbXsrv_session *session = NULL;
5887 files_struct *fsp, *next;
5891 * Take the profile charge here. Not strictly
5892 * correct but better than the other SMB1 async
5893 * code that double-charges at the moment.
5895 START_PROFILE(SMBexit);
5897 status = reply_exit_recv(req);
5899 if (!NT_STATUS_IS_OK(status)) {
5900 TALLOC_FREE(smb1req);
5901 END_PROFILE(SMBexit);
5902 exit_server(__location__ ": reply_exit_recv failed");
5907 * Ensure the session is still valid.
5909 status = smb1srv_session_lookup(xconn,
5913 if (!NT_STATUS_IS_OK(status)) {
5914 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5915 smb_request_done(smb1req);
5916 END_PROFILE(SMBexit);
5920 * Ensure the vuid is still valid - no one
5921 * called reply_ulogoffX() in the meantime.
5922 * reply_exit() doesn't have AS_USER set, so
5923 * use set_current_user_info() directly.
5924 * This is the same logic as in switch_message().
5926 if (session->global->auth_session_info != NULL) {
5927 set_current_user_info(
5928 session->global->auth_session_info->unix_info->sanitized_username,
5929 session->global->auth_session_info->unix_info->unix_name,
5930 session->global->auth_session_info->info->domain_name);
5933 /* No more aio - do the actual closes. */
5934 for (fsp = sconn->files; fsp; fsp = next) {
5938 if (fsp->file_pid != smb1req->smbpid) {
5941 if (fsp->vuid != smb1req->vuid) {
5944 if (!fsp->fsp_flags.closing) {
5949 * reply_exit() has the DO_CHDIR flag set.
5951 ok = chdir_current_service(fsp->conn);
5953 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5954 smb_request_done(smb1req);
5955 END_PROFILE(SMBexit);
5957 close_file(NULL, fsp, SHUTDOWN_CLOSE);
5960 reply_outbuf(smb1req, 0, 0);
5962 * The following call is needed to push the
5963 * reply data back out the socket after async
5964 * return. Plus it frees smb1req.
5966 smb_request_done(smb1req);
5967 DBG_INFO("reply_exit complete\n");
5968 END_PROFILE(SMBexit);
5972 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5974 static void reply_close_done(struct tevent_req *req);
5976 void reply_close(struct smb_request *smb1req)
5978 connection_struct *conn = smb1req->conn;
5979 NTSTATUS status = NT_STATUS_OK;
5980 files_struct *fsp = NULL;
5981 START_PROFILE(SMBclose);
5983 if (smb1req->wct < 3) {
5984 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5985 END_PROFILE(SMBclose);
5989 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5992 * We can only use check_fsp if we know it's not a directory.
5995 if (!check_fsp_open(conn, smb1req, fsp)) {
5996 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
5997 END_PROFILE(SMBclose);
6001 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6002 fsp->fsp_flags.is_directory ?
6003 "directory" : "file",
6004 fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
6005 conn->num_files_open);
6007 if (!fsp->fsp_flags.is_directory) {
6011 * Take care of any time sent in the close.
6014 t = srv_make_unix_date3(smb1req->vwv+1);
6015 set_close_write_time(fsp, time_t_to_full_timespec(t));
6018 if (fsp->num_aio_requests != 0) {
6019 struct tevent_req *req;
6021 req = reply_close_send(smb1req, fsp);
6023 status = NT_STATUS_NO_MEMORY;
6026 /* We're async. This will complete later. */
6027 tevent_req_set_callback(req, reply_close_done, smb1req);
6028 END_PROFILE(SMBclose);
6033 * close_file() returns the unix errno if an error was detected on
6034 * close - normally this is due to a disk full error. If not then it
6035 * was probably an I/O error.
6038 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6040 if (!NT_STATUS_IS_OK(status)) {
6041 reply_nterror(smb1req, status);
6042 END_PROFILE(SMBclose);
6046 reply_outbuf(smb1req, 0, 0);
6047 END_PROFILE(SMBclose);
6051 struct reply_close_state {
6053 struct tevent_queue *wait_queue;
6056 static void reply_close_wait_done(struct tevent_req *subreq);
6058 /****************************************************************************
6060 Note, on failure here we deallocate and return NULL to allow the caller to
6061 SMB1 return an error of ERRnomem immediately.
6062 ****************************************************************************/
6064 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6067 struct tevent_req *req;
6068 struct reply_close_state *state;
6069 struct tevent_req *subreq;
6070 struct smbd_server_connection *sconn = smb1req->sconn;
6072 req = tevent_req_create(smb1req, &state,
6073 struct reply_close_state);
6077 state->wait_queue = tevent_queue_create(state,
6078 "reply_close_wait_queue");
6079 if (tevent_req_nomem(state->wait_queue, req)) {
6085 * Flag the file as close in progress.
6086 * This will prevent any more IO being
6089 fsp->fsp_flags.closing = true;
6092 * Now wait until all aio requests on this fsp are
6095 * We don't set a callback, as we just want to block the
6096 * wait queue and the talloc_free() of fsp->aio_request
6097 * will remove the item from the wait queue.
6099 subreq = tevent_queue_wait_send(fsp->aio_requests,
6102 if (tevent_req_nomem(subreq, req)) {
6108 * Now we add our own waiter to the end of the queue,
6109 * this way we get notified when all pending requests are finished
6110 * and reply to the outstanding SMB1 request.
6112 subreq = tevent_queue_wait_send(state,
6115 if (tevent_req_nomem(subreq, req)) {
6121 * We're really going async - move the SMB1 request from
6122 * a talloc stackframe above us to the conn talloc-context.
6123 * We need this to stick around until the wait_done
6124 * callback is invoked.
6126 smb1req = talloc_move(sconn, &smb1req);
6128 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6133 static void reply_close_wait_done(struct tevent_req *subreq)
6135 struct tevent_req *req = tevent_req_callback_data(
6136 subreq, struct tevent_req);
6138 tevent_queue_wait_recv(subreq);
6139 TALLOC_FREE(subreq);
6140 tevent_req_done(req);
6143 static NTSTATUS reply_close_recv(struct tevent_req *req)
6145 return tevent_req_simple_recv_ntstatus(req);
6148 static void reply_close_done(struct tevent_req *req)
6150 struct smb_request *smb1req = tevent_req_callback_data(
6151 req, struct smb_request);
6152 struct reply_close_state *state = tevent_req_data(req,
6153 struct reply_close_state);
6156 status = reply_close_recv(req);
6158 if (!NT_STATUS_IS_OK(status)) {
6159 TALLOC_FREE(smb1req);
6160 exit_server(__location__ ": reply_close_recv failed");
6164 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6165 if (NT_STATUS_IS_OK(status)) {
6166 reply_outbuf(smb1req, 0, 0);
6168 reply_nterror(smb1req, status);
6171 * The following call is needed to push the
6172 * reply data back out the socket after async
6173 * return. Plus it frees smb1req.
6175 smb_request_done(smb1req);
6178 /****************************************************************************
6179 Reply to a writeclose (Core+ protocol).
6180 ****************************************************************************/
6182 void reply_writeclose(struct smb_request *req)
6184 connection_struct *conn = req->conn;
6187 ssize_t nwritten = -1;
6188 NTSTATUS close_status = NT_STATUS_OK;
6191 struct timespec mtime;
6193 struct lock_struct lock;
6195 START_PROFILE(SMBwriteclose);
6198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6199 END_PROFILE(SMBwriteclose);
6203 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6205 if (!check_fsp(conn, req, fsp)) {
6206 END_PROFILE(SMBwriteclose);
6209 if (!CHECK_WRITE(fsp)) {
6210 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6211 END_PROFILE(SMBwriteclose);
6215 numtowrite = SVAL(req->vwv+1, 0);
6216 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6217 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6218 data = (const char *)req->buf + 1;
6221 * Ensure client isn't asking us to write more than
6222 * they sent. CVE-2017-12163.
6224 remaining = smbreq_bufrem(req, data);
6225 if (numtowrite > remaining) {
6226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6227 END_PROFILE(SMBwriteclose);
6231 if (fsp->print_file == NULL) {
6232 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6233 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6236 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6237 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6238 END_PROFILE(SMBwriteclose);
6243 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6245 set_close_write_time(fsp, mtime);
6248 * More insanity. W2K only closes the file if writelen > 0.
6252 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6253 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6254 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6257 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6258 "file %s\n", fsp_str_dbg(fsp)));
6259 close_status = close_file(req, fsp, NORMAL_CLOSE);
6263 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6264 reply_nterror(req, NT_STATUS_DISK_FULL);
6268 if(!NT_STATUS_IS_OK(close_status)) {
6269 reply_nterror(req, close_status);
6273 reply_outbuf(req, 1, 0);
6275 SSVAL(req->outbuf,smb_vwv0,nwritten);
6279 END_PROFILE(SMBwriteclose);
6284 #define DBGC_CLASS DBGC_LOCKING
6286 /****************************************************************************
6288 ****************************************************************************/
6290 static void reply_lock_done(struct tevent_req *subreq);
6292 void reply_lock(struct smb_request *req)
6294 struct tevent_req *subreq = NULL;
6295 connection_struct *conn = req->conn;
6297 struct smbd_lock_element *lck = NULL;
6299 START_PROFILE(SMBlock);
6302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6303 END_PROFILE(SMBlock);
6307 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6309 if (!check_fsp(conn, req, fsp)) {
6310 END_PROFILE(SMBlock);
6314 lck = talloc(req, struct smbd_lock_element);
6316 reply_nterror(req, NT_STATUS_NO_MEMORY);
6317 END_PROFILE(SMBlock);
6321 *lck = (struct smbd_lock_element) {
6322 .req_guid = smbd_request_guid(req, 0),
6323 .smblctx = req->smbpid,
6324 .brltype = WRITE_LOCK,
6325 .count = IVAL(req->vwv+1, 0),
6326 .offset = IVAL(req->vwv+3, 0),
6329 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6335 subreq = smbd_smb1_do_locks_send(
6341 false, /* large_offset */
6345 if (subreq == NULL) {
6346 reply_nterror(req, NT_STATUS_NO_MEMORY);
6347 END_PROFILE(SMBlock);
6350 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6351 END_PROFILE(SMBlock);
6354 static void reply_lock_done(struct tevent_req *subreq)
6356 struct smb_request *req = NULL;
6360 START_PROFILE(SMBlock);
6362 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6365 status = smbd_smb1_do_locks_recv(subreq);
6366 TALLOC_FREE(subreq);
6368 if (NT_STATUS_IS_OK(status)) {
6369 reply_outbuf(req, 0, 0);
6371 reply_nterror(req, status);
6374 ok = srv_send_smb(req->xconn,
6375 (char *)req->outbuf,
6378 IS_CONN_ENCRYPTED(req->conn),
6381 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6384 END_PROFILE(SMBlock);
6387 /****************************************************************************
6389 ****************************************************************************/
6391 void reply_unlock(struct smb_request *req)
6393 connection_struct *conn = req->conn;
6396 struct smbd_lock_element lck;
6398 START_PROFILE(SMBunlock);
6401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6402 END_PROFILE(SMBunlock);
6406 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6408 if (!check_fsp(conn, req, fsp)) {
6409 END_PROFILE(SMBunlock);
6413 lck = (struct smbd_lock_element) {
6414 .req_guid = smbd_request_guid(req, 0),
6415 .smblctx = req->smbpid,
6416 .brltype = UNLOCK_LOCK,
6417 .offset = IVAL(req->vwv+3, 0),
6418 .count = IVAL(req->vwv+1, 0),
6421 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6423 if (!NT_STATUS_IS_OK(status)) {
6424 reply_nterror(req, status);
6425 END_PROFILE(SMBunlock);
6429 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6435 reply_outbuf(req, 0, 0);
6437 END_PROFILE(SMBunlock);
6442 #define DBGC_CLASS DBGC_ALL
6444 /****************************************************************************
6446 conn POINTER CAN BE NULL HERE !
6447 ****************************************************************************/
6449 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6450 static void reply_tdis_done(struct tevent_req *req);
6452 void reply_tdis(struct smb_request *smb1req)
6454 connection_struct *conn = smb1req->conn;
6455 struct tevent_req *req;
6458 * Don't setup the profile charge here, take
6459 * it in reply_tdis_done(). Not strictly correct
6460 * but better than the other SMB1 async
6461 * code that double-charges at the moment.
6465 /* Not going async, profile here. */
6466 START_PROFILE(SMBtdis);
6467 DBG_INFO("Invalid connection in tdis\n");
6468 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6469 END_PROFILE(SMBtdis);
6473 req = reply_tdis_send(smb1req);
6475 /* Not going async, profile here. */
6476 START_PROFILE(SMBtdis);
6477 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6478 END_PROFILE(SMBtdis);
6481 /* We're async. This will complete later. */
6482 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6486 struct reply_tdis_state {
6487 struct tevent_queue *wait_queue;
6490 static void reply_tdis_wait_done(struct tevent_req *subreq);
6492 /****************************************************************************
6494 Note, on failure here we deallocate and return NULL to allow the caller to
6495 SMB1 return an error of ERRnomem immediately.
6496 ****************************************************************************/
6498 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6500 struct tevent_req *req;
6501 struct reply_tdis_state *state;
6502 struct tevent_req *subreq;
6503 connection_struct *conn = smb1req->conn;
6506 req = tevent_req_create(smb1req, &state,
6507 struct reply_tdis_state);
6511 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6512 if (tevent_req_nomem(state->wait_queue, req)) {
6518 * Make sure that no new request will be able to use this tcon.
6519 * This ensures that once all outstanding fsp->aio_requests
6520 * on this tcon are done, we are safe to close it.
6522 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6524 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6525 if (fsp->conn != conn) {
6529 * Flag the file as close in progress.
6530 * This will prevent any more IO being
6531 * done on it. Not strictly needed, but
6532 * doesn't hurt to flag it as closing.
6534 fsp->fsp_flags.closing = true;
6536 if (fsp->num_aio_requests > 0) {
6538 * Now wait until all aio requests on this fsp are
6541 * We don't set a callback, as we just want to block the
6542 * wait queue and the talloc_free() of fsp->aio_request
6543 * will remove the item from the wait queue.
6545 subreq = tevent_queue_wait_send(fsp->aio_requests,
6546 conn->sconn->ev_ctx,
6548 if (tevent_req_nomem(subreq, req)) {
6556 * Now we add our own waiter to the end of the queue,
6557 * this way we get notified when all pending requests are finished
6558 * and reply to the outstanding SMB1 request.
6560 subreq = tevent_queue_wait_send(state,
6561 conn->sconn->ev_ctx,
6563 if (tevent_req_nomem(subreq, req)) {
6569 * We're really going async - move the SMB1 request from
6570 * a talloc stackframe above us to the sconn talloc-context.
6571 * We need this to stick around until the wait_done
6572 * callback is invoked.
6574 smb1req = talloc_move(smb1req->sconn, &smb1req);
6576 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6581 static void reply_tdis_wait_done(struct tevent_req *subreq)
6583 struct tevent_req *req = tevent_req_callback_data(
6584 subreq, struct tevent_req);
6586 tevent_queue_wait_recv(subreq);
6587 TALLOC_FREE(subreq);
6588 tevent_req_done(req);
6591 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6593 return tevent_req_simple_recv_ntstatus(req);
6596 static void reply_tdis_done(struct tevent_req *req)
6598 struct smb_request *smb1req = tevent_req_callback_data(
6599 req, struct smb_request);
6601 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6605 * Take the profile charge here. Not strictly
6606 * correct but better than the other SMB1 async
6607 * code that double-charges at the moment.
6609 START_PROFILE(SMBtdis);
6611 status = reply_tdis_recv(req);
6613 if (!NT_STATUS_IS_OK(status)) {
6614 TALLOC_FREE(smb1req);
6615 END_PROFILE(SMBtdis);
6616 exit_server(__location__ ": reply_tdis_recv failed");
6621 * As we've been awoken, we may have changed
6622 * directory in the meantime.
6623 * reply_tdis() has the DO_CHDIR flag set.
6625 ok = chdir_current_service(smb1req->conn);
6627 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6628 smb_request_done(smb1req);
6629 END_PROFILE(SMBtdis);
6632 status = smbXsrv_tcon_disconnect(tcon,
6634 if (!NT_STATUS_IS_OK(status)) {
6635 TALLOC_FREE(smb1req);
6636 END_PROFILE(SMBtdis);
6637 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6641 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6642 smb1req->conn = NULL;
6646 reply_outbuf(smb1req, 0, 0);
6648 * The following call is needed to push the
6649 * reply data back out the socket after async
6650 * return. Plus it frees smb1req.
6652 smb_request_done(smb1req);
6653 END_PROFILE(SMBtdis);
6656 /****************************************************************************
6658 conn POINTER CAN BE NULL HERE !
6659 ****************************************************************************/
6661 void reply_echo(struct smb_request *req)
6663 connection_struct *conn = req->conn;
6664 struct smb_perfcount_data local_pcd;
6665 struct smb_perfcount_data *cur_pcd;
6669 START_PROFILE(SMBecho);
6671 smb_init_perfcount_data(&local_pcd);
6674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6675 END_PROFILE(SMBecho);
6679 smb_reverb = SVAL(req->vwv+0, 0);
6681 reply_outbuf(req, 1, req->buflen);
6683 /* copy any incoming data back out */
6684 if (req->buflen > 0) {
6685 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6688 if (smb_reverb > 100) {
6689 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6693 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6695 /* this makes sure we catch the request pcd */
6696 if (seq_num == smb_reverb) {
6697 cur_pcd = &req->pcd;
6699 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6700 cur_pcd = &local_pcd;
6703 SSVAL(req->outbuf,smb_vwv0,seq_num);
6705 show_msg((char *)req->outbuf);
6706 if (!srv_send_smb(req->xconn,
6707 (char *)req->outbuf,
6708 true, req->seqnum+1,
6709 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6711 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6714 DEBUG(3,("echo %d times\n", smb_reverb));
6716 TALLOC_FREE(req->outbuf);
6718 END_PROFILE(SMBecho);
6722 /****************************************************************************
6723 Reply to a printopen.
6724 ****************************************************************************/
6726 void reply_printopen(struct smb_request *req)
6728 connection_struct *conn = req->conn;
6732 START_PROFILE(SMBsplopen);
6735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6736 END_PROFILE(SMBsplopen);
6740 if (!CAN_PRINT(conn)) {
6741 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6742 END_PROFILE(SMBsplopen);
6746 status = file_new(req, conn, &fsp);
6747 if(!NT_STATUS_IS_OK(status)) {
6748 reply_nterror(req, status);
6749 END_PROFILE(SMBsplopen);
6753 /* Open for exclusive use, write only. */
6754 status = print_spool_open(fsp, NULL, req->vuid);
6756 if (!NT_STATUS_IS_OK(status)) {
6757 file_free(req, fsp);
6758 reply_nterror(req, status);
6759 END_PROFILE(SMBsplopen);
6763 reply_outbuf(req, 1, 0);
6764 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6766 DEBUG(3,("openprint fd=%d %s\n",
6767 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
6769 END_PROFILE(SMBsplopen);
6773 /****************************************************************************
6774 Reply to a printclose.
6775 ****************************************************************************/
6777 void reply_printclose(struct smb_request *req)
6779 connection_struct *conn = req->conn;
6783 START_PROFILE(SMBsplclose);
6786 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6787 END_PROFILE(SMBsplclose);
6791 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6793 if (!check_fsp(conn, req, fsp)) {
6794 END_PROFILE(SMBsplclose);
6798 if (!CAN_PRINT(conn)) {
6799 reply_force_doserror(req, ERRSRV, ERRerror);
6800 END_PROFILE(SMBsplclose);
6804 DEBUG(3,("printclose fd=%d %s\n",
6805 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
6807 status = close_file(req, fsp, NORMAL_CLOSE);
6809 if(!NT_STATUS_IS_OK(status)) {
6810 reply_nterror(req, status);
6811 END_PROFILE(SMBsplclose);
6815 reply_outbuf(req, 0, 0);
6817 END_PROFILE(SMBsplclose);
6821 /****************************************************************************
6822 Reply to a printqueue.
6823 ****************************************************************************/
6825 void reply_printqueue(struct smb_request *req)
6827 const struct loadparm_substitution *lp_sub =
6828 loadparm_s3_global_substitution();
6829 connection_struct *conn = req->conn;
6833 START_PROFILE(SMBsplretq);
6836 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6837 END_PROFILE(SMBsplretq);
6841 max_count = SVAL(req->vwv+0, 0);
6842 start_index = SVAL(req->vwv+1, 0);
6844 /* we used to allow the client to get the cnum wrong, but that
6845 is really quite gross and only worked when there was only
6846 one printer - I think we should now only accept it if they
6847 get it right (tridge) */
6848 if (!CAN_PRINT(conn)) {
6849 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6850 END_PROFILE(SMBsplretq);
6854 reply_outbuf(req, 2, 3);
6855 SSVAL(req->outbuf,smb_vwv0,0);
6856 SSVAL(req->outbuf,smb_vwv1,0);
6857 SCVAL(smb_buf(req->outbuf),0,1);
6858 SSVAL(smb_buf(req->outbuf),1,0);
6860 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6861 start_index, max_count));
6864 TALLOC_CTX *mem_ctx = talloc_tos();
6867 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6868 struct rpc_pipe_client *cli = NULL;
6869 struct dcerpc_binding_handle *b = NULL;
6870 struct policy_handle handle;
6871 struct spoolss_DevmodeContainer devmode_ctr;
6872 union spoolss_JobInfo *info;
6874 uint32_t num_to_get;
6878 ZERO_STRUCT(handle);
6880 status = rpc_pipe_open_interface(mem_ctx,
6883 conn->sconn->remote_address,
6884 conn->sconn->local_address,
6885 conn->sconn->msg_ctx,
6887 if (!NT_STATUS_IS_OK(status)) {
6888 DEBUG(0, ("reply_printqueue: "
6889 "could not connect to spoolss: %s\n",
6890 nt_errstr(status)));
6891 reply_nterror(req, status);
6894 b = cli->binding_handle;
6896 ZERO_STRUCT(devmode_ctr);
6898 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6901 SEC_FLAG_MAXIMUM_ALLOWED,
6904 if (!NT_STATUS_IS_OK(status)) {
6905 reply_nterror(req, status);
6908 if (!W_ERROR_IS_OK(werr)) {
6909 reply_nterror(req, werror_to_ntstatus(werr));
6913 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6921 if (!W_ERROR_IS_OK(werr)) {
6922 reply_nterror(req, werror_to_ntstatus(werr));
6926 if (max_count > 0) {
6927 first = start_index;
6929 first = start_index + max_count + 1;
6932 if (first >= count) {
6935 num_to_get = first + MIN(ABS(max_count), count - first);
6938 for (i = first; i < num_to_get; i++) {
6941 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6944 uint16_t qrapjobid = pjobid_to_rap(sharename,
6945 info[i].info2.job_id);
6947 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6953 srv_put_dos_date2(p, 0, qtime);
6954 SCVAL(p, 4, qstatus);
6955 SSVAL(p, 5, qrapjobid);
6956 SIVAL(p, 7, info[i].info2.size);
6958 status = srvstr_push(blob, req->flags2, p+12,
6959 info[i].info2.notify_name, 16, STR_ASCII, &len);
6960 if (!NT_STATUS_IS_OK(status)) {
6961 reply_nterror(req, status);
6964 if (message_push_blob(
6967 blob, sizeof(blob))) == -1) {
6968 reply_nterror(req, NT_STATUS_NO_MEMORY);
6974 SSVAL(req->outbuf,smb_vwv0,count);
6975 SSVAL(req->outbuf,smb_vwv1,
6976 (max_count>0?first+count:first-1));
6977 SCVAL(smb_buf(req->outbuf),0,1);
6978 SSVAL(smb_buf(req->outbuf),1,28*count);
6982 DEBUG(3, ("%u entries returned in queue\n",
6986 if (b && is_valid_policy_hnd(&handle)) {
6987 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6992 END_PROFILE(SMBsplretq);
6996 /****************************************************************************
6997 Reply to a printwrite.
6998 ****************************************************************************/
7000 void reply_printwrite(struct smb_request *req)
7002 connection_struct *conn = req->conn;
7007 START_PROFILE(SMBsplwr);
7010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7011 END_PROFILE(SMBsplwr);
7015 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7017 if (!check_fsp(conn, req, fsp)) {
7018 END_PROFILE(SMBsplwr);
7022 if (!fsp->print_file) {
7023 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7024 END_PROFILE(SMBsplwr);
7028 if (!CHECK_WRITE(fsp)) {
7029 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7030 END_PROFILE(SMBsplwr);
7034 numtowrite = SVAL(req->buf, 1);
7037 * This already protects us against CVE-2017-12163.
7039 if (req->buflen < numtowrite + 3) {
7040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7041 END_PROFILE(SMBsplwr);
7045 data = (const char *)req->buf + 3;
7047 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7048 reply_nterror(req, map_nt_error_from_unix(errno));
7049 END_PROFILE(SMBsplwr);
7053 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7055 END_PROFILE(SMBsplwr);
7059 /****************************************************************************
7061 ****************************************************************************/
7063 void reply_mkdir(struct smb_request *req)
7065 connection_struct *conn = req->conn;
7066 struct smb_filename *smb_dname = NULL;
7067 char *directory = NULL;
7070 TALLOC_CTX *ctx = talloc_tos();
7072 START_PROFILE(SMBmkdir);
7074 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7075 STR_TERMINATE, &status);
7076 if (!NT_STATUS_IS_OK(status)) {
7077 reply_nterror(req, status);
7081 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7082 status = filename_convert(ctx, conn,
7087 if (!NT_STATUS_IS_OK(status)) {
7088 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7089 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7090 ERRSRV, ERRbadpath);
7093 reply_nterror(req, status);
7097 status = create_directory(conn, req, smb_dname);
7099 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7101 if (!NT_STATUS_IS_OK(status)) {
7103 if (!use_nt_status()
7104 && NT_STATUS_EQUAL(status,
7105 NT_STATUS_OBJECT_NAME_COLLISION)) {
7107 * Yes, in the DOS error code case we get a
7108 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7109 * samba4 torture test.
7111 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7114 reply_nterror(req, status);
7118 reply_outbuf(req, 0, 0);
7120 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7122 TALLOC_FREE(smb_dname);
7123 END_PROFILE(SMBmkdir);
7127 /****************************************************************************
7129 ****************************************************************************/
7131 void reply_rmdir(struct smb_request *req)
7133 connection_struct *conn = req->conn;
7134 struct smb_filename *smb_dname = NULL;
7135 char *directory = NULL;
7137 TALLOC_CTX *ctx = talloc_tos();
7138 files_struct *fsp = NULL;
7140 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7142 START_PROFILE(SMBrmdir);
7144 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7145 STR_TERMINATE, &status);
7146 if (!NT_STATUS_IS_OK(status)) {
7147 reply_nterror(req, status);
7151 status = filename_convert(ctx, conn,
7156 if (!NT_STATUS_IS_OK(status)) {
7157 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7158 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7159 ERRSRV, ERRbadpath);
7162 reply_nterror(req, status);
7166 if (is_ntfs_stream_smb_fname(smb_dname)) {
7167 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7171 status = SMB_VFS_CREATE_FILE(
7174 smb_dname, /* fname */
7175 DELETE_ACCESS, /* access_mask */
7176 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7178 FILE_OPEN, /* create_disposition*/
7179 FILE_DIRECTORY_FILE, /* create_options */
7180 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7181 0, /* oplock_request */
7183 0, /* allocation_size */
7184 0, /* private_flags */
7189 NULL, NULL); /* create context */
7191 if (!NT_STATUS_IS_OK(status)) {
7192 if (open_was_deferred(req->xconn, req->mid)) {
7193 /* We have re-scheduled this call. */
7196 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7197 bool ok = defer_smb1_sharing_violation(req);
7202 reply_nterror(req, status);
7206 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7207 if (!NT_STATUS_IS_OK(status)) {
7208 close_file(req, fsp, ERROR_CLOSE);
7209 reply_nterror(req, status);
7213 if (!set_delete_on_close(fsp, true,
7214 conn->session_info->security_token,
7215 conn->session_info->unix_token)) {
7216 close_file(req, fsp, ERROR_CLOSE);
7217 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7221 status = close_file(req, fsp, NORMAL_CLOSE);
7222 if (!NT_STATUS_IS_OK(status)) {
7223 reply_nterror(req, status);
7225 reply_outbuf(req, 0, 0);
7228 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7230 TALLOC_FREE(smb_dname);
7231 END_PROFILE(SMBrmdir);
7235 /*******************************************************************
7236 Resolve wildcards in a filename rename.
7237 ********************************************************************/
7239 static bool resolve_wildcards(TALLOC_CTX *ctx,
7244 char *name2_copy = NULL;
7249 char *p,*p2, *pname1, *pname2;
7251 name2_copy = talloc_strdup(ctx, name2);
7256 pname1 = strrchr_m(name1,'/');
7257 pname2 = strrchr_m(name2_copy,'/');
7259 if (!pname1 || !pname2) {
7263 /* Truncate the copy of name2 at the last '/' */
7266 /* Now go past the '/' */
7270 root1 = talloc_strdup(ctx, pname1);
7271 root2 = talloc_strdup(ctx, pname2);
7273 if (!root1 || !root2) {
7277 p = strrchr_m(root1,'.');
7280 ext1 = talloc_strdup(ctx, p+1);
7282 ext1 = talloc_strdup(ctx, "");
7284 p = strrchr_m(root2,'.');
7287 ext2 = talloc_strdup(ctx, p+1);
7289 ext2 = talloc_strdup(ctx, "");
7292 if (!ext1 || !ext2) {
7300 /* Hmmm. Should this be mb-aware ? */
7303 } else if (*p2 == '*') {
7305 root2 = talloc_asprintf(ctx, "%s%s",
7324 /* Hmmm. Should this be mb-aware ? */
7327 } else if (*p2 == '*') {
7329 ext2 = talloc_asprintf(ctx, "%s%s",
7345 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7350 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7362 /****************************************************************************
7363 Ensure open files have their names updated. Updated to notify other smbd's
7365 ****************************************************************************/
7367 static void rename_open_files(connection_struct *conn,
7368 struct share_mode_lock *lck,
7370 uint32_t orig_name_hash,
7371 const struct smb_filename *smb_fname_dst)
7374 bool did_rename = False;
7376 uint32_t new_name_hash = 0;
7378 for(fsp = file_find_di_first(conn->sconn, id, false); fsp;
7379 fsp = file_find_di_next(fsp, false)) {
7380 struct file_id_buf idbuf;
7381 /* fsp_name is a relative path under the fsp. To change this for other
7382 sharepaths we need to manipulate relative paths. */
7383 /* TODO - create the absolute path and manipulate the newname
7384 relative to the sharepath. */
7385 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7388 if (fsp->name_hash != orig_name_hash) {
7391 DBG_DEBUG("renaming file %s "
7392 "(file_id %s) from %s -> %s\n",
7394 file_id_str_buf(fsp->file_id, &idbuf),
7396 smb_fname_str_dbg(smb_fname_dst));
7398 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7399 if (NT_STATUS_IS_OK(status)) {
7401 new_name_hash = fsp->name_hash;
7406 struct file_id_buf idbuf;
7407 DBG_DEBUG("no open files on file_id %s "
7409 file_id_str_buf(id, &idbuf),
7410 smb_fname_str_dbg(smb_fname_dst));
7413 /* Send messages to all smbd's (not ourself) that the name has changed. */
7414 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7415 orig_name_hash, new_name_hash,
7420 /****************************************************************************
7421 We need to check if the source path is a parent directory of the destination
7422 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7423 refuse the rename with a sharing violation. Under UNIX the above call can
7424 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7425 probably need to check that the client is a Windows one before disallowing
7426 this as a UNIX client (one with UNIX extensions) can know the source is a
7427 symlink and make this decision intelligently. Found by an excellent bug
7428 report from <AndyLiebman@aol.com>.
7429 ****************************************************************************/
7431 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7432 const struct smb_filename *smb_fname_dst)
7434 const char *psrc = smb_fname_src->base_name;
7435 const char *pdst = smb_fname_dst->base_name;
7438 if (psrc[0] == '.' && psrc[1] == '/') {
7441 if (pdst[0] == '.' && pdst[1] == '/') {
7444 if ((slen = strlen(psrc)) > strlen(pdst)) {
7447 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7451 * Do the notify calls from a rename
7454 static void notify_rename(connection_struct *conn, bool is_dir,
7455 const struct smb_filename *smb_fname_src,
7456 const struct smb_filename *smb_fname_dst)
7458 char *parent_dir_src = NULL;
7459 char *parent_dir_dst = NULL;
7462 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7463 : FILE_NOTIFY_CHANGE_FILE_NAME;
7465 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7466 &parent_dir_src, NULL) ||
7467 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7468 &parent_dir_dst, NULL)) {
7472 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7473 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7474 smb_fname_src->base_name);
7475 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7476 smb_fname_dst->base_name);
7479 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7480 smb_fname_src->base_name);
7481 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7482 smb_fname_dst->base_name);
7485 /* this is a strange one. w2k3 gives an additional event for
7486 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7487 files, but not directories */
7489 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7490 FILE_NOTIFY_CHANGE_ATTRIBUTES
7491 |FILE_NOTIFY_CHANGE_CREATION,
7492 smb_fname_dst->base_name);
7495 TALLOC_FREE(parent_dir_src);
7496 TALLOC_FREE(parent_dir_dst);
7499 /****************************************************************************
7500 Returns an error if the parent directory for a filename is open in an
7502 ****************************************************************************/
7504 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7505 const struct smb_filename *smb_fname_dst_in)
7507 struct smb_filename *smb_fname_parent = NULL;
7509 files_struct *fsp = NULL;
7513 ok = parent_smb_fname(talloc_tos(),
7518 return NT_STATUS_NO_MEMORY;
7521 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7523 return map_nt_error_from_unix(errno);
7527 * We're only checking on this smbd here, mostly good
7528 * enough.. and will pass tests.
7531 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7532 for (fsp = file_find_di_first(conn->sconn, id, true); fsp;
7533 fsp = file_find_di_next(fsp, true)) {
7534 if (fsp->access_mask & DELETE_ACCESS) {
7535 return NT_STATUS_SHARING_VIOLATION;
7538 return NT_STATUS_OK;
7541 /****************************************************************************
7542 Rename an open file - given an fsp.
7543 ****************************************************************************/
7545 NTSTATUS rename_internals_fsp(connection_struct *conn,
7547 const struct smb_filename *smb_fname_dst_in,
7548 const char *dst_original_lcomp,
7550 bool replace_if_exists)
7552 TALLOC_CTX *ctx = talloc_tos();
7553 struct smb_filename *smb_fname_dst = NULL;
7554 NTSTATUS status = NT_STATUS_OK;
7555 struct share_mode_lock *lck = NULL;
7556 uint32_t access_mask = SEC_DIR_ADD_FILE;
7557 bool dst_exists, old_is_stream, new_is_stream;
7560 status = check_name(conn, smb_fname_dst_in);
7561 if (!NT_STATUS_IS_OK(status)) {
7565 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7566 if (!NT_STATUS_IS_OK(status)) {
7570 if (file_has_open_streams(fsp)) {
7571 return NT_STATUS_ACCESS_DENIED;
7574 /* Make a copy of the dst smb_fname structs */
7576 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7577 if (smb_fname_dst == NULL) {
7578 status = NT_STATUS_NO_MEMORY;
7583 * Check for special case with case preserving and not
7584 * case sensitive. If the new last component differs from the original
7585 * last component only by case, then we should allow
7586 * the rename (user is trying to change the case of the
7589 if (!conn->case_sensitive && conn->case_preserve &&
7590 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7591 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7592 char *fname_dst_parent = NULL;
7593 const char *fname_dst_lcomp = NULL;
7594 char *orig_lcomp_path = NULL;
7595 char *orig_lcomp_stream = NULL;
7599 * Split off the last component of the processed
7600 * destination name. We will compare this to
7601 * the split components of dst_original_lcomp.
7603 if (!parent_dirname(ctx,
7604 smb_fname_dst->base_name,
7606 &fname_dst_lcomp)) {
7607 status = NT_STATUS_NO_MEMORY;
7612 * The dst_original_lcomp component contains
7613 * the last_component of the path + stream
7614 * name (if a stream exists).
7616 * Split off the stream name so we
7617 * can check them separately.
7620 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7621 /* POSIX - no stream component. */
7622 orig_lcomp_path = talloc_strdup(ctx,
7623 dst_original_lcomp);
7624 if (orig_lcomp_path == NULL) {
7628 ok = split_stream_filename(ctx,
7631 &orig_lcomp_stream);
7635 TALLOC_FREE(fname_dst_parent);
7636 status = NT_STATUS_NO_MEMORY;
7640 /* If the base names only differ by case, use original. */
7641 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7644 * Replace the modified last component with the
7647 if (!ISDOT(fname_dst_parent)) {
7648 tmp = talloc_asprintf(smb_fname_dst,
7653 tmp = talloc_strdup(smb_fname_dst,
7657 status = NT_STATUS_NO_MEMORY;
7658 TALLOC_FREE(fname_dst_parent);
7659 TALLOC_FREE(orig_lcomp_path);
7660 TALLOC_FREE(orig_lcomp_stream);
7663 TALLOC_FREE(smb_fname_dst->base_name);
7664 smb_fname_dst->base_name = tmp;
7667 /* If the stream_names only differ by case, use original. */
7668 if(!strcsequal(smb_fname_dst->stream_name,
7669 orig_lcomp_stream)) {
7670 /* Use the original stream. */
7671 char *tmp = talloc_strdup(smb_fname_dst,
7674 status = NT_STATUS_NO_MEMORY;
7675 TALLOC_FREE(fname_dst_parent);
7676 TALLOC_FREE(orig_lcomp_path);
7677 TALLOC_FREE(orig_lcomp_stream);
7680 TALLOC_FREE(smb_fname_dst->stream_name);
7681 smb_fname_dst->stream_name = tmp;
7683 TALLOC_FREE(fname_dst_parent);
7684 TALLOC_FREE(orig_lcomp_path);
7685 TALLOC_FREE(orig_lcomp_stream);
7689 * If the src and dest names are identical - including case,
7690 * don't do the rename, just return success.
7693 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7694 strcsequal(fsp->fsp_name->stream_name,
7695 smb_fname_dst->stream_name)) {
7696 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7697 "- returning success\n",
7698 smb_fname_str_dbg(smb_fname_dst)));
7699 status = NT_STATUS_OK;
7703 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7704 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7706 /* Return the correct error code if both names aren't streams. */
7707 if (!old_is_stream && new_is_stream) {
7708 status = NT_STATUS_OBJECT_NAME_INVALID;
7712 if (old_is_stream && !new_is_stream) {
7713 status = NT_STATUS_INVALID_PARAMETER;
7717 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7719 if(!replace_if_exists && dst_exists) {
7720 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7721 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7722 smb_fname_str_dbg(smb_fname_dst)));
7723 status = NT_STATUS_OBJECT_NAME_COLLISION;
7728 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7729 &smb_fname_dst->st);
7730 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7732 /* The file can be open when renaming a stream */
7733 if (dst_fsp && !new_is_stream) {
7734 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7735 status = NT_STATUS_ACCESS_DENIED;
7740 /* Ensure we have a valid stat struct for the source. */
7741 status = vfs_stat_fsp(fsp);
7742 if (!NT_STATUS_IS_OK(status)) {
7746 status = can_rename(conn, fsp, attrs);
7748 if (!NT_STATUS_IS_OK(status)) {
7749 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7750 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7751 smb_fname_str_dbg(smb_fname_dst)));
7752 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7753 status = NT_STATUS_ACCESS_DENIED;
7757 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7758 status = NT_STATUS_ACCESS_DENIED;
7762 /* Do we have rights to move into the destination ? */
7763 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7764 /* We're moving a directory. */
7765 access_mask = SEC_DIR_ADD_SUBDIR;
7767 status = check_parent_access(conn,
7771 if (!NT_STATUS_IS_OK(status)) {
7772 DBG_INFO("check_parent_access on "
7773 "dst %s returned %s\n",
7774 smb_fname_str_dbg(smb_fname_dst),
7779 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7782 * We have the file open ourselves, so not being able to get the
7783 * corresponding share mode lock is a fatal error.
7786 SMB_ASSERT(lck != NULL);
7788 ret = SMB_VFS_RENAMEAT(conn,
7794 uint32_t create_options = fh_get_private_options(fsp->fh);
7796 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7797 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7798 smb_fname_str_dbg(smb_fname_dst)));
7800 if (!fsp->fsp_flags.is_directory &&
7801 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7802 (lp_map_archive(SNUM(conn)) ||
7803 lp_store_dos_attributes(SNUM(conn)))) {
7804 /* We must set the archive bit on the newly
7806 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7807 uint32_t old_dosmode = dos_mode(conn,
7809 file_set_dosmode(conn,
7811 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7818 fsp->fsp_flags.is_directory,
7822 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7826 * A rename acts as a new file create w.r.t. allowing an initial delete
7827 * on close, probably because in Windows there is a new handle to the
7828 * new file. If initial delete on close was requested but not
7829 * originally set, we need to set it here. This is probably not 100% correct,
7830 * but will work for the CIFSFS client which in non-posix mode
7831 * depends on these semantics. JRA.
7834 if (create_options & FILE_DELETE_ON_CLOSE) {
7835 status = can_set_delete_on_close(fsp, 0);
7837 if (NT_STATUS_IS_OK(status)) {
7838 /* Note that here we set the *initial* delete on close flag,
7839 * not the regular one. The magic gets handled in close. */
7840 fsp->fsp_flags.initial_delete_on_close = true;
7844 status = NT_STATUS_OK;
7850 if (errno == ENOTDIR || errno == EISDIR) {
7851 status = NT_STATUS_OBJECT_NAME_COLLISION;
7853 status = map_nt_error_from_unix(errno);
7856 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7857 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7858 smb_fname_str_dbg(smb_fname_dst)));
7861 TALLOC_FREE(smb_fname_dst);
7866 /****************************************************************************
7867 The guts of the rename command, split out so it may be called by the NT SMB
7869 ****************************************************************************/
7871 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7872 connection_struct *conn,
7873 struct smb_request *req,
7874 struct smb_filename *smb_fname_src,
7875 const char *src_original_lcomp,
7876 struct smb_filename *smb_fname_dst,
7877 const char *dst_original_lcomp,
7879 bool replace_if_exists,
7880 uint32_t access_mask)
7882 char *fname_src_dir = NULL;
7883 struct smb_filename *smb_fname_src_dir = NULL;
7884 char *fname_src_mask = NULL;
7886 NTSTATUS status = NT_STATUS_OK;
7887 struct smb_Dir *dir_hnd = NULL;
7888 const char *dname = NULL;
7889 char *talloced = NULL;
7891 int create_options = 0;
7892 struct smb2_create_blobs *posx = NULL;
7894 bool src_has_wild = false;
7895 bool dest_has_wild = false;
7898 * Split the old name into directory and last component
7899 * strings. Note that unix_convert may have stripped off a
7900 * leading ./ from both name and newname if the rename is
7901 * at the root of the share. We need to make sure either both
7902 * name and newname contain a / character or neither of them do
7903 * as this is checked in resolve_wildcards().
7906 /* Split up the directory from the filename/mask. */
7907 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7908 &fname_src_dir, &fname_src_mask);
7909 if (!NT_STATUS_IS_OK(status)) {
7910 status = NT_STATUS_NO_MEMORY;
7914 if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
7916 * Check the wildcard mask *before*
7917 * unmangling. As mangling is done
7918 * for names that can't be returned
7919 * to Windows the unmangled name may
7920 * contain Windows wildcard characters.
7922 if (src_original_lcomp != NULL) {
7923 src_has_wild = ms_has_wild(src_original_lcomp);
7925 dest_has_wild = ms_has_wild(dst_original_lcomp);
7929 * We should only check the mangled cache
7930 * here if unix_convert failed. This means
7931 * that the path in 'mask' doesn't exist
7932 * on the file system and so we need to look
7933 * for a possible mangle. This patch from
7934 * Tine Smukavec <valentin.smukavec@hermes.si>.
7937 if (!VALID_STAT(smb_fname_src->st) &&
7938 mangle_is_mangled(fname_src_mask, conn->params)) {
7939 char *new_mask = NULL;
7940 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7943 TALLOC_FREE(fname_src_mask);
7944 fname_src_mask = new_mask;
7948 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7949 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7950 if (!NT_STATUS_IS_OK(status)) {
7951 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7957 if (!src_has_wild) {
7961 * Only one file needs to be renamed. Append the mask back
7962 * onto the directory.
7964 TALLOC_FREE(smb_fname_src->base_name);
7965 if (ISDOT(fname_src_dir)) {
7966 /* Ensure we use canonical names on open. */
7967 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7971 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7976 if (!smb_fname_src->base_name) {
7977 status = NT_STATUS_NO_MEMORY;
7981 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7982 "case_preserve = %d, short case preserve = %d, "
7983 "directory = %s, newname = %s, "
7984 "last_component_dest = %s\n",
7985 conn->case_sensitive, conn->case_preserve,
7986 conn->short_case_preserve,
7987 smb_fname_str_dbg(smb_fname_src),
7988 smb_fname_str_dbg(smb_fname_dst),
7989 dst_original_lcomp));
7991 /* The dest name still may have wildcards. */
7992 if (dest_has_wild) {
7993 char *fname_dst_mod = NULL;
7994 if (!resolve_wildcards(smb_fname_dst,
7995 smb_fname_src->base_name,
7996 smb_fname_dst->base_name,
7998 DEBUG(6, ("rename_internals: resolve_wildcards "
8000 smb_fname_src->base_name,
8001 smb_fname_dst->base_name));
8002 status = NT_STATUS_NO_MEMORY;
8005 TALLOC_FREE(smb_fname_dst->base_name);
8006 smb_fname_dst->base_name = fname_dst_mod;
8009 ZERO_STRUCT(smb_fname_src->st);
8011 rc = vfs_stat(conn, smb_fname_src);
8013 status = map_nt_error_from_unix_common(errno);
8017 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
8018 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
8019 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8021 if (!NT_STATUS_IS_OK(status)) {
8025 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8026 create_options |= FILE_DIRECTORY_FILE;
8029 status = SMB_VFS_CREATE_FILE(
8032 smb_fname_src, /* fname */
8033 access_mask, /* access_mask */
8034 (FILE_SHARE_READ | /* share_access */
8036 FILE_OPEN, /* create_disposition*/
8037 create_options, /* create_options */
8038 0, /* file_attributes */
8039 0, /* oplock_request */
8041 0, /* allocation_size */
8042 0, /* private_flags */
8047 posx, /* in_context_blobs */
8048 NULL); /* out_context_blobs */
8050 if (!NT_STATUS_IS_OK(status)) {
8051 DEBUG(3, ("Could not open rename source %s: %s\n",
8052 smb_fname_str_dbg(smb_fname_src),
8053 nt_errstr(status)));
8057 status = rename_internals_fsp(conn,
8064 close_file(req, fsp, NORMAL_CLOSE);
8066 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8067 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8068 smb_fname_str_dbg(smb_fname_dst)));
8074 * Wildcards - process each file that matches.
8076 if (strequal(fname_src_mask, "????????.???")) {
8077 TALLOC_FREE(fname_src_mask);
8078 fname_src_mask = talloc_strdup(ctx, "*");
8079 if (!fname_src_mask) {
8080 status = NT_STATUS_NO_MEMORY;
8085 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8089 smb_fname_src->twrp,
8090 smb_fname_src->flags);
8091 if (smb_fname_src_dir == NULL) {
8092 status = NT_STATUS_NO_MEMORY;
8096 status = check_name(conn, smb_fname_src_dir);
8097 if (!NT_STATUS_IS_OK(status)) {
8101 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8103 if (dir_hnd == NULL) {
8104 status = map_nt_error_from_unix(errno);
8108 status = NT_STATUS_NO_SUCH_FILE;
8110 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8111 * - gentest fix. JRA
8114 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8116 files_struct *fsp = NULL;
8117 char *destname = NULL;
8118 bool sysdir_entry = False;
8120 /* Quick check for "." and ".." */
8121 if (ISDOT(dname) || ISDOTDOT(dname)) {
8122 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8123 sysdir_entry = True;
8125 TALLOC_FREE(talloced);
8130 if (!is_visible_file(conn,
8135 TALLOC_FREE(talloced);
8139 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8140 TALLOC_FREE(talloced);
8145 status = NT_STATUS_OBJECT_NAME_INVALID;
8149 TALLOC_FREE(smb_fname_src->base_name);
8150 if (ISDOT(fname_src_dir)) {
8151 /* Ensure we use canonical names on open. */
8152 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8156 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8161 if (!smb_fname_src->base_name) {
8162 status = NT_STATUS_NO_MEMORY;
8166 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8167 smb_fname_dst->base_name,
8169 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8170 smb_fname_src->base_name, destname));
8171 TALLOC_FREE(talloced);
8175 status = NT_STATUS_NO_MEMORY;
8179 TALLOC_FREE(smb_fname_dst->base_name);
8180 smb_fname_dst->base_name = destname;
8182 ZERO_STRUCT(smb_fname_src->st);
8183 vfs_stat(conn, smb_fname_src);
8185 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
8186 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
8187 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8189 if (!NT_STATUS_IS_OK(status)) {
8190 DBG_INFO("openat_pathref_fsp [%s] failed: %s\n",
8191 smb_fname_str_dbg(smb_fname_src),
8198 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8199 create_options |= FILE_DIRECTORY_FILE;
8202 status = SMB_VFS_CREATE_FILE(
8205 smb_fname_src, /* fname */
8206 access_mask, /* access_mask */
8207 (FILE_SHARE_READ | /* share_access */
8209 FILE_OPEN, /* create_disposition*/
8210 create_options, /* create_options */
8211 0, /* file_attributes */
8212 0, /* oplock_request */
8214 0, /* allocation_size */
8215 0, /* private_flags */
8220 posx, /* in_context_blobs */
8221 NULL); /* out_context_blobs */
8223 if (!NT_STATUS_IS_OK(status)) {
8224 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8225 "returned %s rename %s -> %s\n",
8227 smb_fname_str_dbg(smb_fname_src),
8228 smb_fname_str_dbg(smb_fname_dst)));
8232 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8233 if (dst_original_lcomp == NULL) {
8234 status = NT_STATUS_NO_MEMORY;
8238 status = rename_internals_fsp(conn,
8245 close_file(req, fsp, NORMAL_CLOSE);
8247 if (!NT_STATUS_IS_OK(status)) {
8248 DEBUG(3, ("rename_internals_fsp returned %s for "
8249 "rename %s -> %s\n", nt_errstr(status),
8250 smb_fname_str_dbg(smb_fname_src),
8251 smb_fname_str_dbg(smb_fname_dst)));
8257 DEBUG(3,("rename_internals: doing rename on %s -> "
8258 "%s\n", smb_fname_str_dbg(smb_fname_src),
8259 smb_fname_str_dbg(smb_fname_src)));
8260 TALLOC_FREE(talloced);
8262 TALLOC_FREE(dir_hnd);
8264 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8265 status = map_nt_error_from_unix(errno);
8270 TALLOC_FREE(talloced);
8271 TALLOC_FREE(smb_fname_src_dir);
8272 TALLOC_FREE(fname_src_dir);
8273 TALLOC_FREE(fname_src_mask);
8277 /****************************************************************************
8279 ****************************************************************************/
8281 void reply_mv(struct smb_request *req)
8283 connection_struct *conn = req->conn;
8285 char *newname = NULL;
8289 TALLOC_CTX *ctx = talloc_tos();
8290 struct smb_filename *smb_fname_src = NULL;
8291 const char *src_original_lcomp = NULL;
8292 struct smb_filename *smb_fname_dst = NULL;
8293 const char *dst_original_lcomp = NULL;
8294 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8295 (!req->posix_pathnames ? UCF_ALWAYS_ALLOW_WCARD_LCOMP : 0);
8296 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8297 (!req->posix_pathnames ? UCF_ALWAYS_ALLOW_WCARD_LCOMP : 0);
8298 bool stream_rename = false;
8300 START_PROFILE(SMBmv);
8303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8307 attrs = SVAL(req->vwv+0, 0);
8309 p = (const char *)req->buf + 1;
8310 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
8312 if (!NT_STATUS_IS_OK(status)) {
8313 reply_nterror(req, status);
8317 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
8319 if (!NT_STATUS_IS_OK(status)) {
8320 reply_nterror(req, status);
8324 if (!req->posix_pathnames) {
8325 /* The newname must begin with a ':' if the
8326 name contains a ':'. */
8327 if (strchr_m(name, ':')) {
8328 if (newname[0] != ':') {
8329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8332 stream_rename = true;
8336 status = filename_convert(ctx,
8343 if (!NT_STATUS_IS_OK(status)) {
8344 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8345 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8346 ERRSRV, ERRbadpath);
8349 reply_nterror(req, status);
8353 /* Get the last component of the source for rename_internals(). */
8354 src_original_lcomp = get_original_lcomp(ctx,
8358 if (src_original_lcomp == NULL) {
8359 reply_nterror(req, NT_STATUS_NO_MEMORY);
8363 status = filename_convert(ctx,
8370 if (!NT_STATUS_IS_OK(status)) {
8371 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8372 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8373 ERRSRV, ERRbadpath);
8376 reply_nterror(req, status);
8380 /* Get the last component of the destination for rename_internals(). */
8381 dst_original_lcomp = get_original_lcomp(ctx,
8385 if (dst_original_lcomp == NULL) {
8386 reply_nterror(req, NT_STATUS_NO_MEMORY);
8390 if (stream_rename) {
8391 /* smb_fname_dst->base_name must be the same as
8392 smb_fname_src->base_name. */
8393 TALLOC_FREE(smb_fname_dst->base_name);
8394 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8395 smb_fname_src->base_name);
8396 if (!smb_fname_dst->base_name) {
8397 reply_nterror(req, NT_STATUS_NO_MEMORY);
8402 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8403 smb_fname_str_dbg(smb_fname_dst)));
8405 status = rename_internals(ctx,
8415 if (!NT_STATUS_IS_OK(status)) {
8416 if (open_was_deferred(req->xconn, req->mid)) {
8417 /* We have re-scheduled this call. */
8420 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8421 bool ok = defer_smb1_sharing_violation(req);
8426 reply_nterror(req, status);
8430 reply_outbuf(req, 0, 0);
8432 TALLOC_FREE(smb_fname_src);
8433 TALLOC_FREE(smb_fname_dst);
8438 /*******************************************************************
8439 Copy a file as part of a reply_copy.
8440 ******************************************************************/
8443 * TODO: check error codes on all callers
8446 NTSTATUS copy_file(TALLOC_CTX *ctx,
8447 connection_struct *conn,
8448 struct smb_filename *smb_fname_src,
8449 struct smb_filename *smb_fname_dst,
8452 bool target_is_directory)
8454 struct smb_filename *smb_fname_dst_tmp = NULL;
8456 files_struct *fsp1,*fsp2;
8458 uint32_t new_create_disposition;
8462 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8463 if (smb_fname_dst_tmp == NULL) {
8464 return NT_STATUS_NO_MEMORY;
8468 * If the target is a directory, extract the last component from the
8469 * src filename and append it to the dst filename
8471 if (target_is_directory) {
8474 /* dest/target can't be a stream if it's a directory. */
8475 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8477 p = strrchr_m(smb_fname_src->base_name,'/');
8481 p = smb_fname_src->base_name;
8483 smb_fname_dst_tmp->base_name =
8484 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8486 if (!smb_fname_dst_tmp->base_name) {
8487 status = NT_STATUS_NO_MEMORY;
8492 status = vfs_file_exist(conn, smb_fname_src);
8493 if (!NT_STATUS_IS_OK(status)) {
8497 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
8498 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
8499 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8501 if (!NT_STATUS_IS_OK(status)) {
8505 if (!target_is_directory && count) {
8506 new_create_disposition = FILE_OPEN;
8508 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8511 &new_create_disposition,
8514 status = NT_STATUS_INVALID_PARAMETER;
8519 /* Open the src file for reading. */
8520 status = SMB_VFS_CREATE_FILE(
8523 smb_fname_src, /* fname */
8524 FILE_GENERIC_READ, /* access_mask */
8525 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8526 FILE_OPEN, /* create_disposition*/
8527 0, /* create_options */
8528 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8529 INTERNAL_OPEN_ONLY, /* oplock_request */
8531 0, /* allocation_size */
8532 0, /* private_flags */
8537 NULL, NULL); /* create context */
8539 if (!NT_STATUS_IS_OK(status)) {
8543 dosattrs = dos_mode(conn, smb_fname_src);
8545 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8546 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8549 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_dst);
8550 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
8551 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8554 if (!NT_STATUS_IS_OK(status) &&
8555 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
8560 /* Open the dst file for writing. */
8561 status = SMB_VFS_CREATE_FILE(
8564 smb_fname_dst, /* fname */
8565 FILE_GENERIC_WRITE, /* access_mask */
8566 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8567 new_create_disposition, /* create_disposition*/
8568 0, /* create_options */
8569 dosattrs, /* file_attributes */
8570 INTERNAL_OPEN_ONLY, /* oplock_request */
8572 0, /* allocation_size */
8573 0, /* private_flags */
8578 NULL, NULL); /* create context */
8580 if (!NT_STATUS_IS_OK(status)) {
8581 close_file(NULL, fsp1, ERROR_CLOSE);
8585 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8586 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8588 DEBUG(0, ("error - vfs lseek returned error %s\n",
8590 status = map_nt_error_from_unix(errno);
8591 close_file(NULL, fsp1, ERROR_CLOSE);
8592 close_file(NULL, fsp2, ERROR_CLOSE);
8597 /* Do the actual copy. */
8598 if (smb_fname_src->st.st_ex_size) {
8599 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8604 close_file(NULL, fsp1, NORMAL_CLOSE);
8606 /* Ensure the modtime is set correctly on the destination file. */
8607 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8610 * As we are opening fsp1 read-only we only expect
8611 * an error on close on fsp2 if we are out of space.
8612 * Thus we don't look at the error return from the
8615 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8617 if (!NT_STATUS_IS_OK(status)) {
8621 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8622 status = NT_STATUS_DISK_FULL;
8626 status = NT_STATUS_OK;
8629 TALLOC_FREE(smb_fname_dst_tmp);
8633 /****************************************************************************
8634 Reply to a file copy.
8635 ****************************************************************************/
8637 void reply_copy(struct smb_request *req)
8639 connection_struct *conn = req->conn;
8640 struct smb_filename *smb_fname_src = NULL;
8641 struct smb_filename *smb_fname_src_dir = NULL;
8642 struct smb_filename *smb_fname_dst = NULL;
8643 char *fname_src = NULL;
8644 char *fname_dst = NULL;
8645 char *fname_src_mask = NULL;
8646 char *fname_src_dir = NULL;
8649 int error = ERRnoaccess;
8653 bool target_is_directory=False;
8654 bool source_has_wild = False;
8655 bool dest_has_wild = False;
8657 uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8658 ucf_flags_from_smb_request(req);
8659 uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8660 ucf_flags_from_smb_request(req);
8661 TALLOC_CTX *ctx = talloc_tos();
8663 START_PROFILE(SMBcopy);
8666 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8670 tid2 = SVAL(req->vwv+0, 0);
8671 ofun = SVAL(req->vwv+1, 0);
8672 flags = SVAL(req->vwv+2, 0);
8674 p = (const char *)req->buf;
8675 p += srvstr_get_path_req(ctx, req, &fname_src, p, STR_TERMINATE,
8677 if (!NT_STATUS_IS_OK(status)) {
8678 reply_nterror(req, status);
8681 p += srvstr_get_path_req(ctx, req, &fname_dst, p, STR_TERMINATE,
8683 if (!NT_STATUS_IS_OK(status)) {
8684 reply_nterror(req, status);
8688 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8690 if (tid2 != conn->cnum) {
8691 /* can't currently handle inter share copies XXXX */
8692 DEBUG(3,("Rejecting inter-share copy\n"));
8693 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8697 status = filename_convert(ctx, conn,
8702 if (!NT_STATUS_IS_OK(status)) {
8703 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8704 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8705 ERRSRV, ERRbadpath);
8708 reply_nterror(req, status);
8712 status = filename_convert(ctx, conn,
8717 if (!NT_STATUS_IS_OK(status)) {
8718 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8719 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8720 ERRSRV, ERRbadpath);
8723 reply_nterror(req, status);
8727 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8729 if ((flags&1) && target_is_directory) {
8730 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8734 if ((flags&2) && !target_is_directory) {
8735 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8739 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8740 /* wants a tree copy! XXXX */
8741 DEBUG(3,("Rejecting tree copy\n"));
8742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8746 /* Split up the directory from the filename/mask. */
8747 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8748 &fname_src_dir, &fname_src_mask);
8749 if (!NT_STATUS_IS_OK(status)) {
8750 reply_nterror(req, NT_STATUS_NO_MEMORY);
8754 if (!req->posix_pathnames) {
8755 char *orig_src_lcomp = NULL;
8756 char *orig_dst_lcomp = NULL;
8758 * Check the wildcard mask *before*
8759 * unmangling. As mangling is done
8760 * for names that can't be returned
8761 * to Windows the unmangled name may
8762 * contain Windows wildcard characters.
8764 orig_src_lcomp = get_original_lcomp(ctx,
8768 if (orig_src_lcomp == NULL) {
8769 reply_nterror(req, NT_STATUS_NO_MEMORY);
8772 orig_dst_lcomp = get_original_lcomp(ctx,
8776 if (orig_dst_lcomp == NULL) {
8777 reply_nterror(req, NT_STATUS_NO_MEMORY);
8780 source_has_wild = ms_has_wild(orig_src_lcomp);
8781 dest_has_wild = ms_has_wild(orig_dst_lcomp);
8782 TALLOC_FREE(orig_src_lcomp);
8783 TALLOC_FREE(orig_dst_lcomp);
8787 * We should only check the mangled cache
8788 * here if unix_convert failed. This means
8789 * that the path in 'mask' doesn't exist
8790 * on the file system and so we need to look
8791 * for a possible mangle. This patch from
8792 * Tine Smukavec <valentin.smukavec@hermes.si>.
8794 if (!VALID_STAT(smb_fname_src->st) &&
8795 mangle_is_mangled(fname_src_mask, conn->params)) {
8796 char *new_mask = NULL;
8797 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8798 &new_mask, conn->params);
8800 /* Use demangled name if one was successfully found. */
8802 TALLOC_FREE(fname_src_mask);
8803 fname_src_mask = new_mask;
8807 if (!source_has_wild) {
8810 * Only one file needs to be copied. Append the mask back onto
8813 TALLOC_FREE(smb_fname_src->base_name);
8814 if (ISDOT(fname_src_dir)) {
8815 /* Ensure we use canonical names on open. */
8816 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8820 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8825 if (!smb_fname_src->base_name) {
8826 reply_nterror(req, NT_STATUS_NO_MEMORY);
8830 if (dest_has_wild) {
8831 char *fname_dst_mod = NULL;
8832 if (!resolve_wildcards(smb_fname_dst,
8833 smb_fname_src->base_name,
8834 smb_fname_dst->base_name,
8836 reply_nterror(req, NT_STATUS_NO_MEMORY);
8839 TALLOC_FREE(smb_fname_dst->base_name);
8840 smb_fname_dst->base_name = fname_dst_mod;
8843 status = check_name(conn, smb_fname_src);
8844 if (!NT_STATUS_IS_OK(status)) {
8845 reply_nterror(req, status);
8849 status = check_name(conn, smb_fname_dst);
8850 if (!NT_STATUS_IS_OK(status)) {
8851 reply_nterror(req, status);
8855 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8856 ofun, count, target_is_directory);
8858 if(!NT_STATUS_IS_OK(status)) {
8859 reply_nterror(req, status);
8865 struct smb_Dir *dir_hnd = NULL;
8866 const char *dname = NULL;
8867 char *talloced = NULL;
8871 * There is a wildcard that requires us to actually read the
8872 * src dir and copy each file matching the mask to the dst.
8873 * Right now streams won't be copied, but this could
8874 * presumably be added with a nested loop for reach dir entry.
8876 SMB_ASSERT(!smb_fname_src->stream_name);
8877 SMB_ASSERT(!smb_fname_dst->stream_name);
8879 smb_fname_src->stream_name = NULL;
8880 smb_fname_dst->stream_name = NULL;
8882 if (strequal(fname_src_mask,"????????.???")) {
8883 TALLOC_FREE(fname_src_mask);
8884 fname_src_mask = talloc_strdup(ctx, "*");
8885 if (!fname_src_mask) {
8886 reply_nterror(req, NT_STATUS_NO_MEMORY);
8891 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8895 smb_fname_src->twrp,
8896 smb_fname_src->flags);
8897 if (smb_fname_src_dir == NULL) {
8898 reply_nterror(req, NT_STATUS_NO_MEMORY);
8902 status = check_name(conn, smb_fname_src_dir);
8903 if (!NT_STATUS_IS_OK(status)) {
8904 reply_nterror(req, status);
8908 dir_hnd = OpenDir(ctx,
8913 if (dir_hnd == NULL) {
8914 status = map_nt_error_from_unix(errno);
8915 reply_nterror(req, status);
8921 /* Iterate over the src dir copying each entry to the dst. */
8922 while ((dname = ReadDirName(dir_hnd, &offset,
8923 &smb_fname_src->st, &talloced))) {
8924 char *destname = NULL;
8926 if (ISDOT(dname) || ISDOTDOT(dname)) {
8927 TALLOC_FREE(talloced);
8931 if (!is_visible_file(conn,
8936 TALLOC_FREE(talloced);
8940 if(!mask_match(dname, fname_src_mask,
8941 conn->case_sensitive)) {
8942 TALLOC_FREE(talloced);
8946 error = ERRnoaccess;
8948 /* Get the src smb_fname struct setup. */
8949 TALLOC_FREE(smb_fname_src->base_name);
8950 if (ISDOT(fname_src_dir)) {
8951 /* Ensure we use canonical names on open. */
8952 smb_fname_src->base_name =
8953 talloc_asprintf(smb_fname_src, "%s",
8956 smb_fname_src->base_name =
8957 talloc_asprintf(smb_fname_src, "%s/%s",
8958 fname_src_dir, dname);
8961 if (!smb_fname_src->base_name) {
8962 TALLOC_FREE(dir_hnd);
8963 TALLOC_FREE(talloced);
8964 reply_nterror(req, NT_STATUS_NO_MEMORY);
8968 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8969 smb_fname_dst->base_name,
8971 TALLOC_FREE(talloced);
8975 TALLOC_FREE(dir_hnd);
8976 TALLOC_FREE(talloced);
8977 reply_nterror(req, NT_STATUS_NO_MEMORY);
8981 TALLOC_FREE(smb_fname_dst->base_name);
8982 smb_fname_dst->base_name = destname;
8984 status = check_name(conn, smb_fname_src);
8985 if (!NT_STATUS_IS_OK(status)) {
8986 TALLOC_FREE(dir_hnd);
8987 TALLOC_FREE(talloced);
8988 reply_nterror(req, status);
8992 status = check_name(conn, smb_fname_dst);
8993 if (!NT_STATUS_IS_OK(status)) {
8994 TALLOC_FREE(dir_hnd);
8995 TALLOC_FREE(talloced);
8996 reply_nterror(req, status);
9000 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
9001 smb_fname_src->base_name,
9002 smb_fname_dst->base_name));
9004 status = copy_file(ctx, conn, smb_fname_src,
9005 smb_fname_dst, ofun, count,
9006 target_is_directory);
9007 if (NT_STATUS_IS_OK(status)) {
9011 TALLOC_FREE(talloced);
9013 TALLOC_FREE(dir_hnd);
9017 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
9021 reply_outbuf(req, 1, 0);
9022 SSVAL(req->outbuf,smb_vwv0,count);
9024 TALLOC_FREE(smb_fname_src);
9025 TALLOC_FREE(smb_fname_src_dir);
9026 TALLOC_FREE(smb_fname_dst);
9027 TALLOC_FREE(fname_src);
9028 TALLOC_FREE(fname_dst);
9029 TALLOC_FREE(fname_src_mask);
9030 TALLOC_FREE(fname_src_dir);
9032 END_PROFILE(SMBcopy);
9037 #define DBGC_CLASS DBGC_LOCKING
9039 /****************************************************************************
9040 Get a lock pid, dealing with large count requests.
9041 ****************************************************************************/
9043 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
9044 bool large_file_format)
9046 if(!large_file_format)
9047 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9049 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9052 /****************************************************************************
9053 Get a lock count, dealing with large count requests.
9054 ****************************************************************************/
9056 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9057 bool large_file_format)
9061 if(!large_file_format) {
9062 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9065 * No BVAL, this is reversed!
9067 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9068 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9074 /****************************************************************************
9075 Get a lock offset, dealing with large offset requests.
9076 ****************************************************************************/
9078 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9079 bool large_file_format)
9081 uint64_t offset = 0;
9083 if(!large_file_format) {
9084 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9087 * No BVAL, this is reversed!
9089 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9090 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9096 struct smbd_do_unlocking_state {
9097 struct files_struct *fsp;
9098 uint16_t num_ulocks;
9099 struct smbd_lock_element *ulocks;
9100 enum brl_flavour lock_flav;
9104 static void smbd_do_unlocking_fn(
9107 bool *pmodified_dependent,
9110 struct smbd_do_unlocking_state *state = private_data;
9111 struct files_struct *fsp = state->fsp;
9112 enum brl_flavour lock_flav = state->lock_flav;
9115 for (i = 0; i < state->num_ulocks; i++) {
9116 struct smbd_lock_element *e = &state->ulocks[i];
9118 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9119 "pid %"PRIu64", file %s\n",
9125 if (e->brltype != UNLOCK_LOCK) {
9126 /* this can only happen with SMB2 */
9127 state->status = NT_STATUS_INVALID_PARAMETER;
9131 state->status = do_unlock(
9132 fsp, e->smblctx, e->count, e->offset, lock_flav);
9134 DBG_DEBUG("do_unlock returned %s\n",
9135 nt_errstr(state->status));
9137 if (!NT_STATUS_IS_OK(state->status)) {
9142 *pmodified_dependent = true;
9145 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9147 uint16_t num_ulocks,
9148 struct smbd_lock_element *ulocks,
9149 enum brl_flavour lock_flav)
9151 struct smbd_do_unlocking_state state = {
9153 .num_ulocks = num_ulocks,
9155 .lock_flav = lock_flav,
9159 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9161 status = share_mode_do_locked(
9162 fsp->file_id, smbd_do_unlocking_fn, &state);
9164 if (!NT_STATUS_IS_OK(status)) {
9165 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9169 if (!NT_STATUS_IS_OK(state.status)) {
9170 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9172 return state.status;
9175 return NT_STATUS_OK;
9178 /****************************************************************************
9179 Reply to a lockingX request.
9180 ****************************************************************************/
9182 static void reply_lockingx_done(struct tevent_req *subreq);
9184 void reply_lockingX(struct smb_request *req)
9186 connection_struct *conn = req->conn;
9188 unsigned char locktype;
9189 enum brl_type brltype;
9190 unsigned char oplocklevel;
9191 uint16_t num_ulocks;
9193 int32_t lock_timeout;
9195 const uint8_t *data;
9196 bool large_file_format;
9197 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9198 struct smbd_lock_element *locks = NULL;
9199 struct tevent_req *subreq = NULL;
9201 START_PROFILE(SMBlockingX);
9204 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9205 END_PROFILE(SMBlockingX);
9209 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9210 locktype = CVAL(req->vwv+3, 0);
9211 oplocklevel = CVAL(req->vwv+3, 1);
9212 num_ulocks = SVAL(req->vwv+6, 0);
9213 num_locks = SVAL(req->vwv+7, 0);
9214 lock_timeout = IVAL(req->vwv+4, 0);
9215 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9217 if (!check_fsp(conn, req, fsp)) {
9218 END_PROFILE(SMBlockingX);
9224 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9225 /* we don't support these - and CANCEL_LOCK makes w2k
9226 and XP reboot so I don't really want to be
9227 compatible! (tridge) */
9228 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9229 END_PROFILE(SMBlockingX);
9233 /* Check if this is an oplock break on a file
9234 we have granted an oplock on.
9236 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9237 /* Client can insist on breaking to none. */
9238 bool break_to_none = (oplocklevel == 0);
9241 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9242 "for %s\n", (unsigned int)oplocklevel,
9243 fsp_fnum_dbg(fsp)));
9246 * Make sure we have granted an exclusive or batch oplock on
9250 if (fsp->oplock_type == 0) {
9252 /* The Samba4 nbench simulator doesn't understand
9253 the difference between break to level2 and break
9254 to none from level2 - it sends oplock break
9255 replies in both cases. Don't keep logging an error
9256 message here - just ignore it. JRA. */
9258 DEBUG(5,("reply_lockingX: Error : oplock break from "
9259 "client for %s (oplock=%d) and no "
9260 "oplock granted on this file (%s).\n",
9261 fsp_fnum_dbg(fsp), fsp->oplock_type,
9264 /* if this is a pure oplock break request then don't
9266 if (num_locks == 0 && num_ulocks == 0) {
9267 END_PROFILE(SMBlockingX);
9271 END_PROFILE(SMBlockingX);
9272 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9276 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9278 result = remove_oplock(fsp);
9280 result = downgrade_oplock(fsp);
9284 DEBUG(0, ("reply_lockingX: error in removing "
9285 "oplock on file %s\n", fsp_str_dbg(fsp)));
9286 /* Hmmm. Is this panic justified? */
9287 smb_panic("internal tdb error");
9290 /* if this is a pure oplock break request then don't send a
9292 if (num_locks == 0 && num_ulocks == 0) {
9293 /* Sanity check - ensure a pure oplock break is not a
9295 if (CVAL(req->vwv+0, 0) != 0xff) {
9296 DEBUG(0,("reply_lockingX: Error : pure oplock "
9297 "break is a chained %d request !\n",
9298 (unsigned int)CVAL(req->vwv+0, 0)));
9300 END_PROFILE(SMBlockingX);
9306 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9308 END_PROFILE(SMBlockingX);
9312 if (num_ulocks != 0) {
9313 struct smbd_lock_element *ulocks = NULL;
9316 ulocks = talloc_array(
9317 req, struct smbd_lock_element, num_ulocks);
9318 if (ulocks == NULL) {
9319 reply_nterror(req, NT_STATUS_NO_MEMORY);
9320 END_PROFILE(SMBlockingX);
9325 * Data now points at the beginning of the list of
9326 * smb_unlkrng structs
9328 for (i = 0; i < num_ulocks; i++) {
9329 ulocks[i].req_guid = smbd_request_guid(req,
9331 ulocks[i].smblctx = get_lock_pid(
9332 data, i, large_file_format);
9333 ulocks[i].count = get_lock_count(
9334 data, i, large_file_format);
9335 ulocks[i].offset = get_lock_offset(
9336 data, i, large_file_format);
9337 ulocks[i].brltype = UNLOCK_LOCK;
9341 * Unlock cancels pending locks
9344 ok = smbd_smb1_brl_finish_by_lock(
9351 reply_outbuf(req, 2, 0);
9352 SSVAL(req->outbuf, smb_vwv0, 0xff);
9353 SSVAL(req->outbuf, smb_vwv1, 0);
9354 END_PROFILE(SMBlockingX);
9358 status = smbd_do_unlocking(
9359 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9360 TALLOC_FREE(ulocks);
9361 if (!NT_STATUS_IS_OK(status)) {
9362 END_PROFILE(SMBlockingX);
9363 reply_nterror(req, status);
9368 /* Now do any requested locks */
9369 data += ((large_file_format ? 20 : 10)*num_ulocks);
9371 /* Data now points at the beginning of the list
9372 of smb_lkrng structs */
9374 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9375 brltype = READ_LOCK;
9377 brltype = WRITE_LOCK;
9380 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9381 if (locks == NULL) {
9382 reply_nterror(req, NT_STATUS_NO_MEMORY);
9383 END_PROFILE(SMBlockingX);
9387 for (i = 0; i < num_locks; i++) {
9388 locks[i].req_guid = smbd_request_guid(req, i),
9389 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9390 locks[i].count = get_lock_count(data, i, large_file_format);
9391 locks[i].offset = get_lock_offset(data, i, large_file_format);
9392 locks[i].brltype = brltype;
9395 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9399 if (num_locks == 0) {
9400 /* See smbtorture3 lock11 test */
9401 reply_outbuf(req, 2, 0);
9402 /* andx chain ends */
9403 SSVAL(req->outbuf, smb_vwv0, 0xff);
9404 SSVAL(req->outbuf, smb_vwv1, 0);
9405 END_PROFILE(SMBlockingX);
9409 ok = smbd_smb1_brl_finish_by_lock(
9413 locks[0], /* Windows only cancels the first lock */
9414 NT_STATUS_FILE_LOCK_CONFLICT);
9417 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9418 END_PROFILE(SMBlockingX);
9422 reply_outbuf(req, 2, 0);
9423 SSVAL(req->outbuf, smb_vwv0, 0xff);
9424 SSVAL(req->outbuf, smb_vwv1, 0);
9425 END_PROFILE(SMBlockingX);
9429 subreq = smbd_smb1_do_locks_send(
9439 if (subreq == NULL) {
9440 reply_nterror(req, NT_STATUS_NO_MEMORY);
9441 END_PROFILE(SMBlockingX);
9444 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9445 END_PROFILE(SMBlockingX);
9448 static void reply_lockingx_done(struct tevent_req *subreq)
9450 struct smb_request *req = NULL;
9454 START_PROFILE(SMBlockingX);
9456 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9459 status = smbd_smb1_do_locks_recv(subreq);
9460 TALLOC_FREE(subreq);
9462 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9464 if (NT_STATUS_IS_OK(status)) {
9465 reply_outbuf(req, 2, 0);
9466 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9467 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9469 reply_nterror(req, status);
9472 ok = srv_send_smb(req->xconn,
9473 (char *)req->outbuf,
9476 IS_CONN_ENCRYPTED(req->conn),
9479 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9482 END_PROFILE(SMBlockingX);
9486 #define DBGC_CLASS DBGC_ALL
9488 /****************************************************************************
9489 Reply to a SMBreadbmpx (read block multiplex) request.
9490 Always reply with an error, if someone has a platform really needs this,
9491 please contact vl@samba.org
9492 ****************************************************************************/
9494 void reply_readbmpx(struct smb_request *req)
9496 START_PROFILE(SMBreadBmpx);
9497 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9498 END_PROFILE(SMBreadBmpx);
9502 /****************************************************************************
9503 Reply to a SMBreadbs (read block multiplex secondary) request.
9504 Always reply with an error, if someone has a platform really needs this,
9505 please contact vl@samba.org
9506 ****************************************************************************/
9508 void reply_readbs(struct smb_request *req)
9510 START_PROFILE(SMBreadBs);
9511 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9512 END_PROFILE(SMBreadBs);
9516 /****************************************************************************
9517 Reply to a SMBsetattrE.
9518 ****************************************************************************/
9520 void reply_setattrE(struct smb_request *req)
9522 connection_struct *conn = req->conn;
9523 struct smb_file_time ft;
9527 START_PROFILE(SMBsetattrE);
9528 init_smb_file_time(&ft);
9531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9535 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9537 if(!fsp || (fsp->conn != conn)) {
9538 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9543 * Convert the DOS times into unix times.
9546 ft.atime = time_t_to_full_timespec(
9547 srv_make_unix_date2(req->vwv+3));
9548 ft.mtime = time_t_to_full_timespec(
9549 srv_make_unix_date2(req->vwv+5));
9550 ft.create_time = time_t_to_full_timespec(
9551 srv_make_unix_date2(req->vwv+1));
9553 reply_outbuf(req, 0, 0);
9556 * Patch from Ray Frush <frush@engr.colostate.edu>
9557 * Sometimes times are sent as zero - ignore them.
9560 /* Ensure we have a valid stat struct for the source. */
9561 status = vfs_stat_fsp(fsp);
9562 if (!NT_STATUS_IS_OK(status)) {
9563 reply_nterror(req, status);
9567 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9568 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9572 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9573 if (!NT_STATUS_IS_OK(status)) {
9574 reply_nterror(req, status);
9578 if (fsp->fsp_flags.modified) {
9579 trigger_write_time_update_immediate(fsp);
9582 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9585 (unsigned int)ft.atime.tv_sec,
9586 (unsigned int)ft.mtime.tv_sec,
9587 (unsigned int)ft.create_time.tv_sec
9590 END_PROFILE(SMBsetattrE);
9595 /* Back from the dead for OS/2..... JRA. */
9597 /****************************************************************************
9598 Reply to a SMBwritebmpx (write block multiplex primary) request.
9599 Always reply with an error, if someone has a platform really needs this,
9600 please contact vl@samba.org
9601 ****************************************************************************/
9603 void reply_writebmpx(struct smb_request *req)
9605 START_PROFILE(SMBwriteBmpx);
9606 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9607 END_PROFILE(SMBwriteBmpx);
9611 /****************************************************************************
9612 Reply to a SMBwritebs (write block multiplex secondary) request.
9613 Always reply with an error, if someone has a platform really needs this,
9614 please contact vl@samba.org
9615 ****************************************************************************/
9617 void reply_writebs(struct smb_request *req)
9619 START_PROFILE(SMBwriteBs);
9620 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9621 END_PROFILE(SMBwriteBs);
9625 /****************************************************************************
9626 Reply to a SMBgetattrE.
9627 ****************************************************************************/
9629 void reply_getattrE(struct smb_request *req)
9631 connection_struct *conn = req->conn;
9634 struct timespec create_ts;
9637 START_PROFILE(SMBgetattrE);
9640 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9641 END_PROFILE(SMBgetattrE);
9645 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9647 if(!fsp || (fsp->conn != conn)) {
9648 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9649 END_PROFILE(SMBgetattrE);
9653 /* Do an fstat on this file */
9654 status = vfs_stat_fsp(fsp);
9655 if (!NT_STATUS_IS_OK(status)) {
9656 reply_nterror(req, status);
9657 END_PROFILE(SMBgetattrE);
9661 mode = dos_mode(conn, fsp->fsp_name);
9664 * Convert the times into dos times. Set create
9665 * date to be last modify date as UNIX doesn't save
9669 reply_outbuf(req, 11, 0);
9671 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9672 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9673 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9674 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9675 /* Should we check pending modtime here ? JRA */
9676 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9677 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9679 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9680 SIVAL(req->outbuf, smb_vwv6, 0);
9681 SIVAL(req->outbuf, smb_vwv8, 0);
9683 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9684 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9685 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9687 SSVAL(req->outbuf,smb_vwv10, mode);
9689 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9691 END_PROFILE(SMBgetattrE);