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);
1804 if (smbreq_bufrem(req, p) < 3) {
1805 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1810 status_len = SVAL(p, 0);
1813 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1815 if (status_len == 0) {
1816 struct smb_filename *smb_dname = NULL;
1817 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1818 ucf_flags_from_smb_request(req);
1819 nt_status = filename_convert(ctx, conn,
1823 &mask_contains_wcard,
1825 if (!NT_STATUS_IS_OK(nt_status)) {
1826 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1827 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1828 ERRSRV, ERRbadpath);
1831 reply_nterror(req, nt_status);
1835 directory = smb_fname->base_name;
1837 p = strrchr_m(directory,'/');
1838 if ((p != NULL) && (*directory != '/')) {
1839 mask = talloc_strdup(ctx, p + 1);
1840 directory = talloc_strndup(ctx, directory,
1841 PTR_DIFF(p, directory));
1843 mask = talloc_strdup(ctx, directory);
1844 directory = talloc_strdup(ctx,".");
1848 reply_nterror(req, NT_STATUS_NO_MEMORY);
1852 memset((char *)status,'\0',21);
1853 SCVAL(status,0,(dirtype & 0x1F));
1855 smb_dname = synthetic_smb_fname(talloc_tos(),
1860 if (smb_dname == NULL) {
1861 reply_nterror(req, NT_STATUS_NO_MEMORY);
1865 nt_status = dptr_create(conn,
1873 mask_contains_wcard,
1877 TALLOC_FREE(smb_dname);
1879 if (!NT_STATUS_IS_OK(nt_status)) {
1880 reply_nterror(req, nt_status);
1883 dptr_num = dptr_dnum(dirptr);
1886 const char *dirpath;
1888 if (smbreq_bufrem(req, p) < 21) {
1889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1893 memcpy(status,p,21);
1894 status_dirtype = CVAL(status,0) & 0x1F;
1895 if (status_dirtype != (dirtype & 0x1F)) {
1896 dirtype = status_dirtype;
1899 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1903 dirpath = dptr_path(sconn, dptr_num);
1904 directory = talloc_strdup(ctx, dirpath);
1906 reply_nterror(req, NT_STATUS_NO_MEMORY);
1910 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1915 * For a 'continue' search we have no string. So
1916 * check from the initial saved string.
1918 if (!req->posix_pathnames) {
1919 mask_contains_wcard = ms_has_wild(mask);
1921 dirtype = dptr_attr(sconn, dptr_num);
1924 DEBUG(4,("dptr_num is %d\n",dptr_num));
1926 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1927 char buf[DIR_STRUCT_SIZE];
1928 memcpy(buf,status,21);
1929 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1930 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1931 reply_nterror(req, NT_STATUS_NO_MEMORY);
1934 dptr_fill(sconn, buf+12,dptr_num);
1935 if (dptr_zero(buf+12) && (status_len==0)) {
1940 if (message_push_blob(&req->outbuf,
1941 data_blob_const(buf, sizeof(buf)))
1943 reply_nterror(req, NT_STATUS_NO_MEMORY);
1948 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1949 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1951 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1953 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1954 directory,lp_dont_descend(ctx, SNUM(conn))));
1955 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1956 check_descend = True;
1959 for (i=numentries;(i<maxentries) && !finished;i++) {
1960 finished = !get_dir_entry(ctx,
1971 char buf[DIR_STRUCT_SIZE];
1972 memcpy(buf,status,21);
1973 if (!make_dir_struct(ctx,
1979 convert_timespec_to_time_t(date),
1980 !allow_long_path_components)) {
1981 reply_nterror(req, NT_STATUS_NO_MEMORY);
1984 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1987 if (message_push_blob(&req->outbuf,
1988 data_blob_const(buf, sizeof(buf)))
1990 reply_nterror(req, NT_STATUS_NO_MEMORY);
2000 /* If we were called as SMBffirst with smb_search_id == NULL
2001 and no entries were found then return error and close dirptr
2004 if (numentries == 0) {
2005 dptr_close(sconn, &dptr_num);
2006 } else if(expect_close && status_len == 0) {
2007 /* Close the dptr - we know it's gone */
2008 dptr_close(sconn, &dptr_num);
2011 /* If we were called as SMBfunique, then we can close the dirptr now ! */
2012 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2013 dptr_close(sconn, &dptr_num);
2016 if ((numentries == 0) && !mask_contains_wcard) {
2017 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2021 SSVAL(req->outbuf,smb_vwv0,numentries);
2022 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2023 SCVAL(smb_buf(req->outbuf),0,5);
2024 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2026 /* The replies here are never long name. */
2027 SSVAL(req->outbuf, smb_flg2,
2028 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2029 if (!allow_long_path_components) {
2030 SSVAL(req->outbuf, smb_flg2,
2031 SVAL(req->outbuf, smb_flg2)
2032 & (~FLAGS2_LONG_PATH_COMPONENTS));
2035 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2036 SSVAL(req->outbuf, smb_flg2,
2037 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2039 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2040 smb_fn_name(req->cmd),
2047 TALLOC_FREE(directory);
2049 TALLOC_FREE(smb_fname);
2050 END_PROFILE(SMBsearch);
2054 /****************************************************************************
2055 Reply to a fclose (stop directory search).
2056 ****************************************************************************/
2058 void reply_fclose(struct smb_request *req)
2066 bool path_contains_wcard = False;
2067 TALLOC_CTX *ctx = talloc_tos();
2068 struct smbd_server_connection *sconn = req->sconn;
2070 START_PROFILE(SMBfclose);
2072 if (req->posix_pathnames) {
2073 reply_unknown_new(req, req->cmd);
2074 END_PROFILE(SMBfclose);
2078 p = (const char *)req->buf + 1;
2079 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2080 &err, &path_contains_wcard);
2081 if (!NT_STATUS_IS_OK(err)) {
2082 reply_nterror(req, err);
2083 END_PROFILE(SMBfclose);
2087 status_len = SVAL(p,0);
2090 if (status_len == 0) {
2091 reply_force_doserror(req, ERRSRV, ERRsrverror);
2092 END_PROFILE(SMBfclose);
2096 memcpy(status,p,21);
2098 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2099 /* Close the dptr - we know it's gone */
2100 dptr_close(sconn, &dptr_num);
2103 reply_outbuf(req, 1, 0);
2104 SSVAL(req->outbuf,smb_vwv0,0);
2106 DEBUG(3,("search close\n"));
2108 END_PROFILE(SMBfclose);
2112 /****************************************************************************
2114 ****************************************************************************/
2116 void reply_open(struct smb_request *req)
2118 connection_struct *conn = req->conn;
2119 struct smb_filename *smb_fname = NULL;
2129 uint32_t access_mask;
2130 uint32_t share_mode;
2131 uint32_t create_disposition;
2132 uint32_t create_options = 0;
2133 uint32_t private_flags = 0;
2136 TALLOC_CTX *ctx = talloc_tos();
2138 START_PROFILE(SMBopen);
2141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2145 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2146 deny_mode = SVAL(req->vwv+0, 0);
2147 dos_attr = SVAL(req->vwv+1, 0);
2149 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2150 STR_TERMINATE, &status);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 reply_nterror(req, status);
2156 if (!map_open_params_to_ntcreate(fname, deny_mode,
2157 OPENX_FILE_EXISTS_OPEN, &access_mask,
2158 &share_mode, &create_disposition,
2159 &create_options, &private_flags)) {
2160 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2164 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2166 status = filename_convert(ctx,
2173 if (!NT_STATUS_IS_OK(status)) {
2174 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2175 reply_botherror(req,
2176 NT_STATUS_PATH_NOT_COVERED,
2177 ERRSRV, ERRbadpath);
2180 reply_nterror(req, status);
2184 status = SMB_VFS_CREATE_FILE(
2187 0, /* root_dir_fid */
2188 smb_fname, /* fname */
2189 access_mask, /* access_mask */
2190 share_mode, /* share_access */
2191 create_disposition, /* create_disposition*/
2192 create_options, /* create_options */
2193 dos_attr, /* file_attributes */
2194 oplock_request, /* oplock_request */
2196 0, /* allocation_size */
2202 NULL, NULL); /* create context */
2204 if (!NT_STATUS_IS_OK(status)) {
2205 if (open_was_deferred(req->xconn, req->mid)) {
2206 /* We have re-scheduled this call. */
2209 reply_openerror(req, status);
2213 /* Ensure we're pointing at the correct stat struct. */
2214 TALLOC_FREE(smb_fname);
2215 smb_fname = fsp->fsp_name;
2217 size = smb_fname->st.st_ex_size;
2218 fattr = dos_mode(conn, smb_fname);
2220 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2222 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2223 DEBUG(3,("attempt to open a directory %s\n",
2225 close_file(req, fsp, ERROR_CLOSE);
2226 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2227 ERRDOS, ERRnoaccess);
2231 reply_outbuf(req, 7, 0);
2232 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2233 SSVAL(req->outbuf,smb_vwv1,fattr);
2234 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2235 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2237 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2239 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2240 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2242 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2243 SCVAL(req->outbuf,smb_flg,
2244 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2247 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2248 SCVAL(req->outbuf,smb_flg,
2249 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2252 END_PROFILE(SMBopen);
2256 /****************************************************************************
2257 Reply to an open and X.
2258 ****************************************************************************/
2260 void reply_open_and_X(struct smb_request *req)
2262 connection_struct *conn = req->conn;
2263 struct smb_filename *smb_fname = NULL;
2265 uint16_t open_flags;
2268 /* Breakout the oplock request bits so we can set the
2269 reply bits separately. */
2270 int ex_oplock_request;
2271 int core_oplock_request;
2274 int smb_sattr = SVAL(req->vwv+4, 0);
2275 uint32_t smb_time = make_unix_date3(req->vwv+6);
2283 uint64_t allocation_size;
2284 ssize_t retval = -1;
2285 uint32_t access_mask;
2286 uint32_t share_mode;
2287 uint32_t create_disposition;
2288 uint32_t create_options = 0;
2289 uint32_t private_flags = 0;
2291 TALLOC_CTX *ctx = talloc_tos();
2293 START_PROFILE(SMBopenX);
2295 if (req->wct < 15) {
2296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2300 open_flags = SVAL(req->vwv+2, 0);
2301 deny_mode = SVAL(req->vwv+3, 0);
2302 smb_attr = SVAL(req->vwv+5, 0);
2303 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2304 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2305 oplock_request = ex_oplock_request | core_oplock_request;
2306 smb_ofun = SVAL(req->vwv+8, 0);
2307 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2309 /* If it's an IPC, pass off the pipe handler. */
2311 if (lp_nt_pipe_support()) {
2312 reply_open_pipe_and_X(conn, req);
2314 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2319 /* XXXX we need to handle passed times, sattr and flags */
2320 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2321 STR_TERMINATE, &status);
2322 if (!NT_STATUS_IS_OK(status)) {
2323 reply_nterror(req, status);
2327 if (!map_open_params_to_ntcreate(fname, deny_mode,
2329 &access_mask, &share_mode,
2330 &create_disposition,
2333 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2337 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2339 status = filename_convert(ctx,
2346 if (!NT_STATUS_IS_OK(status)) {
2347 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2348 reply_botherror(req,
2349 NT_STATUS_PATH_NOT_COVERED,
2350 ERRSRV, ERRbadpath);
2353 reply_nterror(req, status);
2357 status = SMB_VFS_CREATE_FILE(
2360 0, /* root_dir_fid */
2361 smb_fname, /* fname */
2362 access_mask, /* access_mask */
2363 share_mode, /* share_access */
2364 create_disposition, /* create_disposition*/
2365 create_options, /* create_options */
2366 smb_attr, /* file_attributes */
2367 oplock_request, /* oplock_request */
2369 0, /* allocation_size */
2374 &smb_action, /* pinfo */
2375 NULL, NULL); /* create context */
2377 if (!NT_STATUS_IS_OK(status)) {
2378 if (open_was_deferred(req->xconn, req->mid)) {
2379 /* We have re-scheduled this call. */
2382 reply_openerror(req, status);
2386 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2387 if the file is truncated or created. */
2388 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2389 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2390 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2391 close_file(req, fsp, ERROR_CLOSE);
2392 reply_nterror(req, NT_STATUS_DISK_FULL);
2395 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2397 close_file(req, fsp, ERROR_CLOSE);
2398 reply_nterror(req, NT_STATUS_DISK_FULL);
2401 status = vfs_stat_fsp(fsp);
2402 if (!NT_STATUS_IS_OK(status)) {
2403 close_file(req, fsp, ERROR_CLOSE);
2404 reply_nterror(req, status);
2409 fattr = dos_mode(conn, fsp->fsp_name);
2410 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2411 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2412 close_file(req, fsp, ERROR_CLOSE);
2413 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2417 /* If the caller set the extended oplock request bit
2418 and we granted one (by whatever means) - set the
2419 correct bit for extended oplock reply.
2422 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2423 smb_action |= EXTENDED_OPLOCK_GRANTED;
2426 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2427 smb_action |= EXTENDED_OPLOCK_GRANTED;
2430 /* If the caller set the core oplock request bit
2431 and we granted one (by whatever means) - set the
2432 correct bit for core oplock reply.
2435 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2436 reply_outbuf(req, 19, 0);
2438 reply_outbuf(req, 15, 0);
2441 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2442 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2444 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2445 SCVAL(req->outbuf, smb_flg,
2446 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2449 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2450 SCVAL(req->outbuf, smb_flg,
2451 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2454 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2455 SSVAL(req->outbuf,smb_vwv3,fattr);
2456 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2457 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2459 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2461 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2462 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2463 SSVAL(req->outbuf,smb_vwv11,smb_action);
2465 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2466 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2470 TALLOC_FREE(smb_fname);
2471 END_PROFILE(SMBopenX);
2475 /****************************************************************************
2476 Reply to a SMBulogoffX.
2477 ****************************************************************************/
2479 void reply_ulogoffX(struct smb_request *req)
2481 struct smbd_server_connection *sconn = req->sconn;
2482 struct user_struct *vuser;
2483 struct smbXsrv_session *session = NULL;
2486 START_PROFILE(SMBulogoffX);
2488 vuser = get_valid_user_struct(sconn, req->vuid);
2491 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2492 (unsigned long long)req->vuid));
2494 req->vuid = UID_FIELD_INVALID;
2495 reply_force_doserror(req, ERRSRV, ERRbaduid);
2496 END_PROFILE(SMBulogoffX);
2500 session = vuser->session;
2504 * TODO: cancel all outstanding requests on the session
2506 status = smbXsrv_session_logoff(session);
2507 if (!NT_STATUS_IS_OK(status)) {
2508 DEBUG(0, ("reply_ulogoff: "
2509 "smbXsrv_session_logoff() failed: %s\n",
2510 nt_errstr(status)));
2512 * If we hit this case, there is something completely
2513 * wrong, so we better disconnect the transport connection.
2515 END_PROFILE(SMBulogoffX);
2516 exit_server(__location__ ": smbXsrv_session_logoff failed");
2520 TALLOC_FREE(session);
2522 reply_outbuf(req, 2, 0);
2523 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2524 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2526 DEBUG(3, ("ulogoffX vuid=%llu\n",
2527 (unsigned long long)req->vuid));
2529 END_PROFILE(SMBulogoffX);
2530 req->vuid = UID_FIELD_INVALID;
2533 /****************************************************************************
2534 Reply to a mknew or a create.
2535 ****************************************************************************/
2537 void reply_mknew(struct smb_request *req)
2539 connection_struct *conn = req->conn;
2540 struct smb_filename *smb_fname = NULL;
2543 struct smb_file_time ft;
2545 int oplock_request = 0;
2547 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2548 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2549 uint32_t create_disposition;
2550 uint32_t create_options = 0;
2552 TALLOC_CTX *ctx = talloc_tos();
2554 START_PROFILE(SMBcreate);
2558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2562 fattr = SVAL(req->vwv+0, 0);
2563 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2565 if (req->cmd == SMBmknew) {
2566 /* We should fail if file exists. */
2567 create_disposition = FILE_CREATE;
2569 /* Create if file doesn't exist, truncate if it does. */
2570 create_disposition = FILE_OVERWRITE_IF;
2574 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2576 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2577 STR_TERMINATE, &status);
2578 if (!NT_STATUS_IS_OK(status)) {
2579 reply_nterror(req, status);
2583 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2584 status = filename_convert(ctx,
2591 if (!NT_STATUS_IS_OK(status)) {
2592 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2593 reply_botherror(req,
2594 NT_STATUS_PATH_NOT_COVERED,
2595 ERRSRV, ERRbadpath);
2598 reply_nterror(req, status);
2602 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2603 DEBUG(0,("Attempt to create file (%s) with volid set - "
2604 "please report this\n",
2605 smb_fname_str_dbg(smb_fname)));
2608 status = SMB_VFS_CREATE_FILE(
2611 0, /* root_dir_fid */
2612 smb_fname, /* fname */
2613 access_mask, /* access_mask */
2614 share_mode, /* share_access */
2615 create_disposition, /* create_disposition*/
2616 create_options, /* create_options */
2617 fattr, /* file_attributes */
2618 oplock_request, /* oplock_request */
2620 0, /* allocation_size */
2621 0, /* private_flags */
2626 NULL, NULL); /* create context */
2628 if (!NT_STATUS_IS_OK(status)) {
2629 if (open_was_deferred(req->xconn, req->mid)) {
2630 /* We have re-scheduled this call. */
2633 reply_openerror(req, status);
2637 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2638 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2639 if (!NT_STATUS_IS_OK(status)) {
2640 END_PROFILE(SMBcreate);
2644 reply_outbuf(req, 1, 0);
2645 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2647 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2648 SCVAL(req->outbuf,smb_flg,
2649 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2652 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2653 SCVAL(req->outbuf,smb_flg,
2654 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2657 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2658 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2659 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2660 (unsigned int)fattr));
2663 TALLOC_FREE(smb_fname);
2664 END_PROFILE(SMBcreate);
2668 /****************************************************************************
2669 Reply to a create temporary file.
2670 ****************************************************************************/
2672 void reply_ctemp(struct smb_request *req)
2674 connection_struct *conn = req->conn;
2675 struct smb_filename *smb_fname = NULL;
2676 char *wire_name = NULL;
2685 TALLOC_CTX *ctx = talloc_tos();
2687 START_PROFILE(SMBctemp);
2690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2694 fattr = SVAL(req->vwv+0, 0);
2695 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2697 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2698 STR_TERMINATE, &status);
2699 if (!NT_STATUS_IS_OK(status)) {
2700 reply_nterror(req, status);
2704 for (i = 0; i < 10; i++) {
2706 fname = talloc_asprintf(ctx,
2709 generate_random_str_list(ctx, 5, "0123456789"));
2711 fname = talloc_asprintf(ctx,
2713 generate_random_str_list(ctx, 5, "0123456789"));
2717 reply_nterror(req, NT_STATUS_NO_MEMORY);
2721 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2722 status = filename_convert(ctx, conn,
2728 if (!NT_STATUS_IS_OK(status)) {
2729 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2730 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2731 ERRSRV, ERRbadpath);
2734 reply_nterror(req, status);
2738 /* Create the file. */
2739 status = SMB_VFS_CREATE_FILE(
2742 0, /* root_dir_fid */
2743 smb_fname, /* fname */
2744 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2745 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2746 FILE_CREATE, /* create_disposition*/
2747 0, /* create_options */
2748 fattr, /* file_attributes */
2749 oplock_request, /* oplock_request */
2751 0, /* allocation_size */
2752 0, /* private_flags */
2757 NULL, NULL); /* create context */
2759 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2761 TALLOC_FREE(smb_fname);
2765 if (!NT_STATUS_IS_OK(status)) {
2766 if (open_was_deferred(req->xconn, req->mid)) {
2767 /* We have re-scheduled this call. */
2770 reply_openerror(req, status);
2778 /* Collision after 10 times... */
2779 reply_nterror(req, status);
2783 reply_outbuf(req, 1, 0);
2784 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2786 /* the returned filename is relative to the directory */
2787 s = strrchr_m(fsp->fsp_name->base_name, '/');
2789 s = fsp->fsp_name->base_name;
2795 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2796 thing in the byte section. JRA */
2797 SSVALS(p, 0, -1); /* what is this? not in spec */
2799 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2801 reply_nterror(req, NT_STATUS_NO_MEMORY);
2805 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2806 SCVAL(req->outbuf, smb_flg,
2807 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2810 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2811 SCVAL(req->outbuf, smb_flg,
2812 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2815 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2816 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2817 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2819 TALLOC_FREE(smb_fname);
2820 TALLOC_FREE(wire_name);
2821 END_PROFILE(SMBctemp);
2825 /*******************************************************************
2826 Check if a user is allowed to rename a file.
2827 ********************************************************************/
2829 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2832 if (!CAN_WRITE(conn)) {
2833 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2836 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2837 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2838 /* Only bother to read the DOS attribute if we might deny the
2839 rename on the grounds of attribute mismatch. */
2840 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2841 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2842 return NT_STATUS_NO_SUCH_FILE;
2846 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2847 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2848 return NT_STATUS_OK;
2851 /* If no pathnames are open below this
2852 directory, allow the rename. */
2854 if (lp_strict_rename(SNUM(conn))) {
2856 * Strict rename, check open file db.
2858 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2859 return NT_STATUS_ACCESS_DENIED;
2861 } else if (file_find_subpath(fsp)) {
2863 * No strict rename, just look in local process.
2865 return NT_STATUS_ACCESS_DENIED;
2867 return NT_STATUS_OK;
2870 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2871 return NT_STATUS_OK;
2874 return NT_STATUS_ACCESS_DENIED;
2877 /*******************************************************************
2878 * unlink a file with all relevant access checks
2879 *******************************************************************/
2881 static NTSTATUS do_unlink(connection_struct *conn,
2882 struct smb_request *req,
2883 struct smb_filename *smb_fname,
2888 uint32_t dirtype_orig = dirtype;
2891 bool posix_paths = (req != NULL && req->posix_pathnames);
2893 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2894 smb_fname_str_dbg(smb_fname),
2897 if (!CAN_WRITE(conn)) {
2898 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2902 ret = SMB_VFS_LSTAT(conn, smb_fname);
2904 ret = SMB_VFS_STAT(conn, smb_fname);
2907 return map_nt_error_from_unix(errno);
2910 fattr = dos_mode(conn, smb_fname);
2912 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2913 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2916 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2918 return NT_STATUS_NO_SUCH_FILE;
2921 if (!dir_check_ftype(fattr, dirtype)) {
2922 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2923 return NT_STATUS_FILE_IS_A_DIRECTORY;
2925 return NT_STATUS_NO_SUCH_FILE;
2928 if (dirtype_orig & 0x8000) {
2929 /* These will never be set for POSIX. */
2930 return NT_STATUS_NO_SUCH_FILE;
2934 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2935 return NT_STATUS_FILE_IS_A_DIRECTORY;
2938 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2939 return NT_STATUS_NO_SUCH_FILE;
2942 if (dirtype & 0xFF00) {
2943 /* These will never be set for POSIX. */
2944 return NT_STATUS_NO_SUCH_FILE;
2949 return NT_STATUS_NO_SUCH_FILE;
2952 /* Can't delete a directory. */
2953 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2954 return NT_STATUS_FILE_IS_A_DIRECTORY;
2959 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2960 return NT_STATUS_OBJECT_NAME_INVALID;
2961 #endif /* JRATEST */
2963 /* On open checks the open itself will check the share mode, so
2964 don't do it here as we'll get it wrong. */
2966 status = SMB_VFS_CREATE_FILE
2969 0, /* root_dir_fid */
2970 smb_fname, /* fname */
2971 DELETE_ACCESS, /* access_mask */
2972 FILE_SHARE_NONE, /* share_access */
2973 FILE_OPEN, /* create_disposition*/
2974 FILE_NON_DIRECTORY_FILE, /* create_options */
2975 /* file_attributes */
2976 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2977 FILE_ATTRIBUTE_NORMAL,
2978 0, /* oplock_request */
2980 0, /* allocation_size */
2981 0, /* private_flags */
2986 NULL, NULL); /* create context */
2988 if (!NT_STATUS_IS_OK(status)) {
2989 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2990 nt_errstr(status)));
2994 status = can_set_delete_on_close(fsp, fattr);
2995 if (!NT_STATUS_IS_OK(status)) {
2996 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2998 smb_fname_str_dbg(smb_fname),
2999 nt_errstr(status)));
3000 close_file(req, fsp, NORMAL_CLOSE);
3004 /* The set is across all open files on this dev/inode pair. */
3005 if (!set_delete_on_close(fsp, True,
3006 conn->session_info->security_token,
3007 conn->session_info->unix_token)) {
3008 close_file(req, fsp, NORMAL_CLOSE);
3009 return NT_STATUS_ACCESS_DENIED;
3012 return close_file(req, fsp, NORMAL_CLOSE);
3015 /****************************************************************************
3016 The guts of the unlink command, split out so it may be called by the NT SMB
3018 ****************************************************************************/
3020 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3021 uint32_t dirtype, struct smb_filename *smb_fname,
3024 char *fname_dir = NULL;
3025 char *fname_mask = NULL;
3027 NTSTATUS status = NT_STATUS_OK;
3028 struct smb_filename *smb_fname_dir = NULL;
3029 TALLOC_CTX *ctx = talloc_tos();
3031 /* Split up the directory from the filename/mask. */
3032 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3033 &fname_dir, &fname_mask);
3034 if (!NT_STATUS_IS_OK(status)) {
3039 * We should only check the mangled cache
3040 * here if unix_convert failed. This means
3041 * that the path in 'mask' doesn't exist
3042 * on the file system and so we need to look
3043 * for a possible mangle. This patch from
3044 * Tine Smukavec <valentin.smukavec@hermes.si>.
3047 if (!VALID_STAT(smb_fname->st) &&
3048 mangle_is_mangled(fname_mask, conn->params)) {
3049 char *new_mask = NULL;
3050 mangle_lookup_name_from_8_3(ctx, fname_mask,
3051 &new_mask, conn->params);
3053 TALLOC_FREE(fname_mask);
3054 fname_mask = new_mask;
3061 * Only one file needs to be unlinked. Append the mask back
3062 * onto the directory.
3064 TALLOC_FREE(smb_fname->base_name);
3065 if (ISDOT(fname_dir)) {
3066 /* Ensure we use canonical names on open. */
3067 smb_fname->base_name = talloc_asprintf(smb_fname,
3071 smb_fname->base_name = talloc_asprintf(smb_fname,
3076 if (!smb_fname->base_name) {
3077 status = NT_STATUS_NO_MEMORY;
3081 dirtype = FILE_ATTRIBUTE_NORMAL;
3084 status = check_name(conn, smb_fname);
3085 if (!NT_STATUS_IS_OK(status)) {
3089 status = do_unlink(conn, req, smb_fname, dirtype);
3090 if (!NT_STATUS_IS_OK(status)) {
3096 struct smb_Dir *dir_hnd = NULL;
3098 const char *dname = NULL;
3099 char *talloced = NULL;
3101 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3102 status = NT_STATUS_OBJECT_NAME_INVALID;
3106 dirtype = FILE_ATTRIBUTE_NORMAL;
3109 if (strequal(fname_mask,"????????.???")) {
3110 TALLOC_FREE(fname_mask);
3111 fname_mask = talloc_strdup(ctx, "*");
3113 status = NT_STATUS_NO_MEMORY;
3118 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3123 if (smb_fname_dir == NULL) {
3124 status = NT_STATUS_NO_MEMORY;
3128 status = check_name(conn, smb_fname_dir);
3129 if (!NT_STATUS_IS_OK(status)) {
3133 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3135 if (dir_hnd == NULL) {
3136 status = map_nt_error_from_unix(errno);
3140 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3141 the pattern matches against the long name, otherwise the short name
3142 We don't implement this yet XXXX
3145 status = NT_STATUS_NO_SUCH_FILE;
3147 while ((dname = ReadDirName(dir_hnd, &offset,
3148 &smb_fname->st, &talloced))) {
3149 TALLOC_CTX *frame = talloc_stackframe();
3151 if (!is_visible_file(conn, fname_dir, dname,
3152 &smb_fname->st, true)) {
3154 TALLOC_FREE(talloced);
3158 /* Quick check for "." and ".." */
3159 if (ISDOT(dname) || ISDOTDOT(dname)) {
3161 TALLOC_FREE(talloced);
3165 if(!mask_match(dname, fname_mask,
3166 conn->case_sensitive)) {
3168 TALLOC_FREE(talloced);
3172 TALLOC_FREE(smb_fname->base_name);
3173 if (ISDOT(fname_dir)) {
3174 /* Ensure we use canonical names on open. */
3175 smb_fname->base_name =
3176 talloc_asprintf(smb_fname, "%s",
3179 smb_fname->base_name =
3180 talloc_asprintf(smb_fname, "%s/%s",
3184 if (!smb_fname->base_name) {
3185 TALLOC_FREE(dir_hnd);
3186 status = NT_STATUS_NO_MEMORY;
3188 TALLOC_FREE(talloced);
3192 status = check_name(conn, smb_fname);
3193 if (!NT_STATUS_IS_OK(status)) {
3194 TALLOC_FREE(dir_hnd);
3196 TALLOC_FREE(talloced);
3200 status = do_unlink(conn, req, smb_fname, dirtype);
3201 if (!NT_STATUS_IS_OK(status)) {
3202 TALLOC_FREE(dir_hnd);
3204 TALLOC_FREE(talloced);
3209 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3210 smb_fname->base_name));
3213 TALLOC_FREE(talloced);
3215 TALLOC_FREE(dir_hnd);
3218 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3219 status = map_nt_error_from_unix(errno);
3223 TALLOC_FREE(smb_fname_dir);
3224 TALLOC_FREE(fname_dir);
3225 TALLOC_FREE(fname_mask);
3229 /****************************************************************************
3231 ****************************************************************************/
3233 void reply_unlink(struct smb_request *req)
3235 connection_struct *conn = req->conn;
3237 struct smb_filename *smb_fname = NULL;
3240 bool path_contains_wcard = False;
3241 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3242 ucf_flags_from_smb_request(req);
3243 TALLOC_CTX *ctx = talloc_tos();
3245 START_PROFILE(SMBunlink);
3248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3252 dirtype = SVAL(req->vwv+0, 0);
3254 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3255 STR_TERMINATE, &status,
3256 &path_contains_wcard);
3257 if (!NT_STATUS_IS_OK(status)) {
3258 reply_nterror(req, status);
3262 status = filename_convert(ctx, conn,
3266 &path_contains_wcard,
3268 if (!NT_STATUS_IS_OK(status)) {
3269 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3270 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3271 ERRSRV, ERRbadpath);
3274 reply_nterror(req, status);
3278 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3280 status = unlink_internals(conn, req, dirtype, smb_fname,
3281 path_contains_wcard);
3282 if (!NT_STATUS_IS_OK(status)) {
3283 if (open_was_deferred(req->xconn, req->mid)) {
3284 /* We have re-scheduled this call. */
3287 reply_nterror(req, status);
3291 reply_outbuf(req, 0, 0);
3293 TALLOC_FREE(smb_fname);
3294 END_PROFILE(SMBunlink);
3298 /****************************************************************************
3300 ****************************************************************************/
3302 static void fail_readraw(void)
3304 const char *errstr = talloc_asprintf(talloc_tos(),
3305 "FAIL ! reply_readbraw: socket write fail (%s)",
3310 exit_server_cleanly(errstr);
3313 /****************************************************************************
3314 Fake (read/write) sendfile. Returns -1 on read or write fail.
3315 ****************************************************************************/
3317 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3318 off_t startpos, size_t nread)
3321 size_t tosend = nread;
3328 bufsize = MIN(nread, 65536);
3330 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3334 while (tosend > 0) {
3338 cur_read = MIN(tosend, bufsize);
3339 ret = read_file(fsp,buf,startpos,cur_read);
3345 /* If we had a short read, fill with zeros. */
3346 if (ret < cur_read) {
3347 memset(buf + ret, '\0', cur_read - ret);
3350 ret = write_data(xconn->transport.sock, buf, cur_read);
3351 if (ret != cur_read) {
3352 int saved_errno = errno;
3354 * Try and give an error message saying what
3357 DEBUG(0, ("write_data failed for client %s. "
3359 smbXsrv_connection_dbg(xconn),
3360 strerror(saved_errno)));
3362 errno = saved_errno;
3366 startpos += cur_read;
3370 return (ssize_t)nread;
3373 /****************************************************************************
3374 Deal with the case of sendfile reading less bytes from the file than
3375 requested. Fill with zeros (all we can do). Returns 0 on success
3376 ****************************************************************************/
3378 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3384 #define SHORT_SEND_BUFSIZE 1024
3385 if (nread < headersize) {
3386 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3387 "header for file %s (%s). Terminating\n",
3388 fsp_str_dbg(fsp), strerror(errno)));
3392 nread -= headersize;
3394 if (nread < smb_maxcnt) {
3395 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3397 DEBUG(0,("sendfile_short_send: malloc failed "
3398 "for file %s (%s). Terminating\n",
3399 fsp_str_dbg(fsp), strerror(errno)));
3403 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3404 "with zeros !\n", fsp_str_dbg(fsp)));
3406 while (nread < smb_maxcnt) {
3408 * We asked for the real file size and told sendfile
3409 * to not go beyond the end of the file. But it can
3410 * happen that in between our fstat call and the
3411 * sendfile call the file was truncated. This is very
3412 * bad because we have already announced the larger
3413 * number of bytes to the client.
3415 * The best we can do now is to send 0-bytes, just as
3416 * a read from a hole in a sparse file would do.
3418 * This should happen rarely enough that I don't care
3419 * about efficiency here :-)
3424 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3425 ret = write_data(xconn->transport.sock, buf, to_write);
3426 if (ret != to_write) {
3427 int saved_errno = errno;
3429 * Try and give an error message saying what
3432 DEBUG(0, ("write_data failed for client %s. "
3434 smbXsrv_connection_dbg(xconn),
3435 strerror(saved_errno)));
3436 errno = saved_errno;
3447 /****************************************************************************
3448 Return a readbraw error (4 bytes of zero).
3449 ****************************************************************************/
3451 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3457 smbd_lock_socket(xconn);
3458 if (write_data(xconn->transport.sock,header,4) != 4) {
3459 int saved_errno = errno;
3461 * Try and give an error message saying what
3464 DEBUG(0, ("write_data failed for client %s. "
3466 smbXsrv_connection_dbg(xconn),
3467 strerror(saved_errno)));
3468 errno = saved_errno;
3472 smbd_unlock_socket(xconn);
3475 /****************************************************************************
3476 Use sendfile in readbraw.
3477 ****************************************************************************/
3479 static void send_file_readbraw(connection_struct *conn,
3480 struct smb_request *req,
3486 struct smbXsrv_connection *xconn = req->xconn;
3487 char *outbuf = NULL;
3491 * We can only use sendfile on a non-chained packet
3492 * but we can use on a non-oplocked file. tridge proved this
3493 * on a train in Germany :-). JRA.
3494 * reply_readbraw has already checked the length.
3497 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3498 (fsp->wcp == NULL) &&
3499 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3500 ssize_t sendfile_read = -1;
3502 DATA_BLOB header_blob;
3504 _smb_setlen(header,nread);
3505 header_blob = data_blob_const(header, 4);
3507 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3508 &header_blob, startpos,
3510 if (sendfile_read == -1) {
3511 /* Returning ENOSYS means no data at all was sent.
3512 * Do this as a normal read. */
3513 if (errno == ENOSYS) {
3514 goto normal_readbraw;
3518 * Special hack for broken Linux with no working sendfile. If we
3519 * return EINTR we sent the header but not the rest of the data.
3520 * Fake this up by doing read/write calls.
3522 if (errno == EINTR) {
3523 /* Ensure we don't do this again. */
3524 set_use_sendfile(SNUM(conn), False);
3525 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3527 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3528 DEBUG(0,("send_file_readbraw: "
3529 "fake_sendfile failed for "
3533 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3538 DEBUG(0,("send_file_readbraw: sendfile failed for "
3539 "file %s (%s). Terminating\n",
3540 fsp_str_dbg(fsp), strerror(errno)));
3541 exit_server_cleanly("send_file_readbraw sendfile failed");
3542 } else if (sendfile_read == 0) {
3544 * Some sendfile implementations return 0 to indicate
3545 * that there was a short read, but nothing was
3546 * actually written to the socket. In this case,
3547 * fallback to the normal read path so the header gets
3548 * the correct byte count.
3550 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3551 "bytes falling back to the normal read: "
3552 "%s\n", fsp_str_dbg(fsp)));
3553 goto normal_readbraw;
3556 /* Deal with possible short send. */
3557 if (sendfile_read != 4+nread) {
3558 ret = sendfile_short_send(xconn, fsp,
3559 sendfile_read, 4, nread);
3569 outbuf = talloc_array(NULL, char, nread+4);
3571 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3572 (unsigned)(nread+4)));
3573 reply_readbraw_error(xconn);
3578 ret = read_file(fsp,outbuf+4,startpos,nread);
3579 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3588 _smb_setlen(outbuf,ret);
3589 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3590 int saved_errno = errno;
3592 * Try and give an error message saying what
3595 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3596 smbXsrv_connection_dbg(xconn),
3597 strerror(saved_errno)));
3598 errno = saved_errno;
3603 TALLOC_FREE(outbuf);
3606 /****************************************************************************
3607 Reply to a readbraw (core+ protocol).
3608 ****************************************************************************/
3610 void reply_readbraw(struct smb_request *req)
3612 connection_struct *conn = req->conn;
3613 struct smbXsrv_connection *xconn = req->xconn;
3614 ssize_t maxcount,mincount;
3618 struct lock_struct lock;
3621 START_PROFILE(SMBreadbraw);
3623 if (srv_is_signing_active(xconn) || req->encrypted) {
3624 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3625 "raw reads/writes are disallowed.");
3629 reply_readbraw_error(xconn);
3630 END_PROFILE(SMBreadbraw);
3634 if (xconn->smb1.echo_handler.trusted_fde) {
3635 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3636 "'async smb echo handler = yes'\n"));
3637 reply_readbraw_error(xconn);
3638 END_PROFILE(SMBreadbraw);
3643 * Special check if an oplock break has been issued
3644 * and the readraw request croses on the wire, we must
3645 * return a zero length response here.
3648 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3651 * We have to do a check_fsp by hand here, as
3652 * we must always return 4 zero bytes on error,
3656 if (!fsp || !conn || conn != fsp->conn ||
3657 req->vuid != fsp->vuid ||
3658 fsp->is_directory || fsp->fh->fd == -1) {
3660 * fsp could be NULL here so use the value from the packet. JRA.
3662 DEBUG(3,("reply_readbraw: fnum %d not valid "
3664 (int)SVAL(req->vwv+0, 0)));
3665 reply_readbraw_error(xconn);
3666 END_PROFILE(SMBreadbraw);
3670 /* Do a "by hand" version of CHECK_READ. */
3671 if (!(fsp->can_read ||
3672 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3673 (fsp->access_mask & FILE_EXECUTE)))) {
3674 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3675 (int)SVAL(req->vwv+0, 0)));
3676 reply_readbraw_error(xconn);
3677 END_PROFILE(SMBreadbraw);
3681 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3683 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3684 if(req->wct == 10) {
3686 * This is a large offset (64 bit) read.
3689 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3692 DEBUG(0,("reply_readbraw: negative 64 bit "
3693 "readraw offset (%.0f) !\n",
3694 (double)startpos ));
3695 reply_readbraw_error(xconn);
3696 END_PROFILE(SMBreadbraw);
3701 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3702 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3704 /* ensure we don't overrun the packet size */
3705 maxcount = MIN(65535,maxcount);
3707 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3708 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3711 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3712 reply_readbraw_error(xconn);
3713 END_PROFILE(SMBreadbraw);
3717 if (fsp_stat(fsp) == 0) {
3718 size = fsp->fsp_name->st.st_ex_size;
3721 if (startpos >= size) {
3724 nread = MIN(maxcount,(size - startpos));
3727 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3728 if (nread < mincount)
3732 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3733 "min=%lu nread=%lu\n",
3734 fsp_fnum_dbg(fsp), (double)startpos,
3735 (unsigned long)maxcount,
3736 (unsigned long)mincount,
3737 (unsigned long)nread ) );
3739 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3741 DEBUG(5,("reply_readbraw finished\n"));
3743 END_PROFILE(SMBreadbraw);
3748 #define DBGC_CLASS DBGC_LOCKING
3750 /****************************************************************************
3751 Reply to a lockread (core+ protocol).
3752 ****************************************************************************/
3754 static void reply_lockread_locked(struct tevent_req *subreq);
3756 void reply_lockread(struct smb_request *req)
3758 struct tevent_req *subreq = NULL;
3759 connection_struct *conn = req->conn;
3761 struct smbd_lock_element *lck = NULL;
3763 START_PROFILE(SMBlockread);
3766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3767 END_PROFILE(SMBlockread);
3771 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3773 if (!check_fsp(conn, req, fsp)) {
3774 END_PROFILE(SMBlockread);
3778 if (!CHECK_READ(fsp,req)) {
3779 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3780 END_PROFILE(SMBlockread);
3784 lck = talloc(req, struct smbd_lock_element);
3786 reply_nterror(req, NT_STATUS_NO_MEMORY);
3787 END_PROFILE(SMBlockread);
3792 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3793 * protocol request that predates the read/write lock concept.
3794 * Thus instead of asking for a read lock here we need to ask
3795 * for a write lock. JRA.
3796 * Note that the requested lock size is unaffected by max_send.
3799 *lck = (struct smbd_lock_element) {
3800 .smblctx = req->smbpid,
3801 .brltype = WRITE_LOCK,
3802 .count = SVAL(req->vwv+1, 0),
3803 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3806 subreq = smbd_smb1_do_locks_send(
3812 false, /* large_offset */
3816 if (subreq == NULL) {
3817 reply_nterror(req, NT_STATUS_NO_MEMORY);
3818 END_PROFILE(SMBlockread);
3821 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3822 END_PROFILE(SMBlockread);
3825 static void reply_lockread_locked(struct tevent_req *subreq)
3827 struct smb_request *req = NULL;
3833 size_t numtoread, maxtoread;
3834 struct files_struct *fsp = NULL;
3837 START_PROFILE(SMBlockread);
3839 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3842 status = smbd_smb1_do_locks_recv(subreq);
3843 TALLOC_FREE(subreq);
3845 if (!NT_STATUS_IS_OK(status)) {
3846 reply_nterror(req, status);
3850 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3852 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
3856 numtoread = SVAL(req->vwv+1, 0);
3857 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3860 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3862 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3864 if (numtoread > maxtoread) {
3865 DBG_WARNING("requested read size (%zu) is greater than "
3866 "maximum allowed (%zu/%d). "
3867 "Returning short read of maximum allowed for "
3868 "compatibility with Windows 2000.\n",
3871 req->xconn->smb1.sessions.max_send);
3872 numtoread = maxtoread;
3875 reply_outbuf(req, 5, numtoread + 3);
3877 data = smb_buf(req->outbuf) + 3;
3879 nread = read_file(fsp,data,startpos,numtoread);
3882 reply_nterror(req, map_nt_error_from_unix(errno));
3886 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3888 SSVAL(req->outbuf,smb_vwv0,nread);
3889 SSVAL(req->outbuf,smb_vwv5,nread+3);
3890 p = smb_buf(req->outbuf);
3891 SCVAL(p,0,0); /* pad byte. */
3894 DEBUG(3,("lockread %s num=%d nread=%d\n",
3895 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3898 ok = srv_send_smb(req->xconn,
3899 (char *)req->outbuf,
3902 IS_CONN_ENCRYPTED(req->conn),
3905 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
3908 END_PROFILE(SMBlockread);
3913 #define DBGC_CLASS DBGC_ALL
3915 /****************************************************************************
3917 ****************************************************************************/
3919 void reply_read(struct smb_request *req)
3921 connection_struct *conn = req->conn;
3928 struct lock_struct lock;
3929 struct smbXsrv_connection *xconn = req->xconn;
3931 START_PROFILE(SMBread);
3934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3935 END_PROFILE(SMBread);
3939 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3941 if (!check_fsp(conn, req, fsp)) {
3942 END_PROFILE(SMBread);
3946 if (!CHECK_READ(fsp,req)) {
3947 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3948 END_PROFILE(SMBread);
3952 numtoread = SVAL(req->vwv+1, 0);
3953 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3956 * The requested read size cannot be greater than max_send. JRA.
3958 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3960 if (numtoread > maxtoread) {
3961 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3962 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3963 (unsigned int)numtoread, (unsigned int)maxtoread,
3964 (unsigned int)xconn->smb1.sessions.max_send));
3965 numtoread = maxtoread;
3968 reply_outbuf(req, 5, numtoread+3);
3970 data = smb_buf(req->outbuf) + 3;
3972 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3973 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3976 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3977 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3978 END_PROFILE(SMBread);
3983 nread = read_file(fsp,data,startpos,numtoread);
3986 reply_nterror(req, map_nt_error_from_unix(errno));
3990 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3992 SSVAL(req->outbuf,smb_vwv0,nread);
3993 SSVAL(req->outbuf,smb_vwv5,nread+3);
3994 SCVAL(smb_buf(req->outbuf),0,1);
3995 SSVAL(smb_buf(req->outbuf),1,nread);
3997 DEBUG(3, ("read %s num=%d nread=%d\n",
3998 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4001 END_PROFILE(SMBread);
4005 /****************************************************************************
4007 ****************************************************************************/
4009 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4013 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4016 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4018 SCVAL(outbuf,smb_vwv0,0xFF);
4019 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4020 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4021 SSVAL(outbuf,smb_vwv6,
4022 (smb_wct - 4) /* offset from smb header to wct */
4023 + 1 /* the wct field */
4024 + 12 * sizeof(uint16_t) /* vwv */
4025 + 2 /* the buflen field */
4026 + 1); /* padding byte */
4027 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4028 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4029 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4030 _smb_setlen_large(outbuf,
4031 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4035 /****************************************************************************
4036 Reply to a read and X - possibly using sendfile.
4037 ****************************************************************************/
4039 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4040 files_struct *fsp, off_t startpos,
4043 struct smbXsrv_connection *xconn = req->xconn;
4045 struct lock_struct lock;
4046 int saved_errno = 0;
4048 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4049 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4052 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4053 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4058 * We can only use sendfile on a non-chained packet
4059 * but we can use on a non-oplocked file. tridge proved this
4060 * on a train in Germany :-). JRA.
4063 if (!req_is_in_chain(req) &&
4065 (fsp->base_fsp == NULL) &&
4066 (fsp->wcp == NULL) &&
4067 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4068 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4071 if(fsp_stat(fsp) == -1) {
4072 reply_nterror(req, map_nt_error_from_unix(errno));
4076 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4077 (startpos > fsp->fsp_name->st.st_ex_size) ||
4078 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4080 * We already know that we would do a short read, so don't
4081 * try the sendfile() path.
4083 goto nosendfile_read;
4087 * Set up the packet header before send. We
4088 * assume here the sendfile will work (get the
4089 * correct amount of data).
4092 header = data_blob_const(headerbuf, sizeof(headerbuf));
4094 construct_reply_common_req(req, (char *)headerbuf);
4095 setup_readX_header((char *)headerbuf, smb_maxcnt);
4097 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4098 startpos, smb_maxcnt);
4100 saved_errno = errno;
4102 /* Returning ENOSYS means no data at all was sent.
4103 Do this as a normal read. */
4104 if (errno == ENOSYS) {
4109 * Special hack for broken Linux with no working sendfile. If we
4110 * return EINTR we sent the header but not the rest of the data.
4111 * Fake this up by doing read/write calls.
4114 if (errno == EINTR) {
4115 /* Ensure we don't do this again. */
4116 set_use_sendfile(SNUM(conn), False);
4117 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4118 nread = fake_sendfile(xconn, fsp, startpos,
4121 saved_errno = errno;
4122 DEBUG(0,("send_file_readX: "
4123 "fake_sendfile failed for "
4124 "file %s (%s) for client %s. "
4127 smbXsrv_connection_dbg(xconn),
4128 strerror(saved_errno)));
4129 errno = saved_errno;
4130 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4132 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4133 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4134 /* No outbuf here means successful sendfile. */
4138 DEBUG(0,("send_file_readX: sendfile failed for file "
4139 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4141 exit_server_cleanly("send_file_readX sendfile failed");
4142 } else if (nread == 0) {
4144 * Some sendfile implementations return 0 to indicate
4145 * that there was a short read, but nothing was
4146 * actually written to the socket. In this case,
4147 * fallback to the normal read path so the header gets
4148 * the correct byte count.
4150 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4151 "falling back to the normal read: %s\n",
4156 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4157 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4159 /* Deal with possible short send. */
4160 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4163 ret = sendfile_short_send(xconn, fsp, nread,
4164 sizeof(headerbuf), smb_maxcnt);
4167 r = "send_file_readX: sendfile_short_send failed";
4168 DEBUG(0,("%s for file %s (%s).\n",
4169 r, fsp_str_dbg(fsp), strerror(errno)));
4170 exit_server_cleanly(r);
4173 /* No outbuf here means successful sendfile. */
4174 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4175 SMB_PERFCOUNT_END(&req->pcd);
4181 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4182 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4185 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4186 (startpos > fsp->fsp_name->st.st_ex_size) ||
4187 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4189 * We already know that we would do a short
4190 * read, so don't try the sendfile() path.
4192 goto nosendfile_read;
4195 construct_reply_common_req(req, (char *)headerbuf);
4196 setup_readX_header((char *)headerbuf, smb_maxcnt);
4198 /* Send out the header. */
4199 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4201 if (ret != sizeof(headerbuf)) {
4202 saved_errno = errno;
4204 * Try and give an error message saying what
4207 DEBUG(0,("send_file_readX: write_data failed for file "
4208 "%s (%s) for client %s. Terminating\n",
4210 smbXsrv_connection_dbg(xconn),
4211 strerror(saved_errno)));
4212 errno = saved_errno;
4213 exit_server_cleanly("send_file_readX sendfile failed");
4215 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4217 saved_errno = errno;
4218 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4219 "%s (%s) for client %s. Terminating\n",
4221 smbXsrv_connection_dbg(xconn),
4222 strerror(saved_errno)));
4223 errno = saved_errno;
4224 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4231 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4232 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4233 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4235 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4236 startpos, smb_maxcnt);
4237 saved_errno = errno;
4240 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4244 setup_readX_header((char *)req->outbuf, nread);
4246 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4247 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4251 TALLOC_FREE(req->outbuf);
4255 /****************************************************************************
4256 Work out how much space we have for a read return.
4257 ****************************************************************************/
4259 static size_t calc_max_read_pdu(const struct smb_request *req)
4261 struct smbXsrv_connection *xconn = req->xconn;
4263 if (xconn->protocol < PROTOCOL_NT1) {
4264 return xconn->smb1.sessions.max_send;
4267 if (!lp_large_readwrite()) {
4268 return xconn->smb1.sessions.max_send;
4271 if (req_is_in_chain(req)) {
4272 return xconn->smb1.sessions.max_send;
4275 if (req->encrypted) {
4277 * Don't take encrypted traffic up to the
4278 * limit. There are padding considerations
4279 * that make that tricky.
4281 return xconn->smb1.sessions.max_send;
4284 if (srv_is_signing_active(xconn)) {
4288 if (!lp_unix_extensions()) {
4293 * We can do ultra-large POSIX reads.
4298 /****************************************************************************
4299 Calculate how big a read can be. Copes with all clients. It's always
4300 safe to return a short read - Windows does this.
4301 ****************************************************************************/
4303 static size_t calc_read_size(const struct smb_request *req,
4307 struct smbXsrv_connection *xconn = req->xconn;
4308 size_t max_pdu = calc_max_read_pdu(req);
4309 size_t total_size = 0;
4310 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4311 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4314 * Windows explicitly ignores upper size of 0xFFFF.
4315 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4316 * We must do the same as these will never fit even in
4317 * an extended size NetBIOS packet.
4319 if (upper_size == 0xFFFF) {
4323 if (xconn->protocol < PROTOCOL_NT1) {
4327 total_size = ((upper_size<<16) | lower_size);
4330 * LARGE_READX test shows it's always safe to return
4331 * a short read. Windows does so.
4333 return MIN(total_size, max_len);
4336 /****************************************************************************
4337 Reply to a read and X.
4338 ****************************************************************************/
4340 void reply_read_and_X(struct smb_request *req)
4342 connection_struct *conn = req->conn;
4347 bool big_readX = False;
4349 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4352 START_PROFILE(SMBreadX);
4354 if ((req->wct != 10) && (req->wct != 12)) {
4355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4359 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4360 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4361 smb_maxcnt = SVAL(req->vwv+5, 0);
4363 /* If it's an IPC, pass off the pipe handler. */
4365 reply_pipe_read_and_X(req);
4366 END_PROFILE(SMBreadX);
4370 if (!check_fsp(conn, req, fsp)) {
4371 END_PROFILE(SMBreadX);
4375 if (!CHECK_READ(fsp,req)) {
4376 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4377 END_PROFILE(SMBreadX);
4381 upper_size = SVAL(req->vwv+7, 0);
4382 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4383 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4385 * This is a heuristic to avoid keeping large
4386 * outgoing buffers around over long-lived aio
4392 if (req->wct == 12) {
4394 * This is a large offset (64 bit) read.
4396 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4401 NTSTATUS status = schedule_aio_read_and_X(conn,
4406 if (NT_STATUS_IS_OK(status)) {
4407 /* Read scheduled - we're done. */
4410 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4411 /* Real error - report to client. */
4412 END_PROFILE(SMBreadX);
4413 reply_nterror(req, status);
4416 /* NT_STATUS_RETRY - fall back to sync read. */
4419 smbd_lock_socket(req->xconn);
4420 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4421 smbd_unlock_socket(req->xconn);
4424 END_PROFILE(SMBreadX);
4428 /****************************************************************************
4429 Error replies to writebraw must have smb_wct == 1. Fix this up.
4430 ****************************************************************************/
4432 void error_to_writebrawerr(struct smb_request *req)
4434 uint8_t *old_outbuf = req->outbuf;
4436 reply_outbuf(req, 1, 0);
4438 memcpy(req->outbuf, old_outbuf, smb_size);
4439 TALLOC_FREE(old_outbuf);
4442 /****************************************************************************
4443 Read 4 bytes of a smb packet and return the smb length of the packet.
4444 Store the result in the buffer. This version of the function will
4445 never return a session keepalive (length of zero).
4446 Timeout is in milliseconds.
4447 ****************************************************************************/
4449 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4452 uint8_t msgtype = NBSSkeepalive;
4454 while (msgtype == NBSSkeepalive) {
4457 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4459 if (!NT_STATUS_IS_OK(status)) {
4460 char addr[INET6_ADDRSTRLEN];
4461 /* Try and give an error message
4462 * saying what client failed. */
4463 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4464 "client %s read error = %s.\n",
4465 get_peer_addr(fd,addr,sizeof(addr)),
4466 nt_errstr(status)));
4470 msgtype = CVAL(inbuf, 0);
4473 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4474 (unsigned long)len));
4476 return NT_STATUS_OK;
4479 /****************************************************************************
4480 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4481 ****************************************************************************/
4483 void reply_writebraw(struct smb_request *req)
4485 connection_struct *conn = req->conn;
4486 struct smbXsrv_connection *xconn = req->xconn;
4489 ssize_t total_written=0;
4490 size_t numtowrite=0;
4493 const char *data=NULL;
4496 struct lock_struct lock;
4499 START_PROFILE(SMBwritebraw);
4502 * If we ever reply with an error, it must have the SMB command
4503 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4506 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4508 if (srv_is_signing_active(xconn)) {
4509 END_PROFILE(SMBwritebraw);
4510 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4511 "raw reads/writes are disallowed.");
4514 if (req->wct < 12) {
4515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4516 error_to_writebrawerr(req);
4517 END_PROFILE(SMBwritebraw);
4521 if (xconn->smb1.echo_handler.trusted_fde) {
4522 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4523 "'async smb echo handler = yes'\n"));
4524 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4525 error_to_writebrawerr(req);
4526 END_PROFILE(SMBwritebraw);
4530 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4531 if (!check_fsp(conn, req, fsp)) {
4532 error_to_writebrawerr(req);
4533 END_PROFILE(SMBwritebraw);
4537 if (!CHECK_WRITE(fsp)) {
4538 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4539 error_to_writebrawerr(req);
4540 END_PROFILE(SMBwritebraw);
4544 tcount = IVAL(req->vwv+1, 0);
4545 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4546 write_through = BITSETW(req->vwv+7,0);
4548 /* We have to deal with slightly different formats depending
4549 on whether we are using the core+ or lanman1.0 protocol */
4551 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4552 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4553 data = smb_buf_const(req->inbuf);
4555 numtowrite = SVAL(req->vwv+10, 0);
4556 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4559 /* Ensure we don't write bytes past the end of this packet. */
4561 * This already protects us against CVE-2017-12163.
4563 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4565 error_to_writebrawerr(req);
4566 END_PROFILE(SMBwritebraw);
4570 if (!fsp->print_file) {
4571 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4572 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4575 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4576 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4577 error_to_writebrawerr(req);
4578 END_PROFILE(SMBwritebraw);
4584 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4587 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4588 "wrote=%d sync=%d\n",
4589 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4590 (int)nwritten, (int)write_through));
4592 if (nwritten < (ssize_t)numtowrite) {
4593 reply_nterror(req, NT_STATUS_DISK_FULL);
4594 error_to_writebrawerr(req);
4598 total_written = nwritten;
4600 /* Allocate a buffer of 64k + length. */
4601 buf = talloc_array(NULL, char, 65540);
4603 reply_nterror(req, NT_STATUS_NO_MEMORY);
4604 error_to_writebrawerr(req);
4608 /* Return a SMBwritebraw message to the redirector to tell
4609 * it to send more bytes */
4611 memcpy(buf, req->inbuf, smb_size);
4612 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4613 SCVAL(buf,smb_com,SMBwritebraw);
4614 SSVALS(buf,smb_vwv0,0xFFFF);
4616 if (!srv_send_smb(req->xconn,
4618 false, 0, /* no signing */
4619 IS_CONN_ENCRYPTED(conn),
4621 exit_server_cleanly("reply_writebraw: srv_send_smb "
4625 /* Now read the raw data into the buffer and write it */
4626 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4628 if (!NT_STATUS_IS_OK(status)) {
4629 exit_server_cleanly("secondary writebraw failed");
4632 /* Set up outbuf to return the correct size */
4633 reply_outbuf(req, 1, 0);
4635 if (numtowrite != 0) {
4637 if (numtowrite > 0xFFFF) {
4638 DEBUG(0,("reply_writebraw: Oversize secondary write "
4639 "raw requested (%u). Terminating\n",
4640 (unsigned int)numtowrite ));
4641 exit_server_cleanly("secondary writebraw failed");
4644 if (tcount > nwritten+numtowrite) {
4645 DEBUG(3,("reply_writebraw: Client overestimated the "
4647 (int)tcount,(int)nwritten,(int)numtowrite));
4650 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4653 if (!NT_STATUS_IS_OK(status)) {
4654 /* Try and give an error message
4655 * saying what client failed. */
4656 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4657 "raw read failed (%s) for client %s. "
4658 "Terminating\n", nt_errstr(status),
4659 smbXsrv_connection_dbg(xconn)));
4660 exit_server_cleanly("secondary writebraw failed");
4664 * We are not vulnerable to CVE-2017-12163
4665 * here as we are guaranteed to have numtowrite
4666 * bytes available - we just read from the client.
4668 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4669 if (nwritten == -1) {
4671 reply_nterror(req, map_nt_error_from_unix(errno));
4672 error_to_writebrawerr(req);
4676 if (nwritten < (ssize_t)numtowrite) {
4677 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4678 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4682 total_written += nwritten;
4687 SSVAL(req->outbuf,smb_vwv0,total_written);
4689 status = sync_file(conn, fsp, write_through);
4690 if (!NT_STATUS_IS_OK(status)) {
4691 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4692 fsp_str_dbg(fsp), nt_errstr(status)));
4693 reply_nterror(req, status);
4694 error_to_writebrawerr(req);
4698 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4700 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4701 (int)total_written));
4703 /* We won't return a status if write through is not selected - this
4704 * follows what WfWg does */
4705 END_PROFILE(SMBwritebraw);
4707 if (!write_through && total_written==tcount) {
4709 #if RABBIT_PELLET_FIX
4711 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4712 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4715 if (!send_keepalive(xconn->transport.sock)) {
4716 exit_server_cleanly("reply_writebraw: send of "
4717 "keepalive failed");
4720 TALLOC_FREE(req->outbuf);
4725 END_PROFILE(SMBwritebraw);
4730 #define DBGC_CLASS DBGC_LOCKING
4732 /****************************************************************************
4733 Reply to a writeunlock (core+).
4734 ****************************************************************************/
4736 void reply_writeunlock(struct smb_request *req)
4738 connection_struct *conn = req->conn;
4739 ssize_t nwritten = -1;
4744 NTSTATUS status = NT_STATUS_OK;
4746 struct lock_struct lock;
4747 int saved_errno = 0;
4749 START_PROFILE(SMBwriteunlock);
4752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4753 END_PROFILE(SMBwriteunlock);
4757 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4759 if (!check_fsp(conn, req, fsp)) {
4760 END_PROFILE(SMBwriteunlock);
4764 if (!CHECK_WRITE(fsp)) {
4765 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4766 END_PROFILE(SMBwriteunlock);
4770 numtowrite = SVAL(req->vwv+1, 0);
4771 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4772 data = (const char *)req->buf + 3;
4775 * Ensure client isn't asking us to write more than
4776 * they sent. CVE-2017-12163.
4778 remaining = smbreq_bufrem(req, data);
4779 if (numtowrite > remaining) {
4780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4781 END_PROFILE(SMBwriteunlock);
4785 if (!fsp->print_file && numtowrite > 0) {
4786 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4787 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4790 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4791 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4792 END_PROFILE(SMBwriteunlock);
4797 /* The special X/Open SMB protocol handling of
4798 zero length writes is *NOT* done for
4800 if(numtowrite == 0) {
4803 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4804 saved_errno = errno;
4807 status = sync_file(conn, fsp, False /* write through */);
4808 if (!NT_STATUS_IS_OK(status)) {
4809 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4810 fsp_str_dbg(fsp), nt_errstr(status)));
4811 reply_nterror(req, status);
4816 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4820 if((nwritten < numtowrite) && (numtowrite != 0)) {
4821 reply_nterror(req, NT_STATUS_DISK_FULL);
4825 if (numtowrite && !fsp->print_file) {
4826 struct smbd_lock_element l = {
4827 .smblctx = req->smbpid,
4828 .brltype = UNLOCK_LOCK,
4830 .count = numtowrite,
4832 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
4833 if (NT_STATUS_V(status)) {
4834 reply_nterror(req, status);
4839 reply_outbuf(req, 1, 0);
4841 SSVAL(req->outbuf,smb_vwv0,nwritten);
4843 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4844 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4847 END_PROFILE(SMBwriteunlock);
4852 #define DBGC_CLASS DBGC_ALL
4854 /****************************************************************************
4856 ****************************************************************************/
4858 void reply_write(struct smb_request *req)
4860 connection_struct *conn = req->conn;
4863 ssize_t nwritten = -1;
4867 struct lock_struct lock;
4869 int saved_errno = 0;
4871 START_PROFILE(SMBwrite);
4874 END_PROFILE(SMBwrite);
4875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4879 /* If it's an IPC, pass off the pipe handler. */
4881 reply_pipe_write(req);
4882 END_PROFILE(SMBwrite);
4886 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4888 if (!check_fsp(conn, req, fsp)) {
4889 END_PROFILE(SMBwrite);
4893 if (!CHECK_WRITE(fsp)) {
4894 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4895 END_PROFILE(SMBwrite);
4899 numtowrite = SVAL(req->vwv+1, 0);
4900 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4901 data = (const char *)req->buf + 3;
4904 * Ensure client isn't asking us to write more than
4905 * they sent. CVE-2017-12163.
4907 remaining = smbreq_bufrem(req, data);
4908 if (numtowrite > remaining) {
4909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4910 END_PROFILE(SMBwrite);
4914 if (!fsp->print_file) {
4915 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4916 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4919 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4920 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4921 END_PROFILE(SMBwrite);
4927 * X/Open SMB protocol says that if smb_vwv1 is
4928 * zero then the file size should be extended or
4929 * truncated to the size given in smb_vwv[2-3].
4932 if(numtowrite == 0) {
4934 * This is actually an allocate call, and set EOF. JRA.
4936 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4938 reply_nterror(req, NT_STATUS_DISK_FULL);
4941 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4943 reply_nterror(req, NT_STATUS_DISK_FULL);
4946 trigger_write_time_update_immediate(fsp);
4948 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4951 status = sync_file(conn, fsp, False);
4952 if (!NT_STATUS_IS_OK(status)) {
4953 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4954 fsp_str_dbg(fsp), nt_errstr(status)));
4955 reply_nterror(req, status);
4960 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4964 if((nwritten == 0) && (numtowrite != 0)) {
4965 reply_nterror(req, NT_STATUS_DISK_FULL);
4969 reply_outbuf(req, 1, 0);
4971 SSVAL(req->outbuf,smb_vwv0,nwritten);
4973 if (nwritten < (ssize_t)numtowrite) {
4974 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4975 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4978 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4981 END_PROFILE(SMBwrite);
4985 /****************************************************************************
4986 Ensure a buffer is a valid writeX for recvfile purposes.
4987 ****************************************************************************/
4989 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4990 (2*14) + /* word count (including bcc) */ \
4993 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4994 const uint8_t *inbuf)
4997 unsigned int doff = 0;
4998 size_t len = smb_len_large(inbuf);
5000 struct smbXsrv_open *op = NULL;
5001 struct files_struct *fsp = NULL;
5004 if (is_encrypted_packet(inbuf)) {
5005 /* Can't do this on encrypted
5010 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5014 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5015 CVAL(inbuf,smb_wct) != 14) {
5016 DEBUG(10,("is_valid_writeX_buffer: chained or "
5017 "invalid word length.\n"));
5021 fnum = SVAL(inbuf, smb_vwv2);
5022 status = smb1srv_open_lookup(xconn,
5026 if (!NT_STATUS_IS_OK(status)) {
5027 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5032 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5035 if (fsp->conn == NULL) {
5036 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5040 if (IS_IPC(fsp->conn)) {
5041 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5044 if (IS_PRINT(fsp->conn)) {
5045 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5048 if (fsp->base_fsp != NULL) {
5049 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5052 doff = SVAL(inbuf,smb_vwv11);
5054 numtowrite = SVAL(inbuf,smb_vwv10);
5056 if (len > doff && len - doff > 0xFFFF) {
5057 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5060 if (numtowrite == 0) {
5061 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5065 /* Ensure the sizes match up. */
5066 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5067 /* no pad byte...old smbclient :-( */
5068 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5070 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5074 if (len - doff != numtowrite) {
5075 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5076 "len = %u, doff = %u, numtowrite = %u\n",
5079 (unsigned int)numtowrite ));
5083 DEBUG(10,("is_valid_writeX_buffer: true "
5084 "len = %u, doff = %u, numtowrite = %u\n",
5087 (unsigned int)numtowrite ));
5092 /****************************************************************************
5093 Reply to a write and X.
5094 ****************************************************************************/
5096 void reply_write_and_X(struct smb_request *req)
5098 connection_struct *conn = req->conn;
5099 struct smbXsrv_connection *xconn = req->xconn;
5101 struct lock_struct lock;
5106 unsigned int smb_doff;
5107 unsigned int smblen;
5110 int saved_errno = 0;
5112 START_PROFILE(SMBwriteX);
5114 if ((req->wct != 12) && (req->wct != 14)) {
5115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5119 numtowrite = SVAL(req->vwv+10, 0);
5120 smb_doff = SVAL(req->vwv+11, 0);
5121 smblen = smb_len(req->inbuf);
5123 if (req->unread_bytes > 0xFFFF ||
5124 (smblen > smb_doff &&
5125 smblen - smb_doff > 0xFFFF)) {
5126 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5129 if (req->unread_bytes) {
5130 /* Can't do a recvfile write on IPC$ */
5132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5135 if (numtowrite != req->unread_bytes) {
5136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5141 * This already protects us against CVE-2017-12163.
5143 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5144 smb_doff + numtowrite > smblen) {
5145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5150 /* If it's an IPC, pass off the pipe handler. */
5152 if (req->unread_bytes) {
5153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5156 reply_pipe_write_and_X(req);
5160 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5161 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5162 write_through = BITSETW(req->vwv+7,0);
5164 if (!check_fsp(conn, req, fsp)) {
5168 if (!CHECK_WRITE(fsp)) {
5169 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5173 data = smb_base(req->inbuf) + smb_doff;
5175 if(req->wct == 14) {
5177 * This is a large offset (64 bit) write.
5179 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5183 /* X/Open SMB protocol says that, unlike SMBwrite
5184 if the length is zero then NO truncation is
5185 done, just a write of zero. To truncate a file,
5188 if(numtowrite == 0) {
5191 if (req->unread_bytes == 0) {
5192 status = schedule_aio_write_and_X(conn,
5199 if (NT_STATUS_IS_OK(status)) {
5200 /* write scheduled - we're done. */
5203 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5204 /* Real error - report to client. */
5205 reply_nterror(req, status);
5208 /* NT_STATUS_RETRY - fall through to sync write. */
5211 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5212 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5215 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5216 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5220 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5221 saved_errno = errno;
5225 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5229 if((nwritten == 0) && (numtowrite != 0)) {
5230 reply_nterror(req, NT_STATUS_DISK_FULL);
5234 reply_outbuf(req, 6, 0);
5235 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5236 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5237 SSVAL(req->outbuf,smb_vwv2,nwritten);
5238 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5240 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5241 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5243 status = sync_file(conn, fsp, write_through);
5244 if (!NT_STATUS_IS_OK(status)) {
5245 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5246 fsp_str_dbg(fsp), nt_errstr(status)));
5247 reply_nterror(req, status);
5251 END_PROFILE(SMBwriteX);
5255 if (req->unread_bytes) {
5256 /* writeX failed. drain socket. */
5257 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5258 req->unread_bytes) {
5259 smb_panic("failed to drain pending bytes");
5261 req->unread_bytes = 0;
5264 END_PROFILE(SMBwriteX);
5268 /****************************************************************************
5270 ****************************************************************************/
5272 void reply_lseek(struct smb_request *req)
5274 connection_struct *conn = req->conn;
5280 START_PROFILE(SMBlseek);
5283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5284 END_PROFILE(SMBlseek);
5288 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5290 if (!check_fsp(conn, req, fsp)) {
5294 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5296 mode = SVAL(req->vwv+1, 0) & 3;
5297 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5298 startpos = (off_t)IVALS(req->vwv+2, 0);
5307 res = fsp->fh->pos + startpos;
5318 if (umode == SEEK_END) {
5319 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5320 if(errno == EINVAL) {
5321 off_t current_pos = startpos;
5323 if(fsp_stat(fsp) == -1) {
5325 map_nt_error_from_unix(errno));
5326 END_PROFILE(SMBlseek);
5330 current_pos += fsp->fsp_name->st.st_ex_size;
5332 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5337 reply_nterror(req, map_nt_error_from_unix(errno));
5338 END_PROFILE(SMBlseek);
5345 reply_outbuf(req, 2, 0);
5346 SIVAL(req->outbuf,smb_vwv0,res);
5348 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5349 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5351 END_PROFILE(SMBlseek);
5355 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5358 connection_struct *conn = talloc_get_type_abort(
5359 private_data, connection_struct);
5361 if (conn != fsp->conn) {
5364 if (fsp->fh->fd == -1) {
5367 sync_file(conn, fsp, True /* write through */);
5372 /****************************************************************************
5374 ****************************************************************************/
5376 void reply_flush(struct smb_request *req)
5378 connection_struct *conn = req->conn;
5382 START_PROFILE(SMBflush);
5385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5389 fnum = SVAL(req->vwv+0, 0);
5390 fsp = file_fsp(req, fnum);
5392 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5397 files_forall(req->sconn, file_sync_one_fn, conn);
5399 NTSTATUS status = sync_file(conn, fsp, True);
5400 if (!NT_STATUS_IS_OK(status)) {
5401 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5402 fsp_str_dbg(fsp), nt_errstr(status)));
5403 reply_nterror(req, status);
5404 END_PROFILE(SMBflush);
5409 reply_outbuf(req, 0, 0);
5411 DEBUG(3,("flush\n"));
5412 END_PROFILE(SMBflush);
5416 /****************************************************************************
5418 conn POINTER CAN BE NULL HERE !
5419 ****************************************************************************/
5421 void reply_exit(struct smb_request *req)
5423 START_PROFILE(SMBexit);
5425 file_close_pid(req->sconn, req->smbpid, req->vuid);
5427 reply_outbuf(req, 0, 0);
5429 DEBUG(3,("exit\n"));
5431 END_PROFILE(SMBexit);
5435 struct reply_close_state {
5437 struct smb_request *smbreq;
5440 static void do_smb1_close(struct tevent_req *req);
5442 void reply_close(struct smb_request *req)
5444 connection_struct *conn = req->conn;
5445 NTSTATUS status = NT_STATUS_OK;
5446 files_struct *fsp = NULL;
5447 START_PROFILE(SMBclose);
5450 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5451 END_PROFILE(SMBclose);
5455 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5458 * We can only use check_fsp if we know it's not a directory.
5461 if (!check_fsp_open(conn, req, fsp)) {
5462 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5463 END_PROFILE(SMBclose);
5467 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5468 fsp->is_directory ? "directory" : "file",
5469 fsp->fh->fd, fsp_fnum_dbg(fsp),
5470 conn->num_files_open));
5472 if (!fsp->is_directory) {
5476 * Take care of any time sent in the close.
5479 t = srv_make_unix_date3(req->vwv+1);
5480 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5483 if (fsp->num_aio_requests != 0) {
5485 struct reply_close_state *state;
5487 DEBUG(10, ("closing with aio %u requests pending\n",
5488 fsp->num_aio_requests));
5491 * We depend on the aio_extra destructor to take care of this
5492 * close request once fsp->num_aio_request drops to 0.
5495 fsp->deferred_close = tevent_wait_send(
5496 fsp, fsp->conn->sconn->ev_ctx);
5497 if (fsp->deferred_close == NULL) {
5498 status = NT_STATUS_NO_MEMORY;
5502 state = talloc(fsp, struct reply_close_state);
5503 if (state == NULL) {
5504 TALLOC_FREE(fsp->deferred_close);
5505 status = NT_STATUS_NO_MEMORY;
5509 state->smbreq = talloc_move(fsp, &req);
5510 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5512 END_PROFILE(SMBclose);
5517 * close_file() returns the unix errno if an error was detected on
5518 * close - normally this is due to a disk full error. If not then it
5519 * was probably an I/O error.
5522 status = close_file(req, fsp, NORMAL_CLOSE);
5524 if (!NT_STATUS_IS_OK(status)) {
5525 reply_nterror(req, status);
5526 END_PROFILE(SMBclose);
5530 reply_outbuf(req, 0, 0);
5531 END_PROFILE(SMBclose);
5535 static void do_smb1_close(struct tevent_req *req)
5537 struct reply_close_state *state = tevent_req_callback_data(
5538 req, struct reply_close_state);
5539 struct smb_request *smbreq;
5543 ret = tevent_wait_recv(req);
5546 DEBUG(10, ("tevent_wait_recv returned %s\n",
5549 * Continue anyway, this should never happen
5554 * fsp->smb2_close_request right now is a talloc grandchild of
5555 * fsp. When we close_file(fsp), it would go with it. No chance to
5558 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5560 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5561 if (NT_STATUS_IS_OK(status)) {
5562 reply_outbuf(smbreq, 0, 0);
5564 reply_nterror(smbreq, status);
5566 if (!srv_send_smb(smbreq->xconn,
5567 (char *)smbreq->outbuf,
5570 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5572 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5575 TALLOC_FREE(smbreq);
5578 /****************************************************************************
5579 Reply to a writeclose (Core+ protocol).
5580 ****************************************************************************/
5582 void reply_writeclose(struct smb_request *req)
5584 connection_struct *conn = req->conn;
5587 ssize_t nwritten = -1;
5588 NTSTATUS close_status = NT_STATUS_OK;
5591 struct timespec mtime;
5593 struct lock_struct lock;
5595 START_PROFILE(SMBwriteclose);
5598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5599 END_PROFILE(SMBwriteclose);
5603 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5605 if (!check_fsp(conn, req, fsp)) {
5606 END_PROFILE(SMBwriteclose);
5609 if (!CHECK_WRITE(fsp)) {
5610 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5611 END_PROFILE(SMBwriteclose);
5615 numtowrite = SVAL(req->vwv+1, 0);
5616 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5617 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5618 data = (const char *)req->buf + 1;
5621 * Ensure client isn't asking us to write more than
5622 * they sent. CVE-2017-12163.
5624 remaining = smbreq_bufrem(req, data);
5625 if (numtowrite > remaining) {
5626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5627 END_PROFILE(SMBwriteclose);
5631 if (fsp->print_file == NULL) {
5632 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5633 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5636 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5637 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5638 END_PROFILE(SMBwriteclose);
5643 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5645 set_close_write_time(fsp, mtime);
5648 * More insanity. W2K only closes the file if writelen > 0.
5652 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5653 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5654 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5657 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5658 "file %s\n", fsp_str_dbg(fsp)));
5659 close_status = close_file(req, fsp, NORMAL_CLOSE);
5663 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5664 reply_nterror(req, NT_STATUS_DISK_FULL);
5668 if(!NT_STATUS_IS_OK(close_status)) {
5669 reply_nterror(req, close_status);
5673 reply_outbuf(req, 1, 0);
5675 SSVAL(req->outbuf,smb_vwv0,nwritten);
5679 END_PROFILE(SMBwriteclose);
5684 #define DBGC_CLASS DBGC_LOCKING
5686 /****************************************************************************
5688 ****************************************************************************/
5690 static void reply_lock_done(struct tevent_req *subreq);
5692 void reply_lock(struct smb_request *req)
5694 struct tevent_req *subreq = NULL;
5695 connection_struct *conn = req->conn;
5697 struct smbd_lock_element *lck = NULL;
5699 START_PROFILE(SMBlock);
5702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5703 END_PROFILE(SMBlock);
5707 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5709 if (!check_fsp(conn, req, fsp)) {
5710 END_PROFILE(SMBlock);
5714 lck = talloc(req, struct smbd_lock_element);
5716 reply_nterror(req, NT_STATUS_NO_MEMORY);
5717 END_PROFILE(SMBlock);
5721 *lck = (struct smbd_lock_element) {
5722 .smblctx = req->smbpid,
5723 .brltype = WRITE_LOCK,
5724 .count = IVAL(req->vwv+1, 0),
5725 .offset = IVAL(req->vwv+3, 0),
5728 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5734 subreq = smbd_smb1_do_locks_send(
5740 false, /* large_offset */
5744 if (subreq == NULL) {
5745 reply_nterror(req, NT_STATUS_NO_MEMORY);
5746 END_PROFILE(SMBlock);
5749 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5750 END_PROFILE(SMBlock);
5753 static void reply_lock_done(struct tevent_req *subreq)
5755 struct smb_request *req = NULL;
5759 START_PROFILE(SMBlock);
5761 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5764 status = smbd_smb1_do_locks_recv(subreq);
5765 TALLOC_FREE(subreq);
5767 if (NT_STATUS_IS_OK(status)) {
5768 reply_outbuf(req, 0, 0);
5770 reply_nterror(req, status);
5773 ok = srv_send_smb(req->xconn,
5774 (char *)req->outbuf,
5777 IS_CONN_ENCRYPTED(req->conn),
5780 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
5783 END_PROFILE(SMBlock);
5786 /****************************************************************************
5788 ****************************************************************************/
5790 void reply_unlock(struct smb_request *req)
5792 connection_struct *conn = req->conn;
5795 struct smbd_lock_element lck;
5797 START_PROFILE(SMBunlock);
5800 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5801 END_PROFILE(SMBunlock);
5805 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5807 if (!check_fsp(conn, req, fsp)) {
5808 END_PROFILE(SMBunlock);
5812 lck = (struct smbd_lock_element) {
5813 .smblctx = req->smbpid,
5814 .brltype = UNLOCK_LOCK,
5815 .offset = IVAL(req->vwv+3, 0),
5816 .count = IVAL(req->vwv+1, 0),
5819 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
5821 if (!NT_STATUS_IS_OK(status)) {
5822 reply_nterror(req, status);
5823 END_PROFILE(SMBunlock);
5827 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5833 reply_outbuf(req, 0, 0);
5835 END_PROFILE(SMBunlock);
5840 #define DBGC_CLASS DBGC_ALL
5842 /****************************************************************************
5844 conn POINTER CAN BE NULL HERE !
5845 ****************************************************************************/
5847 void reply_tdis(struct smb_request *req)
5850 connection_struct *conn = req->conn;
5851 struct smbXsrv_tcon *tcon;
5853 START_PROFILE(SMBtdis);
5856 DEBUG(4,("Invalid connection in tdis\n"));
5857 reply_force_doserror(req, ERRSRV, ERRinvnid);
5858 END_PROFILE(SMBtdis);
5866 * TODO: cancel all outstanding requests on the tcon
5868 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5869 if (!NT_STATUS_IS_OK(status)) {
5870 DEBUG(0, ("reply_tdis: "
5871 "smbXsrv_tcon_disconnect() failed: %s\n",
5872 nt_errstr(status)));
5874 * If we hit this case, there is something completely
5875 * wrong, so we better disconnect the transport connection.
5877 END_PROFILE(SMBtdis);
5878 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5884 reply_outbuf(req, 0, 0);
5885 END_PROFILE(SMBtdis);
5889 /****************************************************************************
5891 conn POINTER CAN BE NULL HERE !
5892 ****************************************************************************/
5894 void reply_echo(struct smb_request *req)
5896 connection_struct *conn = req->conn;
5897 struct smb_perfcount_data local_pcd;
5898 struct smb_perfcount_data *cur_pcd;
5902 START_PROFILE(SMBecho);
5904 smb_init_perfcount_data(&local_pcd);
5907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5908 END_PROFILE(SMBecho);
5912 smb_reverb = SVAL(req->vwv+0, 0);
5914 reply_outbuf(req, 1, req->buflen);
5916 /* copy any incoming data back out */
5917 if (req->buflen > 0) {
5918 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5921 if (smb_reverb > 100) {
5922 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5926 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5928 /* this makes sure we catch the request pcd */
5929 if (seq_num == smb_reverb) {
5930 cur_pcd = &req->pcd;
5932 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5933 cur_pcd = &local_pcd;
5936 SSVAL(req->outbuf,smb_vwv0,seq_num);
5938 show_msg((char *)req->outbuf);
5939 if (!srv_send_smb(req->xconn,
5940 (char *)req->outbuf,
5941 true, req->seqnum+1,
5942 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5944 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5947 DEBUG(3,("echo %d times\n", smb_reverb));
5949 TALLOC_FREE(req->outbuf);
5951 END_PROFILE(SMBecho);
5955 /****************************************************************************
5956 Reply to a printopen.
5957 ****************************************************************************/
5959 void reply_printopen(struct smb_request *req)
5961 connection_struct *conn = req->conn;
5965 START_PROFILE(SMBsplopen);
5968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5969 END_PROFILE(SMBsplopen);
5973 if (!CAN_PRINT(conn)) {
5974 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5975 END_PROFILE(SMBsplopen);
5979 status = file_new(req, conn, &fsp);
5980 if(!NT_STATUS_IS_OK(status)) {
5981 reply_nterror(req, status);
5982 END_PROFILE(SMBsplopen);
5986 /* Open for exclusive use, write only. */
5987 status = print_spool_open(fsp, NULL, req->vuid);
5989 if (!NT_STATUS_IS_OK(status)) {
5990 file_free(req, fsp);
5991 reply_nterror(req, status);
5992 END_PROFILE(SMBsplopen);
5996 reply_outbuf(req, 1, 0);
5997 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5999 DEBUG(3,("openprint fd=%d %s\n",
6000 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6002 END_PROFILE(SMBsplopen);
6006 /****************************************************************************
6007 Reply to a printclose.
6008 ****************************************************************************/
6010 void reply_printclose(struct smb_request *req)
6012 connection_struct *conn = req->conn;
6016 START_PROFILE(SMBsplclose);
6019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6020 END_PROFILE(SMBsplclose);
6024 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6026 if (!check_fsp(conn, req, fsp)) {
6027 END_PROFILE(SMBsplclose);
6031 if (!CAN_PRINT(conn)) {
6032 reply_force_doserror(req, ERRSRV, ERRerror);
6033 END_PROFILE(SMBsplclose);
6037 DEBUG(3,("printclose fd=%d %s\n",
6038 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6040 status = close_file(req, fsp, NORMAL_CLOSE);
6042 if(!NT_STATUS_IS_OK(status)) {
6043 reply_nterror(req, status);
6044 END_PROFILE(SMBsplclose);
6048 reply_outbuf(req, 0, 0);
6050 END_PROFILE(SMBsplclose);
6054 /****************************************************************************
6055 Reply to a printqueue.
6056 ****************************************************************************/
6058 void reply_printqueue(struct smb_request *req)
6060 connection_struct *conn = req->conn;
6064 START_PROFILE(SMBsplretq);
6067 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6068 END_PROFILE(SMBsplretq);
6072 max_count = SVAL(req->vwv+0, 0);
6073 start_index = SVAL(req->vwv+1, 0);
6075 /* we used to allow the client to get the cnum wrong, but that
6076 is really quite gross and only worked when there was only
6077 one printer - I think we should now only accept it if they
6078 get it right (tridge) */
6079 if (!CAN_PRINT(conn)) {
6080 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6081 END_PROFILE(SMBsplretq);
6085 reply_outbuf(req, 2, 3);
6086 SSVAL(req->outbuf,smb_vwv0,0);
6087 SSVAL(req->outbuf,smb_vwv1,0);
6088 SCVAL(smb_buf(req->outbuf),0,1);
6089 SSVAL(smb_buf(req->outbuf),1,0);
6091 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6092 start_index, max_count));
6095 TALLOC_CTX *mem_ctx = talloc_tos();
6098 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
6099 struct rpc_pipe_client *cli = NULL;
6100 struct dcerpc_binding_handle *b = NULL;
6101 struct policy_handle handle;
6102 struct spoolss_DevmodeContainer devmode_ctr;
6103 union spoolss_JobInfo *info;
6105 uint32_t num_to_get;
6109 ZERO_STRUCT(handle);
6111 status = rpc_pipe_open_interface(mem_ctx,
6114 conn->sconn->remote_address,
6115 conn->sconn->local_address,
6116 conn->sconn->msg_ctx,
6118 if (!NT_STATUS_IS_OK(status)) {
6119 DEBUG(0, ("reply_printqueue: "
6120 "could not connect to spoolss: %s\n",
6121 nt_errstr(status)));
6122 reply_nterror(req, status);
6125 b = cli->binding_handle;
6127 ZERO_STRUCT(devmode_ctr);
6129 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6132 SEC_FLAG_MAXIMUM_ALLOWED,
6135 if (!NT_STATUS_IS_OK(status)) {
6136 reply_nterror(req, status);
6139 if (!W_ERROR_IS_OK(werr)) {
6140 reply_nterror(req, werror_to_ntstatus(werr));
6144 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6152 if (!W_ERROR_IS_OK(werr)) {
6153 reply_nterror(req, werror_to_ntstatus(werr));
6157 if (max_count > 0) {
6158 first = start_index;
6160 first = start_index + max_count + 1;
6163 if (first >= count) {
6166 num_to_get = first + MIN(ABS(max_count), count - first);
6169 for (i = first; i < num_to_get; i++) {
6172 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6175 uint16_t qrapjobid = pjobid_to_rap(sharename,
6176 info[i].info2.job_id);
6178 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6184 srv_put_dos_date2(p, 0, qtime);
6185 SCVAL(p, 4, qstatus);
6186 SSVAL(p, 5, qrapjobid);
6187 SIVAL(p, 7, info[i].info2.size);
6189 status = srvstr_push(blob, req->flags2, p+12,
6190 info[i].info2.notify_name, 16, STR_ASCII, &len);
6191 if (!NT_STATUS_IS_OK(status)) {
6192 reply_nterror(req, status);
6195 if (message_push_blob(
6198 blob, sizeof(blob))) == -1) {
6199 reply_nterror(req, NT_STATUS_NO_MEMORY);
6205 SSVAL(req->outbuf,smb_vwv0,count);
6206 SSVAL(req->outbuf,smb_vwv1,
6207 (max_count>0?first+count:first-1));
6208 SCVAL(smb_buf(req->outbuf),0,1);
6209 SSVAL(smb_buf(req->outbuf),1,28*count);
6213 DEBUG(3, ("%u entries returned in queue\n",
6217 if (b && is_valid_policy_hnd(&handle)) {
6218 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6223 END_PROFILE(SMBsplretq);
6227 /****************************************************************************
6228 Reply to a printwrite.
6229 ****************************************************************************/
6231 void reply_printwrite(struct smb_request *req)
6233 connection_struct *conn = req->conn;
6238 START_PROFILE(SMBsplwr);
6241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6242 END_PROFILE(SMBsplwr);
6246 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6248 if (!check_fsp(conn, req, fsp)) {
6249 END_PROFILE(SMBsplwr);
6253 if (!fsp->print_file) {
6254 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6255 END_PROFILE(SMBsplwr);
6259 if (!CHECK_WRITE(fsp)) {
6260 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6261 END_PROFILE(SMBsplwr);
6265 numtowrite = SVAL(req->buf, 1);
6268 * This already protects us against CVE-2017-12163.
6270 if (req->buflen < numtowrite + 3) {
6271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6272 END_PROFILE(SMBsplwr);
6276 data = (const char *)req->buf + 3;
6278 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6279 reply_nterror(req, map_nt_error_from_unix(errno));
6280 END_PROFILE(SMBsplwr);
6284 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6286 END_PROFILE(SMBsplwr);
6290 /****************************************************************************
6292 ****************************************************************************/
6294 void reply_mkdir(struct smb_request *req)
6296 connection_struct *conn = req->conn;
6297 struct smb_filename *smb_dname = NULL;
6298 char *directory = NULL;
6301 TALLOC_CTX *ctx = talloc_tos();
6303 START_PROFILE(SMBmkdir);
6305 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6306 STR_TERMINATE, &status);
6307 if (!NT_STATUS_IS_OK(status)) {
6308 reply_nterror(req, status);
6312 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6313 status = filename_convert(ctx, conn,
6319 if (!NT_STATUS_IS_OK(status)) {
6320 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6321 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6322 ERRSRV, ERRbadpath);
6325 reply_nterror(req, status);
6329 status = create_directory(conn, req, smb_dname);
6331 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6333 if (!NT_STATUS_IS_OK(status)) {
6335 if (!use_nt_status()
6336 && NT_STATUS_EQUAL(status,
6337 NT_STATUS_OBJECT_NAME_COLLISION)) {
6339 * Yes, in the DOS error code case we get a
6340 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6341 * samba4 torture test.
6343 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6346 reply_nterror(req, status);
6350 reply_outbuf(req, 0, 0);
6352 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6354 TALLOC_FREE(smb_dname);
6355 END_PROFILE(SMBmkdir);
6359 /****************************************************************************
6361 ****************************************************************************/
6363 void reply_rmdir(struct smb_request *req)
6365 connection_struct *conn = req->conn;
6366 struct smb_filename *smb_dname = NULL;
6367 char *directory = NULL;
6369 TALLOC_CTX *ctx = talloc_tos();
6370 files_struct *fsp = NULL;
6372 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6373 struct smbd_server_connection *sconn = req->sconn;
6375 START_PROFILE(SMBrmdir);
6377 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6378 STR_TERMINATE, &status);
6379 if (!NT_STATUS_IS_OK(status)) {
6380 reply_nterror(req, status);
6384 status = filename_convert(ctx, conn,
6390 if (!NT_STATUS_IS_OK(status)) {
6391 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6392 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6393 ERRSRV, ERRbadpath);
6396 reply_nterror(req, status);
6400 if (is_ntfs_stream_smb_fname(smb_dname)) {
6401 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6405 status = SMB_VFS_CREATE_FILE(
6408 0, /* root_dir_fid */
6409 smb_dname, /* fname */
6410 DELETE_ACCESS, /* access_mask */
6411 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6413 FILE_OPEN, /* create_disposition*/
6414 FILE_DIRECTORY_FILE, /* create_options */
6415 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6416 0, /* oplock_request */
6418 0, /* allocation_size */
6419 0, /* private_flags */
6424 NULL, NULL); /* create context */
6426 if (!NT_STATUS_IS_OK(status)) {
6427 if (open_was_deferred(req->xconn, req->mid)) {
6428 /* We have re-scheduled this call. */
6431 reply_nterror(req, status);
6435 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6436 if (!NT_STATUS_IS_OK(status)) {
6437 close_file(req, fsp, ERROR_CLOSE);
6438 reply_nterror(req, status);
6442 if (!set_delete_on_close(fsp, true,
6443 conn->session_info->security_token,
6444 conn->session_info->unix_token)) {
6445 close_file(req, fsp, ERROR_CLOSE);
6446 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6450 status = close_file(req, fsp, NORMAL_CLOSE);
6451 if (!NT_STATUS_IS_OK(status)) {
6452 reply_nterror(req, status);
6454 reply_outbuf(req, 0, 0);
6457 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6459 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6461 TALLOC_FREE(smb_dname);
6462 END_PROFILE(SMBrmdir);
6466 /*******************************************************************
6467 Resolve wildcards in a filename rename.
6468 ********************************************************************/
6470 static bool resolve_wildcards(TALLOC_CTX *ctx,
6475 char *name2_copy = NULL;
6480 char *p,*p2, *pname1, *pname2;
6482 name2_copy = talloc_strdup(ctx, name2);
6487 pname1 = strrchr_m(name1,'/');
6488 pname2 = strrchr_m(name2_copy,'/');
6490 if (!pname1 || !pname2) {
6494 /* Truncate the copy of name2 at the last '/' */
6497 /* Now go past the '/' */
6501 root1 = talloc_strdup(ctx, pname1);
6502 root2 = talloc_strdup(ctx, pname2);
6504 if (!root1 || !root2) {
6508 p = strrchr_m(root1,'.');
6511 ext1 = talloc_strdup(ctx, p+1);
6513 ext1 = talloc_strdup(ctx, "");
6515 p = strrchr_m(root2,'.');
6518 ext2 = talloc_strdup(ctx, p+1);
6520 ext2 = talloc_strdup(ctx, "");
6523 if (!ext1 || !ext2) {
6531 /* Hmmm. Should this be mb-aware ? */
6534 } else if (*p2 == '*') {
6536 root2 = talloc_asprintf(ctx, "%s%s",
6555 /* Hmmm. Should this be mb-aware ? */
6558 } else if (*p2 == '*') {
6560 ext2 = talloc_asprintf(ctx, "%s%s",
6576 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6581 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6593 /****************************************************************************
6594 Ensure open files have their names updated. Updated to notify other smbd's
6596 ****************************************************************************/
6598 static void rename_open_files(connection_struct *conn,
6599 struct share_mode_lock *lck,
6601 uint32_t orig_name_hash,
6602 const struct smb_filename *smb_fname_dst)
6605 bool did_rename = False;
6607 uint32_t new_name_hash = 0;
6609 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6610 fsp = file_find_di_next(fsp)) {
6611 /* fsp_name is a relative path under the fsp. To change this for other
6612 sharepaths we need to manipulate relative paths. */
6613 /* TODO - create the absolute path and manipulate the newname
6614 relative to the sharepath. */
6615 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6618 if (fsp->name_hash != orig_name_hash) {
6621 DEBUG(10, ("rename_open_files: renaming file %s "
6622 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6623 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6624 smb_fname_str_dbg(smb_fname_dst)));
6626 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6627 if (NT_STATUS_IS_OK(status)) {
6629 new_name_hash = fsp->name_hash;
6634 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6635 "for %s\n", file_id_string_tos(&id),
6636 smb_fname_str_dbg(smb_fname_dst)));
6639 /* Send messages to all smbd's (not ourself) that the name has changed. */
6640 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6641 orig_name_hash, new_name_hash,
6646 /****************************************************************************
6647 We need to check if the source path is a parent directory of the destination
6648 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6649 refuse the rename with a sharing violation. Under UNIX the above call can
6650 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6651 probably need to check that the client is a Windows one before disallowing
6652 this as a UNIX client (one with UNIX extensions) can know the source is a
6653 symlink and make this decision intelligently. Found by an excellent bug
6654 report from <AndyLiebman@aol.com>.
6655 ****************************************************************************/
6657 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6658 const struct smb_filename *smb_fname_dst)
6660 const char *psrc = smb_fname_src->base_name;
6661 const char *pdst = smb_fname_dst->base_name;
6664 if (psrc[0] == '.' && psrc[1] == '/') {
6667 if (pdst[0] == '.' && pdst[1] == '/') {
6670 if ((slen = strlen(psrc)) > strlen(pdst)) {
6673 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6677 * Do the notify calls from a rename
6680 static void notify_rename(connection_struct *conn, bool is_dir,
6681 const struct smb_filename *smb_fname_src,
6682 const struct smb_filename *smb_fname_dst)
6684 char *parent_dir_src = NULL;
6685 char *parent_dir_dst = NULL;
6688 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6689 : FILE_NOTIFY_CHANGE_FILE_NAME;
6691 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6692 &parent_dir_src, NULL) ||
6693 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6694 &parent_dir_dst, NULL)) {
6698 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6699 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6700 smb_fname_src->base_name);
6701 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6702 smb_fname_dst->base_name);
6705 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6706 smb_fname_src->base_name);
6707 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6708 smb_fname_dst->base_name);
6711 /* this is a strange one. w2k3 gives an additional event for
6712 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6713 files, but not directories */
6715 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6716 FILE_NOTIFY_CHANGE_ATTRIBUTES
6717 |FILE_NOTIFY_CHANGE_CREATION,
6718 smb_fname_dst->base_name);
6721 TALLOC_FREE(parent_dir_src);
6722 TALLOC_FREE(parent_dir_dst);
6725 /****************************************************************************
6726 Returns an error if the parent directory for a filename is open in an
6728 ****************************************************************************/
6730 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6731 const struct smb_filename *smb_fname_dst_in)
6733 char *parent_dir = NULL;
6734 struct smb_filename smb_fname_parent;
6736 files_struct *fsp = NULL;
6739 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6740 &parent_dir, NULL)) {
6741 return NT_STATUS_NO_MEMORY;
6743 ZERO_STRUCT(smb_fname_parent);
6744 smb_fname_parent.base_name = parent_dir;
6746 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6748 return map_nt_error_from_unix(errno);
6752 * We're only checking on this smbd here, mostly good
6753 * enough.. and will pass tests.
6756 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6757 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6758 fsp = file_find_di_next(fsp)) {
6759 if (fsp->access_mask & DELETE_ACCESS) {
6760 return NT_STATUS_SHARING_VIOLATION;
6763 return NT_STATUS_OK;
6766 /****************************************************************************
6767 Rename an open file - given an fsp.
6768 ****************************************************************************/
6770 NTSTATUS rename_internals_fsp(connection_struct *conn,
6772 const struct smb_filename *smb_fname_dst_in,
6774 bool replace_if_exists)
6776 TALLOC_CTX *ctx = talloc_tos();
6777 struct smb_filename *smb_fname_dst = NULL;
6778 NTSTATUS status = NT_STATUS_OK;
6779 struct share_mode_lock *lck = NULL;
6780 uint32_t access_mask = SEC_DIR_ADD_FILE;
6781 bool dst_exists, old_is_stream, new_is_stream;
6783 status = check_name(conn, smb_fname_dst_in);
6784 if (!NT_STATUS_IS_OK(status)) {
6788 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6789 if (!NT_STATUS_IS_OK(status)) {
6793 if (file_has_open_streams(fsp)) {
6794 return NT_STATUS_ACCESS_DENIED;
6797 /* Make a copy of the dst smb_fname structs */
6799 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6800 if (smb_fname_dst == NULL) {
6801 status = NT_STATUS_NO_MEMORY;
6806 * Check for special case with case preserving and not
6807 * case sensitive. If the new last component differs from the original
6808 * last component only by case, then we should allow
6809 * the rename (user is trying to change the case of the
6812 if (!conn->case_sensitive && conn->case_preserve &&
6813 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6814 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6815 char *fname_dst_parent = NULL;
6816 const char *fname_dst_lcomp = NULL;
6817 char *orig_lcomp_path = NULL;
6818 char *orig_lcomp_stream = NULL;
6822 * Split off the last component of the processed
6823 * destination name. We will compare this to
6824 * the split components of smb_fname_dst->original_lcomp.
6826 if (!parent_dirname(ctx,
6827 smb_fname_dst->base_name,
6829 &fname_dst_lcomp)) {
6830 status = NT_STATUS_NO_MEMORY;
6835 * The original_lcomp component contains
6836 * the last_component of the path + stream
6837 * name (if a stream exists).
6839 * Split off the stream name so we
6840 * can check them separately.
6843 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6844 /* POSIX - no stream component. */
6845 orig_lcomp_path = talloc_strdup(ctx,
6846 smb_fname_dst->original_lcomp);
6847 if (orig_lcomp_path == NULL) {
6851 ok = split_stream_filename(ctx,
6852 smb_fname_dst->original_lcomp,
6854 &orig_lcomp_stream);
6858 TALLOC_FREE(fname_dst_parent);
6859 status = NT_STATUS_NO_MEMORY;
6863 /* If the base names only differ by case, use original. */
6864 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6867 * Replace the modified last component with the
6870 if (!ISDOT(fname_dst_parent)) {
6871 tmp = talloc_asprintf(smb_fname_dst,
6876 tmp = talloc_strdup(smb_fname_dst,
6880 status = NT_STATUS_NO_MEMORY;
6881 TALLOC_FREE(fname_dst_parent);
6882 TALLOC_FREE(orig_lcomp_path);
6883 TALLOC_FREE(orig_lcomp_stream);
6886 TALLOC_FREE(smb_fname_dst->base_name);
6887 smb_fname_dst->base_name = tmp;
6890 /* If the stream_names only differ by case, use original. */
6891 if(!strcsequal(smb_fname_dst->stream_name,
6892 orig_lcomp_stream)) {
6893 /* Use the original stream. */
6894 char *tmp = talloc_strdup(smb_fname_dst,
6897 status = NT_STATUS_NO_MEMORY;
6898 TALLOC_FREE(fname_dst_parent);
6899 TALLOC_FREE(orig_lcomp_path);
6900 TALLOC_FREE(orig_lcomp_stream);
6903 TALLOC_FREE(smb_fname_dst->stream_name);
6904 smb_fname_dst->stream_name = tmp;
6906 TALLOC_FREE(fname_dst_parent);
6907 TALLOC_FREE(orig_lcomp_path);
6908 TALLOC_FREE(orig_lcomp_stream);
6912 * If the src and dest names are identical - including case,
6913 * don't do the rename, just return success.
6916 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6917 strcsequal(fsp->fsp_name->stream_name,
6918 smb_fname_dst->stream_name)) {
6919 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6920 "- returning success\n",
6921 smb_fname_str_dbg(smb_fname_dst)));
6922 status = NT_STATUS_OK;
6926 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6927 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6929 /* Return the correct error code if both names aren't streams. */
6930 if (!old_is_stream && new_is_stream) {
6931 status = NT_STATUS_OBJECT_NAME_INVALID;
6935 if (old_is_stream && !new_is_stream) {
6936 status = NT_STATUS_INVALID_PARAMETER;
6940 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6942 if(!replace_if_exists && dst_exists) {
6943 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6944 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6945 smb_fname_str_dbg(smb_fname_dst)));
6946 status = NT_STATUS_OBJECT_NAME_COLLISION;
6951 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6952 &smb_fname_dst->st);
6953 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6955 /* The file can be open when renaming a stream */
6956 if (dst_fsp && !new_is_stream) {
6957 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6958 status = NT_STATUS_ACCESS_DENIED;
6963 /* Ensure we have a valid stat struct for the source. */
6964 status = vfs_stat_fsp(fsp);
6965 if (!NT_STATUS_IS_OK(status)) {
6969 status = can_rename(conn, fsp, attrs);
6971 if (!NT_STATUS_IS_OK(status)) {
6972 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6973 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6974 smb_fname_str_dbg(smb_fname_dst)));
6975 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6976 status = NT_STATUS_ACCESS_DENIED;
6980 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6981 status = NT_STATUS_ACCESS_DENIED;
6985 /* Do we have rights to move into the destination ? */
6986 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6987 /* We're moving a directory. */
6988 access_mask = SEC_DIR_ADD_SUBDIR;
6990 status = check_parent_access(conn,
6993 if (!NT_STATUS_IS_OK(status)) {
6994 DBG_INFO("check_parent_access on "
6995 "dst %s returned %s\n",
6996 smb_fname_str_dbg(smb_fname_dst),
7001 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7004 * We have the file open ourselves, so not being able to get the
7005 * corresponding share mode lock is a fatal error.
7008 SMB_ASSERT(lck != NULL);
7010 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
7011 uint32_t create_options = fsp->fh->private_options;
7013 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7014 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7015 smb_fname_str_dbg(smb_fname_dst)));
7017 if (!fsp->is_directory &&
7018 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7019 (lp_map_archive(SNUM(conn)) ||
7020 lp_store_dos_attributes(SNUM(conn)))) {
7021 /* We must set the archive bit on the newly
7023 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7024 uint32_t old_dosmode = dos_mode(conn,
7026 file_set_dosmode(conn,
7028 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7034 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
7037 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7041 * A rename acts as a new file create w.r.t. allowing an initial delete
7042 * on close, probably because in Windows there is a new handle to the
7043 * new file. If initial delete on close was requested but not
7044 * originally set, we need to set it here. This is probably not 100% correct,
7045 * but will work for the CIFSFS client which in non-posix mode
7046 * depends on these semantics. JRA.
7049 if (create_options & FILE_DELETE_ON_CLOSE) {
7050 status = can_set_delete_on_close(fsp, 0);
7052 if (NT_STATUS_IS_OK(status)) {
7053 /* Note that here we set the *initial* delete on close flag,
7054 * not the regular one. The magic gets handled in close. */
7055 fsp->initial_delete_on_close = True;
7059 status = NT_STATUS_OK;
7065 if (errno == ENOTDIR || errno == EISDIR) {
7066 status = NT_STATUS_OBJECT_NAME_COLLISION;
7068 status = map_nt_error_from_unix(errno);
7071 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7072 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7073 smb_fname_str_dbg(smb_fname_dst)));
7076 TALLOC_FREE(smb_fname_dst);
7081 /****************************************************************************
7082 The guts of the rename command, split out so it may be called by the NT SMB
7084 ****************************************************************************/
7086 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7087 connection_struct *conn,
7088 struct smb_request *req,
7089 struct smb_filename *smb_fname_src,
7090 struct smb_filename *smb_fname_dst,
7092 bool replace_if_exists,
7095 uint32_t access_mask)
7097 char *fname_src_dir = NULL;
7098 struct smb_filename *smb_fname_src_dir = NULL;
7099 char *fname_src_mask = NULL;
7101 NTSTATUS status = NT_STATUS_OK;
7102 struct smb_Dir *dir_hnd = NULL;
7103 const char *dname = NULL;
7104 char *talloced = NULL;
7106 int create_options = 0;
7107 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7111 * Split the old name into directory and last component
7112 * strings. Note that unix_convert may have stripped off a
7113 * leading ./ from both name and newname if the rename is
7114 * at the root of the share. We need to make sure either both
7115 * name and newname contain a / character or neither of them do
7116 * as this is checked in resolve_wildcards().
7119 /* Split up the directory from the filename/mask. */
7120 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7121 &fname_src_dir, &fname_src_mask);
7122 if (!NT_STATUS_IS_OK(status)) {
7123 status = NT_STATUS_NO_MEMORY;
7128 * We should only check the mangled cache
7129 * here if unix_convert failed. This means
7130 * that the path in 'mask' doesn't exist
7131 * on the file system and so we need to look
7132 * for a possible mangle. This patch from
7133 * Tine Smukavec <valentin.smukavec@hermes.si>.
7136 if (!VALID_STAT(smb_fname_src->st) &&
7137 mangle_is_mangled(fname_src_mask, conn->params)) {
7138 char *new_mask = NULL;
7139 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7142 TALLOC_FREE(fname_src_mask);
7143 fname_src_mask = new_mask;
7147 if (!src_has_wild) {
7151 * Only one file needs to be renamed. Append the mask back
7152 * onto the directory.
7154 TALLOC_FREE(smb_fname_src->base_name);
7155 if (ISDOT(fname_src_dir)) {
7156 /* Ensure we use canonical names on open. */
7157 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7161 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7166 if (!smb_fname_src->base_name) {
7167 status = NT_STATUS_NO_MEMORY;
7171 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7172 "case_preserve = %d, short case preserve = %d, "
7173 "directory = %s, newname = %s, "
7174 "last_component_dest = %s\n",
7175 conn->case_sensitive, conn->case_preserve,
7176 conn->short_case_preserve,
7177 smb_fname_str_dbg(smb_fname_src),
7178 smb_fname_str_dbg(smb_fname_dst),
7179 smb_fname_dst->original_lcomp));
7181 /* The dest name still may have wildcards. */
7182 if (dest_has_wild) {
7183 char *fname_dst_mod = NULL;
7184 if (!resolve_wildcards(smb_fname_dst,
7185 smb_fname_src->base_name,
7186 smb_fname_dst->base_name,
7188 DEBUG(6, ("rename_internals: resolve_wildcards "
7190 smb_fname_src->base_name,
7191 smb_fname_dst->base_name));
7192 status = NT_STATUS_NO_MEMORY;
7195 TALLOC_FREE(smb_fname_dst->base_name);
7196 smb_fname_dst->base_name = fname_dst_mod;
7199 ZERO_STRUCT(smb_fname_src->st);
7200 if (posix_pathnames) {
7201 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7203 rc = SMB_VFS_STAT(conn, smb_fname_src);
7206 status = map_nt_error_from_unix_common(errno);
7210 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7211 create_options |= FILE_DIRECTORY_FILE;
7214 status = SMB_VFS_CREATE_FILE(
7217 0, /* root_dir_fid */
7218 smb_fname_src, /* fname */
7219 access_mask, /* access_mask */
7220 (FILE_SHARE_READ | /* share_access */
7222 FILE_OPEN, /* create_disposition*/
7223 create_options, /* create_options */
7224 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7225 0, /* oplock_request */
7227 0, /* allocation_size */
7228 0, /* private_flags */
7233 NULL, NULL); /* create context */
7235 if (!NT_STATUS_IS_OK(status)) {
7236 DEBUG(3, ("Could not open rename source %s: %s\n",
7237 smb_fname_str_dbg(smb_fname_src),
7238 nt_errstr(status)));
7242 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7243 attrs, replace_if_exists);
7245 close_file(req, fsp, NORMAL_CLOSE);
7247 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7248 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7249 smb_fname_str_dbg(smb_fname_dst)));
7255 * Wildcards - process each file that matches.
7257 if (strequal(fname_src_mask, "????????.???")) {
7258 TALLOC_FREE(fname_src_mask);
7259 fname_src_mask = talloc_strdup(ctx, "*");
7260 if (!fname_src_mask) {
7261 status = NT_STATUS_NO_MEMORY;
7266 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7270 smb_fname_src->flags);
7271 if (smb_fname_src_dir == NULL) {
7272 status = NT_STATUS_NO_MEMORY;
7276 status = check_name(conn, smb_fname_src_dir);
7277 if (!NT_STATUS_IS_OK(status)) {
7281 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7283 if (dir_hnd == NULL) {
7284 status = map_nt_error_from_unix(errno);
7288 status = NT_STATUS_NO_SUCH_FILE;
7290 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7291 * - gentest fix. JRA
7294 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7296 files_struct *fsp = NULL;
7297 char *destname = NULL;
7298 bool sysdir_entry = False;
7300 /* Quick check for "." and ".." */
7301 if (ISDOT(dname) || ISDOTDOT(dname)) {
7302 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7303 sysdir_entry = True;
7305 TALLOC_FREE(talloced);
7310 if (!is_visible_file(conn, fname_src_dir, dname,
7311 &smb_fname_src->st, false)) {
7312 TALLOC_FREE(talloced);
7316 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7317 TALLOC_FREE(talloced);
7322 status = NT_STATUS_OBJECT_NAME_INVALID;
7326 TALLOC_FREE(smb_fname_src->base_name);
7327 if (ISDOT(fname_src_dir)) {
7328 /* Ensure we use canonical names on open. */
7329 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7333 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7338 if (!smb_fname_src->base_name) {
7339 status = NT_STATUS_NO_MEMORY;
7343 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7344 smb_fname_dst->base_name,
7346 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7347 smb_fname_src->base_name, destname));
7348 TALLOC_FREE(talloced);
7352 status = NT_STATUS_NO_MEMORY;
7356 TALLOC_FREE(smb_fname_dst->base_name);
7357 smb_fname_dst->base_name = destname;
7359 ZERO_STRUCT(smb_fname_src->st);
7360 if (posix_pathnames) {
7361 SMB_VFS_LSTAT(conn, smb_fname_src);
7363 SMB_VFS_STAT(conn, smb_fname_src);
7368 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7369 create_options |= FILE_DIRECTORY_FILE;
7372 status = SMB_VFS_CREATE_FILE(
7375 0, /* root_dir_fid */
7376 smb_fname_src, /* fname */
7377 access_mask, /* access_mask */
7378 (FILE_SHARE_READ | /* share_access */
7380 FILE_OPEN, /* create_disposition*/
7381 create_options, /* create_options */
7382 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7383 0, /* oplock_request */
7385 0, /* allocation_size */
7386 0, /* private_flags */
7391 NULL, NULL); /* create context */
7393 if (!NT_STATUS_IS_OK(status)) {
7394 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7395 "returned %s rename %s -> %s\n",
7397 smb_fname_str_dbg(smb_fname_src),
7398 smb_fname_str_dbg(smb_fname_dst)));
7402 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7404 if (!smb_fname_dst->original_lcomp) {
7405 status = NT_STATUS_NO_MEMORY;
7409 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7410 attrs, replace_if_exists);
7412 close_file(req, fsp, NORMAL_CLOSE);
7414 if (!NT_STATUS_IS_OK(status)) {
7415 DEBUG(3, ("rename_internals_fsp returned %s for "
7416 "rename %s -> %s\n", nt_errstr(status),
7417 smb_fname_str_dbg(smb_fname_src),
7418 smb_fname_str_dbg(smb_fname_dst)));
7424 DEBUG(3,("rename_internals: doing rename on %s -> "
7425 "%s\n", smb_fname_str_dbg(smb_fname_src),
7426 smb_fname_str_dbg(smb_fname_src)));
7427 TALLOC_FREE(talloced);
7429 TALLOC_FREE(dir_hnd);
7431 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7432 status = map_nt_error_from_unix(errno);
7436 TALLOC_FREE(talloced);
7437 TALLOC_FREE(smb_fname_src_dir);
7438 TALLOC_FREE(fname_src_dir);
7439 TALLOC_FREE(fname_src_mask);
7443 /****************************************************************************
7445 ****************************************************************************/
7447 void reply_mv(struct smb_request *req)
7449 connection_struct *conn = req->conn;
7451 char *newname = NULL;
7455 bool src_has_wcard = False;
7456 bool dest_has_wcard = False;
7457 TALLOC_CTX *ctx = talloc_tos();
7458 struct smb_filename *smb_fname_src = NULL;
7459 struct smb_filename *smb_fname_dst = NULL;
7460 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7461 (req->posix_pathnames ?
7462 UCF_UNIX_NAME_LOOKUP :
7463 UCF_COND_ALLOW_WCARD_LCOMP);
7464 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7466 (req->posix_pathnames ?
7468 UCF_COND_ALLOW_WCARD_LCOMP);
7469 bool stream_rename = false;
7471 START_PROFILE(SMBmv);
7474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7478 attrs = SVAL(req->vwv+0, 0);
7480 p = (const char *)req->buf + 1;
7481 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7482 &status, &src_has_wcard);
7483 if (!NT_STATUS_IS_OK(status)) {
7484 reply_nterror(req, status);
7488 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7489 &status, &dest_has_wcard);
7490 if (!NT_STATUS_IS_OK(status)) {
7491 reply_nterror(req, status);
7495 if (!req->posix_pathnames) {
7496 /* The newname must begin with a ':' if the
7497 name contains a ':'. */
7498 if (strchr_m(name, ':')) {
7499 if (newname[0] != ':') {
7500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7503 stream_rename = true;
7507 status = filename_convert(ctx,
7515 if (!NT_STATUS_IS_OK(status)) {
7516 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7517 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7518 ERRSRV, ERRbadpath);
7521 reply_nterror(req, status);
7525 status = filename_convert(ctx,
7533 if (!NT_STATUS_IS_OK(status)) {
7534 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7535 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7536 ERRSRV, ERRbadpath);
7539 reply_nterror(req, status);
7543 if (stream_rename) {
7544 /* smb_fname_dst->base_name must be the same as
7545 smb_fname_src->base_name. */
7546 TALLOC_FREE(smb_fname_dst->base_name);
7547 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7548 smb_fname_src->base_name);
7549 if (!smb_fname_dst->base_name) {
7550 reply_nterror(req, NT_STATUS_NO_MEMORY);
7555 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7556 smb_fname_str_dbg(smb_fname_dst)));
7558 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7559 attrs, False, src_has_wcard, dest_has_wcard,
7561 if (!NT_STATUS_IS_OK(status)) {
7562 if (open_was_deferred(req->xconn, req->mid)) {
7563 /* We have re-scheduled this call. */
7566 reply_nterror(req, status);
7570 reply_outbuf(req, 0, 0);
7572 TALLOC_FREE(smb_fname_src);
7573 TALLOC_FREE(smb_fname_dst);
7578 /*******************************************************************
7579 Copy a file as part of a reply_copy.
7580 ******************************************************************/
7583 * TODO: check error codes on all callers
7586 NTSTATUS copy_file(TALLOC_CTX *ctx,
7587 connection_struct *conn,
7588 struct smb_filename *smb_fname_src,
7589 struct smb_filename *smb_fname_dst,
7592 bool target_is_directory)
7594 struct smb_filename *smb_fname_dst_tmp = NULL;
7596 files_struct *fsp1,*fsp2;
7598 uint32_t new_create_disposition;
7602 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7603 if (smb_fname_dst_tmp == NULL) {
7604 return NT_STATUS_NO_MEMORY;
7608 * If the target is a directory, extract the last component from the
7609 * src filename and append it to the dst filename
7611 if (target_is_directory) {
7614 /* dest/target can't be a stream if it's a directory. */
7615 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7617 p = strrchr_m(smb_fname_src->base_name,'/');
7621 p = smb_fname_src->base_name;
7623 smb_fname_dst_tmp->base_name =
7624 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7626 if (!smb_fname_dst_tmp->base_name) {
7627 status = NT_STATUS_NO_MEMORY;
7632 status = vfs_file_exist(conn, smb_fname_src);
7633 if (!NT_STATUS_IS_OK(status)) {
7637 if (!target_is_directory && count) {
7638 new_create_disposition = FILE_OPEN;
7640 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7643 &new_create_disposition,
7646 status = NT_STATUS_INVALID_PARAMETER;
7651 /* Open the src file for reading. */
7652 status = SMB_VFS_CREATE_FILE(
7655 0, /* root_dir_fid */
7656 smb_fname_src, /* fname */
7657 FILE_GENERIC_READ, /* access_mask */
7658 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7659 FILE_OPEN, /* create_disposition*/
7660 0, /* create_options */
7661 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7662 INTERNAL_OPEN_ONLY, /* oplock_request */
7664 0, /* allocation_size */
7665 0, /* private_flags */
7670 NULL, NULL); /* create context */
7672 if (!NT_STATUS_IS_OK(status)) {
7676 dosattrs = dos_mode(conn, smb_fname_src);
7678 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7679 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7682 /* Open the dst file for writing. */
7683 status = SMB_VFS_CREATE_FILE(
7686 0, /* root_dir_fid */
7687 smb_fname_dst, /* fname */
7688 FILE_GENERIC_WRITE, /* access_mask */
7689 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7690 new_create_disposition, /* create_disposition*/
7691 0, /* create_options */
7692 dosattrs, /* file_attributes */
7693 INTERNAL_OPEN_ONLY, /* oplock_request */
7695 0, /* allocation_size */
7696 0, /* private_flags */
7701 NULL, NULL); /* create context */
7703 if (!NT_STATUS_IS_OK(status)) {
7704 close_file(NULL, fsp1, ERROR_CLOSE);
7708 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7709 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7711 DEBUG(0, ("error - vfs lseek returned error %s\n",
7713 status = map_nt_error_from_unix(errno);
7714 close_file(NULL, fsp1, ERROR_CLOSE);
7715 close_file(NULL, fsp2, ERROR_CLOSE);
7720 /* Do the actual copy. */
7721 if (smb_fname_src->st.st_ex_size) {
7722 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7727 close_file(NULL, fsp1, NORMAL_CLOSE);
7729 /* Ensure the modtime is set correctly on the destination file. */
7730 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7733 * As we are opening fsp1 read-only we only expect
7734 * an error on close on fsp2 if we are out of space.
7735 * Thus we don't look at the error return from the
7738 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7740 if (!NT_STATUS_IS_OK(status)) {
7744 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7745 status = NT_STATUS_DISK_FULL;
7749 status = NT_STATUS_OK;
7752 TALLOC_FREE(smb_fname_dst_tmp);
7756 /****************************************************************************
7757 Reply to a file copy.
7758 ****************************************************************************/
7760 void reply_copy(struct smb_request *req)
7762 connection_struct *conn = req->conn;
7763 struct smb_filename *smb_fname_src = NULL;
7764 struct smb_filename *smb_fname_src_dir = NULL;
7765 struct smb_filename *smb_fname_dst = NULL;
7766 char *fname_src = NULL;
7767 char *fname_dst = NULL;
7768 char *fname_src_mask = NULL;
7769 char *fname_src_dir = NULL;
7772 int error = ERRnoaccess;
7776 bool target_is_directory=False;
7777 bool source_has_wild = False;
7778 bool dest_has_wild = False;
7780 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7781 ucf_flags_from_smb_request(req);
7782 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7783 ucf_flags_from_smb_request(req);
7784 TALLOC_CTX *ctx = talloc_tos();
7786 START_PROFILE(SMBcopy);
7789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7793 tid2 = SVAL(req->vwv+0, 0);
7794 ofun = SVAL(req->vwv+1, 0);
7795 flags = SVAL(req->vwv+2, 0);
7797 p = (const char *)req->buf;
7798 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7799 &status, &source_has_wild);
7800 if (!NT_STATUS_IS_OK(status)) {
7801 reply_nterror(req, status);
7804 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7805 &status, &dest_has_wild);
7806 if (!NT_STATUS_IS_OK(status)) {
7807 reply_nterror(req, status);
7811 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7813 if (tid2 != conn->cnum) {
7814 /* can't currently handle inter share copies XXXX */
7815 DEBUG(3,("Rejecting inter-share copy\n"));
7816 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7820 status = filename_convert(ctx, conn,
7826 if (!NT_STATUS_IS_OK(status)) {
7827 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7828 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7829 ERRSRV, ERRbadpath);
7832 reply_nterror(req, status);
7836 status = filename_convert(ctx, conn,
7842 if (!NT_STATUS_IS_OK(status)) {
7843 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7844 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7845 ERRSRV, ERRbadpath);
7848 reply_nterror(req, status);
7852 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7854 if ((flags&1) && target_is_directory) {
7855 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7859 if ((flags&2) && !target_is_directory) {
7860 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7864 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7865 /* wants a tree copy! XXXX */
7866 DEBUG(3,("Rejecting tree copy\n"));
7867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7871 /* Split up the directory from the filename/mask. */
7872 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7873 &fname_src_dir, &fname_src_mask);
7874 if (!NT_STATUS_IS_OK(status)) {
7875 reply_nterror(req, NT_STATUS_NO_MEMORY);
7880 * We should only check the mangled cache
7881 * here if unix_convert failed. This means
7882 * that the path in 'mask' doesn't exist
7883 * on the file system and so we need to look
7884 * for a possible mangle. This patch from
7885 * Tine Smukavec <valentin.smukavec@hermes.si>.
7887 if (!VALID_STAT(smb_fname_src->st) &&
7888 mangle_is_mangled(fname_src_mask, conn->params)) {
7889 char *new_mask = NULL;
7890 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7891 &new_mask, conn->params);
7893 /* Use demangled name if one was successfully found. */
7895 TALLOC_FREE(fname_src_mask);
7896 fname_src_mask = new_mask;
7900 if (!source_has_wild) {
7903 * Only one file needs to be copied. Append the mask back onto
7906 TALLOC_FREE(smb_fname_src->base_name);
7907 if (ISDOT(fname_src_dir)) {
7908 /* Ensure we use canonical names on open. */
7909 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7913 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7918 if (!smb_fname_src->base_name) {
7919 reply_nterror(req, NT_STATUS_NO_MEMORY);
7923 if (dest_has_wild) {
7924 char *fname_dst_mod = NULL;
7925 if (!resolve_wildcards(smb_fname_dst,
7926 smb_fname_src->base_name,
7927 smb_fname_dst->base_name,
7929 reply_nterror(req, NT_STATUS_NO_MEMORY);
7932 TALLOC_FREE(smb_fname_dst->base_name);
7933 smb_fname_dst->base_name = fname_dst_mod;
7936 status = check_name(conn, smb_fname_src);
7937 if (!NT_STATUS_IS_OK(status)) {
7938 reply_nterror(req, status);
7942 status = check_name(conn, smb_fname_dst);
7943 if (!NT_STATUS_IS_OK(status)) {
7944 reply_nterror(req, status);
7948 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7949 ofun, count, target_is_directory);
7951 if(!NT_STATUS_IS_OK(status)) {
7952 reply_nterror(req, status);
7958 struct smb_Dir *dir_hnd = NULL;
7959 const char *dname = NULL;
7960 char *talloced = NULL;
7964 * There is a wildcard that requires us to actually read the
7965 * src dir and copy each file matching the mask to the dst.
7966 * Right now streams won't be copied, but this could
7967 * presumably be added with a nested loop for reach dir entry.
7969 SMB_ASSERT(!smb_fname_src->stream_name);
7970 SMB_ASSERT(!smb_fname_dst->stream_name);
7972 smb_fname_src->stream_name = NULL;
7973 smb_fname_dst->stream_name = NULL;
7975 if (strequal(fname_src_mask,"????????.???")) {
7976 TALLOC_FREE(fname_src_mask);
7977 fname_src_mask = talloc_strdup(ctx, "*");
7978 if (!fname_src_mask) {
7979 reply_nterror(req, NT_STATUS_NO_MEMORY);
7984 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7988 smb_fname_src->flags);
7989 if (smb_fname_src_dir == NULL) {
7990 reply_nterror(req, NT_STATUS_NO_MEMORY);
7994 status = check_name(conn, smb_fname_src_dir);
7995 if (!NT_STATUS_IS_OK(status)) {
7996 reply_nterror(req, status);
8000 dir_hnd = OpenDir(ctx,
8005 if (dir_hnd == NULL) {
8006 status = map_nt_error_from_unix(errno);
8007 reply_nterror(req, status);
8013 /* Iterate over the src dir copying each entry to the dst. */
8014 while ((dname = ReadDirName(dir_hnd, &offset,
8015 &smb_fname_src->st, &talloced))) {
8016 char *destname = NULL;
8018 if (ISDOT(dname) || ISDOTDOT(dname)) {
8019 TALLOC_FREE(talloced);
8023 if (!is_visible_file(conn, fname_src_dir, dname,
8024 &smb_fname_src->st, false)) {
8025 TALLOC_FREE(talloced);
8029 if(!mask_match(dname, fname_src_mask,
8030 conn->case_sensitive)) {
8031 TALLOC_FREE(talloced);
8035 error = ERRnoaccess;
8037 /* Get the src smb_fname struct setup. */
8038 TALLOC_FREE(smb_fname_src->base_name);
8039 if (ISDOT(fname_src_dir)) {
8040 /* Ensure we use canonical names on open. */
8041 smb_fname_src->base_name =
8042 talloc_asprintf(smb_fname_src, "%s",
8045 smb_fname_src->base_name =
8046 talloc_asprintf(smb_fname_src, "%s/%s",
8047 fname_src_dir, dname);
8050 if (!smb_fname_src->base_name) {
8051 TALLOC_FREE(dir_hnd);
8052 TALLOC_FREE(talloced);
8053 reply_nterror(req, NT_STATUS_NO_MEMORY);
8057 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8058 smb_fname_dst->base_name,
8060 TALLOC_FREE(talloced);
8064 TALLOC_FREE(dir_hnd);
8065 TALLOC_FREE(talloced);
8066 reply_nterror(req, NT_STATUS_NO_MEMORY);
8070 TALLOC_FREE(smb_fname_dst->base_name);
8071 smb_fname_dst->base_name = destname;
8073 status = check_name(conn, smb_fname_src);
8074 if (!NT_STATUS_IS_OK(status)) {
8075 TALLOC_FREE(dir_hnd);
8076 TALLOC_FREE(talloced);
8077 reply_nterror(req, status);
8081 status = check_name(conn, smb_fname_dst);
8082 if (!NT_STATUS_IS_OK(status)) {
8083 TALLOC_FREE(dir_hnd);
8084 TALLOC_FREE(talloced);
8085 reply_nterror(req, status);
8089 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8090 smb_fname_src->base_name,
8091 smb_fname_dst->base_name));
8093 status = copy_file(ctx, conn, smb_fname_src,
8094 smb_fname_dst, ofun, count,
8095 target_is_directory);
8096 if (NT_STATUS_IS_OK(status)) {
8100 TALLOC_FREE(talloced);
8102 TALLOC_FREE(dir_hnd);
8106 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8110 reply_outbuf(req, 1, 0);
8111 SSVAL(req->outbuf,smb_vwv0,count);
8113 TALLOC_FREE(smb_fname_src);
8114 TALLOC_FREE(smb_fname_src_dir);
8115 TALLOC_FREE(smb_fname_dst);
8116 TALLOC_FREE(fname_src);
8117 TALLOC_FREE(fname_dst);
8118 TALLOC_FREE(fname_src_mask);
8119 TALLOC_FREE(fname_src_dir);
8121 END_PROFILE(SMBcopy);
8126 #define DBGC_CLASS DBGC_LOCKING
8128 /****************************************************************************
8129 Get a lock pid, dealing with large count requests.
8130 ****************************************************************************/
8132 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8133 bool large_file_format)
8135 if(!large_file_format)
8136 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8138 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8141 /****************************************************************************
8142 Get a lock count, dealing with large count requests.
8143 ****************************************************************************/
8145 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8146 bool large_file_format)
8150 if(!large_file_format) {
8151 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8154 * No BVAL, this is reversed!
8156 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8157 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8163 /****************************************************************************
8164 Get a lock offset, dealing with large offset requests.
8165 ****************************************************************************/
8167 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8168 bool large_file_format)
8170 uint64_t offset = 0;
8172 if(!large_file_format) {
8173 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8176 * No BVAL, this is reversed!
8178 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8179 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8185 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8187 uint16_t num_ulocks,
8188 struct smbd_lock_element *ulocks,
8189 enum brl_flavour lock_flav)
8191 struct share_mode_lock *lck;
8192 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8195 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8197 for(i = 0; i < num_ulocks; i++) {
8198 struct smbd_lock_element *e = &ulocks[i];
8200 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
8201 "pid %"PRIu64", file %s\n",
8207 if (e->brltype != UNLOCK_LOCK) {
8208 /* this can only happen with SMB2 */
8209 status = NT_STATUS_INVALID_PARAMETER;
8220 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8221 nt_errstr(status)));
8223 if (!NT_STATUS_IS_OK(status)) {
8228 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8232 if (NT_STATUS_IS_OK(status) && (lck != NULL)) {
8233 lck->data->modified = true;
8240 /****************************************************************************
8241 Reply to a lockingX request.
8242 ****************************************************************************/
8244 static void reply_lockingx_done(struct tevent_req *subreq);
8246 void reply_lockingX(struct smb_request *req)
8248 connection_struct *conn = req->conn;
8250 unsigned char locktype;
8251 enum brl_type brltype;
8252 unsigned char oplocklevel;
8253 uint16_t num_ulocks;
8255 int32_t lock_timeout;
8257 const uint8_t *data;
8258 bool large_file_format;
8259 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8260 struct smbd_lock_element *locks = NULL;
8261 struct tevent_req *subreq = NULL;
8263 START_PROFILE(SMBlockingX);
8266 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8267 END_PROFILE(SMBlockingX);
8271 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8272 locktype = CVAL(req->vwv+3, 0);
8273 oplocklevel = CVAL(req->vwv+3, 1);
8274 num_ulocks = SVAL(req->vwv+6, 0);
8275 num_locks = SVAL(req->vwv+7, 0);
8276 lock_timeout = IVAL(req->vwv+4, 0);
8277 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8279 if (!check_fsp(conn, req, fsp)) {
8280 END_PROFILE(SMBlockingX);
8286 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8287 /* we don't support these - and CANCEL_LOCK makes w2k
8288 and XP reboot so I don't really want to be
8289 compatible! (tridge) */
8290 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8291 END_PROFILE(SMBlockingX);
8295 /* Check if this is an oplock break on a file
8296 we have granted an oplock on.
8298 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8299 /* Client can insist on breaking to none. */
8300 bool break_to_none = (oplocklevel == 0);
8303 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8304 "for %s\n", (unsigned int)oplocklevel,
8305 fsp_fnum_dbg(fsp)));
8308 * Make sure we have granted an exclusive or batch oplock on
8312 if (fsp->oplock_type == 0) {
8314 /* The Samba4 nbench simulator doesn't understand
8315 the difference between break to level2 and break
8316 to none from level2 - it sends oplock break
8317 replies in both cases. Don't keep logging an error
8318 message here - just ignore it. JRA. */
8320 DEBUG(5,("reply_lockingX: Error : oplock break from "
8321 "client for %s (oplock=%d) and no "
8322 "oplock granted on this file (%s).\n",
8323 fsp_fnum_dbg(fsp), fsp->oplock_type,
8326 /* if this is a pure oplock break request then don't
8328 if (num_locks == 0 && num_ulocks == 0) {
8329 END_PROFILE(SMBlockingX);
8333 END_PROFILE(SMBlockingX);
8334 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8338 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8340 result = remove_oplock(fsp);
8342 result = downgrade_oplock(fsp);
8346 DEBUG(0, ("reply_lockingX: error in removing "
8347 "oplock on file %s\n", fsp_str_dbg(fsp)));
8348 /* Hmmm. Is this panic justified? */
8349 smb_panic("internal tdb error");
8352 /* if this is a pure oplock break request then don't send a
8354 if (num_locks == 0 && num_ulocks == 0) {
8355 /* Sanity check - ensure a pure oplock break is not a
8357 if (CVAL(req->vwv+0, 0) != 0xff) {
8358 DEBUG(0,("reply_lockingX: Error : pure oplock "
8359 "break is a chained %d request !\n",
8360 (unsigned int)CVAL(req->vwv+0, 0)));
8362 END_PROFILE(SMBlockingX);
8368 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8370 END_PROFILE(SMBlockingX);
8374 if (num_ulocks != 0) {
8375 struct smbd_lock_element *ulocks = NULL;
8378 ulocks = talloc_array(
8379 req, struct smbd_lock_element, num_ulocks);
8380 if (ulocks == NULL) {
8381 reply_nterror(req, NT_STATUS_NO_MEMORY);
8382 END_PROFILE(SMBlockingX);
8387 * Data now points at the beginning of the list of
8388 * smb_unlkrng structs
8390 for (i = 0; i < num_ulocks; i++) {
8391 ulocks[i].smblctx = get_lock_pid(
8392 data, i, large_file_format);
8393 ulocks[i].count = get_lock_count(
8394 data, i, large_file_format);
8395 ulocks[i].offset = get_lock_offset(
8396 data, i, large_file_format);
8397 ulocks[i].brltype = UNLOCK_LOCK;
8401 * Unlock cancels pending locks
8404 ok = smbd_smb1_brl_finish_by_lock(
8411 reply_outbuf(req, 2, 0);
8412 SSVAL(req->outbuf, smb_vwv0, 0xff);
8413 SSVAL(req->outbuf, smb_vwv1, 0);
8414 END_PROFILE(SMBlockingX);
8418 status = smbd_do_unlocking(
8419 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
8420 TALLOC_FREE(ulocks);
8421 if (!NT_STATUS_IS_OK(status)) {
8422 END_PROFILE(SMBlockingX);
8423 reply_nterror(req, status);
8428 /* Now do any requested locks */
8429 data += ((large_file_format ? 20 : 10)*num_ulocks);
8431 /* Data now points at the beginning of the list
8432 of smb_lkrng structs */
8434 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8435 brltype = READ_LOCK;
8437 brltype = WRITE_LOCK;
8440 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8441 if (locks == NULL) {
8442 reply_nterror(req, NT_STATUS_NO_MEMORY);
8443 END_PROFILE(SMBlockingX);
8447 for (i = 0; i < num_locks; i++) {
8448 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8449 locks[i].count = get_lock_count(data, i, large_file_format);
8450 locks[i].offset = get_lock_offset(data, i, large_file_format);
8451 locks[i].brltype = brltype;
8454 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8458 if (num_locks == 0) {
8459 /* See smbtorture3 lock11 test */
8460 reply_outbuf(req, 2, 0);
8461 /* andx chain ends */
8462 SSVAL(req->outbuf, smb_vwv0, 0xff);
8463 SSVAL(req->outbuf, smb_vwv1, 0);
8464 END_PROFILE(SMBlockingX);
8468 ok = smbd_smb1_brl_finish_by_lock(
8472 locks[0], /* Windows only cancels the first lock */
8473 NT_STATUS_FILE_LOCK_CONFLICT);
8476 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
8477 END_PROFILE(SMBlockingX);
8481 reply_outbuf(req, 2, 0);
8482 SSVAL(req->outbuf, smb_vwv0, 0xff);
8483 SSVAL(req->outbuf, smb_vwv1, 0);
8484 END_PROFILE(SMBlockingX);
8488 subreq = smbd_smb1_do_locks_send(
8498 if (subreq == NULL) {
8499 reply_nterror(req, NT_STATUS_NO_MEMORY);
8500 END_PROFILE(SMBlockingX);
8503 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
8504 END_PROFILE(SMBlockingX);
8507 static void reply_lockingx_done(struct tevent_req *subreq)
8509 struct smb_request *req = NULL;
8513 START_PROFILE(SMBlockingX);
8515 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
8518 status = smbd_smb1_do_locks_recv(subreq);
8519 TALLOC_FREE(subreq);
8521 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
8523 if (NT_STATUS_IS_OK(status)) {
8524 reply_outbuf(req, 2, 0);
8525 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8526 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8528 reply_nterror(req, status);
8531 ok = srv_send_smb(req->xconn,
8532 (char *)req->outbuf,
8535 IS_CONN_ENCRYPTED(req->conn),
8538 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
8541 END_PROFILE(SMBlockingX);
8545 #define DBGC_CLASS DBGC_ALL
8547 /****************************************************************************
8548 Reply to a SMBreadbmpx (read block multiplex) request.
8549 Always reply with an error, if someone has a platform really needs this,
8550 please contact vl@samba.org
8551 ****************************************************************************/
8553 void reply_readbmpx(struct smb_request *req)
8555 START_PROFILE(SMBreadBmpx);
8556 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8557 END_PROFILE(SMBreadBmpx);
8561 /****************************************************************************
8562 Reply to a SMBreadbs (read block multiplex secondary) request.
8563 Always reply with an error, if someone has a platform really needs this,
8564 please contact vl@samba.org
8565 ****************************************************************************/
8567 void reply_readbs(struct smb_request *req)
8569 START_PROFILE(SMBreadBs);
8570 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8571 END_PROFILE(SMBreadBs);
8575 /****************************************************************************
8576 Reply to a SMBsetattrE.
8577 ****************************************************************************/
8579 void reply_setattrE(struct smb_request *req)
8581 connection_struct *conn = req->conn;
8582 struct smb_file_time ft;
8586 START_PROFILE(SMBsetattrE);
8590 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8594 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8596 if(!fsp || (fsp->conn != conn)) {
8597 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8602 * Convert the DOS times into unix times.
8605 ft.atime = convert_time_t_to_timespec(
8606 srv_make_unix_date2(req->vwv+3));
8607 ft.mtime = convert_time_t_to_timespec(
8608 srv_make_unix_date2(req->vwv+5));
8609 ft.create_time = convert_time_t_to_timespec(
8610 srv_make_unix_date2(req->vwv+1));
8612 reply_outbuf(req, 0, 0);
8615 * Patch from Ray Frush <frush@engr.colostate.edu>
8616 * Sometimes times are sent as zero - ignore them.
8619 /* Ensure we have a valid stat struct for the source. */
8620 status = vfs_stat_fsp(fsp);
8621 if (!NT_STATUS_IS_OK(status)) {
8622 reply_nterror(req, status);
8626 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8627 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8631 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8632 if (!NT_STATUS_IS_OK(status)) {
8633 reply_nterror(req, status);
8637 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8640 (unsigned int)ft.atime.tv_sec,
8641 (unsigned int)ft.mtime.tv_sec,
8642 (unsigned int)ft.create_time.tv_sec
8645 END_PROFILE(SMBsetattrE);
8650 /* Back from the dead for OS/2..... JRA. */
8652 /****************************************************************************
8653 Reply to a SMBwritebmpx (write block multiplex primary) request.
8654 Always reply with an error, if someone has a platform really needs this,
8655 please contact vl@samba.org
8656 ****************************************************************************/
8658 void reply_writebmpx(struct smb_request *req)
8660 START_PROFILE(SMBwriteBmpx);
8661 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8662 END_PROFILE(SMBwriteBmpx);
8666 /****************************************************************************
8667 Reply to a SMBwritebs (write block multiplex secondary) request.
8668 Always reply with an error, if someone has a platform really needs this,
8669 please contact vl@samba.org
8670 ****************************************************************************/
8672 void reply_writebs(struct smb_request *req)
8674 START_PROFILE(SMBwriteBs);
8675 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8676 END_PROFILE(SMBwriteBs);
8680 /****************************************************************************
8681 Reply to a SMBgetattrE.
8682 ****************************************************************************/
8684 void reply_getattrE(struct smb_request *req)
8686 connection_struct *conn = req->conn;
8689 struct timespec create_ts;
8691 START_PROFILE(SMBgetattrE);
8694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8695 END_PROFILE(SMBgetattrE);
8699 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8701 if(!fsp || (fsp->conn != conn)) {
8702 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8703 END_PROFILE(SMBgetattrE);
8707 /* Do an fstat on this file */
8709 reply_nterror(req, map_nt_error_from_unix(errno));
8710 END_PROFILE(SMBgetattrE);
8714 mode = dos_mode(conn, fsp->fsp_name);
8717 * Convert the times into dos times. Set create
8718 * date to be last modify date as UNIX doesn't save
8722 reply_outbuf(req, 11, 0);
8724 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8725 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8726 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8727 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8728 /* Should we check pending modtime here ? JRA */
8729 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8730 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8732 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8733 SIVAL(req->outbuf, smb_vwv6, 0);
8734 SIVAL(req->outbuf, smb_vwv8, 0);
8736 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8737 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8738 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8740 SSVAL(req->outbuf,smb_vwv10, mode);
8742 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8744 END_PROFILE(SMBgetattrE);