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->fh->fd == -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 if (req->posix_pathnames) {
1830 ret = SMB_VFS_LSTAT(conn, smb_dname);
1832 ret = SMB_VFS_STAT(conn, smb_dname);
1835 nt_status = map_nt_error_from_unix(errno);
1836 reply_nterror(req, nt_status);
1841 * Open an fsp on this directory for the dptr.
1843 nt_status = SMB_VFS_CREATE_FILE(
1846 smb_dname, /* dname */
1847 FILE_LIST_DIRECTORY, /* access_mask */
1849 FILE_SHARE_WRITE, /* share_access */
1850 FILE_OPEN, /* create_disposition*/
1851 FILE_DIRECTORY_FILE, /* create_options */
1852 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1853 NO_OPLOCK, /* oplock_request */
1855 0, /* allocation_size */
1856 0, /* private_flags */
1861 NULL, /* in_context */
1862 NULL);/* out_context */
1864 if (!NT_STATUS_IS_OK(nt_status)) {
1865 DBG_ERR("failed to open directory %s\n",
1866 smb_fname_str_dbg(smb_dname));
1867 reply_nterror(req, nt_status);
1871 nt_status = dptr_create(conn,
1881 TALLOC_FREE(smb_dname);
1883 if (!NT_STATUS_IS_OK(nt_status)) {
1885 * Use NULL here for the first parameter (req)
1886 * as this is not a client visible handle so
1887 * can'tbe part of an SMB1 chain.
1889 close_file(NULL, fsp, NORMAL_CLOSE);
1891 reply_nterror(req, nt_status);
1895 dptr_num = dptr_dnum(fsp->dptr);
1899 const char *dirpath;
1901 if (smbreq_bufrem(req, p) < 21) {
1902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1906 memcpy(status,p,21);
1907 status_dirtype = CVAL(status,0) & 0x1F;
1908 if (status_dirtype != (dirtype & 0x1F)) {
1909 dirtype = status_dirtype;
1912 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1916 dirpath = dptr_path(sconn, dptr_num);
1917 directory = talloc_strdup(ctx, dirpath);
1919 reply_nterror(req, NT_STATUS_NO_MEMORY);
1923 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1927 dirtype = dptr_attr(sconn, dptr_num);
1930 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1932 DEBUG(4,("dptr_num is %d\n",dptr_num));
1934 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1935 char buf[DIR_STRUCT_SIZE];
1936 memcpy(buf,status,21);
1937 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1938 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1939 reply_nterror(req, NT_STATUS_NO_MEMORY);
1942 dptr_fill(sconn, buf+12,dptr_num);
1943 if (dptr_zero(buf+12) && (status_len==0)) {
1948 if (message_push_blob(&req->outbuf,
1949 data_blob_const(buf, sizeof(buf)))
1951 reply_nterror(req, NT_STATUS_NO_MEMORY);
1956 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1957 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1959 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1961 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1962 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1963 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1964 check_descend = True;
1967 for (i=numentries;(i<maxentries) && !finished;i++) {
1968 finished = !get_dir_entry(ctx,
1979 char buf[DIR_STRUCT_SIZE];
1980 memcpy(buf,status,21);
1981 if (!make_dir_struct(ctx,
1987 convert_timespec_to_time_t(date),
1988 !allow_long_path_components)) {
1989 reply_nterror(req, NT_STATUS_NO_MEMORY);
1992 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1995 if (message_push_blob(&req->outbuf,
1996 data_blob_const(buf, sizeof(buf)))
1998 reply_nterror(req, NT_STATUS_NO_MEMORY);
2008 /* If we were called as SMBffirst with smb_search_id == NULL
2009 and no entries were found then return error and close fsp->dptr
2012 if (numentries == 0) {
2015 close_file(NULL, fsp, NORMAL_CLOSE);
2018 } else if(expect_close && status_len == 0) {
2019 /* Close the dptr - we know it's gone */
2022 close_file(NULL, fsp, NORMAL_CLOSE);
2027 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2028 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2030 /* fsp may have been closed above. */
2032 close_file(NULL, fsp, NORMAL_CLOSE);
2037 if ((numentries == 0) && !mask_contains_wcard) {
2038 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2042 SSVAL(req->outbuf,smb_vwv0,numentries);
2043 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2044 SCVAL(smb_buf(req->outbuf),0,5);
2045 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2047 /* The replies here are never long name. */
2048 SSVAL(req->outbuf, smb_flg2,
2049 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2050 if (!allow_long_path_components) {
2051 SSVAL(req->outbuf, smb_flg2,
2052 SVAL(req->outbuf, smb_flg2)
2053 & (~FLAGS2_LONG_PATH_COMPONENTS));
2056 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2057 SSVAL(req->outbuf, smb_flg2,
2058 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2060 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2061 smb_fn_name(req->cmd),
2068 TALLOC_FREE(directory);
2070 TALLOC_FREE(smb_fname);
2071 END_PROFILE(SMBsearch);
2075 /****************************************************************************
2076 Reply to a fclose (stop directory search).
2077 ****************************************************************************/
2079 void reply_fclose(struct smb_request *req)
2087 TALLOC_CTX *ctx = talloc_tos();
2088 struct smbd_server_connection *sconn = req->sconn;
2089 files_struct *fsp = NULL;
2091 START_PROFILE(SMBfclose);
2093 if (req->posix_pathnames) {
2094 reply_unknown_new(req, req->cmd);
2095 END_PROFILE(SMBfclose);
2099 p = (const char *)req->buf + 1;
2100 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
2102 if (!NT_STATUS_IS_OK(err)) {
2103 reply_nterror(req, err);
2104 END_PROFILE(SMBfclose);
2108 if (smbreq_bufrem(req, p) < 3) {
2109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2110 END_PROFILE(SMBfclose);
2115 status_len = SVAL(p,0);
2118 if (status_len == 0) {
2119 reply_force_doserror(req, ERRSRV, ERRsrverror);
2120 END_PROFILE(SMBfclose);
2124 if (smbreq_bufrem(req, p) < 21) {
2125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2126 END_PROFILE(SMBfclose);
2130 memcpy(status,p,21);
2132 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2134 /* Close the file - we know it's gone */
2135 close_file(NULL, fsp, NORMAL_CLOSE);
2140 reply_outbuf(req, 1, 0);
2141 SSVAL(req->outbuf,smb_vwv0,0);
2143 DEBUG(3,("search close\n"));
2145 END_PROFILE(SMBfclose);
2149 /****************************************************************************
2151 ****************************************************************************/
2153 void reply_open(struct smb_request *req)
2155 connection_struct *conn = req->conn;
2156 struct smb_filename *smb_fname = NULL;
2166 uint32_t access_mask;
2167 uint32_t share_mode;
2168 uint32_t create_disposition;
2169 uint32_t create_options = 0;
2170 uint32_t private_flags = 0;
2173 TALLOC_CTX *ctx = talloc_tos();
2175 START_PROFILE(SMBopen);
2178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2182 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2183 deny_mode = SVAL(req->vwv+0, 0);
2184 dos_attr = SVAL(req->vwv+1, 0);
2186 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2187 STR_TERMINATE, &status);
2188 if (!NT_STATUS_IS_OK(status)) {
2189 reply_nterror(req, status);
2193 if (!map_open_params_to_ntcreate(fname, deny_mode,
2194 OPENX_FILE_EXISTS_OPEN, &access_mask,
2195 &share_mode, &create_disposition,
2196 &create_options, &private_flags)) {
2197 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2201 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2203 status = filename_convert(ctx,
2209 if (!NT_STATUS_IS_OK(status)) {
2210 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2211 reply_botherror(req,
2212 NT_STATUS_PATH_NOT_COVERED,
2213 ERRSRV, ERRbadpath);
2216 reply_nterror(req, status);
2220 status = SMB_VFS_CREATE_FILE(
2223 smb_fname, /* fname */
2224 access_mask, /* access_mask */
2225 share_mode, /* share_access */
2226 create_disposition, /* create_disposition*/
2227 create_options, /* create_options */
2228 dos_attr, /* file_attributes */
2229 oplock_request, /* oplock_request */
2231 0, /* allocation_size */
2237 NULL, NULL); /* create context */
2239 if (!NT_STATUS_IS_OK(status)) {
2240 if (open_was_deferred(req->xconn, req->mid)) {
2241 /* We have re-scheduled this call. */
2245 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2246 reply_openerror(req, status);
2250 fsp = fcb_or_dos_open(
2257 bool ok = defer_smb1_sharing_violation(req);
2261 reply_openerror(req, status);
2266 /* Ensure we're pointing at the correct stat struct. */
2267 TALLOC_FREE(smb_fname);
2268 smb_fname = fsp->fsp_name;
2270 size = smb_fname->st.st_ex_size;
2271 fattr = dos_mode(conn, smb_fname);
2273 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2275 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2276 DEBUG(3,("attempt to open a directory %s\n",
2278 close_file(req, fsp, ERROR_CLOSE);
2279 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2280 ERRDOS, ERRnoaccess);
2284 reply_outbuf(req, 7, 0);
2285 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2286 SSVAL(req->outbuf,smb_vwv1,fattr);
2287 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2288 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2290 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2292 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2293 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2295 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2296 SCVAL(req->outbuf,smb_flg,
2297 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2300 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2301 SCVAL(req->outbuf,smb_flg,
2302 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2305 END_PROFILE(SMBopen);
2309 /****************************************************************************
2310 Reply to an open and X.
2311 ****************************************************************************/
2313 void reply_open_and_X(struct smb_request *req)
2315 connection_struct *conn = req->conn;
2316 struct smb_filename *smb_fname = NULL;
2318 uint16_t open_flags;
2321 /* Breakout the oplock request bits so we can set the
2322 reply bits separately. */
2323 int ex_oplock_request;
2324 int core_oplock_request;
2327 int smb_sattr = SVAL(req->vwv+4, 0);
2328 uint32_t smb_time = make_unix_date3(req->vwv+6);
2336 uint64_t allocation_size;
2337 ssize_t retval = -1;
2338 uint32_t access_mask;
2339 uint32_t share_mode;
2340 uint32_t create_disposition;
2341 uint32_t create_options = 0;
2342 uint32_t private_flags = 0;
2344 TALLOC_CTX *ctx = talloc_tos();
2346 START_PROFILE(SMBopenX);
2348 if (req->wct < 15) {
2349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2353 open_flags = SVAL(req->vwv+2, 0);
2354 deny_mode = SVAL(req->vwv+3, 0);
2355 smb_attr = SVAL(req->vwv+5, 0);
2356 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2357 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2358 oplock_request = ex_oplock_request | core_oplock_request;
2359 smb_ofun = SVAL(req->vwv+8, 0);
2360 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2362 /* If it's an IPC, pass off the pipe handler. */
2364 if (lp_nt_pipe_support()) {
2365 reply_open_pipe_and_X(conn, req);
2367 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2372 /* XXXX we need to handle passed times, sattr and flags */
2373 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2374 STR_TERMINATE, &status);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 reply_nterror(req, status);
2380 if (!map_open_params_to_ntcreate(fname, deny_mode,
2382 &access_mask, &share_mode,
2383 &create_disposition,
2386 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2390 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2392 status = filename_convert(ctx,
2398 if (!NT_STATUS_IS_OK(status)) {
2399 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2400 reply_botherror(req,
2401 NT_STATUS_PATH_NOT_COVERED,
2402 ERRSRV, ERRbadpath);
2405 reply_nterror(req, status);
2409 status = SMB_VFS_CREATE_FILE(
2412 smb_fname, /* fname */
2413 access_mask, /* access_mask */
2414 share_mode, /* share_access */
2415 create_disposition, /* create_disposition*/
2416 create_options, /* create_options */
2417 smb_attr, /* file_attributes */
2418 oplock_request, /* oplock_request */
2420 0, /* allocation_size */
2425 &smb_action, /* pinfo */
2426 NULL, NULL); /* create context */
2428 if (!NT_STATUS_IS_OK(status)) {
2429 if (open_was_deferred(req->xconn, req->mid)) {
2430 /* We have re-scheduled this call. */
2434 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2435 reply_openerror(req, status);
2439 fsp = fcb_or_dos_open(
2446 bool ok = defer_smb1_sharing_violation(req);
2450 reply_openerror(req, status);
2455 smb_action = FILE_WAS_OPENED;
2458 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2459 if the file is truncated or created. */
2460 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2461 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2462 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2463 close_file(req, fsp, ERROR_CLOSE);
2464 reply_nterror(req, NT_STATUS_DISK_FULL);
2467 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2469 close_file(req, fsp, ERROR_CLOSE);
2470 reply_nterror(req, NT_STATUS_DISK_FULL);
2473 status = vfs_stat_fsp(fsp);
2474 if (!NT_STATUS_IS_OK(status)) {
2475 close_file(req, fsp, ERROR_CLOSE);
2476 reply_nterror(req, status);
2481 fattr = dos_mode(conn, fsp->fsp_name);
2482 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2483 close_file(req, fsp, ERROR_CLOSE);
2484 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2487 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2489 /* If the caller set the extended oplock request bit
2490 and we granted one (by whatever means) - set the
2491 correct bit for extended oplock reply.
2494 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2495 smb_action |= EXTENDED_OPLOCK_GRANTED;
2498 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2499 smb_action |= EXTENDED_OPLOCK_GRANTED;
2502 /* If the caller set the core oplock request bit
2503 and we granted one (by whatever means) - set the
2504 correct bit for core oplock reply.
2507 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2508 reply_outbuf(req, 19, 0);
2510 reply_outbuf(req, 15, 0);
2513 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2514 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2516 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2517 SCVAL(req->outbuf, smb_flg,
2518 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2521 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2522 SCVAL(req->outbuf, smb_flg,
2523 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2526 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2527 SSVAL(req->outbuf,smb_vwv3,fattr);
2528 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2529 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2531 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2533 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2534 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2535 SSVAL(req->outbuf,smb_vwv11,smb_action);
2537 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2538 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2542 TALLOC_FREE(smb_fname);
2543 END_PROFILE(SMBopenX);
2547 /****************************************************************************
2548 Reply to a SMBulogoffX.
2549 ****************************************************************************/
2551 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2552 struct smbXsrv_session *session);
2553 static void reply_ulogoffX_done(struct tevent_req *req);
2555 void reply_ulogoffX(struct smb_request *smb1req)
2557 struct timeval now = timeval_current();
2558 struct smbXsrv_session *session = NULL;
2559 struct tevent_req *req;
2563 * Don't setup the profile charge here, take
2564 * it in reply_ulogoffX_done(). Not strictly correct
2565 * but better than the other SMB1 async
2566 * code that double-charges at the moment.
2569 status = smb1srv_session_lookup(smb1req->xconn,
2571 timeval_to_nttime(&now),
2573 if (!NT_STATUS_IS_OK(status)) {
2574 /* Not going async, profile here. */
2575 START_PROFILE(SMBulogoffX);
2576 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2577 (unsigned long long)smb1req->vuid);
2579 smb1req->vuid = UID_FIELD_INVALID;
2580 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2581 END_PROFILE(SMBulogoffX);
2585 req = reply_ulogoffX_send(smb1req, session);
2587 /* Not going async, profile here. */
2588 START_PROFILE(SMBulogoffX);
2589 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2590 END_PROFILE(SMBulogoffX);
2594 /* We're async. This will complete later. */
2595 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2599 struct reply_ulogoffX_state {
2600 struct tevent_queue *wait_queue;
2601 struct smbXsrv_session *session;
2604 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2606 /****************************************************************************
2607 Async SMB1 ulogoffX.
2608 Note, on failure here we deallocate and return NULL to allow the caller to
2609 SMB1 return an error of ERRnomem immediately.
2610 ****************************************************************************/
2612 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2613 struct smbXsrv_session *session)
2615 struct tevent_req *req;
2616 struct reply_ulogoffX_state *state;
2617 struct tevent_req *subreq;
2619 struct smbd_server_connection *sconn = session->client->sconn;
2620 uint64_t vuid = session->global->session_wire_id;
2622 req = tevent_req_create(smb1req, &state,
2623 struct reply_ulogoffX_state);
2627 state->wait_queue = tevent_queue_create(state,
2628 "reply_ulogoffX_wait_queue");
2629 if (tevent_req_nomem(state->wait_queue, req)) {
2633 state->session = session;
2636 * Make sure that no new request will be able to use this session.
2637 * This ensures that once all outstanding fsp->aio_requests
2638 * on this session are done, we are safe to close it.
2640 session->status = NT_STATUS_USER_SESSION_DELETED;
2642 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2643 if (fsp->vuid != vuid) {
2647 * Flag the file as close in progress.
2648 * This will prevent any more IO being
2651 fsp->fsp_flags.closing = true;
2653 if (fsp->num_aio_requests > 0) {
2655 * Now wait until all aio requests on this fsp are
2658 * We don't set a callback, as we just want to block the
2659 * wait queue and the talloc_free() of fsp->aio_request
2660 * will remove the item from the wait queue.
2662 subreq = tevent_queue_wait_send(fsp->aio_requests,
2665 if (tevent_req_nomem(subreq, req)) {
2673 * Now we add our own waiter to the end of the queue,
2674 * this way we get notified when all pending requests are finished
2675 * and reply to the outstanding SMB1 request.
2677 subreq = tevent_queue_wait_send(state,
2680 if (tevent_req_nomem(subreq, req)) {
2686 * We're really going async - move the SMB1 request from
2687 * a talloc stackframe above us to the sconn talloc-context.
2688 * We need this to stick around until the wait_done
2689 * callback is invoked.
2691 smb1req = talloc_move(sconn, &smb1req);
2693 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2698 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2700 struct tevent_req *req = tevent_req_callback_data(
2701 subreq, struct tevent_req);
2703 tevent_queue_wait_recv(subreq);
2704 TALLOC_FREE(subreq);
2705 tevent_req_done(req);
2708 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2710 return tevent_req_simple_recv_ntstatus(req);
2713 static void reply_ulogoffX_done(struct tevent_req *req)
2715 struct smb_request *smb1req = tevent_req_callback_data(
2716 req, struct smb_request);
2717 struct reply_ulogoffX_state *state = tevent_req_data(req,
2718 struct reply_ulogoffX_state);
2719 struct smbXsrv_session *session = state->session;
2723 * Take the profile charge here. Not strictly
2724 * correct but better than the other SMB1 async
2725 * code that double-charges at the moment.
2727 START_PROFILE(SMBulogoffX);
2729 status = reply_ulogoffX_recv(req);
2731 if (!NT_STATUS_IS_OK(status)) {
2732 TALLOC_FREE(smb1req);
2733 END_PROFILE(SMBulogoffX);
2734 exit_server(__location__ ": reply_ulogoffX_recv failed");
2738 status = smbXsrv_session_logoff(session);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 TALLOC_FREE(smb1req);
2741 END_PROFILE(SMBulogoffX);
2742 exit_server(__location__ ": smbXsrv_session_logoff failed");
2746 TALLOC_FREE(session);
2748 reply_outbuf(smb1req, 2, 0);
2749 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2750 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2752 DBG_NOTICE("ulogoffX vuid=%llu\n",
2753 (unsigned long long)smb1req->vuid);
2755 smb1req->vuid = UID_FIELD_INVALID;
2757 * The following call is needed to push the
2758 * reply data back out the socket after async
2759 * return. Plus it frees smb1req.
2761 smb_request_done(smb1req);
2762 END_PROFILE(SMBulogoffX);
2765 /****************************************************************************
2766 Reply to a mknew or a create.
2767 ****************************************************************************/
2769 void reply_mknew(struct smb_request *req)
2771 connection_struct *conn = req->conn;
2772 struct smb_filename *smb_fname = NULL;
2775 struct smb_file_time ft;
2777 int oplock_request = 0;
2779 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2780 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2781 uint32_t create_disposition;
2782 uint32_t create_options = 0;
2784 TALLOC_CTX *ctx = talloc_tos();
2786 START_PROFILE(SMBcreate);
2787 init_smb_file_time(&ft);
2790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2794 fattr = SVAL(req->vwv+0, 0);
2795 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2797 if (req->cmd == SMBmknew) {
2798 /* We should fail if file exists. */
2799 create_disposition = FILE_CREATE;
2801 /* Create if file doesn't exist, truncate if it does. */
2802 create_disposition = FILE_OVERWRITE_IF;
2806 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2808 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2809 STR_TERMINATE, &status);
2810 if (!NT_STATUS_IS_OK(status)) {
2811 reply_nterror(req, status);
2815 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2816 status = filename_convert(ctx,
2822 if (!NT_STATUS_IS_OK(status)) {
2823 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2824 reply_botherror(req,
2825 NT_STATUS_PATH_NOT_COVERED,
2826 ERRSRV, ERRbadpath);
2829 reply_nterror(req, status);
2833 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2834 DEBUG(0,("Attempt to create file (%s) with volid set - "
2835 "please report this\n",
2836 smb_fname_str_dbg(smb_fname)));
2839 status = SMB_VFS_CREATE_FILE(
2842 smb_fname, /* fname */
2843 access_mask, /* access_mask */
2844 share_mode, /* share_access */
2845 create_disposition, /* create_disposition*/
2846 create_options, /* create_options */
2847 fattr, /* file_attributes */
2848 oplock_request, /* oplock_request */
2850 0, /* allocation_size */
2851 0, /* private_flags */
2856 NULL, NULL); /* create context */
2858 if (!NT_STATUS_IS_OK(status)) {
2859 if (open_was_deferred(req->xconn, req->mid)) {
2860 /* We have re-scheduled this call. */
2863 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2864 bool ok = defer_smb1_sharing_violation(req);
2869 reply_openerror(req, status);
2873 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2874 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2875 if (!NT_STATUS_IS_OK(status)) {
2876 END_PROFILE(SMBcreate);
2880 reply_outbuf(req, 1, 0);
2881 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2883 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2884 SCVAL(req->outbuf,smb_flg,
2885 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2888 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2889 SCVAL(req->outbuf,smb_flg,
2890 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2893 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2894 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2895 smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2896 (unsigned int)fattr));
2899 TALLOC_FREE(smb_fname);
2900 END_PROFILE(SMBcreate);
2904 /****************************************************************************
2905 Reply to a create temporary file.
2906 ****************************************************************************/
2908 void reply_ctemp(struct smb_request *req)
2910 connection_struct *conn = req->conn;
2911 struct smb_filename *smb_fname = NULL;
2912 char *wire_name = NULL;
2921 TALLOC_CTX *ctx = talloc_tos();
2923 START_PROFILE(SMBctemp);
2926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2930 fattr = SVAL(req->vwv+0, 0);
2931 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2933 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2934 STR_TERMINATE, &status);
2935 if (!NT_STATUS_IS_OK(status)) {
2936 reply_nterror(req, status);
2940 for (i = 0; i < 10; i++) {
2942 fname = talloc_asprintf(ctx,
2945 generate_random_str_list(ctx, 5, "0123456789"));
2947 fname = talloc_asprintf(ctx,
2949 generate_random_str_list(ctx, 5, "0123456789"));
2953 reply_nterror(req, NT_STATUS_NO_MEMORY);
2957 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2958 status = filename_convert(ctx, conn,
2963 if (!NT_STATUS_IS_OK(status)) {
2964 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2965 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2966 ERRSRV, ERRbadpath);
2969 reply_nterror(req, status);
2973 /* Create the file. */
2974 status = SMB_VFS_CREATE_FILE(
2977 smb_fname, /* fname */
2978 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2979 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2980 FILE_CREATE, /* create_disposition*/
2981 0, /* create_options */
2982 fattr, /* file_attributes */
2983 oplock_request, /* oplock_request */
2985 0, /* allocation_size */
2986 0, /* private_flags */
2991 NULL, NULL); /* create context */
2993 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2995 TALLOC_FREE(smb_fname);
2999 if (!NT_STATUS_IS_OK(status)) {
3000 if (open_was_deferred(req->xconn, req->mid)) {
3001 /* We have re-scheduled this call. */
3004 if (NT_STATUS_EQUAL(
3005 status, NT_STATUS_SHARING_VIOLATION)) {
3006 bool ok = defer_smb1_sharing_violation(req);
3011 reply_openerror(req, status);
3019 /* Collision after 10 times... */
3020 reply_nterror(req, status);
3024 reply_outbuf(req, 1, 0);
3025 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3027 /* the returned filename is relative to the directory */
3028 s = strrchr_m(fsp->fsp_name->base_name, '/');
3030 s = fsp->fsp_name->base_name;
3036 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3037 thing in the byte section. JRA */
3038 SSVALS(p, 0, -1); /* what is this? not in spec */
3040 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3042 reply_nterror(req, NT_STATUS_NO_MEMORY);
3046 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3047 SCVAL(req->outbuf, smb_flg,
3048 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3051 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3052 SCVAL(req->outbuf, smb_flg,
3053 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3056 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3057 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3058 fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
3060 TALLOC_FREE(smb_fname);
3061 TALLOC_FREE(wire_name);
3062 END_PROFILE(SMBctemp);
3066 /*******************************************************************
3067 Check if a user is allowed to rename a file.
3068 ********************************************************************/
3070 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3073 if (!CAN_WRITE(conn)) {
3074 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3077 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3078 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3079 /* Only bother to read the DOS attribute if we might deny the
3080 rename on the grounds of attribute mismatch. */
3081 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3082 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3083 return NT_STATUS_NO_SUCH_FILE;
3087 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3088 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3089 return NT_STATUS_OK;
3092 /* If no pathnames are open below this
3093 directory, allow the rename. */
3095 if (lp_strict_rename(SNUM(conn))) {
3097 * Strict rename, check open file db.
3099 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3100 return NT_STATUS_ACCESS_DENIED;
3102 } else if (file_find_subpath(fsp)) {
3104 * No strict rename, just look in local process.
3106 return NT_STATUS_ACCESS_DENIED;
3108 return NT_STATUS_OK;
3111 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3112 return NT_STATUS_OK;
3115 return NT_STATUS_ACCESS_DENIED;
3118 /*******************************************************************
3119 * unlink a file with all relevant access checks
3120 *******************************************************************/
3122 static NTSTATUS do_unlink(connection_struct *conn,
3123 struct smb_request *req,
3124 struct smb_filename *smb_fname,
3129 uint32_t dirtype_orig = dirtype;
3132 bool posix_paths = (req != NULL && req->posix_pathnames);
3133 struct smb2_create_blobs *posx = NULL;
3135 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3136 smb_fname_str_dbg(smb_fname),
3139 if (!CAN_WRITE(conn)) {
3140 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3144 ret = SMB_VFS_LSTAT(conn, smb_fname);
3146 ret = SMB_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 */
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 = check_name(conn, f);
3461 if (!NT_STATUS_IS_OK(status)) {
3462 TALLOC_FREE(dir_hnd);
3464 TALLOC_FREE(talloced);
3468 status = do_unlink(conn, req, f, dirtype);
3469 if (!NT_STATUS_IS_OK(status)) {
3470 TALLOC_FREE(dir_hnd);
3472 TALLOC_FREE(talloced);
3477 DBG_DEBUG("successful unlink [%s]\n",
3478 smb_fname_str_dbg(f));
3481 TALLOC_FREE(talloced);
3483 TALLOC_FREE(dir_hnd);
3486 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3487 status = map_nt_error_from_unix(errno);
3491 TALLOC_FREE(smb_fname_dir);
3492 TALLOC_FREE(fname_dir);
3493 TALLOC_FREE(fname_mask);
3497 /****************************************************************************
3499 ****************************************************************************/
3501 void reply_unlink(struct smb_request *req)
3503 connection_struct *conn = req->conn;
3505 struct smb_filename *smb_fname = NULL;
3508 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3509 ucf_flags_from_smb_request(req);
3510 TALLOC_CTX *ctx = talloc_tos();
3511 bool has_wild = false;
3513 START_PROFILE(SMBunlink);
3516 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3520 dirtype = SVAL(req->vwv+0, 0);
3522 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
3523 STR_TERMINATE, &status);
3524 if (!NT_STATUS_IS_OK(status)) {
3525 reply_nterror(req, status);
3529 status = filename_convert(ctx, conn,
3534 if (!NT_STATUS_IS_OK(status)) {
3535 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3536 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3537 ERRSRV, ERRbadpath);
3540 reply_nterror(req, status);
3544 if (req != NULL && !req->posix_pathnames) {
3545 char *lcomp = get_original_lcomp(ctx,
3549 if (lcomp == NULL) {
3550 reply_nterror(req, NT_STATUS_NO_MEMORY);
3553 has_wild = ms_has_wild(lcomp);
3557 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3559 status = unlink_internals(conn, req, dirtype, smb_fname, has_wild);
3560 if (!NT_STATUS_IS_OK(status)) {
3561 if (open_was_deferred(req->xconn, req->mid)) {
3562 /* We have re-scheduled this call. */
3565 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3566 bool ok = defer_smb1_sharing_violation(req);
3571 reply_nterror(req, status);
3575 reply_outbuf(req, 0, 0);
3577 TALLOC_FREE(smb_fname);
3578 END_PROFILE(SMBunlink);
3582 /****************************************************************************
3584 ****************************************************************************/
3586 static void fail_readraw(void)
3588 const char *errstr = talloc_asprintf(talloc_tos(),
3589 "FAIL ! reply_readbraw: socket write fail (%s)",
3594 exit_server_cleanly(errstr);
3597 /****************************************************************************
3598 Fake (read/write) sendfile. Returns -1 on read or write fail.
3599 ****************************************************************************/
3601 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3602 off_t startpos, size_t nread)
3605 size_t tosend = nread;
3612 bufsize = MIN(nread, 65536);
3614 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3618 while (tosend > 0) {
3622 cur_read = MIN(tosend, bufsize);
3623 ret = read_file(fsp,buf,startpos,cur_read);
3629 /* If we had a short read, fill with zeros. */
3630 if (ret < cur_read) {
3631 memset(buf + ret, '\0', cur_read - ret);
3634 ret = write_data(xconn->transport.sock, buf, cur_read);
3635 if (ret != cur_read) {
3636 int saved_errno = errno;
3638 * Try and give an error message saying what
3641 DEBUG(0, ("write_data failed for client %s. "
3643 smbXsrv_connection_dbg(xconn),
3644 strerror(saved_errno)));
3646 errno = saved_errno;
3650 startpos += cur_read;
3654 return (ssize_t)nread;
3657 /****************************************************************************
3658 Deal with the case of sendfile reading less bytes from the file than
3659 requested. Fill with zeros (all we can do). Returns 0 on success
3660 ****************************************************************************/
3662 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3668 #define SHORT_SEND_BUFSIZE 1024
3669 if (nread < headersize) {
3670 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3671 "header for file %s (%s). Terminating\n",
3672 fsp_str_dbg(fsp), strerror(errno)));
3676 nread -= headersize;
3678 if (nread < smb_maxcnt) {
3679 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3681 DEBUG(0,("sendfile_short_send: malloc failed "
3682 "for file %s (%s). Terminating\n",
3683 fsp_str_dbg(fsp), strerror(errno)));
3687 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3688 "with zeros !\n", fsp_str_dbg(fsp)));
3690 while (nread < smb_maxcnt) {
3692 * We asked for the real file size and told sendfile
3693 * to not go beyond the end of the file. But it can
3694 * happen that in between our fstat call and the
3695 * sendfile call the file was truncated. This is very
3696 * bad because we have already announced the larger
3697 * number of bytes to the client.
3699 * The best we can do now is to send 0-bytes, just as
3700 * a read from a hole in a sparse file would do.
3702 * This should happen rarely enough that I don't care
3703 * about efficiency here :-)
3708 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3709 ret = write_data(xconn->transport.sock, buf, to_write);
3710 if (ret != to_write) {
3711 int saved_errno = errno;
3713 * Try and give an error message saying what
3716 DEBUG(0, ("write_data failed for client %s. "
3718 smbXsrv_connection_dbg(xconn),
3719 strerror(saved_errno)));
3720 errno = saved_errno;
3731 /****************************************************************************
3732 Return a readbraw error (4 bytes of zero).
3733 ****************************************************************************/
3735 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3741 smbd_lock_socket(xconn);
3742 if (write_data(xconn->transport.sock,header,4) != 4) {
3743 int saved_errno = errno;
3745 * Try and give an error message saying what
3748 DEBUG(0, ("write_data failed for client %s. "
3750 smbXsrv_connection_dbg(xconn),
3751 strerror(saved_errno)));
3752 errno = saved_errno;
3756 smbd_unlock_socket(xconn);
3759 /*******************************************************************
3760 Ensure we don't use sendfile if server smb signing is active.
3761 ********************************************************************/
3763 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3765 bool sign_active = false;
3767 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3768 if (get_Protocol() < PROTOCOL_NT1) {
3771 if (signing_state) {
3772 sign_active = smb_signing_is_active(signing_state);
3774 return (lp__use_sendfile(snum) &&
3775 (get_remote_arch() != RA_WIN95) &&
3778 /****************************************************************************
3779 Use sendfile in readbraw.
3780 ****************************************************************************/
3782 static void send_file_readbraw(connection_struct *conn,
3783 struct smb_request *req,
3789 struct smbXsrv_connection *xconn = req->xconn;
3790 char *outbuf = NULL;
3794 * We can only use sendfile on a non-chained packet
3795 * but we can use on a non-oplocked file. tridge proved this
3796 * on a train in Germany :-). JRA.
3797 * reply_readbraw has already checked the length.
3800 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3801 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3802 ssize_t sendfile_read = -1;
3804 DATA_BLOB header_blob;
3806 _smb_setlen(header,nread);
3807 header_blob = data_blob_const(header, 4);
3809 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3810 &header_blob, startpos,
3812 if (sendfile_read == -1) {
3813 /* Returning ENOSYS means no data at all was sent.
3814 * Do this as a normal read. */
3815 if (errno == ENOSYS) {
3816 goto normal_readbraw;
3820 * Special hack for broken Linux with no working sendfile. If we
3821 * return EINTR we sent the header but not the rest of the data.
3822 * Fake this up by doing read/write calls.
3824 if (errno == EINTR) {
3825 /* Ensure we don't do this again. */
3826 set_use_sendfile(SNUM(conn), False);
3827 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3829 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3830 DEBUG(0,("send_file_readbraw: "
3831 "fake_sendfile failed for "
3835 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3840 DEBUG(0,("send_file_readbraw: sendfile failed for "
3841 "file %s (%s). Terminating\n",
3842 fsp_str_dbg(fsp), strerror(errno)));
3843 exit_server_cleanly("send_file_readbraw sendfile failed");
3844 } else if (sendfile_read == 0) {
3846 * Some sendfile implementations return 0 to indicate
3847 * that there was a short read, but nothing was
3848 * actually written to the socket. In this case,
3849 * fallback to the normal read path so the header gets
3850 * the correct byte count.
3852 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3853 "bytes falling back to the normal read: "
3854 "%s\n", fsp_str_dbg(fsp)));
3855 goto normal_readbraw;
3858 /* Deal with possible short send. */
3859 if (sendfile_read != 4+nread) {
3860 ret = sendfile_short_send(xconn, fsp,
3861 sendfile_read, 4, nread);
3871 outbuf = talloc_array(NULL, char, nread+4);
3873 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3874 (unsigned)(nread+4)));
3875 reply_readbraw_error(xconn);
3880 ret = read_file(fsp,outbuf+4,startpos,nread);
3881 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3890 _smb_setlen(outbuf,ret);
3891 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3892 int saved_errno = errno;
3894 * Try and give an error message saying what
3897 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3898 smbXsrv_connection_dbg(xconn),
3899 strerror(saved_errno)));
3900 errno = saved_errno;
3905 TALLOC_FREE(outbuf);
3908 /****************************************************************************
3909 Reply to a readbraw (core+ protocol).
3910 ****************************************************************************/
3912 void reply_readbraw(struct smb_request *req)
3914 connection_struct *conn = req->conn;
3915 struct smbXsrv_connection *xconn = req->xconn;
3916 ssize_t maxcount,mincount;
3920 struct lock_struct lock;
3924 START_PROFILE(SMBreadbraw);
3926 if (srv_is_signing_active(xconn) || req->encrypted) {
3927 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3928 "raw reads/writes are disallowed.");
3932 reply_readbraw_error(xconn);
3933 END_PROFILE(SMBreadbraw);
3937 if (xconn->smb1.echo_handler.trusted_fde) {
3938 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3939 "'async smb echo handler = yes'\n"));
3940 reply_readbraw_error(xconn);
3941 END_PROFILE(SMBreadbraw);
3946 * Special check if an oplock break has been issued
3947 * and the readraw request croses on the wire, we must
3948 * return a zero length response here.
3951 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3954 * We have to do a check_fsp by hand here, as
3955 * we must always return 4 zero bytes on error,
3961 conn != fsp->conn ||
3962 req->vuid != fsp->vuid ||
3963 fsp->fsp_flags.is_directory ||
3964 fsp_get_io_fd(fsp) == -1)
3967 * fsp could be NULL here so use the value from the packet. JRA.
3969 DEBUG(3,("reply_readbraw: fnum %d not valid "
3971 (int)SVAL(req->vwv+0, 0)));
3972 reply_readbraw_error(xconn);
3973 END_PROFILE(SMBreadbraw);
3977 /* Do a "by hand" version of CHECK_READ. */
3978 if (!(fsp->fsp_flags.can_read ||
3979 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3980 (fsp->access_mask & FILE_EXECUTE)))) {
3981 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3982 (int)SVAL(req->vwv+0, 0)));
3983 reply_readbraw_error(xconn);
3984 END_PROFILE(SMBreadbraw);
3988 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3989 if(req->wct == 10) {
3991 * This is a large offset (64 bit) read.
3994 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3997 DEBUG(0,("reply_readbraw: negative 64 bit "
3998 "readraw offset (%.0f) !\n",
3999 (double)startpos ));
4000 reply_readbraw_error(xconn);
4001 END_PROFILE(SMBreadbraw);
4006 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4007 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4009 /* ensure we don't overrun the packet size */
4010 maxcount = MIN(65535,maxcount);
4012 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4013 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4016 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4017 reply_readbraw_error(xconn);
4018 END_PROFILE(SMBreadbraw);
4022 status = vfs_stat_fsp(fsp);
4023 if (NT_STATUS_IS_OK(status)) {
4024 size = fsp->fsp_name->st.st_ex_size;
4027 if (startpos >= size) {
4030 nread = MIN(maxcount,(size - startpos));
4033 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4034 if (nread < mincount)
4038 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4039 "min=%lu nread=%lu\n",
4040 fsp_fnum_dbg(fsp), (double)startpos,
4041 (unsigned long)maxcount,
4042 (unsigned long)mincount,
4043 (unsigned long)nread ) );
4045 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4047 DEBUG(5,("reply_readbraw finished\n"));
4049 END_PROFILE(SMBreadbraw);
4054 #define DBGC_CLASS DBGC_LOCKING
4056 /****************************************************************************
4057 Reply to a lockread (core+ protocol).
4058 ****************************************************************************/
4060 static void reply_lockread_locked(struct tevent_req *subreq);
4062 void reply_lockread(struct smb_request *req)
4064 struct tevent_req *subreq = NULL;
4065 connection_struct *conn = req->conn;
4067 struct smbd_lock_element *lck = NULL;
4069 START_PROFILE(SMBlockread);
4072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4073 END_PROFILE(SMBlockread);
4077 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4079 if (!check_fsp(conn, req, fsp)) {
4080 END_PROFILE(SMBlockread);
4084 if (!CHECK_READ(fsp,req)) {
4085 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4086 END_PROFILE(SMBlockread);
4090 lck = talloc(req, struct smbd_lock_element);
4092 reply_nterror(req, NT_STATUS_NO_MEMORY);
4093 END_PROFILE(SMBlockread);
4098 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4099 * protocol request that predates the read/write lock concept.
4100 * Thus instead of asking for a read lock here we need to ask
4101 * for a write lock. JRA.
4102 * Note that the requested lock size is unaffected by max_send.
4105 *lck = (struct smbd_lock_element) {
4106 .req_guid = smbd_request_guid(req, 0),
4107 .smblctx = req->smbpid,
4108 .brltype = WRITE_LOCK,
4109 .count = SVAL(req->vwv+1, 0),
4110 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4113 subreq = smbd_smb1_do_locks_send(
4119 false, /* large_offset */
4123 if (subreq == NULL) {
4124 reply_nterror(req, NT_STATUS_NO_MEMORY);
4125 END_PROFILE(SMBlockread);
4128 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4129 END_PROFILE(SMBlockread);
4132 static void reply_lockread_locked(struct tevent_req *subreq)
4134 struct smb_request *req = NULL;
4140 size_t numtoread, maxtoread;
4141 struct files_struct *fsp = NULL;
4144 START_PROFILE(SMBlockread);
4146 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4149 status = smbd_smb1_do_locks_recv(subreq);
4150 TALLOC_FREE(subreq);
4152 if (!NT_STATUS_IS_OK(status)) {
4153 reply_nterror(req, status);
4157 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4159 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4163 numtoread = SVAL(req->vwv+1, 0);
4164 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4167 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4169 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4171 if (numtoread > maxtoread) {
4172 DBG_WARNING("requested read size (%zu) is greater than "
4173 "maximum allowed (%zu/%d). "
4174 "Returning short read of maximum allowed for "
4175 "compatibility with Windows 2000.\n",
4178 req->xconn->smb1.sessions.max_send);
4179 numtoread = maxtoread;
4182 reply_outbuf(req, 5, numtoread + 3);
4184 data = smb_buf(req->outbuf) + 3;
4186 nread = read_file(fsp,data,startpos,numtoread);
4189 reply_nterror(req, map_nt_error_from_unix(errno));
4193 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4195 SSVAL(req->outbuf,smb_vwv0,nread);
4196 SSVAL(req->outbuf,smb_vwv5,nread+3);
4197 p = smb_buf(req->outbuf);
4198 SCVAL(p,0,0); /* pad byte. */
4201 DEBUG(3,("lockread %s num=%d nread=%d\n",
4202 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4205 ok = srv_send_smb(req->xconn,
4206 (char *)req->outbuf,
4209 IS_CONN_ENCRYPTED(req->conn),
4212 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4215 END_PROFILE(SMBlockread);
4220 #define DBGC_CLASS DBGC_ALL
4222 /****************************************************************************
4224 ****************************************************************************/
4226 void reply_read(struct smb_request *req)
4228 connection_struct *conn = req->conn;
4235 struct lock_struct lock;
4236 struct smbXsrv_connection *xconn = req->xconn;
4238 START_PROFILE(SMBread);
4241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4242 END_PROFILE(SMBread);
4246 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4248 if (!check_fsp(conn, req, fsp)) {
4249 END_PROFILE(SMBread);
4253 if (!CHECK_READ(fsp,req)) {
4254 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4255 END_PROFILE(SMBread);
4259 numtoread = SVAL(req->vwv+1, 0);
4260 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4263 * The requested read size cannot be greater than max_send. JRA.
4265 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4267 if (numtoread > maxtoread) {
4268 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4269 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4270 (unsigned int)numtoread, (unsigned int)maxtoread,
4271 (unsigned int)xconn->smb1.sessions.max_send));
4272 numtoread = maxtoread;
4275 reply_outbuf(req, 5, numtoread+3);
4277 data = smb_buf(req->outbuf) + 3;
4279 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4280 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4283 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4284 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4285 END_PROFILE(SMBread);
4290 nread = read_file(fsp,data,startpos,numtoread);
4293 reply_nterror(req, map_nt_error_from_unix(errno));
4297 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4299 SSVAL(req->outbuf,smb_vwv0,nread);
4300 SSVAL(req->outbuf,smb_vwv5,nread+3);
4301 SCVAL(smb_buf(req->outbuf),0,1);
4302 SSVAL(smb_buf(req->outbuf),1,nread);
4304 DEBUG(3, ("read %s num=%d nread=%d\n",
4305 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4308 END_PROFILE(SMBread);
4312 /****************************************************************************
4314 ****************************************************************************/
4316 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4320 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4323 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4325 SCVAL(outbuf,smb_vwv0,0xFF);
4326 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4327 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4328 SSVAL(outbuf,smb_vwv6,
4329 (smb_wct - 4) /* offset from smb header to wct */
4330 + 1 /* the wct field */
4331 + 12 * sizeof(uint16_t) /* vwv */
4332 + 2 /* the buflen field */
4333 + 1); /* padding byte */
4334 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4335 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4336 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4337 _smb_setlen_large(outbuf,
4338 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4342 /****************************************************************************
4343 Reply to a read and X - possibly using sendfile.
4344 ****************************************************************************/
4346 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4347 files_struct *fsp, off_t startpos,
4350 struct smbXsrv_connection *xconn = req->xconn;
4352 struct lock_struct lock;
4353 int saved_errno = 0;
4356 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4357 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4360 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4361 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4366 * We can only use sendfile on a non-chained packet
4367 * but we can use on a non-oplocked file. tridge proved this
4368 * on a train in Germany :-). JRA.
4371 if (!req_is_in_chain(req) &&
4373 (fsp->base_fsp == NULL) &&
4374 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4375 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4378 status = vfs_stat_fsp(fsp);
4379 if (!NT_STATUS_IS_OK(status)) {
4380 reply_nterror(req, status);
4384 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4385 (startpos > fsp->fsp_name->st.st_ex_size) ||
4386 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4388 * We already know that we would do a short read, so don't
4389 * try the sendfile() path.
4391 goto nosendfile_read;
4395 * Set up the packet header before send. We
4396 * assume here the sendfile will work (get the
4397 * correct amount of data).
4400 header = data_blob_const(headerbuf, sizeof(headerbuf));
4402 construct_reply_common_req(req, (char *)headerbuf);
4403 setup_readX_header((char *)headerbuf, smb_maxcnt);
4405 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4406 startpos, smb_maxcnt);
4408 saved_errno = errno;
4410 /* Returning ENOSYS means no data at all was sent.
4411 Do this as a normal read. */
4412 if (errno == ENOSYS) {
4417 * Special hack for broken Linux with no working sendfile. If we
4418 * return EINTR we sent the header but not the rest of the data.
4419 * Fake this up by doing read/write calls.
4422 if (errno == EINTR) {
4423 /* Ensure we don't do this again. */
4424 set_use_sendfile(SNUM(conn), False);
4425 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4426 nread = fake_sendfile(xconn, fsp, startpos,
4429 saved_errno = errno;
4430 DEBUG(0,("send_file_readX: "
4431 "fake_sendfile failed for "
4432 "file %s (%s) for client %s. "
4435 smbXsrv_connection_dbg(xconn),
4436 strerror(saved_errno)));
4437 errno = saved_errno;
4438 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4440 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4441 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4442 /* No outbuf here means successful sendfile. */
4446 DEBUG(0,("send_file_readX: sendfile failed for file "
4447 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4449 exit_server_cleanly("send_file_readX sendfile failed");
4450 } else if (nread == 0) {
4452 * Some sendfile implementations return 0 to indicate
4453 * that there was a short read, but nothing was
4454 * actually written to the socket. In this case,
4455 * fallback to the normal read path so the header gets
4456 * the correct byte count.
4458 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4459 "falling back to the normal read: %s\n",
4464 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4465 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4467 /* Deal with possible short send. */
4468 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4471 ret = sendfile_short_send(xconn, fsp, nread,
4472 sizeof(headerbuf), smb_maxcnt);
4475 r = "send_file_readX: sendfile_short_send failed";
4476 DEBUG(0,("%s for file %s (%s).\n",
4477 r, fsp_str_dbg(fsp), strerror(errno)));
4478 exit_server_cleanly(r);
4481 /* No outbuf here means successful sendfile. */
4482 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4483 SMB_PERFCOUNT_END(&req->pcd);
4489 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4490 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4493 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4494 (startpos > fsp->fsp_name->st.st_ex_size) ||
4495 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4497 * We already know that we would do a short
4498 * read, so don't try the sendfile() path.
4500 goto nosendfile_read;
4503 construct_reply_common_req(req, (char *)headerbuf);
4504 setup_readX_header((char *)headerbuf, smb_maxcnt);
4506 /* Send out the header. */
4507 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4509 if (ret != sizeof(headerbuf)) {
4510 saved_errno = errno;
4512 * Try and give an error message saying what
4515 DEBUG(0,("send_file_readX: write_data failed for file "
4516 "%s (%s) for client %s. Terminating\n",
4518 smbXsrv_connection_dbg(xconn),
4519 strerror(saved_errno)));
4520 errno = saved_errno;
4521 exit_server_cleanly("send_file_readX sendfile failed");
4523 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4525 saved_errno = errno;
4526 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4527 "%s (%s) for client %s. Terminating\n",
4529 smbXsrv_connection_dbg(xconn),
4530 strerror(saved_errno)));
4531 errno = saved_errno;
4532 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4539 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4540 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4541 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4543 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4544 startpos, smb_maxcnt);
4545 saved_errno = errno;
4548 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4552 setup_readX_header((char *)req->outbuf, nread);
4554 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4555 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4559 TALLOC_FREE(req->outbuf);
4563 /****************************************************************************
4564 Work out how much space we have for a read return.
4565 ****************************************************************************/
4567 static size_t calc_max_read_pdu(const struct smb_request *req)
4569 struct smbXsrv_connection *xconn = req->xconn;
4571 if (xconn->protocol < PROTOCOL_NT1) {
4572 return xconn->smb1.sessions.max_send;
4575 if (!lp_large_readwrite()) {
4576 return xconn->smb1.sessions.max_send;
4579 if (req_is_in_chain(req)) {
4580 return xconn->smb1.sessions.max_send;
4583 if (req->encrypted) {
4585 * Don't take encrypted traffic up to the
4586 * limit. There are padding considerations
4587 * that make that tricky.
4589 return xconn->smb1.sessions.max_send;
4592 if (srv_is_signing_active(xconn)) {
4596 if (!lp_unix_extensions()) {
4601 * We can do ultra-large POSIX reads.
4606 /****************************************************************************
4607 Calculate how big a read can be. Copes with all clients. It's always
4608 safe to return a short read - Windows does this.
4609 ****************************************************************************/
4611 static size_t calc_read_size(const struct smb_request *req,
4615 struct smbXsrv_connection *xconn = req->xconn;
4616 size_t max_pdu = calc_max_read_pdu(req);
4617 size_t total_size = 0;
4618 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4619 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4622 * Windows explicitly ignores upper size of 0xFFFF.
4623 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4624 * We must do the same as these will never fit even in
4625 * an extended size NetBIOS packet.
4627 if (upper_size == 0xFFFF) {
4631 if (xconn->protocol < PROTOCOL_NT1) {
4635 total_size = ((upper_size<<16) | lower_size);
4638 * LARGE_READX test shows it's always safe to return
4639 * a short read. Windows does so.
4641 return MIN(total_size, max_len);
4644 /****************************************************************************
4645 Reply to a read and X.
4646 ****************************************************************************/
4648 void reply_read_and_X(struct smb_request *req)
4650 connection_struct *conn = req->conn;
4655 bool big_readX = False;
4657 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4660 START_PROFILE(SMBreadX);
4662 if ((req->wct != 10) && (req->wct != 12)) {
4663 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4667 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4668 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4669 smb_maxcnt = SVAL(req->vwv+5, 0);
4671 /* If it's an IPC, pass off the pipe handler. */
4673 reply_pipe_read_and_X(req);
4674 END_PROFILE(SMBreadX);
4678 if (!check_fsp(conn, req, fsp)) {
4679 END_PROFILE(SMBreadX);
4683 if (!CHECK_READ(fsp,req)) {
4684 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4685 END_PROFILE(SMBreadX);
4689 upper_size = SVAL(req->vwv+7, 0);
4690 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4691 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4693 * This is a heuristic to avoid keeping large
4694 * outgoing buffers around over long-lived aio
4700 if (req->wct == 12) {
4702 * This is a large offset (64 bit) read.
4704 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4709 NTSTATUS status = schedule_aio_read_and_X(conn,
4714 if (NT_STATUS_IS_OK(status)) {
4715 /* Read scheduled - we're done. */
4718 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4719 /* Real error - report to client. */
4720 END_PROFILE(SMBreadX);
4721 reply_nterror(req, status);
4724 /* NT_STATUS_RETRY - fall back to sync read. */
4727 smbd_lock_socket(req->xconn);
4728 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4729 smbd_unlock_socket(req->xconn);
4732 END_PROFILE(SMBreadX);
4736 /****************************************************************************
4737 Error replies to writebraw must have smb_wct == 1. Fix this up.
4738 ****************************************************************************/
4740 void error_to_writebrawerr(struct smb_request *req)
4742 uint8_t *old_outbuf = req->outbuf;
4744 reply_outbuf(req, 1, 0);
4746 memcpy(req->outbuf, old_outbuf, smb_size);
4747 TALLOC_FREE(old_outbuf);
4750 /****************************************************************************
4751 Read 4 bytes of a smb packet and return the smb length of the packet.
4752 Store the result in the buffer. This version of the function will
4753 never return a session keepalive (length of zero).
4754 Timeout is in milliseconds.
4755 ****************************************************************************/
4757 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4760 uint8_t msgtype = NBSSkeepalive;
4762 while (msgtype == NBSSkeepalive) {
4765 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4767 if (!NT_STATUS_IS_OK(status)) {
4768 char addr[INET6_ADDRSTRLEN];
4769 /* Try and give an error message
4770 * saying what client failed. */
4771 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4772 "client %s read error = %s.\n",
4773 get_peer_addr(fd,addr,sizeof(addr)),
4774 nt_errstr(status)));
4778 msgtype = CVAL(inbuf, 0);
4781 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4782 (unsigned long)len));
4784 return NT_STATUS_OK;
4787 /****************************************************************************
4788 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4789 ****************************************************************************/
4791 void reply_writebraw(struct smb_request *req)
4793 connection_struct *conn = req->conn;
4794 struct smbXsrv_connection *xconn = req->xconn;
4797 ssize_t total_written=0;
4798 size_t numtowrite=0;
4801 const char *data=NULL;
4804 struct lock_struct lock;
4807 START_PROFILE(SMBwritebraw);
4810 * If we ever reply with an error, it must have the SMB command
4811 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4814 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4816 if (srv_is_signing_active(xconn)) {
4817 END_PROFILE(SMBwritebraw);
4818 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4819 "raw reads/writes are disallowed.");
4822 if (req->wct < 12) {
4823 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4824 error_to_writebrawerr(req);
4825 END_PROFILE(SMBwritebraw);
4829 if (xconn->smb1.echo_handler.trusted_fde) {
4830 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4831 "'async smb echo handler = yes'\n"));
4832 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4833 error_to_writebrawerr(req);
4834 END_PROFILE(SMBwritebraw);
4838 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4839 if (!check_fsp(conn, req, fsp)) {
4840 error_to_writebrawerr(req);
4841 END_PROFILE(SMBwritebraw);
4845 if (!CHECK_WRITE(fsp)) {
4846 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4847 error_to_writebrawerr(req);
4848 END_PROFILE(SMBwritebraw);
4852 tcount = IVAL(req->vwv+1, 0);
4853 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4854 write_through = BITSETW(req->vwv+7,0);
4856 /* We have to deal with slightly different formats depending
4857 on whether we are using the core+ or lanman1.0 protocol */
4859 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4860 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4861 data = smb_buf_const(req->inbuf);
4863 numtowrite = SVAL(req->vwv+10, 0);
4864 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4867 /* Ensure we don't write bytes past the end of this packet. */
4869 * This already protects us against CVE-2017-12163.
4871 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4873 error_to_writebrawerr(req);
4874 END_PROFILE(SMBwritebraw);
4878 if (!fsp->print_file) {
4879 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4880 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4883 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4884 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4885 error_to_writebrawerr(req);
4886 END_PROFILE(SMBwritebraw);
4892 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4895 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4896 "wrote=%d sync=%d\n",
4897 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4898 (int)nwritten, (int)write_through));
4900 if (nwritten < (ssize_t)numtowrite) {
4901 reply_nterror(req, NT_STATUS_DISK_FULL);
4902 error_to_writebrawerr(req);
4906 total_written = nwritten;
4908 /* Allocate a buffer of 64k + length. */
4909 buf = talloc_array(NULL, char, 65540);
4911 reply_nterror(req, NT_STATUS_NO_MEMORY);
4912 error_to_writebrawerr(req);
4916 /* Return a SMBwritebraw message to the redirector to tell
4917 * it to send more bytes */
4919 memcpy(buf, req->inbuf, smb_size);
4920 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4921 SCVAL(buf,smb_com,SMBwritebraw);
4922 SSVALS(buf,smb_vwv0,0xFFFF);
4924 if (!srv_send_smb(req->xconn,
4926 false, 0, /* no signing */
4927 IS_CONN_ENCRYPTED(conn),
4929 exit_server_cleanly("reply_writebraw: srv_send_smb "
4933 /* Now read the raw data into the buffer and write it */
4934 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4936 if (!NT_STATUS_IS_OK(status)) {
4937 exit_server_cleanly("secondary writebraw failed");
4940 /* Set up outbuf to return the correct size */
4941 reply_outbuf(req, 1, 0);
4943 if (numtowrite != 0) {
4945 if (numtowrite > 0xFFFF) {
4946 DEBUG(0,("reply_writebraw: Oversize secondary write "
4947 "raw requested (%u). Terminating\n",
4948 (unsigned int)numtowrite ));
4949 exit_server_cleanly("secondary writebraw failed");
4952 if (tcount > nwritten+numtowrite) {
4953 DEBUG(3,("reply_writebraw: Client overestimated the "
4955 (int)tcount,(int)nwritten,(int)numtowrite));
4958 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4961 if (!NT_STATUS_IS_OK(status)) {
4962 /* Try and give an error message
4963 * saying what client failed. */
4964 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4965 "raw read failed (%s) for client %s. "
4966 "Terminating\n", nt_errstr(status),
4967 smbXsrv_connection_dbg(xconn)));
4968 exit_server_cleanly("secondary writebraw failed");
4972 * We are not vulnerable to CVE-2017-12163
4973 * here as we are guaranteed to have numtowrite
4974 * bytes available - we just read from the client.
4976 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4977 if (nwritten == -1) {
4979 reply_nterror(req, map_nt_error_from_unix(errno));
4980 error_to_writebrawerr(req);
4984 if (nwritten < (ssize_t)numtowrite) {
4985 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4986 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4990 total_written += nwritten;
4995 SSVAL(req->outbuf,smb_vwv0,total_written);
4997 status = sync_file(conn, fsp, write_through);
4998 if (!NT_STATUS_IS_OK(status)) {
4999 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5000 fsp_str_dbg(fsp), nt_errstr(status)));
5001 reply_nterror(req, status);
5002 error_to_writebrawerr(req);
5006 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5008 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5009 (int)total_written));
5011 /* We won't return a status if write through is not selected - this
5012 * follows what WfWg does */
5013 END_PROFILE(SMBwritebraw);
5015 if (!write_through && total_written==tcount) {
5017 #if RABBIT_PELLET_FIX
5019 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5020 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5023 if (!send_keepalive(xconn->transport.sock)) {
5024 exit_server_cleanly("reply_writebraw: send of "
5025 "keepalive failed");
5028 TALLOC_FREE(req->outbuf);
5033 END_PROFILE(SMBwritebraw);
5038 #define DBGC_CLASS DBGC_LOCKING
5040 /****************************************************************************
5041 Reply to a writeunlock (core+).
5042 ****************************************************************************/
5044 void reply_writeunlock(struct smb_request *req)
5046 connection_struct *conn = req->conn;
5047 ssize_t nwritten = -1;
5052 NTSTATUS status = NT_STATUS_OK;
5054 struct lock_struct lock;
5055 int saved_errno = 0;
5057 START_PROFILE(SMBwriteunlock);
5060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5061 END_PROFILE(SMBwriteunlock);
5065 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5067 if (!check_fsp(conn, req, fsp)) {
5068 END_PROFILE(SMBwriteunlock);
5072 if (!CHECK_WRITE(fsp)) {
5073 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5074 END_PROFILE(SMBwriteunlock);
5078 numtowrite = SVAL(req->vwv+1, 0);
5079 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5080 data = (const char *)req->buf + 3;
5083 * Ensure client isn't asking us to write more than
5084 * they sent. CVE-2017-12163.
5086 remaining = smbreq_bufrem(req, data);
5087 if (numtowrite > remaining) {
5088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5089 END_PROFILE(SMBwriteunlock);
5093 if (!fsp->print_file && numtowrite > 0) {
5094 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5095 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5098 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5099 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5100 END_PROFILE(SMBwriteunlock);
5105 /* The special X/Open SMB protocol handling of
5106 zero length writes is *NOT* done for
5108 if(numtowrite == 0) {
5111 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5112 saved_errno = errno;
5115 status = sync_file(conn, fsp, False /* write through */);
5116 if (!NT_STATUS_IS_OK(status)) {
5117 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5118 fsp_str_dbg(fsp), nt_errstr(status)));
5119 reply_nterror(req, status);
5124 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5128 if((nwritten < numtowrite) && (numtowrite != 0)) {
5129 reply_nterror(req, NT_STATUS_DISK_FULL);
5133 if (numtowrite && !fsp->print_file) {
5134 struct smbd_lock_element l = {
5135 .req_guid = smbd_request_guid(req, 0),
5136 .smblctx = req->smbpid,
5137 .brltype = UNLOCK_LOCK,
5139 .count = numtowrite,
5141 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5142 if (NT_STATUS_V(status)) {
5143 reply_nterror(req, status);
5148 reply_outbuf(req, 1, 0);
5150 SSVAL(req->outbuf,smb_vwv0,nwritten);
5152 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5153 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5156 END_PROFILE(SMBwriteunlock);
5161 #define DBGC_CLASS DBGC_ALL
5163 /****************************************************************************
5165 ****************************************************************************/
5167 void reply_write(struct smb_request *req)
5169 connection_struct *conn = req->conn;
5172 ssize_t nwritten = -1;
5176 struct lock_struct lock;
5178 int saved_errno = 0;
5180 START_PROFILE(SMBwrite);
5183 END_PROFILE(SMBwrite);
5184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5188 /* If it's an IPC, pass off the pipe handler. */
5190 reply_pipe_write(req);
5191 END_PROFILE(SMBwrite);
5195 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5197 if (!check_fsp(conn, req, fsp)) {
5198 END_PROFILE(SMBwrite);
5202 if (!CHECK_WRITE(fsp)) {
5203 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5204 END_PROFILE(SMBwrite);
5208 numtowrite = SVAL(req->vwv+1, 0);
5209 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5210 data = (const char *)req->buf + 3;
5213 * Ensure client isn't asking us to write more than
5214 * they sent. CVE-2017-12163.
5216 remaining = smbreq_bufrem(req, data);
5217 if (numtowrite > remaining) {
5218 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5219 END_PROFILE(SMBwrite);
5223 if (!fsp->print_file) {
5224 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5225 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5228 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5229 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5230 END_PROFILE(SMBwrite);
5236 * X/Open SMB protocol says that if smb_vwv1 is
5237 * zero then the file size should be extended or
5238 * truncated to the size given in smb_vwv[2-3].
5241 if(numtowrite == 0) {
5243 * This is actually an allocate call, and set EOF. JRA.
5245 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5247 reply_nterror(req, NT_STATUS_DISK_FULL);
5250 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5252 reply_nterror(req, NT_STATUS_DISK_FULL);
5255 trigger_write_time_update_immediate(fsp);
5257 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5260 status = sync_file(conn, fsp, False);
5261 if (!NT_STATUS_IS_OK(status)) {
5262 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5263 fsp_str_dbg(fsp), nt_errstr(status)));
5264 reply_nterror(req, status);
5269 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5273 if((nwritten == 0) && (numtowrite != 0)) {
5274 reply_nterror(req, NT_STATUS_DISK_FULL);
5278 reply_outbuf(req, 1, 0);
5280 SSVAL(req->outbuf,smb_vwv0,nwritten);
5282 if (nwritten < (ssize_t)numtowrite) {
5283 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5284 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5287 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5290 END_PROFILE(SMBwrite);
5294 /****************************************************************************
5295 Ensure a buffer is a valid writeX for recvfile purposes.
5296 ****************************************************************************/
5298 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5299 (2*14) + /* word count (including bcc) */ \
5302 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5303 const uint8_t *inbuf)
5306 unsigned int doff = 0;
5307 size_t len = smb_len_large(inbuf);
5309 struct smbXsrv_open *op = NULL;
5310 struct files_struct *fsp = NULL;
5313 if (is_encrypted_packet(inbuf)) {
5314 /* Can't do this on encrypted
5319 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5323 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5324 CVAL(inbuf,smb_wct) != 14) {
5325 DEBUG(10,("is_valid_writeX_buffer: chained or "
5326 "invalid word length.\n"));
5330 fnum = SVAL(inbuf, smb_vwv2);
5331 status = smb1srv_open_lookup(xconn,
5335 if (!NT_STATUS_IS_OK(status)) {
5336 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5341 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5344 if (fsp->conn == NULL) {
5345 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5349 if (IS_IPC(fsp->conn)) {
5350 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5353 if (IS_PRINT(fsp->conn)) {
5354 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5357 if (fsp->base_fsp != NULL) {
5358 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5361 doff = SVAL(inbuf,smb_vwv11);
5363 numtowrite = SVAL(inbuf,smb_vwv10);
5365 if (len > doff && len - doff > 0xFFFF) {
5366 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5369 if (numtowrite == 0) {
5370 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5374 /* Ensure the sizes match up. */
5375 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5376 /* no pad byte...old smbclient :-( */
5377 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5379 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5383 if (len - doff != numtowrite) {
5384 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5385 "len = %u, doff = %u, numtowrite = %u\n",
5388 (unsigned int)numtowrite ));
5392 DEBUG(10,("is_valid_writeX_buffer: true "
5393 "len = %u, doff = %u, numtowrite = %u\n",
5396 (unsigned int)numtowrite ));
5401 /****************************************************************************
5402 Reply to a write and X.
5403 ****************************************************************************/
5405 void reply_write_and_X(struct smb_request *req)
5407 connection_struct *conn = req->conn;
5408 struct smbXsrv_connection *xconn = req->xconn;
5410 struct lock_struct lock;
5415 unsigned int smb_doff;
5416 unsigned int smblen;
5419 int saved_errno = 0;
5421 START_PROFILE(SMBwriteX);
5423 if ((req->wct != 12) && (req->wct != 14)) {
5424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5428 numtowrite = SVAL(req->vwv+10, 0);
5429 smb_doff = SVAL(req->vwv+11, 0);
5430 smblen = smb_len(req->inbuf);
5432 if (req->unread_bytes > 0xFFFF ||
5433 (smblen > smb_doff &&
5434 smblen - smb_doff > 0xFFFF)) {
5435 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5438 if (req->unread_bytes) {
5439 /* Can't do a recvfile write on IPC$ */
5441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5444 if (numtowrite != req->unread_bytes) {
5445 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5450 * This already protects us against CVE-2017-12163.
5452 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5453 smb_doff + numtowrite > smblen) {
5454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5459 /* If it's an IPC, pass off the pipe handler. */
5461 if (req->unread_bytes) {
5462 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5465 reply_pipe_write_and_X(req);
5469 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5470 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5471 write_through = BITSETW(req->vwv+7,0);
5473 if (!check_fsp(conn, req, fsp)) {
5477 if (!CHECK_WRITE(fsp)) {
5478 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5482 data = smb_base(req->inbuf) + smb_doff;
5484 if(req->wct == 14) {
5486 * This is a large offset (64 bit) write.
5488 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5492 /* X/Open SMB protocol says that, unlike SMBwrite
5493 if the length is zero then NO truncation is
5494 done, just a write of zero. To truncate a file,
5497 if(numtowrite == 0) {
5500 if (req->unread_bytes == 0) {
5501 status = schedule_aio_write_and_X(conn,
5508 if (NT_STATUS_IS_OK(status)) {
5509 /* write scheduled - we're done. */
5512 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5513 /* Real error - report to client. */
5514 reply_nterror(req, status);
5517 /* NT_STATUS_RETRY - fall through to sync write. */
5520 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5521 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5524 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5525 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5529 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5530 saved_errno = errno;
5534 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5538 if((nwritten == 0) && (numtowrite != 0)) {
5539 reply_nterror(req, NT_STATUS_DISK_FULL);
5543 reply_outbuf(req, 6, 0);
5544 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5545 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5546 SSVAL(req->outbuf,smb_vwv2,nwritten);
5547 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5549 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5550 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5552 status = sync_file(conn, fsp, write_through);
5553 if (!NT_STATUS_IS_OK(status)) {
5554 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5555 fsp_str_dbg(fsp), nt_errstr(status)));
5556 reply_nterror(req, status);
5560 END_PROFILE(SMBwriteX);
5564 if (req->unread_bytes) {
5565 /* writeX failed. drain socket. */
5566 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5567 req->unread_bytes) {
5568 smb_panic("failed to drain pending bytes");
5570 req->unread_bytes = 0;
5573 END_PROFILE(SMBwriteX);
5577 /****************************************************************************
5579 ****************************************************************************/
5581 void reply_lseek(struct smb_request *req)
5583 connection_struct *conn = req->conn;
5590 START_PROFILE(SMBlseek);
5593 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5594 END_PROFILE(SMBlseek);
5598 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5600 if (!check_fsp(conn, req, fsp)) {
5604 mode = SVAL(req->vwv+1, 0) & 3;
5605 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5606 startpos = (off_t)IVALS(req->vwv+2, 0);
5615 res = fsp->fh->pos + startpos;
5626 if (umode == SEEK_END) {
5627 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5628 if(errno == EINVAL) {
5629 off_t current_pos = startpos;
5631 status = vfs_stat_fsp(fsp);
5632 if (!NT_STATUS_IS_OK(status)) {
5633 reply_nterror(req, status);
5634 END_PROFILE(SMBlseek);
5638 current_pos += fsp->fsp_name->st.st_ex_size;
5640 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5645 reply_nterror(req, map_nt_error_from_unix(errno));
5646 END_PROFILE(SMBlseek);
5653 reply_outbuf(req, 2, 0);
5654 SIVAL(req->outbuf,smb_vwv0,res);
5656 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5657 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5659 END_PROFILE(SMBlseek);
5663 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5666 connection_struct *conn = talloc_get_type_abort(
5667 private_data, connection_struct);
5669 if (conn != fsp->conn) {
5672 if (fsp_get_io_fd(fsp) == -1) {
5675 sync_file(conn, fsp, True /* write through */);
5677 if (fsp->fsp_flags.modified) {
5678 trigger_write_time_update_immediate(fsp);
5684 /****************************************************************************
5686 ****************************************************************************/
5688 void reply_flush(struct smb_request *req)
5690 connection_struct *conn = req->conn;
5694 START_PROFILE(SMBflush);
5697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5701 fnum = SVAL(req->vwv+0, 0);
5702 fsp = file_fsp(req, fnum);
5704 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5709 files_forall(req->sconn, file_sync_one_fn, conn);
5711 NTSTATUS status = sync_file(conn, fsp, True);
5712 if (!NT_STATUS_IS_OK(status)) {
5713 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5714 fsp_str_dbg(fsp), nt_errstr(status)));
5715 reply_nterror(req, status);
5716 END_PROFILE(SMBflush);
5719 if (fsp->fsp_flags.modified) {
5720 trigger_write_time_update_immediate(fsp);
5724 reply_outbuf(req, 0, 0);
5726 DEBUG(3,("flush\n"));
5727 END_PROFILE(SMBflush);
5731 /****************************************************************************
5733 conn POINTER CAN BE NULL HERE !
5734 ****************************************************************************/
5736 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5737 static void reply_exit_done(struct tevent_req *req);
5739 void reply_exit(struct smb_request *smb1req)
5741 struct tevent_req *req;
5744 * Don't setup the profile charge here, take
5745 * it in reply_exit_done(). Not strictly correct
5746 * but better than the other SMB1 async
5747 * code that double-charges at the moment.
5749 req = reply_exit_send(smb1req);
5751 /* Not going async, profile here. */
5752 START_PROFILE(SMBexit);
5753 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5754 END_PROFILE(SMBexit);
5758 /* We're async. This will complete later. */
5759 tevent_req_set_callback(req, reply_exit_done, smb1req);
5763 struct reply_exit_state {
5764 struct tevent_queue *wait_queue;
5767 static void reply_exit_wait_done(struct tevent_req *subreq);
5769 /****************************************************************************
5771 Note, on failure here we deallocate and return NULL to allow the caller to
5772 SMB1 return an error of ERRnomem immediately.
5773 ****************************************************************************/
5775 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5777 struct tevent_req *req;
5778 struct reply_exit_state *state;
5779 struct tevent_req *subreq;
5781 struct smbd_server_connection *sconn = smb1req->sconn;
5783 req = tevent_req_create(smb1req, &state,
5784 struct reply_exit_state);
5788 state->wait_queue = tevent_queue_create(state,
5789 "reply_exit_wait_queue");
5790 if (tevent_req_nomem(state->wait_queue, req)) {
5795 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5796 if (fsp->file_pid != smb1req->smbpid) {
5799 if (fsp->vuid != smb1req->vuid) {
5803 * Flag the file as close in progress.
5804 * This will prevent any more IO being
5807 fsp->fsp_flags.closing = true;
5809 if (fsp->num_aio_requests > 0) {
5811 * Now wait until all aio requests on this fsp are
5814 * We don't set a callback, as we just want to block the
5815 * wait queue and the talloc_free() of fsp->aio_request
5816 * will remove the item from the wait queue.
5818 subreq = tevent_queue_wait_send(fsp->aio_requests,
5821 if (tevent_req_nomem(subreq, req)) {
5829 * Now we add our own waiter to the end of the queue,
5830 * this way we get notified when all pending requests are finished
5831 * and reply to the outstanding SMB1 request.
5833 subreq = tevent_queue_wait_send(state,
5836 if (tevent_req_nomem(subreq, req)) {
5842 * We're really going async - move the SMB1 request from
5843 * a talloc stackframe above us to the conn talloc-context.
5844 * We need this to stick around until the wait_done
5845 * callback is invoked.
5847 smb1req = talloc_move(sconn, &smb1req);
5849 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5854 static void reply_exit_wait_done(struct tevent_req *subreq)
5856 struct tevent_req *req = tevent_req_callback_data(
5857 subreq, struct tevent_req);
5859 tevent_queue_wait_recv(subreq);
5860 TALLOC_FREE(subreq);
5861 tevent_req_done(req);
5864 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5866 return tevent_req_simple_recv_ntstatus(req);
5869 static void reply_exit_done(struct tevent_req *req)
5871 struct smb_request *smb1req = tevent_req_callback_data(
5872 req, struct smb_request);
5873 struct smbd_server_connection *sconn = smb1req->sconn;
5874 struct smbXsrv_connection *xconn = smb1req->xconn;
5875 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5876 struct smbXsrv_session *session = NULL;
5877 files_struct *fsp, *next;
5881 * Take the profile charge here. Not strictly
5882 * correct but better than the other SMB1 async
5883 * code that double-charges at the moment.
5885 START_PROFILE(SMBexit);
5887 status = reply_exit_recv(req);
5889 if (!NT_STATUS_IS_OK(status)) {
5890 TALLOC_FREE(smb1req);
5891 END_PROFILE(SMBexit);
5892 exit_server(__location__ ": reply_exit_recv failed");
5897 * Ensure the session is still valid.
5899 status = smb1srv_session_lookup(xconn,
5903 if (!NT_STATUS_IS_OK(status)) {
5904 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5905 smb_request_done(smb1req);
5906 END_PROFILE(SMBexit);
5910 * Ensure the vuid is still valid - no one
5911 * called reply_ulogoffX() in the meantime.
5912 * reply_exit() doesn't have AS_USER set, so
5913 * use set_current_user_info() directly.
5914 * This is the same logic as in switch_message().
5916 if (session->global->auth_session_info != NULL) {
5917 set_current_user_info(
5918 session->global->auth_session_info->unix_info->sanitized_username,
5919 session->global->auth_session_info->unix_info->unix_name,
5920 session->global->auth_session_info->info->domain_name);
5923 /* No more aio - do the actual closes. */
5924 for (fsp = sconn->files; fsp; fsp = next) {
5928 if (fsp->file_pid != smb1req->smbpid) {
5931 if (fsp->vuid != smb1req->vuid) {
5934 if (!fsp->fsp_flags.closing) {
5939 * reply_exit() has the DO_CHDIR flag set.
5941 ok = chdir_current_service(fsp->conn);
5943 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5944 smb_request_done(smb1req);
5945 END_PROFILE(SMBexit);
5947 close_file(NULL, fsp, SHUTDOWN_CLOSE);
5950 reply_outbuf(smb1req, 0, 0);
5952 * The following call is needed to push the
5953 * reply data back out the socket after async
5954 * return. Plus it frees smb1req.
5956 smb_request_done(smb1req);
5957 DBG_INFO("reply_exit complete\n");
5958 END_PROFILE(SMBexit);
5962 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5964 static void reply_close_done(struct tevent_req *req);
5966 void reply_close(struct smb_request *smb1req)
5968 connection_struct *conn = smb1req->conn;
5969 NTSTATUS status = NT_STATUS_OK;
5970 files_struct *fsp = NULL;
5971 START_PROFILE(SMBclose);
5973 if (smb1req->wct < 3) {
5974 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5975 END_PROFILE(SMBclose);
5979 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5982 * We can only use check_fsp if we know it's not a directory.
5985 if (!check_fsp_open(conn, smb1req, fsp)) {
5986 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
5987 END_PROFILE(SMBclose);
5991 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5992 fsp->fsp_flags.is_directory ?
5993 "directory" : "file",
5994 fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
5995 conn->num_files_open);
5997 if (!fsp->fsp_flags.is_directory) {
6001 * Take care of any time sent in the close.
6004 t = srv_make_unix_date3(smb1req->vwv+1);
6005 set_close_write_time(fsp, time_t_to_full_timespec(t));
6008 if (fsp->num_aio_requests != 0) {
6009 struct tevent_req *req;
6011 req = reply_close_send(smb1req, fsp);
6013 status = NT_STATUS_NO_MEMORY;
6016 /* We're async. This will complete later. */
6017 tevent_req_set_callback(req, reply_close_done, smb1req);
6018 END_PROFILE(SMBclose);
6023 * close_file() returns the unix errno if an error was detected on
6024 * close - normally this is due to a disk full error. If not then it
6025 * was probably an I/O error.
6028 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6030 if (!NT_STATUS_IS_OK(status)) {
6031 reply_nterror(smb1req, status);
6032 END_PROFILE(SMBclose);
6036 reply_outbuf(smb1req, 0, 0);
6037 END_PROFILE(SMBclose);
6041 struct reply_close_state {
6043 struct tevent_queue *wait_queue;
6046 static void reply_close_wait_done(struct tevent_req *subreq);
6048 /****************************************************************************
6050 Note, on failure here we deallocate and return NULL to allow the caller to
6051 SMB1 return an error of ERRnomem immediately.
6052 ****************************************************************************/
6054 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6057 struct tevent_req *req;
6058 struct reply_close_state *state;
6059 struct tevent_req *subreq;
6060 struct smbd_server_connection *sconn = smb1req->sconn;
6062 req = tevent_req_create(smb1req, &state,
6063 struct reply_close_state);
6067 state->wait_queue = tevent_queue_create(state,
6068 "reply_close_wait_queue");
6069 if (tevent_req_nomem(state->wait_queue, req)) {
6075 * Flag the file as close in progress.
6076 * This will prevent any more IO being
6079 fsp->fsp_flags.closing = true;
6082 * Now wait until all aio requests on this fsp are
6085 * We don't set a callback, as we just want to block the
6086 * wait queue and the talloc_free() of fsp->aio_request
6087 * will remove the item from the wait queue.
6089 subreq = tevent_queue_wait_send(fsp->aio_requests,
6092 if (tevent_req_nomem(subreq, req)) {
6098 * Now we add our own waiter to the end of the queue,
6099 * this way we get notified when all pending requests are finished
6100 * and reply to the outstanding SMB1 request.
6102 subreq = tevent_queue_wait_send(state,
6105 if (tevent_req_nomem(subreq, req)) {
6111 * We're really going async - move the SMB1 request from
6112 * a talloc stackframe above us to the conn talloc-context.
6113 * We need this to stick around until the wait_done
6114 * callback is invoked.
6116 smb1req = talloc_move(sconn, &smb1req);
6118 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6123 static void reply_close_wait_done(struct tevent_req *subreq)
6125 struct tevent_req *req = tevent_req_callback_data(
6126 subreq, struct tevent_req);
6128 tevent_queue_wait_recv(subreq);
6129 TALLOC_FREE(subreq);
6130 tevent_req_done(req);
6133 static NTSTATUS reply_close_recv(struct tevent_req *req)
6135 return tevent_req_simple_recv_ntstatus(req);
6138 static void reply_close_done(struct tevent_req *req)
6140 struct smb_request *smb1req = tevent_req_callback_data(
6141 req, struct smb_request);
6142 struct reply_close_state *state = tevent_req_data(req,
6143 struct reply_close_state);
6146 status = reply_close_recv(req);
6148 if (!NT_STATUS_IS_OK(status)) {
6149 TALLOC_FREE(smb1req);
6150 exit_server(__location__ ": reply_close_recv failed");
6154 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6155 if (NT_STATUS_IS_OK(status)) {
6156 reply_outbuf(smb1req, 0, 0);
6158 reply_nterror(smb1req, status);
6161 * The following call is needed to push the
6162 * reply data back out the socket after async
6163 * return. Plus it frees smb1req.
6165 smb_request_done(smb1req);
6168 /****************************************************************************
6169 Reply to a writeclose (Core+ protocol).
6170 ****************************************************************************/
6172 void reply_writeclose(struct smb_request *req)
6174 connection_struct *conn = req->conn;
6177 ssize_t nwritten = -1;
6178 NTSTATUS close_status = NT_STATUS_OK;
6181 struct timespec mtime;
6183 struct lock_struct lock;
6185 START_PROFILE(SMBwriteclose);
6188 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6189 END_PROFILE(SMBwriteclose);
6193 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6195 if (!check_fsp(conn, req, fsp)) {
6196 END_PROFILE(SMBwriteclose);
6199 if (!CHECK_WRITE(fsp)) {
6200 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6201 END_PROFILE(SMBwriteclose);
6205 numtowrite = SVAL(req->vwv+1, 0);
6206 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6207 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6208 data = (const char *)req->buf + 1;
6211 * Ensure client isn't asking us to write more than
6212 * they sent. CVE-2017-12163.
6214 remaining = smbreq_bufrem(req, data);
6215 if (numtowrite > remaining) {
6216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6217 END_PROFILE(SMBwriteclose);
6221 if (fsp->print_file == NULL) {
6222 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6223 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6226 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6227 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6228 END_PROFILE(SMBwriteclose);
6233 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6235 set_close_write_time(fsp, mtime);
6238 * More insanity. W2K only closes the file if writelen > 0.
6242 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6243 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6244 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6247 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6248 "file %s\n", fsp_str_dbg(fsp)));
6249 close_status = close_file(req, fsp, NORMAL_CLOSE);
6253 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6254 reply_nterror(req, NT_STATUS_DISK_FULL);
6258 if(!NT_STATUS_IS_OK(close_status)) {
6259 reply_nterror(req, close_status);
6263 reply_outbuf(req, 1, 0);
6265 SSVAL(req->outbuf,smb_vwv0,nwritten);
6269 END_PROFILE(SMBwriteclose);
6274 #define DBGC_CLASS DBGC_LOCKING
6276 /****************************************************************************
6278 ****************************************************************************/
6280 static void reply_lock_done(struct tevent_req *subreq);
6282 void reply_lock(struct smb_request *req)
6284 struct tevent_req *subreq = NULL;
6285 connection_struct *conn = req->conn;
6287 struct smbd_lock_element *lck = NULL;
6289 START_PROFILE(SMBlock);
6292 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6293 END_PROFILE(SMBlock);
6297 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6299 if (!check_fsp(conn, req, fsp)) {
6300 END_PROFILE(SMBlock);
6304 lck = talloc(req, struct smbd_lock_element);
6306 reply_nterror(req, NT_STATUS_NO_MEMORY);
6307 END_PROFILE(SMBlock);
6311 *lck = (struct smbd_lock_element) {
6312 .req_guid = smbd_request_guid(req, 0),
6313 .smblctx = req->smbpid,
6314 .brltype = WRITE_LOCK,
6315 .count = IVAL(req->vwv+1, 0),
6316 .offset = IVAL(req->vwv+3, 0),
6319 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6325 subreq = smbd_smb1_do_locks_send(
6331 false, /* large_offset */
6335 if (subreq == NULL) {
6336 reply_nterror(req, NT_STATUS_NO_MEMORY);
6337 END_PROFILE(SMBlock);
6340 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6341 END_PROFILE(SMBlock);
6344 static void reply_lock_done(struct tevent_req *subreq)
6346 struct smb_request *req = NULL;
6350 START_PROFILE(SMBlock);
6352 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6355 status = smbd_smb1_do_locks_recv(subreq);
6356 TALLOC_FREE(subreq);
6358 if (NT_STATUS_IS_OK(status)) {
6359 reply_outbuf(req, 0, 0);
6361 reply_nterror(req, status);
6364 ok = srv_send_smb(req->xconn,
6365 (char *)req->outbuf,
6368 IS_CONN_ENCRYPTED(req->conn),
6371 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6374 END_PROFILE(SMBlock);
6377 /****************************************************************************
6379 ****************************************************************************/
6381 void reply_unlock(struct smb_request *req)
6383 connection_struct *conn = req->conn;
6386 struct smbd_lock_element lck;
6388 START_PROFILE(SMBunlock);
6391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6392 END_PROFILE(SMBunlock);
6396 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6398 if (!check_fsp(conn, req, fsp)) {
6399 END_PROFILE(SMBunlock);
6403 lck = (struct smbd_lock_element) {
6404 .req_guid = smbd_request_guid(req, 0),
6405 .smblctx = req->smbpid,
6406 .brltype = UNLOCK_LOCK,
6407 .offset = IVAL(req->vwv+3, 0),
6408 .count = IVAL(req->vwv+1, 0),
6411 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6413 if (!NT_STATUS_IS_OK(status)) {
6414 reply_nterror(req, status);
6415 END_PROFILE(SMBunlock);
6419 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6425 reply_outbuf(req, 0, 0);
6427 END_PROFILE(SMBunlock);
6432 #define DBGC_CLASS DBGC_ALL
6434 /****************************************************************************
6436 conn POINTER CAN BE NULL HERE !
6437 ****************************************************************************/
6439 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6440 static void reply_tdis_done(struct tevent_req *req);
6442 void reply_tdis(struct smb_request *smb1req)
6444 connection_struct *conn = smb1req->conn;
6445 struct tevent_req *req;
6448 * Don't setup the profile charge here, take
6449 * it in reply_tdis_done(). Not strictly correct
6450 * but better than the other SMB1 async
6451 * code that double-charges at the moment.
6455 /* Not going async, profile here. */
6456 START_PROFILE(SMBtdis);
6457 DBG_INFO("Invalid connection in tdis\n");
6458 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6459 END_PROFILE(SMBtdis);
6463 req = reply_tdis_send(smb1req);
6465 /* Not going async, profile here. */
6466 START_PROFILE(SMBtdis);
6467 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6468 END_PROFILE(SMBtdis);
6471 /* We're async. This will complete later. */
6472 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6476 struct reply_tdis_state {
6477 struct tevent_queue *wait_queue;
6480 static void reply_tdis_wait_done(struct tevent_req *subreq);
6482 /****************************************************************************
6484 Note, on failure here we deallocate and return NULL to allow the caller to
6485 SMB1 return an error of ERRnomem immediately.
6486 ****************************************************************************/
6488 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6490 struct tevent_req *req;
6491 struct reply_tdis_state *state;
6492 struct tevent_req *subreq;
6493 connection_struct *conn = smb1req->conn;
6496 req = tevent_req_create(smb1req, &state,
6497 struct reply_tdis_state);
6501 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6502 if (tevent_req_nomem(state->wait_queue, req)) {
6508 * Make sure that no new request will be able to use this tcon.
6509 * This ensures that once all outstanding fsp->aio_requests
6510 * on this tcon are done, we are safe to close it.
6512 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6514 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6515 if (fsp->conn != conn) {
6519 * Flag the file as close in progress.
6520 * This will prevent any more IO being
6521 * done on it. Not strictly needed, but
6522 * doesn't hurt to flag it as closing.
6524 fsp->fsp_flags.closing = true;
6526 if (fsp->num_aio_requests > 0) {
6528 * Now wait until all aio requests on this fsp are
6531 * We don't set a callback, as we just want to block the
6532 * wait queue and the talloc_free() of fsp->aio_request
6533 * will remove the item from the wait queue.
6535 subreq = tevent_queue_wait_send(fsp->aio_requests,
6536 conn->sconn->ev_ctx,
6538 if (tevent_req_nomem(subreq, req)) {
6546 * Now we add our own waiter to the end of the queue,
6547 * this way we get notified when all pending requests are finished
6548 * and reply to the outstanding SMB1 request.
6550 subreq = tevent_queue_wait_send(state,
6551 conn->sconn->ev_ctx,
6553 if (tevent_req_nomem(subreq, req)) {
6559 * We're really going async - move the SMB1 request from
6560 * a talloc stackframe above us to the sconn talloc-context.
6561 * We need this to stick around until the wait_done
6562 * callback is invoked.
6564 smb1req = talloc_move(smb1req->sconn, &smb1req);
6566 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6571 static void reply_tdis_wait_done(struct tevent_req *subreq)
6573 struct tevent_req *req = tevent_req_callback_data(
6574 subreq, struct tevent_req);
6576 tevent_queue_wait_recv(subreq);
6577 TALLOC_FREE(subreq);
6578 tevent_req_done(req);
6581 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6583 return tevent_req_simple_recv_ntstatus(req);
6586 static void reply_tdis_done(struct tevent_req *req)
6588 struct smb_request *smb1req = tevent_req_callback_data(
6589 req, struct smb_request);
6591 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6595 * Take the profile charge here. Not strictly
6596 * correct but better than the other SMB1 async
6597 * code that double-charges at the moment.
6599 START_PROFILE(SMBtdis);
6601 status = reply_tdis_recv(req);
6603 if (!NT_STATUS_IS_OK(status)) {
6604 TALLOC_FREE(smb1req);
6605 END_PROFILE(SMBtdis);
6606 exit_server(__location__ ": reply_tdis_recv failed");
6611 * As we've been awoken, we may have changed
6612 * directory in the meantime.
6613 * reply_tdis() has the DO_CHDIR flag set.
6615 ok = chdir_current_service(smb1req->conn);
6617 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6618 smb_request_done(smb1req);
6619 END_PROFILE(SMBtdis);
6622 status = smbXsrv_tcon_disconnect(tcon,
6624 if (!NT_STATUS_IS_OK(status)) {
6625 TALLOC_FREE(smb1req);
6626 END_PROFILE(SMBtdis);
6627 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6631 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6632 smb1req->conn = NULL;
6636 reply_outbuf(smb1req, 0, 0);
6638 * The following call is needed to push the
6639 * reply data back out the socket after async
6640 * return. Plus it frees smb1req.
6642 smb_request_done(smb1req);
6643 END_PROFILE(SMBtdis);
6646 /****************************************************************************
6648 conn POINTER CAN BE NULL HERE !
6649 ****************************************************************************/
6651 void reply_echo(struct smb_request *req)
6653 connection_struct *conn = req->conn;
6654 struct smb_perfcount_data local_pcd;
6655 struct smb_perfcount_data *cur_pcd;
6659 START_PROFILE(SMBecho);
6661 smb_init_perfcount_data(&local_pcd);
6664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6665 END_PROFILE(SMBecho);
6669 smb_reverb = SVAL(req->vwv+0, 0);
6671 reply_outbuf(req, 1, req->buflen);
6673 /* copy any incoming data back out */
6674 if (req->buflen > 0) {
6675 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6678 if (smb_reverb > 100) {
6679 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6683 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6685 /* this makes sure we catch the request pcd */
6686 if (seq_num == smb_reverb) {
6687 cur_pcd = &req->pcd;
6689 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6690 cur_pcd = &local_pcd;
6693 SSVAL(req->outbuf,smb_vwv0,seq_num);
6695 show_msg((char *)req->outbuf);
6696 if (!srv_send_smb(req->xconn,
6697 (char *)req->outbuf,
6698 true, req->seqnum+1,
6699 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6701 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6704 DEBUG(3,("echo %d times\n", smb_reverb));
6706 TALLOC_FREE(req->outbuf);
6708 END_PROFILE(SMBecho);
6712 /****************************************************************************
6713 Reply to a printopen.
6714 ****************************************************************************/
6716 void reply_printopen(struct smb_request *req)
6718 connection_struct *conn = req->conn;
6722 START_PROFILE(SMBsplopen);
6725 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6726 END_PROFILE(SMBsplopen);
6730 if (!CAN_PRINT(conn)) {
6731 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6732 END_PROFILE(SMBsplopen);
6736 status = file_new(req, conn, &fsp);
6737 if(!NT_STATUS_IS_OK(status)) {
6738 reply_nterror(req, status);
6739 END_PROFILE(SMBsplopen);
6743 /* Open for exclusive use, write only. */
6744 status = print_spool_open(fsp, NULL, req->vuid);
6746 if (!NT_STATUS_IS_OK(status)) {
6747 file_free(req, fsp);
6748 reply_nterror(req, status);
6749 END_PROFILE(SMBsplopen);
6753 reply_outbuf(req, 1, 0);
6754 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6756 DEBUG(3,("openprint fd=%d %s\n",
6757 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
6759 END_PROFILE(SMBsplopen);
6763 /****************************************************************************
6764 Reply to a printclose.
6765 ****************************************************************************/
6767 void reply_printclose(struct smb_request *req)
6769 connection_struct *conn = req->conn;
6773 START_PROFILE(SMBsplclose);
6776 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6777 END_PROFILE(SMBsplclose);
6781 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6783 if (!check_fsp(conn, req, fsp)) {
6784 END_PROFILE(SMBsplclose);
6788 if (!CAN_PRINT(conn)) {
6789 reply_force_doserror(req, ERRSRV, ERRerror);
6790 END_PROFILE(SMBsplclose);
6794 DEBUG(3,("printclose fd=%d %s\n",
6795 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
6797 status = close_file(req, fsp, NORMAL_CLOSE);
6799 if(!NT_STATUS_IS_OK(status)) {
6800 reply_nterror(req, status);
6801 END_PROFILE(SMBsplclose);
6805 reply_outbuf(req, 0, 0);
6807 END_PROFILE(SMBsplclose);
6811 /****************************************************************************
6812 Reply to a printqueue.
6813 ****************************************************************************/
6815 void reply_printqueue(struct smb_request *req)
6817 const struct loadparm_substitution *lp_sub =
6818 loadparm_s3_global_substitution();
6819 connection_struct *conn = req->conn;
6823 START_PROFILE(SMBsplretq);
6826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6827 END_PROFILE(SMBsplretq);
6831 max_count = SVAL(req->vwv+0, 0);
6832 start_index = SVAL(req->vwv+1, 0);
6834 /* we used to allow the client to get the cnum wrong, but that
6835 is really quite gross and only worked when there was only
6836 one printer - I think we should now only accept it if they
6837 get it right (tridge) */
6838 if (!CAN_PRINT(conn)) {
6839 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6840 END_PROFILE(SMBsplretq);
6844 reply_outbuf(req, 2, 3);
6845 SSVAL(req->outbuf,smb_vwv0,0);
6846 SSVAL(req->outbuf,smb_vwv1,0);
6847 SCVAL(smb_buf(req->outbuf),0,1);
6848 SSVAL(smb_buf(req->outbuf),1,0);
6850 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6851 start_index, max_count));
6854 TALLOC_CTX *mem_ctx = talloc_tos();
6857 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6858 struct rpc_pipe_client *cli = NULL;
6859 struct dcerpc_binding_handle *b = NULL;
6860 struct policy_handle handle;
6861 struct spoolss_DevmodeContainer devmode_ctr;
6862 union spoolss_JobInfo *info;
6864 uint32_t num_to_get;
6868 ZERO_STRUCT(handle);
6870 status = rpc_pipe_open_interface(mem_ctx,
6873 conn->sconn->remote_address,
6874 conn->sconn->local_address,
6875 conn->sconn->msg_ctx,
6877 if (!NT_STATUS_IS_OK(status)) {
6878 DEBUG(0, ("reply_printqueue: "
6879 "could not connect to spoolss: %s\n",
6880 nt_errstr(status)));
6881 reply_nterror(req, status);
6884 b = cli->binding_handle;
6886 ZERO_STRUCT(devmode_ctr);
6888 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6891 SEC_FLAG_MAXIMUM_ALLOWED,
6894 if (!NT_STATUS_IS_OK(status)) {
6895 reply_nterror(req, status);
6898 if (!W_ERROR_IS_OK(werr)) {
6899 reply_nterror(req, werror_to_ntstatus(werr));
6903 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6911 if (!W_ERROR_IS_OK(werr)) {
6912 reply_nterror(req, werror_to_ntstatus(werr));
6916 if (max_count > 0) {
6917 first = start_index;
6919 first = start_index + max_count + 1;
6922 if (first >= count) {
6925 num_to_get = first + MIN(ABS(max_count), count - first);
6928 for (i = first; i < num_to_get; i++) {
6931 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6934 uint16_t qrapjobid = pjobid_to_rap(sharename,
6935 info[i].info2.job_id);
6937 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6943 srv_put_dos_date2(p, 0, qtime);
6944 SCVAL(p, 4, qstatus);
6945 SSVAL(p, 5, qrapjobid);
6946 SIVAL(p, 7, info[i].info2.size);
6948 status = srvstr_push(blob, req->flags2, p+12,
6949 info[i].info2.notify_name, 16, STR_ASCII, &len);
6950 if (!NT_STATUS_IS_OK(status)) {
6951 reply_nterror(req, status);
6954 if (message_push_blob(
6957 blob, sizeof(blob))) == -1) {
6958 reply_nterror(req, NT_STATUS_NO_MEMORY);
6964 SSVAL(req->outbuf,smb_vwv0,count);
6965 SSVAL(req->outbuf,smb_vwv1,
6966 (max_count>0?first+count:first-1));
6967 SCVAL(smb_buf(req->outbuf),0,1);
6968 SSVAL(smb_buf(req->outbuf),1,28*count);
6972 DEBUG(3, ("%u entries returned in queue\n",
6976 if (b && is_valid_policy_hnd(&handle)) {
6977 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6982 END_PROFILE(SMBsplretq);
6986 /****************************************************************************
6987 Reply to a printwrite.
6988 ****************************************************************************/
6990 void reply_printwrite(struct smb_request *req)
6992 connection_struct *conn = req->conn;
6997 START_PROFILE(SMBsplwr);
7000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7001 END_PROFILE(SMBsplwr);
7005 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7007 if (!check_fsp(conn, req, fsp)) {
7008 END_PROFILE(SMBsplwr);
7012 if (!fsp->print_file) {
7013 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7014 END_PROFILE(SMBsplwr);
7018 if (!CHECK_WRITE(fsp)) {
7019 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7020 END_PROFILE(SMBsplwr);
7024 numtowrite = SVAL(req->buf, 1);
7027 * This already protects us against CVE-2017-12163.
7029 if (req->buflen < numtowrite + 3) {
7030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7031 END_PROFILE(SMBsplwr);
7035 data = (const char *)req->buf + 3;
7037 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7038 reply_nterror(req, map_nt_error_from_unix(errno));
7039 END_PROFILE(SMBsplwr);
7043 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7045 END_PROFILE(SMBsplwr);
7049 /****************************************************************************
7051 ****************************************************************************/
7053 void reply_mkdir(struct smb_request *req)
7055 connection_struct *conn = req->conn;
7056 struct smb_filename *smb_dname = NULL;
7057 char *directory = NULL;
7060 TALLOC_CTX *ctx = talloc_tos();
7062 START_PROFILE(SMBmkdir);
7064 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7065 STR_TERMINATE, &status);
7066 if (!NT_STATUS_IS_OK(status)) {
7067 reply_nterror(req, status);
7071 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7072 status = filename_convert(ctx, conn,
7077 if (!NT_STATUS_IS_OK(status)) {
7078 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7079 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7080 ERRSRV, ERRbadpath);
7083 reply_nterror(req, status);
7087 status = create_directory(conn, req, smb_dname);
7089 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7091 if (!NT_STATUS_IS_OK(status)) {
7093 if (!use_nt_status()
7094 && NT_STATUS_EQUAL(status,
7095 NT_STATUS_OBJECT_NAME_COLLISION)) {
7097 * Yes, in the DOS error code case we get a
7098 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7099 * samba4 torture test.
7101 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7104 reply_nterror(req, status);
7108 reply_outbuf(req, 0, 0);
7110 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7112 TALLOC_FREE(smb_dname);
7113 END_PROFILE(SMBmkdir);
7117 /****************************************************************************
7119 ****************************************************************************/
7121 void reply_rmdir(struct smb_request *req)
7123 connection_struct *conn = req->conn;
7124 struct smb_filename *smb_dname = NULL;
7125 char *directory = NULL;
7127 TALLOC_CTX *ctx = talloc_tos();
7128 files_struct *fsp = NULL;
7130 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7132 START_PROFILE(SMBrmdir);
7134 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7135 STR_TERMINATE, &status);
7136 if (!NT_STATUS_IS_OK(status)) {
7137 reply_nterror(req, status);
7141 status = filename_convert(ctx, conn,
7146 if (!NT_STATUS_IS_OK(status)) {
7147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7148 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7149 ERRSRV, ERRbadpath);
7152 reply_nterror(req, status);
7156 if (is_ntfs_stream_smb_fname(smb_dname)) {
7157 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7161 status = SMB_VFS_CREATE_FILE(
7164 smb_dname, /* fname */
7165 DELETE_ACCESS, /* access_mask */
7166 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7168 FILE_OPEN, /* create_disposition*/
7169 FILE_DIRECTORY_FILE, /* create_options */
7170 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7171 0, /* oplock_request */
7173 0, /* allocation_size */
7174 0, /* private_flags */
7179 NULL, NULL); /* create context */
7181 if (!NT_STATUS_IS_OK(status)) {
7182 if (open_was_deferred(req->xconn, req->mid)) {
7183 /* We have re-scheduled this call. */
7186 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7187 bool ok = defer_smb1_sharing_violation(req);
7192 reply_nterror(req, status);
7196 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7197 if (!NT_STATUS_IS_OK(status)) {
7198 close_file(req, fsp, ERROR_CLOSE);
7199 reply_nterror(req, status);
7203 if (!set_delete_on_close(fsp, true,
7204 conn->session_info->security_token,
7205 conn->session_info->unix_token)) {
7206 close_file(req, fsp, ERROR_CLOSE);
7207 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7211 status = close_file(req, fsp, NORMAL_CLOSE);
7212 if (!NT_STATUS_IS_OK(status)) {
7213 reply_nterror(req, status);
7215 reply_outbuf(req, 0, 0);
7218 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7220 TALLOC_FREE(smb_dname);
7221 END_PROFILE(SMBrmdir);
7225 /*******************************************************************
7226 Resolve wildcards in a filename rename.
7227 ********************************************************************/
7229 static bool resolve_wildcards(TALLOC_CTX *ctx,
7234 char *name2_copy = NULL;
7239 char *p,*p2, *pname1, *pname2;
7241 name2_copy = talloc_strdup(ctx, name2);
7246 pname1 = strrchr_m(name1,'/');
7247 pname2 = strrchr_m(name2_copy,'/');
7249 if (!pname1 || !pname2) {
7253 /* Truncate the copy of name2 at the last '/' */
7256 /* Now go past the '/' */
7260 root1 = talloc_strdup(ctx, pname1);
7261 root2 = talloc_strdup(ctx, pname2);
7263 if (!root1 || !root2) {
7267 p = strrchr_m(root1,'.');
7270 ext1 = talloc_strdup(ctx, p+1);
7272 ext1 = talloc_strdup(ctx, "");
7274 p = strrchr_m(root2,'.');
7277 ext2 = talloc_strdup(ctx, p+1);
7279 ext2 = talloc_strdup(ctx, "");
7282 if (!ext1 || !ext2) {
7290 /* Hmmm. Should this be mb-aware ? */
7293 } else if (*p2 == '*') {
7295 root2 = talloc_asprintf(ctx, "%s%s",
7314 /* Hmmm. Should this be mb-aware ? */
7317 } else if (*p2 == '*') {
7319 ext2 = talloc_asprintf(ctx, "%s%s",
7335 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7340 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7352 /****************************************************************************
7353 Ensure open files have their names updated. Updated to notify other smbd's
7355 ****************************************************************************/
7357 static void rename_open_files(connection_struct *conn,
7358 struct share_mode_lock *lck,
7360 uint32_t orig_name_hash,
7361 const struct smb_filename *smb_fname_dst)
7364 bool did_rename = False;
7366 uint32_t new_name_hash = 0;
7368 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7369 fsp = file_find_di_next(fsp)) {
7370 struct file_id_buf idbuf;
7371 /* fsp_name is a relative path under the fsp. To change this for other
7372 sharepaths we need to manipulate relative paths. */
7373 /* TODO - create the absolute path and manipulate the newname
7374 relative to the sharepath. */
7375 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7378 if (fsp->name_hash != orig_name_hash) {
7381 DBG_DEBUG("renaming file %s "
7382 "(file_id %s) from %s -> %s\n",
7384 file_id_str_buf(fsp->file_id, &idbuf),
7386 smb_fname_str_dbg(smb_fname_dst));
7388 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7389 if (NT_STATUS_IS_OK(status)) {
7391 new_name_hash = fsp->name_hash;
7396 struct file_id_buf idbuf;
7397 DBG_DEBUG("no open files on file_id %s "
7399 file_id_str_buf(id, &idbuf),
7400 smb_fname_str_dbg(smb_fname_dst));
7403 /* Send messages to all smbd's (not ourself) that the name has changed. */
7404 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7405 orig_name_hash, new_name_hash,
7410 /****************************************************************************
7411 We need to check if the source path is a parent directory of the destination
7412 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7413 refuse the rename with a sharing violation. Under UNIX the above call can
7414 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7415 probably need to check that the client is a Windows one before disallowing
7416 this as a UNIX client (one with UNIX extensions) can know the source is a
7417 symlink and make this decision intelligently. Found by an excellent bug
7418 report from <AndyLiebman@aol.com>.
7419 ****************************************************************************/
7421 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7422 const struct smb_filename *smb_fname_dst)
7424 const char *psrc = smb_fname_src->base_name;
7425 const char *pdst = smb_fname_dst->base_name;
7428 if (psrc[0] == '.' && psrc[1] == '/') {
7431 if (pdst[0] == '.' && pdst[1] == '/') {
7434 if ((slen = strlen(psrc)) > strlen(pdst)) {
7437 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7441 * Do the notify calls from a rename
7444 static void notify_rename(connection_struct *conn, bool is_dir,
7445 const struct smb_filename *smb_fname_src,
7446 const struct smb_filename *smb_fname_dst)
7448 char *parent_dir_src = NULL;
7449 char *parent_dir_dst = NULL;
7452 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7453 : FILE_NOTIFY_CHANGE_FILE_NAME;
7455 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7456 &parent_dir_src, NULL) ||
7457 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7458 &parent_dir_dst, NULL)) {
7462 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7463 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7464 smb_fname_src->base_name);
7465 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7466 smb_fname_dst->base_name);
7469 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7470 smb_fname_src->base_name);
7471 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7472 smb_fname_dst->base_name);
7475 /* this is a strange one. w2k3 gives an additional event for
7476 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7477 files, but not directories */
7479 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7480 FILE_NOTIFY_CHANGE_ATTRIBUTES
7481 |FILE_NOTIFY_CHANGE_CREATION,
7482 smb_fname_dst->base_name);
7485 TALLOC_FREE(parent_dir_src);
7486 TALLOC_FREE(parent_dir_dst);
7489 /****************************************************************************
7490 Returns an error if the parent directory for a filename is open in an
7492 ****************************************************************************/
7494 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7495 const struct smb_filename *smb_fname_dst_in)
7497 struct smb_filename *smb_fname_parent = NULL;
7499 files_struct *fsp = NULL;
7503 ok = parent_smb_fname(talloc_tos(),
7508 return NT_STATUS_NO_MEMORY;
7511 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7513 return map_nt_error_from_unix(errno);
7517 * We're only checking on this smbd here, mostly good
7518 * enough.. and will pass tests.
7521 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7522 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7523 fsp = file_find_di_next(fsp)) {
7524 if (fsp->access_mask & DELETE_ACCESS) {
7525 return NT_STATUS_SHARING_VIOLATION;
7528 return NT_STATUS_OK;
7531 /****************************************************************************
7532 Rename an open file - given an fsp.
7533 ****************************************************************************/
7535 NTSTATUS rename_internals_fsp(connection_struct *conn,
7537 const struct smb_filename *smb_fname_dst_in,
7538 const char *dst_original_lcomp,
7540 bool replace_if_exists)
7542 TALLOC_CTX *ctx = talloc_tos();
7543 struct smb_filename *smb_fname_dst = NULL;
7544 NTSTATUS status = NT_STATUS_OK;
7545 struct share_mode_lock *lck = NULL;
7546 uint32_t access_mask = SEC_DIR_ADD_FILE;
7547 bool dst_exists, old_is_stream, new_is_stream;
7550 status = check_name(conn, smb_fname_dst_in);
7551 if (!NT_STATUS_IS_OK(status)) {
7555 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7556 if (!NT_STATUS_IS_OK(status)) {
7560 if (file_has_open_streams(fsp)) {
7561 return NT_STATUS_ACCESS_DENIED;
7564 /* Make a copy of the dst smb_fname structs */
7566 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7567 if (smb_fname_dst == NULL) {
7568 status = NT_STATUS_NO_MEMORY;
7573 * Check for special case with case preserving and not
7574 * case sensitive. If the new last component differs from the original
7575 * last component only by case, then we should allow
7576 * the rename (user is trying to change the case of the
7579 if (!conn->case_sensitive && conn->case_preserve &&
7580 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7581 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7582 char *fname_dst_parent = NULL;
7583 const char *fname_dst_lcomp = NULL;
7584 char *orig_lcomp_path = NULL;
7585 char *orig_lcomp_stream = NULL;
7589 * Split off the last component of the processed
7590 * destination name. We will compare this to
7591 * the split components of dst_original_lcomp.
7593 if (!parent_dirname(ctx,
7594 smb_fname_dst->base_name,
7596 &fname_dst_lcomp)) {
7597 status = NT_STATUS_NO_MEMORY;
7602 * The dst_original_lcomp component contains
7603 * the last_component of the path + stream
7604 * name (if a stream exists).
7606 * Split off the stream name so we
7607 * can check them separately.
7610 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7611 /* POSIX - no stream component. */
7612 orig_lcomp_path = talloc_strdup(ctx,
7613 dst_original_lcomp);
7614 if (orig_lcomp_path == NULL) {
7618 ok = split_stream_filename(ctx,
7621 &orig_lcomp_stream);
7625 TALLOC_FREE(fname_dst_parent);
7626 status = NT_STATUS_NO_MEMORY;
7630 /* If the base names only differ by case, use original. */
7631 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7634 * Replace the modified last component with the
7637 if (!ISDOT(fname_dst_parent)) {
7638 tmp = talloc_asprintf(smb_fname_dst,
7643 tmp = talloc_strdup(smb_fname_dst,
7647 status = NT_STATUS_NO_MEMORY;
7648 TALLOC_FREE(fname_dst_parent);
7649 TALLOC_FREE(orig_lcomp_path);
7650 TALLOC_FREE(orig_lcomp_stream);
7653 TALLOC_FREE(smb_fname_dst->base_name);
7654 smb_fname_dst->base_name = tmp;
7657 /* If the stream_names only differ by case, use original. */
7658 if(!strcsequal(smb_fname_dst->stream_name,
7659 orig_lcomp_stream)) {
7660 /* Use the original stream. */
7661 char *tmp = talloc_strdup(smb_fname_dst,
7664 status = NT_STATUS_NO_MEMORY;
7665 TALLOC_FREE(fname_dst_parent);
7666 TALLOC_FREE(orig_lcomp_path);
7667 TALLOC_FREE(orig_lcomp_stream);
7670 TALLOC_FREE(smb_fname_dst->stream_name);
7671 smb_fname_dst->stream_name = tmp;
7673 TALLOC_FREE(fname_dst_parent);
7674 TALLOC_FREE(orig_lcomp_path);
7675 TALLOC_FREE(orig_lcomp_stream);
7679 * If the src and dest names are identical - including case,
7680 * don't do the rename, just return success.
7683 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7684 strcsequal(fsp->fsp_name->stream_name,
7685 smb_fname_dst->stream_name)) {
7686 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7687 "- returning success\n",
7688 smb_fname_str_dbg(smb_fname_dst)));
7689 status = NT_STATUS_OK;
7693 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7694 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7696 /* Return the correct error code if both names aren't streams. */
7697 if (!old_is_stream && new_is_stream) {
7698 status = NT_STATUS_OBJECT_NAME_INVALID;
7702 if (old_is_stream && !new_is_stream) {
7703 status = NT_STATUS_INVALID_PARAMETER;
7707 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7709 if(!replace_if_exists && dst_exists) {
7710 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7711 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7712 smb_fname_str_dbg(smb_fname_dst)));
7713 status = NT_STATUS_OBJECT_NAME_COLLISION;
7718 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7719 &smb_fname_dst->st);
7720 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7722 /* The file can be open when renaming a stream */
7723 if (dst_fsp && !new_is_stream) {
7724 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7725 status = NT_STATUS_ACCESS_DENIED;
7730 /* Ensure we have a valid stat struct for the source. */
7731 status = vfs_stat_fsp(fsp);
7732 if (!NT_STATUS_IS_OK(status)) {
7736 status = can_rename(conn, fsp, attrs);
7738 if (!NT_STATUS_IS_OK(status)) {
7739 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7740 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7741 smb_fname_str_dbg(smb_fname_dst)));
7742 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7743 status = NT_STATUS_ACCESS_DENIED;
7747 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7748 status = NT_STATUS_ACCESS_DENIED;
7752 /* Do we have rights to move into the destination ? */
7753 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7754 /* We're moving a directory. */
7755 access_mask = SEC_DIR_ADD_SUBDIR;
7757 status = check_parent_access(conn,
7761 if (!NT_STATUS_IS_OK(status)) {
7762 DBG_INFO("check_parent_access on "
7763 "dst %s returned %s\n",
7764 smb_fname_str_dbg(smb_fname_dst),
7769 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7772 * We have the file open ourselves, so not being able to get the
7773 * corresponding share mode lock is a fatal error.
7776 SMB_ASSERT(lck != NULL);
7778 ret = SMB_VFS_RENAMEAT(conn,
7784 uint32_t create_options = fsp->fh->private_options;
7786 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7787 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7788 smb_fname_str_dbg(smb_fname_dst)));
7790 if (!fsp->fsp_flags.is_directory &&
7791 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7792 (lp_map_archive(SNUM(conn)) ||
7793 lp_store_dos_attributes(SNUM(conn)))) {
7794 /* We must set the archive bit on the newly
7796 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7797 uint32_t old_dosmode = dos_mode(conn,
7799 file_set_dosmode(conn,
7801 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7808 fsp->fsp_flags.is_directory,
7812 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7816 * A rename acts as a new file create w.r.t. allowing an initial delete
7817 * on close, probably because in Windows there is a new handle to the
7818 * new file. If initial delete on close was requested but not
7819 * originally set, we need to set it here. This is probably not 100% correct,
7820 * but will work for the CIFSFS client which in non-posix mode
7821 * depends on these semantics. JRA.
7824 if (create_options & FILE_DELETE_ON_CLOSE) {
7825 status = can_set_delete_on_close(fsp, 0);
7827 if (NT_STATUS_IS_OK(status)) {
7828 /* Note that here we set the *initial* delete on close flag,
7829 * not the regular one. The magic gets handled in close. */
7830 fsp->fsp_flags.initial_delete_on_close = true;
7834 status = NT_STATUS_OK;
7840 if (errno == ENOTDIR || errno == EISDIR) {
7841 status = NT_STATUS_OBJECT_NAME_COLLISION;
7843 status = map_nt_error_from_unix(errno);
7846 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7847 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7848 smb_fname_str_dbg(smb_fname_dst)));
7851 TALLOC_FREE(smb_fname_dst);
7856 /****************************************************************************
7857 The guts of the rename command, split out so it may be called by the NT SMB
7859 ****************************************************************************/
7861 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7862 connection_struct *conn,
7863 struct smb_request *req,
7864 struct smb_filename *smb_fname_src,
7865 const char *src_original_lcomp,
7866 struct smb_filename *smb_fname_dst,
7867 const char *dst_original_lcomp,
7869 bool replace_if_exists,
7870 uint32_t access_mask)
7872 char *fname_src_dir = NULL;
7873 struct smb_filename *smb_fname_src_dir = NULL;
7874 char *fname_src_mask = NULL;
7876 NTSTATUS status = NT_STATUS_OK;
7877 struct smb_Dir *dir_hnd = NULL;
7878 const char *dname = NULL;
7879 char *talloced = NULL;
7881 int create_options = 0;
7882 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7883 struct smb2_create_blobs *posx = NULL;
7885 bool src_has_wild = false;
7886 bool dest_has_wild = false;
7889 * Split the old name into directory and last component
7890 * strings. Note that unix_convert may have stripped off a
7891 * leading ./ from both name and newname if the rename is
7892 * at the root of the share. We need to make sure either both
7893 * name and newname contain a / character or neither of them do
7894 * as this is checked in resolve_wildcards().
7897 /* Split up the directory from the filename/mask. */
7898 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7899 &fname_src_dir, &fname_src_mask);
7900 if (!NT_STATUS_IS_OK(status)) {
7901 status = NT_STATUS_NO_MEMORY;
7905 if (req != NULL && !req->posix_pathnames) {
7907 * Check the wildcard mask *before*
7908 * unmangling. As mangling is done
7909 * for names that can't be returned
7910 * to Windows the unmangled name may
7911 * contain Windows wildcard characters.
7913 if (src_original_lcomp != NULL) {
7914 src_has_wild = ms_has_wild(src_original_lcomp);
7916 dest_has_wild = ms_has_wild(dst_original_lcomp);
7920 * We should only check the mangled cache
7921 * here if unix_convert failed. This means
7922 * that the path in 'mask' doesn't exist
7923 * on the file system and so we need to look
7924 * for a possible mangle. This patch from
7925 * Tine Smukavec <valentin.smukavec@hermes.si>.
7928 if (!VALID_STAT(smb_fname_src->st) &&
7929 mangle_is_mangled(fname_src_mask, conn->params)) {
7930 char *new_mask = NULL;
7931 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7934 TALLOC_FREE(fname_src_mask);
7935 fname_src_mask = new_mask;
7939 if (posix_pathnames) {
7940 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7941 if (!NT_STATUS_IS_OK(status)) {
7942 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7948 if (!src_has_wild) {
7952 * Only one file needs to be renamed. Append the mask back
7953 * onto the directory.
7955 TALLOC_FREE(smb_fname_src->base_name);
7956 if (ISDOT(fname_src_dir)) {
7957 /* Ensure we use canonical names on open. */
7958 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7962 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7967 if (!smb_fname_src->base_name) {
7968 status = NT_STATUS_NO_MEMORY;
7972 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7973 "case_preserve = %d, short case preserve = %d, "
7974 "directory = %s, newname = %s, "
7975 "last_component_dest = %s\n",
7976 conn->case_sensitive, conn->case_preserve,
7977 conn->short_case_preserve,
7978 smb_fname_str_dbg(smb_fname_src),
7979 smb_fname_str_dbg(smb_fname_dst),
7980 dst_original_lcomp));
7982 /* The dest name still may have wildcards. */
7983 if (dest_has_wild) {
7984 char *fname_dst_mod = NULL;
7985 if (!resolve_wildcards(smb_fname_dst,
7986 smb_fname_src->base_name,
7987 smb_fname_dst->base_name,
7989 DEBUG(6, ("rename_internals: resolve_wildcards "
7991 smb_fname_src->base_name,
7992 smb_fname_dst->base_name));
7993 status = NT_STATUS_NO_MEMORY;
7996 TALLOC_FREE(smb_fname_dst->base_name);
7997 smb_fname_dst->base_name = fname_dst_mod;
8000 ZERO_STRUCT(smb_fname_src->st);
8001 if (posix_pathnames) {
8002 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8004 rc = SMB_VFS_STAT(conn, smb_fname_src);
8007 status = map_nt_error_from_unix_common(errno);
8011 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8012 create_options |= FILE_DIRECTORY_FILE;
8015 status = SMB_VFS_CREATE_FILE(
8018 smb_fname_src, /* fname */
8019 access_mask, /* access_mask */
8020 (FILE_SHARE_READ | /* share_access */
8022 FILE_OPEN, /* create_disposition*/
8023 create_options, /* create_options */
8024 0, /* file_attributes */
8025 0, /* oplock_request */
8027 0, /* allocation_size */
8028 0, /* private_flags */
8033 posx, /* in_context_blobs */
8034 NULL); /* out_context_blobs */
8036 if (!NT_STATUS_IS_OK(status)) {
8037 DEBUG(3, ("Could not open rename source %s: %s\n",
8038 smb_fname_str_dbg(smb_fname_src),
8039 nt_errstr(status)));
8043 status = rename_internals_fsp(conn,
8050 close_file(req, fsp, NORMAL_CLOSE);
8052 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8053 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8054 smb_fname_str_dbg(smb_fname_dst)));
8060 * Wildcards - process each file that matches.
8062 if (strequal(fname_src_mask, "????????.???")) {
8063 TALLOC_FREE(fname_src_mask);
8064 fname_src_mask = talloc_strdup(ctx, "*");
8065 if (!fname_src_mask) {
8066 status = NT_STATUS_NO_MEMORY;
8071 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8075 smb_fname_src->twrp,
8076 smb_fname_src->flags);
8077 if (smb_fname_src_dir == NULL) {
8078 status = NT_STATUS_NO_MEMORY;
8082 status = check_name(conn, smb_fname_src_dir);
8083 if (!NT_STATUS_IS_OK(status)) {
8087 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8089 if (dir_hnd == NULL) {
8090 status = map_nt_error_from_unix(errno);
8094 status = NT_STATUS_NO_SUCH_FILE;
8096 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8097 * - gentest fix. JRA
8100 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8102 files_struct *fsp = NULL;
8103 char *destname = NULL;
8104 bool sysdir_entry = False;
8106 /* Quick check for "." and ".." */
8107 if (ISDOT(dname) || ISDOTDOT(dname)) {
8108 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8109 sysdir_entry = True;
8111 TALLOC_FREE(talloced);
8116 if (!is_visible_file(conn,
8121 TALLOC_FREE(talloced);
8125 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8126 TALLOC_FREE(talloced);
8131 status = NT_STATUS_OBJECT_NAME_INVALID;
8135 TALLOC_FREE(smb_fname_src->base_name);
8136 if (ISDOT(fname_src_dir)) {
8137 /* Ensure we use canonical names on open. */
8138 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8142 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8147 if (!smb_fname_src->base_name) {
8148 status = NT_STATUS_NO_MEMORY;
8152 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8153 smb_fname_dst->base_name,
8155 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8156 smb_fname_src->base_name, destname));
8157 TALLOC_FREE(talloced);
8161 status = NT_STATUS_NO_MEMORY;
8165 TALLOC_FREE(smb_fname_dst->base_name);
8166 smb_fname_dst->base_name = destname;
8168 ZERO_STRUCT(smb_fname_src->st);
8169 if (posix_pathnames) {
8170 SMB_VFS_LSTAT(conn, smb_fname_src);
8172 SMB_VFS_STAT(conn, smb_fname_src);
8177 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8178 create_options |= FILE_DIRECTORY_FILE;
8181 status = SMB_VFS_CREATE_FILE(
8184 smb_fname_src, /* fname */
8185 access_mask, /* access_mask */
8186 (FILE_SHARE_READ | /* share_access */
8188 FILE_OPEN, /* create_disposition*/
8189 create_options, /* create_options */
8190 0, /* file_attributes */
8191 0, /* oplock_request */
8193 0, /* allocation_size */
8194 0, /* private_flags */
8199 posx, /* in_context_blobs */
8200 NULL); /* out_context_blobs */
8202 if (!NT_STATUS_IS_OK(status)) {
8203 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8204 "returned %s rename %s -> %s\n",
8206 smb_fname_str_dbg(smb_fname_src),
8207 smb_fname_str_dbg(smb_fname_dst)));
8211 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8212 if (dst_original_lcomp == NULL) {
8213 status = NT_STATUS_NO_MEMORY;
8217 status = rename_internals_fsp(conn,
8224 close_file(req, fsp, NORMAL_CLOSE);
8226 if (!NT_STATUS_IS_OK(status)) {
8227 DEBUG(3, ("rename_internals_fsp returned %s for "
8228 "rename %s -> %s\n", nt_errstr(status),
8229 smb_fname_str_dbg(smb_fname_src),
8230 smb_fname_str_dbg(smb_fname_dst)));
8236 DEBUG(3,("rename_internals: doing rename on %s -> "
8237 "%s\n", smb_fname_str_dbg(smb_fname_src),
8238 smb_fname_str_dbg(smb_fname_src)));
8239 TALLOC_FREE(talloced);
8241 TALLOC_FREE(dir_hnd);
8243 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8244 status = map_nt_error_from_unix(errno);
8249 TALLOC_FREE(talloced);
8250 TALLOC_FREE(smb_fname_src_dir);
8251 TALLOC_FREE(fname_src_dir);
8252 TALLOC_FREE(fname_src_mask);
8256 /****************************************************************************
8258 ****************************************************************************/
8260 void reply_mv(struct smb_request *req)
8262 connection_struct *conn = req->conn;
8264 char *newname = NULL;
8268 TALLOC_CTX *ctx = talloc_tos();
8269 struct smb_filename *smb_fname_src = NULL;
8270 const char *src_original_lcomp = NULL;
8271 struct smb_filename *smb_fname_dst = NULL;
8272 const char *dst_original_lcomp = NULL;
8273 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8274 (!req->posix_pathnames ? UCF_ALWAYS_ALLOW_WCARD_LCOMP : 0);
8275 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8276 (!req->posix_pathnames ? UCF_ALWAYS_ALLOW_WCARD_LCOMP : 0);
8277 bool stream_rename = false;
8279 START_PROFILE(SMBmv);
8282 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8286 attrs = SVAL(req->vwv+0, 0);
8288 p = (const char *)req->buf + 1;
8289 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
8291 if (!NT_STATUS_IS_OK(status)) {
8292 reply_nterror(req, status);
8296 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
8298 if (!NT_STATUS_IS_OK(status)) {
8299 reply_nterror(req, status);
8303 if (!req->posix_pathnames) {
8304 /* The newname must begin with a ':' if the
8305 name contains a ':'. */
8306 if (strchr_m(name, ':')) {
8307 if (newname[0] != ':') {
8308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8311 stream_rename = true;
8315 status = filename_convert(ctx,
8322 if (!NT_STATUS_IS_OK(status)) {
8323 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8324 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8325 ERRSRV, ERRbadpath);
8328 reply_nterror(req, status);
8332 /* Get the last component of the source for rename_internals(). */
8333 src_original_lcomp = get_original_lcomp(ctx,
8337 if (src_original_lcomp == NULL) {
8338 reply_nterror(req, NT_STATUS_NO_MEMORY);
8342 status = filename_convert(ctx,
8349 if (!NT_STATUS_IS_OK(status)) {
8350 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8351 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8352 ERRSRV, ERRbadpath);
8355 reply_nterror(req, status);
8359 /* Get the last component of the destination for rename_internals(). */
8360 dst_original_lcomp = get_original_lcomp(ctx,
8364 if (dst_original_lcomp == NULL) {
8365 reply_nterror(req, NT_STATUS_NO_MEMORY);
8369 if (stream_rename) {
8370 /* smb_fname_dst->base_name must be the same as
8371 smb_fname_src->base_name. */
8372 TALLOC_FREE(smb_fname_dst->base_name);
8373 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8374 smb_fname_src->base_name);
8375 if (!smb_fname_dst->base_name) {
8376 reply_nterror(req, NT_STATUS_NO_MEMORY);
8381 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8382 smb_fname_str_dbg(smb_fname_dst)));
8384 status = rename_internals(ctx,
8394 if (!NT_STATUS_IS_OK(status)) {
8395 if (open_was_deferred(req->xconn, req->mid)) {
8396 /* We have re-scheduled this call. */
8399 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8400 bool ok = defer_smb1_sharing_violation(req);
8405 reply_nterror(req, status);
8409 reply_outbuf(req, 0, 0);
8411 TALLOC_FREE(smb_fname_src);
8412 TALLOC_FREE(smb_fname_dst);
8417 /*******************************************************************
8418 Copy a file as part of a reply_copy.
8419 ******************************************************************/
8422 * TODO: check error codes on all callers
8425 NTSTATUS copy_file(TALLOC_CTX *ctx,
8426 connection_struct *conn,
8427 struct smb_filename *smb_fname_src,
8428 struct smb_filename *smb_fname_dst,
8431 bool target_is_directory)
8433 struct smb_filename *smb_fname_dst_tmp = NULL;
8435 files_struct *fsp1,*fsp2;
8437 uint32_t new_create_disposition;
8441 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8442 if (smb_fname_dst_tmp == NULL) {
8443 return NT_STATUS_NO_MEMORY;
8447 * If the target is a directory, extract the last component from the
8448 * src filename and append it to the dst filename
8450 if (target_is_directory) {
8453 /* dest/target can't be a stream if it's a directory. */
8454 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8456 p = strrchr_m(smb_fname_src->base_name,'/');
8460 p = smb_fname_src->base_name;
8462 smb_fname_dst_tmp->base_name =
8463 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8465 if (!smb_fname_dst_tmp->base_name) {
8466 status = NT_STATUS_NO_MEMORY;
8471 status = vfs_file_exist(conn, smb_fname_src);
8472 if (!NT_STATUS_IS_OK(status)) {
8476 if (!target_is_directory && count) {
8477 new_create_disposition = FILE_OPEN;
8479 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8482 &new_create_disposition,
8485 status = NT_STATUS_INVALID_PARAMETER;
8490 /* Open the src file for reading. */
8491 status = SMB_VFS_CREATE_FILE(
8494 smb_fname_src, /* fname */
8495 FILE_GENERIC_READ, /* access_mask */
8496 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8497 FILE_OPEN, /* create_disposition*/
8498 0, /* create_options */
8499 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8500 INTERNAL_OPEN_ONLY, /* oplock_request */
8502 0, /* allocation_size */
8503 0, /* private_flags */
8508 NULL, NULL); /* create context */
8510 if (!NT_STATUS_IS_OK(status)) {
8514 dosattrs = dos_mode(conn, smb_fname_src);
8516 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8517 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8520 /* Open the dst file for writing. */
8521 status = SMB_VFS_CREATE_FILE(
8524 smb_fname_dst, /* fname */
8525 FILE_GENERIC_WRITE, /* access_mask */
8526 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8527 new_create_disposition, /* create_disposition*/
8528 0, /* create_options */
8529 dosattrs, /* file_attributes */
8530 INTERNAL_OPEN_ONLY, /* oplock_request */
8532 0, /* allocation_size */
8533 0, /* private_flags */
8538 NULL, NULL); /* create context */
8540 if (!NT_STATUS_IS_OK(status)) {
8541 close_file(NULL, fsp1, ERROR_CLOSE);
8545 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8546 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8548 DEBUG(0, ("error - vfs lseek returned error %s\n",
8550 status = map_nt_error_from_unix(errno);
8551 close_file(NULL, fsp1, ERROR_CLOSE);
8552 close_file(NULL, fsp2, ERROR_CLOSE);
8557 /* Do the actual copy. */
8558 if (smb_fname_src->st.st_ex_size) {
8559 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8564 close_file(NULL, fsp1, NORMAL_CLOSE);
8566 /* Ensure the modtime is set correctly on the destination file. */
8567 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8570 * As we are opening fsp1 read-only we only expect
8571 * an error on close on fsp2 if we are out of space.
8572 * Thus we don't look at the error return from the
8575 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8577 if (!NT_STATUS_IS_OK(status)) {
8581 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8582 status = NT_STATUS_DISK_FULL;
8586 status = NT_STATUS_OK;
8589 TALLOC_FREE(smb_fname_dst_tmp);
8593 /****************************************************************************
8594 Reply to a file copy.
8595 ****************************************************************************/
8597 void reply_copy(struct smb_request *req)
8599 connection_struct *conn = req->conn;
8600 struct smb_filename *smb_fname_src = NULL;
8601 struct smb_filename *smb_fname_src_dir = NULL;
8602 struct smb_filename *smb_fname_dst = NULL;
8603 char *fname_src = NULL;
8604 char *fname_dst = NULL;
8605 char *fname_src_mask = NULL;
8606 char *fname_src_dir = NULL;
8609 int error = ERRnoaccess;
8613 bool target_is_directory=False;
8614 bool source_has_wild = False;
8615 bool dest_has_wild = False;
8617 uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8618 ucf_flags_from_smb_request(req);
8619 uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8620 ucf_flags_from_smb_request(req);
8621 TALLOC_CTX *ctx = talloc_tos();
8623 START_PROFILE(SMBcopy);
8626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8630 tid2 = SVAL(req->vwv+0, 0);
8631 ofun = SVAL(req->vwv+1, 0);
8632 flags = SVAL(req->vwv+2, 0);
8634 p = (const char *)req->buf;
8635 p += srvstr_get_path_req(ctx, req, &fname_src, p, STR_TERMINATE,
8637 if (!NT_STATUS_IS_OK(status)) {
8638 reply_nterror(req, status);
8641 p += srvstr_get_path_req(ctx, req, &fname_dst, p, STR_TERMINATE,
8643 if (!NT_STATUS_IS_OK(status)) {
8644 reply_nterror(req, status);
8648 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8650 if (tid2 != conn->cnum) {
8651 /* can't currently handle inter share copies XXXX */
8652 DEBUG(3,("Rejecting inter-share copy\n"));
8653 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8657 status = filename_convert(ctx, conn,
8662 if (!NT_STATUS_IS_OK(status)) {
8663 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8664 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8665 ERRSRV, ERRbadpath);
8668 reply_nterror(req, status);
8672 status = filename_convert(ctx, conn,
8677 if (!NT_STATUS_IS_OK(status)) {
8678 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8679 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8680 ERRSRV, ERRbadpath);
8683 reply_nterror(req, status);
8687 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8689 if ((flags&1) && target_is_directory) {
8690 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8694 if ((flags&2) && !target_is_directory) {
8695 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8699 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8700 /* wants a tree copy! XXXX */
8701 DEBUG(3,("Rejecting tree copy\n"));
8702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8706 /* Split up the directory from the filename/mask. */
8707 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8708 &fname_src_dir, &fname_src_mask);
8709 if (!NT_STATUS_IS_OK(status)) {
8710 reply_nterror(req, NT_STATUS_NO_MEMORY);
8714 if (!req->posix_pathnames) {
8715 char *orig_src_lcomp = NULL;
8716 char *orig_dst_lcomp = NULL;
8718 * Check the wildcard mask *before*
8719 * unmangling. As mangling is done
8720 * for names that can't be returned
8721 * to Windows the unmangled name may
8722 * contain Windows wildcard characters.
8724 orig_src_lcomp = get_original_lcomp(ctx,
8728 if (orig_src_lcomp == NULL) {
8729 reply_nterror(req, NT_STATUS_NO_MEMORY);
8732 orig_dst_lcomp = get_original_lcomp(ctx,
8736 if (orig_dst_lcomp == NULL) {
8737 reply_nterror(req, NT_STATUS_NO_MEMORY);
8740 source_has_wild = ms_has_wild(orig_src_lcomp);
8741 dest_has_wild = ms_has_wild(orig_dst_lcomp);
8742 TALLOC_FREE(orig_src_lcomp);
8743 TALLOC_FREE(orig_dst_lcomp);
8747 * We should only check the mangled cache
8748 * here if unix_convert failed. This means
8749 * that the path in 'mask' doesn't exist
8750 * on the file system and so we need to look
8751 * for a possible mangle. This patch from
8752 * Tine Smukavec <valentin.smukavec@hermes.si>.
8754 if (!VALID_STAT(smb_fname_src->st) &&
8755 mangle_is_mangled(fname_src_mask, conn->params)) {
8756 char *new_mask = NULL;
8757 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8758 &new_mask, conn->params);
8760 /* Use demangled name if one was successfully found. */
8762 TALLOC_FREE(fname_src_mask);
8763 fname_src_mask = new_mask;
8767 if (!source_has_wild) {
8770 * Only one file needs to be copied. Append the mask back onto
8773 TALLOC_FREE(smb_fname_src->base_name);
8774 if (ISDOT(fname_src_dir)) {
8775 /* Ensure we use canonical names on open. */
8776 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8780 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8785 if (!smb_fname_src->base_name) {
8786 reply_nterror(req, NT_STATUS_NO_MEMORY);
8790 if (dest_has_wild) {
8791 char *fname_dst_mod = NULL;
8792 if (!resolve_wildcards(smb_fname_dst,
8793 smb_fname_src->base_name,
8794 smb_fname_dst->base_name,
8796 reply_nterror(req, NT_STATUS_NO_MEMORY);
8799 TALLOC_FREE(smb_fname_dst->base_name);
8800 smb_fname_dst->base_name = fname_dst_mod;
8803 status = check_name(conn, smb_fname_src);
8804 if (!NT_STATUS_IS_OK(status)) {
8805 reply_nterror(req, status);
8809 status = check_name(conn, smb_fname_dst);
8810 if (!NT_STATUS_IS_OK(status)) {
8811 reply_nterror(req, status);
8815 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8816 ofun, count, target_is_directory);
8818 if(!NT_STATUS_IS_OK(status)) {
8819 reply_nterror(req, status);
8825 struct smb_Dir *dir_hnd = NULL;
8826 const char *dname = NULL;
8827 char *talloced = NULL;
8831 * There is a wildcard that requires us to actually read the
8832 * src dir and copy each file matching the mask to the dst.
8833 * Right now streams won't be copied, but this could
8834 * presumably be added with a nested loop for reach dir entry.
8836 SMB_ASSERT(!smb_fname_src->stream_name);
8837 SMB_ASSERT(!smb_fname_dst->stream_name);
8839 smb_fname_src->stream_name = NULL;
8840 smb_fname_dst->stream_name = NULL;
8842 if (strequal(fname_src_mask,"????????.???")) {
8843 TALLOC_FREE(fname_src_mask);
8844 fname_src_mask = talloc_strdup(ctx, "*");
8845 if (!fname_src_mask) {
8846 reply_nterror(req, NT_STATUS_NO_MEMORY);
8851 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8855 smb_fname_src->twrp,
8856 smb_fname_src->flags);
8857 if (smb_fname_src_dir == NULL) {
8858 reply_nterror(req, NT_STATUS_NO_MEMORY);
8862 status = check_name(conn, smb_fname_src_dir);
8863 if (!NT_STATUS_IS_OK(status)) {
8864 reply_nterror(req, status);
8868 dir_hnd = OpenDir(ctx,
8873 if (dir_hnd == NULL) {
8874 status = map_nt_error_from_unix(errno);
8875 reply_nterror(req, status);
8881 /* Iterate over the src dir copying each entry to the dst. */
8882 while ((dname = ReadDirName(dir_hnd, &offset,
8883 &smb_fname_src->st, &talloced))) {
8884 char *destname = NULL;
8886 if (ISDOT(dname) || ISDOTDOT(dname)) {
8887 TALLOC_FREE(talloced);
8891 if (!is_visible_file(conn,
8896 TALLOC_FREE(talloced);
8900 if(!mask_match(dname, fname_src_mask,
8901 conn->case_sensitive)) {
8902 TALLOC_FREE(talloced);
8906 error = ERRnoaccess;
8908 /* Get the src smb_fname struct setup. */
8909 TALLOC_FREE(smb_fname_src->base_name);
8910 if (ISDOT(fname_src_dir)) {
8911 /* Ensure we use canonical names on open. */
8912 smb_fname_src->base_name =
8913 talloc_asprintf(smb_fname_src, "%s",
8916 smb_fname_src->base_name =
8917 talloc_asprintf(smb_fname_src, "%s/%s",
8918 fname_src_dir, dname);
8921 if (!smb_fname_src->base_name) {
8922 TALLOC_FREE(dir_hnd);
8923 TALLOC_FREE(talloced);
8924 reply_nterror(req, NT_STATUS_NO_MEMORY);
8928 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8929 smb_fname_dst->base_name,
8931 TALLOC_FREE(talloced);
8935 TALLOC_FREE(dir_hnd);
8936 TALLOC_FREE(talloced);
8937 reply_nterror(req, NT_STATUS_NO_MEMORY);
8941 TALLOC_FREE(smb_fname_dst->base_name);
8942 smb_fname_dst->base_name = destname;
8944 status = check_name(conn, smb_fname_src);
8945 if (!NT_STATUS_IS_OK(status)) {
8946 TALLOC_FREE(dir_hnd);
8947 TALLOC_FREE(talloced);
8948 reply_nterror(req, status);
8952 status = check_name(conn, smb_fname_dst);
8953 if (!NT_STATUS_IS_OK(status)) {
8954 TALLOC_FREE(dir_hnd);
8955 TALLOC_FREE(talloced);
8956 reply_nterror(req, status);
8960 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8961 smb_fname_src->base_name,
8962 smb_fname_dst->base_name));
8964 status = copy_file(ctx, conn, smb_fname_src,
8965 smb_fname_dst, ofun, count,
8966 target_is_directory);
8967 if (NT_STATUS_IS_OK(status)) {
8971 TALLOC_FREE(talloced);
8973 TALLOC_FREE(dir_hnd);
8977 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8981 reply_outbuf(req, 1, 0);
8982 SSVAL(req->outbuf,smb_vwv0,count);
8984 TALLOC_FREE(smb_fname_src);
8985 TALLOC_FREE(smb_fname_src_dir);
8986 TALLOC_FREE(smb_fname_dst);
8987 TALLOC_FREE(fname_src);
8988 TALLOC_FREE(fname_dst);
8989 TALLOC_FREE(fname_src_mask);
8990 TALLOC_FREE(fname_src_dir);
8992 END_PROFILE(SMBcopy);
8997 #define DBGC_CLASS DBGC_LOCKING
8999 /****************************************************************************
9000 Get a lock pid, dealing with large count requests.
9001 ****************************************************************************/
9003 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
9004 bool large_file_format)
9006 if(!large_file_format)
9007 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9009 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9012 /****************************************************************************
9013 Get a lock count, dealing with large count requests.
9014 ****************************************************************************/
9016 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9017 bool large_file_format)
9021 if(!large_file_format) {
9022 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9025 * No BVAL, this is reversed!
9027 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9028 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9034 /****************************************************************************
9035 Get a lock offset, dealing with large offset requests.
9036 ****************************************************************************/
9038 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9039 bool large_file_format)
9041 uint64_t offset = 0;
9043 if(!large_file_format) {
9044 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9047 * No BVAL, this is reversed!
9049 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9050 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9056 struct smbd_do_unlocking_state {
9057 struct files_struct *fsp;
9058 uint16_t num_ulocks;
9059 struct smbd_lock_element *ulocks;
9060 enum brl_flavour lock_flav;
9064 static void smbd_do_unlocking_fn(
9067 bool *pmodified_dependent,
9070 struct smbd_do_unlocking_state *state = private_data;
9071 struct files_struct *fsp = state->fsp;
9072 enum brl_flavour lock_flav = state->lock_flav;
9075 for (i = 0; i < state->num_ulocks; i++) {
9076 struct smbd_lock_element *e = &state->ulocks[i];
9078 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9079 "pid %"PRIu64", file %s\n",
9085 if (e->brltype != UNLOCK_LOCK) {
9086 /* this can only happen with SMB2 */
9087 state->status = NT_STATUS_INVALID_PARAMETER;
9091 state->status = do_unlock(
9092 fsp, e->smblctx, e->count, e->offset, lock_flav);
9094 DBG_DEBUG("do_unlock returned %s\n",
9095 nt_errstr(state->status));
9097 if (!NT_STATUS_IS_OK(state->status)) {
9102 *pmodified_dependent = true;
9105 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9107 uint16_t num_ulocks,
9108 struct smbd_lock_element *ulocks,
9109 enum brl_flavour lock_flav)
9111 struct smbd_do_unlocking_state state = {
9113 .num_ulocks = num_ulocks,
9115 .lock_flav = lock_flav,
9119 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9121 status = share_mode_do_locked(
9122 fsp->file_id, smbd_do_unlocking_fn, &state);
9124 if (!NT_STATUS_IS_OK(status)) {
9125 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9129 if (!NT_STATUS_IS_OK(state.status)) {
9130 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9132 return state.status;
9135 return NT_STATUS_OK;
9138 /****************************************************************************
9139 Reply to a lockingX request.
9140 ****************************************************************************/
9142 static void reply_lockingx_done(struct tevent_req *subreq);
9144 void reply_lockingX(struct smb_request *req)
9146 connection_struct *conn = req->conn;
9148 unsigned char locktype;
9149 enum brl_type brltype;
9150 unsigned char oplocklevel;
9151 uint16_t num_ulocks;
9153 int32_t lock_timeout;
9155 const uint8_t *data;
9156 bool large_file_format;
9157 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9158 struct smbd_lock_element *locks = NULL;
9159 struct tevent_req *subreq = NULL;
9161 START_PROFILE(SMBlockingX);
9164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9165 END_PROFILE(SMBlockingX);
9169 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9170 locktype = CVAL(req->vwv+3, 0);
9171 oplocklevel = CVAL(req->vwv+3, 1);
9172 num_ulocks = SVAL(req->vwv+6, 0);
9173 num_locks = SVAL(req->vwv+7, 0);
9174 lock_timeout = IVAL(req->vwv+4, 0);
9175 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9177 if (!check_fsp(conn, req, fsp)) {
9178 END_PROFILE(SMBlockingX);
9184 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9185 /* we don't support these - and CANCEL_LOCK makes w2k
9186 and XP reboot so I don't really want to be
9187 compatible! (tridge) */
9188 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9189 END_PROFILE(SMBlockingX);
9193 /* Check if this is an oplock break on a file
9194 we have granted an oplock on.
9196 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9197 /* Client can insist on breaking to none. */
9198 bool break_to_none = (oplocklevel == 0);
9201 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9202 "for %s\n", (unsigned int)oplocklevel,
9203 fsp_fnum_dbg(fsp)));
9206 * Make sure we have granted an exclusive or batch oplock on
9210 if (fsp->oplock_type == 0) {
9212 /* The Samba4 nbench simulator doesn't understand
9213 the difference between break to level2 and break
9214 to none from level2 - it sends oplock break
9215 replies in both cases. Don't keep logging an error
9216 message here - just ignore it. JRA. */
9218 DEBUG(5,("reply_lockingX: Error : oplock break from "
9219 "client for %s (oplock=%d) and no "
9220 "oplock granted on this file (%s).\n",
9221 fsp_fnum_dbg(fsp), fsp->oplock_type,
9224 /* if this is a pure oplock break request then don't
9226 if (num_locks == 0 && num_ulocks == 0) {
9227 END_PROFILE(SMBlockingX);
9231 END_PROFILE(SMBlockingX);
9232 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9236 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9238 result = remove_oplock(fsp);
9240 result = downgrade_oplock(fsp);
9244 DEBUG(0, ("reply_lockingX: error in removing "
9245 "oplock on file %s\n", fsp_str_dbg(fsp)));
9246 /* Hmmm. Is this panic justified? */
9247 smb_panic("internal tdb error");
9250 /* if this is a pure oplock break request then don't send a
9252 if (num_locks == 0 && num_ulocks == 0) {
9253 /* Sanity check - ensure a pure oplock break is not a
9255 if (CVAL(req->vwv+0, 0) != 0xff) {
9256 DEBUG(0,("reply_lockingX: Error : pure oplock "
9257 "break is a chained %d request !\n",
9258 (unsigned int)CVAL(req->vwv+0, 0)));
9260 END_PROFILE(SMBlockingX);
9266 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9267 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9268 END_PROFILE(SMBlockingX);
9272 if (num_ulocks != 0) {
9273 struct smbd_lock_element *ulocks = NULL;
9276 ulocks = talloc_array(
9277 req, struct smbd_lock_element, num_ulocks);
9278 if (ulocks == NULL) {
9279 reply_nterror(req, NT_STATUS_NO_MEMORY);
9280 END_PROFILE(SMBlockingX);
9285 * Data now points at the beginning of the list of
9286 * smb_unlkrng structs
9288 for (i = 0; i < num_ulocks; i++) {
9289 ulocks[i].req_guid = smbd_request_guid(req,
9291 ulocks[i].smblctx = get_lock_pid(
9292 data, i, large_file_format);
9293 ulocks[i].count = get_lock_count(
9294 data, i, large_file_format);
9295 ulocks[i].offset = get_lock_offset(
9296 data, i, large_file_format);
9297 ulocks[i].brltype = UNLOCK_LOCK;
9301 * Unlock cancels pending locks
9304 ok = smbd_smb1_brl_finish_by_lock(
9311 reply_outbuf(req, 2, 0);
9312 SSVAL(req->outbuf, smb_vwv0, 0xff);
9313 SSVAL(req->outbuf, smb_vwv1, 0);
9314 END_PROFILE(SMBlockingX);
9318 status = smbd_do_unlocking(
9319 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9320 TALLOC_FREE(ulocks);
9321 if (!NT_STATUS_IS_OK(status)) {
9322 END_PROFILE(SMBlockingX);
9323 reply_nterror(req, status);
9328 /* Now do any requested locks */
9329 data += ((large_file_format ? 20 : 10)*num_ulocks);
9331 /* Data now points at the beginning of the list
9332 of smb_lkrng structs */
9334 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9335 brltype = READ_LOCK;
9337 brltype = WRITE_LOCK;
9340 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9341 if (locks == NULL) {
9342 reply_nterror(req, NT_STATUS_NO_MEMORY);
9343 END_PROFILE(SMBlockingX);
9347 for (i = 0; i < num_locks; i++) {
9348 locks[i].req_guid = smbd_request_guid(req, i),
9349 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9350 locks[i].count = get_lock_count(data, i, large_file_format);
9351 locks[i].offset = get_lock_offset(data, i, large_file_format);
9352 locks[i].brltype = brltype;
9355 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9359 if (num_locks == 0) {
9360 /* See smbtorture3 lock11 test */
9361 reply_outbuf(req, 2, 0);
9362 /* andx chain ends */
9363 SSVAL(req->outbuf, smb_vwv0, 0xff);
9364 SSVAL(req->outbuf, smb_vwv1, 0);
9365 END_PROFILE(SMBlockingX);
9369 ok = smbd_smb1_brl_finish_by_lock(
9373 locks[0], /* Windows only cancels the first lock */
9374 NT_STATUS_FILE_LOCK_CONFLICT);
9377 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9378 END_PROFILE(SMBlockingX);
9382 reply_outbuf(req, 2, 0);
9383 SSVAL(req->outbuf, smb_vwv0, 0xff);
9384 SSVAL(req->outbuf, smb_vwv1, 0);
9385 END_PROFILE(SMBlockingX);
9389 subreq = smbd_smb1_do_locks_send(
9399 if (subreq == NULL) {
9400 reply_nterror(req, NT_STATUS_NO_MEMORY);
9401 END_PROFILE(SMBlockingX);
9404 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9405 END_PROFILE(SMBlockingX);
9408 static void reply_lockingx_done(struct tevent_req *subreq)
9410 struct smb_request *req = NULL;
9414 START_PROFILE(SMBlockingX);
9416 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9419 status = smbd_smb1_do_locks_recv(subreq);
9420 TALLOC_FREE(subreq);
9422 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9424 if (NT_STATUS_IS_OK(status)) {
9425 reply_outbuf(req, 2, 0);
9426 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9427 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9429 reply_nterror(req, status);
9432 ok = srv_send_smb(req->xconn,
9433 (char *)req->outbuf,
9436 IS_CONN_ENCRYPTED(req->conn),
9439 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9442 END_PROFILE(SMBlockingX);
9446 #define DBGC_CLASS DBGC_ALL
9448 /****************************************************************************
9449 Reply to a SMBreadbmpx (read block multiplex) request.
9450 Always reply with an error, if someone has a platform really needs this,
9451 please contact vl@samba.org
9452 ****************************************************************************/
9454 void reply_readbmpx(struct smb_request *req)
9456 START_PROFILE(SMBreadBmpx);
9457 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9458 END_PROFILE(SMBreadBmpx);
9462 /****************************************************************************
9463 Reply to a SMBreadbs (read block multiplex secondary) request.
9464 Always reply with an error, if someone has a platform really needs this,
9465 please contact vl@samba.org
9466 ****************************************************************************/
9468 void reply_readbs(struct smb_request *req)
9470 START_PROFILE(SMBreadBs);
9471 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9472 END_PROFILE(SMBreadBs);
9476 /****************************************************************************
9477 Reply to a SMBsetattrE.
9478 ****************************************************************************/
9480 void reply_setattrE(struct smb_request *req)
9482 connection_struct *conn = req->conn;
9483 struct smb_file_time ft;
9487 START_PROFILE(SMBsetattrE);
9488 init_smb_file_time(&ft);
9491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9495 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9497 if(!fsp || (fsp->conn != conn)) {
9498 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9503 * Convert the DOS times into unix times.
9506 ft.atime = time_t_to_full_timespec(
9507 srv_make_unix_date2(req->vwv+3));
9508 ft.mtime = time_t_to_full_timespec(
9509 srv_make_unix_date2(req->vwv+5));
9510 ft.create_time = time_t_to_full_timespec(
9511 srv_make_unix_date2(req->vwv+1));
9513 reply_outbuf(req, 0, 0);
9516 * Patch from Ray Frush <frush@engr.colostate.edu>
9517 * Sometimes times are sent as zero - ignore them.
9520 /* Ensure we have a valid stat struct for the source. */
9521 status = vfs_stat_fsp(fsp);
9522 if (!NT_STATUS_IS_OK(status)) {
9523 reply_nterror(req, status);
9527 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9528 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9532 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9533 if (!NT_STATUS_IS_OK(status)) {
9534 reply_nterror(req, status);
9538 if (fsp->fsp_flags.modified) {
9539 trigger_write_time_update_immediate(fsp);
9542 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9545 (unsigned int)ft.atime.tv_sec,
9546 (unsigned int)ft.mtime.tv_sec,
9547 (unsigned int)ft.create_time.tv_sec
9550 END_PROFILE(SMBsetattrE);
9555 /* Back from the dead for OS/2..... JRA. */
9557 /****************************************************************************
9558 Reply to a SMBwritebmpx (write block multiplex primary) request.
9559 Always reply with an error, if someone has a platform really needs this,
9560 please contact vl@samba.org
9561 ****************************************************************************/
9563 void reply_writebmpx(struct smb_request *req)
9565 START_PROFILE(SMBwriteBmpx);
9566 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9567 END_PROFILE(SMBwriteBmpx);
9571 /****************************************************************************
9572 Reply to a SMBwritebs (write block multiplex secondary) request.
9573 Always reply with an error, if someone has a platform really needs this,
9574 please contact vl@samba.org
9575 ****************************************************************************/
9577 void reply_writebs(struct smb_request *req)
9579 START_PROFILE(SMBwriteBs);
9580 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9581 END_PROFILE(SMBwriteBs);
9585 /****************************************************************************
9586 Reply to a SMBgetattrE.
9587 ****************************************************************************/
9589 void reply_getattrE(struct smb_request *req)
9591 connection_struct *conn = req->conn;
9594 struct timespec create_ts;
9597 START_PROFILE(SMBgetattrE);
9600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9601 END_PROFILE(SMBgetattrE);
9605 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9607 if(!fsp || (fsp->conn != conn)) {
9608 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9609 END_PROFILE(SMBgetattrE);
9613 /* Do an fstat on this file */
9614 status = vfs_stat_fsp(fsp);
9615 if (!NT_STATUS_IS_OK(status)) {
9616 reply_nterror(req, status);
9617 END_PROFILE(SMBgetattrE);
9621 mode = dos_mode(conn, fsp->fsp_name);
9624 * Convert the times into dos times. Set create
9625 * date to be last modify date as UNIX doesn't save
9629 reply_outbuf(req, 11, 0);
9631 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9632 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9633 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9634 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9635 /* Should we check pending modtime here ? JRA */
9636 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9637 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9639 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9640 SIVAL(req->outbuf, smb_vwv6, 0);
9641 SIVAL(req->outbuf, smb_vwv8, 0);
9643 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9644 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9645 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9647 SSVAL(req->outbuf,smb_vwv10, mode);
9649 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9651 END_PROFILE(SMBgetattrE);