2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "librpc/gen_ndr/open_files.h"
49 /****************************************************************************
50 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
51 path or anything including wildcards.
52 We're assuming here that '/' is not the second byte in any multibyte char
53 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
55 ****************************************************************************/
57 /* Custom version for processing POSIX paths. */
58 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
60 static NTSTATUS check_path_syntax_internal(char *path,
62 bool *p_last_component_contains_wcard)
66 NTSTATUS ret = NT_STATUS_OK;
67 bool start_of_name_component = True;
68 bool stream_started = false;
70 *p_last_component_contains_wcard = False;
77 return NT_STATUS_OBJECT_NAME_INVALID;
80 return NT_STATUS_OBJECT_NAME_INVALID;
82 if (strchr_m(&s[1], ':')) {
83 return NT_STATUS_OBJECT_NAME_INVALID;
89 if ((*s == ':') && !posix_path && !stream_started) {
90 if (*p_last_component_contains_wcard) {
91 return NT_STATUS_OBJECT_NAME_INVALID;
93 /* Stream names allow more characters than file names.
94 We're overloading posix_path here to allow a wider
95 range of characters. If stream_started is true this
96 is still a Windows path even if posix_path is true.
99 stream_started = true;
100 start_of_name_component = false;
104 return NT_STATUS_OBJECT_NAME_INVALID;
108 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
110 * Safe to assume is not the second part of a mb char
111 * as this is handled below.
113 /* Eat multiple '/' or '\\' */
114 while (IS_PATH_SEP(*s,posix_path)) {
117 if ((d != path) && (*s != '\0')) {
118 /* We only care about non-leading or trailing '/' or '\\' */
122 start_of_name_component = True;
124 *p_last_component_contains_wcard = False;
128 if (start_of_name_component) {
129 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
130 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
133 * No mb char starts with '.' so we're safe checking the directory separator here.
136 /* If we just added a '/' - delete it */
137 if ((d > path) && (*(d-1) == '/')) {
142 /* Are we at the start ? Can't go back further if so. */
144 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
147 /* Go back one level... */
148 /* We know this is safe as '/' cannot be part of a mb sequence. */
149 /* NOTE - if this assumption is invalid we are not in good shape... */
150 /* Decrement d first as d points to the *next* char to write into. */
151 for (d--; d > path; d--) {
155 s += 2; /* Else go past the .. */
156 /* We're still at the start of a name component, just the previous one. */
159 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
171 if (*s <= 0x1f || *s == '|') {
172 return NT_STATUS_OBJECT_NAME_INVALID;
180 *p_last_component_contains_wcard = True;
189 /* Get the size of the next MB character. */
190 next_codepoint(s,&siz);
208 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
210 return NT_STATUS_INVALID_PARAMETER;
213 start_of_name_component = False;
221 /****************************************************************************
222 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
223 No wildcards allowed.
224 ****************************************************************************/
226 NTSTATUS check_path_syntax(char *path)
229 return check_path_syntax_internal(path, False, &ignore);
232 /****************************************************************************
233 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
234 Wildcards allowed - p_contains_wcard returns true if the last component contained
236 ****************************************************************************/
238 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
240 return check_path_syntax_internal(path, False, p_contains_wcard);
243 /****************************************************************************
244 Check the path for a POSIX client.
245 We're assuming here that '/' is not the second byte in any multibyte char
246 set (a safe assumption).
247 ****************************************************************************/
249 NTSTATUS check_path_syntax_posix(char *path)
252 return check_path_syntax_internal(path, True, &ignore);
255 /****************************************************************************
256 Pull a string and check the path allowing a wilcard - provide for error return.
257 Passes in posix flag.
258 ****************************************************************************/
260 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
261 const char *base_ptr,
267 bool posix_pathnames,
269 bool *contains_wcard)
275 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
279 *err = NT_STATUS_INVALID_PARAMETER;
283 *contains_wcard = False;
285 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
287 * For a DFS path the function parse_dfs_path()
288 * will do the path processing, just make a copy.
294 if (posix_pathnames) {
295 *err = check_path_syntax_posix(*pp_dest);
297 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
303 /****************************************************************************
304 Pull a string and check the path allowing a wilcard - provide for error return.
305 ****************************************************************************/
307 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
308 const char *base_ptr,
315 bool *contains_wcard)
317 return srvstr_get_path_wcard_internal(ctx,
329 /****************************************************************************
330 Pull a string and check the path allowing a wilcard - provide for error return.
331 posix_pathnames version.
332 ****************************************************************************/
334 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
335 const char *base_ptr,
342 bool *contains_wcard)
344 return srvstr_get_path_wcard_internal(ctx,
356 /****************************************************************************
357 Pull a string and check the path - provide for error return.
358 ****************************************************************************/
360 size_t srvstr_get_path(TALLOC_CTX *ctx,
361 const char *base_ptr,
370 return srvstr_get_path_wcard_internal(ctx,
382 /****************************************************************************
383 Pull a string and check the path - provide for error return.
384 posix_pathnames version.
385 ****************************************************************************/
387 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
388 const char *base_ptr,
397 return srvstr_get_path_wcard_internal(ctx,
410 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
411 char **pp_dest, const char *src, int flags,
412 NTSTATUS *err, bool *contains_wcard)
414 ssize_t bufrem = smbreq_bufrem(req, src);
417 *err = NT_STATUS_INVALID_PARAMETER;
421 if (req->posix_pathnames) {
422 return srvstr_get_path_wcard_internal(mem_ctx,
423 (const char *)req->inbuf,
433 return srvstr_get_path_wcard_internal(mem_ctx,
434 (const char *)req->inbuf,
446 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
447 char **pp_dest, const char *src, int flags,
451 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
452 flags, err, &ignore);
456 * pull a string from the smb_buf part of a packet. In this case the
457 * string can either be null terminated or it can be terminated by the
458 * end of the smbbuf area
460 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
461 char **dest, const uint8_t *src, int flags)
463 ssize_t bufrem = smbreq_bufrem(req, src);
469 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
473 /****************************************************************************
474 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
475 ****************************************************************************/
477 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
480 if ((fsp == NULL) || (conn == NULL)) {
481 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
484 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
485 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
491 /****************************************************************************
492 Check if we have a correct fsp pointing to a file.
493 ****************************************************************************/
495 bool check_fsp(connection_struct *conn, struct smb_request *req,
498 if (!check_fsp_open(conn, req, fsp)) {
501 if (fsp->is_directory) {
502 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
505 if (fsp->fh->fd == -1) {
506 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
509 fsp->num_smb_operations++;
513 /****************************************************************************
514 Check if we have a correct fsp pointing to a quota fake file. Replacement for
515 the CHECK_NTQUOTA_HANDLE_OK macro.
516 ****************************************************************************/
518 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
521 if (!check_fsp_open(conn, req, fsp)) {
525 if (fsp->is_directory) {
529 if (fsp->fake_file_handle == NULL) {
533 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
537 if (fsp->fake_file_handle->private_data == NULL) {
544 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
545 const char *name, int name_type)
548 char *trim_name_type;
549 const char *retarget_parm;
552 int retarget_type = 0x20;
553 int retarget_port = NBT_SMB_PORT;
554 struct sockaddr_storage retarget_addr;
555 struct sockaddr_in *in_addr;
559 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
563 trim_name = talloc_strdup(talloc_tos(), name);
564 if (trim_name == NULL) {
567 trim_char(trim_name, ' ', ' ');
569 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
571 if (trim_name_type == NULL) {
575 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
576 trim_name_type, NULL);
577 if (retarget_parm == NULL) {
578 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
581 if (retarget_parm == NULL) {
585 retarget = talloc_strdup(trim_name, retarget_parm);
586 if (retarget == NULL) {
590 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
592 p = strchr(retarget, ':');
595 retarget_port = atoi(p);
598 p = strchr_m(retarget, '#');
601 if (sscanf(p, "%x", &retarget_type) != 1) {
606 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
608 DEBUG(10, ("could not resolve %s\n", retarget));
612 if (retarget_addr.ss_family != AF_INET) {
613 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
617 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
619 _smb_setlen(outbuf, 6);
620 SCVAL(outbuf, 0, 0x84);
621 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
622 *(uint16_t *)(outbuf+8) = htons(retarget_port);
624 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
626 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
632 TALLOC_FREE(trim_name);
636 static void reply_called_name_not_present(char *outbuf)
638 smb_setlen(outbuf, 1);
639 SCVAL(outbuf, 0, 0x83);
640 SCVAL(outbuf, 4, 0x82);
643 /****************************************************************************
644 Reply to a (netbios-level) special message.
645 ****************************************************************************/
647 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
649 struct smbd_server_connection *sconn = xconn->client->sconn;
650 int msg_type = CVAL(inbuf,0);
651 int msg_flags = CVAL(inbuf,1);
653 * We only really use 4 bytes of the outbuf, but for the smb_setlen
654 * calculation & friends (srv_send_smb uses that) we need the full smb
657 char outbuf[smb_size];
659 memset(outbuf, '\0', sizeof(outbuf));
661 smb_setlen(outbuf,0);
664 case NBSSrequest: /* session request */
666 /* inbuf_size is guarenteed to be at least 4. */
668 int name_type1, name_type2;
669 int name_len1, name_len2;
673 if (xconn->transport.nbt.got_session) {
674 exit_server_cleanly("multiple session request not permitted");
677 SCVAL(outbuf,0,NBSSpositive);
680 /* inbuf_size is guaranteed to be at least 4. */
681 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
682 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
683 DEBUG(0,("Invalid name length in session request\n"));
684 reply_called_name_not_present(outbuf);
687 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
688 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
689 DEBUG(0,("Invalid name length in session request\n"));
690 reply_called_name_not_present(outbuf);
694 name_type1 = name_extract((unsigned char *)inbuf,
695 inbuf_size,(unsigned int)4,name1);
696 name_type2 = name_extract((unsigned char *)inbuf,
697 inbuf_size,(unsigned int)(4 + name_len1),name2);
699 if (name_type1 == -1 || name_type2 == -1) {
700 DEBUG(0,("Invalid name type in session request\n"));
701 reply_called_name_not_present(outbuf);
705 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
706 name1, name_type1, name2, name_type2));
708 if (netbios_session_retarget(xconn, name1, name_type1)) {
709 exit_server_cleanly("retargeted client");
713 * Windows NT/2k uses "*SMBSERVER" and XP uses
714 * "*SMBSERV" arrggg!!!
716 if (strequal(name1, "*SMBSERVER ")
717 || strequal(name1, "*SMBSERV ")) {
720 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
723 exit_server_cleanly("could not allocate raddr");
726 fstrcpy(name1, raddr);
729 set_local_machine_name(name1, True);
730 set_remote_machine_name(name2, True);
732 if (is_ipaddress(sconn->remote_hostname)) {
733 char *p = discard_const_p(char, sconn->remote_hostname);
737 sconn->remote_hostname = talloc_strdup(sconn,
738 get_remote_machine_name());
739 if (sconn->remote_hostname == NULL) {
740 exit_server_cleanly("could not copy remote name");
742 xconn->remote_hostname = sconn->remote_hostname;
745 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
746 get_local_machine_name(), get_remote_machine_name(),
749 if (name_type2 == 'R') {
750 /* We are being asked for a pathworks session ---
752 reply_called_name_not_present(outbuf);
756 reload_services(sconn, conn_snum_used, true);
759 xconn->transport.nbt.got_session = true;
763 case 0x89: /* session keepalive request
764 (some old clients produce this?) */
765 SCVAL(outbuf,0,NBSSkeepalive);
769 case NBSSpositive: /* positive session response */
770 case NBSSnegative: /* negative session response */
771 case NBSSretarget: /* retarget session response */
772 DEBUG(0,("Unexpected session response\n"));
775 case NBSSkeepalive: /* session keepalive */
780 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
781 msg_type, msg_flags));
783 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
784 exit_server_cleanly("reply_special: srv_send_smb failed.");
787 if (CVAL(outbuf, 0) != 0x82) {
788 exit_server_cleanly("invalid netbios session");
793 /****************************************************************************
795 conn POINTER CAN BE NULL HERE !
796 ****************************************************************************/
798 void reply_tcon(struct smb_request *req)
800 connection_struct *conn = req->conn;
802 char *service_buf = NULL;
803 char *password = NULL;
809 TALLOC_CTX *ctx = talloc_tos();
810 struct smbXsrv_connection *xconn = req->xconn;
811 NTTIME now = timeval_to_nttime(&req->request_time);
813 START_PROFILE(SMBtcon);
815 if (req->buflen < 4) {
816 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
817 END_PROFILE(SMBtcon);
822 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
824 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
826 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
829 if (service_buf == NULL || password == NULL || dev == NULL) {
830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
831 END_PROFILE(SMBtcon);
834 p2 = strrchr_m(service_buf,'\\');
838 service = service_buf;
841 conn = make_connection(req, now, service, dev,
842 req->vuid,&nt_status);
846 reply_nterror(req, nt_status);
847 END_PROFILE(SMBtcon);
851 reply_outbuf(req, 2, 0);
852 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
853 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
854 SSVAL(req->outbuf,smb_tid,conn->cnum);
856 DEBUG(3,("tcon service=%s cnum=%d\n",
857 service, conn->cnum));
859 END_PROFILE(SMBtcon);
863 /****************************************************************************
864 Reply to a tcon and X.
865 conn POINTER CAN BE NULL HERE !
866 ****************************************************************************/
868 void reply_tcon_and_X(struct smb_request *req)
870 connection_struct *conn = req->conn;
871 const char *service = NULL;
872 TALLOC_CTX *ctx = talloc_tos();
873 /* what the client thinks the device is */
874 char *client_devicetype = NULL;
875 /* what the server tells the client the share represents */
876 const char *server_devicetype;
883 struct smbXsrv_session *session = NULL;
884 NTTIME now = timeval_to_nttime(&req->request_time);
885 bool session_key_updated = false;
886 uint16_t optional_support = 0;
887 struct smbXsrv_connection *xconn = req->xconn;
889 START_PROFILE(SMBtconX);
892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
893 END_PROFILE(SMBtconX);
897 passlen = SVAL(req->vwv+3, 0);
898 tcon_flags = SVAL(req->vwv+2, 0);
900 /* we might have to close an old one */
901 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
902 struct smbXsrv_tcon *tcon;
910 * TODO: cancel all outstanding requests on the tcon
912 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
913 if (!NT_STATUS_IS_OK(status)) {
914 DEBUG(0, ("reply_tcon_and_X: "
915 "smbXsrv_tcon_disconnect() failed: %s\n",
918 * If we hit this case, there is something completely
919 * wrong, so we better disconnect the transport connection.
921 END_PROFILE(SMBtconX);
922 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
928 * This tree id is gone. Make sure we can't re-use it
934 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
935 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
936 END_PROFILE(SMBtconX);
940 if (xconn->smb1.negprot.encrypted_passwords) {
941 p = req->buf + passlen;
943 p = req->buf + passlen + 1;
946 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
950 END_PROFILE(SMBtconX);
955 * the service name can be either: \\server\share
956 * or share directly like on the DELL PowerVault 705
959 q = strchr_m(path+2,'\\');
961 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
962 END_PROFILE(SMBtconX);
970 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
971 &client_devicetype, p,
972 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
974 if (client_devicetype == NULL) {
975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
976 END_PROFILE(SMBtconX);
980 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
982 nt_status = smb1srv_session_lookup(xconn,
983 req->vuid, now, &session);
984 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
985 reply_force_doserror(req, ERRSRV, ERRbaduid);
986 END_PROFILE(SMBtconX);
989 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
990 reply_nterror(req, nt_status);
991 END_PROFILE(SMBtconX);
994 if (!NT_STATUS_IS_OK(nt_status)) {
995 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
996 END_PROFILE(SMBtconX);
1000 if (session->global->auth_session_info == NULL) {
1001 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1002 END_PROFILE(SMBtconX);
1007 * If there is no application key defined yet
1010 * This means we setup the application key on the
1011 * first tcon that happens via the given session.
1013 * Once the application key is defined, it does not
1016 if (session->global->application_key.length == 0 &&
1017 smb2_signing_key_valid(session->global->signing_key))
1019 struct smbXsrv_session *x = session;
1020 struct auth_session_info *session_info =
1021 session->global->auth_session_info;
1022 uint8_t session_key[16];
1024 ZERO_STRUCT(session_key);
1025 memcpy(session_key, x->global->signing_key->blob.data,
1026 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
1029 * The application key is truncated/padded to 16 bytes
1031 x->global->application_key = data_blob_talloc(x->global,
1033 sizeof(session_key));
1034 ZERO_STRUCT(session_key);
1035 if (x->global->application_key.data == NULL) {
1036 reply_nterror(req, NT_STATUS_NO_MEMORY);
1037 END_PROFILE(SMBtconX);
1041 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1044 status = smb_key_derivation(x->global->application_key.data,
1045 x->global->application_key.length,
1046 x->global->application_key.data);
1047 if (!NT_STATUS_IS_OK(status)) {
1048 DBG_ERR("smb_key_derivation failed: %s\n",
1052 optional_support |= SMB_EXTENDED_SIGNATURES;
1056 * Place the application key into the session_info
1058 data_blob_clear_free(&session_info->session_key);
1059 session_info->session_key = data_blob_dup_talloc(session_info,
1060 x->global->application_key);
1061 if (session_info->session_key.data == NULL) {
1062 data_blob_clear_free(&x->global->application_key);
1063 reply_nterror(req, NT_STATUS_NO_MEMORY);
1064 END_PROFILE(SMBtconX);
1067 session_key_updated = true;
1070 conn = make_connection(req, now, service, client_devicetype,
1071 req->vuid, &nt_status);
1075 if (session_key_updated) {
1076 struct smbXsrv_session *x = session;
1077 struct auth_session_info *session_info =
1078 session->global->auth_session_info;
1079 data_blob_clear_free(&x->global->application_key);
1080 data_blob_clear_free(&session_info->session_key);
1082 reply_nterror(req, nt_status);
1083 END_PROFILE(SMBtconX);
1088 server_devicetype = "IPC";
1089 else if ( IS_PRINT(conn) )
1090 server_devicetype = "LPT1:";
1092 server_devicetype = "A:";
1094 if (get_Protocol() < PROTOCOL_NT1) {
1095 reply_outbuf(req, 2, 0);
1096 if (message_push_string(&req->outbuf, server_devicetype,
1097 STR_TERMINATE|STR_ASCII) == -1) {
1098 reply_nterror(req, NT_STATUS_NO_MEMORY);
1099 END_PROFILE(SMBtconX);
1103 /* NT sets the fstype of IPC$ to the null string */
1104 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1106 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1107 /* Return permissions. */
1111 reply_outbuf(req, 7, 0);
1114 perm1 = FILE_ALL_ACCESS;
1115 perm2 = FILE_ALL_ACCESS;
1117 perm1 = conn->share_access;
1120 SIVAL(req->outbuf, smb_vwv3, perm1);
1121 SIVAL(req->outbuf, smb_vwv5, perm2);
1123 reply_outbuf(req, 3, 0);
1126 if ((message_push_string(&req->outbuf, server_devicetype,
1127 STR_TERMINATE|STR_ASCII) == -1)
1128 || (message_push_string(&req->outbuf, fstype,
1129 STR_TERMINATE) == -1)) {
1130 reply_nterror(req, NT_STATUS_NO_MEMORY);
1131 END_PROFILE(SMBtconX);
1135 /* what does setting this bit do? It is set by NT4 and
1136 may affect the ability to autorun mounted cdroms */
1137 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1139 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1141 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1142 DEBUG(2,("Serving %s as a Dfs root\n",
1143 lp_servicename(ctx, SNUM(conn)) ));
1144 optional_support |= SMB_SHARE_IN_DFS;
1147 SSVAL(req->outbuf, smb_vwv2, optional_support);
1150 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1151 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1153 DEBUG(3,("tconX service=%s \n",
1156 /* set the incoming and outgoing tid to the just created one */
1157 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1158 SSVAL(req->outbuf,smb_tid,conn->cnum);
1160 END_PROFILE(SMBtconX);
1162 req->tid = conn->cnum;
1165 /****************************************************************************
1166 Reply to an unknown type.
1167 ****************************************************************************/
1169 void reply_unknown_new(struct smb_request *req, uint8_t type)
1171 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1172 smb_fn_name(type), type, type));
1173 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1177 /****************************************************************************
1179 conn POINTER CAN BE NULL HERE !
1180 ****************************************************************************/
1182 void reply_ioctl(struct smb_request *req)
1184 connection_struct *conn = req->conn;
1187 uint32_t ioctl_code;
1191 START_PROFILE(SMBioctl);
1194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1195 END_PROFILE(SMBioctl);
1199 device = SVAL(req->vwv+1, 0);
1200 function = SVAL(req->vwv+2, 0);
1201 ioctl_code = (device << 16) + function;
1203 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1205 switch (ioctl_code) {
1206 case IOCTL_QUERY_JOB_INFO:
1210 reply_force_doserror(req, ERRSRV, ERRnosupport);
1211 END_PROFILE(SMBioctl);
1215 reply_outbuf(req, 8, replysize+1);
1216 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1217 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1218 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1219 p = smb_buf(req->outbuf);
1220 memset(p, '\0', replysize+1); /* valgrind-safe. */
1221 p += 1; /* Allow for alignment */
1223 switch (ioctl_code) {
1224 case IOCTL_QUERY_JOB_INFO:
1228 files_struct *fsp = file_fsp(
1229 req, SVAL(req->vwv+0, 0));
1231 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1232 END_PROFILE(SMBioctl);
1236 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1238 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1239 lp_netbios_name(), 15,
1240 STR_TERMINATE|STR_ASCII, &len);
1241 if (!NT_STATUS_IS_OK(status)) {
1242 reply_nterror(req, status);
1243 END_PROFILE(SMBioctl);
1247 status = srvstr_push((char *)req->outbuf, req->flags2,
1249 lp_servicename(talloc_tos(),
1251 13, STR_TERMINATE|STR_ASCII, &len);
1252 if (!NT_STATUS_IS_OK(status)) {
1253 reply_nterror(req, status);
1254 END_PROFILE(SMBioctl);
1258 memset(p+18, 0, 13);
1264 END_PROFILE(SMBioctl);
1268 /****************************************************************************
1269 Strange checkpath NTSTATUS mapping.
1270 ****************************************************************************/
1272 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1274 /* Strange DOS error code semantics only for checkpath... */
1275 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1276 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1277 /* We need to map to ERRbadpath */
1278 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1284 /****************************************************************************
1285 Reply to a checkpath.
1286 ****************************************************************************/
1288 void reply_checkpath(struct smb_request *req)
1290 connection_struct *conn = req->conn;
1291 struct smb_filename *smb_fname = NULL;
1294 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1295 TALLOC_CTX *ctx = talloc_tos();
1297 START_PROFILE(SMBcheckpath);
1299 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1300 STR_TERMINATE, &status);
1302 if (!NT_STATUS_IS_OK(status)) {
1303 status = map_checkpath_error(req->flags2, status);
1304 reply_nterror(req, status);
1305 END_PROFILE(SMBcheckpath);
1309 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1311 status = filename_convert(ctx,
1319 if (!NT_STATUS_IS_OK(status)) {
1320 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1321 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1322 ERRSRV, ERRbadpath);
1323 END_PROFILE(SMBcheckpath);
1329 if (!VALID_STAT(smb_fname->st) &&
1330 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1331 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1332 smb_fname_str_dbg(smb_fname), strerror(errno)));
1333 status = map_nt_error_from_unix(errno);
1337 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1338 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1339 ERRDOS, ERRbadpath);
1343 reply_outbuf(req, 0, 0);
1346 /* We special case this - as when a Windows machine
1347 is parsing a path is steps through the components
1348 one at a time - if a component fails it expects
1349 ERRbadpath, not ERRbadfile.
1351 status = map_checkpath_error(req->flags2, status);
1352 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1354 * Windows returns different error codes if
1355 * the parent directory is valid but not the
1356 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1357 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1358 * if the path is invalid.
1360 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1361 ERRDOS, ERRbadpath);
1365 reply_nterror(req, status);
1368 TALLOC_FREE(smb_fname);
1369 END_PROFILE(SMBcheckpath);
1373 /****************************************************************************
1375 ****************************************************************************/
1377 void reply_getatr(struct smb_request *req)
1379 connection_struct *conn = req->conn;
1380 struct smb_filename *smb_fname = NULL;
1387 TALLOC_CTX *ctx = talloc_tos();
1388 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1390 START_PROFILE(SMBgetatr);
1392 p = (const char *)req->buf + 1;
1393 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1394 if (!NT_STATUS_IS_OK(status)) {
1395 reply_nterror(req, status);
1399 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1400 under WfWg - weird! */
1401 if (*fname == '\0') {
1402 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1403 if (!CAN_WRITE(conn)) {
1404 mode |= FILE_ATTRIBUTE_READONLY;
1409 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1410 status = filename_convert(ctx,
1417 if (!NT_STATUS_IS_OK(status)) {
1418 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1419 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1420 ERRSRV, ERRbadpath);
1423 reply_nterror(req, status);
1426 if (!VALID_STAT(smb_fname->st) &&
1427 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1428 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1429 smb_fname_str_dbg(smb_fname),
1431 reply_nterror(req, map_nt_error_from_unix(errno));
1435 mode = dos_mode(conn, smb_fname);
1436 size = smb_fname->st.st_ex_size;
1438 if (ask_sharemode) {
1439 struct timespec write_time_ts;
1440 struct file_id fileid;
1442 ZERO_STRUCT(write_time_ts);
1443 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1444 get_file_infos(fileid, 0, NULL, &write_time_ts);
1445 if (!null_timespec(write_time_ts)) {
1446 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1450 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1451 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1456 reply_outbuf(req, 10, 0);
1458 SSVAL(req->outbuf,smb_vwv0,mode);
1459 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1460 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1462 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1464 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1466 if (get_Protocol() >= PROTOCOL_NT1) {
1467 SSVAL(req->outbuf, smb_flg2,
1468 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1471 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1472 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1475 TALLOC_FREE(smb_fname);
1477 END_PROFILE(SMBgetatr);
1481 /****************************************************************************
1483 ****************************************************************************/
1485 void reply_setatr(struct smb_request *req)
1487 struct smb_file_time ft;
1488 connection_struct *conn = req->conn;
1489 struct smb_filename *smb_fname = NULL;
1495 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1496 TALLOC_CTX *ctx = talloc_tos();
1498 START_PROFILE(SMBsetatr);
1501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1505 p = (const char *)req->buf + 1;
1506 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1507 if (!NT_STATUS_IS_OK(status)) {
1508 reply_nterror(req, status);
1512 status = filename_convert(ctx,
1519 if (!NT_STATUS_IS_OK(status)) {
1520 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1521 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1522 ERRSRV, ERRbadpath);
1525 reply_nterror(req, status);
1529 if (ISDOT(smb_fname->base_name)) {
1531 * Not sure here is the right place to catch this
1532 * condition. Might be moved to somewhere else later -- vl
1534 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1538 mode = SVAL(req->vwv+0, 0);
1539 mtime = srv_make_unix_date3(req->vwv+1);
1541 if (mode != FILE_ATTRIBUTE_NORMAL) {
1542 if (VALID_STAT_OF_DIR(smb_fname->st))
1543 mode |= FILE_ATTRIBUTE_DIRECTORY;
1545 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1547 status = smbd_check_access_rights(
1548 conn, smb_fname, false, FILE_WRITE_ATTRIBUTES);
1549 if (!NT_STATUS_IS_OK(status)) {
1550 reply_nterror(req, status);
1554 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1556 reply_nterror(req, map_nt_error_from_unix(errno));
1561 ft = (struct smb_file_time) {
1562 .mtime = convert_time_t_to_timespec(mtime)
1565 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1566 if (!NT_STATUS_IS_OK(status)) {
1567 reply_nterror(req, status);
1571 reply_outbuf(req, 0, 0);
1573 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1576 TALLOC_FREE(smb_fname);
1577 END_PROFILE(SMBsetatr);
1581 /****************************************************************************
1583 ****************************************************************************/
1585 void reply_dskattr(struct smb_request *req)
1587 connection_struct *conn = req->conn;
1589 uint64_t dfree,dsize,bsize;
1590 struct smb_filename smb_fname;
1591 START_PROFILE(SMBdskattr);
1593 ZERO_STRUCT(smb_fname);
1594 smb_fname.base_name = discard_const_p(char, ".");
1596 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1597 reply_nterror(req, map_nt_error_from_unix(errno));
1598 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1599 END_PROFILE(SMBdskattr);
1603 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1604 if (ret == (uint64_t)-1) {
1605 reply_nterror(req, map_nt_error_from_unix(errno));
1606 END_PROFILE(SMBdskattr);
1611 * Force max to fit in 16 bit fields.
1613 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1617 if (bsize > (WORDMAX*512)) {
1618 bsize = (WORDMAX*512);
1619 if (dsize > WORDMAX)
1621 if (dfree > WORDMAX)
1627 reply_outbuf(req, 5, 0);
1629 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1630 double total_space, free_space;
1631 /* we need to scale this to a number that DOS6 can handle. We
1632 use floating point so we can handle large drives on systems
1633 that don't have 64 bit integers
1635 we end up displaying a maximum of 2G to DOS systems
1637 total_space = dsize * (double)bsize;
1638 free_space = dfree * (double)bsize;
1640 dsize = (uint64_t)((total_space+63*512) / (64*512));
1641 dfree = (uint64_t)((free_space+63*512) / (64*512));
1643 if (dsize > 0xFFFF) dsize = 0xFFFF;
1644 if (dfree > 0xFFFF) dfree = 0xFFFF;
1646 SSVAL(req->outbuf,smb_vwv0,dsize);
1647 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1648 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1649 SSVAL(req->outbuf,smb_vwv3,dfree);
1651 SSVAL(req->outbuf,smb_vwv0,dsize);
1652 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1653 SSVAL(req->outbuf,smb_vwv2,512);
1654 SSVAL(req->outbuf,smb_vwv3,dfree);
1657 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1659 END_PROFILE(SMBdskattr);
1664 * Utility function to split the filename from the directory.
1666 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1667 char **fname_dir_out,
1668 char **fname_mask_out)
1670 const char *p = NULL;
1671 char *fname_dir = NULL;
1672 char *fname_mask = NULL;
1674 p = strrchr_m(fname_in, '/');
1676 fname_dir = talloc_strdup(ctx, ".");
1677 fname_mask = talloc_strdup(ctx, fname_in);
1679 fname_dir = talloc_strndup(ctx, fname_in,
1680 PTR_DIFF(p, fname_in));
1681 fname_mask = talloc_strdup(ctx, p+1);
1684 if (!fname_dir || !fname_mask) {
1685 TALLOC_FREE(fname_dir);
1686 TALLOC_FREE(fname_mask);
1687 return NT_STATUS_NO_MEMORY;
1690 *fname_dir_out = fname_dir;
1691 *fname_mask_out = fname_mask;
1692 return NT_STATUS_OK;
1695 /****************************************************************************
1697 ****************************************************************************/
1699 static bool make_dir_struct(TALLOC_CTX *ctx,
1709 char *mask2 = talloc_strdup(ctx, mask);
1715 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1719 memset(buf+1,' ',11);
1720 if ((p = strchr_m(mask2,'.')) != NULL) {
1722 push_ascii(buf+1,mask2,8, 0);
1723 push_ascii(buf+9,p+1,3, 0);
1726 push_ascii(buf+1,mask2,11, 0);
1729 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1731 srv_put_dos_date(buf,22,date);
1732 SSVAL(buf,26,size & 0xFFFF);
1733 SSVAL(buf,28,(size >> 16)&0xFFFF);
1734 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1735 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1736 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1737 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1741 /****************************************************************************
1743 Can be called from SMBsearch, SMBffirst or SMBfunique.
1744 ****************************************************************************/
1746 void reply_search(struct smb_request *req)
1748 connection_struct *conn = req->conn;
1751 char *directory = NULL;
1752 struct smb_filename *smb_fname = NULL;
1756 struct timespec date;
1758 unsigned int numentries = 0;
1759 unsigned int maxentries = 0;
1760 bool finished = False;
1765 bool check_descend = False;
1766 bool expect_close = False;
1768 bool mask_contains_wcard = False;
1769 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1770 TALLOC_CTX *ctx = talloc_tos();
1771 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1772 struct dptr_struct *dirptr = NULL;
1773 struct smbXsrv_connection *xconn = req->xconn;
1774 struct smbd_server_connection *sconn = req->sconn;
1776 START_PROFILE(SMBsearch);
1779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1783 if (req->posix_pathnames) {
1784 reply_unknown_new(req, req->cmd);
1788 /* If we were called as SMBffirst then we must expect close. */
1789 if(req->cmd == SMBffirst) {
1790 expect_close = True;
1793 reply_outbuf(req, 1, 3);
1794 maxentries = SVAL(req->vwv+0, 0);
1795 dirtype = SVAL(req->vwv+1, 0);
1796 p = (const char *)req->buf + 1;
1797 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1798 &nt_status, &mask_contains_wcard);
1799 if (!NT_STATUS_IS_OK(nt_status)) {
1800 reply_nterror(req, nt_status);
1805 status_len = SVAL(p, 0);
1808 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1810 if (status_len == 0) {
1811 struct smb_filename *smb_dname = NULL;
1812 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1813 ucf_flags_from_smb_request(req);
1814 nt_status = filename_convert(ctx, conn,
1818 &mask_contains_wcard,
1820 if (!NT_STATUS_IS_OK(nt_status)) {
1821 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1822 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1823 ERRSRV, ERRbadpath);
1826 reply_nterror(req, nt_status);
1830 directory = smb_fname->base_name;
1832 p = strrchr_m(directory,'/');
1833 if ((p != NULL) && (*directory != '/')) {
1834 mask = talloc_strdup(ctx, p + 1);
1835 directory = talloc_strndup(ctx, directory,
1836 PTR_DIFF(p, directory));
1838 mask = talloc_strdup(ctx, directory);
1839 directory = talloc_strdup(ctx,".");
1843 reply_nterror(req, NT_STATUS_NO_MEMORY);
1847 memset((char *)status,'\0',21);
1848 SCVAL(status,0,(dirtype & 0x1F));
1850 smb_dname = synthetic_smb_fname(talloc_tos(),
1855 if (smb_dname == NULL) {
1856 reply_nterror(req, NT_STATUS_NO_MEMORY);
1860 nt_status = dptr_create(conn,
1868 mask_contains_wcard,
1872 TALLOC_FREE(smb_dname);
1874 if (!NT_STATUS_IS_OK(nt_status)) {
1875 reply_nterror(req, nt_status);
1878 dptr_num = dptr_dnum(dirptr);
1881 const char *dirpath;
1883 memcpy(status,p,21);
1884 status_dirtype = CVAL(status,0) & 0x1F;
1885 if (status_dirtype != (dirtype & 0x1F)) {
1886 dirtype = status_dirtype;
1889 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1893 dirpath = dptr_path(sconn, dptr_num);
1894 directory = talloc_strdup(ctx, dirpath);
1896 reply_nterror(req, NT_STATUS_NO_MEMORY);
1900 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1905 * For a 'continue' search we have no string. So
1906 * check from the initial saved string.
1908 if (!req->posix_pathnames) {
1909 mask_contains_wcard = ms_has_wild(mask);
1911 dirtype = dptr_attr(sconn, dptr_num);
1914 DEBUG(4,("dptr_num is %d\n",dptr_num));
1916 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1917 char buf[DIR_STRUCT_SIZE];
1918 memcpy(buf,status,21);
1919 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1920 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1921 reply_nterror(req, NT_STATUS_NO_MEMORY);
1924 dptr_fill(sconn, buf+12,dptr_num);
1925 if (dptr_zero(buf+12) && (status_len==0)) {
1930 if (message_push_blob(&req->outbuf,
1931 data_blob_const(buf, sizeof(buf)))
1933 reply_nterror(req, NT_STATUS_NO_MEMORY);
1938 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1939 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1941 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1943 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1944 directory,lp_dont_descend(ctx, SNUM(conn))));
1945 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1946 check_descend = True;
1949 for (i=numentries;(i<maxentries) && !finished;i++) {
1950 finished = !get_dir_entry(ctx,
1961 char buf[DIR_STRUCT_SIZE];
1962 memcpy(buf,status,21);
1963 if (!make_dir_struct(ctx,
1969 convert_timespec_to_time_t(date),
1970 !allow_long_path_components)) {
1971 reply_nterror(req, NT_STATUS_NO_MEMORY);
1974 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1977 if (message_push_blob(&req->outbuf,
1978 data_blob_const(buf, sizeof(buf)))
1980 reply_nterror(req, NT_STATUS_NO_MEMORY);
1990 /* If we were called as SMBffirst with smb_search_id == NULL
1991 and no entries were found then return error and close dirptr
1994 if (numentries == 0) {
1995 dptr_close(sconn, &dptr_num);
1996 } else if(expect_close && status_len == 0) {
1997 /* Close the dptr - we know it's gone */
1998 dptr_close(sconn, &dptr_num);
2001 /* If we were called as SMBfunique, then we can close the dirptr now ! */
2002 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2003 dptr_close(sconn, &dptr_num);
2006 if ((numentries == 0) && !mask_contains_wcard) {
2007 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2011 SSVAL(req->outbuf,smb_vwv0,numentries);
2012 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2013 SCVAL(smb_buf(req->outbuf),0,5);
2014 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2016 /* The replies here are never long name. */
2017 SSVAL(req->outbuf, smb_flg2,
2018 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2019 if (!allow_long_path_components) {
2020 SSVAL(req->outbuf, smb_flg2,
2021 SVAL(req->outbuf, smb_flg2)
2022 & (~FLAGS2_LONG_PATH_COMPONENTS));
2025 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2026 SSVAL(req->outbuf, smb_flg2,
2027 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2029 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2030 smb_fn_name(req->cmd),
2037 TALLOC_FREE(directory);
2039 TALLOC_FREE(smb_fname);
2040 END_PROFILE(SMBsearch);
2044 /****************************************************************************
2045 Reply to a fclose (stop directory search).
2046 ****************************************************************************/
2048 void reply_fclose(struct smb_request *req)
2056 bool path_contains_wcard = False;
2057 TALLOC_CTX *ctx = talloc_tos();
2058 struct smbd_server_connection *sconn = req->sconn;
2060 START_PROFILE(SMBfclose);
2062 if (req->posix_pathnames) {
2063 reply_unknown_new(req, req->cmd);
2064 END_PROFILE(SMBfclose);
2068 p = (const char *)req->buf + 1;
2069 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2070 &err, &path_contains_wcard);
2071 if (!NT_STATUS_IS_OK(err)) {
2072 reply_nterror(req, err);
2073 END_PROFILE(SMBfclose);
2077 status_len = SVAL(p,0);
2080 if (status_len == 0) {
2081 reply_force_doserror(req, ERRSRV, ERRsrverror);
2082 END_PROFILE(SMBfclose);
2086 memcpy(status,p,21);
2088 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2089 /* Close the dptr - we know it's gone */
2090 dptr_close(sconn, &dptr_num);
2093 reply_outbuf(req, 1, 0);
2094 SSVAL(req->outbuf,smb_vwv0,0);
2096 DEBUG(3,("search close\n"));
2098 END_PROFILE(SMBfclose);
2102 /****************************************************************************
2104 ****************************************************************************/
2106 void reply_open(struct smb_request *req)
2108 connection_struct *conn = req->conn;
2109 struct smb_filename *smb_fname = NULL;
2119 uint32_t access_mask;
2120 uint32_t share_mode;
2121 uint32_t create_disposition;
2122 uint32_t create_options = 0;
2123 uint32_t private_flags = 0;
2126 TALLOC_CTX *ctx = talloc_tos();
2128 START_PROFILE(SMBopen);
2131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2135 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2136 deny_mode = SVAL(req->vwv+0, 0);
2137 dos_attr = SVAL(req->vwv+1, 0);
2139 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2140 STR_TERMINATE, &status);
2141 if (!NT_STATUS_IS_OK(status)) {
2142 reply_nterror(req, status);
2146 if (!map_open_params_to_ntcreate(fname, deny_mode,
2147 OPENX_FILE_EXISTS_OPEN, &access_mask,
2148 &share_mode, &create_disposition,
2149 &create_options, &private_flags)) {
2150 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2154 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2156 status = filename_convert(ctx,
2163 if (!NT_STATUS_IS_OK(status)) {
2164 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2165 reply_botherror(req,
2166 NT_STATUS_PATH_NOT_COVERED,
2167 ERRSRV, ERRbadpath);
2170 reply_nterror(req, status);
2174 status = SMB_VFS_CREATE_FILE(
2177 0, /* root_dir_fid */
2178 smb_fname, /* fname */
2179 access_mask, /* access_mask */
2180 share_mode, /* share_access */
2181 create_disposition, /* create_disposition*/
2182 create_options, /* create_options */
2183 dos_attr, /* file_attributes */
2184 oplock_request, /* oplock_request */
2186 0, /* allocation_size */
2192 NULL, NULL); /* create context */
2194 if (!NT_STATUS_IS_OK(status)) {
2195 if (open_was_deferred(req->xconn, req->mid)) {
2196 /* We have re-scheduled this call. */
2199 reply_openerror(req, status);
2203 /* Ensure we're pointing at the correct stat struct. */
2204 TALLOC_FREE(smb_fname);
2205 smb_fname = fsp->fsp_name;
2207 size = smb_fname->st.st_ex_size;
2208 fattr = dos_mode(conn, smb_fname);
2210 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2212 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2213 DEBUG(3,("attempt to open a directory %s\n",
2215 close_file(req, fsp, ERROR_CLOSE);
2216 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2217 ERRDOS, ERRnoaccess);
2221 reply_outbuf(req, 7, 0);
2222 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2223 SSVAL(req->outbuf,smb_vwv1,fattr);
2224 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2225 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2227 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2229 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2230 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2232 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2233 SCVAL(req->outbuf,smb_flg,
2234 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2237 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2238 SCVAL(req->outbuf,smb_flg,
2239 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2242 END_PROFILE(SMBopen);
2246 /****************************************************************************
2247 Reply to an open and X.
2248 ****************************************************************************/
2250 void reply_open_and_X(struct smb_request *req)
2252 connection_struct *conn = req->conn;
2253 struct smb_filename *smb_fname = NULL;
2255 uint16_t open_flags;
2258 /* Breakout the oplock request bits so we can set the
2259 reply bits separately. */
2260 int ex_oplock_request;
2261 int core_oplock_request;
2264 int smb_sattr = SVAL(req->vwv+4, 0);
2265 uint32_t smb_time = make_unix_date3(req->vwv+6);
2273 uint64_t allocation_size;
2274 ssize_t retval = -1;
2275 uint32_t access_mask;
2276 uint32_t share_mode;
2277 uint32_t create_disposition;
2278 uint32_t create_options = 0;
2279 uint32_t private_flags = 0;
2281 TALLOC_CTX *ctx = talloc_tos();
2283 START_PROFILE(SMBopenX);
2285 if (req->wct < 15) {
2286 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2290 open_flags = SVAL(req->vwv+2, 0);
2291 deny_mode = SVAL(req->vwv+3, 0);
2292 smb_attr = SVAL(req->vwv+5, 0);
2293 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2294 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2295 oplock_request = ex_oplock_request | core_oplock_request;
2296 smb_ofun = SVAL(req->vwv+8, 0);
2297 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2299 /* If it's an IPC, pass off the pipe handler. */
2301 if (lp_nt_pipe_support()) {
2302 reply_open_pipe_and_X(conn, req);
2304 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2309 /* XXXX we need to handle passed times, sattr and flags */
2310 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2311 STR_TERMINATE, &status);
2312 if (!NT_STATUS_IS_OK(status)) {
2313 reply_nterror(req, status);
2317 if (!map_open_params_to_ntcreate(fname, deny_mode,
2319 &access_mask, &share_mode,
2320 &create_disposition,
2323 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2327 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2329 status = filename_convert(ctx,
2336 if (!NT_STATUS_IS_OK(status)) {
2337 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2338 reply_botherror(req,
2339 NT_STATUS_PATH_NOT_COVERED,
2340 ERRSRV, ERRbadpath);
2343 reply_nterror(req, status);
2347 status = SMB_VFS_CREATE_FILE(
2350 0, /* root_dir_fid */
2351 smb_fname, /* fname */
2352 access_mask, /* access_mask */
2353 share_mode, /* share_access */
2354 create_disposition, /* create_disposition*/
2355 create_options, /* create_options */
2356 smb_attr, /* file_attributes */
2357 oplock_request, /* oplock_request */
2359 0, /* allocation_size */
2364 &smb_action, /* pinfo */
2365 NULL, NULL); /* create context */
2367 if (!NT_STATUS_IS_OK(status)) {
2368 if (open_was_deferred(req->xconn, req->mid)) {
2369 /* We have re-scheduled this call. */
2372 reply_openerror(req, status);
2376 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2377 if the file is truncated or created. */
2378 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2379 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2380 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2381 close_file(req, fsp, ERROR_CLOSE);
2382 reply_nterror(req, NT_STATUS_DISK_FULL);
2385 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2387 close_file(req, fsp, ERROR_CLOSE);
2388 reply_nterror(req, NT_STATUS_DISK_FULL);
2391 status = vfs_stat_fsp(fsp);
2392 if (!NT_STATUS_IS_OK(status)) {
2393 close_file(req, fsp, ERROR_CLOSE);
2394 reply_nterror(req, status);
2399 fattr = dos_mode(conn, fsp->fsp_name);
2400 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2401 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2402 close_file(req, fsp, ERROR_CLOSE);
2403 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2407 /* If the caller set the extended oplock request bit
2408 and we granted one (by whatever means) - set the
2409 correct bit for extended oplock reply.
2412 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2413 smb_action |= EXTENDED_OPLOCK_GRANTED;
2416 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2417 smb_action |= EXTENDED_OPLOCK_GRANTED;
2420 /* If the caller set the core oplock request bit
2421 and we granted one (by whatever means) - set the
2422 correct bit for core oplock reply.
2425 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2426 reply_outbuf(req, 19, 0);
2428 reply_outbuf(req, 15, 0);
2431 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2432 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2434 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2435 SCVAL(req->outbuf, smb_flg,
2436 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2439 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2440 SCVAL(req->outbuf, smb_flg,
2441 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2444 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2445 SSVAL(req->outbuf,smb_vwv3,fattr);
2446 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2447 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2449 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2451 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2452 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2453 SSVAL(req->outbuf,smb_vwv11,smb_action);
2455 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2456 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2460 TALLOC_FREE(smb_fname);
2461 END_PROFILE(SMBopenX);
2465 /****************************************************************************
2466 Reply to a SMBulogoffX.
2467 ****************************************************************************/
2469 void reply_ulogoffX(struct smb_request *req)
2471 struct smbd_server_connection *sconn = req->sconn;
2472 struct user_struct *vuser;
2473 struct smbXsrv_session *session = NULL;
2476 START_PROFILE(SMBulogoffX);
2478 vuser = get_valid_user_struct(sconn, req->vuid);
2481 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2482 (unsigned long long)req->vuid));
2484 req->vuid = UID_FIELD_INVALID;
2485 reply_force_doserror(req, ERRSRV, ERRbaduid);
2486 END_PROFILE(SMBulogoffX);
2490 session = vuser->session;
2494 * TODO: cancel all outstanding requests on the session
2496 status = smbXsrv_session_logoff(session);
2497 if (!NT_STATUS_IS_OK(status)) {
2498 DEBUG(0, ("reply_ulogoff: "
2499 "smbXsrv_session_logoff() failed: %s\n",
2500 nt_errstr(status)));
2502 * If we hit this case, there is something completely
2503 * wrong, so we better disconnect the transport connection.
2505 END_PROFILE(SMBulogoffX);
2506 exit_server(__location__ ": smbXsrv_session_logoff failed");
2510 TALLOC_FREE(session);
2512 reply_outbuf(req, 2, 0);
2513 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2514 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2516 DEBUG(3, ("ulogoffX vuid=%llu\n",
2517 (unsigned long long)req->vuid));
2519 END_PROFILE(SMBulogoffX);
2520 req->vuid = UID_FIELD_INVALID;
2523 /****************************************************************************
2524 Reply to a mknew or a create.
2525 ****************************************************************************/
2527 void reply_mknew(struct smb_request *req)
2529 connection_struct *conn = req->conn;
2530 struct smb_filename *smb_fname = NULL;
2533 struct smb_file_time ft;
2535 int oplock_request = 0;
2537 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2538 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2539 uint32_t create_disposition;
2540 uint32_t create_options = 0;
2542 TALLOC_CTX *ctx = talloc_tos();
2544 START_PROFILE(SMBcreate);
2548 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2552 fattr = SVAL(req->vwv+0, 0);
2553 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2555 if (req->cmd == SMBmknew) {
2556 /* We should fail if file exists. */
2557 create_disposition = FILE_CREATE;
2559 /* Create if file doesn't exist, truncate if it does. */
2560 create_disposition = FILE_OVERWRITE_IF;
2564 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2566 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2567 STR_TERMINATE, &status);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 reply_nterror(req, status);
2573 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2574 status = filename_convert(ctx,
2581 if (!NT_STATUS_IS_OK(status)) {
2582 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2583 reply_botherror(req,
2584 NT_STATUS_PATH_NOT_COVERED,
2585 ERRSRV, ERRbadpath);
2588 reply_nterror(req, status);
2592 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2593 DEBUG(0,("Attempt to create file (%s) with volid set - "
2594 "please report this\n",
2595 smb_fname_str_dbg(smb_fname)));
2598 status = SMB_VFS_CREATE_FILE(
2601 0, /* root_dir_fid */
2602 smb_fname, /* fname */
2603 access_mask, /* access_mask */
2604 share_mode, /* share_access */
2605 create_disposition, /* create_disposition*/
2606 create_options, /* create_options */
2607 fattr, /* file_attributes */
2608 oplock_request, /* oplock_request */
2610 0, /* allocation_size */
2611 0, /* private_flags */
2616 NULL, NULL); /* create context */
2618 if (!NT_STATUS_IS_OK(status)) {
2619 if (open_was_deferred(req->xconn, req->mid)) {
2620 /* We have re-scheduled this call. */
2623 reply_openerror(req, status);
2627 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2628 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2629 if (!NT_STATUS_IS_OK(status)) {
2630 END_PROFILE(SMBcreate);
2634 reply_outbuf(req, 1, 0);
2635 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2637 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2638 SCVAL(req->outbuf,smb_flg,
2639 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2642 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2643 SCVAL(req->outbuf,smb_flg,
2644 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2647 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2648 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2649 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2650 (unsigned int)fattr));
2653 TALLOC_FREE(smb_fname);
2654 END_PROFILE(SMBcreate);
2658 /****************************************************************************
2659 Reply to a create temporary file.
2660 ****************************************************************************/
2662 void reply_ctemp(struct smb_request *req)
2664 connection_struct *conn = req->conn;
2665 struct smb_filename *smb_fname = NULL;
2666 char *wire_name = NULL;
2675 TALLOC_CTX *ctx = talloc_tos();
2677 START_PROFILE(SMBctemp);
2680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2684 fattr = SVAL(req->vwv+0, 0);
2685 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2687 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2688 STR_TERMINATE, &status);
2689 if (!NT_STATUS_IS_OK(status)) {
2690 reply_nterror(req, status);
2694 for (i = 0; i < 10; i++) {
2696 fname = talloc_asprintf(ctx,
2699 generate_random_str_list(ctx, 5, "0123456789"));
2701 fname = talloc_asprintf(ctx,
2703 generate_random_str_list(ctx, 5, "0123456789"));
2707 reply_nterror(req, NT_STATUS_NO_MEMORY);
2711 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2712 status = filename_convert(ctx, conn,
2718 if (!NT_STATUS_IS_OK(status)) {
2719 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2720 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2721 ERRSRV, ERRbadpath);
2724 reply_nterror(req, status);
2728 /* Create the file. */
2729 status = SMB_VFS_CREATE_FILE(
2732 0, /* root_dir_fid */
2733 smb_fname, /* fname */
2734 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2735 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2736 FILE_CREATE, /* create_disposition*/
2737 0, /* create_options */
2738 fattr, /* file_attributes */
2739 oplock_request, /* oplock_request */
2741 0, /* allocation_size */
2742 0, /* private_flags */
2747 NULL, NULL); /* create context */
2749 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2751 TALLOC_FREE(smb_fname);
2755 if (!NT_STATUS_IS_OK(status)) {
2756 if (open_was_deferred(req->xconn, req->mid)) {
2757 /* We have re-scheduled this call. */
2760 reply_openerror(req, status);
2768 /* Collision after 10 times... */
2769 reply_nterror(req, status);
2773 reply_outbuf(req, 1, 0);
2774 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2776 /* the returned filename is relative to the directory */
2777 s = strrchr_m(fsp->fsp_name->base_name, '/');
2779 s = fsp->fsp_name->base_name;
2785 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2786 thing in the byte section. JRA */
2787 SSVALS(p, 0, -1); /* what is this? not in spec */
2789 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2791 reply_nterror(req, NT_STATUS_NO_MEMORY);
2795 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2796 SCVAL(req->outbuf, smb_flg,
2797 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2800 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2801 SCVAL(req->outbuf, smb_flg,
2802 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2805 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2806 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2807 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2809 TALLOC_FREE(smb_fname);
2810 TALLOC_FREE(wire_name);
2811 END_PROFILE(SMBctemp);
2815 /*******************************************************************
2816 Check if a user is allowed to rename a file.
2817 ********************************************************************/
2819 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2822 if (!CAN_WRITE(conn)) {
2823 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2826 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2827 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2828 /* Only bother to read the DOS attribute if we might deny the
2829 rename on the grounds of attribute mismatch. */
2830 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2831 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2832 return NT_STATUS_NO_SUCH_FILE;
2836 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2837 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2838 return NT_STATUS_OK;
2841 /* If no pathnames are open below this
2842 directory, allow the rename. */
2844 if (lp_strict_rename(SNUM(conn))) {
2846 * Strict rename, check open file db.
2848 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2849 return NT_STATUS_ACCESS_DENIED;
2851 } else if (file_find_subpath(fsp)) {
2853 * No strict rename, just look in local process.
2855 return NT_STATUS_ACCESS_DENIED;
2857 return NT_STATUS_OK;
2860 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2861 return NT_STATUS_OK;
2864 return NT_STATUS_ACCESS_DENIED;
2867 /*******************************************************************
2868 * unlink a file with all relevant access checks
2869 *******************************************************************/
2871 static NTSTATUS do_unlink(connection_struct *conn,
2872 struct smb_request *req,
2873 struct smb_filename *smb_fname,
2878 uint32_t dirtype_orig = dirtype;
2881 bool posix_paths = (req != NULL && req->posix_pathnames);
2883 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2884 smb_fname_str_dbg(smb_fname),
2887 if (!CAN_WRITE(conn)) {
2888 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2892 ret = SMB_VFS_LSTAT(conn, smb_fname);
2894 ret = SMB_VFS_STAT(conn, smb_fname);
2897 return map_nt_error_from_unix(errno);
2900 fattr = dos_mode(conn, smb_fname);
2902 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2903 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2906 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2908 return NT_STATUS_NO_SUCH_FILE;
2911 if (!dir_check_ftype(fattr, dirtype)) {
2912 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2913 return NT_STATUS_FILE_IS_A_DIRECTORY;
2915 return NT_STATUS_NO_SUCH_FILE;
2918 if (dirtype_orig & 0x8000) {
2919 /* These will never be set for POSIX. */
2920 return NT_STATUS_NO_SUCH_FILE;
2924 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2925 return NT_STATUS_FILE_IS_A_DIRECTORY;
2928 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2929 return NT_STATUS_NO_SUCH_FILE;
2932 if (dirtype & 0xFF00) {
2933 /* These will never be set for POSIX. */
2934 return NT_STATUS_NO_SUCH_FILE;
2939 return NT_STATUS_NO_SUCH_FILE;
2942 /* Can't delete a directory. */
2943 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2944 return NT_STATUS_FILE_IS_A_DIRECTORY;
2949 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2950 return NT_STATUS_OBJECT_NAME_INVALID;
2951 #endif /* JRATEST */
2953 /* On open checks the open itself will check the share mode, so
2954 don't do it here as we'll get it wrong. */
2956 status = SMB_VFS_CREATE_FILE
2959 0, /* root_dir_fid */
2960 smb_fname, /* fname */
2961 DELETE_ACCESS, /* access_mask */
2962 FILE_SHARE_NONE, /* share_access */
2963 FILE_OPEN, /* create_disposition*/
2964 FILE_NON_DIRECTORY_FILE, /* create_options */
2965 /* file_attributes */
2966 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2967 FILE_ATTRIBUTE_NORMAL,
2968 0, /* oplock_request */
2970 0, /* allocation_size */
2971 0, /* private_flags */
2976 NULL, NULL); /* create context */
2978 if (!NT_STATUS_IS_OK(status)) {
2979 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2980 nt_errstr(status)));
2984 status = can_set_delete_on_close(fsp, fattr);
2985 if (!NT_STATUS_IS_OK(status)) {
2986 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2988 smb_fname_str_dbg(smb_fname),
2989 nt_errstr(status)));
2990 close_file(req, fsp, NORMAL_CLOSE);
2994 /* The set is across all open files on this dev/inode pair. */
2995 if (!set_delete_on_close(fsp, True,
2996 conn->session_info->security_token,
2997 conn->session_info->unix_token)) {
2998 close_file(req, fsp, NORMAL_CLOSE);
2999 return NT_STATUS_ACCESS_DENIED;
3002 return close_file(req, fsp, NORMAL_CLOSE);
3005 /****************************************************************************
3006 The guts of the unlink command, split out so it may be called by the NT SMB
3008 ****************************************************************************/
3010 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3011 uint32_t dirtype, struct smb_filename *smb_fname,
3014 char *fname_dir = NULL;
3015 char *fname_mask = NULL;
3017 NTSTATUS status = NT_STATUS_OK;
3018 struct smb_filename *smb_fname_dir = NULL;
3019 TALLOC_CTX *ctx = talloc_tos();
3021 /* Split up the directory from the filename/mask. */
3022 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3023 &fname_dir, &fname_mask);
3024 if (!NT_STATUS_IS_OK(status)) {
3029 * We should only check the mangled cache
3030 * here if unix_convert failed. This means
3031 * that the path in 'mask' doesn't exist
3032 * on the file system and so we need to look
3033 * for a possible mangle. This patch from
3034 * Tine Smukavec <valentin.smukavec@hermes.si>.
3037 if (!VALID_STAT(smb_fname->st) &&
3038 mangle_is_mangled(fname_mask, conn->params)) {
3039 char *new_mask = NULL;
3040 mangle_lookup_name_from_8_3(ctx, fname_mask,
3041 &new_mask, conn->params);
3043 TALLOC_FREE(fname_mask);
3044 fname_mask = new_mask;
3051 * Only one file needs to be unlinked. Append the mask back
3052 * onto the directory.
3054 TALLOC_FREE(smb_fname->base_name);
3055 if (ISDOT(fname_dir)) {
3056 /* Ensure we use canonical names on open. */
3057 smb_fname->base_name = talloc_asprintf(smb_fname,
3061 smb_fname->base_name = talloc_asprintf(smb_fname,
3066 if (!smb_fname->base_name) {
3067 status = NT_STATUS_NO_MEMORY;
3071 dirtype = FILE_ATTRIBUTE_NORMAL;
3074 status = check_name(conn, smb_fname);
3075 if (!NT_STATUS_IS_OK(status)) {
3079 status = do_unlink(conn, req, smb_fname, dirtype);
3080 if (!NT_STATUS_IS_OK(status)) {
3086 struct smb_Dir *dir_hnd = NULL;
3088 const char *dname = NULL;
3089 char *talloced = NULL;
3091 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3092 status = NT_STATUS_OBJECT_NAME_INVALID;
3096 dirtype = FILE_ATTRIBUTE_NORMAL;
3099 if (strequal(fname_mask,"????????.???")) {
3100 TALLOC_FREE(fname_mask);
3101 fname_mask = talloc_strdup(ctx, "*");
3103 status = NT_STATUS_NO_MEMORY;
3108 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3113 if (smb_fname_dir == NULL) {
3114 status = NT_STATUS_NO_MEMORY;
3118 status = check_name(conn, smb_fname_dir);
3119 if (!NT_STATUS_IS_OK(status)) {
3123 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3125 if (dir_hnd == NULL) {
3126 status = map_nt_error_from_unix(errno);
3130 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3131 the pattern matches against the long name, otherwise the short name
3132 We don't implement this yet XXXX
3135 status = NT_STATUS_NO_SUCH_FILE;
3137 while ((dname = ReadDirName(dir_hnd, &offset,
3138 &smb_fname->st, &talloced))) {
3139 TALLOC_CTX *frame = talloc_stackframe();
3141 if (!is_visible_file(conn, fname_dir, dname,
3142 &smb_fname->st, true)) {
3144 TALLOC_FREE(talloced);
3148 /* Quick check for "." and ".." */
3149 if (ISDOT(dname) || ISDOTDOT(dname)) {
3151 TALLOC_FREE(talloced);
3155 if(!mask_match(dname, fname_mask,
3156 conn->case_sensitive)) {
3158 TALLOC_FREE(talloced);
3162 TALLOC_FREE(smb_fname->base_name);
3163 if (ISDOT(fname_dir)) {
3164 /* Ensure we use canonical names on open. */
3165 smb_fname->base_name =
3166 talloc_asprintf(smb_fname, "%s",
3169 smb_fname->base_name =
3170 talloc_asprintf(smb_fname, "%s/%s",
3174 if (!smb_fname->base_name) {
3175 TALLOC_FREE(dir_hnd);
3176 status = NT_STATUS_NO_MEMORY;
3178 TALLOC_FREE(talloced);
3182 status = check_name(conn, smb_fname);
3183 if (!NT_STATUS_IS_OK(status)) {
3184 TALLOC_FREE(dir_hnd);
3186 TALLOC_FREE(talloced);
3190 status = do_unlink(conn, req, smb_fname, dirtype);
3191 if (!NT_STATUS_IS_OK(status)) {
3192 TALLOC_FREE(dir_hnd);
3194 TALLOC_FREE(talloced);
3199 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3200 smb_fname->base_name));
3203 TALLOC_FREE(talloced);
3205 TALLOC_FREE(dir_hnd);
3208 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3209 status = map_nt_error_from_unix(errno);
3213 TALLOC_FREE(smb_fname_dir);
3214 TALLOC_FREE(fname_dir);
3215 TALLOC_FREE(fname_mask);
3219 /****************************************************************************
3221 ****************************************************************************/
3223 void reply_unlink(struct smb_request *req)
3225 connection_struct *conn = req->conn;
3227 struct smb_filename *smb_fname = NULL;
3230 bool path_contains_wcard = False;
3231 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3232 ucf_flags_from_smb_request(req);
3233 TALLOC_CTX *ctx = talloc_tos();
3235 START_PROFILE(SMBunlink);
3238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3242 dirtype = SVAL(req->vwv+0, 0);
3244 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3245 STR_TERMINATE, &status,
3246 &path_contains_wcard);
3247 if (!NT_STATUS_IS_OK(status)) {
3248 reply_nterror(req, status);
3252 status = filename_convert(ctx, conn,
3256 &path_contains_wcard,
3258 if (!NT_STATUS_IS_OK(status)) {
3259 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3260 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3261 ERRSRV, ERRbadpath);
3264 reply_nterror(req, status);
3268 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3270 status = unlink_internals(conn, req, dirtype, smb_fname,
3271 path_contains_wcard);
3272 if (!NT_STATUS_IS_OK(status)) {
3273 if (open_was_deferred(req->xconn, req->mid)) {
3274 /* We have re-scheduled this call. */
3277 reply_nterror(req, status);
3281 reply_outbuf(req, 0, 0);
3283 TALLOC_FREE(smb_fname);
3284 END_PROFILE(SMBunlink);
3288 /****************************************************************************
3290 ****************************************************************************/
3292 static void fail_readraw(void)
3294 const char *errstr = talloc_asprintf(talloc_tos(),
3295 "FAIL ! reply_readbraw: socket write fail (%s)",
3300 exit_server_cleanly(errstr);
3303 /****************************************************************************
3304 Fake (read/write) sendfile. Returns -1 on read or write fail.
3305 ****************************************************************************/
3307 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3308 off_t startpos, size_t nread)
3311 size_t tosend = nread;
3318 bufsize = MIN(nread, 65536);
3320 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3324 while (tosend > 0) {
3328 cur_read = MIN(tosend, bufsize);
3329 ret = read_file(fsp,buf,startpos,cur_read);
3335 /* If we had a short read, fill with zeros. */
3336 if (ret < cur_read) {
3337 memset(buf + ret, '\0', cur_read - ret);
3340 ret = write_data(xconn->transport.sock, buf, cur_read);
3341 if (ret != cur_read) {
3342 int saved_errno = errno;
3344 * Try and give an error message saying what
3347 DEBUG(0, ("write_data failed for client %s. "
3349 smbXsrv_connection_dbg(xconn),
3350 strerror(saved_errno)));
3352 errno = saved_errno;
3356 startpos += cur_read;
3360 return (ssize_t)nread;
3363 /****************************************************************************
3364 Deal with the case of sendfile reading less bytes from the file than
3365 requested. Fill with zeros (all we can do). Returns 0 on success
3366 ****************************************************************************/
3368 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3374 #define SHORT_SEND_BUFSIZE 1024
3375 if (nread < headersize) {
3376 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3377 "header for file %s (%s). Terminating\n",
3378 fsp_str_dbg(fsp), strerror(errno)));
3382 nread -= headersize;
3384 if (nread < smb_maxcnt) {
3385 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3387 DEBUG(0,("sendfile_short_send: malloc failed "
3388 "for file %s (%s). Terminating\n",
3389 fsp_str_dbg(fsp), strerror(errno)));
3393 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3394 "with zeros !\n", fsp_str_dbg(fsp)));
3396 while (nread < smb_maxcnt) {
3398 * We asked for the real file size and told sendfile
3399 * to not go beyond the end of the file. But it can
3400 * happen that in between our fstat call and the
3401 * sendfile call the file was truncated. This is very
3402 * bad because we have already announced the larger
3403 * number of bytes to the client.
3405 * The best we can do now is to send 0-bytes, just as
3406 * a read from a hole in a sparse file would do.
3408 * This should happen rarely enough that I don't care
3409 * about efficiency here :-)
3414 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3415 ret = write_data(xconn->transport.sock, buf, to_write);
3416 if (ret != to_write) {
3417 int saved_errno = errno;
3419 * Try and give an error message saying what
3422 DEBUG(0, ("write_data failed for client %s. "
3424 smbXsrv_connection_dbg(xconn),
3425 strerror(saved_errno)));
3426 errno = saved_errno;
3437 /****************************************************************************
3438 Return a readbraw error (4 bytes of zero).
3439 ****************************************************************************/
3441 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3447 smbd_lock_socket(xconn);
3448 if (write_data(xconn->transport.sock,header,4) != 4) {
3449 int saved_errno = errno;
3451 * Try and give an error message saying what
3454 DEBUG(0, ("write_data failed for client %s. "
3456 smbXsrv_connection_dbg(xconn),
3457 strerror(saved_errno)));
3458 errno = saved_errno;
3462 smbd_unlock_socket(xconn);
3465 /****************************************************************************
3466 Use sendfile in readbraw.
3467 ****************************************************************************/
3469 static void send_file_readbraw(connection_struct *conn,
3470 struct smb_request *req,
3476 struct smbXsrv_connection *xconn = req->xconn;
3477 char *outbuf = NULL;
3481 * We can only use sendfile on a non-chained packet
3482 * but we can use on a non-oplocked file. tridge proved this
3483 * on a train in Germany :-). JRA.
3484 * reply_readbraw has already checked the length.
3487 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3488 (fsp->wcp == NULL) &&
3489 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3490 ssize_t sendfile_read = -1;
3492 DATA_BLOB header_blob;
3494 _smb_setlen(header,nread);
3495 header_blob = data_blob_const(header, 4);
3497 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3498 &header_blob, startpos,
3500 if (sendfile_read == -1) {
3501 /* Returning ENOSYS means no data at all was sent.
3502 * Do this as a normal read. */
3503 if (errno == ENOSYS) {
3504 goto normal_readbraw;
3508 * Special hack for broken Linux with no working sendfile. If we
3509 * return EINTR we sent the header but not the rest of the data.
3510 * Fake this up by doing read/write calls.
3512 if (errno == EINTR) {
3513 /* Ensure we don't do this again. */
3514 set_use_sendfile(SNUM(conn), False);
3515 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3517 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3518 DEBUG(0,("send_file_readbraw: "
3519 "fake_sendfile failed for "
3523 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3528 DEBUG(0,("send_file_readbraw: sendfile failed for "
3529 "file %s (%s). Terminating\n",
3530 fsp_str_dbg(fsp), strerror(errno)));
3531 exit_server_cleanly("send_file_readbraw sendfile failed");
3532 } else if (sendfile_read == 0) {
3534 * Some sendfile implementations return 0 to indicate
3535 * that there was a short read, but nothing was
3536 * actually written to the socket. In this case,
3537 * fallback to the normal read path so the header gets
3538 * the correct byte count.
3540 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3541 "bytes falling back to the normal read: "
3542 "%s\n", fsp_str_dbg(fsp)));
3543 goto normal_readbraw;
3546 /* Deal with possible short send. */
3547 if (sendfile_read != 4+nread) {
3548 ret = sendfile_short_send(xconn, fsp,
3549 sendfile_read, 4, nread);
3559 outbuf = talloc_array(NULL, char, nread+4);
3561 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3562 (unsigned)(nread+4)));
3563 reply_readbraw_error(xconn);
3568 ret = read_file(fsp,outbuf+4,startpos,nread);
3569 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3578 _smb_setlen(outbuf,ret);
3579 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3580 int saved_errno = errno;
3582 * Try and give an error message saying what
3585 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3586 smbXsrv_connection_dbg(xconn),
3587 strerror(saved_errno)));
3588 errno = saved_errno;
3593 TALLOC_FREE(outbuf);
3596 /****************************************************************************
3597 Reply to a readbraw (core+ protocol).
3598 ****************************************************************************/
3600 void reply_readbraw(struct smb_request *req)
3602 connection_struct *conn = req->conn;
3603 struct smbXsrv_connection *xconn = req->xconn;
3604 ssize_t maxcount,mincount;
3608 struct lock_struct lock;
3611 START_PROFILE(SMBreadbraw);
3613 if (srv_is_signing_active(xconn) || req->encrypted) {
3614 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3615 "raw reads/writes are disallowed.");
3619 reply_readbraw_error(xconn);
3620 END_PROFILE(SMBreadbraw);
3624 if (xconn->smb1.echo_handler.trusted_fde) {
3625 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3626 "'async smb echo handler = yes'\n"));
3627 reply_readbraw_error(xconn);
3628 END_PROFILE(SMBreadbraw);
3633 * Special check if an oplock break has been issued
3634 * and the readraw request croses on the wire, we must
3635 * return a zero length response here.
3638 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3641 * We have to do a check_fsp by hand here, as
3642 * we must always return 4 zero bytes on error,
3646 if (!fsp || !conn || conn != fsp->conn ||
3647 req->vuid != fsp->vuid ||
3648 fsp->is_directory || fsp->fh->fd == -1) {
3650 * fsp could be NULL here so use the value from the packet. JRA.
3652 DEBUG(3,("reply_readbraw: fnum %d not valid "
3654 (int)SVAL(req->vwv+0, 0)));
3655 reply_readbraw_error(xconn);
3656 END_PROFILE(SMBreadbraw);
3660 /* Do a "by hand" version of CHECK_READ. */
3661 if (!(fsp->can_read ||
3662 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3663 (fsp->access_mask & FILE_EXECUTE)))) {
3664 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3665 (int)SVAL(req->vwv+0, 0)));
3666 reply_readbraw_error(xconn);
3667 END_PROFILE(SMBreadbraw);
3671 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3673 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3674 if(req->wct == 10) {
3676 * This is a large offset (64 bit) read.
3679 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3682 DEBUG(0,("reply_readbraw: negative 64 bit "
3683 "readraw offset (%.0f) !\n",
3684 (double)startpos ));
3685 reply_readbraw_error(xconn);
3686 END_PROFILE(SMBreadbraw);
3691 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3692 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3694 /* ensure we don't overrun the packet size */
3695 maxcount = MIN(65535,maxcount);
3697 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3698 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3701 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3702 reply_readbraw_error(xconn);
3703 END_PROFILE(SMBreadbraw);
3707 if (fsp_stat(fsp) == 0) {
3708 size = fsp->fsp_name->st.st_ex_size;
3711 if (startpos >= size) {
3714 nread = MIN(maxcount,(size - startpos));
3717 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3718 if (nread < mincount)
3722 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3723 "min=%lu nread=%lu\n",
3724 fsp_fnum_dbg(fsp), (double)startpos,
3725 (unsigned long)maxcount,
3726 (unsigned long)mincount,
3727 (unsigned long)nread ) );
3729 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3731 DEBUG(5,("reply_readbraw finished\n"));
3733 END_PROFILE(SMBreadbraw);
3738 #define DBGC_CLASS DBGC_LOCKING
3740 /****************************************************************************
3741 Reply to a lockread (core+ protocol).
3742 ****************************************************************************/
3744 static void reply_lockread_locked(struct tevent_req *subreq);
3746 void reply_lockread(struct smb_request *req)
3748 struct tevent_req *subreq = NULL;
3749 connection_struct *conn = req->conn;
3751 struct smbd_lock_element *lck = NULL;
3753 START_PROFILE(SMBlockread);
3756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3757 END_PROFILE(SMBlockread);
3761 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3763 if (!check_fsp(conn, req, fsp)) {
3764 END_PROFILE(SMBlockread);
3768 if (!CHECK_READ(fsp,req)) {
3769 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3770 END_PROFILE(SMBlockread);
3774 lck = talloc(req, struct smbd_lock_element);
3776 reply_nterror(req, NT_STATUS_NO_MEMORY);
3777 END_PROFILE(SMBlockread);
3782 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3783 * protocol request that predates the read/write lock concept.
3784 * Thus instead of asking for a read lock here we need to ask
3785 * for a write lock. JRA.
3786 * Note that the requested lock size is unaffected by max_send.
3789 *lck = (struct smbd_lock_element) {
3790 .smblctx = req->smbpid,
3791 .brltype = WRITE_LOCK,
3792 .count = SVAL(req->vwv+1, 0),
3793 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3796 subreq = smbd_smb1_do_locks_send(
3802 false, /* large_offset */
3806 if (subreq == NULL) {
3807 reply_nterror(req, NT_STATUS_NO_MEMORY);
3808 END_PROFILE(SMBlockread);
3811 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3812 END_PROFILE(SMBlockread);
3815 static void reply_lockread_locked(struct tevent_req *subreq)
3817 struct smb_request *req = NULL;
3823 size_t numtoread, maxtoread;
3824 struct files_struct *fsp = NULL;
3827 START_PROFILE(SMBlockread);
3829 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3832 status = smbd_smb1_do_locks_recv(subreq);
3833 TALLOC_FREE(subreq);
3835 if (!NT_STATUS_IS_OK(status)) {
3836 reply_nterror(req, status);
3840 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3842 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
3846 numtoread = SVAL(req->vwv+1, 0);
3847 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3850 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3852 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3854 if (numtoread > maxtoread) {
3855 DBG_WARNING("requested read size (%zu) is greater than "
3856 "maximum allowed (%zu/%d). "
3857 "Returning short read of maximum allowed for "
3858 "compatibility with Windows 2000.\n",
3861 req->xconn->smb1.sessions.max_send);
3862 numtoread = maxtoread;
3865 reply_outbuf(req, 5, numtoread + 3);
3867 data = smb_buf(req->outbuf) + 3;
3869 nread = read_file(fsp,data,startpos,numtoread);
3872 reply_nterror(req, map_nt_error_from_unix(errno));
3876 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3878 SSVAL(req->outbuf,smb_vwv0,nread);
3879 SSVAL(req->outbuf,smb_vwv5,nread+3);
3880 p = smb_buf(req->outbuf);
3881 SCVAL(p,0,0); /* pad byte. */
3884 DEBUG(3,("lockread %s num=%d nread=%d\n",
3885 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3888 ok = srv_send_smb(req->xconn,
3889 (char *)req->outbuf,
3892 IS_CONN_ENCRYPTED(req->conn),
3895 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
3898 END_PROFILE(SMBlockread);
3903 #define DBGC_CLASS DBGC_ALL
3905 /****************************************************************************
3907 ****************************************************************************/
3909 void reply_read(struct smb_request *req)
3911 connection_struct *conn = req->conn;
3918 struct lock_struct lock;
3919 struct smbXsrv_connection *xconn = req->xconn;
3921 START_PROFILE(SMBread);
3924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3925 END_PROFILE(SMBread);
3929 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3931 if (!check_fsp(conn, req, fsp)) {
3932 END_PROFILE(SMBread);
3936 if (!CHECK_READ(fsp,req)) {
3937 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3938 END_PROFILE(SMBread);
3942 numtoread = SVAL(req->vwv+1, 0);
3943 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3946 * The requested read size cannot be greater than max_send. JRA.
3948 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3950 if (numtoread > maxtoread) {
3951 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3952 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3953 (unsigned int)numtoread, (unsigned int)maxtoread,
3954 (unsigned int)xconn->smb1.sessions.max_send));
3955 numtoread = maxtoread;
3958 reply_outbuf(req, 5, numtoread+3);
3960 data = smb_buf(req->outbuf) + 3;
3962 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3963 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3966 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3967 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3968 END_PROFILE(SMBread);
3973 nread = read_file(fsp,data,startpos,numtoread);
3976 reply_nterror(req, map_nt_error_from_unix(errno));
3980 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3982 SSVAL(req->outbuf,smb_vwv0,nread);
3983 SSVAL(req->outbuf,smb_vwv5,nread+3);
3984 SCVAL(smb_buf(req->outbuf),0,1);
3985 SSVAL(smb_buf(req->outbuf),1,nread);
3987 DEBUG(3, ("read %s num=%d nread=%d\n",
3988 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3991 END_PROFILE(SMBread);
3995 /****************************************************************************
3997 ****************************************************************************/
3999 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4003 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4006 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4008 SCVAL(outbuf,smb_vwv0,0xFF);
4009 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4010 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4011 SSVAL(outbuf,smb_vwv6,
4012 (smb_wct - 4) /* offset from smb header to wct */
4013 + 1 /* the wct field */
4014 + 12 * sizeof(uint16_t) /* vwv */
4015 + 2 /* the buflen field */
4016 + 1); /* padding byte */
4017 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4018 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4019 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4020 _smb_setlen_large(outbuf,
4021 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4025 /****************************************************************************
4026 Reply to a read and X - possibly using sendfile.
4027 ****************************************************************************/
4029 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4030 files_struct *fsp, off_t startpos,
4033 struct smbXsrv_connection *xconn = req->xconn;
4035 struct lock_struct lock;
4036 int saved_errno = 0;
4038 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4039 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4042 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4043 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4048 * We can only use sendfile on a non-chained packet
4049 * but we can use on a non-oplocked file. tridge proved this
4050 * on a train in Germany :-). JRA.
4053 if (!req_is_in_chain(req) &&
4055 (fsp->base_fsp == NULL) &&
4056 (fsp->wcp == NULL) &&
4057 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4058 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4061 if(fsp_stat(fsp) == -1) {
4062 reply_nterror(req, map_nt_error_from_unix(errno));
4066 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4067 (startpos > fsp->fsp_name->st.st_ex_size) ||
4068 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4070 * We already know that we would do a short read, so don't
4071 * try the sendfile() path.
4073 goto nosendfile_read;
4077 * Set up the packet header before send. We
4078 * assume here the sendfile will work (get the
4079 * correct amount of data).
4082 header = data_blob_const(headerbuf, sizeof(headerbuf));
4084 construct_reply_common_req(req, (char *)headerbuf);
4085 setup_readX_header((char *)headerbuf, smb_maxcnt);
4087 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4088 startpos, smb_maxcnt);
4090 saved_errno = errno;
4092 /* Returning ENOSYS means no data at all was sent.
4093 Do this as a normal read. */
4094 if (errno == ENOSYS) {
4099 * Special hack for broken Linux with no working sendfile. If we
4100 * return EINTR we sent the header but not the rest of the data.
4101 * Fake this up by doing read/write calls.
4104 if (errno == EINTR) {
4105 /* Ensure we don't do this again. */
4106 set_use_sendfile(SNUM(conn), False);
4107 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4108 nread = fake_sendfile(xconn, fsp, startpos,
4111 saved_errno = errno;
4112 DEBUG(0,("send_file_readX: "
4113 "fake_sendfile failed for "
4114 "file %s (%s) for client %s. "
4117 smbXsrv_connection_dbg(xconn),
4118 strerror(saved_errno)));
4119 errno = saved_errno;
4120 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4122 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4123 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4124 /* No outbuf here means successful sendfile. */
4128 DEBUG(0,("send_file_readX: sendfile failed for file "
4129 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4131 exit_server_cleanly("send_file_readX sendfile failed");
4132 } else if (nread == 0) {
4134 * Some sendfile implementations return 0 to indicate
4135 * that there was a short read, but nothing was
4136 * actually written to the socket. In this case,
4137 * fallback to the normal read path so the header gets
4138 * the correct byte count.
4140 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4141 "falling back to the normal read: %s\n",
4146 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4147 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4149 /* Deal with possible short send. */
4150 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4153 ret = sendfile_short_send(xconn, fsp, nread,
4154 sizeof(headerbuf), smb_maxcnt);
4157 r = "send_file_readX: sendfile_short_send failed";
4158 DEBUG(0,("%s for file %s (%s).\n",
4159 r, fsp_str_dbg(fsp), strerror(errno)));
4160 exit_server_cleanly(r);
4163 /* No outbuf here means successful sendfile. */
4164 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4165 SMB_PERFCOUNT_END(&req->pcd);
4171 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4172 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4175 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4176 (startpos > fsp->fsp_name->st.st_ex_size) ||
4177 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4179 * We already know that we would do a short
4180 * read, so don't try the sendfile() path.
4182 goto nosendfile_read;
4185 construct_reply_common_req(req, (char *)headerbuf);
4186 setup_readX_header((char *)headerbuf, smb_maxcnt);
4188 /* Send out the header. */
4189 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4191 if (ret != sizeof(headerbuf)) {
4192 saved_errno = errno;
4194 * Try and give an error message saying what
4197 DEBUG(0,("send_file_readX: write_data failed for file "
4198 "%s (%s) for client %s. Terminating\n",
4200 smbXsrv_connection_dbg(xconn),
4201 strerror(saved_errno)));
4202 errno = saved_errno;
4203 exit_server_cleanly("send_file_readX sendfile failed");
4205 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4207 saved_errno = errno;
4208 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4209 "%s (%s) for client %s. Terminating\n",
4211 smbXsrv_connection_dbg(xconn),
4212 strerror(saved_errno)));
4213 errno = saved_errno;
4214 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4221 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4222 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4223 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4225 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4226 startpos, smb_maxcnt);
4227 saved_errno = errno;
4230 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4234 setup_readX_header((char *)req->outbuf, nread);
4236 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4237 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4241 TALLOC_FREE(req->outbuf);
4245 /****************************************************************************
4246 Work out how much space we have for a read return.
4247 ****************************************************************************/
4249 static size_t calc_max_read_pdu(const struct smb_request *req)
4251 struct smbXsrv_connection *xconn = req->xconn;
4253 if (xconn->protocol < PROTOCOL_NT1) {
4254 return xconn->smb1.sessions.max_send;
4257 if (!lp_large_readwrite()) {
4258 return xconn->smb1.sessions.max_send;
4261 if (req_is_in_chain(req)) {
4262 return xconn->smb1.sessions.max_send;
4265 if (req->encrypted) {
4267 * Don't take encrypted traffic up to the
4268 * limit. There are padding considerations
4269 * that make that tricky.
4271 return xconn->smb1.sessions.max_send;
4274 if (srv_is_signing_active(xconn)) {
4278 if (!lp_unix_extensions()) {
4283 * We can do ultra-large POSIX reads.
4288 /****************************************************************************
4289 Calculate how big a read can be. Copes with all clients. It's always
4290 safe to return a short read - Windows does this.
4291 ****************************************************************************/
4293 static size_t calc_read_size(const struct smb_request *req,
4297 struct smbXsrv_connection *xconn = req->xconn;
4298 size_t max_pdu = calc_max_read_pdu(req);
4299 size_t total_size = 0;
4300 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4301 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4304 * Windows explicitly ignores upper size of 0xFFFF.
4305 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4306 * We must do the same as these will never fit even in
4307 * an extended size NetBIOS packet.
4309 if (upper_size == 0xFFFF) {
4313 if (xconn->protocol < PROTOCOL_NT1) {
4317 total_size = ((upper_size<<16) | lower_size);
4320 * LARGE_READX test shows it's always safe to return
4321 * a short read. Windows does so.
4323 return MIN(total_size, max_len);
4326 /****************************************************************************
4327 Reply to a read and X.
4328 ****************************************************************************/
4330 void reply_read_and_X(struct smb_request *req)
4332 connection_struct *conn = req->conn;
4337 bool big_readX = False;
4339 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4342 START_PROFILE(SMBreadX);
4344 if ((req->wct != 10) && (req->wct != 12)) {
4345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4349 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4350 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4351 smb_maxcnt = SVAL(req->vwv+5, 0);
4353 /* If it's an IPC, pass off the pipe handler. */
4355 reply_pipe_read_and_X(req);
4356 END_PROFILE(SMBreadX);
4360 if (!check_fsp(conn, req, fsp)) {
4361 END_PROFILE(SMBreadX);
4365 if (!CHECK_READ(fsp,req)) {
4366 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4367 END_PROFILE(SMBreadX);
4371 upper_size = SVAL(req->vwv+7, 0);
4372 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4373 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4375 * This is a heuristic to avoid keeping large
4376 * outgoing buffers around over long-lived aio
4382 if (req->wct == 12) {
4384 * This is a large offset (64 bit) read.
4386 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4391 NTSTATUS status = schedule_aio_read_and_X(conn,
4396 if (NT_STATUS_IS_OK(status)) {
4397 /* Read scheduled - we're done. */
4400 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4401 /* Real error - report to client. */
4402 END_PROFILE(SMBreadX);
4403 reply_nterror(req, status);
4406 /* NT_STATUS_RETRY - fall back to sync read. */
4409 smbd_lock_socket(req->xconn);
4410 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4411 smbd_unlock_socket(req->xconn);
4414 END_PROFILE(SMBreadX);
4418 /****************************************************************************
4419 Error replies to writebraw must have smb_wct == 1. Fix this up.
4420 ****************************************************************************/
4422 void error_to_writebrawerr(struct smb_request *req)
4424 uint8_t *old_outbuf = req->outbuf;
4426 reply_outbuf(req, 1, 0);
4428 memcpy(req->outbuf, old_outbuf, smb_size);
4429 TALLOC_FREE(old_outbuf);
4432 /****************************************************************************
4433 Read 4 bytes of a smb packet and return the smb length of the packet.
4434 Store the result in the buffer. This version of the function will
4435 never return a session keepalive (length of zero).
4436 Timeout is in milliseconds.
4437 ****************************************************************************/
4439 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4442 uint8_t msgtype = NBSSkeepalive;
4444 while (msgtype == NBSSkeepalive) {
4447 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4449 if (!NT_STATUS_IS_OK(status)) {
4450 char addr[INET6_ADDRSTRLEN];
4451 /* Try and give an error message
4452 * saying what client failed. */
4453 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4454 "client %s read error = %s.\n",
4455 get_peer_addr(fd,addr,sizeof(addr)),
4456 nt_errstr(status)));
4460 msgtype = CVAL(inbuf, 0);
4463 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4464 (unsigned long)len));
4466 return NT_STATUS_OK;
4469 /****************************************************************************
4470 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4471 ****************************************************************************/
4473 void reply_writebraw(struct smb_request *req)
4475 connection_struct *conn = req->conn;
4476 struct smbXsrv_connection *xconn = req->xconn;
4479 ssize_t total_written=0;
4480 size_t numtowrite=0;
4483 const char *data=NULL;
4486 struct lock_struct lock;
4489 START_PROFILE(SMBwritebraw);
4492 * If we ever reply with an error, it must have the SMB command
4493 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4496 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4498 if (srv_is_signing_active(xconn)) {
4499 END_PROFILE(SMBwritebraw);
4500 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4501 "raw reads/writes are disallowed.");
4504 if (req->wct < 12) {
4505 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4506 error_to_writebrawerr(req);
4507 END_PROFILE(SMBwritebraw);
4511 if (xconn->smb1.echo_handler.trusted_fde) {
4512 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4513 "'async smb echo handler = yes'\n"));
4514 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4515 error_to_writebrawerr(req);
4516 END_PROFILE(SMBwritebraw);
4520 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4521 if (!check_fsp(conn, req, fsp)) {
4522 error_to_writebrawerr(req);
4523 END_PROFILE(SMBwritebraw);
4527 if (!CHECK_WRITE(fsp)) {
4528 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4529 error_to_writebrawerr(req);
4530 END_PROFILE(SMBwritebraw);
4534 tcount = IVAL(req->vwv+1, 0);
4535 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4536 write_through = BITSETW(req->vwv+7,0);
4538 /* We have to deal with slightly different formats depending
4539 on whether we are using the core+ or lanman1.0 protocol */
4541 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4542 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4543 data = smb_buf_const(req->inbuf);
4545 numtowrite = SVAL(req->vwv+10, 0);
4546 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4549 /* Ensure we don't write bytes past the end of this packet. */
4551 * This already protects us against CVE-2017-12163.
4553 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4555 error_to_writebrawerr(req);
4556 END_PROFILE(SMBwritebraw);
4560 if (!fsp->print_file) {
4561 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4562 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4565 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4566 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4567 error_to_writebrawerr(req);
4568 END_PROFILE(SMBwritebraw);
4574 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4577 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4578 "wrote=%d sync=%d\n",
4579 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4580 (int)nwritten, (int)write_through));
4582 if (nwritten < (ssize_t)numtowrite) {
4583 reply_nterror(req, NT_STATUS_DISK_FULL);
4584 error_to_writebrawerr(req);
4588 total_written = nwritten;
4590 /* Allocate a buffer of 64k + length. */
4591 buf = talloc_array(NULL, char, 65540);
4593 reply_nterror(req, NT_STATUS_NO_MEMORY);
4594 error_to_writebrawerr(req);
4598 /* Return a SMBwritebraw message to the redirector to tell
4599 * it to send more bytes */
4601 memcpy(buf, req->inbuf, smb_size);
4602 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4603 SCVAL(buf,smb_com,SMBwritebraw);
4604 SSVALS(buf,smb_vwv0,0xFFFF);
4606 if (!srv_send_smb(req->xconn,
4608 false, 0, /* no signing */
4609 IS_CONN_ENCRYPTED(conn),
4611 exit_server_cleanly("reply_writebraw: srv_send_smb "
4615 /* Now read the raw data into the buffer and write it */
4616 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4618 if (!NT_STATUS_IS_OK(status)) {
4619 exit_server_cleanly("secondary writebraw failed");
4622 /* Set up outbuf to return the correct size */
4623 reply_outbuf(req, 1, 0);
4625 if (numtowrite != 0) {
4627 if (numtowrite > 0xFFFF) {
4628 DEBUG(0,("reply_writebraw: Oversize secondary write "
4629 "raw requested (%u). Terminating\n",
4630 (unsigned int)numtowrite ));
4631 exit_server_cleanly("secondary writebraw failed");
4634 if (tcount > nwritten+numtowrite) {
4635 DEBUG(3,("reply_writebraw: Client overestimated the "
4637 (int)tcount,(int)nwritten,(int)numtowrite));
4640 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4643 if (!NT_STATUS_IS_OK(status)) {
4644 /* Try and give an error message
4645 * saying what client failed. */
4646 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4647 "raw read failed (%s) for client %s. "
4648 "Terminating\n", nt_errstr(status),
4649 smbXsrv_connection_dbg(xconn)));
4650 exit_server_cleanly("secondary writebraw failed");
4654 * We are not vulnerable to CVE-2017-12163
4655 * here as we are guaranteed to have numtowrite
4656 * bytes available - we just read from the client.
4658 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4659 if (nwritten == -1) {
4661 reply_nterror(req, map_nt_error_from_unix(errno));
4662 error_to_writebrawerr(req);
4666 if (nwritten < (ssize_t)numtowrite) {
4667 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4668 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4672 total_written += nwritten;
4677 SSVAL(req->outbuf,smb_vwv0,total_written);
4679 status = sync_file(conn, fsp, write_through);
4680 if (!NT_STATUS_IS_OK(status)) {
4681 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4682 fsp_str_dbg(fsp), nt_errstr(status)));
4683 reply_nterror(req, status);
4684 error_to_writebrawerr(req);
4688 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4690 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4691 (int)total_written));
4693 /* We won't return a status if write through is not selected - this
4694 * follows what WfWg does */
4695 END_PROFILE(SMBwritebraw);
4697 if (!write_through && total_written==tcount) {
4699 #if RABBIT_PELLET_FIX
4701 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4702 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4705 if (!send_keepalive(xconn->transport.sock)) {
4706 exit_server_cleanly("reply_writebraw: send of "
4707 "keepalive failed");
4710 TALLOC_FREE(req->outbuf);
4715 END_PROFILE(SMBwritebraw);
4720 #define DBGC_CLASS DBGC_LOCKING
4722 /****************************************************************************
4723 Reply to a writeunlock (core+).
4724 ****************************************************************************/
4726 void reply_writeunlock(struct smb_request *req)
4728 connection_struct *conn = req->conn;
4729 ssize_t nwritten = -1;
4734 NTSTATUS status = NT_STATUS_OK;
4736 struct lock_struct lock;
4737 int saved_errno = 0;
4739 START_PROFILE(SMBwriteunlock);
4742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4743 END_PROFILE(SMBwriteunlock);
4747 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4749 if (!check_fsp(conn, req, fsp)) {
4750 END_PROFILE(SMBwriteunlock);
4754 if (!CHECK_WRITE(fsp)) {
4755 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4756 END_PROFILE(SMBwriteunlock);
4760 numtowrite = SVAL(req->vwv+1, 0);
4761 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4762 data = (const char *)req->buf + 3;
4765 * Ensure client isn't asking us to write more than
4766 * they sent. CVE-2017-12163.
4768 remaining = smbreq_bufrem(req, data);
4769 if (numtowrite > remaining) {
4770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4771 END_PROFILE(SMBwriteunlock);
4775 if (!fsp->print_file && numtowrite > 0) {
4776 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4777 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4780 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4781 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4782 END_PROFILE(SMBwriteunlock);
4787 /* The special X/Open SMB protocol handling of
4788 zero length writes is *NOT* done for
4790 if(numtowrite == 0) {
4793 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4794 saved_errno = errno;
4797 status = sync_file(conn, fsp, False /* write through */);
4798 if (!NT_STATUS_IS_OK(status)) {
4799 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4800 fsp_str_dbg(fsp), nt_errstr(status)));
4801 reply_nterror(req, status);
4806 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4810 if((nwritten < numtowrite) && (numtowrite != 0)) {
4811 reply_nterror(req, NT_STATUS_DISK_FULL);
4815 if (numtowrite && !fsp->print_file) {
4816 struct smbd_lock_element l = {
4817 .smblctx = req->smbpid,
4818 .brltype = UNLOCK_LOCK,
4820 .count = numtowrite,
4822 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
4823 if (NT_STATUS_V(status)) {
4824 reply_nterror(req, status);
4829 reply_outbuf(req, 1, 0);
4831 SSVAL(req->outbuf,smb_vwv0,nwritten);
4833 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4834 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4837 END_PROFILE(SMBwriteunlock);
4842 #define DBGC_CLASS DBGC_ALL
4844 /****************************************************************************
4846 ****************************************************************************/
4848 void reply_write(struct smb_request *req)
4850 connection_struct *conn = req->conn;
4853 ssize_t nwritten = -1;
4857 struct lock_struct lock;
4859 int saved_errno = 0;
4861 START_PROFILE(SMBwrite);
4864 END_PROFILE(SMBwrite);
4865 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4869 /* If it's an IPC, pass off the pipe handler. */
4871 reply_pipe_write(req);
4872 END_PROFILE(SMBwrite);
4876 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4878 if (!check_fsp(conn, req, fsp)) {
4879 END_PROFILE(SMBwrite);
4883 if (!CHECK_WRITE(fsp)) {
4884 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4885 END_PROFILE(SMBwrite);
4889 numtowrite = SVAL(req->vwv+1, 0);
4890 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4891 data = (const char *)req->buf + 3;
4894 * Ensure client isn't asking us to write more than
4895 * they sent. CVE-2017-12163.
4897 remaining = smbreq_bufrem(req, data);
4898 if (numtowrite > remaining) {
4899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4900 END_PROFILE(SMBwrite);
4904 if (!fsp->print_file) {
4905 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4906 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4909 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4910 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4911 END_PROFILE(SMBwrite);
4917 * X/Open SMB protocol says that if smb_vwv1 is
4918 * zero then the file size should be extended or
4919 * truncated to the size given in smb_vwv[2-3].
4922 if(numtowrite == 0) {
4924 * This is actually an allocate call, and set EOF. JRA.
4926 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4928 reply_nterror(req, NT_STATUS_DISK_FULL);
4931 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4933 reply_nterror(req, NT_STATUS_DISK_FULL);
4936 trigger_write_time_update_immediate(fsp);
4938 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4941 status = sync_file(conn, fsp, False);
4942 if (!NT_STATUS_IS_OK(status)) {
4943 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4944 fsp_str_dbg(fsp), nt_errstr(status)));
4945 reply_nterror(req, status);
4950 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4954 if((nwritten == 0) && (numtowrite != 0)) {
4955 reply_nterror(req, NT_STATUS_DISK_FULL);
4959 reply_outbuf(req, 1, 0);
4961 SSVAL(req->outbuf,smb_vwv0,nwritten);
4963 if (nwritten < (ssize_t)numtowrite) {
4964 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4965 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4968 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4971 END_PROFILE(SMBwrite);
4975 /****************************************************************************
4976 Ensure a buffer is a valid writeX for recvfile purposes.
4977 ****************************************************************************/
4979 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4980 (2*14) + /* word count (including bcc) */ \
4983 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4984 const uint8_t *inbuf)
4987 unsigned int doff = 0;
4988 size_t len = smb_len_large(inbuf);
4990 struct smbXsrv_open *op = NULL;
4991 struct files_struct *fsp = NULL;
4994 if (is_encrypted_packet(inbuf)) {
4995 /* Can't do this on encrypted
5000 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5004 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5005 CVAL(inbuf,smb_wct) != 14) {
5006 DEBUG(10,("is_valid_writeX_buffer: chained or "
5007 "invalid word length.\n"));
5011 fnum = SVAL(inbuf, smb_vwv2);
5012 status = smb1srv_open_lookup(xconn,
5016 if (!NT_STATUS_IS_OK(status)) {
5017 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5022 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5025 if (fsp->conn == NULL) {
5026 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5030 if (IS_IPC(fsp->conn)) {
5031 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5034 if (IS_PRINT(fsp->conn)) {
5035 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5038 if (fsp->base_fsp != NULL) {
5039 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5042 doff = SVAL(inbuf,smb_vwv11);
5044 numtowrite = SVAL(inbuf,smb_vwv10);
5046 if (len > doff && len - doff > 0xFFFF) {
5047 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5050 if (numtowrite == 0) {
5051 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5055 /* Ensure the sizes match up. */
5056 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5057 /* no pad byte...old smbclient :-( */
5058 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5060 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5064 if (len - doff != numtowrite) {
5065 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5066 "len = %u, doff = %u, numtowrite = %u\n",
5069 (unsigned int)numtowrite ));
5073 DEBUG(10,("is_valid_writeX_buffer: true "
5074 "len = %u, doff = %u, numtowrite = %u\n",
5077 (unsigned int)numtowrite ));
5082 /****************************************************************************
5083 Reply to a write and X.
5084 ****************************************************************************/
5086 void reply_write_and_X(struct smb_request *req)
5088 connection_struct *conn = req->conn;
5089 struct smbXsrv_connection *xconn = req->xconn;
5091 struct lock_struct lock;
5096 unsigned int smb_doff;
5097 unsigned int smblen;
5100 int saved_errno = 0;
5102 START_PROFILE(SMBwriteX);
5104 if ((req->wct != 12) && (req->wct != 14)) {
5105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5109 numtowrite = SVAL(req->vwv+10, 0);
5110 smb_doff = SVAL(req->vwv+11, 0);
5111 smblen = smb_len(req->inbuf);
5113 if (req->unread_bytes > 0xFFFF ||
5114 (smblen > smb_doff &&
5115 smblen - smb_doff > 0xFFFF)) {
5116 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5119 if (req->unread_bytes) {
5120 /* Can't do a recvfile write on IPC$ */
5122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5125 if (numtowrite != req->unread_bytes) {
5126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5131 * This already protects us against CVE-2017-12163.
5133 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5134 smb_doff + numtowrite > smblen) {
5135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5140 /* If it's an IPC, pass off the pipe handler. */
5142 if (req->unread_bytes) {
5143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5146 reply_pipe_write_and_X(req);
5150 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5151 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5152 write_through = BITSETW(req->vwv+7,0);
5154 if (!check_fsp(conn, req, fsp)) {
5158 if (!CHECK_WRITE(fsp)) {
5159 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5163 data = smb_base(req->inbuf) + smb_doff;
5165 if(req->wct == 14) {
5167 * This is a large offset (64 bit) write.
5169 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5173 /* X/Open SMB protocol says that, unlike SMBwrite
5174 if the length is zero then NO truncation is
5175 done, just a write of zero. To truncate a file,
5178 if(numtowrite == 0) {
5181 if (req->unread_bytes == 0) {
5182 status = schedule_aio_write_and_X(conn,
5189 if (NT_STATUS_IS_OK(status)) {
5190 /* write scheduled - we're done. */
5193 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5194 /* Real error - report to client. */
5195 reply_nterror(req, status);
5198 /* NT_STATUS_RETRY - fall through to sync write. */
5201 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5202 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5205 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5206 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5210 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5211 saved_errno = errno;
5215 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5219 if((nwritten == 0) && (numtowrite != 0)) {
5220 reply_nterror(req, NT_STATUS_DISK_FULL);
5224 reply_outbuf(req, 6, 0);
5225 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5226 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5227 SSVAL(req->outbuf,smb_vwv2,nwritten);
5228 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5230 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5231 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5233 status = sync_file(conn, fsp, write_through);
5234 if (!NT_STATUS_IS_OK(status)) {
5235 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5236 fsp_str_dbg(fsp), nt_errstr(status)));
5237 reply_nterror(req, status);
5241 END_PROFILE(SMBwriteX);
5245 if (req->unread_bytes) {
5246 /* writeX failed. drain socket. */
5247 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5248 req->unread_bytes) {
5249 smb_panic("failed to drain pending bytes");
5251 req->unread_bytes = 0;
5254 END_PROFILE(SMBwriteX);
5258 /****************************************************************************
5260 ****************************************************************************/
5262 void reply_lseek(struct smb_request *req)
5264 connection_struct *conn = req->conn;
5270 START_PROFILE(SMBlseek);
5273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5274 END_PROFILE(SMBlseek);
5278 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5280 if (!check_fsp(conn, req, fsp)) {
5284 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5286 mode = SVAL(req->vwv+1, 0) & 3;
5287 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5288 startpos = (off_t)IVALS(req->vwv+2, 0);
5297 res = fsp->fh->pos + startpos;
5308 if (umode == SEEK_END) {
5309 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5310 if(errno == EINVAL) {
5311 off_t current_pos = startpos;
5313 if(fsp_stat(fsp) == -1) {
5315 map_nt_error_from_unix(errno));
5316 END_PROFILE(SMBlseek);
5320 current_pos += fsp->fsp_name->st.st_ex_size;
5322 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5327 reply_nterror(req, map_nt_error_from_unix(errno));
5328 END_PROFILE(SMBlseek);
5335 reply_outbuf(req, 2, 0);
5336 SIVAL(req->outbuf,smb_vwv0,res);
5338 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5339 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5341 END_PROFILE(SMBlseek);
5345 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5348 connection_struct *conn = talloc_get_type_abort(
5349 private_data, connection_struct);
5351 if (conn != fsp->conn) {
5354 if (fsp->fh->fd == -1) {
5357 sync_file(conn, fsp, True /* write through */);
5362 /****************************************************************************
5364 ****************************************************************************/
5366 void reply_flush(struct smb_request *req)
5368 connection_struct *conn = req->conn;
5372 START_PROFILE(SMBflush);
5375 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5379 fnum = SVAL(req->vwv+0, 0);
5380 fsp = file_fsp(req, fnum);
5382 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5387 files_forall(req->sconn, file_sync_one_fn, conn);
5389 NTSTATUS status = sync_file(conn, fsp, True);
5390 if (!NT_STATUS_IS_OK(status)) {
5391 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5392 fsp_str_dbg(fsp), nt_errstr(status)));
5393 reply_nterror(req, status);
5394 END_PROFILE(SMBflush);
5399 reply_outbuf(req, 0, 0);
5401 DEBUG(3,("flush\n"));
5402 END_PROFILE(SMBflush);
5406 /****************************************************************************
5408 conn POINTER CAN BE NULL HERE !
5409 ****************************************************************************/
5411 void reply_exit(struct smb_request *req)
5413 START_PROFILE(SMBexit);
5415 file_close_pid(req->sconn, req->smbpid, req->vuid);
5417 reply_outbuf(req, 0, 0);
5419 DEBUG(3,("exit\n"));
5421 END_PROFILE(SMBexit);
5425 struct reply_close_state {
5427 struct smb_request *smbreq;
5430 static void do_smb1_close(struct tevent_req *req);
5432 void reply_close(struct smb_request *req)
5434 connection_struct *conn = req->conn;
5435 NTSTATUS status = NT_STATUS_OK;
5436 files_struct *fsp = NULL;
5437 START_PROFILE(SMBclose);
5440 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5441 END_PROFILE(SMBclose);
5445 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5448 * We can only use check_fsp if we know it's not a directory.
5451 if (!check_fsp_open(conn, req, fsp)) {
5452 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5453 END_PROFILE(SMBclose);
5457 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5458 fsp->is_directory ? "directory" : "file",
5459 fsp->fh->fd, fsp_fnum_dbg(fsp),
5460 conn->num_files_open));
5462 if (!fsp->is_directory) {
5466 * Take care of any time sent in the close.
5469 t = srv_make_unix_date3(req->vwv+1);
5470 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5473 if (fsp->num_aio_requests != 0) {
5475 struct reply_close_state *state;
5477 DEBUG(10, ("closing with aio %u requests pending\n",
5478 fsp->num_aio_requests));
5481 * We depend on the aio_extra destructor to take care of this
5482 * close request once fsp->num_aio_request drops to 0.
5485 fsp->deferred_close = tevent_wait_send(
5486 fsp, fsp->conn->sconn->ev_ctx);
5487 if (fsp->deferred_close == NULL) {
5488 status = NT_STATUS_NO_MEMORY;
5492 state = talloc(fsp, struct reply_close_state);
5493 if (state == NULL) {
5494 TALLOC_FREE(fsp->deferred_close);
5495 status = NT_STATUS_NO_MEMORY;
5499 state->smbreq = talloc_move(fsp, &req);
5500 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5502 END_PROFILE(SMBclose);
5507 * close_file() returns the unix errno if an error was detected on
5508 * close - normally this is due to a disk full error. If not then it
5509 * was probably an I/O error.
5512 status = close_file(req, fsp, NORMAL_CLOSE);
5514 if (!NT_STATUS_IS_OK(status)) {
5515 reply_nterror(req, status);
5516 END_PROFILE(SMBclose);
5520 reply_outbuf(req, 0, 0);
5521 END_PROFILE(SMBclose);
5525 static void do_smb1_close(struct tevent_req *req)
5527 struct reply_close_state *state = tevent_req_callback_data(
5528 req, struct reply_close_state);
5529 struct smb_request *smbreq;
5533 ret = tevent_wait_recv(req);
5536 DEBUG(10, ("tevent_wait_recv returned %s\n",
5539 * Continue anyway, this should never happen
5544 * fsp->smb2_close_request right now is a talloc grandchild of
5545 * fsp. When we close_file(fsp), it would go with it. No chance to
5548 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5550 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5551 if (NT_STATUS_IS_OK(status)) {
5552 reply_outbuf(smbreq, 0, 0);
5554 reply_nterror(smbreq, status);
5556 if (!srv_send_smb(smbreq->xconn,
5557 (char *)smbreq->outbuf,
5560 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5562 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5565 TALLOC_FREE(smbreq);
5568 /****************************************************************************
5569 Reply to a writeclose (Core+ protocol).
5570 ****************************************************************************/
5572 void reply_writeclose(struct smb_request *req)
5574 connection_struct *conn = req->conn;
5577 ssize_t nwritten = -1;
5578 NTSTATUS close_status = NT_STATUS_OK;
5581 struct timespec mtime;
5583 struct lock_struct lock;
5585 START_PROFILE(SMBwriteclose);
5588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5589 END_PROFILE(SMBwriteclose);
5593 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5595 if (!check_fsp(conn, req, fsp)) {
5596 END_PROFILE(SMBwriteclose);
5599 if (!CHECK_WRITE(fsp)) {
5600 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5601 END_PROFILE(SMBwriteclose);
5605 numtowrite = SVAL(req->vwv+1, 0);
5606 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5607 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5608 data = (const char *)req->buf + 1;
5611 * Ensure client isn't asking us to write more than
5612 * they sent. CVE-2017-12163.
5614 remaining = smbreq_bufrem(req, data);
5615 if (numtowrite > remaining) {
5616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5617 END_PROFILE(SMBwriteclose);
5621 if (fsp->print_file == NULL) {
5622 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5623 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5626 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5627 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5628 END_PROFILE(SMBwriteclose);
5633 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5635 set_close_write_time(fsp, mtime);
5638 * More insanity. W2K only closes the file if writelen > 0.
5642 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5643 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5644 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5647 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5648 "file %s\n", fsp_str_dbg(fsp)));
5649 close_status = close_file(req, fsp, NORMAL_CLOSE);
5653 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5654 reply_nterror(req, NT_STATUS_DISK_FULL);
5658 if(!NT_STATUS_IS_OK(close_status)) {
5659 reply_nterror(req, close_status);
5663 reply_outbuf(req, 1, 0);
5665 SSVAL(req->outbuf,smb_vwv0,nwritten);
5669 END_PROFILE(SMBwriteclose);
5674 #define DBGC_CLASS DBGC_LOCKING
5676 /****************************************************************************
5678 ****************************************************************************/
5680 static void reply_lock_done(struct tevent_req *subreq);
5682 void reply_lock(struct smb_request *req)
5684 struct tevent_req *subreq = NULL;
5685 connection_struct *conn = req->conn;
5687 struct smbd_lock_element *lck = NULL;
5689 START_PROFILE(SMBlock);
5692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5693 END_PROFILE(SMBlock);
5697 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5699 if (!check_fsp(conn, req, fsp)) {
5700 END_PROFILE(SMBlock);
5704 lck = talloc(req, struct smbd_lock_element);
5706 reply_nterror(req, NT_STATUS_NO_MEMORY);
5707 END_PROFILE(SMBlock);
5711 *lck = (struct smbd_lock_element) {
5712 .smblctx = req->smbpid,
5713 .brltype = WRITE_LOCK,
5714 .count = IVAL(req->vwv+1, 0),
5715 .offset = IVAL(req->vwv+3, 0),
5718 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5724 subreq = smbd_smb1_do_locks_send(
5730 false, /* large_offset */
5734 if (subreq == NULL) {
5735 reply_nterror(req, NT_STATUS_NO_MEMORY);
5736 END_PROFILE(SMBlock);
5739 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5740 END_PROFILE(SMBlock);
5743 static void reply_lock_done(struct tevent_req *subreq)
5745 struct smb_request *req = NULL;
5749 START_PROFILE(SMBlock);
5751 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5754 status = smbd_smb1_do_locks_recv(subreq);
5755 TALLOC_FREE(subreq);
5757 if (NT_STATUS_IS_OK(status)) {
5758 reply_outbuf(req, 0, 0);
5760 reply_nterror(req, status);
5763 ok = srv_send_smb(req->xconn,
5764 (char *)req->outbuf,
5767 IS_CONN_ENCRYPTED(req->conn),
5770 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
5773 END_PROFILE(SMBlock);
5776 /****************************************************************************
5778 ****************************************************************************/
5780 void reply_unlock(struct smb_request *req)
5782 connection_struct *conn = req->conn;
5785 struct smbd_lock_element lck;
5787 START_PROFILE(SMBunlock);
5790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5791 END_PROFILE(SMBunlock);
5795 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5797 if (!check_fsp(conn, req, fsp)) {
5798 END_PROFILE(SMBunlock);
5802 lck = (struct smbd_lock_element) {
5803 .smblctx = req->smbpid,
5804 .brltype = UNLOCK_LOCK,
5805 .offset = IVAL(req->vwv+3, 0),
5806 .count = IVAL(req->vwv+1, 0),
5809 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
5811 if (!NT_STATUS_IS_OK(status)) {
5812 reply_nterror(req, status);
5813 END_PROFILE(SMBunlock);
5817 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5823 reply_outbuf(req, 0, 0);
5825 END_PROFILE(SMBunlock);
5830 #define DBGC_CLASS DBGC_ALL
5832 /****************************************************************************
5834 conn POINTER CAN BE NULL HERE !
5835 ****************************************************************************/
5837 void reply_tdis(struct smb_request *req)
5840 connection_struct *conn = req->conn;
5841 struct smbXsrv_tcon *tcon;
5843 START_PROFILE(SMBtdis);
5846 DEBUG(4,("Invalid connection in tdis\n"));
5847 reply_force_doserror(req, ERRSRV, ERRinvnid);
5848 END_PROFILE(SMBtdis);
5856 * TODO: cancel all outstanding requests on the tcon
5858 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5859 if (!NT_STATUS_IS_OK(status)) {
5860 DEBUG(0, ("reply_tdis: "
5861 "smbXsrv_tcon_disconnect() failed: %s\n",
5862 nt_errstr(status)));
5864 * If we hit this case, there is something completely
5865 * wrong, so we better disconnect the transport connection.
5867 END_PROFILE(SMBtdis);
5868 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5874 reply_outbuf(req, 0, 0);
5875 END_PROFILE(SMBtdis);
5879 /****************************************************************************
5881 conn POINTER CAN BE NULL HERE !
5882 ****************************************************************************/
5884 void reply_echo(struct smb_request *req)
5886 connection_struct *conn = req->conn;
5887 struct smb_perfcount_data local_pcd;
5888 struct smb_perfcount_data *cur_pcd;
5892 START_PROFILE(SMBecho);
5894 smb_init_perfcount_data(&local_pcd);
5897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5898 END_PROFILE(SMBecho);
5902 smb_reverb = SVAL(req->vwv+0, 0);
5904 reply_outbuf(req, 1, req->buflen);
5906 /* copy any incoming data back out */
5907 if (req->buflen > 0) {
5908 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5911 if (smb_reverb > 100) {
5912 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5916 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5918 /* this makes sure we catch the request pcd */
5919 if (seq_num == smb_reverb) {
5920 cur_pcd = &req->pcd;
5922 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5923 cur_pcd = &local_pcd;
5926 SSVAL(req->outbuf,smb_vwv0,seq_num);
5928 show_msg((char *)req->outbuf);
5929 if (!srv_send_smb(req->xconn,
5930 (char *)req->outbuf,
5931 true, req->seqnum+1,
5932 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5934 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5937 DEBUG(3,("echo %d times\n", smb_reverb));
5939 TALLOC_FREE(req->outbuf);
5941 END_PROFILE(SMBecho);
5945 /****************************************************************************
5946 Reply to a printopen.
5947 ****************************************************************************/
5949 void reply_printopen(struct smb_request *req)
5951 connection_struct *conn = req->conn;
5955 START_PROFILE(SMBsplopen);
5958 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5959 END_PROFILE(SMBsplopen);
5963 if (!CAN_PRINT(conn)) {
5964 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5965 END_PROFILE(SMBsplopen);
5969 status = file_new(req, conn, &fsp);
5970 if(!NT_STATUS_IS_OK(status)) {
5971 reply_nterror(req, status);
5972 END_PROFILE(SMBsplopen);
5976 /* Open for exclusive use, write only. */
5977 status = print_spool_open(fsp, NULL, req->vuid);
5979 if (!NT_STATUS_IS_OK(status)) {
5980 file_free(req, fsp);
5981 reply_nterror(req, status);
5982 END_PROFILE(SMBsplopen);
5986 reply_outbuf(req, 1, 0);
5987 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5989 DEBUG(3,("openprint fd=%d %s\n",
5990 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5992 END_PROFILE(SMBsplopen);
5996 /****************************************************************************
5997 Reply to a printclose.
5998 ****************************************************************************/
6000 void reply_printclose(struct smb_request *req)
6002 connection_struct *conn = req->conn;
6006 START_PROFILE(SMBsplclose);
6009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6010 END_PROFILE(SMBsplclose);
6014 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6016 if (!check_fsp(conn, req, fsp)) {
6017 END_PROFILE(SMBsplclose);
6021 if (!CAN_PRINT(conn)) {
6022 reply_force_doserror(req, ERRSRV, ERRerror);
6023 END_PROFILE(SMBsplclose);
6027 DEBUG(3,("printclose fd=%d %s\n",
6028 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6030 status = close_file(req, fsp, NORMAL_CLOSE);
6032 if(!NT_STATUS_IS_OK(status)) {
6033 reply_nterror(req, status);
6034 END_PROFILE(SMBsplclose);
6038 reply_outbuf(req, 0, 0);
6040 END_PROFILE(SMBsplclose);
6044 /****************************************************************************
6045 Reply to a printqueue.
6046 ****************************************************************************/
6048 void reply_printqueue(struct smb_request *req)
6050 connection_struct *conn = req->conn;
6054 START_PROFILE(SMBsplretq);
6057 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6058 END_PROFILE(SMBsplretq);
6062 max_count = SVAL(req->vwv+0, 0);
6063 start_index = SVAL(req->vwv+1, 0);
6065 /* we used to allow the client to get the cnum wrong, but that
6066 is really quite gross and only worked when there was only
6067 one printer - I think we should now only accept it if they
6068 get it right (tridge) */
6069 if (!CAN_PRINT(conn)) {
6070 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6071 END_PROFILE(SMBsplretq);
6075 reply_outbuf(req, 2, 3);
6076 SSVAL(req->outbuf,smb_vwv0,0);
6077 SSVAL(req->outbuf,smb_vwv1,0);
6078 SCVAL(smb_buf(req->outbuf),0,1);
6079 SSVAL(smb_buf(req->outbuf),1,0);
6081 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6082 start_index, max_count));
6085 TALLOC_CTX *mem_ctx = talloc_tos();
6088 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
6089 struct rpc_pipe_client *cli = NULL;
6090 struct dcerpc_binding_handle *b = NULL;
6091 struct policy_handle handle;
6092 struct spoolss_DevmodeContainer devmode_ctr;
6093 union spoolss_JobInfo *info;
6095 uint32_t num_to_get;
6099 ZERO_STRUCT(handle);
6101 status = rpc_pipe_open_interface(mem_ctx,
6104 conn->sconn->remote_address,
6105 conn->sconn->local_address,
6106 conn->sconn->msg_ctx,
6108 if (!NT_STATUS_IS_OK(status)) {
6109 DEBUG(0, ("reply_printqueue: "
6110 "could not connect to spoolss: %s\n",
6111 nt_errstr(status)));
6112 reply_nterror(req, status);
6115 b = cli->binding_handle;
6117 ZERO_STRUCT(devmode_ctr);
6119 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6122 SEC_FLAG_MAXIMUM_ALLOWED,
6125 if (!NT_STATUS_IS_OK(status)) {
6126 reply_nterror(req, status);
6129 if (!W_ERROR_IS_OK(werr)) {
6130 reply_nterror(req, werror_to_ntstatus(werr));
6134 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6142 if (!W_ERROR_IS_OK(werr)) {
6143 reply_nterror(req, werror_to_ntstatus(werr));
6147 if (max_count > 0) {
6148 first = start_index;
6150 first = start_index + max_count + 1;
6153 if (first >= count) {
6156 num_to_get = first + MIN(ABS(max_count), count - first);
6159 for (i = first; i < num_to_get; i++) {
6162 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6165 uint16_t qrapjobid = pjobid_to_rap(sharename,
6166 info[i].info2.job_id);
6168 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6174 srv_put_dos_date2(p, 0, qtime);
6175 SCVAL(p, 4, qstatus);
6176 SSVAL(p, 5, qrapjobid);
6177 SIVAL(p, 7, info[i].info2.size);
6179 status = srvstr_push(blob, req->flags2, p+12,
6180 info[i].info2.notify_name, 16, STR_ASCII, &len);
6181 if (!NT_STATUS_IS_OK(status)) {
6182 reply_nterror(req, status);
6185 if (message_push_blob(
6188 blob, sizeof(blob))) == -1) {
6189 reply_nterror(req, NT_STATUS_NO_MEMORY);
6195 SSVAL(req->outbuf,smb_vwv0,count);
6196 SSVAL(req->outbuf,smb_vwv1,
6197 (max_count>0?first+count:first-1));
6198 SCVAL(smb_buf(req->outbuf),0,1);
6199 SSVAL(smb_buf(req->outbuf),1,28*count);
6203 DEBUG(3, ("%u entries returned in queue\n",
6207 if (b && is_valid_policy_hnd(&handle)) {
6208 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6213 END_PROFILE(SMBsplretq);
6217 /****************************************************************************
6218 Reply to a printwrite.
6219 ****************************************************************************/
6221 void reply_printwrite(struct smb_request *req)
6223 connection_struct *conn = req->conn;
6228 START_PROFILE(SMBsplwr);
6231 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6232 END_PROFILE(SMBsplwr);
6236 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6238 if (!check_fsp(conn, req, fsp)) {
6239 END_PROFILE(SMBsplwr);
6243 if (!fsp->print_file) {
6244 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6245 END_PROFILE(SMBsplwr);
6249 if (!CHECK_WRITE(fsp)) {
6250 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6251 END_PROFILE(SMBsplwr);
6255 numtowrite = SVAL(req->buf, 1);
6258 * This already protects us against CVE-2017-12163.
6260 if (req->buflen < numtowrite + 3) {
6261 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6262 END_PROFILE(SMBsplwr);
6266 data = (const char *)req->buf + 3;
6268 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6269 reply_nterror(req, map_nt_error_from_unix(errno));
6270 END_PROFILE(SMBsplwr);
6274 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6276 END_PROFILE(SMBsplwr);
6280 /****************************************************************************
6282 ****************************************************************************/
6284 void reply_mkdir(struct smb_request *req)
6286 connection_struct *conn = req->conn;
6287 struct smb_filename *smb_dname = NULL;
6288 char *directory = NULL;
6291 TALLOC_CTX *ctx = talloc_tos();
6293 START_PROFILE(SMBmkdir);
6295 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6296 STR_TERMINATE, &status);
6297 if (!NT_STATUS_IS_OK(status)) {
6298 reply_nterror(req, status);
6302 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6303 status = filename_convert(ctx, conn,
6309 if (!NT_STATUS_IS_OK(status)) {
6310 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6311 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6312 ERRSRV, ERRbadpath);
6315 reply_nterror(req, status);
6319 status = create_directory(conn, req, smb_dname);
6321 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6323 if (!NT_STATUS_IS_OK(status)) {
6325 if (!use_nt_status()
6326 && NT_STATUS_EQUAL(status,
6327 NT_STATUS_OBJECT_NAME_COLLISION)) {
6329 * Yes, in the DOS error code case we get a
6330 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6331 * samba4 torture test.
6333 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6336 reply_nterror(req, status);
6340 reply_outbuf(req, 0, 0);
6342 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6344 TALLOC_FREE(smb_dname);
6345 END_PROFILE(SMBmkdir);
6349 /****************************************************************************
6351 ****************************************************************************/
6353 void reply_rmdir(struct smb_request *req)
6355 connection_struct *conn = req->conn;
6356 struct smb_filename *smb_dname = NULL;
6357 char *directory = NULL;
6359 TALLOC_CTX *ctx = talloc_tos();
6360 files_struct *fsp = NULL;
6362 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6363 struct smbd_server_connection *sconn = req->sconn;
6365 START_PROFILE(SMBrmdir);
6367 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6368 STR_TERMINATE, &status);
6369 if (!NT_STATUS_IS_OK(status)) {
6370 reply_nterror(req, status);
6374 status = filename_convert(ctx, conn,
6380 if (!NT_STATUS_IS_OK(status)) {
6381 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6382 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6383 ERRSRV, ERRbadpath);
6386 reply_nterror(req, status);
6390 if (is_ntfs_stream_smb_fname(smb_dname)) {
6391 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6395 status = SMB_VFS_CREATE_FILE(
6398 0, /* root_dir_fid */
6399 smb_dname, /* fname */
6400 DELETE_ACCESS, /* access_mask */
6401 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6403 FILE_OPEN, /* create_disposition*/
6404 FILE_DIRECTORY_FILE, /* create_options */
6405 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6406 0, /* oplock_request */
6408 0, /* allocation_size */
6409 0, /* private_flags */
6414 NULL, NULL); /* create context */
6416 if (!NT_STATUS_IS_OK(status)) {
6417 if (open_was_deferred(req->xconn, req->mid)) {
6418 /* We have re-scheduled this call. */
6421 reply_nterror(req, status);
6425 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6426 if (!NT_STATUS_IS_OK(status)) {
6427 close_file(req, fsp, ERROR_CLOSE);
6428 reply_nterror(req, status);
6432 if (!set_delete_on_close(fsp, true,
6433 conn->session_info->security_token,
6434 conn->session_info->unix_token)) {
6435 close_file(req, fsp, ERROR_CLOSE);
6436 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6440 status = close_file(req, fsp, NORMAL_CLOSE);
6441 if (!NT_STATUS_IS_OK(status)) {
6442 reply_nterror(req, status);
6444 reply_outbuf(req, 0, 0);
6447 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6449 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6451 TALLOC_FREE(smb_dname);
6452 END_PROFILE(SMBrmdir);
6456 /*******************************************************************
6457 Resolve wildcards in a filename rename.
6458 ********************************************************************/
6460 static bool resolve_wildcards(TALLOC_CTX *ctx,
6465 char *name2_copy = NULL;
6470 char *p,*p2, *pname1, *pname2;
6472 name2_copy = talloc_strdup(ctx, name2);
6477 pname1 = strrchr_m(name1,'/');
6478 pname2 = strrchr_m(name2_copy,'/');
6480 if (!pname1 || !pname2) {
6484 /* Truncate the copy of name2 at the last '/' */
6487 /* Now go past the '/' */
6491 root1 = talloc_strdup(ctx, pname1);
6492 root2 = talloc_strdup(ctx, pname2);
6494 if (!root1 || !root2) {
6498 p = strrchr_m(root1,'.');
6501 ext1 = talloc_strdup(ctx, p+1);
6503 ext1 = talloc_strdup(ctx, "");
6505 p = strrchr_m(root2,'.');
6508 ext2 = talloc_strdup(ctx, p+1);
6510 ext2 = talloc_strdup(ctx, "");
6513 if (!ext1 || !ext2) {
6521 /* Hmmm. Should this be mb-aware ? */
6524 } else if (*p2 == '*') {
6526 root2 = talloc_asprintf(ctx, "%s%s",
6545 /* Hmmm. Should this be mb-aware ? */
6548 } else if (*p2 == '*') {
6550 ext2 = talloc_asprintf(ctx, "%s%s",
6566 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6571 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6583 /****************************************************************************
6584 Ensure open files have their names updated. Updated to notify other smbd's
6586 ****************************************************************************/
6588 static void rename_open_files(connection_struct *conn,
6589 struct share_mode_lock *lck,
6591 uint32_t orig_name_hash,
6592 const struct smb_filename *smb_fname_dst)
6595 bool did_rename = False;
6597 uint32_t new_name_hash = 0;
6599 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6600 fsp = file_find_di_next(fsp)) {
6601 /* fsp_name is a relative path under the fsp. To change this for other
6602 sharepaths we need to manipulate relative paths. */
6603 /* TODO - create the absolute path and manipulate the newname
6604 relative to the sharepath. */
6605 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6608 if (fsp->name_hash != orig_name_hash) {
6611 DEBUG(10, ("rename_open_files: renaming file %s "
6612 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6613 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6614 smb_fname_str_dbg(smb_fname_dst)));
6616 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6617 if (NT_STATUS_IS_OK(status)) {
6619 new_name_hash = fsp->name_hash;
6624 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6625 "for %s\n", file_id_string_tos(&id),
6626 smb_fname_str_dbg(smb_fname_dst)));
6629 /* Send messages to all smbd's (not ourself) that the name has changed. */
6630 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6631 orig_name_hash, new_name_hash,
6636 /****************************************************************************
6637 We need to check if the source path is a parent directory of the destination
6638 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6639 refuse the rename with a sharing violation. Under UNIX the above call can
6640 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6641 probably need to check that the client is a Windows one before disallowing
6642 this as a UNIX client (one with UNIX extensions) can know the source is a
6643 symlink and make this decision intelligently. Found by an excellent bug
6644 report from <AndyLiebman@aol.com>.
6645 ****************************************************************************/
6647 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6648 const struct smb_filename *smb_fname_dst)
6650 const char *psrc = smb_fname_src->base_name;
6651 const char *pdst = smb_fname_dst->base_name;
6654 if (psrc[0] == '.' && psrc[1] == '/') {
6657 if (pdst[0] == '.' && pdst[1] == '/') {
6660 if ((slen = strlen(psrc)) > strlen(pdst)) {
6663 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6667 * Do the notify calls from a rename
6670 static void notify_rename(connection_struct *conn, bool is_dir,
6671 const struct smb_filename *smb_fname_src,
6672 const struct smb_filename *smb_fname_dst)
6674 char *parent_dir_src = NULL;
6675 char *parent_dir_dst = NULL;
6678 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6679 : FILE_NOTIFY_CHANGE_FILE_NAME;
6681 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6682 &parent_dir_src, NULL) ||
6683 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6684 &parent_dir_dst, NULL)) {
6688 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6689 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6690 smb_fname_src->base_name);
6691 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6692 smb_fname_dst->base_name);
6695 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6696 smb_fname_src->base_name);
6697 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6698 smb_fname_dst->base_name);
6701 /* this is a strange one. w2k3 gives an additional event for
6702 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6703 files, but not directories */
6705 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6706 FILE_NOTIFY_CHANGE_ATTRIBUTES
6707 |FILE_NOTIFY_CHANGE_CREATION,
6708 smb_fname_dst->base_name);
6711 TALLOC_FREE(parent_dir_src);
6712 TALLOC_FREE(parent_dir_dst);
6715 /****************************************************************************
6716 Returns an error if the parent directory for a filename is open in an
6718 ****************************************************************************/
6720 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6721 const struct smb_filename *smb_fname_dst_in)
6723 char *parent_dir = NULL;
6724 struct smb_filename smb_fname_parent;
6726 files_struct *fsp = NULL;
6729 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6730 &parent_dir, NULL)) {
6731 return NT_STATUS_NO_MEMORY;
6733 ZERO_STRUCT(smb_fname_parent);
6734 smb_fname_parent.base_name = parent_dir;
6736 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6738 return map_nt_error_from_unix(errno);
6742 * We're only checking on this smbd here, mostly good
6743 * enough.. and will pass tests.
6746 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6747 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6748 fsp = file_find_di_next(fsp)) {
6749 if (fsp->access_mask & DELETE_ACCESS) {
6750 return NT_STATUS_SHARING_VIOLATION;
6753 return NT_STATUS_OK;
6756 /****************************************************************************
6757 Rename an open file - given an fsp.
6758 ****************************************************************************/
6760 NTSTATUS rename_internals_fsp(connection_struct *conn,
6762 const struct smb_filename *smb_fname_dst_in,
6764 bool replace_if_exists)
6766 TALLOC_CTX *ctx = talloc_tos();
6767 struct smb_filename *smb_fname_dst = NULL;
6768 NTSTATUS status = NT_STATUS_OK;
6769 struct share_mode_lock *lck = NULL;
6770 uint32_t access_mask = SEC_DIR_ADD_FILE;
6771 bool dst_exists, old_is_stream, new_is_stream;
6773 status = check_name(conn, smb_fname_dst_in);
6774 if (!NT_STATUS_IS_OK(status)) {
6778 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6779 if (!NT_STATUS_IS_OK(status)) {
6783 if (file_has_open_streams(fsp)) {
6784 return NT_STATUS_ACCESS_DENIED;
6787 /* Make a copy of the dst smb_fname structs */
6789 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6790 if (smb_fname_dst == NULL) {
6791 status = NT_STATUS_NO_MEMORY;
6796 * Check for special case with case preserving and not
6797 * case sensitive. If the new last component differs from the original
6798 * last component only by case, then we should allow
6799 * the rename (user is trying to change the case of the
6802 if (!conn->case_sensitive && conn->case_preserve &&
6803 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6804 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6805 char *fname_dst_parent = NULL;
6806 const char *fname_dst_lcomp = NULL;
6807 char *orig_lcomp_path = NULL;
6808 char *orig_lcomp_stream = NULL;
6812 * Split off the last component of the processed
6813 * destination name. We will compare this to
6814 * the split components of smb_fname_dst->original_lcomp.
6816 if (!parent_dirname(ctx,
6817 smb_fname_dst->base_name,
6819 &fname_dst_lcomp)) {
6820 status = NT_STATUS_NO_MEMORY;
6825 * The original_lcomp component contains
6826 * the last_component of the path + stream
6827 * name (if a stream exists).
6829 * Split off the stream name so we
6830 * can check them separately.
6833 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6834 /* POSIX - no stream component. */
6835 orig_lcomp_path = talloc_strdup(ctx,
6836 smb_fname_dst->original_lcomp);
6837 if (orig_lcomp_path == NULL) {
6841 ok = split_stream_filename(ctx,
6842 smb_fname_dst->original_lcomp,
6844 &orig_lcomp_stream);
6848 TALLOC_FREE(fname_dst_parent);
6849 status = NT_STATUS_NO_MEMORY;
6853 /* If the base names only differ by case, use original. */
6854 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6857 * Replace the modified last component with the
6860 if (!ISDOT(fname_dst_parent)) {
6861 tmp = talloc_asprintf(smb_fname_dst,
6866 tmp = talloc_strdup(smb_fname_dst,
6870 status = NT_STATUS_NO_MEMORY;
6871 TALLOC_FREE(fname_dst_parent);
6872 TALLOC_FREE(orig_lcomp_path);
6873 TALLOC_FREE(orig_lcomp_stream);
6876 TALLOC_FREE(smb_fname_dst->base_name);
6877 smb_fname_dst->base_name = tmp;
6880 /* If the stream_names only differ by case, use original. */
6881 if(!strcsequal(smb_fname_dst->stream_name,
6882 orig_lcomp_stream)) {
6883 /* Use the original stream. */
6884 char *tmp = talloc_strdup(smb_fname_dst,
6887 status = NT_STATUS_NO_MEMORY;
6888 TALLOC_FREE(fname_dst_parent);
6889 TALLOC_FREE(orig_lcomp_path);
6890 TALLOC_FREE(orig_lcomp_stream);
6893 TALLOC_FREE(smb_fname_dst->stream_name);
6894 smb_fname_dst->stream_name = tmp;
6896 TALLOC_FREE(fname_dst_parent);
6897 TALLOC_FREE(orig_lcomp_path);
6898 TALLOC_FREE(orig_lcomp_stream);
6902 * If the src and dest names are identical - including case,
6903 * don't do the rename, just return success.
6906 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6907 strcsequal(fsp->fsp_name->stream_name,
6908 smb_fname_dst->stream_name)) {
6909 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6910 "- returning success\n",
6911 smb_fname_str_dbg(smb_fname_dst)));
6912 status = NT_STATUS_OK;
6916 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6917 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6919 /* Return the correct error code if both names aren't streams. */
6920 if (!old_is_stream && new_is_stream) {
6921 status = NT_STATUS_OBJECT_NAME_INVALID;
6925 if (old_is_stream && !new_is_stream) {
6926 status = NT_STATUS_INVALID_PARAMETER;
6930 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6932 if(!replace_if_exists && dst_exists) {
6933 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6934 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6935 smb_fname_str_dbg(smb_fname_dst)));
6936 status = NT_STATUS_OBJECT_NAME_COLLISION;
6941 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6942 &smb_fname_dst->st);
6943 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6945 /* The file can be open when renaming a stream */
6946 if (dst_fsp && !new_is_stream) {
6947 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6948 status = NT_STATUS_ACCESS_DENIED;
6953 /* Ensure we have a valid stat struct for the source. */
6954 status = vfs_stat_fsp(fsp);
6955 if (!NT_STATUS_IS_OK(status)) {
6959 status = can_rename(conn, fsp, attrs);
6961 if (!NT_STATUS_IS_OK(status)) {
6962 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6963 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6964 smb_fname_str_dbg(smb_fname_dst)));
6965 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6966 status = NT_STATUS_ACCESS_DENIED;
6970 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6971 status = NT_STATUS_ACCESS_DENIED;
6975 /* Do we have rights to move into the destination ? */
6976 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6977 /* We're moving a directory. */
6978 access_mask = SEC_DIR_ADD_SUBDIR;
6980 status = check_parent_access(conn,
6983 if (!NT_STATUS_IS_OK(status)) {
6984 DBG_INFO("check_parent_access on "
6985 "dst %s returned %s\n",
6986 smb_fname_str_dbg(smb_fname_dst),
6991 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6994 * We have the file open ourselves, so not being able to get the
6995 * corresponding share mode lock is a fatal error.
6998 SMB_ASSERT(lck != NULL);
7000 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
7001 uint32_t create_options = fsp->fh->private_options;
7003 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7004 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7005 smb_fname_str_dbg(smb_fname_dst)));
7007 if (!fsp->is_directory &&
7008 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7009 (lp_map_archive(SNUM(conn)) ||
7010 lp_store_dos_attributes(SNUM(conn)))) {
7011 /* We must set the archive bit on the newly
7013 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7014 uint32_t old_dosmode = dos_mode(conn,
7016 file_set_dosmode(conn,
7018 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7024 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
7027 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7031 * A rename acts as a new file create w.r.t. allowing an initial delete
7032 * on close, probably because in Windows there is a new handle to the
7033 * new file. If initial delete on close was requested but not
7034 * originally set, we need to set it here. This is probably not 100% correct,
7035 * but will work for the CIFSFS client which in non-posix mode
7036 * depends on these semantics. JRA.
7039 if (create_options & FILE_DELETE_ON_CLOSE) {
7040 status = can_set_delete_on_close(fsp, 0);
7042 if (NT_STATUS_IS_OK(status)) {
7043 /* Note that here we set the *initial* delete on close flag,
7044 * not the regular one. The magic gets handled in close. */
7045 fsp->initial_delete_on_close = True;
7049 status = NT_STATUS_OK;
7055 if (errno == ENOTDIR || errno == EISDIR) {
7056 status = NT_STATUS_OBJECT_NAME_COLLISION;
7058 status = map_nt_error_from_unix(errno);
7061 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7062 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7063 smb_fname_str_dbg(smb_fname_dst)));
7066 TALLOC_FREE(smb_fname_dst);
7071 /****************************************************************************
7072 The guts of the rename command, split out so it may be called by the NT SMB
7074 ****************************************************************************/
7076 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7077 connection_struct *conn,
7078 struct smb_request *req,
7079 struct smb_filename *smb_fname_src,
7080 struct smb_filename *smb_fname_dst,
7082 bool replace_if_exists,
7085 uint32_t access_mask)
7087 char *fname_src_dir = NULL;
7088 struct smb_filename *smb_fname_src_dir = NULL;
7089 char *fname_src_mask = NULL;
7091 NTSTATUS status = NT_STATUS_OK;
7092 struct smb_Dir *dir_hnd = NULL;
7093 const char *dname = NULL;
7094 char *talloced = NULL;
7096 int create_options = 0;
7097 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7101 * Split the old name into directory and last component
7102 * strings. Note that unix_convert may have stripped off a
7103 * leading ./ from both name and newname if the rename is
7104 * at the root of the share. We need to make sure either both
7105 * name and newname contain a / character or neither of them do
7106 * as this is checked in resolve_wildcards().
7109 /* Split up the directory from the filename/mask. */
7110 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7111 &fname_src_dir, &fname_src_mask);
7112 if (!NT_STATUS_IS_OK(status)) {
7113 status = NT_STATUS_NO_MEMORY;
7118 * We should only check the mangled cache
7119 * here if unix_convert failed. This means
7120 * that the path in 'mask' doesn't exist
7121 * on the file system and so we need to look
7122 * for a possible mangle. This patch from
7123 * Tine Smukavec <valentin.smukavec@hermes.si>.
7126 if (!VALID_STAT(smb_fname_src->st) &&
7127 mangle_is_mangled(fname_src_mask, conn->params)) {
7128 char *new_mask = NULL;
7129 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7132 TALLOC_FREE(fname_src_mask);
7133 fname_src_mask = new_mask;
7137 if (!src_has_wild) {
7141 * Only one file needs to be renamed. Append the mask back
7142 * onto the directory.
7144 TALLOC_FREE(smb_fname_src->base_name);
7145 if (ISDOT(fname_src_dir)) {
7146 /* Ensure we use canonical names on open. */
7147 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7151 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7156 if (!smb_fname_src->base_name) {
7157 status = NT_STATUS_NO_MEMORY;
7161 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7162 "case_preserve = %d, short case preserve = %d, "
7163 "directory = %s, newname = %s, "
7164 "last_component_dest = %s\n",
7165 conn->case_sensitive, conn->case_preserve,
7166 conn->short_case_preserve,
7167 smb_fname_str_dbg(smb_fname_src),
7168 smb_fname_str_dbg(smb_fname_dst),
7169 smb_fname_dst->original_lcomp));
7171 /* The dest name still may have wildcards. */
7172 if (dest_has_wild) {
7173 char *fname_dst_mod = NULL;
7174 if (!resolve_wildcards(smb_fname_dst,
7175 smb_fname_src->base_name,
7176 smb_fname_dst->base_name,
7178 DEBUG(6, ("rename_internals: resolve_wildcards "
7180 smb_fname_src->base_name,
7181 smb_fname_dst->base_name));
7182 status = NT_STATUS_NO_MEMORY;
7185 TALLOC_FREE(smb_fname_dst->base_name);
7186 smb_fname_dst->base_name = fname_dst_mod;
7189 ZERO_STRUCT(smb_fname_src->st);
7190 if (posix_pathnames) {
7191 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7193 rc = SMB_VFS_STAT(conn, smb_fname_src);
7196 status = map_nt_error_from_unix_common(errno);
7200 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7201 create_options |= FILE_DIRECTORY_FILE;
7204 status = SMB_VFS_CREATE_FILE(
7207 0, /* root_dir_fid */
7208 smb_fname_src, /* fname */
7209 access_mask, /* access_mask */
7210 (FILE_SHARE_READ | /* share_access */
7212 FILE_OPEN, /* create_disposition*/
7213 create_options, /* create_options */
7214 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7215 0, /* oplock_request */
7217 0, /* allocation_size */
7218 0, /* private_flags */
7223 NULL, NULL); /* create context */
7225 if (!NT_STATUS_IS_OK(status)) {
7226 DEBUG(3, ("Could not open rename source %s: %s\n",
7227 smb_fname_str_dbg(smb_fname_src),
7228 nt_errstr(status)));
7232 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7233 attrs, replace_if_exists);
7235 close_file(req, fsp, NORMAL_CLOSE);
7237 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7238 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7239 smb_fname_str_dbg(smb_fname_dst)));
7245 * Wildcards - process each file that matches.
7247 if (strequal(fname_src_mask, "????????.???")) {
7248 TALLOC_FREE(fname_src_mask);
7249 fname_src_mask = talloc_strdup(ctx, "*");
7250 if (!fname_src_mask) {
7251 status = NT_STATUS_NO_MEMORY;
7256 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7260 smb_fname_src->flags);
7261 if (smb_fname_src_dir == NULL) {
7262 status = NT_STATUS_NO_MEMORY;
7266 status = check_name(conn, smb_fname_src_dir);
7267 if (!NT_STATUS_IS_OK(status)) {
7271 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7273 if (dir_hnd == NULL) {
7274 status = map_nt_error_from_unix(errno);
7278 status = NT_STATUS_NO_SUCH_FILE;
7280 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7281 * - gentest fix. JRA
7284 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7286 files_struct *fsp = NULL;
7287 char *destname = NULL;
7288 bool sysdir_entry = False;
7290 /* Quick check for "." and ".." */
7291 if (ISDOT(dname) || ISDOTDOT(dname)) {
7292 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7293 sysdir_entry = True;
7295 TALLOC_FREE(talloced);
7300 if (!is_visible_file(conn, fname_src_dir, dname,
7301 &smb_fname_src->st, false)) {
7302 TALLOC_FREE(talloced);
7306 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7307 TALLOC_FREE(talloced);
7312 status = NT_STATUS_OBJECT_NAME_INVALID;
7316 TALLOC_FREE(smb_fname_src->base_name);
7317 if (ISDOT(fname_src_dir)) {
7318 /* Ensure we use canonical names on open. */
7319 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7323 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7328 if (!smb_fname_src->base_name) {
7329 status = NT_STATUS_NO_MEMORY;
7333 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7334 smb_fname_dst->base_name,
7336 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7337 smb_fname_src->base_name, destname));
7338 TALLOC_FREE(talloced);
7342 status = NT_STATUS_NO_MEMORY;
7346 TALLOC_FREE(smb_fname_dst->base_name);
7347 smb_fname_dst->base_name = destname;
7349 ZERO_STRUCT(smb_fname_src->st);
7350 if (posix_pathnames) {
7351 SMB_VFS_LSTAT(conn, smb_fname_src);
7353 SMB_VFS_STAT(conn, smb_fname_src);
7358 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7359 create_options |= FILE_DIRECTORY_FILE;
7362 status = SMB_VFS_CREATE_FILE(
7365 0, /* root_dir_fid */
7366 smb_fname_src, /* fname */
7367 access_mask, /* access_mask */
7368 (FILE_SHARE_READ | /* share_access */
7370 FILE_OPEN, /* create_disposition*/
7371 create_options, /* create_options */
7372 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7373 0, /* oplock_request */
7375 0, /* allocation_size */
7376 0, /* private_flags */
7381 NULL, NULL); /* create context */
7383 if (!NT_STATUS_IS_OK(status)) {
7384 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7385 "returned %s rename %s -> %s\n",
7387 smb_fname_str_dbg(smb_fname_src),
7388 smb_fname_str_dbg(smb_fname_dst)));
7392 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7394 if (!smb_fname_dst->original_lcomp) {
7395 status = NT_STATUS_NO_MEMORY;
7399 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7400 attrs, replace_if_exists);
7402 close_file(req, fsp, NORMAL_CLOSE);
7404 if (!NT_STATUS_IS_OK(status)) {
7405 DEBUG(3, ("rename_internals_fsp returned %s for "
7406 "rename %s -> %s\n", nt_errstr(status),
7407 smb_fname_str_dbg(smb_fname_src),
7408 smb_fname_str_dbg(smb_fname_dst)));
7414 DEBUG(3,("rename_internals: doing rename on %s -> "
7415 "%s\n", smb_fname_str_dbg(smb_fname_src),
7416 smb_fname_str_dbg(smb_fname_src)));
7417 TALLOC_FREE(talloced);
7419 TALLOC_FREE(dir_hnd);
7421 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7422 status = map_nt_error_from_unix(errno);
7426 TALLOC_FREE(talloced);
7427 TALLOC_FREE(smb_fname_src_dir);
7428 TALLOC_FREE(fname_src_dir);
7429 TALLOC_FREE(fname_src_mask);
7433 /****************************************************************************
7435 ****************************************************************************/
7437 void reply_mv(struct smb_request *req)
7439 connection_struct *conn = req->conn;
7441 char *newname = NULL;
7445 bool src_has_wcard = False;
7446 bool dest_has_wcard = False;
7447 TALLOC_CTX *ctx = talloc_tos();
7448 struct smb_filename *smb_fname_src = NULL;
7449 struct smb_filename *smb_fname_dst = NULL;
7450 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7451 (req->posix_pathnames ?
7452 UCF_UNIX_NAME_LOOKUP :
7453 UCF_COND_ALLOW_WCARD_LCOMP);
7454 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7456 (req->posix_pathnames ?
7458 UCF_COND_ALLOW_WCARD_LCOMP);
7459 bool stream_rename = false;
7461 START_PROFILE(SMBmv);
7464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7468 attrs = SVAL(req->vwv+0, 0);
7470 p = (const char *)req->buf + 1;
7471 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7472 &status, &src_has_wcard);
7473 if (!NT_STATUS_IS_OK(status)) {
7474 reply_nterror(req, status);
7478 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7479 &status, &dest_has_wcard);
7480 if (!NT_STATUS_IS_OK(status)) {
7481 reply_nterror(req, status);
7485 if (!req->posix_pathnames) {
7486 /* The newname must begin with a ':' if the
7487 name contains a ':'. */
7488 if (strchr_m(name, ':')) {
7489 if (newname[0] != ':') {
7490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7493 stream_rename = true;
7497 status = filename_convert(ctx,
7505 if (!NT_STATUS_IS_OK(status)) {
7506 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7507 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7508 ERRSRV, ERRbadpath);
7511 reply_nterror(req, status);
7515 status = filename_convert(ctx,
7523 if (!NT_STATUS_IS_OK(status)) {
7524 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7525 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7526 ERRSRV, ERRbadpath);
7529 reply_nterror(req, status);
7533 if (stream_rename) {
7534 /* smb_fname_dst->base_name must be the same as
7535 smb_fname_src->base_name. */
7536 TALLOC_FREE(smb_fname_dst->base_name);
7537 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7538 smb_fname_src->base_name);
7539 if (!smb_fname_dst->base_name) {
7540 reply_nterror(req, NT_STATUS_NO_MEMORY);
7545 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7546 smb_fname_str_dbg(smb_fname_dst)));
7548 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7549 attrs, False, src_has_wcard, dest_has_wcard,
7551 if (!NT_STATUS_IS_OK(status)) {
7552 if (open_was_deferred(req->xconn, req->mid)) {
7553 /* We have re-scheduled this call. */
7556 reply_nterror(req, status);
7560 reply_outbuf(req, 0, 0);
7562 TALLOC_FREE(smb_fname_src);
7563 TALLOC_FREE(smb_fname_dst);
7568 /*******************************************************************
7569 Copy a file as part of a reply_copy.
7570 ******************************************************************/
7573 * TODO: check error codes on all callers
7576 NTSTATUS copy_file(TALLOC_CTX *ctx,
7577 connection_struct *conn,
7578 struct smb_filename *smb_fname_src,
7579 struct smb_filename *smb_fname_dst,
7582 bool target_is_directory)
7584 struct smb_filename *smb_fname_dst_tmp = NULL;
7586 files_struct *fsp1,*fsp2;
7588 uint32_t new_create_disposition;
7592 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7593 if (smb_fname_dst_tmp == NULL) {
7594 return NT_STATUS_NO_MEMORY;
7598 * If the target is a directory, extract the last component from the
7599 * src filename and append it to the dst filename
7601 if (target_is_directory) {
7604 /* dest/target can't be a stream if it's a directory. */
7605 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7607 p = strrchr_m(smb_fname_src->base_name,'/');
7611 p = smb_fname_src->base_name;
7613 smb_fname_dst_tmp->base_name =
7614 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7616 if (!smb_fname_dst_tmp->base_name) {
7617 status = NT_STATUS_NO_MEMORY;
7622 status = vfs_file_exist(conn, smb_fname_src);
7623 if (!NT_STATUS_IS_OK(status)) {
7627 if (!target_is_directory && count) {
7628 new_create_disposition = FILE_OPEN;
7630 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7633 &new_create_disposition,
7636 status = NT_STATUS_INVALID_PARAMETER;
7641 /* Open the src file for reading. */
7642 status = SMB_VFS_CREATE_FILE(
7645 0, /* root_dir_fid */
7646 smb_fname_src, /* fname */
7647 FILE_GENERIC_READ, /* access_mask */
7648 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7649 FILE_OPEN, /* create_disposition*/
7650 0, /* create_options */
7651 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7652 INTERNAL_OPEN_ONLY, /* oplock_request */
7654 0, /* allocation_size */
7655 0, /* private_flags */
7660 NULL, NULL); /* create context */
7662 if (!NT_STATUS_IS_OK(status)) {
7666 dosattrs = dos_mode(conn, smb_fname_src);
7668 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7669 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7672 /* Open the dst file for writing. */
7673 status = SMB_VFS_CREATE_FILE(
7676 0, /* root_dir_fid */
7677 smb_fname_dst, /* fname */
7678 FILE_GENERIC_WRITE, /* access_mask */
7679 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7680 new_create_disposition, /* create_disposition*/
7681 0, /* create_options */
7682 dosattrs, /* file_attributes */
7683 INTERNAL_OPEN_ONLY, /* oplock_request */
7685 0, /* allocation_size */
7686 0, /* private_flags */
7691 NULL, NULL); /* create context */
7693 if (!NT_STATUS_IS_OK(status)) {
7694 close_file(NULL, fsp1, ERROR_CLOSE);
7698 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7699 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7701 DEBUG(0, ("error - vfs lseek returned error %s\n",
7703 status = map_nt_error_from_unix(errno);
7704 close_file(NULL, fsp1, ERROR_CLOSE);
7705 close_file(NULL, fsp2, ERROR_CLOSE);
7710 /* Do the actual copy. */
7711 if (smb_fname_src->st.st_ex_size) {
7712 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7717 close_file(NULL, fsp1, NORMAL_CLOSE);
7719 /* Ensure the modtime is set correctly on the destination file. */
7720 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7723 * As we are opening fsp1 read-only we only expect
7724 * an error on close on fsp2 if we are out of space.
7725 * Thus we don't look at the error return from the
7728 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7730 if (!NT_STATUS_IS_OK(status)) {
7734 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7735 status = NT_STATUS_DISK_FULL;
7739 status = NT_STATUS_OK;
7742 TALLOC_FREE(smb_fname_dst_tmp);
7746 /****************************************************************************
7747 Reply to a file copy.
7748 ****************************************************************************/
7750 void reply_copy(struct smb_request *req)
7752 connection_struct *conn = req->conn;
7753 struct smb_filename *smb_fname_src = NULL;
7754 struct smb_filename *smb_fname_src_dir = NULL;
7755 struct smb_filename *smb_fname_dst = NULL;
7756 char *fname_src = NULL;
7757 char *fname_dst = NULL;
7758 char *fname_src_mask = NULL;
7759 char *fname_src_dir = NULL;
7762 int error = ERRnoaccess;
7766 bool target_is_directory=False;
7767 bool source_has_wild = False;
7768 bool dest_has_wild = False;
7770 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7771 ucf_flags_from_smb_request(req);
7772 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7773 ucf_flags_from_smb_request(req);
7774 TALLOC_CTX *ctx = talloc_tos();
7776 START_PROFILE(SMBcopy);
7779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7783 tid2 = SVAL(req->vwv+0, 0);
7784 ofun = SVAL(req->vwv+1, 0);
7785 flags = SVAL(req->vwv+2, 0);
7787 p = (const char *)req->buf;
7788 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7789 &status, &source_has_wild);
7790 if (!NT_STATUS_IS_OK(status)) {
7791 reply_nterror(req, status);
7794 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7795 &status, &dest_has_wild);
7796 if (!NT_STATUS_IS_OK(status)) {
7797 reply_nterror(req, status);
7801 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7803 if (tid2 != conn->cnum) {
7804 /* can't currently handle inter share copies XXXX */
7805 DEBUG(3,("Rejecting inter-share copy\n"));
7806 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7810 status = filename_convert(ctx, conn,
7816 if (!NT_STATUS_IS_OK(status)) {
7817 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7818 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7819 ERRSRV, ERRbadpath);
7822 reply_nterror(req, status);
7826 status = filename_convert(ctx, conn,
7832 if (!NT_STATUS_IS_OK(status)) {
7833 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7834 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7835 ERRSRV, ERRbadpath);
7838 reply_nterror(req, status);
7842 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7844 if ((flags&1) && target_is_directory) {
7845 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7849 if ((flags&2) && !target_is_directory) {
7850 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7854 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7855 /* wants a tree copy! XXXX */
7856 DEBUG(3,("Rejecting tree copy\n"));
7857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7861 /* Split up the directory from the filename/mask. */
7862 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7863 &fname_src_dir, &fname_src_mask);
7864 if (!NT_STATUS_IS_OK(status)) {
7865 reply_nterror(req, NT_STATUS_NO_MEMORY);
7870 * We should only check the mangled cache
7871 * here if unix_convert failed. This means
7872 * that the path in 'mask' doesn't exist
7873 * on the file system and so we need to look
7874 * for a possible mangle. This patch from
7875 * Tine Smukavec <valentin.smukavec@hermes.si>.
7877 if (!VALID_STAT(smb_fname_src->st) &&
7878 mangle_is_mangled(fname_src_mask, conn->params)) {
7879 char *new_mask = NULL;
7880 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7881 &new_mask, conn->params);
7883 /* Use demangled name if one was successfully found. */
7885 TALLOC_FREE(fname_src_mask);
7886 fname_src_mask = new_mask;
7890 if (!source_has_wild) {
7893 * Only one file needs to be copied. Append the mask back onto
7896 TALLOC_FREE(smb_fname_src->base_name);
7897 if (ISDOT(fname_src_dir)) {
7898 /* Ensure we use canonical names on open. */
7899 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7903 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7908 if (!smb_fname_src->base_name) {
7909 reply_nterror(req, NT_STATUS_NO_MEMORY);
7913 if (dest_has_wild) {
7914 char *fname_dst_mod = NULL;
7915 if (!resolve_wildcards(smb_fname_dst,
7916 smb_fname_src->base_name,
7917 smb_fname_dst->base_name,
7919 reply_nterror(req, NT_STATUS_NO_MEMORY);
7922 TALLOC_FREE(smb_fname_dst->base_name);
7923 smb_fname_dst->base_name = fname_dst_mod;
7926 status = check_name(conn, smb_fname_src);
7927 if (!NT_STATUS_IS_OK(status)) {
7928 reply_nterror(req, status);
7932 status = check_name(conn, smb_fname_dst);
7933 if (!NT_STATUS_IS_OK(status)) {
7934 reply_nterror(req, status);
7938 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7939 ofun, count, target_is_directory);
7941 if(!NT_STATUS_IS_OK(status)) {
7942 reply_nterror(req, status);
7948 struct smb_Dir *dir_hnd = NULL;
7949 const char *dname = NULL;
7950 char *talloced = NULL;
7954 * There is a wildcard that requires us to actually read the
7955 * src dir and copy each file matching the mask to the dst.
7956 * Right now streams won't be copied, but this could
7957 * presumably be added with a nested loop for reach dir entry.
7959 SMB_ASSERT(!smb_fname_src->stream_name);
7960 SMB_ASSERT(!smb_fname_dst->stream_name);
7962 smb_fname_src->stream_name = NULL;
7963 smb_fname_dst->stream_name = NULL;
7965 if (strequal(fname_src_mask,"????????.???")) {
7966 TALLOC_FREE(fname_src_mask);
7967 fname_src_mask = talloc_strdup(ctx, "*");
7968 if (!fname_src_mask) {
7969 reply_nterror(req, NT_STATUS_NO_MEMORY);
7974 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7978 smb_fname_src->flags);
7979 if (smb_fname_src_dir == NULL) {
7980 reply_nterror(req, NT_STATUS_NO_MEMORY);
7984 status = check_name(conn, smb_fname_src_dir);
7985 if (!NT_STATUS_IS_OK(status)) {
7986 reply_nterror(req, status);
7990 dir_hnd = OpenDir(ctx,
7995 if (dir_hnd == NULL) {
7996 status = map_nt_error_from_unix(errno);
7997 reply_nterror(req, status);
8003 /* Iterate over the src dir copying each entry to the dst. */
8004 while ((dname = ReadDirName(dir_hnd, &offset,
8005 &smb_fname_src->st, &talloced))) {
8006 char *destname = NULL;
8008 if (ISDOT(dname) || ISDOTDOT(dname)) {
8009 TALLOC_FREE(talloced);
8013 if (!is_visible_file(conn, fname_src_dir, dname,
8014 &smb_fname_src->st, false)) {
8015 TALLOC_FREE(talloced);
8019 if(!mask_match(dname, fname_src_mask,
8020 conn->case_sensitive)) {
8021 TALLOC_FREE(talloced);
8025 error = ERRnoaccess;
8027 /* Get the src smb_fname struct setup. */
8028 TALLOC_FREE(smb_fname_src->base_name);
8029 if (ISDOT(fname_src_dir)) {
8030 /* Ensure we use canonical names on open. */
8031 smb_fname_src->base_name =
8032 talloc_asprintf(smb_fname_src, "%s",
8035 smb_fname_src->base_name =
8036 talloc_asprintf(smb_fname_src, "%s/%s",
8037 fname_src_dir, dname);
8040 if (!smb_fname_src->base_name) {
8041 TALLOC_FREE(dir_hnd);
8042 TALLOC_FREE(talloced);
8043 reply_nterror(req, NT_STATUS_NO_MEMORY);
8047 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8048 smb_fname_dst->base_name,
8050 TALLOC_FREE(talloced);
8054 TALLOC_FREE(dir_hnd);
8055 TALLOC_FREE(talloced);
8056 reply_nterror(req, NT_STATUS_NO_MEMORY);
8060 TALLOC_FREE(smb_fname_dst->base_name);
8061 smb_fname_dst->base_name = destname;
8063 status = check_name(conn, smb_fname_src);
8064 if (!NT_STATUS_IS_OK(status)) {
8065 TALLOC_FREE(dir_hnd);
8066 TALLOC_FREE(talloced);
8067 reply_nterror(req, status);
8071 status = check_name(conn, smb_fname_dst);
8072 if (!NT_STATUS_IS_OK(status)) {
8073 TALLOC_FREE(dir_hnd);
8074 TALLOC_FREE(talloced);
8075 reply_nterror(req, status);
8079 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8080 smb_fname_src->base_name,
8081 smb_fname_dst->base_name));
8083 status = copy_file(ctx, conn, smb_fname_src,
8084 smb_fname_dst, ofun, count,
8085 target_is_directory);
8086 if (NT_STATUS_IS_OK(status)) {
8090 TALLOC_FREE(talloced);
8092 TALLOC_FREE(dir_hnd);
8096 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8100 reply_outbuf(req, 1, 0);
8101 SSVAL(req->outbuf,smb_vwv0,count);
8103 TALLOC_FREE(smb_fname_src);
8104 TALLOC_FREE(smb_fname_src_dir);
8105 TALLOC_FREE(smb_fname_dst);
8106 TALLOC_FREE(fname_src);
8107 TALLOC_FREE(fname_dst);
8108 TALLOC_FREE(fname_src_mask);
8109 TALLOC_FREE(fname_src_dir);
8111 END_PROFILE(SMBcopy);
8116 #define DBGC_CLASS DBGC_LOCKING
8118 /****************************************************************************
8119 Get a lock pid, dealing with large count requests.
8120 ****************************************************************************/
8122 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8123 bool large_file_format)
8125 if(!large_file_format)
8126 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8128 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8131 /****************************************************************************
8132 Get a lock count, dealing with large count requests.
8133 ****************************************************************************/
8135 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8136 bool large_file_format)
8140 if(!large_file_format) {
8141 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8144 * No BVAL, this is reversed!
8146 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8147 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8153 /****************************************************************************
8154 Get a lock offset, dealing with large offset requests.
8155 ****************************************************************************/
8157 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8158 bool large_file_format)
8160 uint64_t offset = 0;
8162 if(!large_file_format) {
8163 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8166 * No BVAL, this is reversed!
8168 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8169 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8175 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8177 uint16_t num_ulocks,
8178 struct smbd_lock_element *ulocks,
8179 enum brl_flavour lock_flav)
8181 struct share_mode_lock *lck;
8182 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8185 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8187 for(i = 0; i < num_ulocks; i++) {
8188 struct smbd_lock_element *e = &ulocks[i];
8190 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
8191 "pid %"PRIu64", file %s\n",
8197 if (e->brltype != UNLOCK_LOCK) {
8198 /* this can only happen with SMB2 */
8199 status = NT_STATUS_INVALID_PARAMETER;
8210 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8211 nt_errstr(status)));
8213 if (!NT_STATUS_IS_OK(status)) {
8218 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8222 if (NT_STATUS_IS_OK(status) && (lck != NULL)) {
8223 lck->data->modified = true;
8230 /****************************************************************************
8231 Reply to a lockingX request.
8232 ****************************************************************************/
8234 static void reply_lockingx_done(struct tevent_req *subreq);
8236 void reply_lockingX(struct smb_request *req)
8238 connection_struct *conn = req->conn;
8240 unsigned char locktype;
8241 enum brl_type brltype;
8242 unsigned char oplocklevel;
8243 uint16_t num_ulocks;
8245 int32_t lock_timeout;
8247 const uint8_t *data;
8248 bool large_file_format;
8249 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8250 struct smbd_lock_element *locks = NULL;
8251 struct tevent_req *subreq = NULL;
8253 START_PROFILE(SMBlockingX);
8256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8257 END_PROFILE(SMBlockingX);
8261 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8262 locktype = CVAL(req->vwv+3, 0);
8263 oplocklevel = CVAL(req->vwv+3, 1);
8264 num_ulocks = SVAL(req->vwv+6, 0);
8265 num_locks = SVAL(req->vwv+7, 0);
8266 lock_timeout = IVAL(req->vwv+4, 0);
8267 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8269 if (!check_fsp(conn, req, fsp)) {
8270 END_PROFILE(SMBlockingX);
8276 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8277 /* we don't support these - and CANCEL_LOCK makes w2k
8278 and XP reboot so I don't really want to be
8279 compatible! (tridge) */
8280 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8281 END_PROFILE(SMBlockingX);
8285 /* Check if this is an oplock break on a file
8286 we have granted an oplock on.
8288 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8289 /* Client can insist on breaking to none. */
8290 bool break_to_none = (oplocklevel == 0);
8293 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8294 "for %s\n", (unsigned int)oplocklevel,
8295 fsp_fnum_dbg(fsp)));
8298 * Make sure we have granted an exclusive or batch oplock on
8302 if (fsp->oplock_type == 0) {
8304 /* The Samba4 nbench simulator doesn't understand
8305 the difference between break to level2 and break
8306 to none from level2 - it sends oplock break
8307 replies in both cases. Don't keep logging an error
8308 message here - just ignore it. JRA. */
8310 DEBUG(5,("reply_lockingX: Error : oplock break from "
8311 "client for %s (oplock=%d) and no "
8312 "oplock granted on this file (%s).\n",
8313 fsp_fnum_dbg(fsp), fsp->oplock_type,
8316 /* if this is a pure oplock break request then don't
8318 if (num_locks == 0 && num_ulocks == 0) {
8319 END_PROFILE(SMBlockingX);
8323 END_PROFILE(SMBlockingX);
8324 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8328 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8330 result = remove_oplock(fsp);
8332 result = downgrade_oplock(fsp);
8336 DEBUG(0, ("reply_lockingX: error in removing "
8337 "oplock on file %s\n", fsp_str_dbg(fsp)));
8338 /* Hmmm. Is this panic justified? */
8339 smb_panic("internal tdb error");
8342 /* if this is a pure oplock break request then don't send a
8344 if (num_locks == 0 && num_ulocks == 0) {
8345 /* Sanity check - ensure a pure oplock break is not a
8347 if (CVAL(req->vwv+0, 0) != 0xff) {
8348 DEBUG(0,("reply_lockingX: Error : pure oplock "
8349 "break is a chained %d request !\n",
8350 (unsigned int)CVAL(req->vwv+0, 0)));
8352 END_PROFILE(SMBlockingX);
8358 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8359 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8360 END_PROFILE(SMBlockingX);
8364 if (num_ulocks != 0) {
8365 struct smbd_lock_element *ulocks = NULL;
8368 ulocks = talloc_array(
8369 req, struct smbd_lock_element, num_ulocks);
8370 if (ulocks == NULL) {
8371 reply_nterror(req, NT_STATUS_NO_MEMORY);
8372 END_PROFILE(SMBlockingX);
8377 * Data now points at the beginning of the list of
8378 * smb_unlkrng structs
8380 for (i = 0; i < num_ulocks; i++) {
8381 ulocks[i].smblctx = get_lock_pid(
8382 data, i, large_file_format);
8383 ulocks[i].count = get_lock_count(
8384 data, i, large_file_format);
8385 ulocks[i].offset = get_lock_offset(
8386 data, i, large_file_format);
8387 ulocks[i].brltype = UNLOCK_LOCK;
8391 * Unlock cancels pending locks
8394 ok = smbd_smb1_brl_finish_by_lock(
8401 reply_outbuf(req, 2, 0);
8402 SSVAL(req->outbuf, smb_vwv0, 0xff);
8403 SSVAL(req->outbuf, smb_vwv1, 0);
8404 END_PROFILE(SMBlockingX);
8408 status = smbd_do_unlocking(
8409 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
8410 TALLOC_FREE(ulocks);
8411 if (!NT_STATUS_IS_OK(status)) {
8412 END_PROFILE(SMBlockingX);
8413 reply_nterror(req, status);
8418 /* Now do any requested locks */
8419 data += ((large_file_format ? 20 : 10)*num_ulocks);
8421 /* Data now points at the beginning of the list
8422 of smb_lkrng structs */
8424 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8425 brltype = READ_LOCK;
8427 brltype = WRITE_LOCK;
8430 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8431 if (locks == NULL) {
8432 reply_nterror(req, NT_STATUS_NO_MEMORY);
8433 END_PROFILE(SMBlockingX);
8437 for (i = 0; i < num_locks; i++) {
8438 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8439 locks[i].count = get_lock_count(data, i, large_file_format);
8440 locks[i].offset = get_lock_offset(data, i, large_file_format);
8441 locks[i].brltype = brltype;
8444 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8448 if (num_locks == 0) {
8449 /* See smbtorture3 lock11 test */
8450 reply_outbuf(req, 2, 0);
8451 /* andx chain ends */
8452 SSVAL(req->outbuf, smb_vwv0, 0xff);
8453 SSVAL(req->outbuf, smb_vwv1, 0);
8454 END_PROFILE(SMBlockingX);
8458 ok = smbd_smb1_brl_finish_by_lock(
8462 locks[0], /* Windows only cancels the first lock */
8463 NT_STATUS_FILE_LOCK_CONFLICT);
8466 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
8467 END_PROFILE(SMBlockingX);
8471 reply_outbuf(req, 2, 0);
8472 SSVAL(req->outbuf, smb_vwv0, 0xff);
8473 SSVAL(req->outbuf, smb_vwv1, 0);
8474 END_PROFILE(SMBlockingX);
8478 subreq = smbd_smb1_do_locks_send(
8488 if (subreq == NULL) {
8489 reply_nterror(req, NT_STATUS_NO_MEMORY);
8490 END_PROFILE(SMBlockingX);
8493 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
8494 END_PROFILE(SMBlockingX);
8497 static void reply_lockingx_done(struct tevent_req *subreq)
8499 struct smb_request *req = NULL;
8503 START_PROFILE(SMBlockingX);
8505 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
8508 status = smbd_smb1_do_locks_recv(subreq);
8509 TALLOC_FREE(subreq);
8511 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
8513 if (NT_STATUS_IS_OK(status)) {
8514 reply_outbuf(req, 2, 0);
8515 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8516 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8518 reply_nterror(req, status);
8521 ok = srv_send_smb(req->xconn,
8522 (char *)req->outbuf,
8525 IS_CONN_ENCRYPTED(req->conn),
8528 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
8531 END_PROFILE(SMBlockingX);
8535 #define DBGC_CLASS DBGC_ALL
8537 /****************************************************************************
8538 Reply to a SMBreadbmpx (read block multiplex) request.
8539 Always reply with an error, if someone has a platform really needs this,
8540 please contact vl@samba.org
8541 ****************************************************************************/
8543 void reply_readbmpx(struct smb_request *req)
8545 START_PROFILE(SMBreadBmpx);
8546 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8547 END_PROFILE(SMBreadBmpx);
8551 /****************************************************************************
8552 Reply to a SMBreadbs (read block multiplex secondary) request.
8553 Always reply with an error, if someone has a platform really needs this,
8554 please contact vl@samba.org
8555 ****************************************************************************/
8557 void reply_readbs(struct smb_request *req)
8559 START_PROFILE(SMBreadBs);
8560 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8561 END_PROFILE(SMBreadBs);
8565 /****************************************************************************
8566 Reply to a SMBsetattrE.
8567 ****************************************************************************/
8569 void reply_setattrE(struct smb_request *req)
8571 connection_struct *conn = req->conn;
8572 struct smb_file_time ft;
8576 START_PROFILE(SMBsetattrE);
8580 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8584 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8586 if(!fsp || (fsp->conn != conn)) {
8587 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8592 * Convert the DOS times into unix times.
8595 ft.atime = convert_time_t_to_timespec(
8596 srv_make_unix_date2(req->vwv+3));
8597 ft.mtime = convert_time_t_to_timespec(
8598 srv_make_unix_date2(req->vwv+5));
8599 ft.create_time = convert_time_t_to_timespec(
8600 srv_make_unix_date2(req->vwv+1));
8602 reply_outbuf(req, 0, 0);
8605 * Patch from Ray Frush <frush@engr.colostate.edu>
8606 * Sometimes times are sent as zero - ignore them.
8609 /* Ensure we have a valid stat struct for the source. */
8610 status = vfs_stat_fsp(fsp);
8611 if (!NT_STATUS_IS_OK(status)) {
8612 reply_nterror(req, status);
8616 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8617 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8621 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8622 if (!NT_STATUS_IS_OK(status)) {
8623 reply_nterror(req, status);
8627 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8630 (unsigned int)ft.atime.tv_sec,
8631 (unsigned int)ft.mtime.tv_sec,
8632 (unsigned int)ft.create_time.tv_sec
8635 END_PROFILE(SMBsetattrE);
8640 /* Back from the dead for OS/2..... JRA. */
8642 /****************************************************************************
8643 Reply to a SMBwritebmpx (write block multiplex primary) request.
8644 Always reply with an error, if someone has a platform really needs this,
8645 please contact vl@samba.org
8646 ****************************************************************************/
8648 void reply_writebmpx(struct smb_request *req)
8650 START_PROFILE(SMBwriteBmpx);
8651 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8652 END_PROFILE(SMBwriteBmpx);
8656 /****************************************************************************
8657 Reply to a SMBwritebs (write block multiplex secondary) request.
8658 Always reply with an error, if someone has a platform really needs this,
8659 please contact vl@samba.org
8660 ****************************************************************************/
8662 void reply_writebs(struct smb_request *req)
8664 START_PROFILE(SMBwriteBs);
8665 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8666 END_PROFILE(SMBwriteBs);
8670 /****************************************************************************
8671 Reply to a SMBgetattrE.
8672 ****************************************************************************/
8674 void reply_getattrE(struct smb_request *req)
8676 connection_struct *conn = req->conn;
8679 struct timespec create_ts;
8681 START_PROFILE(SMBgetattrE);
8684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8685 END_PROFILE(SMBgetattrE);
8689 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8691 if(!fsp || (fsp->conn != conn)) {
8692 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8693 END_PROFILE(SMBgetattrE);
8697 /* Do an fstat on this file */
8699 reply_nterror(req, map_nt_error_from_unix(errno));
8700 END_PROFILE(SMBgetattrE);
8704 mode = dos_mode(conn, fsp->fsp_name);
8707 * Convert the times into dos times. Set create
8708 * date to be last modify date as UNIX doesn't save
8712 reply_outbuf(req, 11, 0);
8714 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8715 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8716 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8717 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8718 /* Should we check pending modtime here ? JRA */
8719 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8720 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8722 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8723 SIVAL(req->outbuf, smb_vwv6, 0);
8724 SIVAL(req->outbuf, smb_vwv8, 0);
8726 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8727 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8728 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8730 SSVAL(req->outbuf,smb_vwv10, mode);
8732 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8734 END_PROFILE(SMBgetattrE);