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 "../librpc/gen_ndr/open_files.h"
37 #include "rpc_client/cli_spoolss.h"
38 #include "rpc_client/init_spoolss.h"
39 #include "rpc_server/rpc_ncacn_np.h"
40 #include "libcli/security/security.h"
41 #include "libsmb/nmblib.h"
43 #include "smbprofile.h"
44 #include "../lib/tsocket/tsocket.h"
45 #include "lib/tevent_wait.h"
46 #include "libcli/smb/smb_signing.h"
47 #include "lib/util/sys_rw_data.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 session->global->signing_key.length > 0)
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.data,
1026 MIN(x->global->signing_key.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) {
1042 smb_key_derivation(x->global->application_key.data,
1043 x->global->application_key.length,
1044 x->global->application_key.data);
1045 optional_support |= SMB_EXTENDED_SIGNATURES;
1049 * Place the application key into the session_info
1051 data_blob_clear_free(&session_info->session_key);
1052 session_info->session_key = data_blob_dup_talloc(session_info,
1053 x->global->application_key);
1054 if (session_info->session_key.data == NULL) {
1055 data_blob_clear_free(&x->global->application_key);
1056 reply_nterror(req, NT_STATUS_NO_MEMORY);
1057 END_PROFILE(SMBtconX);
1060 session_key_updated = true;
1063 conn = make_connection(req, now, service, client_devicetype,
1064 req->vuid, &nt_status);
1068 if (session_key_updated) {
1069 struct smbXsrv_session *x = session;
1070 struct auth_session_info *session_info =
1071 session->global->auth_session_info;
1072 data_blob_clear_free(&x->global->application_key);
1073 data_blob_clear_free(&session_info->session_key);
1075 reply_nterror(req, nt_status);
1076 END_PROFILE(SMBtconX);
1081 server_devicetype = "IPC";
1082 else if ( IS_PRINT(conn) )
1083 server_devicetype = "LPT1:";
1085 server_devicetype = "A:";
1087 if (get_Protocol() < PROTOCOL_NT1) {
1088 reply_outbuf(req, 2, 0);
1089 if (message_push_string(&req->outbuf, server_devicetype,
1090 STR_TERMINATE|STR_ASCII) == -1) {
1091 reply_nterror(req, NT_STATUS_NO_MEMORY);
1092 END_PROFILE(SMBtconX);
1096 /* NT sets the fstype of IPC$ to the null string */
1097 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1099 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1100 /* Return permissions. */
1104 reply_outbuf(req, 7, 0);
1107 perm1 = FILE_ALL_ACCESS;
1108 perm2 = FILE_ALL_ACCESS;
1110 perm1 = conn->share_access;
1113 SIVAL(req->outbuf, smb_vwv3, perm1);
1114 SIVAL(req->outbuf, smb_vwv5, perm2);
1116 reply_outbuf(req, 3, 0);
1119 if ((message_push_string(&req->outbuf, server_devicetype,
1120 STR_TERMINATE|STR_ASCII) == -1)
1121 || (message_push_string(&req->outbuf, fstype,
1122 STR_TERMINATE) == -1)) {
1123 reply_nterror(req, NT_STATUS_NO_MEMORY);
1124 END_PROFILE(SMBtconX);
1128 /* what does setting this bit do? It is set by NT4 and
1129 may affect the ability to autorun mounted cdroms */
1130 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1132 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1134 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1135 DEBUG(2,("Serving %s as a Dfs root\n",
1136 lp_servicename(ctx, SNUM(conn)) ));
1137 optional_support |= SMB_SHARE_IN_DFS;
1140 SSVAL(req->outbuf, smb_vwv2, optional_support);
1143 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1144 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1146 DEBUG(3,("tconX service=%s \n",
1149 /* set the incoming and outgoing tid to the just created one */
1150 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1151 SSVAL(req->outbuf,smb_tid,conn->cnum);
1153 END_PROFILE(SMBtconX);
1155 req->tid = conn->cnum;
1158 /****************************************************************************
1159 Reply to an unknown type.
1160 ****************************************************************************/
1162 void reply_unknown_new(struct smb_request *req, uint8_t type)
1164 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1165 smb_fn_name(type), type, type));
1166 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1170 /****************************************************************************
1172 conn POINTER CAN BE NULL HERE !
1173 ****************************************************************************/
1175 void reply_ioctl(struct smb_request *req)
1177 connection_struct *conn = req->conn;
1180 uint32_t ioctl_code;
1184 START_PROFILE(SMBioctl);
1187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1188 END_PROFILE(SMBioctl);
1192 device = SVAL(req->vwv+1, 0);
1193 function = SVAL(req->vwv+2, 0);
1194 ioctl_code = (device << 16) + function;
1196 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1198 switch (ioctl_code) {
1199 case IOCTL_QUERY_JOB_INFO:
1203 reply_force_doserror(req, ERRSRV, ERRnosupport);
1204 END_PROFILE(SMBioctl);
1208 reply_outbuf(req, 8, replysize+1);
1209 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1210 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1211 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1212 p = smb_buf(req->outbuf);
1213 memset(p, '\0', replysize+1); /* valgrind-safe. */
1214 p += 1; /* Allow for alignment */
1216 switch (ioctl_code) {
1217 case IOCTL_QUERY_JOB_INFO:
1221 files_struct *fsp = file_fsp(
1222 req, SVAL(req->vwv+0, 0));
1224 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1225 END_PROFILE(SMBioctl);
1229 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1231 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1232 lp_netbios_name(), 15,
1233 STR_TERMINATE|STR_ASCII, &len);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 reply_nterror(req, status);
1236 END_PROFILE(SMBioctl);
1240 status = srvstr_push((char *)req->outbuf, req->flags2,
1242 lp_servicename(talloc_tos(),
1244 13, STR_TERMINATE|STR_ASCII, &len);
1245 if (!NT_STATUS_IS_OK(status)) {
1246 reply_nterror(req, status);
1247 END_PROFILE(SMBioctl);
1251 memset(p+18, 0, 13);
1257 END_PROFILE(SMBioctl);
1261 /****************************************************************************
1262 Strange checkpath NTSTATUS mapping.
1263 ****************************************************************************/
1265 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1267 /* Strange DOS error code semantics only for checkpath... */
1268 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1269 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1270 /* We need to map to ERRbadpath */
1271 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1277 /****************************************************************************
1278 Reply to a checkpath.
1279 ****************************************************************************/
1281 void reply_checkpath(struct smb_request *req)
1283 connection_struct *conn = req->conn;
1284 struct smb_filename *smb_fname = NULL;
1287 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1288 TALLOC_CTX *ctx = talloc_tos();
1290 START_PROFILE(SMBcheckpath);
1292 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1293 STR_TERMINATE, &status);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 status = map_checkpath_error(req->flags2, status);
1297 reply_nterror(req, status);
1298 END_PROFILE(SMBcheckpath);
1302 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1304 status = filename_convert(ctx,
1311 if (!NT_STATUS_IS_OK(status)) {
1312 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1313 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1314 ERRSRV, ERRbadpath);
1315 END_PROFILE(SMBcheckpath);
1321 if (!VALID_STAT(smb_fname->st) &&
1322 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1323 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1324 smb_fname_str_dbg(smb_fname), strerror(errno)));
1325 status = map_nt_error_from_unix(errno);
1329 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1330 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1331 ERRDOS, ERRbadpath);
1335 reply_outbuf(req, 0, 0);
1338 /* We special case this - as when a Windows machine
1339 is parsing a path is steps through the components
1340 one at a time - if a component fails it expects
1341 ERRbadpath, not ERRbadfile.
1343 status = map_checkpath_error(req->flags2, status);
1344 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1346 * Windows returns different error codes if
1347 * the parent directory is valid but not the
1348 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1349 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1350 * if the path is invalid.
1352 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1353 ERRDOS, ERRbadpath);
1357 reply_nterror(req, status);
1360 TALLOC_FREE(smb_fname);
1361 END_PROFILE(SMBcheckpath);
1365 /****************************************************************************
1367 ****************************************************************************/
1369 void reply_getatr(struct smb_request *req)
1371 connection_struct *conn = req->conn;
1372 struct smb_filename *smb_fname = NULL;
1379 TALLOC_CTX *ctx = talloc_tos();
1380 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1382 START_PROFILE(SMBgetatr);
1384 p = (const char *)req->buf + 1;
1385 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1386 if (!NT_STATUS_IS_OK(status)) {
1387 reply_nterror(req, status);
1391 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1392 under WfWg - weird! */
1393 if (*fname == '\0') {
1394 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1395 if (!CAN_WRITE(conn)) {
1396 mode |= FILE_ATTRIBUTE_READONLY;
1401 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1402 status = filename_convert(ctx,
1408 if (!NT_STATUS_IS_OK(status)) {
1409 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1410 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1411 ERRSRV, ERRbadpath);
1414 reply_nterror(req, status);
1417 if (!VALID_STAT(smb_fname->st) &&
1418 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1419 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1420 smb_fname_str_dbg(smb_fname),
1422 reply_nterror(req, map_nt_error_from_unix(errno));
1426 mode = dos_mode(conn, smb_fname);
1427 size = smb_fname->st.st_ex_size;
1429 if (ask_sharemode) {
1430 struct timespec write_time_ts;
1431 struct file_id fileid;
1433 ZERO_STRUCT(write_time_ts);
1434 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1435 get_file_infos(fileid, 0, NULL, &write_time_ts);
1436 if (!null_timespec(write_time_ts)) {
1437 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1441 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1442 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1447 reply_outbuf(req, 10, 0);
1449 SSVAL(req->outbuf,smb_vwv0,mode);
1450 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1451 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1453 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1455 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1457 if (get_Protocol() >= PROTOCOL_NT1) {
1458 SSVAL(req->outbuf, smb_flg2,
1459 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1462 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1463 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1466 TALLOC_FREE(smb_fname);
1468 END_PROFILE(SMBgetatr);
1472 /****************************************************************************
1474 ****************************************************************************/
1476 void reply_setatr(struct smb_request *req)
1478 struct smb_file_time ft;
1479 connection_struct *conn = req->conn;
1480 struct smb_filename *smb_fname = NULL;
1486 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1487 TALLOC_CTX *ctx = talloc_tos();
1489 START_PROFILE(SMBsetatr);
1494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1498 p = (const char *)req->buf + 1;
1499 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1500 if (!NT_STATUS_IS_OK(status)) {
1501 reply_nterror(req, status);
1505 status = filename_convert(ctx,
1511 if (!NT_STATUS_IS_OK(status)) {
1512 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1513 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1514 ERRSRV, ERRbadpath);
1517 reply_nterror(req, status);
1521 if (smb_fname->base_name[0] == '.' &&
1522 smb_fname->base_name[1] == '\0') {
1524 * Not sure here is the right place to catch this
1525 * condition. Might be moved to somewhere else later -- vl
1527 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1531 mode = SVAL(req->vwv+0, 0);
1532 mtime = srv_make_unix_date3(req->vwv+1);
1534 if (mode != FILE_ATTRIBUTE_NORMAL) {
1535 if (VALID_STAT_OF_DIR(smb_fname->st))
1536 mode |= FILE_ATTRIBUTE_DIRECTORY;
1538 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1540 status = check_access(conn, NULL, smb_fname,
1541 FILE_WRITE_ATTRIBUTES);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 reply_nterror(req, status);
1547 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1549 reply_nterror(req, map_nt_error_from_unix(errno));
1554 ft.mtime = convert_time_t_to_timespec(mtime);
1555 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1556 if (!NT_STATUS_IS_OK(status)) {
1557 reply_nterror(req, status);
1561 reply_outbuf(req, 0, 0);
1563 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1566 TALLOC_FREE(smb_fname);
1567 END_PROFILE(SMBsetatr);
1571 /****************************************************************************
1573 ****************************************************************************/
1575 void reply_dskattr(struct smb_request *req)
1577 connection_struct *conn = req->conn;
1579 uint64_t dfree,dsize,bsize;
1580 struct smb_filename smb_fname;
1581 START_PROFILE(SMBdskattr);
1583 ZERO_STRUCT(smb_fname);
1584 smb_fname.base_name = discard_const_p(char, ".");
1586 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1587 reply_nterror(req, map_nt_error_from_unix(errno));
1588 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1589 END_PROFILE(SMBdskattr);
1593 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1594 if (ret == (uint64_t)-1) {
1595 reply_nterror(req, map_nt_error_from_unix(errno));
1596 END_PROFILE(SMBdskattr);
1601 * Force max to fit in 16 bit fields.
1603 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1607 if (bsize > (WORDMAX*512)) {
1608 bsize = (WORDMAX*512);
1609 if (dsize > WORDMAX)
1611 if (dfree > WORDMAX)
1617 reply_outbuf(req, 5, 0);
1619 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1620 double total_space, free_space;
1621 /* we need to scale this to a number that DOS6 can handle. We
1622 use floating point so we can handle large drives on systems
1623 that don't have 64 bit integers
1625 we end up displaying a maximum of 2G to DOS systems
1627 total_space = dsize * (double)bsize;
1628 free_space = dfree * (double)bsize;
1630 dsize = (uint64_t)((total_space+63*512) / (64*512));
1631 dfree = (uint64_t)((free_space+63*512) / (64*512));
1633 if (dsize > 0xFFFF) dsize = 0xFFFF;
1634 if (dfree > 0xFFFF) dfree = 0xFFFF;
1636 SSVAL(req->outbuf,smb_vwv0,dsize);
1637 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1638 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1639 SSVAL(req->outbuf,smb_vwv3,dfree);
1641 SSVAL(req->outbuf,smb_vwv0,dsize);
1642 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1643 SSVAL(req->outbuf,smb_vwv2,512);
1644 SSVAL(req->outbuf,smb_vwv3,dfree);
1647 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1649 END_PROFILE(SMBdskattr);
1654 * Utility function to split the filename from the directory.
1656 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1657 char **fname_dir_out,
1658 char **fname_mask_out)
1660 const char *p = NULL;
1661 char *fname_dir = NULL;
1662 char *fname_mask = NULL;
1664 p = strrchr_m(fname_in, '/');
1666 fname_dir = talloc_strdup(ctx, ".");
1667 fname_mask = talloc_strdup(ctx, fname_in);
1669 fname_dir = talloc_strndup(ctx, fname_in,
1670 PTR_DIFF(p, fname_in));
1671 fname_mask = talloc_strdup(ctx, p+1);
1674 if (!fname_dir || !fname_mask) {
1675 TALLOC_FREE(fname_dir);
1676 TALLOC_FREE(fname_mask);
1677 return NT_STATUS_NO_MEMORY;
1680 *fname_dir_out = fname_dir;
1681 *fname_mask_out = fname_mask;
1682 return NT_STATUS_OK;
1685 /****************************************************************************
1687 ****************************************************************************/
1689 static bool make_dir_struct(TALLOC_CTX *ctx,
1699 char *mask2 = talloc_strdup(ctx, mask);
1705 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1709 memset(buf+1,' ',11);
1710 if ((p = strchr_m(mask2,'.')) != NULL) {
1712 push_ascii(buf+1,mask2,8, 0);
1713 push_ascii(buf+9,p+1,3, 0);
1716 push_ascii(buf+1,mask2,11, 0);
1719 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1721 srv_put_dos_date(buf,22,date);
1722 SSVAL(buf,26,size & 0xFFFF);
1723 SSVAL(buf,28,(size >> 16)&0xFFFF);
1724 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1725 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1726 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1727 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1731 /****************************************************************************
1733 Can be called from SMBsearch, SMBffirst or SMBfunique.
1734 ****************************************************************************/
1736 void reply_search(struct smb_request *req)
1738 connection_struct *conn = req->conn;
1741 char *directory = NULL;
1742 struct smb_filename *smb_fname = NULL;
1746 struct timespec date;
1748 unsigned int numentries = 0;
1749 unsigned int maxentries = 0;
1750 bool finished = False;
1755 bool check_descend = False;
1756 bool expect_close = False;
1758 bool mask_contains_wcard = False;
1759 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1760 TALLOC_CTX *ctx = talloc_tos();
1761 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1762 struct dptr_struct *dirptr = NULL;
1763 struct smbXsrv_connection *xconn = req->xconn;
1764 struct smbd_server_connection *sconn = req->sconn;
1766 START_PROFILE(SMBsearch);
1769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1773 if (req->posix_pathnames) {
1774 reply_unknown_new(req, req->cmd);
1778 /* If we were called as SMBffirst then we must expect close. */
1779 if(req->cmd == SMBffirst) {
1780 expect_close = True;
1783 reply_outbuf(req, 1, 3);
1784 maxentries = SVAL(req->vwv+0, 0);
1785 dirtype = SVAL(req->vwv+1, 0);
1786 p = (const char *)req->buf + 1;
1787 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1788 &nt_status, &mask_contains_wcard);
1789 if (!NT_STATUS_IS_OK(nt_status)) {
1790 reply_nterror(req, nt_status);
1795 status_len = SVAL(p, 0);
1798 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1800 if (status_len == 0) {
1801 struct smb_filename *smb_dname = NULL;
1802 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1803 ucf_flags_from_smb_request(req);
1804 nt_status = filename_convert(ctx, conn,
1807 &mask_contains_wcard,
1809 if (!NT_STATUS_IS_OK(nt_status)) {
1810 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1811 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1812 ERRSRV, ERRbadpath);
1815 reply_nterror(req, nt_status);
1819 directory = smb_fname->base_name;
1821 p = strrchr_m(directory,'/');
1822 if ((p != NULL) && (*directory != '/')) {
1823 mask = talloc_strdup(ctx, p + 1);
1824 directory = talloc_strndup(ctx, directory,
1825 PTR_DIFF(p, directory));
1827 mask = talloc_strdup(ctx, directory);
1828 directory = talloc_strdup(ctx,".");
1832 reply_nterror(req, NT_STATUS_NO_MEMORY);
1836 memset((char *)status,'\0',21);
1837 SCVAL(status,0,(dirtype & 0x1F));
1839 smb_dname = synthetic_smb_fname(talloc_tos(),
1844 if (smb_dname == NULL) {
1845 reply_nterror(req, NT_STATUS_NO_MEMORY);
1849 nt_status = dptr_create(conn,
1857 mask_contains_wcard,
1861 TALLOC_FREE(smb_dname);
1863 if (!NT_STATUS_IS_OK(nt_status)) {
1864 reply_nterror(req, nt_status);
1867 dptr_num = dptr_dnum(dirptr);
1870 const char *dirpath;
1872 memcpy(status,p,21);
1873 status_dirtype = CVAL(status,0) & 0x1F;
1874 if (status_dirtype != (dirtype & 0x1F)) {
1875 dirtype = status_dirtype;
1878 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1882 dirpath = dptr_path(sconn, dptr_num);
1883 directory = talloc_strdup(ctx, dirpath);
1885 reply_nterror(req, NT_STATUS_NO_MEMORY);
1889 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1894 * For a 'continue' search we have no string. So
1895 * check from the initial saved string.
1897 if (!req->posix_pathnames) {
1898 mask_contains_wcard = ms_has_wild(mask);
1900 dirtype = dptr_attr(sconn, dptr_num);
1903 DEBUG(4,("dptr_num is %d\n",dptr_num));
1905 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1906 char buf[DIR_STRUCT_SIZE];
1907 memcpy(buf,status,21);
1908 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1909 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1910 reply_nterror(req, NT_STATUS_NO_MEMORY);
1913 dptr_fill(sconn, buf+12,dptr_num);
1914 if (dptr_zero(buf+12) && (status_len==0)) {
1919 if (message_push_blob(&req->outbuf,
1920 data_blob_const(buf, sizeof(buf)))
1922 reply_nterror(req, NT_STATUS_NO_MEMORY);
1927 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1928 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1930 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1932 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1933 directory,lp_dont_descend(ctx, SNUM(conn))));
1934 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1935 check_descend = True;
1938 for (i=numentries;(i<maxentries) && !finished;i++) {
1939 finished = !get_dir_entry(ctx,
1950 char buf[DIR_STRUCT_SIZE];
1951 memcpy(buf,status,21);
1952 if (!make_dir_struct(ctx,
1958 convert_timespec_to_time_t(date),
1959 !allow_long_path_components)) {
1960 reply_nterror(req, NT_STATUS_NO_MEMORY);
1963 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1966 if (message_push_blob(&req->outbuf,
1967 data_blob_const(buf, sizeof(buf)))
1969 reply_nterror(req, NT_STATUS_NO_MEMORY);
1979 /* If we were called as SMBffirst with smb_search_id == NULL
1980 and no entries were found then return error and close dirptr
1983 if (numentries == 0) {
1984 dptr_close(sconn, &dptr_num);
1985 } else if(expect_close && status_len == 0) {
1986 /* Close the dptr - we know it's gone */
1987 dptr_close(sconn, &dptr_num);
1990 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1991 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1992 dptr_close(sconn, &dptr_num);
1995 if ((numentries == 0) && !mask_contains_wcard) {
1996 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2000 SSVAL(req->outbuf,smb_vwv0,numentries);
2001 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2002 SCVAL(smb_buf(req->outbuf),0,5);
2003 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2005 /* The replies here are never long name. */
2006 SSVAL(req->outbuf, smb_flg2,
2007 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2008 if (!allow_long_path_components) {
2009 SSVAL(req->outbuf, smb_flg2,
2010 SVAL(req->outbuf, smb_flg2)
2011 & (~FLAGS2_LONG_PATH_COMPONENTS));
2014 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2015 SSVAL(req->outbuf, smb_flg2,
2016 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2018 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2019 smb_fn_name(req->cmd),
2026 TALLOC_FREE(directory);
2028 TALLOC_FREE(smb_fname);
2029 END_PROFILE(SMBsearch);
2033 /****************************************************************************
2034 Reply to a fclose (stop directory search).
2035 ****************************************************************************/
2037 void reply_fclose(struct smb_request *req)
2045 bool path_contains_wcard = False;
2046 TALLOC_CTX *ctx = talloc_tos();
2047 struct smbd_server_connection *sconn = req->sconn;
2049 START_PROFILE(SMBfclose);
2051 if (req->posix_pathnames) {
2052 reply_unknown_new(req, req->cmd);
2053 END_PROFILE(SMBfclose);
2057 p = (const char *)req->buf + 1;
2058 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2059 &err, &path_contains_wcard);
2060 if (!NT_STATUS_IS_OK(err)) {
2061 reply_nterror(req, err);
2062 END_PROFILE(SMBfclose);
2066 status_len = SVAL(p,0);
2069 if (status_len == 0) {
2070 reply_force_doserror(req, ERRSRV, ERRsrverror);
2071 END_PROFILE(SMBfclose);
2075 memcpy(status,p,21);
2077 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2078 /* Close the dptr - we know it's gone */
2079 dptr_close(sconn, &dptr_num);
2082 reply_outbuf(req, 1, 0);
2083 SSVAL(req->outbuf,smb_vwv0,0);
2085 DEBUG(3,("search close\n"));
2087 END_PROFILE(SMBfclose);
2091 /****************************************************************************
2093 ****************************************************************************/
2095 void reply_open(struct smb_request *req)
2097 connection_struct *conn = req->conn;
2098 struct smb_filename *smb_fname = NULL;
2108 uint32_t access_mask;
2109 uint32_t share_mode;
2110 uint32_t create_disposition;
2111 uint32_t create_options = 0;
2112 uint32_t private_flags = 0;
2115 TALLOC_CTX *ctx = talloc_tos();
2117 START_PROFILE(SMBopen);
2120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2124 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2125 deny_mode = SVAL(req->vwv+0, 0);
2126 dos_attr = SVAL(req->vwv+1, 0);
2128 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2129 STR_TERMINATE, &status);
2130 if (!NT_STATUS_IS_OK(status)) {
2131 reply_nterror(req, status);
2135 if (!map_open_params_to_ntcreate(fname, deny_mode,
2136 OPENX_FILE_EXISTS_OPEN, &access_mask,
2137 &share_mode, &create_disposition,
2138 &create_options, &private_flags)) {
2139 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2143 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2145 status = filename_convert(ctx,
2151 if (!NT_STATUS_IS_OK(status)) {
2152 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2153 reply_botherror(req,
2154 NT_STATUS_PATH_NOT_COVERED,
2155 ERRSRV, ERRbadpath);
2158 reply_nterror(req, status);
2162 status = SMB_VFS_CREATE_FILE(
2165 0, /* root_dir_fid */
2166 smb_fname, /* fname */
2167 access_mask, /* access_mask */
2168 share_mode, /* share_access */
2169 create_disposition, /* create_disposition*/
2170 create_options, /* create_options */
2171 dos_attr, /* file_attributes */
2172 oplock_request, /* oplock_request */
2174 0, /* allocation_size */
2180 NULL, NULL); /* create context */
2182 if (!NT_STATUS_IS_OK(status)) {
2183 if (open_was_deferred(req->xconn, req->mid)) {
2184 /* We have re-scheduled this call. */
2187 reply_openerror(req, status);
2191 /* Ensure we're pointing at the correct stat struct. */
2192 TALLOC_FREE(smb_fname);
2193 smb_fname = fsp->fsp_name;
2195 size = smb_fname->st.st_ex_size;
2196 fattr = dos_mode(conn, smb_fname);
2198 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2200 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2201 DEBUG(3,("attempt to open a directory %s\n",
2203 close_file(req, fsp, ERROR_CLOSE);
2204 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2205 ERRDOS, ERRnoaccess);
2209 reply_outbuf(req, 7, 0);
2210 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2211 SSVAL(req->outbuf,smb_vwv1,fattr);
2212 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2213 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2215 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2217 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2218 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2220 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2221 SCVAL(req->outbuf,smb_flg,
2222 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2225 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2226 SCVAL(req->outbuf,smb_flg,
2227 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2230 END_PROFILE(SMBopen);
2234 /****************************************************************************
2235 Reply to an open and X.
2236 ****************************************************************************/
2238 void reply_open_and_X(struct smb_request *req)
2240 connection_struct *conn = req->conn;
2241 struct smb_filename *smb_fname = NULL;
2243 uint16_t open_flags;
2246 /* Breakout the oplock request bits so we can set the
2247 reply bits separately. */
2248 int ex_oplock_request;
2249 int core_oplock_request;
2252 int smb_sattr = SVAL(req->vwv+4, 0);
2253 uint32_t smb_time = make_unix_date3(req->vwv+6);
2261 uint64_t allocation_size;
2262 ssize_t retval = -1;
2263 uint32_t access_mask;
2264 uint32_t share_mode;
2265 uint32_t create_disposition;
2266 uint32_t create_options = 0;
2267 uint32_t private_flags = 0;
2269 TALLOC_CTX *ctx = talloc_tos();
2271 START_PROFILE(SMBopenX);
2273 if (req->wct < 15) {
2274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2278 open_flags = SVAL(req->vwv+2, 0);
2279 deny_mode = SVAL(req->vwv+3, 0);
2280 smb_attr = SVAL(req->vwv+5, 0);
2281 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2282 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2283 oplock_request = ex_oplock_request | core_oplock_request;
2284 smb_ofun = SVAL(req->vwv+8, 0);
2285 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2287 /* If it's an IPC, pass off the pipe handler. */
2289 if (lp_nt_pipe_support()) {
2290 reply_open_pipe_and_X(conn, req);
2292 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2297 /* XXXX we need to handle passed times, sattr and flags */
2298 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2299 STR_TERMINATE, &status);
2300 if (!NT_STATUS_IS_OK(status)) {
2301 reply_nterror(req, status);
2305 if (!map_open_params_to_ntcreate(fname, deny_mode,
2307 &access_mask, &share_mode,
2308 &create_disposition,
2311 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2315 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2317 status = filename_convert(ctx,
2323 if (!NT_STATUS_IS_OK(status)) {
2324 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2325 reply_botherror(req,
2326 NT_STATUS_PATH_NOT_COVERED,
2327 ERRSRV, ERRbadpath);
2330 reply_nterror(req, status);
2334 status = SMB_VFS_CREATE_FILE(
2337 0, /* root_dir_fid */
2338 smb_fname, /* fname */
2339 access_mask, /* access_mask */
2340 share_mode, /* share_access */
2341 create_disposition, /* create_disposition*/
2342 create_options, /* create_options */
2343 smb_attr, /* file_attributes */
2344 oplock_request, /* oplock_request */
2346 0, /* allocation_size */
2351 &smb_action, /* pinfo */
2352 NULL, NULL); /* create context */
2354 if (!NT_STATUS_IS_OK(status)) {
2355 if (open_was_deferred(req->xconn, req->mid)) {
2356 /* We have re-scheduled this call. */
2359 reply_openerror(req, status);
2363 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2364 if the file is truncated or created. */
2365 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2366 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2367 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2368 close_file(req, fsp, ERROR_CLOSE);
2369 reply_nterror(req, NT_STATUS_DISK_FULL);
2372 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2374 close_file(req, fsp, ERROR_CLOSE);
2375 reply_nterror(req, NT_STATUS_DISK_FULL);
2378 status = vfs_stat_fsp(fsp);
2379 if (!NT_STATUS_IS_OK(status)) {
2380 close_file(req, fsp, ERROR_CLOSE);
2381 reply_nterror(req, status);
2386 fattr = dos_mode(conn, fsp->fsp_name);
2387 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2388 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2389 close_file(req, fsp, ERROR_CLOSE);
2390 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2394 /* If the caller set the extended oplock request bit
2395 and we granted one (by whatever means) - set the
2396 correct bit for extended oplock reply.
2399 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2400 smb_action |= EXTENDED_OPLOCK_GRANTED;
2403 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2404 smb_action |= EXTENDED_OPLOCK_GRANTED;
2407 /* If the caller set the core oplock request bit
2408 and we granted one (by whatever means) - set the
2409 correct bit for core oplock reply.
2412 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2413 reply_outbuf(req, 19, 0);
2415 reply_outbuf(req, 15, 0);
2418 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2419 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2421 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2422 SCVAL(req->outbuf, smb_flg,
2423 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2426 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2427 SCVAL(req->outbuf, smb_flg,
2428 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2431 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2432 SSVAL(req->outbuf,smb_vwv3,fattr);
2433 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2434 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2436 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2438 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2439 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2440 SSVAL(req->outbuf,smb_vwv11,smb_action);
2442 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2443 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2447 TALLOC_FREE(smb_fname);
2448 END_PROFILE(SMBopenX);
2452 /****************************************************************************
2453 Reply to a SMBulogoffX.
2454 ****************************************************************************/
2456 void reply_ulogoffX(struct smb_request *req)
2458 struct smbd_server_connection *sconn = req->sconn;
2459 struct user_struct *vuser;
2460 struct smbXsrv_session *session = NULL;
2463 START_PROFILE(SMBulogoffX);
2465 vuser = get_valid_user_struct(sconn, req->vuid);
2468 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2469 (unsigned long long)req->vuid));
2471 req->vuid = UID_FIELD_INVALID;
2472 reply_force_doserror(req, ERRSRV, ERRbaduid);
2473 END_PROFILE(SMBulogoffX);
2477 session = vuser->session;
2481 * TODO: cancel all outstanding requests on the session
2483 status = smbXsrv_session_logoff(session);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 DEBUG(0, ("reply_ulogoff: "
2486 "smbXsrv_session_logoff() failed: %s\n",
2487 nt_errstr(status)));
2489 * If we hit this case, there is something completely
2490 * wrong, so we better disconnect the transport connection.
2492 END_PROFILE(SMBulogoffX);
2493 exit_server(__location__ ": smbXsrv_session_logoff failed");
2497 TALLOC_FREE(session);
2499 reply_outbuf(req, 2, 0);
2500 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2501 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2503 DEBUG(3, ("ulogoffX vuid=%llu\n",
2504 (unsigned long long)req->vuid));
2506 END_PROFILE(SMBulogoffX);
2507 req->vuid = UID_FIELD_INVALID;
2510 /****************************************************************************
2511 Reply to a mknew or a create.
2512 ****************************************************************************/
2514 void reply_mknew(struct smb_request *req)
2516 connection_struct *conn = req->conn;
2517 struct smb_filename *smb_fname = NULL;
2520 struct smb_file_time ft;
2522 int oplock_request = 0;
2524 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2525 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2526 uint32_t create_disposition;
2527 uint32_t create_options = 0;
2529 TALLOC_CTX *ctx = talloc_tos();
2531 START_PROFILE(SMBcreate);
2535 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2539 fattr = SVAL(req->vwv+0, 0);
2540 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2542 if (req->cmd == SMBmknew) {
2543 /* We should fail if file exists. */
2544 create_disposition = FILE_CREATE;
2546 /* Create if file doesn't exist, truncate if it does. */
2547 create_disposition = FILE_OVERWRITE_IF;
2551 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2553 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2554 STR_TERMINATE, &status);
2555 if (!NT_STATUS_IS_OK(status)) {
2556 reply_nterror(req, status);
2560 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2561 status = filename_convert(ctx,
2567 if (!NT_STATUS_IS_OK(status)) {
2568 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2569 reply_botherror(req,
2570 NT_STATUS_PATH_NOT_COVERED,
2571 ERRSRV, ERRbadpath);
2574 reply_nterror(req, status);
2578 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2579 DEBUG(0,("Attempt to create file (%s) with volid set - "
2580 "please report this\n",
2581 smb_fname_str_dbg(smb_fname)));
2584 status = SMB_VFS_CREATE_FILE(
2587 0, /* root_dir_fid */
2588 smb_fname, /* fname */
2589 access_mask, /* access_mask */
2590 share_mode, /* share_access */
2591 create_disposition, /* create_disposition*/
2592 create_options, /* create_options */
2593 fattr, /* file_attributes */
2594 oplock_request, /* oplock_request */
2596 0, /* allocation_size */
2597 0, /* private_flags */
2602 NULL, NULL); /* create context */
2604 if (!NT_STATUS_IS_OK(status)) {
2605 if (open_was_deferred(req->xconn, req->mid)) {
2606 /* We have re-scheduled this call. */
2609 reply_openerror(req, status);
2613 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2614 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2615 if (!NT_STATUS_IS_OK(status)) {
2616 END_PROFILE(SMBcreate);
2620 reply_outbuf(req, 1, 0);
2621 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2623 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2624 SCVAL(req->outbuf,smb_flg,
2625 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2628 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2629 SCVAL(req->outbuf,smb_flg,
2630 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2633 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2634 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2635 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2636 (unsigned int)fattr));
2639 TALLOC_FREE(smb_fname);
2640 END_PROFILE(SMBcreate);
2644 /****************************************************************************
2645 Reply to a create temporary file.
2646 ****************************************************************************/
2648 void reply_ctemp(struct smb_request *req)
2650 connection_struct *conn = req->conn;
2651 struct smb_filename *smb_fname = NULL;
2652 char *wire_name = NULL;
2661 TALLOC_CTX *ctx = talloc_tos();
2663 START_PROFILE(SMBctemp);
2666 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2670 fattr = SVAL(req->vwv+0, 0);
2671 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2673 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2674 STR_TERMINATE, &status);
2675 if (!NT_STATUS_IS_OK(status)) {
2676 reply_nterror(req, status);
2680 for (i = 0; i < 10; i++) {
2682 fname = talloc_asprintf(ctx,
2685 generate_random_str_list(ctx, 5, "0123456789"));
2687 fname = talloc_asprintf(ctx,
2689 generate_random_str_list(ctx, 5, "0123456789"));
2693 reply_nterror(req, NT_STATUS_NO_MEMORY);
2697 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2698 status = filename_convert(ctx, conn,
2703 if (!NT_STATUS_IS_OK(status)) {
2704 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2705 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2706 ERRSRV, ERRbadpath);
2709 reply_nterror(req, status);
2713 /* Create the file. */
2714 status = SMB_VFS_CREATE_FILE(
2717 0, /* root_dir_fid */
2718 smb_fname, /* fname */
2719 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2720 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2721 FILE_CREATE, /* create_disposition*/
2722 0, /* create_options */
2723 fattr, /* file_attributes */
2724 oplock_request, /* oplock_request */
2726 0, /* allocation_size */
2727 0, /* private_flags */
2732 NULL, NULL); /* create context */
2734 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2736 TALLOC_FREE(smb_fname);
2740 if (!NT_STATUS_IS_OK(status)) {
2741 if (open_was_deferred(req->xconn, req->mid)) {
2742 /* We have re-scheduled this call. */
2745 reply_openerror(req, status);
2753 /* Collision after 10 times... */
2754 reply_nterror(req, status);
2758 reply_outbuf(req, 1, 0);
2759 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2761 /* the returned filename is relative to the directory */
2762 s = strrchr_m(fsp->fsp_name->base_name, '/');
2764 s = fsp->fsp_name->base_name;
2770 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2771 thing in the byte section. JRA */
2772 SSVALS(p, 0, -1); /* what is this? not in spec */
2774 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2776 reply_nterror(req, NT_STATUS_NO_MEMORY);
2780 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2781 SCVAL(req->outbuf, smb_flg,
2782 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2785 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2786 SCVAL(req->outbuf, smb_flg,
2787 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2790 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2791 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2792 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2794 TALLOC_FREE(smb_fname);
2795 TALLOC_FREE(wire_name);
2796 END_PROFILE(SMBctemp);
2800 /*******************************************************************
2801 Check if a user is allowed to rename a file.
2802 ********************************************************************/
2804 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2807 if (!CAN_WRITE(conn)) {
2808 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2811 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2812 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2813 /* Only bother to read the DOS attribute if we might deny the
2814 rename on the grounds of attribute mismatch. */
2815 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2816 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2817 return NT_STATUS_NO_SUCH_FILE;
2821 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2822 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2823 return NT_STATUS_OK;
2826 /* If no pathnames are open below this
2827 directory, allow the rename. */
2829 if (lp_strict_rename(SNUM(conn))) {
2831 * Strict rename, check open file db.
2833 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2834 return NT_STATUS_ACCESS_DENIED;
2836 } else if (file_find_subpath(fsp)) {
2838 * No strict rename, just look in local process.
2840 return NT_STATUS_ACCESS_DENIED;
2842 return NT_STATUS_OK;
2845 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2846 return NT_STATUS_OK;
2849 return NT_STATUS_ACCESS_DENIED;
2852 /*******************************************************************
2853 * unlink a file with all relevant access checks
2854 *******************************************************************/
2856 static NTSTATUS do_unlink(connection_struct *conn,
2857 struct smb_request *req,
2858 struct smb_filename *smb_fname,
2863 uint32_t dirtype_orig = dirtype;
2866 bool posix_paths = (req != NULL && req->posix_pathnames);
2868 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2869 smb_fname_str_dbg(smb_fname),
2872 if (!CAN_WRITE(conn)) {
2873 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2877 ret = SMB_VFS_LSTAT(conn, smb_fname);
2879 ret = SMB_VFS_STAT(conn, smb_fname);
2882 return map_nt_error_from_unix(errno);
2885 fattr = dos_mode(conn, smb_fname);
2887 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2888 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2891 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2893 return NT_STATUS_NO_SUCH_FILE;
2896 if (!dir_check_ftype(fattr, dirtype)) {
2897 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2898 return NT_STATUS_FILE_IS_A_DIRECTORY;
2900 return NT_STATUS_NO_SUCH_FILE;
2903 if (dirtype_orig & 0x8000) {
2904 /* These will never be set for POSIX. */
2905 return NT_STATUS_NO_SUCH_FILE;
2909 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2910 return NT_STATUS_FILE_IS_A_DIRECTORY;
2913 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2914 return NT_STATUS_NO_SUCH_FILE;
2917 if (dirtype & 0xFF00) {
2918 /* These will never be set for POSIX. */
2919 return NT_STATUS_NO_SUCH_FILE;
2924 return NT_STATUS_NO_SUCH_FILE;
2927 /* Can't delete a directory. */
2928 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2929 return NT_STATUS_FILE_IS_A_DIRECTORY;
2934 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2935 return NT_STATUS_OBJECT_NAME_INVALID;
2936 #endif /* JRATEST */
2938 /* On open checks the open itself will check the share mode, so
2939 don't do it here as we'll get it wrong. */
2941 status = SMB_VFS_CREATE_FILE
2944 0, /* root_dir_fid */
2945 smb_fname, /* fname */
2946 DELETE_ACCESS, /* access_mask */
2947 FILE_SHARE_NONE, /* share_access */
2948 FILE_OPEN, /* create_disposition*/
2949 FILE_NON_DIRECTORY_FILE, /* create_options */
2950 /* file_attributes */
2951 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2952 FILE_ATTRIBUTE_NORMAL,
2953 0, /* oplock_request */
2955 0, /* allocation_size */
2956 0, /* private_flags */
2961 NULL, NULL); /* create context */
2963 if (!NT_STATUS_IS_OK(status)) {
2964 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2965 nt_errstr(status)));
2969 status = can_set_delete_on_close(fsp, fattr);
2970 if (!NT_STATUS_IS_OK(status)) {
2971 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2973 smb_fname_str_dbg(smb_fname),
2974 nt_errstr(status)));
2975 close_file(req, fsp, NORMAL_CLOSE);
2979 /* The set is across all open files on this dev/inode pair. */
2980 if (!set_delete_on_close(fsp, True,
2981 conn->session_info->security_token,
2982 conn->session_info->unix_token)) {
2983 close_file(req, fsp, NORMAL_CLOSE);
2984 return NT_STATUS_ACCESS_DENIED;
2987 return close_file(req, fsp, NORMAL_CLOSE);
2990 /****************************************************************************
2991 The guts of the unlink command, split out so it may be called by the NT SMB
2993 ****************************************************************************/
2995 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2996 uint32_t dirtype, struct smb_filename *smb_fname,
2999 char *fname_dir = NULL;
3000 char *fname_mask = NULL;
3002 NTSTATUS status = NT_STATUS_OK;
3003 struct smb_filename *smb_fname_dir = NULL;
3004 TALLOC_CTX *ctx = talloc_tos();
3006 /* Split up the directory from the filename/mask. */
3007 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3008 &fname_dir, &fname_mask);
3009 if (!NT_STATUS_IS_OK(status)) {
3014 * We should only check the mangled cache
3015 * here if unix_convert failed. This means
3016 * that the path in 'mask' doesn't exist
3017 * on the file system and so we need to look
3018 * for a possible mangle. This patch from
3019 * Tine Smukavec <valentin.smukavec@hermes.si>.
3022 if (!VALID_STAT(smb_fname->st) &&
3023 mangle_is_mangled(fname_mask, conn->params)) {
3024 char *new_mask = NULL;
3025 mangle_lookup_name_from_8_3(ctx, fname_mask,
3026 &new_mask, conn->params);
3028 TALLOC_FREE(fname_mask);
3029 fname_mask = new_mask;
3036 * Only one file needs to be unlinked. Append the mask back
3037 * onto the directory.
3039 TALLOC_FREE(smb_fname->base_name);
3040 if (ISDOT(fname_dir)) {
3041 /* Ensure we use canonical names on open. */
3042 smb_fname->base_name = talloc_asprintf(smb_fname,
3046 smb_fname->base_name = talloc_asprintf(smb_fname,
3051 if (!smb_fname->base_name) {
3052 status = NT_STATUS_NO_MEMORY;
3056 dirtype = FILE_ATTRIBUTE_NORMAL;
3059 status = check_name(conn, smb_fname);
3060 if (!NT_STATUS_IS_OK(status)) {
3064 status = do_unlink(conn, req, smb_fname, dirtype);
3065 if (!NT_STATUS_IS_OK(status)) {
3071 struct smb_Dir *dir_hnd = NULL;
3073 const char *dname = NULL;
3074 char *talloced = NULL;
3076 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3077 status = NT_STATUS_OBJECT_NAME_INVALID;
3081 dirtype = FILE_ATTRIBUTE_NORMAL;
3084 if (strequal(fname_mask,"????????.???")) {
3085 TALLOC_FREE(fname_mask);
3086 fname_mask = talloc_strdup(ctx, "*");
3088 status = NT_STATUS_NO_MEMORY;
3093 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3098 if (smb_fname_dir == NULL) {
3099 status = NT_STATUS_NO_MEMORY;
3103 status = check_name(conn, smb_fname_dir);
3104 if (!NT_STATUS_IS_OK(status)) {
3108 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3110 if (dir_hnd == NULL) {
3111 status = map_nt_error_from_unix(errno);
3115 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3116 the pattern matches against the long name, otherwise the short name
3117 We don't implement this yet XXXX
3120 status = NT_STATUS_NO_SUCH_FILE;
3122 while ((dname = ReadDirName(dir_hnd, &offset,
3123 &smb_fname->st, &talloced))) {
3124 TALLOC_CTX *frame = talloc_stackframe();
3126 if (!is_visible_file(conn, fname_dir, dname,
3127 &smb_fname->st, true)) {
3129 TALLOC_FREE(talloced);
3133 /* Quick check for "." and ".." */
3134 if (ISDOT(dname) || ISDOTDOT(dname)) {
3136 TALLOC_FREE(talloced);
3140 if(!mask_match(dname, fname_mask,
3141 conn->case_sensitive)) {
3143 TALLOC_FREE(talloced);
3147 TALLOC_FREE(smb_fname->base_name);
3148 if (ISDOT(fname_dir)) {
3149 /* Ensure we use canonical names on open. */
3150 smb_fname->base_name =
3151 talloc_asprintf(smb_fname, "%s",
3154 smb_fname->base_name =
3155 talloc_asprintf(smb_fname, "%s/%s",
3159 if (!smb_fname->base_name) {
3160 TALLOC_FREE(dir_hnd);
3161 status = NT_STATUS_NO_MEMORY;
3163 TALLOC_FREE(talloced);
3167 status = check_name(conn, smb_fname);
3168 if (!NT_STATUS_IS_OK(status)) {
3169 TALLOC_FREE(dir_hnd);
3171 TALLOC_FREE(talloced);
3175 status = do_unlink(conn, req, smb_fname, dirtype);
3176 if (!NT_STATUS_IS_OK(status)) {
3177 TALLOC_FREE(dir_hnd);
3179 TALLOC_FREE(talloced);
3184 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3185 smb_fname->base_name));
3188 TALLOC_FREE(talloced);
3190 TALLOC_FREE(dir_hnd);
3193 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3194 status = map_nt_error_from_unix(errno);
3198 TALLOC_FREE(smb_fname_dir);
3199 TALLOC_FREE(fname_dir);
3200 TALLOC_FREE(fname_mask);
3204 /****************************************************************************
3206 ****************************************************************************/
3208 void reply_unlink(struct smb_request *req)
3210 connection_struct *conn = req->conn;
3212 struct smb_filename *smb_fname = NULL;
3215 bool path_contains_wcard = False;
3216 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3217 ucf_flags_from_smb_request(req);
3218 TALLOC_CTX *ctx = talloc_tos();
3220 START_PROFILE(SMBunlink);
3223 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3227 dirtype = SVAL(req->vwv+0, 0);
3229 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3230 STR_TERMINATE, &status,
3231 &path_contains_wcard);
3232 if (!NT_STATUS_IS_OK(status)) {
3233 reply_nterror(req, status);
3237 status = filename_convert(ctx, conn,
3240 &path_contains_wcard,
3242 if (!NT_STATUS_IS_OK(status)) {
3243 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3244 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3245 ERRSRV, ERRbadpath);
3248 reply_nterror(req, status);
3252 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3254 status = unlink_internals(conn, req, dirtype, smb_fname,
3255 path_contains_wcard);
3256 if (!NT_STATUS_IS_OK(status)) {
3257 if (open_was_deferred(req->xconn, req->mid)) {
3258 /* We have re-scheduled this call. */
3261 reply_nterror(req, status);
3265 reply_outbuf(req, 0, 0);
3267 TALLOC_FREE(smb_fname);
3268 END_PROFILE(SMBunlink);
3272 /****************************************************************************
3274 ****************************************************************************/
3276 static void fail_readraw(void)
3278 const char *errstr = talloc_asprintf(talloc_tos(),
3279 "FAIL ! reply_readbraw: socket write fail (%s)",
3284 exit_server_cleanly(errstr);
3287 /****************************************************************************
3288 Fake (read/write) sendfile. Returns -1 on read or write fail.
3289 ****************************************************************************/
3291 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3292 off_t startpos, size_t nread)
3295 size_t tosend = nread;
3302 bufsize = MIN(nread, 65536);
3304 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3308 while (tosend > 0) {
3312 cur_read = MIN(tosend, bufsize);
3313 ret = read_file(fsp,buf,startpos,cur_read);
3319 /* If we had a short read, fill with zeros. */
3320 if (ret < cur_read) {
3321 memset(buf + ret, '\0', cur_read - ret);
3324 ret = write_data(xconn->transport.sock, buf, cur_read);
3325 if (ret != cur_read) {
3326 int saved_errno = errno;
3328 * Try and give an error message saying what
3331 DEBUG(0, ("write_data failed for client %s. "
3333 smbXsrv_connection_dbg(xconn),
3334 strerror(saved_errno)));
3336 errno = saved_errno;
3340 startpos += cur_read;
3344 return (ssize_t)nread;
3347 /****************************************************************************
3348 Deal with the case of sendfile reading less bytes from the file than
3349 requested. Fill with zeros (all we can do). Returns 0 on success
3350 ****************************************************************************/
3352 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3358 #define SHORT_SEND_BUFSIZE 1024
3359 if (nread < headersize) {
3360 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3361 "header for file %s (%s). Terminating\n",
3362 fsp_str_dbg(fsp), strerror(errno)));
3366 nread -= headersize;
3368 if (nread < smb_maxcnt) {
3369 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3371 DEBUG(0,("sendfile_short_send: malloc failed "
3372 "for file %s (%s). Terminating\n",
3373 fsp_str_dbg(fsp), strerror(errno)));
3377 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3378 "with zeros !\n", fsp_str_dbg(fsp)));
3380 while (nread < smb_maxcnt) {
3382 * We asked for the real file size and told sendfile
3383 * to not go beyond the end of the file. But it can
3384 * happen that in between our fstat call and the
3385 * sendfile call the file was truncated. This is very
3386 * bad because we have already announced the larger
3387 * number of bytes to the client.
3389 * The best we can do now is to send 0-bytes, just as
3390 * a read from a hole in a sparse file would do.
3392 * This should happen rarely enough that I don't care
3393 * about efficiency here :-)
3398 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3399 ret = write_data(xconn->transport.sock, buf, to_write);
3400 if (ret != to_write) {
3401 int saved_errno = errno;
3403 * Try and give an error message saying what
3406 DEBUG(0, ("write_data failed for client %s. "
3408 smbXsrv_connection_dbg(xconn),
3409 strerror(saved_errno)));
3410 errno = saved_errno;
3421 /****************************************************************************
3422 Return a readbraw error (4 bytes of zero).
3423 ****************************************************************************/
3425 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3431 smbd_lock_socket(xconn);
3432 if (write_data(xconn->transport.sock,header,4) != 4) {
3433 int saved_errno = errno;
3435 * Try and give an error message saying what
3438 DEBUG(0, ("write_data failed for client %s. "
3440 smbXsrv_connection_dbg(xconn),
3441 strerror(saved_errno)));
3442 errno = saved_errno;
3446 smbd_unlock_socket(xconn);
3449 /****************************************************************************
3450 Use sendfile in readbraw.
3451 ****************************************************************************/
3453 static void send_file_readbraw(connection_struct *conn,
3454 struct smb_request *req,
3460 struct smbXsrv_connection *xconn = req->xconn;
3461 char *outbuf = NULL;
3465 * We can only use sendfile on a non-chained packet
3466 * but we can use on a non-oplocked file. tridge proved this
3467 * on a train in Germany :-). JRA.
3468 * reply_readbraw has already checked the length.
3471 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3472 (fsp->wcp == NULL) &&
3473 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3474 ssize_t sendfile_read = -1;
3476 DATA_BLOB header_blob;
3478 _smb_setlen(header,nread);
3479 header_blob = data_blob_const(header, 4);
3481 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3482 &header_blob, startpos,
3484 if (sendfile_read == -1) {
3485 /* Returning ENOSYS means no data at all was sent.
3486 * Do this as a normal read. */
3487 if (errno == ENOSYS) {
3488 goto normal_readbraw;
3492 * Special hack for broken Linux with no working sendfile. If we
3493 * return EINTR we sent the header but not the rest of the data.
3494 * Fake this up by doing read/write calls.
3496 if (errno == EINTR) {
3497 /* Ensure we don't do this again. */
3498 set_use_sendfile(SNUM(conn), False);
3499 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3501 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3502 DEBUG(0,("send_file_readbraw: "
3503 "fake_sendfile failed for "
3507 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3512 DEBUG(0,("send_file_readbraw: sendfile failed for "
3513 "file %s (%s). Terminating\n",
3514 fsp_str_dbg(fsp), strerror(errno)));
3515 exit_server_cleanly("send_file_readbraw sendfile failed");
3516 } else if (sendfile_read == 0) {
3518 * Some sendfile implementations return 0 to indicate
3519 * that there was a short read, but nothing was
3520 * actually written to the socket. In this case,
3521 * fallback to the normal read path so the header gets
3522 * the correct byte count.
3524 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3525 "bytes falling back to the normal read: "
3526 "%s\n", fsp_str_dbg(fsp)));
3527 goto normal_readbraw;
3530 /* Deal with possible short send. */
3531 if (sendfile_read != 4+nread) {
3532 ret = sendfile_short_send(xconn, fsp,
3533 sendfile_read, 4, nread);
3543 outbuf = talloc_array(NULL, char, nread+4);
3545 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3546 (unsigned)(nread+4)));
3547 reply_readbraw_error(xconn);
3552 ret = read_file(fsp,outbuf+4,startpos,nread);
3553 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3562 _smb_setlen(outbuf,ret);
3563 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3564 int saved_errno = errno;
3566 * Try and give an error message saying what
3569 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3570 smbXsrv_connection_dbg(xconn),
3571 strerror(saved_errno)));
3572 errno = saved_errno;
3577 TALLOC_FREE(outbuf);
3580 /****************************************************************************
3581 Reply to a readbraw (core+ protocol).
3582 ****************************************************************************/
3584 void reply_readbraw(struct smb_request *req)
3586 connection_struct *conn = req->conn;
3587 struct smbXsrv_connection *xconn = req->xconn;
3588 ssize_t maxcount,mincount;
3592 struct lock_struct lock;
3595 START_PROFILE(SMBreadbraw);
3597 if (srv_is_signing_active(xconn) || req->encrypted) {
3598 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3599 "raw reads/writes are disallowed.");
3603 reply_readbraw_error(xconn);
3604 END_PROFILE(SMBreadbraw);
3608 if (xconn->smb1.echo_handler.trusted_fde) {
3609 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3610 "'async smb echo handler = yes'\n"));
3611 reply_readbraw_error(xconn);
3612 END_PROFILE(SMBreadbraw);
3617 * Special check if an oplock break has been issued
3618 * and the readraw request croses on the wire, we must
3619 * return a zero length response here.
3622 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3625 * We have to do a check_fsp by hand here, as
3626 * we must always return 4 zero bytes on error,
3630 if (!fsp || !conn || conn != fsp->conn ||
3631 req->vuid != fsp->vuid ||
3632 fsp->is_directory || fsp->fh->fd == -1) {
3634 * fsp could be NULL here so use the value from the packet. JRA.
3636 DEBUG(3,("reply_readbraw: fnum %d not valid "
3638 (int)SVAL(req->vwv+0, 0)));
3639 reply_readbraw_error(xconn);
3640 END_PROFILE(SMBreadbraw);
3644 /* Do a "by hand" version of CHECK_READ. */
3645 if (!(fsp->can_read ||
3646 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3647 (fsp->access_mask & FILE_EXECUTE)))) {
3648 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3649 (int)SVAL(req->vwv+0, 0)));
3650 reply_readbraw_error(xconn);
3651 END_PROFILE(SMBreadbraw);
3655 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3657 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3658 if(req->wct == 10) {
3660 * This is a large offset (64 bit) read.
3663 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3666 DEBUG(0,("reply_readbraw: negative 64 bit "
3667 "readraw offset (%.0f) !\n",
3668 (double)startpos ));
3669 reply_readbraw_error(xconn);
3670 END_PROFILE(SMBreadbraw);
3675 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3676 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3678 /* ensure we don't overrun the packet size */
3679 maxcount = MIN(65535,maxcount);
3681 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3682 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3685 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3686 reply_readbraw_error(xconn);
3687 END_PROFILE(SMBreadbraw);
3691 if (fsp_stat(fsp) == 0) {
3692 size = fsp->fsp_name->st.st_ex_size;
3695 if (startpos >= size) {
3698 nread = MIN(maxcount,(size - startpos));
3701 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3702 if (nread < mincount)
3706 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3707 "min=%lu nread=%lu\n",
3708 fsp_fnum_dbg(fsp), (double)startpos,
3709 (unsigned long)maxcount,
3710 (unsigned long)mincount,
3711 (unsigned long)nread ) );
3713 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3715 DEBUG(5,("reply_readbraw finished\n"));
3717 END_PROFILE(SMBreadbraw);
3722 #define DBGC_CLASS DBGC_LOCKING
3724 /****************************************************************************
3725 Reply to a lockread (core+ protocol).
3726 ****************************************************************************/
3728 void reply_lockread(struct smb_request *req)
3730 connection_struct *conn = req->conn;
3738 struct byte_range_lock *br_lck = NULL;
3740 struct smbXsrv_connection *xconn = req->xconn;
3742 START_PROFILE(SMBlockread);
3745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3746 END_PROFILE(SMBlockread);
3750 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3752 if (!check_fsp(conn, req, fsp)) {
3753 END_PROFILE(SMBlockread);
3757 if (!CHECK_READ(fsp,req)) {
3758 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3759 END_PROFILE(SMBlockread);
3763 numtoread = SVAL(req->vwv+1, 0);
3764 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3767 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3768 * protocol request that predates the read/write lock concept.
3769 * Thus instead of asking for a read lock here we need to ask
3770 * for a write lock. JRA.
3771 * Note that the requested lock size is unaffected by max_send.
3774 br_lck = do_lock(req->sconn->msg_ctx,
3776 (uint64_t)req->smbpid,
3777 (uint64_t)numtoread,
3781 False, /* Non-blocking lock. */
3784 TALLOC_FREE(br_lck);
3786 if (NT_STATUS_V(status)) {
3787 reply_nterror(req, status);
3788 END_PROFILE(SMBlockread);
3793 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3795 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3797 if (numtoread > maxtoread) {
3798 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3799 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3800 (unsigned int)numtoread, (unsigned int)maxtoread,
3801 (unsigned int)xconn->smb1.sessions.max_send));
3802 numtoread = maxtoread;
3805 reply_outbuf(req, 5, numtoread + 3);
3807 data = smb_buf(req->outbuf) + 3;
3809 nread = read_file(fsp,data,startpos,numtoread);
3812 reply_nterror(req, map_nt_error_from_unix(errno));
3813 END_PROFILE(SMBlockread);
3817 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3819 SSVAL(req->outbuf,smb_vwv0,nread);
3820 SSVAL(req->outbuf,smb_vwv5,nread+3);
3821 p = smb_buf(req->outbuf);
3822 SCVAL(p,0,0); /* pad byte. */
3825 DEBUG(3,("lockread %s num=%d nread=%d\n",
3826 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3828 END_PROFILE(SMBlockread);
3833 #define DBGC_CLASS DBGC_ALL
3835 /****************************************************************************
3837 ****************************************************************************/
3839 void reply_read(struct smb_request *req)
3841 connection_struct *conn = req->conn;
3848 struct lock_struct lock;
3849 struct smbXsrv_connection *xconn = req->xconn;
3851 START_PROFILE(SMBread);
3854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3855 END_PROFILE(SMBread);
3859 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3861 if (!check_fsp(conn, req, fsp)) {
3862 END_PROFILE(SMBread);
3866 if (!CHECK_READ(fsp,req)) {
3867 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3868 END_PROFILE(SMBread);
3872 numtoread = SVAL(req->vwv+1, 0);
3873 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3876 * The requested read size cannot be greater than max_send. JRA.
3878 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3880 if (numtoread > maxtoread) {
3881 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3882 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3883 (unsigned int)numtoread, (unsigned int)maxtoread,
3884 (unsigned int)xconn->smb1.sessions.max_send));
3885 numtoread = maxtoread;
3888 reply_outbuf(req, 5, numtoread+3);
3890 data = smb_buf(req->outbuf) + 3;
3892 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3893 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3896 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3897 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3898 END_PROFILE(SMBread);
3903 nread = read_file(fsp,data,startpos,numtoread);
3906 reply_nterror(req, map_nt_error_from_unix(errno));
3910 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3912 SSVAL(req->outbuf,smb_vwv0,nread);
3913 SSVAL(req->outbuf,smb_vwv5,nread+3);
3914 SCVAL(smb_buf(req->outbuf),0,1);
3915 SSVAL(smb_buf(req->outbuf),1,nread);
3917 DEBUG(3, ("read %s num=%d nread=%d\n",
3918 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3921 END_PROFILE(SMBread);
3925 /****************************************************************************
3927 ****************************************************************************/
3929 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3933 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3936 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3938 SCVAL(outbuf,smb_vwv0,0xFF);
3939 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3940 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3941 SSVAL(outbuf,smb_vwv6,
3942 (smb_wct - 4) /* offset from smb header to wct */
3943 + 1 /* the wct field */
3944 + 12 * sizeof(uint16_t) /* vwv */
3945 + 2 /* the buflen field */
3946 + 1); /* padding byte */
3947 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3948 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3949 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3950 _smb_setlen_large(outbuf,
3951 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3955 /****************************************************************************
3956 Reply to a read and X - possibly using sendfile.
3957 ****************************************************************************/
3959 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3960 files_struct *fsp, off_t startpos,
3963 struct smbXsrv_connection *xconn = req->xconn;
3965 struct lock_struct lock;
3966 int saved_errno = 0;
3968 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3969 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3972 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3973 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3978 * We can only use sendfile on a non-chained packet
3979 * but we can use on a non-oplocked file. tridge proved this
3980 * on a train in Germany :-). JRA.
3983 if (!req_is_in_chain(req) &&
3985 (fsp->base_fsp == NULL) &&
3986 (fsp->wcp == NULL) &&
3987 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3988 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3991 if(fsp_stat(fsp) == -1) {
3992 reply_nterror(req, map_nt_error_from_unix(errno));
3996 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3997 (startpos > fsp->fsp_name->st.st_ex_size) ||
3998 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4000 * We already know that we would do a short read, so don't
4001 * try the sendfile() path.
4003 goto nosendfile_read;
4007 * Set up the packet header before send. We
4008 * assume here the sendfile will work (get the
4009 * correct amount of data).
4012 header = data_blob_const(headerbuf, sizeof(headerbuf));
4014 construct_reply_common_req(req, (char *)headerbuf);
4015 setup_readX_header((char *)headerbuf, smb_maxcnt);
4017 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4018 startpos, smb_maxcnt);
4020 saved_errno = errno;
4022 /* Returning ENOSYS means no data at all was sent.
4023 Do this as a normal read. */
4024 if (errno == ENOSYS) {
4029 * Special hack for broken Linux with no working sendfile. If we
4030 * return EINTR we sent the header but not the rest of the data.
4031 * Fake this up by doing read/write calls.
4034 if (errno == EINTR) {
4035 /* Ensure we don't do this again. */
4036 set_use_sendfile(SNUM(conn), False);
4037 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4038 nread = fake_sendfile(xconn, fsp, startpos,
4041 saved_errno = errno;
4042 DEBUG(0,("send_file_readX: "
4043 "fake_sendfile failed for "
4044 "file %s (%s) for client %s. "
4047 smbXsrv_connection_dbg(xconn),
4048 strerror(saved_errno)));
4049 errno = saved_errno;
4050 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4052 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4053 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4054 /* No outbuf here means successful sendfile. */
4058 DEBUG(0,("send_file_readX: sendfile failed for file "
4059 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4061 exit_server_cleanly("send_file_readX sendfile failed");
4062 } else if (nread == 0) {
4064 * Some sendfile implementations return 0 to indicate
4065 * that there was a short read, but nothing was
4066 * actually written to the socket. In this case,
4067 * fallback to the normal read path so the header gets
4068 * the correct byte count.
4070 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4071 "falling back to the normal read: %s\n",
4076 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4077 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4079 /* Deal with possible short send. */
4080 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4083 ret = sendfile_short_send(xconn, fsp, nread,
4084 sizeof(headerbuf), smb_maxcnt);
4087 r = "send_file_readX: sendfile_short_send failed";
4088 DEBUG(0,("%s for file %s (%s).\n",
4089 r, fsp_str_dbg(fsp), strerror(errno)));
4090 exit_server_cleanly(r);
4093 /* No outbuf here means successful sendfile. */
4094 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4095 SMB_PERFCOUNT_END(&req->pcd);
4101 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4102 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4105 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4106 (startpos > fsp->fsp_name->st.st_ex_size) ||
4107 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4109 * We already know that we would do a short
4110 * read, so don't try the sendfile() path.
4112 goto nosendfile_read;
4115 construct_reply_common_req(req, (char *)headerbuf);
4116 setup_readX_header((char *)headerbuf, smb_maxcnt);
4118 /* Send out the header. */
4119 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4121 if (ret != sizeof(headerbuf)) {
4122 saved_errno = errno;
4124 * Try and give an error message saying what
4127 DEBUG(0,("send_file_readX: write_data failed for file "
4128 "%s (%s) for client %s. Terminating\n",
4130 smbXsrv_connection_dbg(xconn),
4131 strerror(saved_errno)));
4132 errno = saved_errno;
4133 exit_server_cleanly("send_file_readX sendfile failed");
4135 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4137 saved_errno = errno;
4138 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4139 "%s (%s) for client %s. Terminating\n",
4141 smbXsrv_connection_dbg(xconn),
4142 strerror(saved_errno)));
4143 errno = saved_errno;
4144 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4151 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4152 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4153 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4155 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4156 startpos, smb_maxcnt);
4157 saved_errno = errno;
4160 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4164 setup_readX_header((char *)req->outbuf, nread);
4166 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4167 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4171 TALLOC_FREE(req->outbuf);
4175 /****************************************************************************
4176 Work out how much space we have for a read return.
4177 ****************************************************************************/
4179 static size_t calc_max_read_pdu(const struct smb_request *req)
4181 struct smbXsrv_connection *xconn = req->xconn;
4183 if (xconn->protocol < PROTOCOL_NT1) {
4184 return xconn->smb1.sessions.max_send;
4187 if (!lp_large_readwrite()) {
4188 return xconn->smb1.sessions.max_send;
4191 if (req_is_in_chain(req)) {
4192 return xconn->smb1.sessions.max_send;
4195 if (req->encrypted) {
4197 * Don't take encrypted traffic up to the
4198 * limit. There are padding considerations
4199 * that make that tricky.
4201 return xconn->smb1.sessions.max_send;
4204 if (srv_is_signing_active(xconn)) {
4208 if (!lp_unix_extensions()) {
4213 * We can do ultra-large POSIX reads.
4218 /****************************************************************************
4219 Calculate how big a read can be. Copes with all clients. It's always
4220 safe to return a short read - Windows does this.
4221 ****************************************************************************/
4223 static size_t calc_read_size(const struct smb_request *req,
4227 struct smbXsrv_connection *xconn = req->xconn;
4228 size_t max_pdu = calc_max_read_pdu(req);
4229 size_t total_size = 0;
4230 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4231 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4234 * Windows explicitly ignores upper size of 0xFFFF.
4235 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4236 * We must do the same as these will never fit even in
4237 * an extended size NetBIOS packet.
4239 if (upper_size == 0xFFFF) {
4243 if (xconn->protocol < PROTOCOL_NT1) {
4247 total_size = ((upper_size<<16) | lower_size);
4250 * LARGE_READX test shows it's always safe to return
4251 * a short read. Windows does so.
4253 return MIN(total_size, max_len);
4256 /****************************************************************************
4257 Reply to a read and X.
4258 ****************************************************************************/
4260 void reply_read_and_X(struct smb_request *req)
4262 connection_struct *conn = req->conn;
4267 bool big_readX = False;
4269 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4272 START_PROFILE(SMBreadX);
4274 if ((req->wct != 10) && (req->wct != 12)) {
4275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4279 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4280 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4281 smb_maxcnt = SVAL(req->vwv+5, 0);
4283 /* If it's an IPC, pass off the pipe handler. */
4285 reply_pipe_read_and_X(req);
4286 END_PROFILE(SMBreadX);
4290 if (!check_fsp(conn, req, fsp)) {
4291 END_PROFILE(SMBreadX);
4295 if (!CHECK_READ(fsp,req)) {
4296 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4297 END_PROFILE(SMBreadX);
4301 upper_size = SVAL(req->vwv+7, 0);
4302 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4303 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4305 * This is a heuristic to avoid keeping large
4306 * outgoing buffers around over long-lived aio
4312 if (req->wct == 12) {
4314 * This is a large offset (64 bit) read.
4316 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4321 NTSTATUS status = schedule_aio_read_and_X(conn,
4326 if (NT_STATUS_IS_OK(status)) {
4327 /* Read scheduled - we're done. */
4330 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4331 /* Real error - report to client. */
4332 END_PROFILE(SMBreadX);
4333 reply_nterror(req, status);
4336 /* NT_STATUS_RETRY - fall back to sync read. */
4339 smbd_lock_socket(req->xconn);
4340 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4341 smbd_unlock_socket(req->xconn);
4344 END_PROFILE(SMBreadX);
4348 /****************************************************************************
4349 Error replies to writebraw must have smb_wct == 1. Fix this up.
4350 ****************************************************************************/
4352 void error_to_writebrawerr(struct smb_request *req)
4354 uint8_t *old_outbuf = req->outbuf;
4356 reply_outbuf(req, 1, 0);
4358 memcpy(req->outbuf, old_outbuf, smb_size);
4359 TALLOC_FREE(old_outbuf);
4362 /****************************************************************************
4363 Read 4 bytes of a smb packet and return the smb length of the packet.
4364 Store the result in the buffer. This version of the function will
4365 never return a session keepalive (length of zero).
4366 Timeout is in milliseconds.
4367 ****************************************************************************/
4369 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4372 uint8_t msgtype = NBSSkeepalive;
4374 while (msgtype == NBSSkeepalive) {
4377 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4379 if (!NT_STATUS_IS_OK(status)) {
4380 char addr[INET6_ADDRSTRLEN];
4381 /* Try and give an error message
4382 * saying what client failed. */
4383 DEBUG(0, ("read_fd_with_timeout failed for "
4384 "client %s read error = %s.\n",
4385 get_peer_addr(fd,addr,sizeof(addr)),
4386 nt_errstr(status)));
4390 msgtype = CVAL(inbuf, 0);
4393 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4394 (unsigned long)len));
4396 return NT_STATUS_OK;
4399 /****************************************************************************
4400 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4401 ****************************************************************************/
4403 void reply_writebraw(struct smb_request *req)
4405 connection_struct *conn = req->conn;
4406 struct smbXsrv_connection *xconn = req->xconn;
4409 ssize_t total_written=0;
4410 size_t numtowrite=0;
4413 const char *data=NULL;
4416 struct lock_struct lock;
4419 START_PROFILE(SMBwritebraw);
4422 * If we ever reply with an error, it must have the SMB command
4423 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4426 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4428 if (srv_is_signing_active(xconn)) {
4429 END_PROFILE(SMBwritebraw);
4430 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4431 "raw reads/writes are disallowed.");
4434 if (req->wct < 12) {
4435 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4436 error_to_writebrawerr(req);
4437 END_PROFILE(SMBwritebraw);
4441 if (xconn->smb1.echo_handler.trusted_fde) {
4442 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4443 "'async smb echo handler = yes'\n"));
4444 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4445 error_to_writebrawerr(req);
4446 END_PROFILE(SMBwritebraw);
4450 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4451 if (!check_fsp(conn, req, fsp)) {
4452 error_to_writebrawerr(req);
4453 END_PROFILE(SMBwritebraw);
4457 if (!CHECK_WRITE(fsp)) {
4458 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4459 error_to_writebrawerr(req);
4460 END_PROFILE(SMBwritebraw);
4464 tcount = IVAL(req->vwv+1, 0);
4465 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4466 write_through = BITSETW(req->vwv+7,0);
4468 /* We have to deal with slightly different formats depending
4469 on whether we are using the core+ or lanman1.0 protocol */
4471 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4472 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4473 data = smb_buf_const(req->inbuf);
4475 numtowrite = SVAL(req->vwv+10, 0);
4476 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4479 /* Ensure we don't write bytes past the end of this packet. */
4481 * This already protects us against CVE-2017-12163.
4483 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4485 error_to_writebrawerr(req);
4486 END_PROFILE(SMBwritebraw);
4490 if (!fsp->print_file) {
4491 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4492 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4495 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4496 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4497 error_to_writebrawerr(req);
4498 END_PROFILE(SMBwritebraw);
4504 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4507 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4508 "wrote=%d sync=%d\n",
4509 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4510 (int)nwritten, (int)write_through));
4512 if (nwritten < (ssize_t)numtowrite) {
4513 reply_nterror(req, NT_STATUS_DISK_FULL);
4514 error_to_writebrawerr(req);
4518 total_written = nwritten;
4520 /* Allocate a buffer of 64k + length. */
4521 buf = talloc_array(NULL, char, 65540);
4523 reply_nterror(req, NT_STATUS_NO_MEMORY);
4524 error_to_writebrawerr(req);
4528 /* Return a SMBwritebraw message to the redirector to tell
4529 * it to send more bytes */
4531 memcpy(buf, req->inbuf, smb_size);
4532 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4533 SCVAL(buf,smb_com,SMBwritebraw);
4534 SSVALS(buf,smb_vwv0,0xFFFF);
4536 if (!srv_send_smb(req->xconn,
4538 false, 0, /* no signing */
4539 IS_CONN_ENCRYPTED(conn),
4541 exit_server_cleanly("reply_writebraw: srv_send_smb "
4545 /* Now read the raw data into the buffer and write it */
4546 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4548 if (!NT_STATUS_IS_OK(status)) {
4549 exit_server_cleanly("secondary writebraw failed");
4552 /* Set up outbuf to return the correct size */
4553 reply_outbuf(req, 1, 0);
4555 if (numtowrite != 0) {
4557 if (numtowrite > 0xFFFF) {
4558 DEBUG(0,("reply_writebraw: Oversize secondary write "
4559 "raw requested (%u). Terminating\n",
4560 (unsigned int)numtowrite ));
4561 exit_server_cleanly("secondary writebraw failed");
4564 if (tcount > nwritten+numtowrite) {
4565 DEBUG(3,("reply_writebraw: Client overestimated the "
4567 (int)tcount,(int)nwritten,(int)numtowrite));
4570 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4573 if (!NT_STATUS_IS_OK(status)) {
4574 /* Try and give an error message
4575 * saying what client failed. */
4576 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4577 "raw read failed (%s) for client %s. "
4578 "Terminating\n", nt_errstr(status),
4579 smbXsrv_connection_dbg(xconn)));
4580 exit_server_cleanly("secondary writebraw failed");
4584 * We are not vulnerable to CVE-2017-12163
4585 * here as we are guarenteed to have numtowrite
4586 * bytes available - we just read from the client.
4588 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4589 if (nwritten == -1) {
4591 reply_nterror(req, map_nt_error_from_unix(errno));
4592 error_to_writebrawerr(req);
4596 if (nwritten < (ssize_t)numtowrite) {
4597 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4598 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4602 total_written += nwritten;
4607 SSVAL(req->outbuf,smb_vwv0,total_written);
4609 status = sync_file(conn, fsp, write_through);
4610 if (!NT_STATUS_IS_OK(status)) {
4611 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4612 fsp_str_dbg(fsp), nt_errstr(status)));
4613 reply_nterror(req, status);
4614 error_to_writebrawerr(req);
4618 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4620 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4621 (int)total_written));
4623 /* We won't return a status if write through is not selected - this
4624 * follows what WfWg does */
4625 END_PROFILE(SMBwritebraw);
4627 if (!write_through && total_written==tcount) {
4629 #if RABBIT_PELLET_FIX
4631 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4632 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4635 if (!send_keepalive(xconn->transport.sock)) {
4636 exit_server_cleanly("reply_writebraw: send of "
4637 "keepalive failed");
4640 TALLOC_FREE(req->outbuf);
4645 END_PROFILE(SMBwritebraw);
4650 #define DBGC_CLASS DBGC_LOCKING
4652 /****************************************************************************
4653 Reply to a writeunlock (core+).
4654 ****************************************************************************/
4656 void reply_writeunlock(struct smb_request *req)
4658 connection_struct *conn = req->conn;
4659 ssize_t nwritten = -1;
4664 NTSTATUS status = NT_STATUS_OK;
4666 struct lock_struct lock;
4667 int saved_errno = 0;
4669 START_PROFILE(SMBwriteunlock);
4672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4673 END_PROFILE(SMBwriteunlock);
4677 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4679 if (!check_fsp(conn, req, fsp)) {
4680 END_PROFILE(SMBwriteunlock);
4684 if (!CHECK_WRITE(fsp)) {
4685 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4686 END_PROFILE(SMBwriteunlock);
4690 numtowrite = SVAL(req->vwv+1, 0);
4691 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4692 data = (const char *)req->buf + 3;
4695 * Ensure client isn't asking us to write more than
4696 * they sent. CVE-2017-12163.
4698 remaining = smbreq_bufrem(req, data);
4699 if (numtowrite > remaining) {
4700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4701 END_PROFILE(SMBwriteunlock);
4705 if (!fsp->print_file && numtowrite > 0) {
4706 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4707 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4710 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4711 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4712 END_PROFILE(SMBwriteunlock);
4717 /* The special X/Open SMB protocol handling of
4718 zero length writes is *NOT* done for
4720 if(numtowrite == 0) {
4723 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4724 saved_errno = errno;
4727 status = sync_file(conn, fsp, False /* write through */);
4728 if (!NT_STATUS_IS_OK(status)) {
4729 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4730 fsp_str_dbg(fsp), nt_errstr(status)));
4731 reply_nterror(req, status);
4736 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4740 if((nwritten < numtowrite) && (numtowrite != 0)) {
4741 reply_nterror(req, NT_STATUS_DISK_FULL);
4745 if (numtowrite && !fsp->print_file) {
4746 status = do_unlock(req->sconn->msg_ctx,
4748 (uint64_t)req->smbpid,
4749 (uint64_t)numtowrite,
4753 if (NT_STATUS_V(status)) {
4754 reply_nterror(req, status);
4759 reply_outbuf(req, 1, 0);
4761 SSVAL(req->outbuf,smb_vwv0,nwritten);
4763 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4764 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4767 END_PROFILE(SMBwriteunlock);
4772 #define DBGC_CLASS DBGC_ALL
4774 /****************************************************************************
4776 ****************************************************************************/
4778 void reply_write(struct smb_request *req)
4780 connection_struct *conn = req->conn;
4783 ssize_t nwritten = -1;
4787 struct lock_struct lock;
4789 int saved_errno = 0;
4791 START_PROFILE(SMBwrite);
4794 END_PROFILE(SMBwrite);
4795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4799 /* If it's an IPC, pass off the pipe handler. */
4801 reply_pipe_write(req);
4802 END_PROFILE(SMBwrite);
4806 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4808 if (!check_fsp(conn, req, fsp)) {
4809 END_PROFILE(SMBwrite);
4813 if (!CHECK_WRITE(fsp)) {
4814 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4815 END_PROFILE(SMBwrite);
4819 numtowrite = SVAL(req->vwv+1, 0);
4820 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4821 data = (const char *)req->buf + 3;
4824 * Ensure client isn't asking us to write more than
4825 * they sent. CVE-2017-12163.
4827 remaining = smbreq_bufrem(req, data);
4828 if (numtowrite > remaining) {
4829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4830 END_PROFILE(SMBwrite);
4834 if (!fsp->print_file) {
4835 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4836 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4839 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4840 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4841 END_PROFILE(SMBwrite);
4847 * X/Open SMB protocol says that if smb_vwv1 is
4848 * zero then the file size should be extended or
4849 * truncated to the size given in smb_vwv[2-3].
4852 if(numtowrite == 0) {
4854 * This is actually an allocate call, and set EOF. JRA.
4856 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4858 reply_nterror(req, NT_STATUS_DISK_FULL);
4861 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4863 reply_nterror(req, NT_STATUS_DISK_FULL);
4866 trigger_write_time_update_immediate(fsp);
4868 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4871 status = sync_file(conn, fsp, False);
4872 if (!NT_STATUS_IS_OK(status)) {
4873 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4874 fsp_str_dbg(fsp), nt_errstr(status)));
4875 reply_nterror(req, status);
4880 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4884 if((nwritten == 0) && (numtowrite != 0)) {
4885 reply_nterror(req, NT_STATUS_DISK_FULL);
4889 reply_outbuf(req, 1, 0);
4891 SSVAL(req->outbuf,smb_vwv0,nwritten);
4893 if (nwritten < (ssize_t)numtowrite) {
4894 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4895 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4898 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4901 END_PROFILE(SMBwrite);
4905 /****************************************************************************
4906 Ensure a buffer is a valid writeX for recvfile purposes.
4907 ****************************************************************************/
4909 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4910 (2*14) + /* word count (including bcc) */ \
4913 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4914 const uint8_t *inbuf)
4917 unsigned int doff = 0;
4918 size_t len = smb_len_large(inbuf);
4920 struct smbXsrv_open *op = NULL;
4921 struct files_struct *fsp = NULL;
4924 if (is_encrypted_packet(inbuf)) {
4925 /* Can't do this on encrypted
4930 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4934 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4935 CVAL(inbuf,smb_wct) != 14) {
4936 DEBUG(10,("is_valid_writeX_buffer: chained or "
4937 "invalid word length.\n"));
4941 fnum = SVAL(inbuf, smb_vwv2);
4942 status = smb1srv_open_lookup(xconn,
4946 if (!NT_STATUS_IS_OK(status)) {
4947 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4952 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4955 if (fsp->conn == NULL) {
4956 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4960 if (IS_IPC(fsp->conn)) {
4961 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4964 if (IS_PRINT(fsp->conn)) {
4965 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4968 doff = SVAL(inbuf,smb_vwv11);
4970 numtowrite = SVAL(inbuf,smb_vwv10);
4972 if (len > doff && len - doff > 0xFFFF) {
4973 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4976 if (numtowrite == 0) {
4977 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4981 /* Ensure the sizes match up. */
4982 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4983 /* no pad byte...old smbclient :-( */
4984 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4986 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4990 if (len - doff != numtowrite) {
4991 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4992 "len = %u, doff = %u, numtowrite = %u\n",
4995 (unsigned int)numtowrite ));
4999 DEBUG(10,("is_valid_writeX_buffer: true "
5000 "len = %u, doff = %u, numtowrite = %u\n",
5003 (unsigned int)numtowrite ));
5008 /****************************************************************************
5009 Reply to a write and X.
5010 ****************************************************************************/
5012 void reply_write_and_X(struct smb_request *req)
5014 connection_struct *conn = req->conn;
5015 struct smbXsrv_connection *xconn = req->xconn;
5017 struct lock_struct lock;
5022 unsigned int smb_doff;
5023 unsigned int smblen;
5026 int saved_errno = 0;
5028 START_PROFILE(SMBwriteX);
5030 if ((req->wct != 12) && (req->wct != 14)) {
5031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5035 numtowrite = SVAL(req->vwv+10, 0);
5036 smb_doff = SVAL(req->vwv+11, 0);
5037 smblen = smb_len(req->inbuf);
5039 if (req->unread_bytes > 0xFFFF ||
5040 (smblen > smb_doff &&
5041 smblen - smb_doff > 0xFFFF)) {
5042 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5045 if (req->unread_bytes) {
5046 /* Can't do a recvfile write on IPC$ */
5048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5051 if (numtowrite != req->unread_bytes) {
5052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5057 * This already protects us against CVE-2017-12163.
5059 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5060 smb_doff + numtowrite > smblen) {
5061 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5066 /* If it's an IPC, pass off the pipe handler. */
5068 if (req->unread_bytes) {
5069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5072 reply_pipe_write_and_X(req);
5076 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5077 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5078 write_through = BITSETW(req->vwv+7,0);
5080 if (!check_fsp(conn, req, fsp)) {
5084 if (!CHECK_WRITE(fsp)) {
5085 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5089 data = smb_base(req->inbuf) + smb_doff;
5091 if(req->wct == 14) {
5093 * This is a large offset (64 bit) write.
5095 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5099 /* X/Open SMB protocol says that, unlike SMBwrite
5100 if the length is zero then NO truncation is
5101 done, just a write of zero. To truncate a file,
5104 if(numtowrite == 0) {
5107 if (req->unread_bytes == 0) {
5108 status = schedule_aio_write_and_X(conn,
5115 if (NT_STATUS_IS_OK(status)) {
5116 /* write scheduled - we're done. */
5119 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5120 /* Real error - report to client. */
5121 reply_nterror(req, status);
5124 /* NT_STATUS_RETRY - fall through to sync write. */
5127 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5128 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5131 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5132 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5136 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5137 saved_errno = errno;
5141 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5145 if((nwritten == 0) && (numtowrite != 0)) {
5146 reply_nterror(req, NT_STATUS_DISK_FULL);
5150 reply_outbuf(req, 6, 0);
5151 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5152 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5153 SSVAL(req->outbuf,smb_vwv2,nwritten);
5154 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5156 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5157 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5159 status = sync_file(conn, fsp, write_through);
5160 if (!NT_STATUS_IS_OK(status)) {
5161 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5162 fsp_str_dbg(fsp), nt_errstr(status)));
5163 reply_nterror(req, status);
5167 END_PROFILE(SMBwriteX);
5171 if (req->unread_bytes) {
5172 /* writeX failed. drain socket. */
5173 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5174 req->unread_bytes) {
5175 smb_panic("failed to drain pending bytes");
5177 req->unread_bytes = 0;
5180 END_PROFILE(SMBwriteX);
5184 /****************************************************************************
5186 ****************************************************************************/
5188 void reply_lseek(struct smb_request *req)
5190 connection_struct *conn = req->conn;
5196 START_PROFILE(SMBlseek);
5199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5200 END_PROFILE(SMBlseek);
5204 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5206 if (!check_fsp(conn, req, fsp)) {
5210 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5212 mode = SVAL(req->vwv+1, 0) & 3;
5213 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5214 startpos = (off_t)IVALS(req->vwv+2, 0);
5223 res = fsp->fh->pos + startpos;
5234 if (umode == SEEK_END) {
5235 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5236 if(errno == EINVAL) {
5237 off_t current_pos = startpos;
5239 if(fsp_stat(fsp) == -1) {
5241 map_nt_error_from_unix(errno));
5242 END_PROFILE(SMBlseek);
5246 current_pos += fsp->fsp_name->st.st_ex_size;
5248 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5253 reply_nterror(req, map_nt_error_from_unix(errno));
5254 END_PROFILE(SMBlseek);
5261 reply_outbuf(req, 2, 0);
5262 SIVAL(req->outbuf,smb_vwv0,res);
5264 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5265 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5267 END_PROFILE(SMBlseek);
5271 /****************************************************************************
5273 ****************************************************************************/
5275 void reply_flush(struct smb_request *req)
5277 connection_struct *conn = req->conn;
5281 START_PROFILE(SMBflush);
5284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5288 fnum = SVAL(req->vwv+0, 0);
5289 fsp = file_fsp(req, fnum);
5291 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5296 file_sync_all(conn);
5298 NTSTATUS status = sync_file(conn, fsp, True);
5299 if (!NT_STATUS_IS_OK(status)) {
5300 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5301 fsp_str_dbg(fsp), nt_errstr(status)));
5302 reply_nterror(req, status);
5303 END_PROFILE(SMBflush);
5308 reply_outbuf(req, 0, 0);
5310 DEBUG(3,("flush\n"));
5311 END_PROFILE(SMBflush);
5315 /****************************************************************************
5317 conn POINTER CAN BE NULL HERE !
5318 ****************************************************************************/
5320 void reply_exit(struct smb_request *req)
5322 START_PROFILE(SMBexit);
5324 file_close_pid(req->sconn, req->smbpid, req->vuid);
5326 reply_outbuf(req, 0, 0);
5328 DEBUG(3,("exit\n"));
5330 END_PROFILE(SMBexit);
5334 struct reply_close_state {
5336 struct smb_request *smbreq;
5339 static void do_smb1_close(struct tevent_req *req);
5341 void reply_close(struct smb_request *req)
5343 connection_struct *conn = req->conn;
5344 NTSTATUS status = NT_STATUS_OK;
5345 files_struct *fsp = NULL;
5346 START_PROFILE(SMBclose);
5349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5350 END_PROFILE(SMBclose);
5354 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5357 * We can only use check_fsp if we know it's not a directory.
5360 if (!check_fsp_open(conn, req, fsp)) {
5361 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5362 END_PROFILE(SMBclose);
5366 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5367 fsp->is_directory ? "directory" : "file",
5368 fsp->fh->fd, fsp_fnum_dbg(fsp),
5369 conn->num_files_open));
5371 if (!fsp->is_directory) {
5375 * Take care of any time sent in the close.
5378 t = srv_make_unix_date3(req->vwv+1);
5379 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5382 if (fsp->num_aio_requests != 0) {
5384 struct reply_close_state *state;
5386 DEBUG(10, ("closing with aio %u requests pending\n",
5387 fsp->num_aio_requests));
5390 * We depend on the aio_extra destructor to take care of this
5391 * close request once fsp->num_aio_request drops to 0.
5394 fsp->deferred_close = tevent_wait_send(
5395 fsp, fsp->conn->sconn->ev_ctx);
5396 if (fsp->deferred_close == NULL) {
5397 status = NT_STATUS_NO_MEMORY;
5401 state = talloc(fsp, struct reply_close_state);
5402 if (state == NULL) {
5403 TALLOC_FREE(fsp->deferred_close);
5404 status = NT_STATUS_NO_MEMORY;
5408 state->smbreq = talloc_move(fsp, &req);
5409 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5411 END_PROFILE(SMBclose);
5416 * close_file() returns the unix errno if an error was detected on
5417 * close - normally this is due to a disk full error. If not then it
5418 * was probably an I/O error.
5421 status = close_file(req, fsp, NORMAL_CLOSE);
5423 if (!NT_STATUS_IS_OK(status)) {
5424 reply_nterror(req, status);
5425 END_PROFILE(SMBclose);
5429 reply_outbuf(req, 0, 0);
5430 END_PROFILE(SMBclose);
5434 static void do_smb1_close(struct tevent_req *req)
5436 struct reply_close_state *state = tevent_req_callback_data(
5437 req, struct reply_close_state);
5438 struct smb_request *smbreq;
5442 ret = tevent_wait_recv(req);
5445 DEBUG(10, ("tevent_wait_recv returned %s\n",
5448 * Continue anyway, this should never happen
5453 * fsp->smb2_close_request right now is a talloc grandchild of
5454 * fsp. When we close_file(fsp), it would go with it. No chance to
5457 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5459 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5460 if (NT_STATUS_IS_OK(status)) {
5461 reply_outbuf(smbreq, 0, 0);
5463 reply_nterror(smbreq, status);
5465 if (!srv_send_smb(smbreq->xconn,
5466 (char *)smbreq->outbuf,
5469 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5471 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5474 TALLOC_FREE(smbreq);
5477 /****************************************************************************
5478 Reply to a writeclose (Core+ protocol).
5479 ****************************************************************************/
5481 void reply_writeclose(struct smb_request *req)
5483 connection_struct *conn = req->conn;
5486 ssize_t nwritten = -1;
5487 NTSTATUS close_status = NT_STATUS_OK;
5490 struct timespec mtime;
5492 struct lock_struct lock;
5494 START_PROFILE(SMBwriteclose);
5497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5498 END_PROFILE(SMBwriteclose);
5502 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5504 if (!check_fsp(conn, req, fsp)) {
5505 END_PROFILE(SMBwriteclose);
5508 if (!CHECK_WRITE(fsp)) {
5509 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5510 END_PROFILE(SMBwriteclose);
5514 numtowrite = SVAL(req->vwv+1, 0);
5515 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5516 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5517 data = (const char *)req->buf + 1;
5520 * Ensure client isn't asking us to write more than
5521 * they sent. CVE-2017-12163.
5523 remaining = smbreq_bufrem(req, data);
5524 if (numtowrite > remaining) {
5525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5526 END_PROFILE(SMBwriteclose);
5530 if (fsp->print_file == NULL) {
5531 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5532 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5535 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5536 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5537 END_PROFILE(SMBwriteclose);
5542 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5544 set_close_write_time(fsp, mtime);
5547 * More insanity. W2K only closes the file if writelen > 0.
5551 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5552 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5553 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5556 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5557 "file %s\n", fsp_str_dbg(fsp)));
5558 close_status = close_file(req, fsp, NORMAL_CLOSE);
5562 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5563 reply_nterror(req, NT_STATUS_DISK_FULL);
5567 if(!NT_STATUS_IS_OK(close_status)) {
5568 reply_nterror(req, close_status);
5572 reply_outbuf(req, 1, 0);
5574 SSVAL(req->outbuf,smb_vwv0,nwritten);
5578 END_PROFILE(SMBwriteclose);
5583 #define DBGC_CLASS DBGC_LOCKING
5585 /****************************************************************************
5587 ****************************************************************************/
5589 void reply_lock(struct smb_request *req)
5591 connection_struct *conn = req->conn;
5592 uint64_t count,offset;
5595 struct byte_range_lock *br_lck = NULL;
5597 START_PROFILE(SMBlock);
5600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5601 END_PROFILE(SMBlock);
5605 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5607 if (!check_fsp(conn, req, fsp)) {
5608 END_PROFILE(SMBlock);
5612 count = (uint64_t)IVAL(req->vwv+1, 0);
5613 offset = (uint64_t)IVAL(req->vwv+3, 0);
5615 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5616 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5618 br_lck = do_lock(req->sconn->msg_ctx,
5620 (uint64_t)req->smbpid,
5625 False, /* Non-blocking lock. */
5629 TALLOC_FREE(br_lck);
5631 if (NT_STATUS_V(status)) {
5632 reply_nterror(req, status);
5633 END_PROFILE(SMBlock);
5637 reply_outbuf(req, 0, 0);
5639 END_PROFILE(SMBlock);
5643 /****************************************************************************
5645 ****************************************************************************/
5647 void reply_unlock(struct smb_request *req)
5649 connection_struct *conn = req->conn;
5650 uint64_t count,offset;
5654 START_PROFILE(SMBunlock);
5657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5658 END_PROFILE(SMBunlock);
5662 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5664 if (!check_fsp(conn, req, fsp)) {
5665 END_PROFILE(SMBunlock);
5669 count = (uint64_t)IVAL(req->vwv+1, 0);
5670 offset = (uint64_t)IVAL(req->vwv+3, 0);
5672 status = do_unlock(req->sconn->msg_ctx,
5674 (uint64_t)req->smbpid,
5679 if (NT_STATUS_V(status)) {
5680 reply_nterror(req, status);
5681 END_PROFILE(SMBunlock);
5685 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5686 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5688 reply_outbuf(req, 0, 0);
5690 END_PROFILE(SMBunlock);
5695 #define DBGC_CLASS DBGC_ALL
5697 /****************************************************************************
5699 conn POINTER CAN BE NULL HERE !
5700 ****************************************************************************/
5702 void reply_tdis(struct smb_request *req)
5705 connection_struct *conn = req->conn;
5706 struct smbXsrv_tcon *tcon;
5708 START_PROFILE(SMBtdis);
5711 DEBUG(4,("Invalid connection in tdis\n"));
5712 reply_force_doserror(req, ERRSRV, ERRinvnid);
5713 END_PROFILE(SMBtdis);
5721 * TODO: cancel all outstanding requests on the tcon
5723 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5724 if (!NT_STATUS_IS_OK(status)) {
5725 DEBUG(0, ("reply_tdis: "
5726 "smbXsrv_tcon_disconnect() failed: %s\n",
5727 nt_errstr(status)));
5729 * If we hit this case, there is something completely
5730 * wrong, so we better disconnect the transport connection.
5732 END_PROFILE(SMBtdis);
5733 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5739 reply_outbuf(req, 0, 0);
5740 END_PROFILE(SMBtdis);
5744 /****************************************************************************
5746 conn POINTER CAN BE NULL HERE !
5747 ****************************************************************************/
5749 void reply_echo(struct smb_request *req)
5751 connection_struct *conn = req->conn;
5752 struct smb_perfcount_data local_pcd;
5753 struct smb_perfcount_data *cur_pcd;
5757 START_PROFILE(SMBecho);
5759 smb_init_perfcount_data(&local_pcd);
5762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5763 END_PROFILE(SMBecho);
5767 smb_reverb = SVAL(req->vwv+0, 0);
5769 reply_outbuf(req, 1, req->buflen);
5771 /* copy any incoming data back out */
5772 if (req->buflen > 0) {
5773 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5776 if (smb_reverb > 100) {
5777 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5781 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5783 /* this makes sure we catch the request pcd */
5784 if (seq_num == smb_reverb) {
5785 cur_pcd = &req->pcd;
5787 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5788 cur_pcd = &local_pcd;
5791 SSVAL(req->outbuf,smb_vwv0,seq_num);
5793 show_msg((char *)req->outbuf);
5794 if (!srv_send_smb(req->xconn,
5795 (char *)req->outbuf,
5796 true, req->seqnum+1,
5797 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5799 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5802 DEBUG(3,("echo %d times\n", smb_reverb));
5804 TALLOC_FREE(req->outbuf);
5806 END_PROFILE(SMBecho);
5810 /****************************************************************************
5811 Reply to a printopen.
5812 ****************************************************************************/
5814 void reply_printopen(struct smb_request *req)
5816 connection_struct *conn = req->conn;
5820 START_PROFILE(SMBsplopen);
5823 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5824 END_PROFILE(SMBsplopen);
5828 if (!CAN_PRINT(conn)) {
5829 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5830 END_PROFILE(SMBsplopen);
5834 status = file_new(req, conn, &fsp);
5835 if(!NT_STATUS_IS_OK(status)) {
5836 reply_nterror(req, status);
5837 END_PROFILE(SMBsplopen);
5841 /* Open for exclusive use, write only. */
5842 status = print_spool_open(fsp, NULL, req->vuid);
5844 if (!NT_STATUS_IS_OK(status)) {
5845 file_free(req, fsp);
5846 reply_nterror(req, status);
5847 END_PROFILE(SMBsplopen);
5851 reply_outbuf(req, 1, 0);
5852 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5854 DEBUG(3,("openprint fd=%d %s\n",
5855 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5857 END_PROFILE(SMBsplopen);
5861 /****************************************************************************
5862 Reply to a printclose.
5863 ****************************************************************************/
5865 void reply_printclose(struct smb_request *req)
5867 connection_struct *conn = req->conn;
5871 START_PROFILE(SMBsplclose);
5874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5875 END_PROFILE(SMBsplclose);
5879 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5881 if (!check_fsp(conn, req, fsp)) {
5882 END_PROFILE(SMBsplclose);
5886 if (!CAN_PRINT(conn)) {
5887 reply_force_doserror(req, ERRSRV, ERRerror);
5888 END_PROFILE(SMBsplclose);
5892 DEBUG(3,("printclose fd=%d %s\n",
5893 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5895 status = close_file(req, fsp, NORMAL_CLOSE);
5897 if(!NT_STATUS_IS_OK(status)) {
5898 reply_nterror(req, status);
5899 END_PROFILE(SMBsplclose);
5903 reply_outbuf(req, 0, 0);
5905 END_PROFILE(SMBsplclose);
5909 /****************************************************************************
5910 Reply to a printqueue.
5911 ****************************************************************************/
5913 void reply_printqueue(struct smb_request *req)
5915 connection_struct *conn = req->conn;
5919 START_PROFILE(SMBsplretq);
5922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5923 END_PROFILE(SMBsplretq);
5927 max_count = SVAL(req->vwv+0, 0);
5928 start_index = SVAL(req->vwv+1, 0);
5930 /* we used to allow the client to get the cnum wrong, but that
5931 is really quite gross and only worked when there was only
5932 one printer - I think we should now only accept it if they
5933 get it right (tridge) */
5934 if (!CAN_PRINT(conn)) {
5935 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5936 END_PROFILE(SMBsplretq);
5940 reply_outbuf(req, 2, 3);
5941 SSVAL(req->outbuf,smb_vwv0,0);
5942 SSVAL(req->outbuf,smb_vwv1,0);
5943 SCVAL(smb_buf(req->outbuf),0,1);
5944 SSVAL(smb_buf(req->outbuf),1,0);
5946 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5947 start_index, max_count));
5950 TALLOC_CTX *mem_ctx = talloc_tos();
5953 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5954 struct rpc_pipe_client *cli = NULL;
5955 struct dcerpc_binding_handle *b = NULL;
5956 struct policy_handle handle;
5957 struct spoolss_DevmodeContainer devmode_ctr;
5958 union spoolss_JobInfo *info;
5960 uint32_t num_to_get;
5964 ZERO_STRUCT(handle);
5966 status = rpc_pipe_open_interface(mem_ctx,
5969 conn->sconn->remote_address,
5970 conn->sconn->local_address,
5971 conn->sconn->msg_ctx,
5973 if (!NT_STATUS_IS_OK(status)) {
5974 DEBUG(0, ("reply_printqueue: "
5975 "could not connect to spoolss: %s\n",
5976 nt_errstr(status)));
5977 reply_nterror(req, status);
5980 b = cli->binding_handle;
5982 ZERO_STRUCT(devmode_ctr);
5984 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5987 SEC_FLAG_MAXIMUM_ALLOWED,
5990 if (!NT_STATUS_IS_OK(status)) {
5991 reply_nterror(req, status);
5994 if (!W_ERROR_IS_OK(werr)) {
5995 reply_nterror(req, werror_to_ntstatus(werr));
5999 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6007 if (!W_ERROR_IS_OK(werr)) {
6008 reply_nterror(req, werror_to_ntstatus(werr));
6012 if (max_count > 0) {
6013 first = start_index;
6015 first = start_index + max_count + 1;
6018 if (first >= count) {
6021 num_to_get = first + MIN(ABS(max_count), count - first);
6024 for (i = first; i < num_to_get; i++) {
6027 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6030 uint16_t qrapjobid = pjobid_to_rap(sharename,
6031 info[i].info2.job_id);
6033 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6039 srv_put_dos_date2(p, 0, qtime);
6040 SCVAL(p, 4, qstatus);
6041 SSVAL(p, 5, qrapjobid);
6042 SIVAL(p, 7, info[i].info2.size);
6044 status = srvstr_push(blob, req->flags2, p+12,
6045 info[i].info2.notify_name, 16, STR_ASCII, &len);
6046 if (!NT_STATUS_IS_OK(status)) {
6047 reply_nterror(req, status);
6050 if (message_push_blob(
6053 blob, sizeof(blob))) == -1) {
6054 reply_nterror(req, NT_STATUS_NO_MEMORY);
6060 SSVAL(req->outbuf,smb_vwv0,count);
6061 SSVAL(req->outbuf,smb_vwv1,
6062 (max_count>0?first+count:first-1));
6063 SCVAL(smb_buf(req->outbuf),0,1);
6064 SSVAL(smb_buf(req->outbuf),1,28*count);
6068 DEBUG(3, ("%u entries returned in queue\n",
6072 if (b && is_valid_policy_hnd(&handle)) {
6073 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6078 END_PROFILE(SMBsplretq);
6082 /****************************************************************************
6083 Reply to a printwrite.
6084 ****************************************************************************/
6086 void reply_printwrite(struct smb_request *req)
6088 connection_struct *conn = req->conn;
6093 START_PROFILE(SMBsplwr);
6096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6097 END_PROFILE(SMBsplwr);
6101 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6103 if (!check_fsp(conn, req, fsp)) {
6104 END_PROFILE(SMBsplwr);
6108 if (!fsp->print_file) {
6109 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6110 END_PROFILE(SMBsplwr);
6114 if (!CHECK_WRITE(fsp)) {
6115 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6116 END_PROFILE(SMBsplwr);
6120 numtowrite = SVAL(req->buf, 1);
6123 * This already protects us against CVE-2017-12163.
6125 if (req->buflen < numtowrite + 3) {
6126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6127 END_PROFILE(SMBsplwr);
6131 data = (const char *)req->buf + 3;
6133 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6134 reply_nterror(req, map_nt_error_from_unix(errno));
6135 END_PROFILE(SMBsplwr);
6139 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6141 END_PROFILE(SMBsplwr);
6145 /****************************************************************************
6147 ****************************************************************************/
6149 void reply_mkdir(struct smb_request *req)
6151 connection_struct *conn = req->conn;
6152 struct smb_filename *smb_dname = NULL;
6153 char *directory = NULL;
6156 TALLOC_CTX *ctx = talloc_tos();
6158 START_PROFILE(SMBmkdir);
6160 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6161 STR_TERMINATE, &status);
6162 if (!NT_STATUS_IS_OK(status)) {
6163 reply_nterror(req, status);
6167 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6168 status = filename_convert(ctx, conn,
6173 if (!NT_STATUS_IS_OK(status)) {
6174 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6175 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6176 ERRSRV, ERRbadpath);
6179 reply_nterror(req, status);
6183 status = create_directory(conn, req, smb_dname);
6185 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6187 if (!NT_STATUS_IS_OK(status)) {
6189 if (!use_nt_status()
6190 && NT_STATUS_EQUAL(status,
6191 NT_STATUS_OBJECT_NAME_COLLISION)) {
6193 * Yes, in the DOS error code case we get a
6194 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6195 * samba4 torture test.
6197 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6200 reply_nterror(req, status);
6204 reply_outbuf(req, 0, 0);
6206 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6208 TALLOC_FREE(smb_dname);
6209 END_PROFILE(SMBmkdir);
6213 /****************************************************************************
6215 ****************************************************************************/
6217 void reply_rmdir(struct smb_request *req)
6219 connection_struct *conn = req->conn;
6220 struct smb_filename *smb_dname = NULL;
6221 char *directory = NULL;
6223 TALLOC_CTX *ctx = talloc_tos();
6224 files_struct *fsp = NULL;
6226 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6227 struct smbd_server_connection *sconn = req->sconn;
6229 START_PROFILE(SMBrmdir);
6231 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6232 STR_TERMINATE, &status);
6233 if (!NT_STATUS_IS_OK(status)) {
6234 reply_nterror(req, status);
6238 status = filename_convert(ctx, conn,
6243 if (!NT_STATUS_IS_OK(status)) {
6244 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6245 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6246 ERRSRV, ERRbadpath);
6249 reply_nterror(req, status);
6253 if (is_ntfs_stream_smb_fname(smb_dname)) {
6254 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6258 status = SMB_VFS_CREATE_FILE(
6261 0, /* root_dir_fid */
6262 smb_dname, /* fname */
6263 DELETE_ACCESS, /* access_mask */
6264 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6266 FILE_OPEN, /* create_disposition*/
6267 FILE_DIRECTORY_FILE, /* create_options */
6268 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6269 0, /* oplock_request */
6271 0, /* allocation_size */
6272 0, /* private_flags */
6277 NULL, NULL); /* create context */
6279 if (!NT_STATUS_IS_OK(status)) {
6280 if (open_was_deferred(req->xconn, req->mid)) {
6281 /* We have re-scheduled this call. */
6284 reply_nterror(req, status);
6288 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6289 if (!NT_STATUS_IS_OK(status)) {
6290 close_file(req, fsp, ERROR_CLOSE);
6291 reply_nterror(req, status);
6295 if (!set_delete_on_close(fsp, true,
6296 conn->session_info->security_token,
6297 conn->session_info->unix_token)) {
6298 close_file(req, fsp, ERROR_CLOSE);
6299 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6303 status = close_file(req, fsp, NORMAL_CLOSE);
6304 if (!NT_STATUS_IS_OK(status)) {
6305 reply_nterror(req, status);
6307 reply_outbuf(req, 0, 0);
6310 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6312 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6314 TALLOC_FREE(smb_dname);
6315 END_PROFILE(SMBrmdir);
6319 /*******************************************************************
6320 Resolve wildcards in a filename rename.
6321 ********************************************************************/
6323 static bool resolve_wildcards(TALLOC_CTX *ctx,
6328 char *name2_copy = NULL;
6333 char *p,*p2, *pname1, *pname2;
6335 name2_copy = talloc_strdup(ctx, name2);
6340 pname1 = strrchr_m(name1,'/');
6341 pname2 = strrchr_m(name2_copy,'/');
6343 if (!pname1 || !pname2) {
6347 /* Truncate the copy of name2 at the last '/' */
6350 /* Now go past the '/' */
6354 root1 = talloc_strdup(ctx, pname1);
6355 root2 = talloc_strdup(ctx, pname2);
6357 if (!root1 || !root2) {
6361 p = strrchr_m(root1,'.');
6364 ext1 = talloc_strdup(ctx, p+1);
6366 ext1 = talloc_strdup(ctx, "");
6368 p = strrchr_m(root2,'.');
6371 ext2 = talloc_strdup(ctx, p+1);
6373 ext2 = talloc_strdup(ctx, "");
6376 if (!ext1 || !ext2) {
6384 /* Hmmm. Should this be mb-aware ? */
6387 } else if (*p2 == '*') {
6389 root2 = talloc_asprintf(ctx, "%s%s",
6408 /* Hmmm. Should this be mb-aware ? */
6411 } else if (*p2 == '*') {
6413 ext2 = talloc_asprintf(ctx, "%s%s",
6429 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6434 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6446 /****************************************************************************
6447 Ensure open files have their names updated. Updated to notify other smbd's
6449 ****************************************************************************/
6451 static void rename_open_files(connection_struct *conn,
6452 struct share_mode_lock *lck,
6454 uint32_t orig_name_hash,
6455 const struct smb_filename *smb_fname_dst)
6458 bool did_rename = False;
6460 uint32_t new_name_hash = 0;
6462 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6463 fsp = file_find_di_next(fsp)) {
6464 /* fsp_name is a relative path under the fsp. To change this for other
6465 sharepaths we need to manipulate relative paths. */
6466 /* TODO - create the absolute path and manipulate the newname
6467 relative to the sharepath. */
6468 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6471 if (fsp->name_hash != orig_name_hash) {
6474 DEBUG(10, ("rename_open_files: renaming file %s "
6475 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6476 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6477 smb_fname_str_dbg(smb_fname_dst)));
6479 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6480 if (NT_STATUS_IS_OK(status)) {
6482 new_name_hash = fsp->name_hash;
6487 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6488 "for %s\n", file_id_string_tos(&id),
6489 smb_fname_str_dbg(smb_fname_dst)));
6492 /* Send messages to all smbd's (not ourself) that the name has changed. */
6493 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6494 orig_name_hash, new_name_hash,
6499 /****************************************************************************
6500 We need to check if the source path is a parent directory of the destination
6501 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6502 refuse the rename with a sharing violation. Under UNIX the above call can
6503 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6504 probably need to check that the client is a Windows one before disallowing
6505 this as a UNIX client (one with UNIX extensions) can know the source is a
6506 symlink and make this decision intelligently. Found by an excellent bug
6507 report from <AndyLiebman@aol.com>.
6508 ****************************************************************************/
6510 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6511 const struct smb_filename *smb_fname_dst)
6513 const char *psrc = smb_fname_src->base_name;
6514 const char *pdst = smb_fname_dst->base_name;
6517 if (psrc[0] == '.' && psrc[1] == '/') {
6520 if (pdst[0] == '.' && pdst[1] == '/') {
6523 if ((slen = strlen(psrc)) > strlen(pdst)) {
6526 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6530 * Do the notify calls from a rename
6533 static void notify_rename(connection_struct *conn, bool is_dir,
6534 const struct smb_filename *smb_fname_src,
6535 const struct smb_filename *smb_fname_dst)
6537 char *parent_dir_src = NULL;
6538 char *parent_dir_dst = NULL;
6541 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6542 : FILE_NOTIFY_CHANGE_FILE_NAME;
6544 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6545 &parent_dir_src, NULL) ||
6546 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6547 &parent_dir_dst, NULL)) {
6551 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6552 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6553 smb_fname_src->base_name);
6554 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6555 smb_fname_dst->base_name);
6558 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6559 smb_fname_src->base_name);
6560 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6561 smb_fname_dst->base_name);
6564 /* this is a strange one. w2k3 gives an additional event for
6565 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6566 files, but not directories */
6568 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6569 FILE_NOTIFY_CHANGE_ATTRIBUTES
6570 |FILE_NOTIFY_CHANGE_CREATION,
6571 smb_fname_dst->base_name);
6574 TALLOC_FREE(parent_dir_src);
6575 TALLOC_FREE(parent_dir_dst);
6578 /****************************************************************************
6579 Returns an error if the parent directory for a filename is open in an
6581 ****************************************************************************/
6583 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6584 const struct smb_filename *smb_fname_dst_in)
6586 char *parent_dir = NULL;
6587 struct smb_filename smb_fname_parent;
6589 files_struct *fsp = NULL;
6592 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6593 &parent_dir, NULL)) {
6594 return NT_STATUS_NO_MEMORY;
6596 ZERO_STRUCT(smb_fname_parent);
6597 smb_fname_parent.base_name = parent_dir;
6599 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6601 return map_nt_error_from_unix(errno);
6605 * We're only checking on this smbd here, mostly good
6606 * enough.. and will pass tests.
6609 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6610 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6611 fsp = file_find_di_next(fsp)) {
6612 if (fsp->access_mask & DELETE_ACCESS) {
6613 return NT_STATUS_SHARING_VIOLATION;
6616 return NT_STATUS_OK;
6619 /****************************************************************************
6620 Rename an open file - given an fsp.
6621 ****************************************************************************/
6623 NTSTATUS rename_internals_fsp(connection_struct *conn,
6625 const struct smb_filename *smb_fname_dst_in,
6627 bool replace_if_exists)
6629 TALLOC_CTX *ctx = talloc_tos();
6630 struct smb_filename *smb_fname_dst = NULL;
6631 NTSTATUS status = NT_STATUS_OK;
6632 struct share_mode_lock *lck = NULL;
6633 uint32_t access_mask = SEC_DIR_ADD_FILE;
6634 bool dst_exists, old_is_stream, new_is_stream;
6636 status = check_name(conn, smb_fname_dst_in);
6637 if (!NT_STATUS_IS_OK(status)) {
6641 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6642 if (!NT_STATUS_IS_OK(status)) {
6646 if (file_has_open_streams(fsp)) {
6647 return NT_STATUS_ACCESS_DENIED;
6650 /* Make a copy of the dst smb_fname structs */
6652 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6653 if (smb_fname_dst == NULL) {
6654 status = NT_STATUS_NO_MEMORY;
6659 * Check for special case with case preserving and not
6660 * case sensitive. If the new last component differs from the original
6661 * last component only by case, then we should allow
6662 * the rename (user is trying to change the case of the
6665 if (!conn->case_sensitive && conn->case_preserve &&
6666 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6667 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6668 char *fname_dst_parent = NULL;
6669 const char *fname_dst_lcomp = NULL;
6670 char *orig_lcomp_path = NULL;
6671 char *orig_lcomp_stream = NULL;
6675 * Split off the last component of the processed
6676 * destination name. We will compare this to
6677 * the split components of smb_fname_dst->original_lcomp.
6679 if (!parent_dirname(ctx,
6680 smb_fname_dst->base_name,
6682 &fname_dst_lcomp)) {
6683 status = NT_STATUS_NO_MEMORY;
6688 * The original_lcomp component contains
6689 * the last_component of the path + stream
6690 * name (if a stream exists).
6692 * Split off the stream name so we
6693 * can check them separately.
6696 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6697 /* POSIX - no stream component. */
6698 orig_lcomp_path = talloc_strdup(ctx,
6699 smb_fname_dst->original_lcomp);
6700 if (orig_lcomp_path == NULL) {
6704 ok = split_stream_filename(ctx,
6705 smb_fname_dst->original_lcomp,
6707 &orig_lcomp_stream);
6711 TALLOC_FREE(fname_dst_parent);
6712 status = NT_STATUS_NO_MEMORY;
6716 /* If the base names only differ by case, use original. */
6717 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6720 * Replace the modified last component with the
6723 if (!ISDOT(fname_dst_parent)) {
6724 tmp = talloc_asprintf(smb_fname_dst,
6729 tmp = talloc_strdup(smb_fname_dst,
6733 status = NT_STATUS_NO_MEMORY;
6734 TALLOC_FREE(fname_dst_parent);
6735 TALLOC_FREE(orig_lcomp_path);
6736 TALLOC_FREE(orig_lcomp_stream);
6739 TALLOC_FREE(smb_fname_dst->base_name);
6740 smb_fname_dst->base_name = tmp;
6743 /* If the stream_names only differ by case, use original. */
6744 if(!strcsequal(smb_fname_dst->stream_name,
6745 orig_lcomp_stream)) {
6746 /* Use the original stream. */
6747 char *tmp = talloc_strdup(smb_fname_dst,
6750 status = NT_STATUS_NO_MEMORY;
6751 TALLOC_FREE(fname_dst_parent);
6752 TALLOC_FREE(orig_lcomp_path);
6753 TALLOC_FREE(orig_lcomp_stream);
6756 TALLOC_FREE(smb_fname_dst->stream_name);
6757 smb_fname_dst->stream_name = tmp;
6759 TALLOC_FREE(fname_dst_parent);
6760 TALLOC_FREE(orig_lcomp_path);
6761 TALLOC_FREE(orig_lcomp_stream);
6765 * If the src and dest names are identical - including case,
6766 * don't do the rename, just return success.
6769 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6770 strcsequal(fsp->fsp_name->stream_name,
6771 smb_fname_dst->stream_name)) {
6772 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6773 "- returning success\n",
6774 smb_fname_str_dbg(smb_fname_dst)));
6775 status = NT_STATUS_OK;
6779 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6780 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6782 /* Return the correct error code if both names aren't streams. */
6783 if (!old_is_stream && new_is_stream) {
6784 status = NT_STATUS_OBJECT_NAME_INVALID;
6788 if (old_is_stream && !new_is_stream) {
6789 status = NT_STATUS_INVALID_PARAMETER;
6793 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6795 if(!replace_if_exists && dst_exists) {
6796 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6797 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6798 smb_fname_str_dbg(smb_fname_dst)));
6799 status = NT_STATUS_OBJECT_NAME_COLLISION;
6804 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6805 &smb_fname_dst->st);
6806 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6808 /* The file can be open when renaming a stream */
6809 if (dst_fsp && !new_is_stream) {
6810 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6811 status = NT_STATUS_ACCESS_DENIED;
6816 /* Ensure we have a valid stat struct for the source. */
6817 status = vfs_stat_fsp(fsp);
6818 if (!NT_STATUS_IS_OK(status)) {
6822 status = can_rename(conn, fsp, attrs);
6824 if (!NT_STATUS_IS_OK(status)) {
6825 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6826 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6827 smb_fname_str_dbg(smb_fname_dst)));
6828 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6829 status = NT_STATUS_ACCESS_DENIED;
6833 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6834 status = NT_STATUS_ACCESS_DENIED;
6838 /* Do we have rights to move into the destination ? */
6839 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6840 /* We're moving a directory. */
6841 access_mask = SEC_DIR_ADD_SUBDIR;
6843 status = check_parent_access(conn,
6846 if (!NT_STATUS_IS_OK(status)) {
6847 DBG_INFO("check_parent_access on "
6848 "dst %s returned %s\n",
6849 smb_fname_str_dbg(smb_fname_dst),
6854 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6857 * We have the file open ourselves, so not being able to get the
6858 * corresponding share mode lock is a fatal error.
6861 SMB_ASSERT(lck != NULL);
6863 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6864 uint32_t create_options = fsp->fh->private_options;
6866 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6867 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6868 smb_fname_str_dbg(smb_fname_dst)));
6870 if (!fsp->is_directory &&
6871 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6872 (lp_map_archive(SNUM(conn)) ||
6873 lp_store_dos_attributes(SNUM(conn)))) {
6874 /* We must set the archive bit on the newly
6876 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6877 uint32_t old_dosmode = dos_mode(conn,
6879 file_set_dosmode(conn,
6881 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6887 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6890 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6894 * A rename acts as a new file create w.r.t. allowing an initial delete
6895 * on close, probably because in Windows there is a new handle to the
6896 * new file. If initial delete on close was requested but not
6897 * originally set, we need to set it here. This is probably not 100% correct,
6898 * but will work for the CIFSFS client which in non-posix mode
6899 * depends on these semantics. JRA.
6902 if (create_options & FILE_DELETE_ON_CLOSE) {
6903 status = can_set_delete_on_close(fsp, 0);
6905 if (NT_STATUS_IS_OK(status)) {
6906 /* Note that here we set the *inital* delete on close flag,
6907 * not the regular one. The magic gets handled in close. */
6908 fsp->initial_delete_on_close = True;
6912 status = NT_STATUS_OK;
6918 if (errno == ENOTDIR || errno == EISDIR) {
6919 status = NT_STATUS_OBJECT_NAME_COLLISION;
6921 status = map_nt_error_from_unix(errno);
6924 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6925 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6926 smb_fname_str_dbg(smb_fname_dst)));
6929 TALLOC_FREE(smb_fname_dst);
6934 /****************************************************************************
6935 The guts of the rename command, split out so it may be called by the NT SMB
6937 ****************************************************************************/
6939 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6940 connection_struct *conn,
6941 struct smb_request *req,
6942 struct smb_filename *smb_fname_src,
6943 struct smb_filename *smb_fname_dst,
6945 bool replace_if_exists,
6948 uint32_t access_mask)
6950 char *fname_src_dir = NULL;
6951 struct smb_filename *smb_fname_src_dir = NULL;
6952 char *fname_src_mask = NULL;
6954 NTSTATUS status = NT_STATUS_OK;
6955 struct smb_Dir *dir_hnd = NULL;
6956 const char *dname = NULL;
6957 char *talloced = NULL;
6959 int create_options = 0;
6960 bool posix_pathnames = (req != NULL && req->posix_pathnames);
6964 * Split the old name into directory and last component
6965 * strings. Note that unix_convert may have stripped off a
6966 * leading ./ from both name and newname if the rename is
6967 * at the root of the share. We need to make sure either both
6968 * name and newname contain a / character or neither of them do
6969 * as this is checked in resolve_wildcards().
6972 /* Split up the directory from the filename/mask. */
6973 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6974 &fname_src_dir, &fname_src_mask);
6975 if (!NT_STATUS_IS_OK(status)) {
6976 status = NT_STATUS_NO_MEMORY;
6981 * We should only check the mangled cache
6982 * here if unix_convert failed. This means
6983 * that the path in 'mask' doesn't exist
6984 * on the file system and so we need to look
6985 * for a possible mangle. This patch from
6986 * Tine Smukavec <valentin.smukavec@hermes.si>.
6989 if (!VALID_STAT(smb_fname_src->st) &&
6990 mangle_is_mangled(fname_src_mask, conn->params)) {
6991 char *new_mask = NULL;
6992 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6995 TALLOC_FREE(fname_src_mask);
6996 fname_src_mask = new_mask;
7000 if (!src_has_wild) {
7004 * Only one file needs to be renamed. Append the mask back
7005 * onto the directory.
7007 TALLOC_FREE(smb_fname_src->base_name);
7008 if (ISDOT(fname_src_dir)) {
7009 /* Ensure we use canonical names on open. */
7010 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7014 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7019 if (!smb_fname_src->base_name) {
7020 status = NT_STATUS_NO_MEMORY;
7024 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7025 "case_preserve = %d, short case preserve = %d, "
7026 "directory = %s, newname = %s, "
7027 "last_component_dest = %s\n",
7028 conn->case_sensitive, conn->case_preserve,
7029 conn->short_case_preserve,
7030 smb_fname_str_dbg(smb_fname_src),
7031 smb_fname_str_dbg(smb_fname_dst),
7032 smb_fname_dst->original_lcomp));
7034 /* The dest name still may have wildcards. */
7035 if (dest_has_wild) {
7036 char *fname_dst_mod = NULL;
7037 if (!resolve_wildcards(smb_fname_dst,
7038 smb_fname_src->base_name,
7039 smb_fname_dst->base_name,
7041 DEBUG(6, ("rename_internals: resolve_wildcards "
7043 smb_fname_src->base_name,
7044 smb_fname_dst->base_name));
7045 status = NT_STATUS_NO_MEMORY;
7048 TALLOC_FREE(smb_fname_dst->base_name);
7049 smb_fname_dst->base_name = fname_dst_mod;
7052 ZERO_STRUCT(smb_fname_src->st);
7053 if (posix_pathnames) {
7054 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7056 rc = SMB_VFS_STAT(conn, smb_fname_src);
7059 status = map_nt_error_from_unix_common(errno);
7063 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7064 create_options |= FILE_DIRECTORY_FILE;
7067 status = SMB_VFS_CREATE_FILE(
7070 0, /* root_dir_fid */
7071 smb_fname_src, /* fname */
7072 access_mask, /* access_mask */
7073 (FILE_SHARE_READ | /* share_access */
7075 FILE_OPEN, /* create_disposition*/
7076 create_options, /* create_options */
7077 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7078 0, /* oplock_request */
7080 0, /* allocation_size */
7081 0, /* private_flags */
7086 NULL, NULL); /* create context */
7088 if (!NT_STATUS_IS_OK(status)) {
7089 DEBUG(3, ("Could not open rename source %s: %s\n",
7090 smb_fname_str_dbg(smb_fname_src),
7091 nt_errstr(status)));
7095 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7096 attrs, replace_if_exists);
7098 close_file(req, fsp, NORMAL_CLOSE);
7100 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7101 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7102 smb_fname_str_dbg(smb_fname_dst)));
7108 * Wildcards - process each file that matches.
7110 if (strequal(fname_src_mask, "????????.???")) {
7111 TALLOC_FREE(fname_src_mask);
7112 fname_src_mask = talloc_strdup(ctx, "*");
7113 if (!fname_src_mask) {
7114 status = NT_STATUS_NO_MEMORY;
7119 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7123 smb_fname_src->flags);
7124 if (smb_fname_src_dir == NULL) {
7125 status = NT_STATUS_NO_MEMORY;
7129 status = check_name(conn, smb_fname_src_dir);
7130 if (!NT_STATUS_IS_OK(status)) {
7134 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7136 if (dir_hnd == NULL) {
7137 status = map_nt_error_from_unix(errno);
7141 status = NT_STATUS_NO_SUCH_FILE;
7143 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7144 * - gentest fix. JRA
7147 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7149 files_struct *fsp = NULL;
7150 char *destname = NULL;
7151 bool sysdir_entry = False;
7153 /* Quick check for "." and ".." */
7154 if (ISDOT(dname) || ISDOTDOT(dname)) {
7155 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7156 sysdir_entry = True;
7158 TALLOC_FREE(talloced);
7163 if (!is_visible_file(conn, fname_src_dir, dname,
7164 &smb_fname_src->st, false)) {
7165 TALLOC_FREE(talloced);
7169 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7170 TALLOC_FREE(talloced);
7175 status = NT_STATUS_OBJECT_NAME_INVALID;
7179 TALLOC_FREE(smb_fname_src->base_name);
7180 if (ISDOT(fname_src_dir)) {
7181 /* Ensure we use canonical names on open. */
7182 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7186 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7191 if (!smb_fname_src->base_name) {
7192 status = NT_STATUS_NO_MEMORY;
7196 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7197 smb_fname_dst->base_name,
7199 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7200 smb_fname_src->base_name, destname));
7201 TALLOC_FREE(talloced);
7205 status = NT_STATUS_NO_MEMORY;
7209 TALLOC_FREE(smb_fname_dst->base_name);
7210 smb_fname_dst->base_name = destname;
7212 ZERO_STRUCT(smb_fname_src->st);
7213 if (posix_pathnames) {
7214 SMB_VFS_LSTAT(conn, smb_fname_src);
7216 SMB_VFS_STAT(conn, smb_fname_src);
7221 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7222 create_options |= FILE_DIRECTORY_FILE;
7225 status = SMB_VFS_CREATE_FILE(
7228 0, /* root_dir_fid */
7229 smb_fname_src, /* fname */
7230 access_mask, /* access_mask */
7231 (FILE_SHARE_READ | /* share_access */
7233 FILE_OPEN, /* create_disposition*/
7234 create_options, /* create_options */
7235 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7236 0, /* oplock_request */
7238 0, /* allocation_size */
7239 0, /* private_flags */
7244 NULL, NULL); /* create context */
7246 if (!NT_STATUS_IS_OK(status)) {
7247 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7248 "returned %s rename %s -> %s\n",
7250 smb_fname_str_dbg(smb_fname_src),
7251 smb_fname_str_dbg(smb_fname_dst)));
7255 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7257 if (!smb_fname_dst->original_lcomp) {
7258 status = NT_STATUS_NO_MEMORY;
7262 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7263 attrs, replace_if_exists);
7265 close_file(req, fsp, NORMAL_CLOSE);
7267 if (!NT_STATUS_IS_OK(status)) {
7268 DEBUG(3, ("rename_internals_fsp returned %s for "
7269 "rename %s -> %s\n", nt_errstr(status),
7270 smb_fname_str_dbg(smb_fname_src),
7271 smb_fname_str_dbg(smb_fname_dst)));
7277 DEBUG(3,("rename_internals: doing rename on %s -> "
7278 "%s\n", smb_fname_str_dbg(smb_fname_src),
7279 smb_fname_str_dbg(smb_fname_src)));
7280 TALLOC_FREE(talloced);
7282 TALLOC_FREE(dir_hnd);
7284 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7285 status = map_nt_error_from_unix(errno);
7289 TALLOC_FREE(talloced);
7290 TALLOC_FREE(smb_fname_src_dir);
7291 TALLOC_FREE(fname_src_dir);
7292 TALLOC_FREE(fname_src_mask);
7296 /****************************************************************************
7298 ****************************************************************************/
7300 void reply_mv(struct smb_request *req)
7302 connection_struct *conn = req->conn;
7304 char *newname = NULL;
7308 bool src_has_wcard = False;
7309 bool dest_has_wcard = False;
7310 TALLOC_CTX *ctx = talloc_tos();
7311 struct smb_filename *smb_fname_src = NULL;
7312 struct smb_filename *smb_fname_dst = NULL;
7313 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7314 (req->posix_pathnames ?
7315 UCF_UNIX_NAME_LOOKUP :
7316 UCF_COND_ALLOW_WCARD_LCOMP);
7317 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7319 (req->posix_pathnames ?
7321 UCF_COND_ALLOW_WCARD_LCOMP);
7322 bool stream_rename = false;
7324 START_PROFILE(SMBmv);
7327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7331 attrs = SVAL(req->vwv+0, 0);
7333 p = (const char *)req->buf + 1;
7334 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7335 &status, &src_has_wcard);
7336 if (!NT_STATUS_IS_OK(status)) {
7337 reply_nterror(req, status);
7341 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7342 &status, &dest_has_wcard);
7343 if (!NT_STATUS_IS_OK(status)) {
7344 reply_nterror(req, status);
7348 if (!req->posix_pathnames) {
7349 /* The newname must begin with a ':' if the
7350 name contains a ':'. */
7351 if (strchr_m(name, ':')) {
7352 if (newname[0] != ':') {
7353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7356 stream_rename = true;
7360 status = filename_convert(ctx,
7367 if (!NT_STATUS_IS_OK(status)) {
7368 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7369 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7370 ERRSRV, ERRbadpath);
7373 reply_nterror(req, status);
7377 status = filename_convert(ctx,
7384 if (!NT_STATUS_IS_OK(status)) {
7385 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7386 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7387 ERRSRV, ERRbadpath);
7390 reply_nterror(req, status);
7394 if (stream_rename) {
7395 /* smb_fname_dst->base_name must be the same as
7396 smb_fname_src->base_name. */
7397 TALLOC_FREE(smb_fname_dst->base_name);
7398 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7399 smb_fname_src->base_name);
7400 if (!smb_fname_dst->base_name) {
7401 reply_nterror(req, NT_STATUS_NO_MEMORY);
7406 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7407 smb_fname_str_dbg(smb_fname_dst)));
7409 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7410 attrs, False, src_has_wcard, dest_has_wcard,
7412 if (!NT_STATUS_IS_OK(status)) {
7413 if (open_was_deferred(req->xconn, req->mid)) {
7414 /* We have re-scheduled this call. */
7417 reply_nterror(req, status);
7421 reply_outbuf(req, 0, 0);
7423 TALLOC_FREE(smb_fname_src);
7424 TALLOC_FREE(smb_fname_dst);
7429 /*******************************************************************
7430 Copy a file as part of a reply_copy.
7431 ******************************************************************/
7434 * TODO: check error codes on all callers
7437 NTSTATUS copy_file(TALLOC_CTX *ctx,
7438 connection_struct *conn,
7439 struct smb_filename *smb_fname_src,
7440 struct smb_filename *smb_fname_dst,
7443 bool target_is_directory)
7445 struct smb_filename *smb_fname_dst_tmp = NULL;
7447 files_struct *fsp1,*fsp2;
7449 uint32_t new_create_disposition;
7453 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7454 if (smb_fname_dst_tmp == NULL) {
7455 return NT_STATUS_NO_MEMORY;
7459 * If the target is a directory, extract the last component from the
7460 * src filename and append it to the dst filename
7462 if (target_is_directory) {
7465 /* dest/target can't be a stream if it's a directory. */
7466 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7468 p = strrchr_m(smb_fname_src->base_name,'/');
7472 p = smb_fname_src->base_name;
7474 smb_fname_dst_tmp->base_name =
7475 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7477 if (!smb_fname_dst_tmp->base_name) {
7478 status = NT_STATUS_NO_MEMORY;
7483 status = vfs_file_exist(conn, smb_fname_src);
7484 if (!NT_STATUS_IS_OK(status)) {
7488 if (!target_is_directory && count) {
7489 new_create_disposition = FILE_OPEN;
7491 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7494 &new_create_disposition,
7497 status = NT_STATUS_INVALID_PARAMETER;
7502 /* Open the src file for reading. */
7503 status = SMB_VFS_CREATE_FILE(
7506 0, /* root_dir_fid */
7507 smb_fname_src, /* fname */
7508 FILE_GENERIC_READ, /* access_mask */
7509 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7510 FILE_OPEN, /* create_disposition*/
7511 0, /* create_options */
7512 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7513 INTERNAL_OPEN_ONLY, /* oplock_request */
7515 0, /* allocation_size */
7516 0, /* private_flags */
7521 NULL, NULL); /* create context */
7523 if (!NT_STATUS_IS_OK(status)) {
7527 dosattrs = dos_mode(conn, smb_fname_src);
7529 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7530 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7533 /* Open the dst file for writing. */
7534 status = SMB_VFS_CREATE_FILE(
7537 0, /* root_dir_fid */
7538 smb_fname_dst, /* fname */
7539 FILE_GENERIC_WRITE, /* access_mask */
7540 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7541 new_create_disposition, /* create_disposition*/
7542 0, /* create_options */
7543 dosattrs, /* file_attributes */
7544 INTERNAL_OPEN_ONLY, /* oplock_request */
7546 0, /* allocation_size */
7547 0, /* private_flags */
7552 NULL, NULL); /* create context */
7554 if (!NT_STATUS_IS_OK(status)) {
7555 close_file(NULL, fsp1, ERROR_CLOSE);
7559 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7560 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7562 DEBUG(0, ("error - vfs lseek returned error %s\n",
7564 status = map_nt_error_from_unix(errno);
7565 close_file(NULL, fsp1, ERROR_CLOSE);
7566 close_file(NULL, fsp2, ERROR_CLOSE);
7571 /* Do the actual copy. */
7572 if (smb_fname_src->st.st_ex_size) {
7573 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7578 close_file(NULL, fsp1, NORMAL_CLOSE);
7580 /* Ensure the modtime is set correctly on the destination file. */
7581 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7584 * As we are opening fsp1 read-only we only expect
7585 * an error on close on fsp2 if we are out of space.
7586 * Thus we don't look at the error return from the
7589 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7591 if (!NT_STATUS_IS_OK(status)) {
7595 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7596 status = NT_STATUS_DISK_FULL;
7600 status = NT_STATUS_OK;
7603 TALLOC_FREE(smb_fname_dst_tmp);
7607 /****************************************************************************
7608 Reply to a file copy.
7609 ****************************************************************************/
7611 void reply_copy(struct smb_request *req)
7613 connection_struct *conn = req->conn;
7614 struct smb_filename *smb_fname_src = NULL;
7615 struct smb_filename *smb_fname_src_dir = NULL;
7616 struct smb_filename *smb_fname_dst = NULL;
7617 char *fname_src = NULL;
7618 char *fname_dst = NULL;
7619 char *fname_src_mask = NULL;
7620 char *fname_src_dir = NULL;
7623 int error = ERRnoaccess;
7627 bool target_is_directory=False;
7628 bool source_has_wild = False;
7629 bool dest_has_wild = False;
7631 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7632 ucf_flags_from_smb_request(req);
7633 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7634 ucf_flags_from_smb_request(req);
7635 TALLOC_CTX *ctx = talloc_tos();
7637 START_PROFILE(SMBcopy);
7640 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7644 tid2 = SVAL(req->vwv+0, 0);
7645 ofun = SVAL(req->vwv+1, 0);
7646 flags = SVAL(req->vwv+2, 0);
7648 p = (const char *)req->buf;
7649 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7650 &status, &source_has_wild);
7651 if (!NT_STATUS_IS_OK(status)) {
7652 reply_nterror(req, status);
7655 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7656 &status, &dest_has_wild);
7657 if (!NT_STATUS_IS_OK(status)) {
7658 reply_nterror(req, status);
7662 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7664 if (tid2 != conn->cnum) {
7665 /* can't currently handle inter share copies XXXX */
7666 DEBUG(3,("Rejecting inter-share copy\n"));
7667 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7671 status = filename_convert(ctx, conn,
7676 if (!NT_STATUS_IS_OK(status)) {
7677 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7678 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7679 ERRSRV, ERRbadpath);
7682 reply_nterror(req, status);
7686 status = filename_convert(ctx, conn,
7691 if (!NT_STATUS_IS_OK(status)) {
7692 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7693 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7694 ERRSRV, ERRbadpath);
7697 reply_nterror(req, status);
7701 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7703 if ((flags&1) && target_is_directory) {
7704 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7708 if ((flags&2) && !target_is_directory) {
7709 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7713 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7714 /* wants a tree copy! XXXX */
7715 DEBUG(3,("Rejecting tree copy\n"));
7716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7720 /* Split up the directory from the filename/mask. */
7721 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7722 &fname_src_dir, &fname_src_mask);
7723 if (!NT_STATUS_IS_OK(status)) {
7724 reply_nterror(req, NT_STATUS_NO_MEMORY);
7729 * We should only check the mangled cache
7730 * here if unix_convert failed. This means
7731 * that the path in 'mask' doesn't exist
7732 * on the file system and so we need to look
7733 * for a possible mangle. This patch from
7734 * Tine Smukavec <valentin.smukavec@hermes.si>.
7736 if (!VALID_STAT(smb_fname_src->st) &&
7737 mangle_is_mangled(fname_src_mask, conn->params)) {
7738 char *new_mask = NULL;
7739 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7740 &new_mask, conn->params);
7742 /* Use demangled name if one was successfully found. */
7744 TALLOC_FREE(fname_src_mask);
7745 fname_src_mask = new_mask;
7749 if (!source_has_wild) {
7752 * Only one file needs to be copied. Append the mask back onto
7755 TALLOC_FREE(smb_fname_src->base_name);
7756 if (ISDOT(fname_src_dir)) {
7757 /* Ensure we use canonical names on open. */
7758 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7762 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7767 if (!smb_fname_src->base_name) {
7768 reply_nterror(req, NT_STATUS_NO_MEMORY);
7772 if (dest_has_wild) {
7773 char *fname_dst_mod = NULL;
7774 if (!resolve_wildcards(smb_fname_dst,
7775 smb_fname_src->base_name,
7776 smb_fname_dst->base_name,
7778 reply_nterror(req, NT_STATUS_NO_MEMORY);
7781 TALLOC_FREE(smb_fname_dst->base_name);
7782 smb_fname_dst->base_name = fname_dst_mod;
7785 status = check_name(conn, smb_fname_src);
7786 if (!NT_STATUS_IS_OK(status)) {
7787 reply_nterror(req, status);
7791 status = check_name(conn, smb_fname_dst);
7792 if (!NT_STATUS_IS_OK(status)) {
7793 reply_nterror(req, status);
7797 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7798 ofun, count, target_is_directory);
7800 if(!NT_STATUS_IS_OK(status)) {
7801 reply_nterror(req, status);
7807 struct smb_Dir *dir_hnd = NULL;
7808 const char *dname = NULL;
7809 char *talloced = NULL;
7813 * There is a wildcard that requires us to actually read the
7814 * src dir and copy each file matching the mask to the dst.
7815 * Right now streams won't be copied, but this could
7816 * presumably be added with a nested loop for reach dir entry.
7818 SMB_ASSERT(!smb_fname_src->stream_name);
7819 SMB_ASSERT(!smb_fname_dst->stream_name);
7821 smb_fname_src->stream_name = NULL;
7822 smb_fname_dst->stream_name = NULL;
7824 if (strequal(fname_src_mask,"????????.???")) {
7825 TALLOC_FREE(fname_src_mask);
7826 fname_src_mask = talloc_strdup(ctx, "*");
7827 if (!fname_src_mask) {
7828 reply_nterror(req, NT_STATUS_NO_MEMORY);
7833 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7837 smb_fname_src->flags);
7838 if (smb_fname_src_dir == NULL) {
7839 reply_nterror(req, NT_STATUS_NO_MEMORY);
7843 status = check_name(conn, smb_fname_src_dir);
7844 if (!NT_STATUS_IS_OK(status)) {
7845 reply_nterror(req, status);
7849 dir_hnd = OpenDir(ctx,
7854 if (dir_hnd == NULL) {
7855 status = map_nt_error_from_unix(errno);
7856 reply_nterror(req, status);
7862 /* Iterate over the src dir copying each entry to the dst. */
7863 while ((dname = ReadDirName(dir_hnd, &offset,
7864 &smb_fname_src->st, &talloced))) {
7865 char *destname = NULL;
7867 if (ISDOT(dname) || ISDOTDOT(dname)) {
7868 TALLOC_FREE(talloced);
7872 if (!is_visible_file(conn, fname_src_dir, dname,
7873 &smb_fname_src->st, false)) {
7874 TALLOC_FREE(talloced);
7878 if(!mask_match(dname, fname_src_mask,
7879 conn->case_sensitive)) {
7880 TALLOC_FREE(talloced);
7884 error = ERRnoaccess;
7886 /* Get the src smb_fname struct setup. */
7887 TALLOC_FREE(smb_fname_src->base_name);
7888 if (ISDOT(fname_src_dir)) {
7889 /* Ensure we use canonical names on open. */
7890 smb_fname_src->base_name =
7891 talloc_asprintf(smb_fname_src, "%s",
7894 smb_fname_src->base_name =
7895 talloc_asprintf(smb_fname_src, "%s/%s",
7896 fname_src_dir, dname);
7899 if (!smb_fname_src->base_name) {
7900 TALLOC_FREE(dir_hnd);
7901 TALLOC_FREE(talloced);
7902 reply_nterror(req, NT_STATUS_NO_MEMORY);
7906 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7907 smb_fname_dst->base_name,
7909 TALLOC_FREE(talloced);
7913 TALLOC_FREE(dir_hnd);
7914 TALLOC_FREE(talloced);
7915 reply_nterror(req, NT_STATUS_NO_MEMORY);
7919 TALLOC_FREE(smb_fname_dst->base_name);
7920 smb_fname_dst->base_name = destname;
7922 status = check_name(conn, smb_fname_src);
7923 if (!NT_STATUS_IS_OK(status)) {
7924 TALLOC_FREE(dir_hnd);
7925 TALLOC_FREE(talloced);
7926 reply_nterror(req, status);
7930 status = check_name(conn, smb_fname_dst);
7931 if (!NT_STATUS_IS_OK(status)) {
7932 TALLOC_FREE(dir_hnd);
7933 TALLOC_FREE(talloced);
7934 reply_nterror(req, status);
7938 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7939 smb_fname_src->base_name,
7940 smb_fname_dst->base_name));
7942 status = copy_file(ctx, conn, smb_fname_src,
7943 smb_fname_dst, ofun, count,
7944 target_is_directory);
7945 if (NT_STATUS_IS_OK(status)) {
7949 TALLOC_FREE(talloced);
7951 TALLOC_FREE(dir_hnd);
7955 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7959 reply_outbuf(req, 1, 0);
7960 SSVAL(req->outbuf,smb_vwv0,count);
7962 TALLOC_FREE(smb_fname_src);
7963 TALLOC_FREE(smb_fname_src_dir);
7964 TALLOC_FREE(smb_fname_dst);
7965 TALLOC_FREE(fname_src);
7966 TALLOC_FREE(fname_dst);
7967 TALLOC_FREE(fname_src_mask);
7968 TALLOC_FREE(fname_src_dir);
7970 END_PROFILE(SMBcopy);
7975 #define DBGC_CLASS DBGC_LOCKING
7977 /****************************************************************************
7978 Get a lock pid, dealing with large count requests.
7979 ****************************************************************************/
7981 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7982 bool large_file_format)
7984 if(!large_file_format)
7985 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7987 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7990 /****************************************************************************
7991 Get a lock count, dealing with large count requests.
7992 ****************************************************************************/
7994 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7995 bool large_file_format)
7999 if(!large_file_format) {
8000 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8003 * No BVAL, this is reversed!
8005 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8006 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8012 /****************************************************************************
8013 Get a lock offset, dealing with large offset requests.
8014 ****************************************************************************/
8016 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8017 bool large_file_format)
8019 uint64_t offset = 0;
8021 if(!large_file_format) {
8022 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8025 * No BVAL, this is reversed!
8027 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8028 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8034 NTSTATUS smbd_do_locking(struct smb_request *req,
8039 struct smbd_lock_element *locks,
8042 connection_struct *conn = req->conn;
8044 NTSTATUS status = NT_STATUS_OK;
8048 /* Setup the timeout in seconds. */
8050 if (!lp_blocking_locks(SNUM(conn))) {
8054 for(i = 0; i < (int)num_locks; i++) {
8055 struct smbd_lock_element *e = &locks[i];
8057 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8058 "%llu, file %s timeout = %d\n",
8061 (unsigned long long)e->smblctx,
8065 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8066 struct blocking_lock_record *blr = NULL;
8068 if (num_locks > 1) {
8070 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8071 * if the lock vector contains one entry. When given multiple cancel
8072 * requests in a single PDU we expect the server to return an
8073 * error. Windows servers seem to accept the request but only
8074 * cancel the first lock.
8075 * JRA - Do what Windows does (tm) :-).
8079 /* MS-CIFS (2.2.4.32.1) behavior. */
8080 return NT_STATUS_DOS(ERRDOS,
8081 ERRcancelviolation);
8083 /* Windows behavior. */
8085 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8086 "cancel request\n"));
8092 if (lp_blocking_locks(SNUM(conn))) {
8094 /* Schedule a message to ourselves to
8095 remove the blocking lock record and
8096 return the right error. */
8098 blr = blocking_lock_cancel_smb1(fsp,
8104 NT_STATUS_FILE_LOCK_CONFLICT);
8106 return NT_STATUS_DOS(
8108 ERRcancelviolation);
8111 /* Remove a matching pending lock. */
8112 status = do_lock_cancel(fsp,
8118 bool blocking_lock = timeout ? true : false;
8119 bool defer_lock = false;
8120 struct byte_range_lock *br_lck;
8121 uint64_t block_smblctx;
8123 br_lck = do_lock(req->sconn->msg_ctx,
8134 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8135 /* Windows internal resolution for blocking locks seems
8136 to be about 200ms... Don't wait for less than that. JRA. */
8137 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8138 timeout = lp_lock_spin_time();
8143 /* If a lock sent with timeout of zero would fail, and
8144 * this lock has been requested multiple times,
8145 * according to brl_lock_failed() we convert this
8146 * request to a blocking lock with a timeout of between
8147 * 150 - 300 milliseconds.
8149 * If lp_lock_spin_time() has been set to 0, we skip
8150 * this blocking retry and fail immediately.
8152 * Replacement for do_lock_spin(). JRA. */
8154 if (!req->sconn->using_smb2 &&
8155 br_lck && lp_blocking_locks(SNUM(conn)) &&
8156 lp_lock_spin_time() && !blocking_lock &&
8157 NT_STATUS_EQUAL((status),
8158 NT_STATUS_FILE_LOCK_CONFLICT))
8161 timeout = lp_lock_spin_time();
8164 if (br_lck && defer_lock) {
8166 * A blocking lock was requested. Package up
8167 * this smb into a queued request and push it
8168 * onto the blocking lock queue.
8170 if(push_blocking_lock_request(br_lck,
8181 TALLOC_FREE(br_lck);
8183 return NT_STATUS_OK;
8187 TALLOC_FREE(br_lck);
8190 if (!NT_STATUS_IS_OK(status)) {
8195 /* If any of the above locks failed, then we must unlock
8196 all of the previous locks (X/Open spec). */
8198 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8200 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8201 i = -1; /* we want to skip the for loop */
8205 * Ensure we don't do a remove on the lock that just failed,
8206 * as under POSIX rules, if we have a lock already there, we
8207 * will delete it (and we shouldn't) .....
8209 for(i--; i >= 0; i--) {
8210 struct smbd_lock_element *e = &locks[i];
8212 do_unlock(req->sconn->msg_ctx,
8222 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8223 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8225 return NT_STATUS_OK;
8228 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8230 uint16_t num_ulocks,
8231 struct smbd_lock_element *ulocks)
8235 for(i = 0; i < (int)num_ulocks; i++) {
8236 struct smbd_lock_element *e = &ulocks[i];
8239 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8240 "pid %u, file %s\n", __func__,
8243 (unsigned int)e->smblctx,
8246 if (e->brltype != UNLOCK_LOCK) {
8247 /* this can only happen with SMB2 */
8248 return NT_STATUS_INVALID_PARAMETER;
8251 status = do_unlock(req->sconn->msg_ctx,
8258 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8259 nt_errstr(status)));
8261 if (!NT_STATUS_IS_OK(status)) {
8266 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8269 return NT_STATUS_OK;
8272 /****************************************************************************
8273 Reply to a lockingX request.
8274 ****************************************************************************/
8276 void reply_lockingX(struct smb_request *req)
8278 connection_struct *conn = req->conn;
8280 unsigned char locktype;
8281 unsigned char oplocklevel;
8282 uint16_t num_ulocks;
8284 int32_t lock_timeout;
8286 const uint8_t *data;
8287 bool large_file_format;
8288 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8289 struct smbd_lock_element *ulocks;
8290 struct smbd_lock_element *locks;
8293 START_PROFILE(SMBlockingX);
8296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8297 END_PROFILE(SMBlockingX);
8301 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8302 locktype = CVAL(req->vwv+3, 0);
8303 oplocklevel = CVAL(req->vwv+3, 1);
8304 num_ulocks = SVAL(req->vwv+6, 0);
8305 num_locks = SVAL(req->vwv+7, 0);
8306 lock_timeout = IVAL(req->vwv+4, 0);
8307 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8309 if (!check_fsp(conn, req, fsp)) {
8310 END_PROFILE(SMBlockingX);
8316 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8317 /* we don't support these - and CANCEL_LOCK makes w2k
8318 and XP reboot so I don't really want to be
8319 compatible! (tridge) */
8320 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8321 END_PROFILE(SMBlockingX);
8325 /* Check if this is an oplock break on a file
8326 we have granted an oplock on.
8328 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8329 /* Client can insist on breaking to none. */
8330 bool break_to_none = (oplocklevel == 0);
8333 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8334 "for %s\n", (unsigned int)oplocklevel,
8335 fsp_fnum_dbg(fsp)));
8338 * Make sure we have granted an exclusive or batch oplock on
8342 if (fsp->oplock_type == 0) {
8344 /* The Samba4 nbench simulator doesn't understand
8345 the difference between break to level2 and break
8346 to none from level2 - it sends oplock break
8347 replies in both cases. Don't keep logging an error
8348 message here - just ignore it. JRA. */
8350 DEBUG(5,("reply_lockingX: Error : oplock break from "
8351 "client for %s (oplock=%d) and no "
8352 "oplock granted on this file (%s).\n",
8353 fsp_fnum_dbg(fsp), fsp->oplock_type,
8356 /* if this is a pure oplock break request then don't
8358 if (num_locks == 0 && num_ulocks == 0) {
8359 END_PROFILE(SMBlockingX);
8362 END_PROFILE(SMBlockingX);
8363 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8368 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8370 result = remove_oplock(fsp);
8372 result = downgrade_oplock(fsp);
8376 DEBUG(0, ("reply_lockingX: error in removing "
8377 "oplock on file %s\n", fsp_str_dbg(fsp)));
8378 /* Hmmm. Is this panic justified? */
8379 smb_panic("internal tdb error");
8382 /* if this is a pure oplock break request then don't send a
8384 if (num_locks == 0 && num_ulocks == 0) {
8385 /* Sanity check - ensure a pure oplock break is not a
8387 if (CVAL(req->vwv+0, 0) != 0xff) {
8388 DEBUG(0,("reply_lockingX: Error : pure oplock "
8389 "break is a chained %d request !\n",
8390 (unsigned int)CVAL(req->vwv+0, 0)));
8392 END_PROFILE(SMBlockingX);
8398 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8399 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8400 END_PROFILE(SMBlockingX);
8404 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8405 if (ulocks == NULL) {
8406 reply_nterror(req, NT_STATUS_NO_MEMORY);
8407 END_PROFILE(SMBlockingX);
8411 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8412 if (locks == NULL) {
8413 reply_nterror(req, NT_STATUS_NO_MEMORY);
8414 END_PROFILE(SMBlockingX);
8418 /* Data now points at the beginning of the list
8419 of smb_unlkrng structs */
8420 for(i = 0; i < (int)num_ulocks; i++) {
8421 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8422 ulocks[i].count = get_lock_count(data, i, large_file_format);
8423 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8424 ulocks[i].brltype = UNLOCK_LOCK;
8427 /* Now do any requested locks */
8428 data += ((large_file_format ? 20 : 10)*num_ulocks);
8430 /* Data now points at the beginning of the list
8431 of smb_lkrng structs */
8433 for(i = 0; i < (int)num_locks; i++) {
8434 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8435 locks[i].count = get_lock_count(data, i, large_file_format);
8436 locks[i].offset = get_lock_offset(data, i, large_file_format);
8438 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8439 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8440 locks[i].brltype = PENDING_READ_LOCK;
8442 locks[i].brltype = READ_LOCK;
8445 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8446 locks[i].brltype = PENDING_WRITE_LOCK;
8448 locks[i].brltype = WRITE_LOCK;
8453 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8454 if (!NT_STATUS_IS_OK(status)) {
8455 END_PROFILE(SMBlockingX);
8456 reply_nterror(req, status);
8460 status = smbd_do_locking(req, fsp,
8461 locktype, lock_timeout,
8464 if (!NT_STATUS_IS_OK(status)) {
8465 END_PROFILE(SMBlockingX);
8466 reply_nterror(req, status);
8470 END_PROFILE(SMBlockingX);
8474 reply_outbuf(req, 2, 0);
8475 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8476 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8478 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8479 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8481 END_PROFILE(SMBlockingX);
8485 #define DBGC_CLASS DBGC_ALL
8487 /****************************************************************************
8488 Reply to a SMBreadbmpx (read block multiplex) request.
8489 Always reply with an error, if someone has a platform really needs this,
8490 please contact vl@samba.org
8491 ****************************************************************************/
8493 void reply_readbmpx(struct smb_request *req)
8495 START_PROFILE(SMBreadBmpx);
8496 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8497 END_PROFILE(SMBreadBmpx);
8501 /****************************************************************************
8502 Reply to a SMBreadbs (read block multiplex secondary) request.
8503 Always reply with an error, if someone has a platform really needs this,
8504 please contact vl@samba.org
8505 ****************************************************************************/
8507 void reply_readbs(struct smb_request *req)
8509 START_PROFILE(SMBreadBs);
8510 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8511 END_PROFILE(SMBreadBs);
8515 /****************************************************************************
8516 Reply to a SMBsetattrE.
8517 ****************************************************************************/
8519 void reply_setattrE(struct smb_request *req)
8521 connection_struct *conn = req->conn;
8522 struct smb_file_time ft;
8526 START_PROFILE(SMBsetattrE);
8530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8534 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8536 if(!fsp || (fsp->conn != conn)) {
8537 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8542 * Convert the DOS times into unix times.
8545 ft.atime = convert_time_t_to_timespec(
8546 srv_make_unix_date2(req->vwv+3));
8547 ft.mtime = convert_time_t_to_timespec(
8548 srv_make_unix_date2(req->vwv+5));
8549 ft.create_time = convert_time_t_to_timespec(
8550 srv_make_unix_date2(req->vwv+1));
8552 reply_outbuf(req, 0, 0);
8555 * Patch from Ray Frush <frush@engr.colostate.edu>
8556 * Sometimes times are sent as zero - ignore them.
8559 /* Ensure we have a valid stat struct for the source. */
8560 status = vfs_stat_fsp(fsp);
8561 if (!NT_STATUS_IS_OK(status)) {
8562 reply_nterror(req, status);
8566 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8567 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8571 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8572 if (!NT_STATUS_IS_OK(status)) {
8573 reply_nterror(req, status);
8577 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8580 (unsigned int)ft.atime.tv_sec,
8581 (unsigned int)ft.mtime.tv_sec,
8582 (unsigned int)ft.create_time.tv_sec
8585 END_PROFILE(SMBsetattrE);
8590 /* Back from the dead for OS/2..... JRA. */
8592 /****************************************************************************
8593 Reply to a SMBwritebmpx (write block multiplex primary) request.
8594 Always reply with an error, if someone has a platform really needs this,
8595 please contact vl@samba.org
8596 ****************************************************************************/
8598 void reply_writebmpx(struct smb_request *req)
8600 START_PROFILE(SMBwriteBmpx);
8601 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8602 END_PROFILE(SMBwriteBmpx);
8606 /****************************************************************************
8607 Reply to a SMBwritebs (write block multiplex secondary) request.
8608 Always reply with an error, if someone has a platform really needs this,
8609 please contact vl@samba.org
8610 ****************************************************************************/
8612 void reply_writebs(struct smb_request *req)
8614 START_PROFILE(SMBwriteBs);
8615 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8616 END_PROFILE(SMBwriteBs);
8620 /****************************************************************************
8621 Reply to a SMBgetattrE.
8622 ****************************************************************************/
8624 void reply_getattrE(struct smb_request *req)
8626 connection_struct *conn = req->conn;
8629 struct timespec create_ts;
8631 START_PROFILE(SMBgetattrE);
8634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8635 END_PROFILE(SMBgetattrE);
8639 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8641 if(!fsp || (fsp->conn != conn)) {
8642 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8643 END_PROFILE(SMBgetattrE);
8647 /* Do an fstat on this file */
8649 reply_nterror(req, map_nt_error_from_unix(errno));
8650 END_PROFILE(SMBgetattrE);
8654 mode = dos_mode(conn, fsp->fsp_name);
8657 * Convert the times into dos times. Set create
8658 * date to be last modify date as UNIX doesn't save
8662 reply_outbuf(req, 11, 0);
8664 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8665 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8666 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8667 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8668 /* Should we check pending modtime here ? JRA */
8669 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8670 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8672 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8673 SIVAL(req->outbuf, smb_vwv6, 0);
8674 SIVAL(req->outbuf, smb_vwv8, 0);
8676 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8677 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8678 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8680 SSVAL(req->outbuf,smb_vwv10, mode);
8682 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8684 END_PROFILE(SMBgetattrE);