2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/util/tevent_ntstatus.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "librpc/gen_ndr/open_files.h"
48 #include "smb1_utils.h"
49 #include "libcli/smb/smb2_posix.h"
51 /****************************************************************************
52 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
53 path or anything including wildcards.
54 We're assuming here that '/' is not the second byte in any multibyte char
55 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
57 ****************************************************************************/
59 /* Custom version for processing POSIX paths. */
60 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
62 static NTSTATUS check_path_syntax_internal(char *path,
64 bool *p_last_component_contains_wcard)
68 NTSTATUS ret = NT_STATUS_OK;
69 bool start_of_name_component = True;
70 bool stream_started = false;
72 *p_last_component_contains_wcard = False;
79 return NT_STATUS_OBJECT_NAME_INVALID;
82 return NT_STATUS_OBJECT_NAME_INVALID;
84 if (strchr_m(&s[1], ':')) {
85 return NT_STATUS_OBJECT_NAME_INVALID;
91 if ((*s == ':') && !posix_path && !stream_started) {
92 if (*p_last_component_contains_wcard) {
93 return NT_STATUS_OBJECT_NAME_INVALID;
95 /* Stream names allow more characters than file names.
96 We're overloading posix_path here to allow a wider
97 range of characters. If stream_started is true this
98 is still a Windows path even if posix_path is true.
101 stream_started = true;
102 start_of_name_component = false;
106 return NT_STATUS_OBJECT_NAME_INVALID;
110 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
112 * Safe to assume is not the second part of a mb char
113 * as this is handled below.
115 /* Eat multiple '/' or '\\' */
116 while (IS_PATH_SEP(*s,posix_path)) {
119 if ((d != path) && (*s != '\0')) {
120 /* We only care about non-leading or trailing '/' or '\\' */
124 start_of_name_component = True;
126 *p_last_component_contains_wcard = False;
130 if (start_of_name_component) {
131 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
132 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
135 * No mb char starts with '.' so we're safe checking the directory separator here.
138 /* If we just added a '/' - delete it */
139 if ((d > path) && (*(d-1) == '/')) {
144 /* Are we at the start ? Can't go back further if so. */
146 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
149 /* Go back one level... */
150 /* We know this is safe as '/' cannot be part of a mb sequence. */
151 /* NOTE - if this assumption is invalid we are not in good shape... */
152 /* Decrement d first as d points to the *next* char to write into. */
153 for (d--; d > path; d--) {
157 s += 2; /* Else go past the .. */
158 /* We're still at the start of a name component, just the previous one. */
161 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
173 if (*s <= 0x1f || *s == '|') {
174 return NT_STATUS_OBJECT_NAME_INVALID;
182 *p_last_component_contains_wcard = True;
191 /* Get the size of the next MB character. */
192 next_codepoint(s,&siz);
210 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
212 return NT_STATUS_INVALID_PARAMETER;
215 start_of_name_component = False;
223 /****************************************************************************
224 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
225 No wildcards allowed.
226 ****************************************************************************/
228 NTSTATUS check_path_syntax(char *path)
231 return check_path_syntax_internal(path, False, &ignore);
234 /****************************************************************************
235 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
236 Wildcards allowed - p_contains_wcard returns true if the last component contained
238 ****************************************************************************/
240 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
242 return check_path_syntax_internal(path, False, p_contains_wcard);
245 /****************************************************************************
246 Check the path for a POSIX client.
247 We're assuming here that '/' is not the second byte in any multibyte char
248 set (a safe assumption).
249 ****************************************************************************/
251 NTSTATUS check_path_syntax_posix(char *path)
254 return check_path_syntax_internal(path, True, &ignore);
257 /****************************************************************************
258 Pull a string and check the path allowing a wildcard - provide for error return.
259 Passes in posix flag.
260 ****************************************************************************/
262 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
263 const char *base_ptr,
269 bool posix_pathnames,
271 bool *contains_wcard)
277 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
281 *err = NT_STATUS_INVALID_PARAMETER;
285 *contains_wcard = False;
287 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
289 * For a DFS path the function parse_dfs_path()
290 * will do the path processing, just make a copy.
296 if (posix_pathnames) {
297 *err = check_path_syntax_posix(*pp_dest);
299 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
305 /****************************************************************************
306 Pull a string and check the path allowing a wildcard - provide for error return.
307 ****************************************************************************/
309 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
310 const char *base_ptr,
317 bool *contains_wcard)
319 return srvstr_get_path_wcard_internal(ctx,
331 /****************************************************************************
332 Pull a string and check the path allowing a wildcard - provide for error return.
333 posix_pathnames version.
334 ****************************************************************************/
336 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
337 const char *base_ptr,
344 bool *contains_wcard)
346 return srvstr_get_path_wcard_internal(ctx,
358 /****************************************************************************
359 Pull a string and check the path - provide for error return.
360 ****************************************************************************/
362 size_t srvstr_get_path(TALLOC_CTX *ctx,
363 const char *base_ptr,
372 return srvstr_get_path_wcard_internal(ctx,
384 /****************************************************************************
385 Pull a string and check the path - provide for error return.
386 posix_pathnames version.
387 ****************************************************************************/
389 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
390 const char *base_ptr,
399 return srvstr_get_path_wcard_internal(ctx,
412 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
413 char **pp_dest, const char *src, int flags,
414 NTSTATUS *err, bool *contains_wcard)
416 ssize_t bufrem = smbreq_bufrem(req, src);
419 *err = NT_STATUS_INVALID_PARAMETER;
423 if (req->posix_pathnames) {
424 return srvstr_get_path_wcard_internal(mem_ctx,
425 (const char *)req->inbuf,
435 return srvstr_get_path_wcard_internal(mem_ctx,
436 (const char *)req->inbuf,
448 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
449 char **pp_dest, const char *src, int flags,
453 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
454 flags, err, &ignore);
458 * pull a string from the smb_buf part of a packet. In this case the
459 * string can either be null terminated or it can be terminated by the
460 * end of the smbbuf area
462 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
463 char **dest, const uint8_t *src, int flags)
465 ssize_t bufrem = smbreq_bufrem(req, src);
471 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
475 /****************************************************************************
476 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
477 ****************************************************************************/
479 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
482 if ((fsp == NULL) || (conn == NULL)) {
483 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
486 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
487 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
493 /****************************************************************************
494 Check if we have a correct fsp pointing to a file.
495 ****************************************************************************/
497 bool check_fsp(connection_struct *conn, struct smb_request *req,
500 if (!check_fsp_open(conn, req, fsp)) {
503 if (fsp->fsp_flags.is_directory) {
504 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
507 if (fsp->fh->fd == -1) {
508 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
511 fsp->num_smb_operations++;
515 /****************************************************************************
516 Check if we have a correct fsp pointing to a quota fake file. Replacement for
517 the CHECK_NTQUOTA_HANDLE_OK macro.
518 ****************************************************************************/
520 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
523 if (!check_fsp_open(conn, req, fsp)) {
527 if (fsp->fsp_flags.is_directory) {
531 if (fsp->fake_file_handle == NULL) {
535 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
539 if (fsp->fake_file_handle->private_data == NULL) {
546 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
547 const char *name, int name_type)
550 char *trim_name_type;
551 const char *retarget_parm;
554 int retarget_type = 0x20;
555 int retarget_port = NBT_SMB_PORT;
556 struct sockaddr_storage retarget_addr;
557 struct sockaddr_in *in_addr;
561 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
565 trim_name = talloc_strdup(talloc_tos(), name);
566 if (trim_name == NULL) {
569 trim_char(trim_name, ' ', ' ');
571 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
573 if (trim_name_type == NULL) {
577 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
578 trim_name_type, NULL);
579 if (retarget_parm == NULL) {
580 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
583 if (retarget_parm == NULL) {
587 retarget = talloc_strdup(trim_name, retarget_parm);
588 if (retarget == NULL) {
592 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
594 p = strchr(retarget, ':');
597 retarget_port = atoi(p);
600 p = strchr_m(retarget, '#');
603 if (sscanf(p, "%x", &retarget_type) != 1) {
608 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
610 DEBUG(10, ("could not resolve %s\n", retarget));
614 if (retarget_addr.ss_family != AF_INET) {
615 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
619 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
621 _smb_setlen(outbuf, 6);
622 SCVAL(outbuf, 0, 0x84);
623 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
624 *(uint16_t *)(outbuf+8) = htons(retarget_port);
626 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
628 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
634 TALLOC_FREE(trim_name);
638 static void reply_called_name_not_present(char *outbuf)
640 smb_setlen(outbuf, 1);
641 SCVAL(outbuf, 0, 0x83);
642 SCVAL(outbuf, 4, 0x82);
645 /****************************************************************************
646 Reply to a (netbios-level) special message.
647 ****************************************************************************/
649 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
651 struct smbd_server_connection *sconn = xconn->client->sconn;
652 int msg_type = CVAL(inbuf,0);
653 int msg_flags = CVAL(inbuf,1);
655 * We only really use 4 bytes of the outbuf, but for the smb_setlen
656 * calculation & friends (srv_send_smb uses that) we need the full smb
659 char outbuf[smb_size];
661 memset(outbuf, '\0', sizeof(outbuf));
663 smb_setlen(outbuf,0);
666 case NBSSrequest: /* session request */
668 /* inbuf_size is guarenteed to be at least 4. */
670 int name_type1, name_type2;
671 int name_len1, name_len2;
675 if (xconn->transport.nbt.got_session) {
676 exit_server_cleanly("multiple session request not permitted");
679 SCVAL(outbuf,0,NBSSpositive);
682 /* inbuf_size is guaranteed to be at least 4. */
683 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
684 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
685 DEBUG(0,("Invalid name length in session request\n"));
686 reply_called_name_not_present(outbuf);
689 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
690 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
691 DEBUG(0,("Invalid name length in session request\n"));
692 reply_called_name_not_present(outbuf);
696 name_type1 = name_extract((unsigned char *)inbuf,
697 inbuf_size,(unsigned int)4,name1);
698 name_type2 = name_extract((unsigned char *)inbuf,
699 inbuf_size,(unsigned int)(4 + name_len1),name2);
701 if (name_type1 == -1 || name_type2 == -1) {
702 DEBUG(0,("Invalid name type in session request\n"));
703 reply_called_name_not_present(outbuf);
707 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
708 name1, name_type1, name2, name_type2));
710 if (netbios_session_retarget(xconn, name1, name_type1)) {
711 exit_server_cleanly("retargeted client");
715 * Windows NT/2k uses "*SMBSERVER" and XP uses
716 * "*SMBSERV" arrggg!!!
718 if (strequal(name1, "*SMBSERVER ")
719 || strequal(name1, "*SMBSERV ")) {
722 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
725 exit_server_cleanly("could not allocate raddr");
728 fstrcpy(name1, raddr);
731 set_local_machine_name(name1, True);
732 set_remote_machine_name(name2, True);
734 if (is_ipaddress(sconn->remote_hostname)) {
735 char *p = discard_const_p(char, sconn->remote_hostname);
739 sconn->remote_hostname = talloc_strdup(sconn,
740 get_remote_machine_name());
741 if (sconn->remote_hostname == NULL) {
742 exit_server_cleanly("could not copy remote name");
744 xconn->remote_hostname = sconn->remote_hostname;
747 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
748 get_local_machine_name(), get_remote_machine_name(),
751 if (name_type2 == 'R') {
752 /* We are being asked for a pathworks session ---
754 reply_called_name_not_present(outbuf);
758 reload_services(sconn, conn_snum_used, true);
761 xconn->transport.nbt.got_session = true;
765 case 0x89: /* session keepalive request
766 (some old clients produce this?) */
767 SCVAL(outbuf,0,NBSSkeepalive);
771 case NBSSpositive: /* positive session response */
772 case NBSSnegative: /* negative session response */
773 case NBSSretarget: /* retarget session response */
774 DEBUG(0,("Unexpected session response\n"));
777 case NBSSkeepalive: /* session keepalive */
782 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
783 msg_type, msg_flags));
785 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
786 exit_server_cleanly("reply_special: srv_send_smb failed.");
789 if (CVAL(outbuf, 0) != 0x82) {
790 exit_server_cleanly("invalid netbios session");
795 /****************************************************************************
797 conn POINTER CAN BE NULL HERE !
798 ****************************************************************************/
800 void reply_tcon(struct smb_request *req)
802 connection_struct *conn = req->conn;
804 char *service_buf = NULL;
805 char *password = NULL;
811 TALLOC_CTX *ctx = talloc_tos();
812 struct smbXsrv_connection *xconn = req->xconn;
813 NTTIME now = timeval_to_nttime(&req->request_time);
815 START_PROFILE(SMBtcon);
817 if (req->buflen < 4) {
818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
819 END_PROFILE(SMBtcon);
824 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
826 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
828 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
831 if (service_buf == NULL || password == NULL || dev == NULL) {
832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
833 END_PROFILE(SMBtcon);
836 p2 = strrchr_m(service_buf,'\\');
840 service = service_buf;
843 conn = make_connection(req, now, service, dev,
844 req->vuid,&nt_status);
848 reply_nterror(req, nt_status);
849 END_PROFILE(SMBtcon);
853 reply_outbuf(req, 2, 0);
854 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
855 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
856 SSVAL(req->outbuf,smb_tid,conn->cnum);
858 DEBUG(3,("tcon service=%s cnum=%d\n",
859 service, conn->cnum));
861 END_PROFILE(SMBtcon);
865 /****************************************************************************
866 Reply to a tcon and X.
867 conn POINTER CAN BE NULL HERE !
868 ****************************************************************************/
870 void reply_tcon_and_X(struct smb_request *req)
872 const struct loadparm_substitution *lp_sub =
873 loadparm_s3_global_substitution();
874 connection_struct *conn = req->conn;
875 const char *service = NULL;
876 TALLOC_CTX *ctx = talloc_tos();
877 /* what the client thinks the device is */
878 char *client_devicetype = NULL;
879 /* what the server tells the client the share represents */
880 const char *server_devicetype;
887 struct smbXsrv_session *session = NULL;
888 NTTIME now = timeval_to_nttime(&req->request_time);
889 bool session_key_updated = false;
890 uint16_t optional_support = 0;
891 struct smbXsrv_connection *xconn = req->xconn;
893 START_PROFILE(SMBtconX);
896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
897 END_PROFILE(SMBtconX);
901 passlen = SVAL(req->vwv+3, 0);
902 tcon_flags = SVAL(req->vwv+2, 0);
904 /* we might have to close an old one */
905 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
906 struct smbXsrv_tcon *tcon;
914 * TODO: cancel all outstanding requests on the tcon
916 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
917 if (!NT_STATUS_IS_OK(status)) {
918 DEBUG(0, ("reply_tcon_and_X: "
919 "smbXsrv_tcon_disconnect() failed: %s\n",
922 * If we hit this case, there is something completely
923 * wrong, so we better disconnect the transport connection.
925 END_PROFILE(SMBtconX);
926 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
932 * This tree id is gone. Make sure we can't re-use it
938 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
939 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
940 END_PROFILE(SMBtconX);
944 if (xconn->smb1.negprot.encrypted_passwords) {
945 p = req->buf + passlen;
947 p = req->buf + passlen + 1;
950 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
954 END_PROFILE(SMBtconX);
959 * the service name can be either: \\server\share
960 * or share directly like on the DELL PowerVault 705
963 q = strchr_m(path+2,'\\');
965 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
966 END_PROFILE(SMBtconX);
974 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
975 &client_devicetype, p,
976 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
978 if (client_devicetype == NULL) {
979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
980 END_PROFILE(SMBtconX);
984 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
986 nt_status = smb1srv_session_lookup(xconn,
987 req->vuid, now, &session);
988 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
989 reply_force_doserror(req, ERRSRV, ERRbaduid);
990 END_PROFILE(SMBtconX);
993 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
994 reply_nterror(req, nt_status);
995 END_PROFILE(SMBtconX);
998 if (!NT_STATUS_IS_OK(nt_status)) {
999 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1000 END_PROFILE(SMBtconX);
1004 if (session->global->auth_session_info == NULL) {
1005 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1006 END_PROFILE(SMBtconX);
1011 * If there is no application key defined yet
1014 * This means we setup the application key on the
1015 * first tcon that happens via the given session.
1017 * Once the application key is defined, it does not
1020 if (session->global->application_key.length == 0 &&
1021 smb2_signing_key_valid(session->global->signing_key))
1023 struct smbXsrv_session *x = session;
1024 struct auth_session_info *session_info =
1025 session->global->auth_session_info;
1026 uint8_t session_key[16];
1028 ZERO_STRUCT(session_key);
1029 memcpy(session_key, x->global->signing_key->blob.data,
1030 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
1033 * The application key is truncated/padded to 16 bytes
1035 x->global->application_key = data_blob_talloc(x->global,
1037 sizeof(session_key));
1038 ZERO_STRUCT(session_key);
1039 if (x->global->application_key.data == NULL) {
1040 reply_nterror(req, NT_STATUS_NO_MEMORY);
1041 END_PROFILE(SMBtconX);
1045 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1048 status = smb_key_derivation(x->global->application_key.data,
1049 x->global->application_key.length,
1050 x->global->application_key.data);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 DBG_ERR("smb_key_derivation failed: %s\n",
1054 END_PROFILE(SMBtconX);
1057 optional_support |= SMB_EXTENDED_SIGNATURES;
1061 * Place the application key into the session_info
1063 data_blob_clear_free(&session_info->session_key);
1064 session_info->session_key = data_blob_dup_talloc(session_info,
1065 x->global->application_key);
1066 if (session_info->session_key.data == NULL) {
1067 data_blob_clear_free(&x->global->application_key);
1068 reply_nterror(req, NT_STATUS_NO_MEMORY);
1069 END_PROFILE(SMBtconX);
1072 session_key_updated = true;
1075 conn = make_connection(req, now, service, client_devicetype,
1076 req->vuid, &nt_status);
1080 if (session_key_updated) {
1081 struct smbXsrv_session *x = session;
1082 struct auth_session_info *session_info =
1083 session->global->auth_session_info;
1084 data_blob_clear_free(&x->global->application_key);
1085 data_blob_clear_free(&session_info->session_key);
1087 reply_nterror(req, nt_status);
1088 END_PROFILE(SMBtconX);
1093 server_devicetype = "IPC";
1094 else if ( IS_PRINT(conn) )
1095 server_devicetype = "LPT1:";
1097 server_devicetype = "A:";
1099 if (get_Protocol() < PROTOCOL_NT1) {
1100 reply_outbuf(req, 2, 0);
1101 if (message_push_string(&req->outbuf, server_devicetype,
1102 STR_TERMINATE|STR_ASCII) == -1) {
1103 reply_nterror(req, NT_STATUS_NO_MEMORY);
1104 END_PROFILE(SMBtconX);
1108 /* NT sets the fstype of IPC$ to the null string */
1109 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1111 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1112 /* Return permissions. */
1116 reply_outbuf(req, 7, 0);
1119 perm1 = FILE_ALL_ACCESS;
1120 perm2 = FILE_ALL_ACCESS;
1122 perm1 = conn->share_access;
1125 SIVAL(req->outbuf, smb_vwv3, perm1);
1126 SIVAL(req->outbuf, smb_vwv5, perm2);
1128 reply_outbuf(req, 3, 0);
1131 if ((message_push_string(&req->outbuf, server_devicetype,
1132 STR_TERMINATE|STR_ASCII) == -1)
1133 || (message_push_string(&req->outbuf, fstype,
1134 STR_TERMINATE) == -1)) {
1135 reply_nterror(req, NT_STATUS_NO_MEMORY);
1136 END_PROFILE(SMBtconX);
1140 /* what does setting this bit do? It is set by NT4 and
1141 may affect the ability to autorun mounted cdroms */
1142 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1144 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1146 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1147 DEBUG(2,("Serving %s as a Dfs root\n",
1148 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1149 optional_support |= SMB_SHARE_IN_DFS;
1152 SSVAL(req->outbuf, smb_vwv2, optional_support);
1155 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1156 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1158 DEBUG(3,("tconX service=%s \n",
1161 /* set the incoming and outgoing tid to the just created one */
1162 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1163 SSVAL(req->outbuf,smb_tid,conn->cnum);
1165 END_PROFILE(SMBtconX);
1167 req->tid = conn->cnum;
1170 /****************************************************************************
1171 Reply to an unknown type.
1172 ****************************************************************************/
1174 void reply_unknown_new(struct smb_request *req, uint8_t type)
1176 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1177 smb_fn_name(type), type, type));
1178 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1182 /****************************************************************************
1184 conn POINTER CAN BE NULL HERE !
1185 ****************************************************************************/
1187 void reply_ioctl(struct smb_request *req)
1189 const struct loadparm_substitution *lp_sub =
1190 loadparm_s3_global_substitution();
1191 connection_struct *conn = req->conn;
1194 uint32_t ioctl_code;
1198 START_PROFILE(SMBioctl);
1201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1202 END_PROFILE(SMBioctl);
1206 device = SVAL(req->vwv+1, 0);
1207 function = SVAL(req->vwv+2, 0);
1208 ioctl_code = (device << 16) + function;
1210 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1212 switch (ioctl_code) {
1213 case IOCTL_QUERY_JOB_INFO:
1217 reply_force_doserror(req, ERRSRV, ERRnosupport);
1218 END_PROFILE(SMBioctl);
1222 reply_outbuf(req, 8, replysize+1);
1223 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1224 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1225 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1226 p = smb_buf(req->outbuf);
1227 memset(p, '\0', replysize+1); /* valgrind-safe. */
1228 p += 1; /* Allow for alignment */
1230 switch (ioctl_code) {
1231 case IOCTL_QUERY_JOB_INFO:
1235 files_struct *fsp = file_fsp(
1236 req, SVAL(req->vwv+0, 0));
1238 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1239 END_PROFILE(SMBioctl);
1243 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1245 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1246 lp_netbios_name(), 15,
1247 STR_TERMINATE|STR_ASCII, &len);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 reply_nterror(req, status);
1250 END_PROFILE(SMBioctl);
1254 status = srvstr_push((char *)req->outbuf, req->flags2,
1256 lp_servicename(talloc_tos(),
1259 13, STR_TERMINATE|STR_ASCII, &len);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 reply_nterror(req, status);
1262 END_PROFILE(SMBioctl);
1266 memset(p+18, 0, 13);
1272 END_PROFILE(SMBioctl);
1276 /****************************************************************************
1277 Strange checkpath NTSTATUS mapping.
1278 ****************************************************************************/
1280 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1282 /* Strange DOS error code semantics only for checkpath... */
1283 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1284 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1285 /* We need to map to ERRbadpath */
1286 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1292 /****************************************************************************
1293 Reply to a checkpath.
1294 ****************************************************************************/
1296 void reply_checkpath(struct smb_request *req)
1298 connection_struct *conn = req->conn;
1299 struct smb_filename *smb_fname = NULL;
1302 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1303 TALLOC_CTX *ctx = talloc_tos();
1305 START_PROFILE(SMBcheckpath);
1307 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1308 STR_TERMINATE, &status);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 status = map_checkpath_error(req->flags2, status);
1312 reply_nterror(req, status);
1313 END_PROFILE(SMBcheckpath);
1317 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1319 status = filename_convert(ctx,
1327 if (!NT_STATUS_IS_OK(status)) {
1328 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1329 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1330 ERRSRV, ERRbadpath);
1331 END_PROFILE(SMBcheckpath);
1337 if (!VALID_STAT(smb_fname->st) &&
1338 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1339 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1340 smb_fname_str_dbg(smb_fname), strerror(errno)));
1341 status = map_nt_error_from_unix(errno);
1345 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1346 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1347 ERRDOS, ERRbadpath);
1351 reply_outbuf(req, 0, 0);
1354 /* We special case this - as when a Windows machine
1355 is parsing a path is steps through the components
1356 one at a time - if a component fails it expects
1357 ERRbadpath, not ERRbadfile.
1359 status = map_checkpath_error(req->flags2, status);
1360 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1362 * Windows returns different error codes if
1363 * the parent directory is valid but not the
1364 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1365 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1366 * if the path is invalid.
1368 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1369 ERRDOS, ERRbadpath);
1373 reply_nterror(req, status);
1376 TALLOC_FREE(smb_fname);
1377 END_PROFILE(SMBcheckpath);
1381 /****************************************************************************
1383 ****************************************************************************/
1385 void reply_getatr(struct smb_request *req)
1387 connection_struct *conn = req->conn;
1388 struct smb_filename *smb_fname = NULL;
1395 TALLOC_CTX *ctx = talloc_tos();
1396 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1398 START_PROFILE(SMBgetatr);
1400 p = (const char *)req->buf + 1;
1401 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1402 if (!NT_STATUS_IS_OK(status)) {
1403 reply_nterror(req, status);
1407 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1408 under WfWg - weird! */
1409 if (*fname == '\0') {
1410 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1411 if (!CAN_WRITE(conn)) {
1412 mode |= FILE_ATTRIBUTE_READONLY;
1417 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1418 status = filename_convert(ctx,
1425 if (!NT_STATUS_IS_OK(status)) {
1426 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1427 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1428 ERRSRV, ERRbadpath);
1431 reply_nterror(req, status);
1434 if (!VALID_STAT(smb_fname->st) &&
1435 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1436 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1437 smb_fname_str_dbg(smb_fname),
1439 reply_nterror(req, map_nt_error_from_unix(errno));
1443 mode = dos_mode(conn, smb_fname);
1444 size = smb_fname->st.st_ex_size;
1446 if (ask_sharemode) {
1447 struct timespec write_time_ts;
1448 struct file_id fileid;
1450 ZERO_STRUCT(write_time_ts);
1451 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1452 get_file_infos(fileid, 0, NULL, &write_time_ts);
1453 if (!is_omit_timespec(&write_time_ts)) {
1454 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1458 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1459 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1464 reply_outbuf(req, 10, 0);
1466 SSVAL(req->outbuf,smb_vwv0,mode);
1467 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1468 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1470 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1472 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1474 if (get_Protocol() >= PROTOCOL_NT1) {
1475 SSVAL(req->outbuf, smb_flg2,
1476 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1479 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1480 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1483 TALLOC_FREE(smb_fname);
1485 END_PROFILE(SMBgetatr);
1489 /****************************************************************************
1491 ****************************************************************************/
1493 void reply_setatr(struct smb_request *req)
1495 struct smb_file_time ft;
1496 connection_struct *conn = req->conn;
1497 struct smb_filename *smb_fname = NULL;
1503 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1504 TALLOC_CTX *ctx = talloc_tos();
1506 START_PROFILE(SMBsetatr);
1507 init_smb_file_time(&ft);
1510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1514 p = (const char *)req->buf + 1;
1515 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 reply_nterror(req, status);
1521 status = filename_convert(ctx,
1528 if (!NT_STATUS_IS_OK(status)) {
1529 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1530 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1531 ERRSRV, ERRbadpath);
1534 reply_nterror(req, status);
1538 if (ISDOT(smb_fname->base_name)) {
1540 * Not sure here is the right place to catch this
1541 * condition. Might be moved to somewhere else later -- vl
1543 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1547 mode = SVAL(req->vwv+0, 0);
1548 mtime = srv_make_unix_date3(req->vwv+1);
1550 if (mode != FILE_ATTRIBUTE_NORMAL) {
1551 if (VALID_STAT_OF_DIR(smb_fname->st))
1552 mode |= FILE_ATTRIBUTE_DIRECTORY;
1554 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1556 status = smbd_check_access_rights(conn,
1560 FILE_WRITE_ATTRIBUTES);
1561 if (!NT_STATUS_IS_OK(status)) {
1562 reply_nterror(req, status);
1566 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1568 reply_nterror(req, map_nt_error_from_unix(errno));
1573 ft.mtime = time_t_to_full_timespec(mtime);
1575 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1576 if (!NT_STATUS_IS_OK(status)) {
1577 reply_nterror(req, status);
1581 reply_outbuf(req, 0, 0);
1583 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1586 TALLOC_FREE(smb_fname);
1587 END_PROFILE(SMBsetatr);
1591 /****************************************************************************
1593 ****************************************************************************/
1595 void reply_dskattr(struct smb_request *req)
1597 connection_struct *conn = req->conn;
1599 uint64_t dfree,dsize,bsize;
1600 struct smb_filename smb_fname;
1601 START_PROFILE(SMBdskattr);
1603 ZERO_STRUCT(smb_fname);
1604 smb_fname.base_name = discard_const_p(char, ".");
1606 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1607 reply_nterror(req, map_nt_error_from_unix(errno));
1608 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1609 END_PROFILE(SMBdskattr);
1613 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1614 if (ret == (uint64_t)-1) {
1615 reply_nterror(req, map_nt_error_from_unix(errno));
1616 END_PROFILE(SMBdskattr);
1621 * Force max to fit in 16 bit fields.
1623 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1627 if (bsize > (WORDMAX*512)) {
1628 bsize = (WORDMAX*512);
1629 if (dsize > WORDMAX)
1631 if (dfree > WORDMAX)
1637 reply_outbuf(req, 5, 0);
1639 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1640 double total_space, free_space;
1641 /* we need to scale this to a number that DOS6 can handle. We
1642 use floating point so we can handle large drives on systems
1643 that don't have 64 bit integers
1645 we end up displaying a maximum of 2G to DOS systems
1647 total_space = dsize * (double)bsize;
1648 free_space = dfree * (double)bsize;
1650 dsize = (uint64_t)((total_space+63*512) / (64*512));
1651 dfree = (uint64_t)((free_space+63*512) / (64*512));
1653 if (dsize > 0xFFFF) dsize = 0xFFFF;
1654 if (dfree > 0xFFFF) dfree = 0xFFFF;
1656 SSVAL(req->outbuf,smb_vwv0,dsize);
1657 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1658 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1659 SSVAL(req->outbuf,smb_vwv3,dfree);
1661 SSVAL(req->outbuf,smb_vwv0,dsize);
1662 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1663 SSVAL(req->outbuf,smb_vwv2,512);
1664 SSVAL(req->outbuf,smb_vwv3,dfree);
1667 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1669 END_PROFILE(SMBdskattr);
1674 * Utility function to split the filename from the directory.
1676 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1677 char **fname_dir_out,
1678 char **fname_mask_out)
1680 const char *p = NULL;
1681 char *fname_dir = NULL;
1682 char *fname_mask = NULL;
1684 p = strrchr_m(fname_in, '/');
1686 fname_dir = talloc_strdup(ctx, ".");
1687 fname_mask = talloc_strdup(ctx, fname_in);
1689 fname_dir = talloc_strndup(ctx, fname_in,
1690 PTR_DIFF(p, fname_in));
1691 fname_mask = talloc_strdup(ctx, p+1);
1694 if (!fname_dir || !fname_mask) {
1695 TALLOC_FREE(fname_dir);
1696 TALLOC_FREE(fname_mask);
1697 return NT_STATUS_NO_MEMORY;
1700 *fname_dir_out = fname_dir;
1701 *fname_mask_out = fname_mask;
1702 return NT_STATUS_OK;
1705 /****************************************************************************
1707 ****************************************************************************/
1709 static bool make_dir_struct(TALLOC_CTX *ctx,
1719 char *mask2 = talloc_strdup(ctx, mask);
1725 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1729 memset(buf+1,' ',11);
1730 if ((p = strchr_m(mask2,'.')) != NULL) {
1732 push_ascii(buf+1,mask2,8, 0);
1733 push_ascii(buf+9,p+1,3, 0);
1736 push_ascii(buf+1,mask2,11, 0);
1739 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1741 srv_put_dos_date(buf,22,date);
1742 SSVAL(buf,26,size & 0xFFFF);
1743 SSVAL(buf,28,(size >> 16)&0xFFFF);
1744 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1745 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1746 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1747 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1751 /****************************************************************************
1753 Can be called from SMBsearch, SMBffirst or SMBfunique.
1754 ****************************************************************************/
1756 void reply_search(struct smb_request *req)
1758 connection_struct *conn = req->conn;
1761 char *directory = NULL;
1762 struct smb_filename *smb_fname = NULL;
1766 struct timespec date;
1768 unsigned int numentries = 0;
1769 unsigned int maxentries = 0;
1770 bool finished = False;
1775 bool check_descend = False;
1776 bool expect_close = False;
1778 bool mask_contains_wcard = False;
1779 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1780 TALLOC_CTX *ctx = talloc_tos();
1781 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1782 struct smbXsrv_connection *xconn = req->xconn;
1783 struct smbd_server_connection *sconn = req->sconn;
1784 files_struct *fsp = NULL;
1785 const struct loadparm_substitution *lp_sub =
1786 loadparm_s3_global_substitution();
1788 START_PROFILE(SMBsearch);
1791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1795 if (req->posix_pathnames) {
1796 reply_unknown_new(req, req->cmd);
1800 /* If we were called as SMBffirst then we must expect close. */
1801 if(req->cmd == SMBffirst) {
1802 expect_close = True;
1805 reply_outbuf(req, 1, 3);
1806 maxentries = SVAL(req->vwv+0, 0);
1807 dirtype = SVAL(req->vwv+1, 0);
1808 p = (const char *)req->buf + 1;
1809 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1810 &nt_status, &mask_contains_wcard);
1811 if (!NT_STATUS_IS_OK(nt_status)) {
1812 reply_nterror(req, nt_status);
1816 if (smbreq_bufrem(req, p) < 3) {
1817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1822 status_len = SVAL(p, 0);
1825 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1827 if (status_len == 0) {
1829 struct smb_filename *smb_dname = NULL;
1830 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1831 ucf_flags_from_smb_request(req);
1832 nt_status = filename_convert(ctx, conn,
1836 &mask_contains_wcard,
1838 if (!NT_STATUS_IS_OK(nt_status)) {
1839 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1840 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1841 ERRSRV, ERRbadpath);
1844 reply_nterror(req, nt_status);
1848 directory = smb_fname->base_name;
1850 p = strrchr_m(directory,'/');
1851 if ((p != NULL) && (*directory != '/')) {
1852 mask = talloc_strdup(ctx, p + 1);
1853 directory = talloc_strndup(ctx, directory,
1854 PTR_DIFF(p, directory));
1856 mask = talloc_strdup(ctx, directory);
1857 directory = talloc_strdup(ctx,".");
1861 reply_nterror(req, NT_STATUS_NO_MEMORY);
1865 memset((char *)status,'\0',21);
1866 SCVAL(status,0,(dirtype & 0x1F));
1868 smb_dname = synthetic_smb_fname(talloc_tos(),
1874 if (smb_dname == NULL) {
1875 reply_nterror(req, NT_STATUS_NO_MEMORY);
1880 * As we've cut off the last component from
1881 * smb_fname we need to re-stat smb_dname
1882 * so FILE_OPEN disposition knows the directory
1885 if (req->posix_pathnames) {
1886 ret = SMB_VFS_LSTAT(conn, smb_dname);
1888 ret = SMB_VFS_STAT(conn, smb_dname);
1891 nt_status = map_nt_error_from_unix(errno);
1892 reply_nterror(req, nt_status);
1897 * Open an fsp on this directory for the dptr.
1899 nt_status = SMB_VFS_CREATE_FILE(
1902 &conn->cwd_fsp, /* dirfsp */
1903 smb_dname, /* dname */
1904 FILE_LIST_DIRECTORY, /* access_mask */
1906 FILE_SHARE_WRITE, /* share_access */
1907 FILE_OPEN, /* create_disposition*/
1908 FILE_DIRECTORY_FILE, /* create_options */
1909 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1910 NO_OPLOCK, /* oplock_request */
1912 0, /* allocation_size */
1913 0, /* private_flags */
1918 NULL, /* in_context */
1919 NULL);/* out_context */
1921 if (!NT_STATUS_IS_OK(nt_status)) {
1922 DBG_ERR("failed to open directory %s\n",
1923 smb_fname_str_dbg(smb_dname));
1924 reply_nterror(req, nt_status);
1928 nt_status = dptr_create(conn,
1935 mask_contains_wcard,
1939 TALLOC_FREE(smb_dname);
1941 if (!NT_STATUS_IS_OK(nt_status)) {
1943 * Use NULL here for the first parameter (req)
1944 * as this is not a client visible handle so
1945 * can'tbe part of an SMB1 chain.
1947 close_file(NULL, fsp, NORMAL_CLOSE);
1949 reply_nterror(req, nt_status);
1953 dptr_num = dptr_dnum(fsp->dptr);
1957 const char *dirpath;
1959 if (smbreq_bufrem(req, p) < 21) {
1960 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1964 memcpy(status,p,21);
1965 status_dirtype = CVAL(status,0) & 0x1F;
1966 if (status_dirtype != (dirtype & 0x1F)) {
1967 dirtype = status_dirtype;
1970 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1974 dirpath = dptr_path(sconn, dptr_num);
1975 directory = talloc_strdup(ctx, dirpath);
1977 reply_nterror(req, NT_STATUS_NO_MEMORY);
1981 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1986 * For a 'continue' search we have no string. So
1987 * check from the initial saved string.
1989 if (!req->posix_pathnames) {
1990 mask_contains_wcard = ms_has_wild(mask);
1992 dirtype = dptr_attr(sconn, dptr_num);
1995 DEBUG(4,("dptr_num is %d\n",dptr_num));
1997 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1998 char buf[DIR_STRUCT_SIZE];
1999 memcpy(buf,status,21);
2000 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
2001 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
2002 reply_nterror(req, NT_STATUS_NO_MEMORY);
2005 dptr_fill(sconn, buf+12,dptr_num);
2006 if (dptr_zero(buf+12) && (status_len==0)) {
2011 if (message_push_blob(&req->outbuf,
2012 data_blob_const(buf, sizeof(buf)))
2014 reply_nterror(req, NT_STATUS_NO_MEMORY);
2019 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
2020 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
2022 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
2024 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2025 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
2026 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
2027 check_descend = True;
2030 for (i=numentries;(i<maxentries) && !finished;i++) {
2031 finished = !get_dir_entry(ctx,
2042 char buf[DIR_STRUCT_SIZE];
2043 memcpy(buf,status,21);
2044 if (!make_dir_struct(ctx,
2050 convert_timespec_to_time_t(date),
2051 !allow_long_path_components)) {
2052 reply_nterror(req, NT_STATUS_NO_MEMORY);
2055 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2058 if (message_push_blob(&req->outbuf,
2059 data_blob_const(buf, sizeof(buf)))
2061 reply_nterror(req, NT_STATUS_NO_MEMORY);
2071 /* If we were called as SMBffirst with smb_search_id == NULL
2072 and no entries were found then return error and close fsp->dptr
2075 if (numentries == 0) {
2078 close_file(NULL, fsp, NORMAL_CLOSE);
2081 } else if(expect_close && status_len == 0) {
2082 /* Close the dptr - we know it's gone */
2085 close_file(NULL, fsp, NORMAL_CLOSE);
2090 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2091 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2093 /* fsp may have been closed above. */
2095 close_file(NULL, fsp, NORMAL_CLOSE);
2100 if ((numentries == 0) && !mask_contains_wcard) {
2101 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2105 SSVAL(req->outbuf,smb_vwv0,numentries);
2106 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2107 SCVAL(smb_buf(req->outbuf),0,5);
2108 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2110 /* The replies here are never long name. */
2111 SSVAL(req->outbuf, smb_flg2,
2112 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2113 if (!allow_long_path_components) {
2114 SSVAL(req->outbuf, smb_flg2,
2115 SVAL(req->outbuf, smb_flg2)
2116 & (~FLAGS2_LONG_PATH_COMPONENTS));
2119 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2120 SSVAL(req->outbuf, smb_flg2,
2121 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2123 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2124 smb_fn_name(req->cmd),
2131 TALLOC_FREE(directory);
2133 TALLOC_FREE(smb_fname);
2134 END_PROFILE(SMBsearch);
2138 /****************************************************************************
2139 Reply to a fclose (stop directory search).
2140 ****************************************************************************/
2142 void reply_fclose(struct smb_request *req)
2150 bool path_contains_wcard = False;
2151 TALLOC_CTX *ctx = talloc_tos();
2152 struct smbd_server_connection *sconn = req->sconn;
2153 files_struct *fsp = NULL;
2155 START_PROFILE(SMBfclose);
2157 if (req->posix_pathnames) {
2158 reply_unknown_new(req, req->cmd);
2159 END_PROFILE(SMBfclose);
2163 p = (const char *)req->buf + 1;
2164 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2165 &err, &path_contains_wcard);
2166 if (!NT_STATUS_IS_OK(err)) {
2167 reply_nterror(req, err);
2168 END_PROFILE(SMBfclose);
2172 if (smbreq_bufrem(req, p) < 3) {
2173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2174 END_PROFILE(SMBfclose);
2179 status_len = SVAL(p,0);
2182 if (status_len == 0) {
2183 reply_force_doserror(req, ERRSRV, ERRsrverror);
2184 END_PROFILE(SMBfclose);
2188 if (smbreq_bufrem(req, p) < 21) {
2189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2190 END_PROFILE(SMBfclose);
2194 memcpy(status,p,21);
2196 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2198 /* Close the file - we know it's gone */
2199 close_file(NULL, fsp, NORMAL_CLOSE);
2204 reply_outbuf(req, 1, 0);
2205 SSVAL(req->outbuf,smb_vwv0,0);
2207 DEBUG(3,("search close\n"));
2209 END_PROFILE(SMBfclose);
2213 /****************************************************************************
2215 ****************************************************************************/
2217 void reply_open(struct smb_request *req)
2219 connection_struct *conn = req->conn;
2220 struct smb_filename *smb_fname = NULL;
2230 uint32_t access_mask;
2231 uint32_t share_mode;
2232 uint32_t create_disposition;
2233 uint32_t create_options = 0;
2234 uint32_t private_flags = 0;
2237 TALLOC_CTX *ctx = talloc_tos();
2239 START_PROFILE(SMBopen);
2242 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2246 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2247 deny_mode = SVAL(req->vwv+0, 0);
2248 dos_attr = SVAL(req->vwv+1, 0);
2250 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2251 STR_TERMINATE, &status);
2252 if (!NT_STATUS_IS_OK(status)) {
2253 reply_nterror(req, status);
2257 if (!map_open_params_to_ntcreate(fname, deny_mode,
2258 OPENX_FILE_EXISTS_OPEN, &access_mask,
2259 &share_mode, &create_disposition,
2260 &create_options, &private_flags)) {
2261 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2265 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2267 status = filename_convert(ctx,
2274 if (!NT_STATUS_IS_OK(status)) {
2275 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2276 reply_botherror(req,
2277 NT_STATUS_PATH_NOT_COVERED,
2278 ERRSRV, ERRbadpath);
2281 reply_nterror(req, status);
2285 status = SMB_VFS_CREATE_FILE(
2288 &conn->cwd_fsp, /* dirfsp */
2289 smb_fname, /* fname */
2290 access_mask, /* access_mask */
2291 share_mode, /* share_access */
2292 create_disposition, /* create_disposition*/
2293 create_options, /* create_options */
2294 dos_attr, /* file_attributes */
2295 oplock_request, /* oplock_request */
2297 0, /* allocation_size */
2303 NULL, NULL); /* create context */
2305 if (!NT_STATUS_IS_OK(status)) {
2306 if (open_was_deferred(req->xconn, req->mid)) {
2307 /* We have re-scheduled this call. */
2311 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2312 reply_openerror(req, status);
2316 fsp = fcb_or_dos_open(
2323 bool ok = defer_smb1_sharing_violation(req);
2327 reply_openerror(req, status);
2332 /* Ensure we're pointing at the correct stat struct. */
2333 TALLOC_FREE(smb_fname);
2334 smb_fname = fsp->fsp_name;
2336 size = smb_fname->st.st_ex_size;
2337 fattr = dos_mode(conn, smb_fname);
2339 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2341 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2342 DEBUG(3,("attempt to open a directory %s\n",
2344 close_file(req, fsp, ERROR_CLOSE);
2345 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2346 ERRDOS, ERRnoaccess);
2350 reply_outbuf(req, 7, 0);
2351 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2352 SSVAL(req->outbuf,smb_vwv1,fattr);
2353 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2354 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2356 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2358 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2359 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2361 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2362 SCVAL(req->outbuf,smb_flg,
2363 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2366 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2367 SCVAL(req->outbuf,smb_flg,
2368 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2371 END_PROFILE(SMBopen);
2375 /****************************************************************************
2376 Reply to an open and X.
2377 ****************************************************************************/
2379 void reply_open_and_X(struct smb_request *req)
2381 connection_struct *conn = req->conn;
2382 struct smb_filename *smb_fname = NULL;
2384 uint16_t open_flags;
2387 /* Breakout the oplock request bits so we can set the
2388 reply bits separately. */
2389 int ex_oplock_request;
2390 int core_oplock_request;
2393 int smb_sattr = SVAL(req->vwv+4, 0);
2394 uint32_t smb_time = make_unix_date3(req->vwv+6);
2402 uint64_t allocation_size;
2403 ssize_t retval = -1;
2404 uint32_t access_mask;
2405 uint32_t share_mode;
2406 uint32_t create_disposition;
2407 uint32_t create_options = 0;
2408 uint32_t private_flags = 0;
2410 TALLOC_CTX *ctx = talloc_tos();
2412 START_PROFILE(SMBopenX);
2414 if (req->wct < 15) {
2415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2419 open_flags = SVAL(req->vwv+2, 0);
2420 deny_mode = SVAL(req->vwv+3, 0);
2421 smb_attr = SVAL(req->vwv+5, 0);
2422 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2423 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2424 oplock_request = ex_oplock_request | core_oplock_request;
2425 smb_ofun = SVAL(req->vwv+8, 0);
2426 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2428 /* If it's an IPC, pass off the pipe handler. */
2430 if (lp_nt_pipe_support()) {
2431 reply_open_pipe_and_X(conn, req);
2433 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2438 /* XXXX we need to handle passed times, sattr and flags */
2439 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2440 STR_TERMINATE, &status);
2441 if (!NT_STATUS_IS_OK(status)) {
2442 reply_nterror(req, status);
2446 if (!map_open_params_to_ntcreate(fname, deny_mode,
2448 &access_mask, &share_mode,
2449 &create_disposition,
2452 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2456 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2458 status = filename_convert(ctx,
2465 if (!NT_STATUS_IS_OK(status)) {
2466 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2467 reply_botherror(req,
2468 NT_STATUS_PATH_NOT_COVERED,
2469 ERRSRV, ERRbadpath);
2472 reply_nterror(req, status);
2476 status = SMB_VFS_CREATE_FILE(
2479 &conn->cwd_fsp, /* dirfsp */
2480 smb_fname, /* fname */
2481 access_mask, /* access_mask */
2482 share_mode, /* share_access */
2483 create_disposition, /* create_disposition*/
2484 create_options, /* create_options */
2485 smb_attr, /* file_attributes */
2486 oplock_request, /* oplock_request */
2488 0, /* allocation_size */
2493 &smb_action, /* pinfo */
2494 NULL, NULL); /* create context */
2496 if (!NT_STATUS_IS_OK(status)) {
2497 if (open_was_deferred(req->xconn, req->mid)) {
2498 /* We have re-scheduled this call. */
2502 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2503 reply_openerror(req, status);
2507 fsp = fcb_or_dos_open(
2514 bool ok = defer_smb1_sharing_violation(req);
2518 reply_openerror(req, status);
2523 smb_action = FILE_WAS_OPENED;
2526 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2527 if the file is truncated or created. */
2528 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2529 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2530 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2531 close_file(req, fsp, ERROR_CLOSE);
2532 reply_nterror(req, NT_STATUS_DISK_FULL);
2535 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2537 close_file(req, fsp, ERROR_CLOSE);
2538 reply_nterror(req, NT_STATUS_DISK_FULL);
2541 status = vfs_stat_fsp(fsp);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 close_file(req, fsp, ERROR_CLOSE);
2544 reply_nterror(req, status);
2549 fattr = dos_mode(conn, fsp->fsp_name);
2550 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2551 close_file(req, fsp, ERROR_CLOSE);
2552 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2555 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2557 /* If the caller set the extended oplock request bit
2558 and we granted one (by whatever means) - set the
2559 correct bit for extended oplock reply.
2562 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2563 smb_action |= EXTENDED_OPLOCK_GRANTED;
2566 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2567 smb_action |= EXTENDED_OPLOCK_GRANTED;
2570 /* If the caller set the core oplock request bit
2571 and we granted one (by whatever means) - set the
2572 correct bit for core oplock reply.
2575 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2576 reply_outbuf(req, 19, 0);
2578 reply_outbuf(req, 15, 0);
2581 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2582 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2584 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2585 SCVAL(req->outbuf, smb_flg,
2586 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2589 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2590 SCVAL(req->outbuf, smb_flg,
2591 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2594 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2595 SSVAL(req->outbuf,smb_vwv3,fattr);
2596 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2597 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2599 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2601 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2602 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2603 SSVAL(req->outbuf,smb_vwv11,smb_action);
2605 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2606 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2610 TALLOC_FREE(smb_fname);
2611 END_PROFILE(SMBopenX);
2615 /****************************************************************************
2616 Reply to a SMBulogoffX.
2617 ****************************************************************************/
2619 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2620 struct smbXsrv_session *session);
2621 static void reply_ulogoffX_done(struct tevent_req *req);
2623 void reply_ulogoffX(struct smb_request *smb1req)
2625 struct timeval now = timeval_current();
2626 struct smbXsrv_session *session = NULL;
2627 struct tevent_req *req;
2631 * Don't setup the profile charge here, take
2632 * it in reply_ulogoffX_done(). Not strictly correct
2633 * but better than the other SMB1 async
2634 * code that double-charges at the moment.
2637 status = smb1srv_session_lookup(smb1req->xconn,
2639 timeval_to_nttime(&now),
2641 if (!NT_STATUS_IS_OK(status)) {
2642 /* Not going async, profile here. */
2643 START_PROFILE(SMBulogoffX);
2644 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2645 (unsigned long long)smb1req->vuid);
2647 smb1req->vuid = UID_FIELD_INVALID;
2648 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2649 END_PROFILE(SMBulogoffX);
2653 req = reply_ulogoffX_send(smb1req, session);
2655 /* Not going async, profile here. */
2656 START_PROFILE(SMBulogoffX);
2657 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2658 END_PROFILE(SMBulogoffX);
2662 /* We're async. This will complete later. */
2663 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2667 struct reply_ulogoffX_state {
2668 struct tevent_queue *wait_queue;
2669 struct smbXsrv_session *session;
2672 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2674 /****************************************************************************
2675 Async SMB1 ulogoffX.
2676 Note, on failure here we deallocate and return NULL to allow the caller to
2677 SMB1 return an error of ERRnomem immediately.
2678 ****************************************************************************/
2680 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2681 struct smbXsrv_session *session)
2683 struct tevent_req *req;
2684 struct reply_ulogoffX_state *state;
2685 struct tevent_req *subreq;
2687 struct smbd_server_connection *sconn = session->client->sconn;
2688 uint64_t vuid = session->global->session_wire_id;
2690 req = tevent_req_create(smb1req, &state,
2691 struct reply_ulogoffX_state);
2695 state->wait_queue = tevent_queue_create(state,
2696 "reply_ulogoffX_wait_queue");
2697 if (tevent_req_nomem(state->wait_queue, req)) {
2701 state->session = session;
2704 * Make sure that no new request will be able to use this session.
2705 * This ensures that once all outstanding fsp->aio_requests
2706 * on this session are done, we are safe to close it.
2708 session->status = NT_STATUS_USER_SESSION_DELETED;
2710 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2711 if (fsp->vuid != vuid) {
2715 * Flag the file as close in progress.
2716 * This will prevent any more IO being
2719 fsp->fsp_flags.closing = true;
2721 if (fsp->num_aio_requests > 0) {
2723 * Now wait until all aio requests on this fsp are
2726 * We don't set a callback, as we just want to block the
2727 * wait queue and the talloc_free() of fsp->aio_request
2728 * will remove the item from the wait queue.
2730 subreq = tevent_queue_wait_send(fsp->aio_requests,
2733 if (tevent_req_nomem(subreq, req)) {
2741 * Now we add our own waiter to the end of the queue,
2742 * this way we get notified when all pending requests are finished
2743 * and reply to the outstanding SMB1 request.
2745 subreq = tevent_queue_wait_send(state,
2748 if (tevent_req_nomem(subreq, req)) {
2754 * We're really going async - move the SMB1 request from
2755 * a talloc stackframe above us to the sconn talloc-context.
2756 * We need this to stick around until the wait_done
2757 * callback is invoked.
2759 smb1req = talloc_move(sconn, &smb1req);
2761 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2766 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2768 struct tevent_req *req = tevent_req_callback_data(
2769 subreq, struct tevent_req);
2771 tevent_queue_wait_recv(subreq);
2772 TALLOC_FREE(subreq);
2773 tevent_req_done(req);
2776 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2778 return tevent_req_simple_recv_ntstatus(req);
2781 static void reply_ulogoffX_done(struct tevent_req *req)
2783 struct smb_request *smb1req = tevent_req_callback_data(
2784 req, struct smb_request);
2785 struct reply_ulogoffX_state *state = tevent_req_data(req,
2786 struct reply_ulogoffX_state);
2787 struct smbXsrv_session *session = state->session;
2791 * Take the profile charge here. Not strictly
2792 * correct but better than the other SMB1 async
2793 * code that double-charges at the moment.
2795 START_PROFILE(SMBulogoffX);
2797 status = reply_ulogoffX_recv(req);
2799 if (!NT_STATUS_IS_OK(status)) {
2800 TALLOC_FREE(smb1req);
2801 END_PROFILE(SMBulogoffX);
2802 exit_server(__location__ ": reply_ulogoffX_recv failed");
2806 status = smbXsrv_session_logoff(session);
2807 if (!NT_STATUS_IS_OK(status)) {
2808 TALLOC_FREE(smb1req);
2809 END_PROFILE(SMBulogoffX);
2810 exit_server(__location__ ": smbXsrv_session_logoff failed");
2814 TALLOC_FREE(session);
2816 reply_outbuf(smb1req, 2, 0);
2817 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2818 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2820 DBG_NOTICE("ulogoffX vuid=%llu\n",
2821 (unsigned long long)smb1req->vuid);
2823 smb1req->vuid = UID_FIELD_INVALID;
2825 * The following call is needed to push the
2826 * reply data back out the socket after async
2827 * return. Plus it frees smb1req.
2829 smb_request_done(smb1req);
2830 END_PROFILE(SMBulogoffX);
2833 /****************************************************************************
2834 Reply to a mknew or a create.
2835 ****************************************************************************/
2837 void reply_mknew(struct smb_request *req)
2839 connection_struct *conn = req->conn;
2840 struct smb_filename *smb_fname = NULL;
2843 struct smb_file_time ft;
2845 int oplock_request = 0;
2847 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2848 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2849 uint32_t create_disposition;
2850 uint32_t create_options = 0;
2852 TALLOC_CTX *ctx = talloc_tos();
2854 START_PROFILE(SMBcreate);
2855 init_smb_file_time(&ft);
2858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2862 fattr = SVAL(req->vwv+0, 0);
2863 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2865 if (req->cmd == SMBmknew) {
2866 /* We should fail if file exists. */
2867 create_disposition = FILE_CREATE;
2869 /* Create if file doesn't exist, truncate if it does. */
2870 create_disposition = FILE_OVERWRITE_IF;
2874 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2876 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2877 STR_TERMINATE, &status);
2878 if (!NT_STATUS_IS_OK(status)) {
2879 reply_nterror(req, status);
2883 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2884 status = filename_convert(ctx,
2891 if (!NT_STATUS_IS_OK(status)) {
2892 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2893 reply_botherror(req,
2894 NT_STATUS_PATH_NOT_COVERED,
2895 ERRSRV, ERRbadpath);
2898 reply_nterror(req, status);
2902 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2903 DEBUG(0,("Attempt to create file (%s) with volid set - "
2904 "please report this\n",
2905 smb_fname_str_dbg(smb_fname)));
2908 status = SMB_VFS_CREATE_FILE(
2911 &conn->cwd_fsp, /* dirfsp */
2912 smb_fname, /* fname */
2913 access_mask, /* access_mask */
2914 share_mode, /* share_access */
2915 create_disposition, /* create_disposition*/
2916 create_options, /* create_options */
2917 fattr, /* file_attributes */
2918 oplock_request, /* oplock_request */
2920 0, /* allocation_size */
2921 0, /* private_flags */
2926 NULL, NULL); /* create context */
2928 if (!NT_STATUS_IS_OK(status)) {
2929 if (open_was_deferred(req->xconn, req->mid)) {
2930 /* We have re-scheduled this call. */
2933 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2934 bool ok = defer_smb1_sharing_violation(req);
2939 reply_openerror(req, status);
2943 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2944 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2945 if (!NT_STATUS_IS_OK(status)) {
2946 END_PROFILE(SMBcreate);
2950 reply_outbuf(req, 1, 0);
2951 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2953 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2954 SCVAL(req->outbuf,smb_flg,
2955 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2958 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2959 SCVAL(req->outbuf,smb_flg,
2960 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2963 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2964 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2965 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2966 (unsigned int)fattr));
2969 TALLOC_FREE(smb_fname);
2970 END_PROFILE(SMBcreate);
2974 /****************************************************************************
2975 Reply to a create temporary file.
2976 ****************************************************************************/
2978 void reply_ctemp(struct smb_request *req)
2980 connection_struct *conn = req->conn;
2981 struct smb_filename *smb_fname = NULL;
2982 char *wire_name = NULL;
2991 TALLOC_CTX *ctx = talloc_tos();
2993 START_PROFILE(SMBctemp);
2996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3000 fattr = SVAL(req->vwv+0, 0);
3001 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
3003 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
3004 STR_TERMINATE, &status);
3005 if (!NT_STATUS_IS_OK(status)) {
3006 reply_nterror(req, status);
3010 for (i = 0; i < 10; i++) {
3012 fname = talloc_asprintf(ctx,
3015 generate_random_str_list(ctx, 5, "0123456789"));
3017 fname = talloc_asprintf(ctx,
3019 generate_random_str_list(ctx, 5, "0123456789"));
3023 reply_nterror(req, NT_STATUS_NO_MEMORY);
3027 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
3028 status = filename_convert(ctx, conn,
3034 if (!NT_STATUS_IS_OK(status)) {
3035 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3036 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3037 ERRSRV, ERRbadpath);
3040 reply_nterror(req, status);
3044 /* Create the file. */
3045 status = SMB_VFS_CREATE_FILE(
3048 &conn->cwd_fsp, /* dirfsp */
3049 smb_fname, /* fname */
3050 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
3051 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
3052 FILE_CREATE, /* create_disposition*/
3053 0, /* create_options */
3054 fattr, /* file_attributes */
3055 oplock_request, /* oplock_request */
3057 0, /* allocation_size */
3058 0, /* private_flags */
3063 NULL, NULL); /* create context */
3065 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3067 TALLOC_FREE(smb_fname);
3071 if (!NT_STATUS_IS_OK(status)) {
3072 if (open_was_deferred(req->xconn, req->mid)) {
3073 /* We have re-scheduled this call. */
3076 if (NT_STATUS_EQUAL(
3077 status, NT_STATUS_SHARING_VIOLATION)) {
3078 bool ok = defer_smb1_sharing_violation(req);
3083 reply_openerror(req, status);
3091 /* Collision after 10 times... */
3092 reply_nterror(req, status);
3096 reply_outbuf(req, 1, 0);
3097 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3099 /* the returned filename is relative to the directory */
3100 s = strrchr_m(fsp->fsp_name->base_name, '/');
3102 s = fsp->fsp_name->base_name;
3108 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3109 thing in the byte section. JRA */
3110 SSVALS(p, 0, -1); /* what is this? not in spec */
3112 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3114 reply_nterror(req, NT_STATUS_NO_MEMORY);
3118 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3119 SCVAL(req->outbuf, smb_flg,
3120 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3123 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3124 SCVAL(req->outbuf, smb_flg,
3125 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3128 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3129 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3130 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
3132 TALLOC_FREE(smb_fname);
3133 TALLOC_FREE(wire_name);
3134 END_PROFILE(SMBctemp);
3138 /*******************************************************************
3139 Check if a user is allowed to rename a file.
3140 ********************************************************************/
3142 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3145 if (!CAN_WRITE(conn)) {
3146 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3149 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3150 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3151 /* Only bother to read the DOS attribute if we might deny the
3152 rename on the grounds of attribute mismatch. */
3153 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3154 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3155 return NT_STATUS_NO_SUCH_FILE;
3159 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3160 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3161 return NT_STATUS_OK;
3164 /* If no pathnames are open below this
3165 directory, allow the rename. */
3167 if (lp_strict_rename(SNUM(conn))) {
3169 * Strict rename, check open file db.
3171 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3172 return NT_STATUS_ACCESS_DENIED;
3174 } else if (file_find_subpath(fsp)) {
3176 * No strict rename, just look in local process.
3178 return NT_STATUS_ACCESS_DENIED;
3180 return NT_STATUS_OK;
3183 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3184 return NT_STATUS_OK;
3187 return NT_STATUS_ACCESS_DENIED;
3190 /*******************************************************************
3191 * unlink a file with all relevant access checks
3192 *******************************************************************/
3194 static NTSTATUS do_unlink(connection_struct *conn,
3195 struct smb_request *req,
3196 struct smb_filename *smb_fname,
3201 uint32_t dirtype_orig = dirtype;
3204 bool posix_paths = (req != NULL && req->posix_pathnames);
3205 struct smb2_create_blobs *posx = NULL;
3207 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3208 smb_fname_str_dbg(smb_fname),
3211 if (!CAN_WRITE(conn)) {
3212 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3216 ret = SMB_VFS_LSTAT(conn, smb_fname);
3218 ret = SMB_VFS_STAT(conn, smb_fname);
3221 return map_nt_error_from_unix(errno);
3224 fattr = dos_mode(conn, smb_fname);
3226 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3227 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3230 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3232 return NT_STATUS_NO_SUCH_FILE;
3235 if (!dir_check_ftype(fattr, dirtype)) {
3236 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3237 return NT_STATUS_FILE_IS_A_DIRECTORY;
3239 return NT_STATUS_NO_SUCH_FILE;
3242 if (dirtype_orig & 0x8000) {
3243 /* These will never be set for POSIX. */
3244 return NT_STATUS_NO_SUCH_FILE;
3248 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3249 return NT_STATUS_FILE_IS_A_DIRECTORY;
3252 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3253 return NT_STATUS_NO_SUCH_FILE;
3256 if (dirtype & 0xFF00) {
3257 /* These will never be set for POSIX. */
3258 return NT_STATUS_NO_SUCH_FILE;
3263 return NT_STATUS_NO_SUCH_FILE;
3266 /* Can't delete a directory. */
3267 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3268 return NT_STATUS_FILE_IS_A_DIRECTORY;
3273 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3274 return NT_STATUS_OBJECT_NAME_INVALID;
3275 #endif /* JRATEST */
3278 status = make_smb2_posix_create_ctx(
3279 talloc_tos(), &posx, 0777);
3280 if (!NT_STATUS_IS_OK(status)) {
3281 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3287 /* On open checks the open itself will check the share mode, so
3288 don't do it here as we'll get it wrong. */
3290 status = SMB_VFS_CREATE_FILE
3293 &conn->cwd_fsp, /* dirfsp */
3294 smb_fname, /* fname */
3295 DELETE_ACCESS, /* access_mask */
3296 FILE_SHARE_NONE, /* share_access */
3297 FILE_OPEN, /* create_disposition*/
3298 FILE_NON_DIRECTORY_FILE, /* create_options */
3299 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3300 0, /* oplock_request */
3302 0, /* allocation_size */
3303 0, /* private_flags */
3308 posx, /* in_context_blobs */
3309 NULL); /* out_context_blobs */
3313 if (!NT_STATUS_IS_OK(status)) {
3314 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3315 nt_errstr(status)));
3319 status = can_set_delete_on_close(fsp, fattr);
3320 if (!NT_STATUS_IS_OK(status)) {
3321 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3323 smb_fname_str_dbg(smb_fname),
3324 nt_errstr(status)));
3325 close_file(req, fsp, NORMAL_CLOSE);
3329 /* The set is across all open files on this dev/inode pair. */
3330 if (!set_delete_on_close(fsp, True,
3331 conn->session_info->security_token,
3332 conn->session_info->unix_token)) {
3333 close_file(req, fsp, NORMAL_CLOSE);
3334 return NT_STATUS_ACCESS_DENIED;
3337 return close_file(req, fsp, NORMAL_CLOSE);
3340 /****************************************************************************
3341 The guts of the unlink command, split out so it may be called by the NT SMB
3343 ****************************************************************************/
3345 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3346 uint32_t dirtype, struct smb_filename *smb_fname,
3349 char *fname_dir = NULL;
3350 char *fname_mask = NULL;
3352 NTSTATUS status = NT_STATUS_OK;
3353 struct smb_filename *smb_fname_dir = NULL;
3354 TALLOC_CTX *ctx = talloc_tos();
3356 /* Split up the directory from the filename/mask. */
3357 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3358 &fname_dir, &fname_mask);
3359 if (!NT_STATUS_IS_OK(status)) {
3364 * We should only check the mangled cache
3365 * here if unix_convert failed. This means
3366 * that the path in 'mask' doesn't exist
3367 * on the file system and so we need to look
3368 * for a possible mangle. This patch from
3369 * Tine Smukavec <valentin.smukavec@hermes.si>.
3372 if (!VALID_STAT(smb_fname->st) &&
3373 mangle_is_mangled(fname_mask, conn->params)) {
3374 char *new_mask = NULL;
3375 mangle_lookup_name_from_8_3(ctx, fname_mask,
3376 &new_mask, conn->params);
3378 TALLOC_FREE(fname_mask);
3379 fname_mask = new_mask;
3386 * Only one file needs to be unlinked. Append the mask back
3387 * onto the directory.
3389 TALLOC_FREE(smb_fname->base_name);
3390 if (ISDOT(fname_dir)) {
3391 /* Ensure we use canonical names on open. */
3392 smb_fname->base_name = talloc_asprintf(smb_fname,
3396 smb_fname->base_name = talloc_asprintf(smb_fname,
3401 if (!smb_fname->base_name) {
3402 status = NT_STATUS_NO_MEMORY;
3406 dirtype = FILE_ATTRIBUTE_NORMAL;
3409 status = check_name(conn, smb_fname);
3410 if (!NT_STATUS_IS_OK(status)) {
3414 status = do_unlink(conn, req, smb_fname, dirtype);
3415 if (!NT_STATUS_IS_OK(status)) {
3421 struct smb_Dir *dir_hnd = NULL;
3423 const char *dname = NULL;
3424 char *talloced = NULL;
3426 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3427 status = NT_STATUS_OBJECT_NAME_INVALID;
3431 dirtype = FILE_ATTRIBUTE_NORMAL;
3434 if (strequal(fname_mask,"????????.???")) {
3435 TALLOC_FREE(fname_mask);
3436 fname_mask = talloc_strdup(ctx, "*");
3438 status = NT_STATUS_NO_MEMORY;
3443 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3449 if (smb_fname_dir == NULL) {
3450 status = NT_STATUS_NO_MEMORY;
3454 status = check_name(conn, smb_fname_dir);
3455 if (!NT_STATUS_IS_OK(status)) {
3459 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3461 if (dir_hnd == NULL) {
3462 status = map_nt_error_from_unix(errno);
3466 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3467 the pattern matches against the long name, otherwise the short name
3468 We don't implement this yet XXXX
3471 status = NT_STATUS_NO_SUCH_FILE;
3473 while ((dname = ReadDirName(dir_hnd, &offset,
3474 &smb_fname->st, &talloced))) {
3475 TALLOC_CTX *frame = talloc_stackframe();
3477 if (!is_visible_file(conn,
3483 TALLOC_FREE(talloced);
3487 /* Quick check for "." and ".." */
3488 if (ISDOT(dname) || ISDOTDOT(dname)) {
3490 TALLOC_FREE(talloced);
3494 if(!mask_match(dname, fname_mask,
3495 conn->case_sensitive)) {
3497 TALLOC_FREE(talloced);
3501 TALLOC_FREE(smb_fname->base_name);
3502 if (ISDOT(fname_dir)) {
3503 /* Ensure we use canonical names on open. */
3504 smb_fname->base_name =
3505 talloc_asprintf(smb_fname, "%s",
3508 smb_fname->base_name =
3509 talloc_asprintf(smb_fname, "%s/%s",
3513 if (!smb_fname->base_name) {
3514 TALLOC_FREE(dir_hnd);
3515 status = NT_STATUS_NO_MEMORY;
3517 TALLOC_FREE(talloced);
3521 status = check_name(conn, smb_fname);
3522 if (!NT_STATUS_IS_OK(status)) {
3523 TALLOC_FREE(dir_hnd);
3525 TALLOC_FREE(talloced);
3529 status = do_unlink(conn, req, smb_fname, dirtype);
3530 if (!NT_STATUS_IS_OK(status)) {
3531 TALLOC_FREE(dir_hnd);
3533 TALLOC_FREE(talloced);
3538 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3539 smb_fname->base_name));
3542 TALLOC_FREE(talloced);
3544 TALLOC_FREE(dir_hnd);
3547 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3548 status = map_nt_error_from_unix(errno);
3552 TALLOC_FREE(smb_fname_dir);
3553 TALLOC_FREE(fname_dir);
3554 TALLOC_FREE(fname_mask);
3558 /****************************************************************************
3560 ****************************************************************************/
3562 void reply_unlink(struct smb_request *req)
3564 connection_struct *conn = req->conn;
3566 struct smb_filename *smb_fname = NULL;
3569 bool path_contains_wcard = False;
3570 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3571 ucf_flags_from_smb_request(req);
3572 TALLOC_CTX *ctx = talloc_tos();
3574 START_PROFILE(SMBunlink);
3577 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3581 dirtype = SVAL(req->vwv+0, 0);
3583 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3584 STR_TERMINATE, &status,
3585 &path_contains_wcard);
3586 if (!NT_STATUS_IS_OK(status)) {
3587 reply_nterror(req, status);
3591 status = filename_convert(ctx, conn,
3595 &path_contains_wcard,
3597 if (!NT_STATUS_IS_OK(status)) {
3598 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3599 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3600 ERRSRV, ERRbadpath);
3603 reply_nterror(req, status);
3607 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3609 status = unlink_internals(conn, req, dirtype, smb_fname,
3610 path_contains_wcard);
3611 if (!NT_STATUS_IS_OK(status)) {
3612 if (open_was_deferred(req->xconn, req->mid)) {
3613 /* We have re-scheduled this call. */
3616 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3617 bool ok = defer_smb1_sharing_violation(req);
3622 reply_nterror(req, status);
3626 reply_outbuf(req, 0, 0);
3628 TALLOC_FREE(smb_fname);
3629 END_PROFILE(SMBunlink);
3633 /****************************************************************************
3635 ****************************************************************************/
3637 static void fail_readraw(void)
3639 const char *errstr = talloc_asprintf(talloc_tos(),
3640 "FAIL ! reply_readbraw: socket write fail (%s)",
3645 exit_server_cleanly(errstr);
3648 /****************************************************************************
3649 Fake (read/write) sendfile. Returns -1 on read or write fail.
3650 ****************************************************************************/
3652 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3653 off_t startpos, size_t nread)
3656 size_t tosend = nread;
3663 bufsize = MIN(nread, 65536);
3665 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3669 while (tosend > 0) {
3673 cur_read = MIN(tosend, bufsize);
3674 ret = read_file(fsp,buf,startpos,cur_read);
3680 /* If we had a short read, fill with zeros. */
3681 if (ret < cur_read) {
3682 memset(buf + ret, '\0', cur_read - ret);
3685 ret = write_data(xconn->transport.sock, buf, cur_read);
3686 if (ret != cur_read) {
3687 int saved_errno = errno;
3689 * Try and give an error message saying what
3692 DEBUG(0, ("write_data failed for client %s. "
3694 smbXsrv_connection_dbg(xconn),
3695 strerror(saved_errno)));
3697 errno = saved_errno;
3701 startpos += cur_read;
3705 return (ssize_t)nread;
3708 /****************************************************************************
3709 Deal with the case of sendfile reading less bytes from the file than
3710 requested. Fill with zeros (all we can do). Returns 0 on success
3711 ****************************************************************************/
3713 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3719 #define SHORT_SEND_BUFSIZE 1024
3720 if (nread < headersize) {
3721 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3722 "header for file %s (%s). Terminating\n",
3723 fsp_str_dbg(fsp), strerror(errno)));
3727 nread -= headersize;
3729 if (nread < smb_maxcnt) {
3730 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3732 DEBUG(0,("sendfile_short_send: malloc failed "
3733 "for file %s (%s). Terminating\n",
3734 fsp_str_dbg(fsp), strerror(errno)));
3738 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3739 "with zeros !\n", fsp_str_dbg(fsp)));
3741 while (nread < smb_maxcnt) {
3743 * We asked for the real file size and told sendfile
3744 * to not go beyond the end of the file. But it can
3745 * happen that in between our fstat call and the
3746 * sendfile call the file was truncated. This is very
3747 * bad because we have already announced the larger
3748 * number of bytes to the client.
3750 * The best we can do now is to send 0-bytes, just as
3751 * a read from a hole in a sparse file would do.
3753 * This should happen rarely enough that I don't care
3754 * about efficiency here :-)
3759 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3760 ret = write_data(xconn->transport.sock, buf, to_write);
3761 if (ret != to_write) {
3762 int saved_errno = errno;
3764 * Try and give an error message saying what
3767 DEBUG(0, ("write_data failed for client %s. "
3769 smbXsrv_connection_dbg(xconn),
3770 strerror(saved_errno)));
3771 errno = saved_errno;
3782 /****************************************************************************
3783 Return a readbraw error (4 bytes of zero).
3784 ****************************************************************************/
3786 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3792 smbd_lock_socket(xconn);
3793 if (write_data(xconn->transport.sock,header,4) != 4) {
3794 int saved_errno = errno;
3796 * Try and give an error message saying what
3799 DEBUG(0, ("write_data failed for client %s. "
3801 smbXsrv_connection_dbg(xconn),
3802 strerror(saved_errno)));
3803 errno = saved_errno;
3807 smbd_unlock_socket(xconn);
3810 /*******************************************************************
3811 Ensure we don't use sendfile if server smb signing is active.
3812 ********************************************************************/
3814 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3816 bool sign_active = false;
3818 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3819 if (get_Protocol() < PROTOCOL_NT1) {
3822 if (signing_state) {
3823 sign_active = smb_signing_is_active(signing_state);
3825 return (lp__use_sendfile(snum) &&
3826 (get_remote_arch() != RA_WIN95) &&
3829 /****************************************************************************
3830 Use sendfile in readbraw.
3831 ****************************************************************************/
3833 static void send_file_readbraw(connection_struct *conn,
3834 struct smb_request *req,
3840 struct smbXsrv_connection *xconn = req->xconn;
3841 char *outbuf = NULL;
3845 * We can only use sendfile on a non-chained packet
3846 * but we can use on a non-oplocked file. tridge proved this
3847 * on a train in Germany :-). JRA.
3848 * reply_readbraw has already checked the length.
3851 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3852 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3853 ssize_t sendfile_read = -1;
3855 DATA_BLOB header_blob;
3857 _smb_setlen(header,nread);
3858 header_blob = data_blob_const(header, 4);
3860 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3861 &header_blob, startpos,
3863 if (sendfile_read == -1) {
3864 /* Returning ENOSYS means no data at all was sent.
3865 * Do this as a normal read. */
3866 if (errno == ENOSYS) {
3867 goto normal_readbraw;
3871 * Special hack for broken Linux with no working sendfile. If we
3872 * return EINTR we sent the header but not the rest of the data.
3873 * Fake this up by doing read/write calls.
3875 if (errno == EINTR) {
3876 /* Ensure we don't do this again. */
3877 set_use_sendfile(SNUM(conn), False);
3878 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3880 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3881 DEBUG(0,("send_file_readbraw: "
3882 "fake_sendfile failed for "
3886 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3891 DEBUG(0,("send_file_readbraw: sendfile failed for "
3892 "file %s (%s). Terminating\n",
3893 fsp_str_dbg(fsp), strerror(errno)));
3894 exit_server_cleanly("send_file_readbraw sendfile failed");
3895 } else if (sendfile_read == 0) {
3897 * Some sendfile implementations return 0 to indicate
3898 * that there was a short read, but nothing was
3899 * actually written to the socket. In this case,
3900 * fallback to the normal read path so the header gets
3901 * the correct byte count.
3903 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3904 "bytes falling back to the normal read: "
3905 "%s\n", fsp_str_dbg(fsp)));
3906 goto normal_readbraw;
3909 /* Deal with possible short send. */
3910 if (sendfile_read != 4+nread) {
3911 ret = sendfile_short_send(xconn, fsp,
3912 sendfile_read, 4, nread);
3922 outbuf = talloc_array(NULL, char, nread+4);
3924 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3925 (unsigned)(nread+4)));
3926 reply_readbraw_error(xconn);
3931 ret = read_file(fsp,outbuf+4,startpos,nread);
3932 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3941 _smb_setlen(outbuf,ret);
3942 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3943 int saved_errno = errno;
3945 * Try and give an error message saying what
3948 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3949 smbXsrv_connection_dbg(xconn),
3950 strerror(saved_errno)));
3951 errno = saved_errno;
3956 TALLOC_FREE(outbuf);
3959 /****************************************************************************
3960 Reply to a readbraw (core+ protocol).
3961 ****************************************************************************/
3963 void reply_readbraw(struct smb_request *req)
3965 connection_struct *conn = req->conn;
3966 struct smbXsrv_connection *xconn = req->xconn;
3967 ssize_t maxcount,mincount;
3971 struct lock_struct lock;
3975 START_PROFILE(SMBreadbraw);
3977 if (srv_is_signing_active(xconn) || req->encrypted) {
3978 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3979 "raw reads/writes are disallowed.");
3983 reply_readbraw_error(xconn);
3984 END_PROFILE(SMBreadbraw);
3988 if (xconn->smb1.echo_handler.trusted_fde) {
3989 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3990 "'async smb echo handler = yes'\n"));
3991 reply_readbraw_error(xconn);
3992 END_PROFILE(SMBreadbraw);
3997 * Special check if an oplock break has been issued
3998 * and the readraw request croses on the wire, we must
3999 * return a zero length response here.
4002 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4005 * We have to do a check_fsp by hand here, as
4006 * we must always return 4 zero bytes on error,
4012 conn != fsp->conn ||
4013 req->vuid != fsp->vuid ||
4014 fsp->fsp_flags.is_directory ||
4018 * fsp could be NULL here so use the value from the packet. JRA.
4020 DEBUG(3,("reply_readbraw: fnum %d not valid "
4022 (int)SVAL(req->vwv+0, 0)));
4023 reply_readbraw_error(xconn);
4024 END_PROFILE(SMBreadbraw);
4028 /* Do a "by hand" version of CHECK_READ. */
4029 if (!(fsp->fsp_flags.can_read ||
4030 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
4031 (fsp->access_mask & FILE_EXECUTE)))) {
4032 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4033 (int)SVAL(req->vwv+0, 0)));
4034 reply_readbraw_error(xconn);
4035 END_PROFILE(SMBreadbraw);
4039 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
4040 if(req->wct == 10) {
4042 * This is a large offset (64 bit) read.
4045 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4048 DEBUG(0,("reply_readbraw: negative 64 bit "
4049 "readraw offset (%.0f) !\n",
4050 (double)startpos ));
4051 reply_readbraw_error(xconn);
4052 END_PROFILE(SMBreadbraw);
4057 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4058 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4060 /* ensure we don't overrun the packet size */
4061 maxcount = MIN(65535,maxcount);
4063 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4064 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4067 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4068 reply_readbraw_error(xconn);
4069 END_PROFILE(SMBreadbraw);
4073 status = vfs_stat_fsp(fsp);
4074 if (NT_STATUS_IS_OK(status)) {
4075 size = fsp->fsp_name->st.st_ex_size;
4078 if (startpos >= size) {
4081 nread = MIN(maxcount,(size - startpos));
4084 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4085 if (nread < mincount)
4089 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4090 "min=%lu nread=%lu\n",
4091 fsp_fnum_dbg(fsp), (double)startpos,
4092 (unsigned long)maxcount,
4093 (unsigned long)mincount,
4094 (unsigned long)nread ) );
4096 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4098 DEBUG(5,("reply_readbraw finished\n"));
4100 END_PROFILE(SMBreadbraw);
4105 #define DBGC_CLASS DBGC_LOCKING
4107 /****************************************************************************
4108 Reply to a lockread (core+ protocol).
4109 ****************************************************************************/
4111 static void reply_lockread_locked(struct tevent_req *subreq);
4113 void reply_lockread(struct smb_request *req)
4115 struct tevent_req *subreq = NULL;
4116 connection_struct *conn = req->conn;
4118 struct smbd_lock_element *lck = NULL;
4120 START_PROFILE(SMBlockread);
4123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4124 END_PROFILE(SMBlockread);
4128 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4130 if (!check_fsp(conn, req, fsp)) {
4131 END_PROFILE(SMBlockread);
4135 if (!CHECK_READ(fsp,req)) {
4136 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4137 END_PROFILE(SMBlockread);
4141 lck = talloc(req, struct smbd_lock_element);
4143 reply_nterror(req, NT_STATUS_NO_MEMORY);
4144 END_PROFILE(SMBlockread);
4149 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4150 * protocol request that predates the read/write lock concept.
4151 * Thus instead of asking for a read lock here we need to ask
4152 * for a write lock. JRA.
4153 * Note that the requested lock size is unaffected by max_send.
4156 *lck = (struct smbd_lock_element) {
4157 .req_guid = smbd_request_guid(req, 0),
4158 .smblctx = req->smbpid,
4159 .brltype = WRITE_LOCK,
4160 .count = SVAL(req->vwv+1, 0),
4161 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4164 subreq = smbd_smb1_do_locks_send(
4170 false, /* large_offset */
4174 if (subreq == NULL) {
4175 reply_nterror(req, NT_STATUS_NO_MEMORY);
4176 END_PROFILE(SMBlockread);
4179 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4180 END_PROFILE(SMBlockread);
4183 static void reply_lockread_locked(struct tevent_req *subreq)
4185 struct smb_request *req = NULL;
4191 size_t numtoread, maxtoread;
4192 struct files_struct *fsp = NULL;
4195 START_PROFILE(SMBlockread);
4197 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4200 status = smbd_smb1_do_locks_recv(subreq);
4201 TALLOC_FREE(subreq);
4203 if (!NT_STATUS_IS_OK(status)) {
4204 reply_nterror(req, status);
4208 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4210 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4214 numtoread = SVAL(req->vwv+1, 0);
4215 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4218 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4220 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4222 if (numtoread > maxtoread) {
4223 DBG_WARNING("requested read size (%zu) is greater than "
4224 "maximum allowed (%zu/%d). "
4225 "Returning short read of maximum allowed for "
4226 "compatibility with Windows 2000.\n",
4229 req->xconn->smb1.sessions.max_send);
4230 numtoread = maxtoread;
4233 reply_outbuf(req, 5, numtoread + 3);
4235 data = smb_buf(req->outbuf) + 3;
4237 nread = read_file(fsp,data,startpos,numtoread);
4240 reply_nterror(req, map_nt_error_from_unix(errno));
4244 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4246 SSVAL(req->outbuf,smb_vwv0,nread);
4247 SSVAL(req->outbuf,smb_vwv5,nread+3);
4248 p = smb_buf(req->outbuf);
4249 SCVAL(p,0,0); /* pad byte. */
4252 DEBUG(3,("lockread %s num=%d nread=%d\n",
4253 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4256 ok = srv_send_smb(req->xconn,
4257 (char *)req->outbuf,
4260 IS_CONN_ENCRYPTED(req->conn),
4263 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4266 END_PROFILE(SMBlockread);
4271 #define DBGC_CLASS DBGC_ALL
4273 /****************************************************************************
4275 ****************************************************************************/
4277 void reply_read(struct smb_request *req)
4279 connection_struct *conn = req->conn;
4286 struct lock_struct lock;
4287 struct smbXsrv_connection *xconn = req->xconn;
4289 START_PROFILE(SMBread);
4292 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4293 END_PROFILE(SMBread);
4297 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4299 if (!check_fsp(conn, req, fsp)) {
4300 END_PROFILE(SMBread);
4304 if (!CHECK_READ(fsp,req)) {
4305 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4306 END_PROFILE(SMBread);
4310 numtoread = SVAL(req->vwv+1, 0);
4311 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4314 * The requested read size cannot be greater than max_send. JRA.
4316 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4318 if (numtoread > maxtoread) {
4319 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4320 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4321 (unsigned int)numtoread, (unsigned int)maxtoread,
4322 (unsigned int)xconn->smb1.sessions.max_send));
4323 numtoread = maxtoread;
4326 reply_outbuf(req, 5, numtoread+3);
4328 data = smb_buf(req->outbuf) + 3;
4330 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4331 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4334 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4335 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4336 END_PROFILE(SMBread);
4341 nread = read_file(fsp,data,startpos,numtoread);
4344 reply_nterror(req, map_nt_error_from_unix(errno));
4348 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4350 SSVAL(req->outbuf,smb_vwv0,nread);
4351 SSVAL(req->outbuf,smb_vwv5,nread+3);
4352 SCVAL(smb_buf(req->outbuf),0,1);
4353 SSVAL(smb_buf(req->outbuf),1,nread);
4355 DEBUG(3, ("read %s num=%d nread=%d\n",
4356 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4359 END_PROFILE(SMBread);
4363 /****************************************************************************
4365 ****************************************************************************/
4367 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4371 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4374 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4376 SCVAL(outbuf,smb_vwv0,0xFF);
4377 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4378 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4379 SSVAL(outbuf,smb_vwv6,
4380 (smb_wct - 4) /* offset from smb header to wct */
4381 + 1 /* the wct field */
4382 + 12 * sizeof(uint16_t) /* vwv */
4383 + 2 /* the buflen field */
4384 + 1); /* padding byte */
4385 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4386 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4387 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4388 _smb_setlen_large(outbuf,
4389 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4393 /****************************************************************************
4394 Reply to a read and X - possibly using sendfile.
4395 ****************************************************************************/
4397 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4398 files_struct *fsp, off_t startpos,
4401 struct smbXsrv_connection *xconn = req->xconn;
4403 struct lock_struct lock;
4404 int saved_errno = 0;
4407 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4408 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4411 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4412 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4417 * We can only use sendfile on a non-chained packet
4418 * but we can use on a non-oplocked file. tridge proved this
4419 * on a train in Germany :-). JRA.
4422 if (!req_is_in_chain(req) &&
4424 (fsp->base_fsp == NULL) &&
4425 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4426 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4429 status = vfs_stat_fsp(fsp);
4430 if (!NT_STATUS_IS_OK(status)) {
4431 reply_nterror(req, status);
4435 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4436 (startpos > fsp->fsp_name->st.st_ex_size) ||
4437 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4439 * We already know that we would do a short read, so don't
4440 * try the sendfile() path.
4442 goto nosendfile_read;
4446 * Set up the packet header before send. We
4447 * assume here the sendfile will work (get the
4448 * correct amount of data).
4451 header = data_blob_const(headerbuf, sizeof(headerbuf));
4453 construct_reply_common_req(req, (char *)headerbuf);
4454 setup_readX_header((char *)headerbuf, smb_maxcnt);
4456 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4457 startpos, smb_maxcnt);
4459 saved_errno = errno;
4461 /* Returning ENOSYS means no data at all was sent.
4462 Do this as a normal read. */
4463 if (errno == ENOSYS) {
4468 * Special hack for broken Linux with no working sendfile. If we
4469 * return EINTR we sent the header but not the rest of the data.
4470 * Fake this up by doing read/write calls.
4473 if (errno == EINTR) {
4474 /* Ensure we don't do this again. */
4475 set_use_sendfile(SNUM(conn), False);
4476 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4477 nread = fake_sendfile(xconn, fsp, startpos,
4480 saved_errno = errno;
4481 DEBUG(0,("send_file_readX: "
4482 "fake_sendfile failed for "
4483 "file %s (%s) for client %s. "
4486 smbXsrv_connection_dbg(xconn),
4487 strerror(saved_errno)));
4488 errno = saved_errno;
4489 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4491 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4492 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4493 /* No outbuf here means successful sendfile. */
4497 DEBUG(0,("send_file_readX: sendfile failed for file "
4498 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4500 exit_server_cleanly("send_file_readX sendfile failed");
4501 } else if (nread == 0) {
4503 * Some sendfile implementations return 0 to indicate
4504 * that there was a short read, but nothing was
4505 * actually written to the socket. In this case,
4506 * fallback to the normal read path so the header gets
4507 * the correct byte count.
4509 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4510 "falling back to the normal read: %s\n",
4515 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4516 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4518 /* Deal with possible short send. */
4519 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4522 ret = sendfile_short_send(xconn, fsp, nread,
4523 sizeof(headerbuf), smb_maxcnt);
4526 r = "send_file_readX: sendfile_short_send failed";
4527 DEBUG(0,("%s for file %s (%s).\n",
4528 r, fsp_str_dbg(fsp), strerror(errno)));
4529 exit_server_cleanly(r);
4532 /* No outbuf here means successful sendfile. */
4533 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4534 SMB_PERFCOUNT_END(&req->pcd);
4540 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4541 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4544 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4545 (startpos > fsp->fsp_name->st.st_ex_size) ||
4546 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4548 * We already know that we would do a short
4549 * read, so don't try the sendfile() path.
4551 goto nosendfile_read;
4554 construct_reply_common_req(req, (char *)headerbuf);
4555 setup_readX_header((char *)headerbuf, smb_maxcnt);
4557 /* Send out the header. */
4558 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4560 if (ret != sizeof(headerbuf)) {
4561 saved_errno = errno;
4563 * Try and give an error message saying what
4566 DEBUG(0,("send_file_readX: write_data failed for file "
4567 "%s (%s) for client %s. Terminating\n",
4569 smbXsrv_connection_dbg(xconn),
4570 strerror(saved_errno)));
4571 errno = saved_errno;
4572 exit_server_cleanly("send_file_readX sendfile failed");
4574 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4576 saved_errno = errno;
4577 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4578 "%s (%s) for client %s. Terminating\n",
4580 smbXsrv_connection_dbg(xconn),
4581 strerror(saved_errno)));
4582 errno = saved_errno;
4583 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4590 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4591 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4592 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4594 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4595 startpos, smb_maxcnt);
4596 saved_errno = errno;
4599 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4603 setup_readX_header((char *)req->outbuf, nread);
4605 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4606 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4610 TALLOC_FREE(req->outbuf);
4614 /****************************************************************************
4615 Work out how much space we have for a read return.
4616 ****************************************************************************/
4618 static size_t calc_max_read_pdu(const struct smb_request *req)
4620 struct smbXsrv_connection *xconn = req->xconn;
4622 if (xconn->protocol < PROTOCOL_NT1) {
4623 return xconn->smb1.sessions.max_send;
4626 if (!lp_large_readwrite()) {
4627 return xconn->smb1.sessions.max_send;
4630 if (req_is_in_chain(req)) {
4631 return xconn->smb1.sessions.max_send;
4634 if (req->encrypted) {
4636 * Don't take encrypted traffic up to the
4637 * limit. There are padding considerations
4638 * that make that tricky.
4640 return xconn->smb1.sessions.max_send;
4643 if (srv_is_signing_active(xconn)) {
4647 if (!lp_unix_extensions()) {
4652 * We can do ultra-large POSIX reads.
4657 /****************************************************************************
4658 Calculate how big a read can be. Copes with all clients. It's always
4659 safe to return a short read - Windows does this.
4660 ****************************************************************************/
4662 static size_t calc_read_size(const struct smb_request *req,
4666 struct smbXsrv_connection *xconn = req->xconn;
4667 size_t max_pdu = calc_max_read_pdu(req);
4668 size_t total_size = 0;
4669 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4670 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4673 * Windows explicitly ignores upper size of 0xFFFF.
4674 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4675 * We must do the same as these will never fit even in
4676 * an extended size NetBIOS packet.
4678 if (upper_size == 0xFFFF) {
4682 if (xconn->protocol < PROTOCOL_NT1) {
4686 total_size = ((upper_size<<16) | lower_size);
4689 * LARGE_READX test shows it's always safe to return
4690 * a short read. Windows does so.
4692 return MIN(total_size, max_len);
4695 /****************************************************************************
4696 Reply to a read and X.
4697 ****************************************************************************/
4699 void reply_read_and_X(struct smb_request *req)
4701 connection_struct *conn = req->conn;
4706 bool big_readX = False;
4708 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4711 START_PROFILE(SMBreadX);
4713 if ((req->wct != 10) && (req->wct != 12)) {
4714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4718 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4719 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4720 smb_maxcnt = SVAL(req->vwv+5, 0);
4722 /* If it's an IPC, pass off the pipe handler. */
4724 reply_pipe_read_and_X(req);
4725 END_PROFILE(SMBreadX);
4729 if (!check_fsp(conn, req, fsp)) {
4730 END_PROFILE(SMBreadX);
4734 if (!CHECK_READ(fsp,req)) {
4735 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4736 END_PROFILE(SMBreadX);
4740 upper_size = SVAL(req->vwv+7, 0);
4741 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4742 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4744 * This is a heuristic to avoid keeping large
4745 * outgoing buffers around over long-lived aio
4751 if (req->wct == 12) {
4753 * This is a large offset (64 bit) read.
4755 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4760 NTSTATUS status = schedule_aio_read_and_X(conn,
4765 if (NT_STATUS_IS_OK(status)) {
4766 /* Read scheduled - we're done. */
4769 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4770 /* Real error - report to client. */
4771 END_PROFILE(SMBreadX);
4772 reply_nterror(req, status);
4775 /* NT_STATUS_RETRY - fall back to sync read. */
4778 smbd_lock_socket(req->xconn);
4779 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4780 smbd_unlock_socket(req->xconn);
4783 END_PROFILE(SMBreadX);
4787 /****************************************************************************
4788 Error replies to writebraw must have smb_wct == 1. Fix this up.
4789 ****************************************************************************/
4791 void error_to_writebrawerr(struct smb_request *req)
4793 uint8_t *old_outbuf = req->outbuf;
4795 reply_outbuf(req, 1, 0);
4797 memcpy(req->outbuf, old_outbuf, smb_size);
4798 TALLOC_FREE(old_outbuf);
4801 /****************************************************************************
4802 Read 4 bytes of a smb packet and return the smb length of the packet.
4803 Store the result in the buffer. This version of the function will
4804 never return a session keepalive (length of zero).
4805 Timeout is in milliseconds.
4806 ****************************************************************************/
4808 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4811 uint8_t msgtype = NBSSkeepalive;
4813 while (msgtype == NBSSkeepalive) {
4816 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4818 if (!NT_STATUS_IS_OK(status)) {
4819 char addr[INET6_ADDRSTRLEN];
4820 /* Try and give an error message
4821 * saying what client failed. */
4822 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4823 "client %s read error = %s.\n",
4824 get_peer_addr(fd,addr,sizeof(addr)),
4825 nt_errstr(status)));
4829 msgtype = CVAL(inbuf, 0);
4832 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4833 (unsigned long)len));
4835 return NT_STATUS_OK;
4838 /****************************************************************************
4839 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4840 ****************************************************************************/
4842 void reply_writebraw(struct smb_request *req)
4844 connection_struct *conn = req->conn;
4845 struct smbXsrv_connection *xconn = req->xconn;
4848 ssize_t total_written=0;
4849 size_t numtowrite=0;
4852 const char *data=NULL;
4855 struct lock_struct lock;
4858 START_PROFILE(SMBwritebraw);
4861 * If we ever reply with an error, it must have the SMB command
4862 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4865 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4867 if (srv_is_signing_active(xconn)) {
4868 END_PROFILE(SMBwritebraw);
4869 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4870 "raw reads/writes are disallowed.");
4873 if (req->wct < 12) {
4874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4875 error_to_writebrawerr(req);
4876 END_PROFILE(SMBwritebraw);
4880 if (xconn->smb1.echo_handler.trusted_fde) {
4881 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4882 "'async smb echo handler = yes'\n"));
4883 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4884 error_to_writebrawerr(req);
4885 END_PROFILE(SMBwritebraw);
4889 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4890 if (!check_fsp(conn, req, fsp)) {
4891 error_to_writebrawerr(req);
4892 END_PROFILE(SMBwritebraw);
4896 if (!CHECK_WRITE(fsp)) {
4897 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4898 error_to_writebrawerr(req);
4899 END_PROFILE(SMBwritebraw);
4903 tcount = IVAL(req->vwv+1, 0);
4904 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4905 write_through = BITSETW(req->vwv+7,0);
4907 /* We have to deal with slightly different formats depending
4908 on whether we are using the core+ or lanman1.0 protocol */
4910 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4911 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4912 data = smb_buf_const(req->inbuf);
4914 numtowrite = SVAL(req->vwv+10, 0);
4915 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4918 /* Ensure we don't write bytes past the end of this packet. */
4920 * This already protects us against CVE-2017-12163.
4922 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4924 error_to_writebrawerr(req);
4925 END_PROFILE(SMBwritebraw);
4929 if (!fsp->print_file) {
4930 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4931 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4934 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4935 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4936 error_to_writebrawerr(req);
4937 END_PROFILE(SMBwritebraw);
4943 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4946 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4947 "wrote=%d sync=%d\n",
4948 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4949 (int)nwritten, (int)write_through));
4951 if (nwritten < (ssize_t)numtowrite) {
4952 reply_nterror(req, NT_STATUS_DISK_FULL);
4953 error_to_writebrawerr(req);
4957 total_written = nwritten;
4959 /* Allocate a buffer of 64k + length. */
4960 buf = talloc_array(NULL, char, 65540);
4962 reply_nterror(req, NT_STATUS_NO_MEMORY);
4963 error_to_writebrawerr(req);
4967 /* Return a SMBwritebraw message to the redirector to tell
4968 * it to send more bytes */
4970 memcpy(buf, req->inbuf, smb_size);
4971 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4972 SCVAL(buf,smb_com,SMBwritebraw);
4973 SSVALS(buf,smb_vwv0,0xFFFF);
4975 if (!srv_send_smb(req->xconn,
4977 false, 0, /* no signing */
4978 IS_CONN_ENCRYPTED(conn),
4980 exit_server_cleanly("reply_writebraw: srv_send_smb "
4984 /* Now read the raw data into the buffer and write it */
4985 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4987 if (!NT_STATUS_IS_OK(status)) {
4988 exit_server_cleanly("secondary writebraw failed");
4991 /* Set up outbuf to return the correct size */
4992 reply_outbuf(req, 1, 0);
4994 if (numtowrite != 0) {
4996 if (numtowrite > 0xFFFF) {
4997 DEBUG(0,("reply_writebraw: Oversize secondary write "
4998 "raw requested (%u). Terminating\n",
4999 (unsigned int)numtowrite ));
5000 exit_server_cleanly("secondary writebraw failed");
5003 if (tcount > nwritten+numtowrite) {
5004 DEBUG(3,("reply_writebraw: Client overestimated the "
5006 (int)tcount,(int)nwritten,(int)numtowrite));
5009 status = read_data_ntstatus(xconn->transport.sock, buf+4,
5012 if (!NT_STATUS_IS_OK(status)) {
5013 /* Try and give an error message
5014 * saying what client failed. */
5015 DEBUG(0, ("reply_writebraw: Oversize secondary write "
5016 "raw read failed (%s) for client %s. "
5017 "Terminating\n", nt_errstr(status),
5018 smbXsrv_connection_dbg(xconn)));
5019 exit_server_cleanly("secondary writebraw failed");
5023 * We are not vulnerable to CVE-2017-12163
5024 * here as we are guaranteed to have numtowrite
5025 * bytes available - we just read from the client.
5027 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
5028 if (nwritten == -1) {
5030 reply_nterror(req, map_nt_error_from_unix(errno));
5031 error_to_writebrawerr(req);
5035 if (nwritten < (ssize_t)numtowrite) {
5036 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5037 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5041 total_written += nwritten;
5046 SSVAL(req->outbuf,smb_vwv0,total_written);
5048 status = sync_file(conn, fsp, write_through);
5049 if (!NT_STATUS_IS_OK(status)) {
5050 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5051 fsp_str_dbg(fsp), nt_errstr(status)));
5052 reply_nterror(req, status);
5053 error_to_writebrawerr(req);
5057 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5059 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5060 (int)total_written));
5062 /* We won't return a status if write through is not selected - this
5063 * follows what WfWg does */
5064 END_PROFILE(SMBwritebraw);
5066 if (!write_through && total_written==tcount) {
5068 #if RABBIT_PELLET_FIX
5070 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5071 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5074 if (!send_keepalive(xconn->transport.sock)) {
5075 exit_server_cleanly("reply_writebraw: send of "
5076 "keepalive failed");
5079 TALLOC_FREE(req->outbuf);
5084 END_PROFILE(SMBwritebraw);
5089 #define DBGC_CLASS DBGC_LOCKING
5091 /****************************************************************************
5092 Reply to a writeunlock (core+).
5093 ****************************************************************************/
5095 void reply_writeunlock(struct smb_request *req)
5097 connection_struct *conn = req->conn;
5098 ssize_t nwritten = -1;
5103 NTSTATUS status = NT_STATUS_OK;
5105 struct lock_struct lock;
5106 int saved_errno = 0;
5108 START_PROFILE(SMBwriteunlock);
5111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5112 END_PROFILE(SMBwriteunlock);
5116 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5118 if (!check_fsp(conn, req, fsp)) {
5119 END_PROFILE(SMBwriteunlock);
5123 if (!CHECK_WRITE(fsp)) {
5124 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5125 END_PROFILE(SMBwriteunlock);
5129 numtowrite = SVAL(req->vwv+1, 0);
5130 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5131 data = (const char *)req->buf + 3;
5134 * Ensure client isn't asking us to write more than
5135 * they sent. CVE-2017-12163.
5137 remaining = smbreq_bufrem(req, data);
5138 if (numtowrite > remaining) {
5139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5140 END_PROFILE(SMBwriteunlock);
5144 if (!fsp->print_file && numtowrite > 0) {
5145 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5146 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5149 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5150 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5151 END_PROFILE(SMBwriteunlock);
5156 /* The special X/Open SMB protocol handling of
5157 zero length writes is *NOT* done for
5159 if(numtowrite == 0) {
5162 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5163 saved_errno = errno;
5166 status = sync_file(conn, fsp, False /* write through */);
5167 if (!NT_STATUS_IS_OK(status)) {
5168 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5169 fsp_str_dbg(fsp), nt_errstr(status)));
5170 reply_nterror(req, status);
5175 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5179 if((nwritten < numtowrite) && (numtowrite != 0)) {
5180 reply_nterror(req, NT_STATUS_DISK_FULL);
5184 if (numtowrite && !fsp->print_file) {
5185 struct smbd_lock_element l = {
5186 .req_guid = smbd_request_guid(req, 0),
5187 .smblctx = req->smbpid,
5188 .brltype = UNLOCK_LOCK,
5190 .count = numtowrite,
5192 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5193 if (NT_STATUS_V(status)) {
5194 reply_nterror(req, status);
5199 reply_outbuf(req, 1, 0);
5201 SSVAL(req->outbuf,smb_vwv0,nwritten);
5203 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5204 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5207 END_PROFILE(SMBwriteunlock);
5212 #define DBGC_CLASS DBGC_ALL
5214 /****************************************************************************
5216 ****************************************************************************/
5218 void reply_write(struct smb_request *req)
5220 connection_struct *conn = req->conn;
5223 ssize_t nwritten = -1;
5227 struct lock_struct lock;
5229 int saved_errno = 0;
5231 START_PROFILE(SMBwrite);
5234 END_PROFILE(SMBwrite);
5235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5239 /* If it's an IPC, pass off the pipe handler. */
5241 reply_pipe_write(req);
5242 END_PROFILE(SMBwrite);
5246 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5248 if (!check_fsp(conn, req, fsp)) {
5249 END_PROFILE(SMBwrite);
5253 if (!CHECK_WRITE(fsp)) {
5254 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5255 END_PROFILE(SMBwrite);
5259 numtowrite = SVAL(req->vwv+1, 0);
5260 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5261 data = (const char *)req->buf + 3;
5264 * Ensure client isn't asking us to write more than
5265 * they sent. CVE-2017-12163.
5267 remaining = smbreq_bufrem(req, data);
5268 if (numtowrite > remaining) {
5269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5270 END_PROFILE(SMBwrite);
5274 if (!fsp->print_file) {
5275 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5276 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5279 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5280 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5281 END_PROFILE(SMBwrite);
5287 * X/Open SMB protocol says that if smb_vwv1 is
5288 * zero then the file size should be extended or
5289 * truncated to the size given in smb_vwv[2-3].
5292 if(numtowrite == 0) {
5294 * This is actually an allocate call, and set EOF. JRA.
5296 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5298 reply_nterror(req, NT_STATUS_DISK_FULL);
5301 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5303 reply_nterror(req, NT_STATUS_DISK_FULL);
5306 trigger_write_time_update_immediate(fsp);
5308 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5311 status = sync_file(conn, fsp, False);
5312 if (!NT_STATUS_IS_OK(status)) {
5313 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5314 fsp_str_dbg(fsp), nt_errstr(status)));
5315 reply_nterror(req, status);
5320 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5324 if((nwritten == 0) && (numtowrite != 0)) {
5325 reply_nterror(req, NT_STATUS_DISK_FULL);
5329 reply_outbuf(req, 1, 0);
5331 SSVAL(req->outbuf,smb_vwv0,nwritten);
5333 if (nwritten < (ssize_t)numtowrite) {
5334 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5335 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5338 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5341 END_PROFILE(SMBwrite);
5345 /****************************************************************************
5346 Ensure a buffer is a valid writeX for recvfile purposes.
5347 ****************************************************************************/
5349 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5350 (2*14) + /* word count (including bcc) */ \
5353 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5354 const uint8_t *inbuf)
5357 unsigned int doff = 0;
5358 size_t len = smb_len_large(inbuf);
5360 struct smbXsrv_open *op = NULL;
5361 struct files_struct *fsp = NULL;
5364 if (is_encrypted_packet(inbuf)) {
5365 /* Can't do this on encrypted
5370 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5374 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5375 CVAL(inbuf,smb_wct) != 14) {
5376 DEBUG(10,("is_valid_writeX_buffer: chained or "
5377 "invalid word length.\n"));
5381 fnum = SVAL(inbuf, smb_vwv2);
5382 status = smb1srv_open_lookup(xconn,
5386 if (!NT_STATUS_IS_OK(status)) {
5387 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5392 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5395 if (fsp->conn == NULL) {
5396 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5400 if (IS_IPC(fsp->conn)) {
5401 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5404 if (IS_PRINT(fsp->conn)) {
5405 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5408 if (fsp->base_fsp != NULL) {
5409 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5412 doff = SVAL(inbuf,smb_vwv11);
5414 numtowrite = SVAL(inbuf,smb_vwv10);
5416 if (len > doff && len - doff > 0xFFFF) {
5417 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5420 if (numtowrite == 0) {
5421 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5425 /* Ensure the sizes match up. */
5426 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5427 /* no pad byte...old smbclient :-( */
5428 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5430 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5434 if (len - doff != numtowrite) {
5435 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5436 "len = %u, doff = %u, numtowrite = %u\n",
5439 (unsigned int)numtowrite ));
5443 DEBUG(10,("is_valid_writeX_buffer: true "
5444 "len = %u, doff = %u, numtowrite = %u\n",
5447 (unsigned int)numtowrite ));
5452 /****************************************************************************
5453 Reply to a write and X.
5454 ****************************************************************************/
5456 void reply_write_and_X(struct smb_request *req)
5458 connection_struct *conn = req->conn;
5459 struct smbXsrv_connection *xconn = req->xconn;
5461 struct lock_struct lock;
5466 unsigned int smb_doff;
5467 unsigned int smblen;
5470 int saved_errno = 0;
5472 START_PROFILE(SMBwriteX);
5474 if ((req->wct != 12) && (req->wct != 14)) {
5475 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5479 numtowrite = SVAL(req->vwv+10, 0);
5480 smb_doff = SVAL(req->vwv+11, 0);
5481 smblen = smb_len(req->inbuf);
5483 if (req->unread_bytes > 0xFFFF ||
5484 (smblen > smb_doff &&
5485 smblen - smb_doff > 0xFFFF)) {
5486 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5489 if (req->unread_bytes) {
5490 /* Can't do a recvfile write on IPC$ */
5492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5495 if (numtowrite != req->unread_bytes) {
5496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5501 * This already protects us against CVE-2017-12163.
5503 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5504 smb_doff + numtowrite > smblen) {
5505 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5510 /* If it's an IPC, pass off the pipe handler. */
5512 if (req->unread_bytes) {
5513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5516 reply_pipe_write_and_X(req);
5520 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5521 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5522 write_through = BITSETW(req->vwv+7,0);
5524 if (!check_fsp(conn, req, fsp)) {
5528 if (!CHECK_WRITE(fsp)) {
5529 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5533 data = smb_base(req->inbuf) + smb_doff;
5535 if(req->wct == 14) {
5537 * This is a large offset (64 bit) write.
5539 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5543 /* X/Open SMB protocol says that, unlike SMBwrite
5544 if the length is zero then NO truncation is
5545 done, just a write of zero. To truncate a file,
5548 if(numtowrite == 0) {
5551 if (req->unread_bytes == 0) {
5552 status = schedule_aio_write_and_X(conn,
5559 if (NT_STATUS_IS_OK(status)) {
5560 /* write scheduled - we're done. */
5563 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5564 /* Real error - report to client. */
5565 reply_nterror(req, status);
5568 /* NT_STATUS_RETRY - fall through to sync write. */
5571 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5572 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5575 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5576 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5580 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5581 saved_errno = errno;
5585 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5589 if((nwritten == 0) && (numtowrite != 0)) {
5590 reply_nterror(req, NT_STATUS_DISK_FULL);
5594 reply_outbuf(req, 6, 0);
5595 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5596 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5597 SSVAL(req->outbuf,smb_vwv2,nwritten);
5598 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5600 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5601 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5603 status = sync_file(conn, fsp, write_through);
5604 if (!NT_STATUS_IS_OK(status)) {
5605 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5606 fsp_str_dbg(fsp), nt_errstr(status)));
5607 reply_nterror(req, status);
5611 END_PROFILE(SMBwriteX);
5615 if (req->unread_bytes) {
5616 /* writeX failed. drain socket. */
5617 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5618 req->unread_bytes) {
5619 smb_panic("failed to drain pending bytes");
5621 req->unread_bytes = 0;
5624 END_PROFILE(SMBwriteX);
5628 /****************************************************************************
5630 ****************************************************************************/
5632 void reply_lseek(struct smb_request *req)
5634 connection_struct *conn = req->conn;
5641 START_PROFILE(SMBlseek);
5644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5645 END_PROFILE(SMBlseek);
5649 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5651 if (!check_fsp(conn, req, fsp)) {
5655 mode = SVAL(req->vwv+1, 0) & 3;
5656 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5657 startpos = (off_t)IVALS(req->vwv+2, 0);
5666 res = fsp->fh->pos + startpos;
5677 if (umode == SEEK_END) {
5678 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5679 if(errno == EINVAL) {
5680 off_t current_pos = startpos;
5682 status = vfs_stat_fsp(fsp);
5683 if (!NT_STATUS_IS_OK(status)) {
5684 reply_nterror(req, status);
5685 END_PROFILE(SMBlseek);
5689 current_pos += fsp->fsp_name->st.st_ex_size;
5691 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5696 reply_nterror(req, map_nt_error_from_unix(errno));
5697 END_PROFILE(SMBlseek);
5704 reply_outbuf(req, 2, 0);
5705 SIVAL(req->outbuf,smb_vwv0,res);
5707 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5708 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5710 END_PROFILE(SMBlseek);
5714 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5717 connection_struct *conn = talloc_get_type_abort(
5718 private_data, connection_struct);
5720 if (conn != fsp->conn) {
5723 if (fsp->fh->fd == -1) {
5726 sync_file(conn, fsp, True /* write through */);
5728 if (fsp->fsp_flags.modified) {
5729 trigger_write_time_update_immediate(fsp);
5735 /****************************************************************************
5737 ****************************************************************************/
5739 void reply_flush(struct smb_request *req)
5741 connection_struct *conn = req->conn;
5745 START_PROFILE(SMBflush);
5748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5752 fnum = SVAL(req->vwv+0, 0);
5753 fsp = file_fsp(req, fnum);
5755 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5760 files_forall(req->sconn, file_sync_one_fn, conn);
5762 NTSTATUS status = sync_file(conn, fsp, True);
5763 if (!NT_STATUS_IS_OK(status)) {
5764 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5765 fsp_str_dbg(fsp), nt_errstr(status)));
5766 reply_nterror(req, status);
5767 END_PROFILE(SMBflush);
5770 if (fsp->fsp_flags.modified) {
5771 trigger_write_time_update_immediate(fsp);
5775 reply_outbuf(req, 0, 0);
5777 DEBUG(3,("flush\n"));
5778 END_PROFILE(SMBflush);
5782 /****************************************************************************
5784 conn POINTER CAN BE NULL HERE !
5785 ****************************************************************************/
5787 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5788 static void reply_exit_done(struct tevent_req *req);
5790 void reply_exit(struct smb_request *smb1req)
5792 struct tevent_req *req;
5795 * Don't setup the profile charge here, take
5796 * it in reply_exit_done(). Not strictly correct
5797 * but better than the other SMB1 async
5798 * code that double-charges at the moment.
5800 req = reply_exit_send(smb1req);
5802 /* Not going async, profile here. */
5803 START_PROFILE(SMBexit);
5804 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5805 END_PROFILE(SMBexit);
5809 /* We're async. This will complete later. */
5810 tevent_req_set_callback(req, reply_exit_done, smb1req);
5814 struct reply_exit_state {
5815 struct tevent_queue *wait_queue;
5818 static void reply_exit_wait_done(struct tevent_req *subreq);
5820 /****************************************************************************
5822 Note, on failure here we deallocate and return NULL to allow the caller to
5823 SMB1 return an error of ERRnomem immediately.
5824 ****************************************************************************/
5826 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5828 struct tevent_req *req;
5829 struct reply_exit_state *state;
5830 struct tevent_req *subreq;
5832 struct smbd_server_connection *sconn = smb1req->sconn;
5834 req = tevent_req_create(smb1req, &state,
5835 struct reply_exit_state);
5839 state->wait_queue = tevent_queue_create(state,
5840 "reply_exit_wait_queue");
5841 if (tevent_req_nomem(state->wait_queue, req)) {
5846 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5847 if (fsp->file_pid != smb1req->smbpid) {
5850 if (fsp->vuid != smb1req->vuid) {
5854 * Flag the file as close in progress.
5855 * This will prevent any more IO being
5858 fsp->fsp_flags.closing = true;
5860 if (fsp->num_aio_requests > 0) {
5862 * Now wait until all aio requests on this fsp are
5865 * We don't set a callback, as we just want to block the
5866 * wait queue and the talloc_free() of fsp->aio_request
5867 * will remove the item from the wait queue.
5869 subreq = tevent_queue_wait_send(fsp->aio_requests,
5872 if (tevent_req_nomem(subreq, req)) {
5880 * Now we add our own waiter to the end of the queue,
5881 * this way we get notified when all pending requests are finished
5882 * and reply to the outstanding SMB1 request.
5884 subreq = tevent_queue_wait_send(state,
5887 if (tevent_req_nomem(subreq, req)) {
5893 * We're really going async - move the SMB1 request from
5894 * a talloc stackframe above us to the conn talloc-context.
5895 * We need this to stick around until the wait_done
5896 * callback is invoked.
5898 smb1req = talloc_move(sconn, &smb1req);
5900 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5905 static void reply_exit_wait_done(struct tevent_req *subreq)
5907 struct tevent_req *req = tevent_req_callback_data(
5908 subreq, struct tevent_req);
5910 tevent_queue_wait_recv(subreq);
5911 TALLOC_FREE(subreq);
5912 tevent_req_done(req);
5915 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5917 return tevent_req_simple_recv_ntstatus(req);
5920 static void reply_exit_done(struct tevent_req *req)
5922 struct smb_request *smb1req = tevent_req_callback_data(
5923 req, struct smb_request);
5924 struct smbd_server_connection *sconn = smb1req->sconn;
5925 struct smbXsrv_connection *xconn = smb1req->xconn;
5926 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5927 struct smbXsrv_session *session = NULL;
5928 files_struct *fsp, *next;
5932 * Take the profile charge here. Not strictly
5933 * correct but better than the other SMB1 async
5934 * code that double-charges at the moment.
5936 START_PROFILE(SMBexit);
5938 status = reply_exit_recv(req);
5940 if (!NT_STATUS_IS_OK(status)) {
5941 TALLOC_FREE(smb1req);
5942 END_PROFILE(SMBexit);
5943 exit_server(__location__ ": reply_exit_recv failed");
5948 * Ensure the session is still valid.
5950 status = smb1srv_session_lookup(xconn,
5954 if (!NT_STATUS_IS_OK(status)) {
5955 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5956 smb_request_done(smb1req);
5957 END_PROFILE(SMBexit);
5961 * Ensure the vuid is still valid - no one
5962 * called reply_ulogoffX() in the meantime.
5963 * reply_exit() doesn't have AS_USER set, so
5964 * use set_current_user_info() directly.
5965 * This is the same logic as in switch_message().
5967 if (session->global->auth_session_info != NULL) {
5968 set_current_user_info(
5969 session->global->auth_session_info->unix_info->sanitized_username,
5970 session->global->auth_session_info->unix_info->unix_name,
5971 session->global->auth_session_info->info->domain_name);
5974 /* No more aio - do the actual closes. */
5975 for (fsp = sconn->files; fsp; fsp = next) {
5979 if (fsp->file_pid != smb1req->smbpid) {
5982 if (fsp->vuid != smb1req->vuid) {
5985 if (!fsp->fsp_flags.closing) {
5990 * reply_exit() has the DO_CHDIR flag set.
5992 ok = chdir_current_service(fsp->conn);
5994 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5995 smb_request_done(smb1req);
5996 END_PROFILE(SMBexit);
5998 close_file(NULL, fsp, SHUTDOWN_CLOSE);
6001 reply_outbuf(smb1req, 0, 0);
6003 * The following call is needed to push the
6004 * reply data back out the socket after async
6005 * return. Plus it frees smb1req.
6007 smb_request_done(smb1req);
6008 DBG_INFO("reply_exit complete\n");
6009 END_PROFILE(SMBexit);
6013 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6015 static void reply_close_done(struct tevent_req *req);
6017 void reply_close(struct smb_request *smb1req)
6019 connection_struct *conn = smb1req->conn;
6020 NTSTATUS status = NT_STATUS_OK;
6021 files_struct *fsp = NULL;
6022 START_PROFILE(SMBclose);
6024 if (smb1req->wct < 3) {
6025 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
6026 END_PROFILE(SMBclose);
6030 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
6033 * We can only use check_fsp if we know it's not a directory.
6036 if (!check_fsp_open(conn, smb1req, fsp)) {
6037 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
6038 END_PROFILE(SMBclose);
6042 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6043 fsp->fsp_flags.is_directory ?
6044 "directory" : "file",
6045 fsp->fh->fd, fsp_fnum_dbg(fsp),
6046 conn->num_files_open);
6048 if (!fsp->fsp_flags.is_directory) {
6052 * Take care of any time sent in the close.
6055 t = srv_make_unix_date3(smb1req->vwv+1);
6056 set_close_write_time(fsp, time_t_to_full_timespec(t));
6059 if (fsp->num_aio_requests != 0) {
6060 struct tevent_req *req;
6062 req = reply_close_send(smb1req, fsp);
6064 status = NT_STATUS_NO_MEMORY;
6067 /* We're async. This will complete later. */
6068 tevent_req_set_callback(req, reply_close_done, smb1req);
6069 END_PROFILE(SMBclose);
6074 * close_file() returns the unix errno if an error was detected on
6075 * close - normally this is due to a disk full error. If not then it
6076 * was probably an I/O error.
6079 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6081 if (!NT_STATUS_IS_OK(status)) {
6082 reply_nterror(smb1req, status);
6083 END_PROFILE(SMBclose);
6087 reply_outbuf(smb1req, 0, 0);
6088 END_PROFILE(SMBclose);
6092 struct reply_close_state {
6094 struct tevent_queue *wait_queue;
6097 static void reply_close_wait_done(struct tevent_req *subreq);
6099 /****************************************************************************
6101 Note, on failure here we deallocate and return NULL to allow the caller to
6102 SMB1 return an error of ERRnomem immediately.
6103 ****************************************************************************/
6105 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6108 struct tevent_req *req;
6109 struct reply_close_state *state;
6110 struct tevent_req *subreq;
6111 struct smbd_server_connection *sconn = smb1req->sconn;
6113 req = tevent_req_create(smb1req, &state,
6114 struct reply_close_state);
6118 state->wait_queue = tevent_queue_create(state,
6119 "reply_close_wait_queue");
6120 if (tevent_req_nomem(state->wait_queue, req)) {
6126 * Flag the file as close in progress.
6127 * This will prevent any more IO being
6130 fsp->fsp_flags.closing = true;
6133 * Now wait until all aio requests on this fsp are
6136 * We don't set a callback, as we just want to block the
6137 * wait queue and the talloc_free() of fsp->aio_request
6138 * will remove the item from the wait queue.
6140 subreq = tevent_queue_wait_send(fsp->aio_requests,
6143 if (tevent_req_nomem(subreq, req)) {
6149 * Now we add our own waiter to the end of the queue,
6150 * this way we get notified when all pending requests are finished
6151 * and reply to the outstanding SMB1 request.
6153 subreq = tevent_queue_wait_send(state,
6156 if (tevent_req_nomem(subreq, req)) {
6162 * We're really going async - move the SMB1 request from
6163 * a talloc stackframe above us to the conn talloc-context.
6164 * We need this to stick around until the wait_done
6165 * callback is invoked.
6167 smb1req = talloc_move(sconn, &smb1req);
6169 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6174 static void reply_close_wait_done(struct tevent_req *subreq)
6176 struct tevent_req *req = tevent_req_callback_data(
6177 subreq, struct tevent_req);
6179 tevent_queue_wait_recv(subreq);
6180 TALLOC_FREE(subreq);
6181 tevent_req_done(req);
6184 static NTSTATUS reply_close_recv(struct tevent_req *req)
6186 return tevent_req_simple_recv_ntstatus(req);
6189 static void reply_close_done(struct tevent_req *req)
6191 struct smb_request *smb1req = tevent_req_callback_data(
6192 req, struct smb_request);
6193 struct reply_close_state *state = tevent_req_data(req,
6194 struct reply_close_state);
6197 status = reply_close_recv(req);
6199 if (!NT_STATUS_IS_OK(status)) {
6200 TALLOC_FREE(smb1req);
6201 exit_server(__location__ ": reply_close_recv failed");
6205 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6206 if (NT_STATUS_IS_OK(status)) {
6207 reply_outbuf(smb1req, 0, 0);
6209 reply_nterror(smb1req, status);
6212 * The following call is needed to push the
6213 * reply data back out the socket after async
6214 * return. Plus it frees smb1req.
6216 smb_request_done(smb1req);
6219 /****************************************************************************
6220 Reply to a writeclose (Core+ protocol).
6221 ****************************************************************************/
6223 void reply_writeclose(struct smb_request *req)
6225 connection_struct *conn = req->conn;
6228 ssize_t nwritten = -1;
6229 NTSTATUS close_status = NT_STATUS_OK;
6232 struct timespec mtime;
6234 struct lock_struct lock;
6236 START_PROFILE(SMBwriteclose);
6239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6240 END_PROFILE(SMBwriteclose);
6244 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6246 if (!check_fsp(conn, req, fsp)) {
6247 END_PROFILE(SMBwriteclose);
6250 if (!CHECK_WRITE(fsp)) {
6251 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6252 END_PROFILE(SMBwriteclose);
6256 numtowrite = SVAL(req->vwv+1, 0);
6257 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6258 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6259 data = (const char *)req->buf + 1;
6262 * Ensure client isn't asking us to write more than
6263 * they sent. CVE-2017-12163.
6265 remaining = smbreq_bufrem(req, data);
6266 if (numtowrite > remaining) {
6267 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6268 END_PROFILE(SMBwriteclose);
6272 if (fsp->print_file == NULL) {
6273 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6274 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6277 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6278 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6279 END_PROFILE(SMBwriteclose);
6284 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6286 set_close_write_time(fsp, mtime);
6289 * More insanity. W2K only closes the file if writelen > 0.
6293 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6294 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6295 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6298 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6299 "file %s\n", fsp_str_dbg(fsp)));
6300 close_status = close_file(req, fsp, NORMAL_CLOSE);
6304 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6305 reply_nterror(req, NT_STATUS_DISK_FULL);
6309 if(!NT_STATUS_IS_OK(close_status)) {
6310 reply_nterror(req, close_status);
6314 reply_outbuf(req, 1, 0);
6316 SSVAL(req->outbuf,smb_vwv0,nwritten);
6320 END_PROFILE(SMBwriteclose);
6325 #define DBGC_CLASS DBGC_LOCKING
6327 /****************************************************************************
6329 ****************************************************************************/
6331 static void reply_lock_done(struct tevent_req *subreq);
6333 void reply_lock(struct smb_request *req)
6335 struct tevent_req *subreq = NULL;
6336 connection_struct *conn = req->conn;
6338 struct smbd_lock_element *lck = NULL;
6340 START_PROFILE(SMBlock);
6343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6344 END_PROFILE(SMBlock);
6348 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6350 if (!check_fsp(conn, req, fsp)) {
6351 END_PROFILE(SMBlock);
6355 lck = talloc(req, struct smbd_lock_element);
6357 reply_nterror(req, NT_STATUS_NO_MEMORY);
6358 END_PROFILE(SMBlock);
6362 *lck = (struct smbd_lock_element) {
6363 .req_guid = smbd_request_guid(req, 0),
6364 .smblctx = req->smbpid,
6365 .brltype = WRITE_LOCK,
6366 .count = IVAL(req->vwv+1, 0),
6367 .offset = IVAL(req->vwv+3, 0),
6370 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6376 subreq = smbd_smb1_do_locks_send(
6382 false, /* large_offset */
6386 if (subreq == NULL) {
6387 reply_nterror(req, NT_STATUS_NO_MEMORY);
6388 END_PROFILE(SMBlock);
6391 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6392 END_PROFILE(SMBlock);
6395 static void reply_lock_done(struct tevent_req *subreq)
6397 struct smb_request *req = NULL;
6401 START_PROFILE(SMBlock);
6403 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6406 status = smbd_smb1_do_locks_recv(subreq);
6407 TALLOC_FREE(subreq);
6409 if (NT_STATUS_IS_OK(status)) {
6410 reply_outbuf(req, 0, 0);
6412 reply_nterror(req, status);
6415 ok = srv_send_smb(req->xconn,
6416 (char *)req->outbuf,
6419 IS_CONN_ENCRYPTED(req->conn),
6422 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6425 END_PROFILE(SMBlock);
6428 /****************************************************************************
6430 ****************************************************************************/
6432 void reply_unlock(struct smb_request *req)
6434 connection_struct *conn = req->conn;
6437 struct smbd_lock_element lck;
6439 START_PROFILE(SMBunlock);
6442 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6443 END_PROFILE(SMBunlock);
6447 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6449 if (!check_fsp(conn, req, fsp)) {
6450 END_PROFILE(SMBunlock);
6454 lck = (struct smbd_lock_element) {
6455 .req_guid = smbd_request_guid(req, 0),
6456 .smblctx = req->smbpid,
6457 .brltype = UNLOCK_LOCK,
6458 .offset = IVAL(req->vwv+3, 0),
6459 .count = IVAL(req->vwv+1, 0),
6462 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6464 if (!NT_STATUS_IS_OK(status)) {
6465 reply_nterror(req, status);
6466 END_PROFILE(SMBunlock);
6470 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6476 reply_outbuf(req, 0, 0);
6478 END_PROFILE(SMBunlock);
6483 #define DBGC_CLASS DBGC_ALL
6485 /****************************************************************************
6487 conn POINTER CAN BE NULL HERE !
6488 ****************************************************************************/
6490 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6491 static void reply_tdis_done(struct tevent_req *req);
6493 void reply_tdis(struct smb_request *smb1req)
6495 connection_struct *conn = smb1req->conn;
6496 struct tevent_req *req;
6499 * Don't setup the profile charge here, take
6500 * it in reply_tdis_done(). Not strictly correct
6501 * but better than the other SMB1 async
6502 * code that double-charges at the moment.
6506 /* Not going async, profile here. */
6507 START_PROFILE(SMBtdis);
6508 DBG_INFO("Invalid connection in tdis\n");
6509 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6510 END_PROFILE(SMBtdis);
6514 req = reply_tdis_send(smb1req);
6516 /* Not going async, profile here. */
6517 START_PROFILE(SMBtdis);
6518 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6519 END_PROFILE(SMBtdis);
6522 /* We're async. This will complete later. */
6523 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6527 struct reply_tdis_state {
6528 struct tevent_queue *wait_queue;
6531 static void reply_tdis_wait_done(struct tevent_req *subreq);
6533 /****************************************************************************
6535 Note, on failure here we deallocate and return NULL to allow the caller to
6536 SMB1 return an error of ERRnomem immediately.
6537 ****************************************************************************/
6539 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6541 struct tevent_req *req;
6542 struct reply_tdis_state *state;
6543 struct tevent_req *subreq;
6544 connection_struct *conn = smb1req->conn;
6547 req = tevent_req_create(smb1req, &state,
6548 struct reply_tdis_state);
6552 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6553 if (tevent_req_nomem(state->wait_queue, req)) {
6559 * Make sure that no new request will be able to use this tcon.
6560 * This ensures that once all outstanding fsp->aio_requests
6561 * on this tcon are done, we are safe to close it.
6563 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6565 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6566 if (fsp->conn != conn) {
6570 * Flag the file as close in progress.
6571 * This will prevent any more IO being
6572 * done on it. Not strictly needed, but
6573 * doesn't hurt to flag it as closing.
6575 fsp->fsp_flags.closing = true;
6577 if (fsp->num_aio_requests > 0) {
6579 * Now wait until all aio requests on this fsp are
6582 * We don't set a callback, as we just want to block the
6583 * wait queue and the talloc_free() of fsp->aio_request
6584 * will remove the item from the wait queue.
6586 subreq = tevent_queue_wait_send(fsp->aio_requests,
6587 conn->sconn->ev_ctx,
6589 if (tevent_req_nomem(subreq, req)) {
6597 * Now we add our own waiter to the end of the queue,
6598 * this way we get notified when all pending requests are finished
6599 * and reply to the outstanding SMB1 request.
6601 subreq = tevent_queue_wait_send(state,
6602 conn->sconn->ev_ctx,
6604 if (tevent_req_nomem(subreq, req)) {
6610 * We're really going async - move the SMB1 request from
6611 * a talloc stackframe above us to the sconn talloc-context.
6612 * We need this to stick around until the wait_done
6613 * callback is invoked.
6615 smb1req = talloc_move(smb1req->sconn, &smb1req);
6617 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6622 static void reply_tdis_wait_done(struct tevent_req *subreq)
6624 struct tevent_req *req = tevent_req_callback_data(
6625 subreq, struct tevent_req);
6627 tevent_queue_wait_recv(subreq);
6628 TALLOC_FREE(subreq);
6629 tevent_req_done(req);
6632 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6634 return tevent_req_simple_recv_ntstatus(req);
6637 static void reply_tdis_done(struct tevent_req *req)
6639 struct smb_request *smb1req = tevent_req_callback_data(
6640 req, struct smb_request);
6642 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6646 * Take the profile charge here. Not strictly
6647 * correct but better than the other SMB1 async
6648 * code that double-charges at the moment.
6650 START_PROFILE(SMBtdis);
6652 status = reply_tdis_recv(req);
6654 if (!NT_STATUS_IS_OK(status)) {
6655 TALLOC_FREE(smb1req);
6656 END_PROFILE(SMBtdis);
6657 exit_server(__location__ ": reply_tdis_recv failed");
6662 * As we've been awoken, we may have changed
6663 * directory in the meantime.
6664 * reply_tdis() has the DO_CHDIR flag set.
6666 ok = chdir_current_service(smb1req->conn);
6668 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6669 smb_request_done(smb1req);
6670 END_PROFILE(SMBtdis);
6673 status = smbXsrv_tcon_disconnect(tcon,
6675 if (!NT_STATUS_IS_OK(status)) {
6676 TALLOC_FREE(smb1req);
6677 END_PROFILE(SMBtdis);
6678 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6682 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6683 smb1req->conn = NULL;
6687 reply_outbuf(smb1req, 0, 0);
6689 * The following call is needed to push the
6690 * reply data back out the socket after async
6691 * return. Plus it frees smb1req.
6693 smb_request_done(smb1req);
6694 END_PROFILE(SMBtdis);
6697 /****************************************************************************
6699 conn POINTER CAN BE NULL HERE !
6700 ****************************************************************************/
6702 void reply_echo(struct smb_request *req)
6704 connection_struct *conn = req->conn;
6705 struct smb_perfcount_data local_pcd;
6706 struct smb_perfcount_data *cur_pcd;
6710 START_PROFILE(SMBecho);
6712 smb_init_perfcount_data(&local_pcd);
6715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6716 END_PROFILE(SMBecho);
6720 smb_reverb = SVAL(req->vwv+0, 0);
6722 reply_outbuf(req, 1, req->buflen);
6724 /* copy any incoming data back out */
6725 if (req->buflen > 0) {
6726 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6729 if (smb_reverb > 100) {
6730 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6734 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6736 /* this makes sure we catch the request pcd */
6737 if (seq_num == smb_reverb) {
6738 cur_pcd = &req->pcd;
6740 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6741 cur_pcd = &local_pcd;
6744 SSVAL(req->outbuf,smb_vwv0,seq_num);
6746 show_msg((char *)req->outbuf);
6747 if (!srv_send_smb(req->xconn,
6748 (char *)req->outbuf,
6749 true, req->seqnum+1,
6750 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6752 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6755 DEBUG(3,("echo %d times\n", smb_reverb));
6757 TALLOC_FREE(req->outbuf);
6759 END_PROFILE(SMBecho);
6763 /****************************************************************************
6764 Reply to a printopen.
6765 ****************************************************************************/
6767 void reply_printopen(struct smb_request *req)
6769 connection_struct *conn = req->conn;
6773 START_PROFILE(SMBsplopen);
6776 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6777 END_PROFILE(SMBsplopen);
6781 if (!CAN_PRINT(conn)) {
6782 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6783 END_PROFILE(SMBsplopen);
6787 status = file_new(req, conn, &fsp);
6788 if(!NT_STATUS_IS_OK(status)) {
6789 reply_nterror(req, status);
6790 END_PROFILE(SMBsplopen);
6794 /* Open for exclusive use, write only. */
6795 status = print_spool_open(fsp, NULL, req->vuid);
6797 if (!NT_STATUS_IS_OK(status)) {
6798 file_free(req, fsp);
6799 reply_nterror(req, status);
6800 END_PROFILE(SMBsplopen);
6804 reply_outbuf(req, 1, 0);
6805 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6807 DEBUG(3,("openprint fd=%d %s\n",
6808 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6810 END_PROFILE(SMBsplopen);
6814 /****************************************************************************
6815 Reply to a printclose.
6816 ****************************************************************************/
6818 void reply_printclose(struct smb_request *req)
6820 connection_struct *conn = req->conn;
6824 START_PROFILE(SMBsplclose);
6827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6828 END_PROFILE(SMBsplclose);
6832 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6834 if (!check_fsp(conn, req, fsp)) {
6835 END_PROFILE(SMBsplclose);
6839 if (!CAN_PRINT(conn)) {
6840 reply_force_doserror(req, ERRSRV, ERRerror);
6841 END_PROFILE(SMBsplclose);
6845 DEBUG(3,("printclose fd=%d %s\n",
6846 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6848 status = close_file(req, fsp, NORMAL_CLOSE);
6850 if(!NT_STATUS_IS_OK(status)) {
6851 reply_nterror(req, status);
6852 END_PROFILE(SMBsplclose);
6856 reply_outbuf(req, 0, 0);
6858 END_PROFILE(SMBsplclose);
6862 /****************************************************************************
6863 Reply to a printqueue.
6864 ****************************************************************************/
6866 void reply_printqueue(struct smb_request *req)
6868 const struct loadparm_substitution *lp_sub =
6869 loadparm_s3_global_substitution();
6870 connection_struct *conn = req->conn;
6874 START_PROFILE(SMBsplretq);
6877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6878 END_PROFILE(SMBsplretq);
6882 max_count = SVAL(req->vwv+0, 0);
6883 start_index = SVAL(req->vwv+1, 0);
6885 /* we used to allow the client to get the cnum wrong, but that
6886 is really quite gross and only worked when there was only
6887 one printer - I think we should now only accept it if they
6888 get it right (tridge) */
6889 if (!CAN_PRINT(conn)) {
6890 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6891 END_PROFILE(SMBsplretq);
6895 reply_outbuf(req, 2, 3);
6896 SSVAL(req->outbuf,smb_vwv0,0);
6897 SSVAL(req->outbuf,smb_vwv1,0);
6898 SCVAL(smb_buf(req->outbuf),0,1);
6899 SSVAL(smb_buf(req->outbuf),1,0);
6901 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6902 start_index, max_count));
6905 TALLOC_CTX *mem_ctx = talloc_tos();
6908 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6909 struct rpc_pipe_client *cli = NULL;
6910 struct dcerpc_binding_handle *b = NULL;
6911 struct policy_handle handle;
6912 struct spoolss_DevmodeContainer devmode_ctr;
6913 union spoolss_JobInfo *info;
6915 uint32_t num_to_get;
6919 ZERO_STRUCT(handle);
6921 status = rpc_pipe_open_interface(mem_ctx,
6924 conn->sconn->remote_address,
6925 conn->sconn->local_address,
6926 conn->sconn->msg_ctx,
6928 if (!NT_STATUS_IS_OK(status)) {
6929 DEBUG(0, ("reply_printqueue: "
6930 "could not connect to spoolss: %s\n",
6931 nt_errstr(status)));
6932 reply_nterror(req, status);
6935 b = cli->binding_handle;
6937 ZERO_STRUCT(devmode_ctr);
6939 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6942 SEC_FLAG_MAXIMUM_ALLOWED,
6945 if (!NT_STATUS_IS_OK(status)) {
6946 reply_nterror(req, status);
6949 if (!W_ERROR_IS_OK(werr)) {
6950 reply_nterror(req, werror_to_ntstatus(werr));
6954 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6962 if (!W_ERROR_IS_OK(werr)) {
6963 reply_nterror(req, werror_to_ntstatus(werr));
6967 if (max_count > 0) {
6968 first = start_index;
6970 first = start_index + max_count + 1;
6973 if (first >= count) {
6976 num_to_get = first + MIN(ABS(max_count), count - first);
6979 for (i = first; i < num_to_get; i++) {
6982 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6985 uint16_t qrapjobid = pjobid_to_rap(sharename,
6986 info[i].info2.job_id);
6988 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6994 srv_put_dos_date2(p, 0, qtime);
6995 SCVAL(p, 4, qstatus);
6996 SSVAL(p, 5, qrapjobid);
6997 SIVAL(p, 7, info[i].info2.size);
6999 status = srvstr_push(blob, req->flags2, p+12,
7000 info[i].info2.notify_name, 16, STR_ASCII, &len);
7001 if (!NT_STATUS_IS_OK(status)) {
7002 reply_nterror(req, status);
7005 if (message_push_blob(
7008 blob, sizeof(blob))) == -1) {
7009 reply_nterror(req, NT_STATUS_NO_MEMORY);
7015 SSVAL(req->outbuf,smb_vwv0,count);
7016 SSVAL(req->outbuf,smb_vwv1,
7017 (max_count>0?first+count:first-1));
7018 SCVAL(smb_buf(req->outbuf),0,1);
7019 SSVAL(smb_buf(req->outbuf),1,28*count);
7023 DEBUG(3, ("%u entries returned in queue\n",
7027 if (b && is_valid_policy_hnd(&handle)) {
7028 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
7033 END_PROFILE(SMBsplretq);
7037 /****************************************************************************
7038 Reply to a printwrite.
7039 ****************************************************************************/
7041 void reply_printwrite(struct smb_request *req)
7043 connection_struct *conn = req->conn;
7048 START_PROFILE(SMBsplwr);
7051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7052 END_PROFILE(SMBsplwr);
7056 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7058 if (!check_fsp(conn, req, fsp)) {
7059 END_PROFILE(SMBsplwr);
7063 if (!fsp->print_file) {
7064 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7065 END_PROFILE(SMBsplwr);
7069 if (!CHECK_WRITE(fsp)) {
7070 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7071 END_PROFILE(SMBsplwr);
7075 numtowrite = SVAL(req->buf, 1);
7078 * This already protects us against CVE-2017-12163.
7080 if (req->buflen < numtowrite + 3) {
7081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7082 END_PROFILE(SMBsplwr);
7086 data = (const char *)req->buf + 3;
7088 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7089 reply_nterror(req, map_nt_error_from_unix(errno));
7090 END_PROFILE(SMBsplwr);
7094 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7096 END_PROFILE(SMBsplwr);
7100 /****************************************************************************
7102 ****************************************************************************/
7104 void reply_mkdir(struct smb_request *req)
7106 connection_struct *conn = req->conn;
7107 struct smb_filename *smb_dname = NULL;
7108 char *directory = NULL;
7111 TALLOC_CTX *ctx = talloc_tos();
7113 START_PROFILE(SMBmkdir);
7115 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7116 STR_TERMINATE, &status);
7117 if (!NT_STATUS_IS_OK(status)) {
7118 reply_nterror(req, status);
7122 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7123 status = filename_convert(ctx, conn,
7129 if (!NT_STATUS_IS_OK(status)) {
7130 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7131 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7132 ERRSRV, ERRbadpath);
7135 reply_nterror(req, status);
7139 status = create_directory(conn, req, smb_dname);
7141 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7143 if (!NT_STATUS_IS_OK(status)) {
7145 if (!use_nt_status()
7146 && NT_STATUS_EQUAL(status,
7147 NT_STATUS_OBJECT_NAME_COLLISION)) {
7149 * Yes, in the DOS error code case we get a
7150 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7151 * samba4 torture test.
7153 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7156 reply_nterror(req, status);
7160 reply_outbuf(req, 0, 0);
7162 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7164 TALLOC_FREE(smb_dname);
7165 END_PROFILE(SMBmkdir);
7169 /****************************************************************************
7171 ****************************************************************************/
7173 void reply_rmdir(struct smb_request *req)
7175 connection_struct *conn = req->conn;
7176 struct smb_filename *smb_dname = NULL;
7177 char *directory = NULL;
7179 TALLOC_CTX *ctx = talloc_tos();
7180 files_struct *fsp = NULL;
7182 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7184 START_PROFILE(SMBrmdir);
7186 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7187 STR_TERMINATE, &status);
7188 if (!NT_STATUS_IS_OK(status)) {
7189 reply_nterror(req, status);
7193 status = filename_convert(ctx, conn,
7199 if (!NT_STATUS_IS_OK(status)) {
7200 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7201 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7202 ERRSRV, ERRbadpath);
7205 reply_nterror(req, status);
7209 if (is_ntfs_stream_smb_fname(smb_dname)) {
7210 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7214 status = SMB_VFS_CREATE_FILE(
7217 &conn->cwd_fsp, /* dirfsp */
7218 smb_dname, /* fname */
7219 DELETE_ACCESS, /* access_mask */
7220 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7222 FILE_OPEN, /* create_disposition*/
7223 FILE_DIRECTORY_FILE, /* create_options */
7224 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7225 0, /* oplock_request */
7227 0, /* allocation_size */
7228 0, /* private_flags */
7233 NULL, NULL); /* create context */
7235 if (!NT_STATUS_IS_OK(status)) {
7236 if (open_was_deferred(req->xconn, req->mid)) {
7237 /* We have re-scheduled this call. */
7240 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7241 bool ok = defer_smb1_sharing_violation(req);
7246 reply_nterror(req, status);
7250 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7251 if (!NT_STATUS_IS_OK(status)) {
7252 close_file(req, fsp, ERROR_CLOSE);
7253 reply_nterror(req, status);
7257 if (!set_delete_on_close(fsp, true,
7258 conn->session_info->security_token,
7259 conn->session_info->unix_token)) {
7260 close_file(req, fsp, ERROR_CLOSE);
7261 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7265 status = close_file(req, fsp, NORMAL_CLOSE);
7266 if (!NT_STATUS_IS_OK(status)) {
7267 reply_nterror(req, status);
7269 reply_outbuf(req, 0, 0);
7272 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7274 TALLOC_FREE(smb_dname);
7275 END_PROFILE(SMBrmdir);
7279 /*******************************************************************
7280 Resolve wildcards in a filename rename.
7281 ********************************************************************/
7283 static bool resolve_wildcards(TALLOC_CTX *ctx,
7288 char *name2_copy = NULL;
7293 char *p,*p2, *pname1, *pname2;
7295 name2_copy = talloc_strdup(ctx, name2);
7300 pname1 = strrchr_m(name1,'/');
7301 pname2 = strrchr_m(name2_copy,'/');
7303 if (!pname1 || !pname2) {
7307 /* Truncate the copy of name2 at the last '/' */
7310 /* Now go past the '/' */
7314 root1 = talloc_strdup(ctx, pname1);
7315 root2 = talloc_strdup(ctx, pname2);
7317 if (!root1 || !root2) {
7321 p = strrchr_m(root1,'.');
7324 ext1 = talloc_strdup(ctx, p+1);
7326 ext1 = talloc_strdup(ctx, "");
7328 p = strrchr_m(root2,'.');
7331 ext2 = talloc_strdup(ctx, p+1);
7333 ext2 = talloc_strdup(ctx, "");
7336 if (!ext1 || !ext2) {
7344 /* Hmmm. Should this be mb-aware ? */
7347 } else if (*p2 == '*') {
7349 root2 = talloc_asprintf(ctx, "%s%s",
7368 /* Hmmm. Should this be mb-aware ? */
7371 } else if (*p2 == '*') {
7373 ext2 = talloc_asprintf(ctx, "%s%s",
7389 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7394 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7406 /****************************************************************************
7407 Ensure open files have their names updated. Updated to notify other smbd's
7409 ****************************************************************************/
7411 static void rename_open_files(connection_struct *conn,
7412 struct share_mode_lock *lck,
7414 uint32_t orig_name_hash,
7415 const struct smb_filename *smb_fname_dst)
7418 bool did_rename = False;
7420 uint32_t new_name_hash = 0;
7422 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7423 fsp = file_find_di_next(fsp)) {
7424 struct file_id_buf idbuf;
7425 /* fsp_name is a relative path under the fsp. To change this for other
7426 sharepaths we need to manipulate relative paths. */
7427 /* TODO - create the absolute path and manipulate the newname
7428 relative to the sharepath. */
7429 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7432 if (fsp->name_hash != orig_name_hash) {
7435 DBG_DEBUG("renaming file %s "
7436 "(file_id %s) from %s -> %s\n",
7438 file_id_str_buf(fsp->file_id, &idbuf),
7440 smb_fname_str_dbg(smb_fname_dst));
7442 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7443 if (NT_STATUS_IS_OK(status)) {
7445 new_name_hash = fsp->name_hash;
7450 struct file_id_buf idbuf;
7451 DBG_DEBUG("no open files on file_id %s "
7453 file_id_str_buf(id, &idbuf),
7454 smb_fname_str_dbg(smb_fname_dst));
7457 /* Send messages to all smbd's (not ourself) that the name has changed. */
7458 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7459 orig_name_hash, new_name_hash,
7464 /****************************************************************************
7465 We need to check if the source path is a parent directory of the destination
7466 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7467 refuse the rename with a sharing violation. Under UNIX the above call can
7468 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7469 probably need to check that the client is a Windows one before disallowing
7470 this as a UNIX client (one with UNIX extensions) can know the source is a
7471 symlink and make this decision intelligently. Found by an excellent bug
7472 report from <AndyLiebman@aol.com>.
7473 ****************************************************************************/
7475 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7476 const struct smb_filename *smb_fname_dst)
7478 const char *psrc = smb_fname_src->base_name;
7479 const char *pdst = smb_fname_dst->base_name;
7482 if (psrc[0] == '.' && psrc[1] == '/') {
7485 if (pdst[0] == '.' && pdst[1] == '/') {
7488 if ((slen = strlen(psrc)) > strlen(pdst)) {
7491 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7495 * Do the notify calls from a rename
7498 static void notify_rename(connection_struct *conn, bool is_dir,
7499 const struct smb_filename *smb_fname_src,
7500 const struct smb_filename *smb_fname_dst)
7502 char *parent_dir_src = NULL;
7503 char *parent_dir_dst = NULL;
7506 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7507 : FILE_NOTIFY_CHANGE_FILE_NAME;
7509 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7510 &parent_dir_src, NULL) ||
7511 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7512 &parent_dir_dst, NULL)) {
7516 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7517 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7518 smb_fname_src->base_name);
7519 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7520 smb_fname_dst->base_name);
7523 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7524 smb_fname_src->base_name);
7525 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7526 smb_fname_dst->base_name);
7529 /* this is a strange one. w2k3 gives an additional event for
7530 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7531 files, but not directories */
7533 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7534 FILE_NOTIFY_CHANGE_ATTRIBUTES
7535 |FILE_NOTIFY_CHANGE_CREATION,
7536 smb_fname_dst->base_name);
7539 TALLOC_FREE(parent_dir_src);
7540 TALLOC_FREE(parent_dir_dst);
7543 /****************************************************************************
7544 Returns an error if the parent directory for a filename is open in an
7546 ****************************************************************************/
7548 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7549 const struct smb_filename *smb_fname_dst_in)
7551 struct smb_filename *smb_fname_parent = NULL;
7553 files_struct *fsp = NULL;
7557 ok = parent_smb_fname(talloc_tos(),
7562 return NT_STATUS_NO_MEMORY;
7565 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7567 return map_nt_error_from_unix(errno);
7571 * We're only checking on this smbd here, mostly good
7572 * enough.. and will pass tests.
7575 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7576 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7577 fsp = file_find_di_next(fsp)) {
7578 if (fsp->access_mask & DELETE_ACCESS) {
7579 return NT_STATUS_SHARING_VIOLATION;
7582 return NT_STATUS_OK;
7585 /****************************************************************************
7586 Rename an open file - given an fsp.
7587 ****************************************************************************/
7589 NTSTATUS rename_internals_fsp(connection_struct *conn,
7591 const struct smb_filename *smb_fname_dst_in,
7592 const char *dst_original_lcomp,
7594 bool replace_if_exists)
7596 TALLOC_CTX *ctx = talloc_tos();
7597 struct smb_filename *smb_fname_dst = NULL;
7598 NTSTATUS status = NT_STATUS_OK;
7599 struct share_mode_lock *lck = NULL;
7600 uint32_t access_mask = SEC_DIR_ADD_FILE;
7601 bool dst_exists, old_is_stream, new_is_stream;
7604 status = check_name(conn, smb_fname_dst_in);
7605 if (!NT_STATUS_IS_OK(status)) {
7609 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7610 if (!NT_STATUS_IS_OK(status)) {
7614 if (file_has_open_streams(fsp)) {
7615 return NT_STATUS_ACCESS_DENIED;
7618 /* Make a copy of the dst smb_fname structs */
7620 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7621 if (smb_fname_dst == NULL) {
7622 status = NT_STATUS_NO_MEMORY;
7627 * Check for special case with case preserving and not
7628 * case sensitive. If the new last component differs from the original
7629 * last component only by case, then we should allow
7630 * the rename (user is trying to change the case of the
7633 if (!conn->case_sensitive && conn->case_preserve &&
7634 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7635 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7636 char *fname_dst_parent = NULL;
7637 const char *fname_dst_lcomp = NULL;
7638 char *orig_lcomp_path = NULL;
7639 char *orig_lcomp_stream = NULL;
7643 * Split off the last component of the processed
7644 * destination name. We will compare this to
7645 * the split components of dst_original_lcomp.
7647 if (!parent_dirname(ctx,
7648 smb_fname_dst->base_name,
7650 &fname_dst_lcomp)) {
7651 status = NT_STATUS_NO_MEMORY;
7656 * The dst_original_lcomp component contains
7657 * the last_component of the path + stream
7658 * name (if a stream exists).
7660 * Split off the stream name so we
7661 * can check them separately.
7664 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7665 /* POSIX - no stream component. */
7666 orig_lcomp_path = talloc_strdup(ctx,
7667 dst_original_lcomp);
7668 if (orig_lcomp_path == NULL) {
7672 ok = split_stream_filename(ctx,
7675 &orig_lcomp_stream);
7679 TALLOC_FREE(fname_dst_parent);
7680 status = NT_STATUS_NO_MEMORY;
7684 /* If the base names only differ by case, use original. */
7685 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7688 * Replace the modified last component with the
7691 if (!ISDOT(fname_dst_parent)) {
7692 tmp = talloc_asprintf(smb_fname_dst,
7697 tmp = talloc_strdup(smb_fname_dst,
7701 status = NT_STATUS_NO_MEMORY;
7702 TALLOC_FREE(fname_dst_parent);
7703 TALLOC_FREE(orig_lcomp_path);
7704 TALLOC_FREE(orig_lcomp_stream);
7707 TALLOC_FREE(smb_fname_dst->base_name);
7708 smb_fname_dst->base_name = tmp;
7711 /* If the stream_names only differ by case, use original. */
7712 if(!strcsequal(smb_fname_dst->stream_name,
7713 orig_lcomp_stream)) {
7714 /* Use the original stream. */
7715 char *tmp = talloc_strdup(smb_fname_dst,
7718 status = NT_STATUS_NO_MEMORY;
7719 TALLOC_FREE(fname_dst_parent);
7720 TALLOC_FREE(orig_lcomp_path);
7721 TALLOC_FREE(orig_lcomp_stream);
7724 TALLOC_FREE(smb_fname_dst->stream_name);
7725 smb_fname_dst->stream_name = tmp;
7727 TALLOC_FREE(fname_dst_parent);
7728 TALLOC_FREE(orig_lcomp_path);
7729 TALLOC_FREE(orig_lcomp_stream);
7733 * If the src and dest names are identical - including case,
7734 * don't do the rename, just return success.
7737 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7738 strcsequal(fsp->fsp_name->stream_name,
7739 smb_fname_dst->stream_name)) {
7740 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7741 "- returning success\n",
7742 smb_fname_str_dbg(smb_fname_dst)));
7743 status = NT_STATUS_OK;
7747 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7748 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7750 /* Return the correct error code if both names aren't streams. */
7751 if (!old_is_stream && new_is_stream) {
7752 status = NT_STATUS_OBJECT_NAME_INVALID;
7756 if (old_is_stream && !new_is_stream) {
7757 status = NT_STATUS_INVALID_PARAMETER;
7761 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7763 if(!replace_if_exists && dst_exists) {
7764 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7765 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7766 smb_fname_str_dbg(smb_fname_dst)));
7767 status = NT_STATUS_OBJECT_NAME_COLLISION;
7772 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7773 &smb_fname_dst->st);
7774 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7776 /* The file can be open when renaming a stream */
7777 if (dst_fsp && !new_is_stream) {
7778 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7779 status = NT_STATUS_ACCESS_DENIED;
7784 /* Ensure we have a valid stat struct for the source. */
7785 status = vfs_stat_fsp(fsp);
7786 if (!NT_STATUS_IS_OK(status)) {
7790 status = can_rename(conn, fsp, attrs);
7792 if (!NT_STATUS_IS_OK(status)) {
7793 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7794 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7795 smb_fname_str_dbg(smb_fname_dst)));
7796 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7797 status = NT_STATUS_ACCESS_DENIED;
7801 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7802 status = NT_STATUS_ACCESS_DENIED;
7806 /* Do we have rights to move into the destination ? */
7807 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7808 /* We're moving a directory. */
7809 access_mask = SEC_DIR_ADD_SUBDIR;
7811 status = check_parent_access(conn,
7815 if (!NT_STATUS_IS_OK(status)) {
7816 DBG_INFO("check_parent_access on "
7817 "dst %s returned %s\n",
7818 smb_fname_str_dbg(smb_fname_dst),
7823 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7826 * We have the file open ourselves, so not being able to get the
7827 * corresponding share mode lock is a fatal error.
7830 SMB_ASSERT(lck != NULL);
7832 ret = SMB_VFS_RENAMEAT(conn,
7838 uint32_t create_options = fsp->fh->private_options;
7840 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7841 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7842 smb_fname_str_dbg(smb_fname_dst)));
7844 if (!fsp->fsp_flags.is_directory &&
7845 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7846 (lp_map_archive(SNUM(conn)) ||
7847 lp_store_dos_attributes(SNUM(conn)))) {
7848 /* We must set the archive bit on the newly
7850 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7851 uint32_t old_dosmode = dos_mode(conn,
7853 file_set_dosmode(conn,
7855 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7862 fsp->fsp_flags.is_directory,
7866 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7870 * A rename acts as a new file create w.r.t. allowing an initial delete
7871 * on close, probably because in Windows there is a new handle to the
7872 * new file. If initial delete on close was requested but not
7873 * originally set, we need to set it here. This is probably not 100% correct,
7874 * but will work for the CIFSFS client which in non-posix mode
7875 * depends on these semantics. JRA.
7878 if (create_options & FILE_DELETE_ON_CLOSE) {
7879 status = can_set_delete_on_close(fsp, 0);
7881 if (NT_STATUS_IS_OK(status)) {
7882 /* Note that here we set the *initial* delete on close flag,
7883 * not the regular one. The magic gets handled in close. */
7884 fsp->fsp_flags.initial_delete_on_close = true;
7888 status = NT_STATUS_OK;
7894 if (errno == ENOTDIR || errno == EISDIR) {
7895 status = NT_STATUS_OBJECT_NAME_COLLISION;
7897 status = map_nt_error_from_unix(errno);
7900 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7901 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7902 smb_fname_str_dbg(smb_fname_dst)));
7905 TALLOC_FREE(smb_fname_dst);
7910 /****************************************************************************
7911 The guts of the rename command, split out so it may be called by the NT SMB
7913 ****************************************************************************/
7915 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7916 connection_struct *conn,
7917 struct smb_request *req,
7918 struct smb_filename *smb_fname_src,
7919 struct smb_filename *smb_fname_dst,
7920 const char *dst_original_lcomp,
7922 bool replace_if_exists,
7925 uint32_t access_mask)
7927 char *fname_src_dir = NULL;
7928 struct smb_filename *smb_fname_src_dir = NULL;
7929 char *fname_src_mask = NULL;
7931 NTSTATUS status = NT_STATUS_OK;
7932 struct smb_Dir *dir_hnd = NULL;
7933 const char *dname = NULL;
7934 char *talloced = NULL;
7936 int create_options = 0;
7937 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7938 struct smb2_create_blobs *posx = NULL;
7942 * Split the old name into directory and last component
7943 * strings. Note that unix_convert may have stripped off a
7944 * leading ./ from both name and newname if the rename is
7945 * at the root of the share. We need to make sure either both
7946 * name and newname contain a / character or neither of them do
7947 * as this is checked in resolve_wildcards().
7950 /* Split up the directory from the filename/mask. */
7951 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7952 &fname_src_dir, &fname_src_mask);
7953 if (!NT_STATUS_IS_OK(status)) {
7954 status = NT_STATUS_NO_MEMORY;
7959 * We should only check the mangled cache
7960 * here if unix_convert failed. This means
7961 * that the path in 'mask' doesn't exist
7962 * on the file system and so we need to look
7963 * for a possible mangle. This patch from
7964 * Tine Smukavec <valentin.smukavec@hermes.si>.
7967 if (!VALID_STAT(smb_fname_src->st) &&
7968 mangle_is_mangled(fname_src_mask, conn->params)) {
7969 char *new_mask = NULL;
7970 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7973 TALLOC_FREE(fname_src_mask);
7974 fname_src_mask = new_mask;
7978 if (posix_pathnames) {
7979 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7980 if (!NT_STATUS_IS_OK(status)) {
7981 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7987 if (!src_has_wild) {
7991 * Only one file needs to be renamed. Append the mask back
7992 * onto the directory.
7994 TALLOC_FREE(smb_fname_src->base_name);
7995 if (ISDOT(fname_src_dir)) {
7996 /* Ensure we use canonical names on open. */
7997 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8001 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8006 if (!smb_fname_src->base_name) {
8007 status = NT_STATUS_NO_MEMORY;
8011 DEBUG(3, ("rename_internals: case_sensitive = %d, "
8012 "case_preserve = %d, short case preserve = %d, "
8013 "directory = %s, newname = %s, "
8014 "last_component_dest = %s\n",
8015 conn->case_sensitive, conn->case_preserve,
8016 conn->short_case_preserve,
8017 smb_fname_str_dbg(smb_fname_src),
8018 smb_fname_str_dbg(smb_fname_dst),
8019 dst_original_lcomp));
8021 /* The dest name still may have wildcards. */
8022 if (dest_has_wild) {
8023 char *fname_dst_mod = NULL;
8024 if (!resolve_wildcards(smb_fname_dst,
8025 smb_fname_src->base_name,
8026 smb_fname_dst->base_name,
8028 DEBUG(6, ("rename_internals: resolve_wildcards "
8030 smb_fname_src->base_name,
8031 smb_fname_dst->base_name));
8032 status = NT_STATUS_NO_MEMORY;
8035 TALLOC_FREE(smb_fname_dst->base_name);
8036 smb_fname_dst->base_name = fname_dst_mod;
8039 ZERO_STRUCT(smb_fname_src->st);
8040 if (posix_pathnames) {
8041 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8043 rc = SMB_VFS_STAT(conn, smb_fname_src);
8046 status = map_nt_error_from_unix_common(errno);
8050 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8051 create_options |= FILE_DIRECTORY_FILE;
8054 status = SMB_VFS_CREATE_FILE(
8057 &conn->cwd_fsp, /* dirfsp */
8058 smb_fname_src, /* fname */
8059 access_mask, /* access_mask */
8060 (FILE_SHARE_READ | /* share_access */
8062 FILE_OPEN, /* create_disposition*/
8063 create_options, /* create_options */
8064 0, /* file_attributes */
8065 0, /* oplock_request */
8067 0, /* allocation_size */
8068 0, /* private_flags */
8073 posx, /* in_context_blobs */
8074 NULL); /* out_context_blobs */
8076 if (!NT_STATUS_IS_OK(status)) {
8077 DEBUG(3, ("Could not open rename source %s: %s\n",
8078 smb_fname_str_dbg(smb_fname_src),
8079 nt_errstr(status)));
8083 status = rename_internals_fsp(conn,
8090 close_file(req, fsp, NORMAL_CLOSE);
8092 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8093 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8094 smb_fname_str_dbg(smb_fname_dst)));
8100 * Wildcards - process each file that matches.
8102 if (strequal(fname_src_mask, "????????.???")) {
8103 TALLOC_FREE(fname_src_mask);
8104 fname_src_mask = talloc_strdup(ctx, "*");
8105 if (!fname_src_mask) {
8106 status = NT_STATUS_NO_MEMORY;
8111 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8115 smb_fname_src->twrp,
8116 smb_fname_src->flags);
8117 if (smb_fname_src_dir == NULL) {
8118 status = NT_STATUS_NO_MEMORY;
8122 status = check_name(conn, smb_fname_src_dir);
8123 if (!NT_STATUS_IS_OK(status)) {
8127 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8129 if (dir_hnd == NULL) {
8130 status = map_nt_error_from_unix(errno);
8134 status = NT_STATUS_NO_SUCH_FILE;
8136 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8137 * - gentest fix. JRA
8140 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8142 files_struct *fsp = NULL;
8143 char *destname = NULL;
8144 bool sysdir_entry = False;
8146 /* Quick check for "." and ".." */
8147 if (ISDOT(dname) || ISDOTDOT(dname)) {
8148 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8149 sysdir_entry = True;
8151 TALLOC_FREE(talloced);
8156 if (!is_visible_file(conn,
8161 TALLOC_FREE(talloced);
8165 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8166 TALLOC_FREE(talloced);
8171 status = NT_STATUS_OBJECT_NAME_INVALID;
8175 TALLOC_FREE(smb_fname_src->base_name);
8176 if (ISDOT(fname_src_dir)) {
8177 /* Ensure we use canonical names on open. */
8178 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8182 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8187 if (!smb_fname_src->base_name) {
8188 status = NT_STATUS_NO_MEMORY;
8192 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8193 smb_fname_dst->base_name,
8195 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8196 smb_fname_src->base_name, destname));
8197 TALLOC_FREE(talloced);
8201 status = NT_STATUS_NO_MEMORY;
8205 TALLOC_FREE(smb_fname_dst->base_name);
8206 smb_fname_dst->base_name = destname;
8208 ZERO_STRUCT(smb_fname_src->st);
8209 if (posix_pathnames) {
8210 SMB_VFS_LSTAT(conn, smb_fname_src);
8212 SMB_VFS_STAT(conn, smb_fname_src);
8217 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8218 create_options |= FILE_DIRECTORY_FILE;
8221 status = SMB_VFS_CREATE_FILE(
8224 &conn->cwd_fsp, /* dirfsp */
8225 smb_fname_src, /* fname */
8226 access_mask, /* access_mask */
8227 (FILE_SHARE_READ | /* share_access */
8229 FILE_OPEN, /* create_disposition*/
8230 create_options, /* create_options */
8231 0, /* file_attributes */
8232 0, /* oplock_request */
8234 0, /* allocation_size */
8235 0, /* private_flags */
8240 posx, /* in_context_blobs */
8241 NULL); /* out_context_blobs */
8243 if (!NT_STATUS_IS_OK(status)) {
8244 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8245 "returned %s rename %s -> %s\n",
8247 smb_fname_str_dbg(smb_fname_src),
8248 smb_fname_str_dbg(smb_fname_dst)));
8252 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8253 if (dst_original_lcomp == NULL) {
8254 status = NT_STATUS_NO_MEMORY;
8258 status = rename_internals_fsp(conn,
8265 close_file(req, fsp, NORMAL_CLOSE);
8267 if (!NT_STATUS_IS_OK(status)) {
8268 DEBUG(3, ("rename_internals_fsp returned %s for "
8269 "rename %s -> %s\n", nt_errstr(status),
8270 smb_fname_str_dbg(smb_fname_src),
8271 smb_fname_str_dbg(smb_fname_dst)));
8277 DEBUG(3,("rename_internals: doing rename on %s -> "
8278 "%s\n", smb_fname_str_dbg(smb_fname_src),
8279 smb_fname_str_dbg(smb_fname_src)));
8280 TALLOC_FREE(talloced);
8282 TALLOC_FREE(dir_hnd);
8284 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8285 status = map_nt_error_from_unix(errno);
8290 TALLOC_FREE(talloced);
8291 TALLOC_FREE(smb_fname_src_dir);
8292 TALLOC_FREE(fname_src_dir);
8293 TALLOC_FREE(fname_src_mask);
8297 /****************************************************************************
8299 ****************************************************************************/
8301 void reply_mv(struct smb_request *req)
8303 connection_struct *conn = req->conn;
8305 char *newname = NULL;
8309 bool src_has_wcard = False;
8310 bool dest_has_wcard = False;
8311 TALLOC_CTX *ctx = talloc_tos();
8312 struct smb_filename *smb_fname_src = NULL;
8313 struct smb_filename *smb_fname_dst = NULL;
8314 const char *dst_original_lcomp = NULL;
8315 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8316 (req->posix_pathnames ?
8317 UCF_UNIX_NAME_LOOKUP :
8318 UCF_COND_ALLOW_WCARD_LCOMP);
8319 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8320 (req->posix_pathnames ?
8322 UCF_COND_ALLOW_WCARD_LCOMP);
8323 bool stream_rename = false;
8325 START_PROFILE(SMBmv);
8328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8332 attrs = SVAL(req->vwv+0, 0);
8334 p = (const char *)req->buf + 1;
8335 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
8336 &status, &src_has_wcard);
8337 if (!NT_STATUS_IS_OK(status)) {
8338 reply_nterror(req, status);
8342 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
8343 &status, &dest_has_wcard);
8344 if (!NT_STATUS_IS_OK(status)) {
8345 reply_nterror(req, status);
8349 if (!req->posix_pathnames) {
8350 /* The newname must begin with a ':' if the
8351 name contains a ':'. */
8352 if (strchr_m(name, ':')) {
8353 if (newname[0] != ':') {
8354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8357 stream_rename = true;
8361 status = filename_convert(ctx,
8369 if (!NT_STATUS_IS_OK(status)) {
8370 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8371 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8372 ERRSRV, ERRbadpath);
8375 reply_nterror(req, status);
8379 status = filename_convert(ctx,
8387 if (!NT_STATUS_IS_OK(status)) {
8388 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8389 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8390 ERRSRV, ERRbadpath);
8393 reply_nterror(req, status);
8397 /* Get the last component of the destination for rename_internals(). */
8398 dst_original_lcomp = get_original_lcomp(ctx,
8402 if (dst_original_lcomp == NULL) {
8403 reply_nterror(req, NT_STATUS_NO_MEMORY);
8407 if (stream_rename) {
8408 /* smb_fname_dst->base_name must be the same as
8409 smb_fname_src->base_name. */
8410 TALLOC_FREE(smb_fname_dst->base_name);
8411 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8412 smb_fname_src->base_name);
8413 if (!smb_fname_dst->base_name) {
8414 reply_nterror(req, NT_STATUS_NO_MEMORY);
8419 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8420 smb_fname_str_dbg(smb_fname_dst)));
8422 status = rename_internals(ctx,
8433 if (!NT_STATUS_IS_OK(status)) {
8434 if (open_was_deferred(req->xconn, req->mid)) {
8435 /* We have re-scheduled this call. */
8438 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8439 bool ok = defer_smb1_sharing_violation(req);
8444 reply_nterror(req, status);
8448 reply_outbuf(req, 0, 0);
8450 TALLOC_FREE(smb_fname_src);
8451 TALLOC_FREE(smb_fname_dst);
8456 /*******************************************************************
8457 Copy a file as part of a reply_copy.
8458 ******************************************************************/
8461 * TODO: check error codes on all callers
8464 NTSTATUS copy_file(TALLOC_CTX *ctx,
8465 connection_struct *conn,
8466 struct smb_filename *smb_fname_src,
8467 struct smb_filename *smb_fname_dst,
8470 bool target_is_directory)
8472 struct smb_filename *smb_fname_dst_tmp = NULL;
8474 files_struct *fsp1,*fsp2;
8476 uint32_t new_create_disposition;
8480 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8481 if (smb_fname_dst_tmp == NULL) {
8482 return NT_STATUS_NO_MEMORY;
8486 * If the target is a directory, extract the last component from the
8487 * src filename and append it to the dst filename
8489 if (target_is_directory) {
8492 /* dest/target can't be a stream if it's a directory. */
8493 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8495 p = strrchr_m(smb_fname_src->base_name,'/');
8499 p = smb_fname_src->base_name;
8501 smb_fname_dst_tmp->base_name =
8502 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8504 if (!smb_fname_dst_tmp->base_name) {
8505 status = NT_STATUS_NO_MEMORY;
8510 status = vfs_file_exist(conn, smb_fname_src);
8511 if (!NT_STATUS_IS_OK(status)) {
8515 if (!target_is_directory && count) {
8516 new_create_disposition = FILE_OPEN;
8518 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8521 &new_create_disposition,
8524 status = NT_STATUS_INVALID_PARAMETER;
8529 /* Open the src file for reading. */
8530 status = SMB_VFS_CREATE_FILE(
8533 &conn->cwd_fsp, /* dirfsp */
8534 smb_fname_src, /* fname */
8535 FILE_GENERIC_READ, /* access_mask */
8536 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8537 FILE_OPEN, /* create_disposition*/
8538 0, /* create_options */
8539 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8540 INTERNAL_OPEN_ONLY, /* oplock_request */
8542 0, /* allocation_size */
8543 0, /* private_flags */
8548 NULL, NULL); /* create context */
8550 if (!NT_STATUS_IS_OK(status)) {
8554 dosattrs = dos_mode(conn, smb_fname_src);
8556 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8557 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8560 /* Open the dst file for writing. */
8561 status = SMB_VFS_CREATE_FILE(
8564 &conn->cwd_fsp, /* dirfsp */
8565 smb_fname_dst, /* fname */
8566 FILE_GENERIC_WRITE, /* access_mask */
8567 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8568 new_create_disposition, /* create_disposition*/
8569 0, /* create_options */
8570 dosattrs, /* file_attributes */
8571 INTERNAL_OPEN_ONLY, /* oplock_request */
8573 0, /* allocation_size */
8574 0, /* private_flags */
8579 NULL, NULL); /* create context */
8581 if (!NT_STATUS_IS_OK(status)) {
8582 close_file(NULL, fsp1, ERROR_CLOSE);
8586 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8587 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8589 DEBUG(0, ("error - vfs lseek returned error %s\n",
8591 status = map_nt_error_from_unix(errno);
8592 close_file(NULL, fsp1, ERROR_CLOSE);
8593 close_file(NULL, fsp2, ERROR_CLOSE);
8598 /* Do the actual copy. */
8599 if (smb_fname_src->st.st_ex_size) {
8600 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8605 close_file(NULL, fsp1, NORMAL_CLOSE);
8607 /* Ensure the modtime is set correctly on the destination file. */
8608 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8611 * As we are opening fsp1 read-only we only expect
8612 * an error on close on fsp2 if we are out of space.
8613 * Thus we don't look at the error return from the
8616 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8618 if (!NT_STATUS_IS_OK(status)) {
8622 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8623 status = NT_STATUS_DISK_FULL;
8627 status = NT_STATUS_OK;
8630 TALLOC_FREE(smb_fname_dst_tmp);
8634 /****************************************************************************
8635 Reply to a file copy.
8636 ****************************************************************************/
8638 void reply_copy(struct smb_request *req)
8640 connection_struct *conn = req->conn;
8641 struct smb_filename *smb_fname_src = NULL;
8642 struct smb_filename *smb_fname_src_dir = NULL;
8643 struct smb_filename *smb_fname_dst = NULL;
8644 char *fname_src = NULL;
8645 char *fname_dst = NULL;
8646 char *fname_src_mask = NULL;
8647 char *fname_src_dir = NULL;
8650 int error = ERRnoaccess;
8654 bool target_is_directory=False;
8655 bool source_has_wild = False;
8656 bool dest_has_wild = False;
8658 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
8659 ucf_flags_from_smb_request(req);
8660 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
8661 ucf_flags_from_smb_request(req);
8662 TALLOC_CTX *ctx = talloc_tos();
8664 START_PROFILE(SMBcopy);
8667 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8671 tid2 = SVAL(req->vwv+0, 0);
8672 ofun = SVAL(req->vwv+1, 0);
8673 flags = SVAL(req->vwv+2, 0);
8675 p = (const char *)req->buf;
8676 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8677 &status, &source_has_wild);
8678 if (!NT_STATUS_IS_OK(status)) {
8679 reply_nterror(req, status);
8682 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8683 &status, &dest_has_wild);
8684 if (!NT_STATUS_IS_OK(status)) {
8685 reply_nterror(req, status);
8689 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8691 if (tid2 != conn->cnum) {
8692 /* can't currently handle inter share copies XXXX */
8693 DEBUG(3,("Rejecting inter-share copy\n"));
8694 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8698 status = filename_convert(ctx, conn,
8704 if (!NT_STATUS_IS_OK(status)) {
8705 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8706 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8707 ERRSRV, ERRbadpath);
8710 reply_nterror(req, status);
8714 status = filename_convert(ctx, conn,
8720 if (!NT_STATUS_IS_OK(status)) {
8721 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8722 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8723 ERRSRV, ERRbadpath);
8726 reply_nterror(req, status);
8730 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8732 if ((flags&1) && target_is_directory) {
8733 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8737 if ((flags&2) && !target_is_directory) {
8738 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8742 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8743 /* wants a tree copy! XXXX */
8744 DEBUG(3,("Rejecting tree copy\n"));
8745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8749 /* Split up the directory from the filename/mask. */
8750 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8751 &fname_src_dir, &fname_src_mask);
8752 if (!NT_STATUS_IS_OK(status)) {
8753 reply_nterror(req, NT_STATUS_NO_MEMORY);
8758 * We should only check the mangled cache
8759 * here if unix_convert failed. This means
8760 * that the path in 'mask' doesn't exist
8761 * on the file system and so we need to look
8762 * for a possible mangle. This patch from
8763 * Tine Smukavec <valentin.smukavec@hermes.si>.
8765 if (!VALID_STAT(smb_fname_src->st) &&
8766 mangle_is_mangled(fname_src_mask, conn->params)) {
8767 char *new_mask = NULL;
8768 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8769 &new_mask, conn->params);
8771 /* Use demangled name if one was successfully found. */
8773 TALLOC_FREE(fname_src_mask);
8774 fname_src_mask = new_mask;
8778 if (!source_has_wild) {
8781 * Only one file needs to be copied. Append the mask back onto
8784 TALLOC_FREE(smb_fname_src->base_name);
8785 if (ISDOT(fname_src_dir)) {
8786 /* Ensure we use canonical names on open. */
8787 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8791 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8796 if (!smb_fname_src->base_name) {
8797 reply_nterror(req, NT_STATUS_NO_MEMORY);
8801 if (dest_has_wild) {
8802 char *fname_dst_mod = NULL;
8803 if (!resolve_wildcards(smb_fname_dst,
8804 smb_fname_src->base_name,
8805 smb_fname_dst->base_name,
8807 reply_nterror(req, NT_STATUS_NO_MEMORY);
8810 TALLOC_FREE(smb_fname_dst->base_name);
8811 smb_fname_dst->base_name = fname_dst_mod;
8814 status = check_name(conn, smb_fname_src);
8815 if (!NT_STATUS_IS_OK(status)) {
8816 reply_nterror(req, status);
8820 status = check_name(conn, smb_fname_dst);
8821 if (!NT_STATUS_IS_OK(status)) {
8822 reply_nterror(req, status);
8826 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8827 ofun, count, target_is_directory);
8829 if(!NT_STATUS_IS_OK(status)) {
8830 reply_nterror(req, status);
8836 struct smb_Dir *dir_hnd = NULL;
8837 const char *dname = NULL;
8838 char *talloced = NULL;
8842 * There is a wildcard that requires us to actually read the
8843 * src dir and copy each file matching the mask to the dst.
8844 * Right now streams won't be copied, but this could
8845 * presumably be added with a nested loop for reach dir entry.
8847 SMB_ASSERT(!smb_fname_src->stream_name);
8848 SMB_ASSERT(!smb_fname_dst->stream_name);
8850 smb_fname_src->stream_name = NULL;
8851 smb_fname_dst->stream_name = NULL;
8853 if (strequal(fname_src_mask,"????????.???")) {
8854 TALLOC_FREE(fname_src_mask);
8855 fname_src_mask = talloc_strdup(ctx, "*");
8856 if (!fname_src_mask) {
8857 reply_nterror(req, NT_STATUS_NO_MEMORY);
8862 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8866 smb_fname_src->twrp,
8867 smb_fname_src->flags);
8868 if (smb_fname_src_dir == NULL) {
8869 reply_nterror(req, NT_STATUS_NO_MEMORY);
8873 status = check_name(conn, smb_fname_src_dir);
8874 if (!NT_STATUS_IS_OK(status)) {
8875 reply_nterror(req, status);
8879 dir_hnd = OpenDir(ctx,
8884 if (dir_hnd == NULL) {
8885 status = map_nt_error_from_unix(errno);
8886 reply_nterror(req, status);
8892 /* Iterate over the src dir copying each entry to the dst. */
8893 while ((dname = ReadDirName(dir_hnd, &offset,
8894 &smb_fname_src->st, &talloced))) {
8895 char *destname = NULL;
8897 if (ISDOT(dname) || ISDOTDOT(dname)) {
8898 TALLOC_FREE(talloced);
8902 if (!is_visible_file(conn,
8907 TALLOC_FREE(talloced);
8911 if(!mask_match(dname, fname_src_mask,
8912 conn->case_sensitive)) {
8913 TALLOC_FREE(talloced);
8917 error = ERRnoaccess;
8919 /* Get the src smb_fname struct setup. */
8920 TALLOC_FREE(smb_fname_src->base_name);
8921 if (ISDOT(fname_src_dir)) {
8922 /* Ensure we use canonical names on open. */
8923 smb_fname_src->base_name =
8924 talloc_asprintf(smb_fname_src, "%s",
8927 smb_fname_src->base_name =
8928 talloc_asprintf(smb_fname_src, "%s/%s",
8929 fname_src_dir, dname);
8932 if (!smb_fname_src->base_name) {
8933 TALLOC_FREE(dir_hnd);
8934 TALLOC_FREE(talloced);
8935 reply_nterror(req, NT_STATUS_NO_MEMORY);
8939 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8940 smb_fname_dst->base_name,
8942 TALLOC_FREE(talloced);
8946 TALLOC_FREE(dir_hnd);
8947 TALLOC_FREE(talloced);
8948 reply_nterror(req, NT_STATUS_NO_MEMORY);
8952 TALLOC_FREE(smb_fname_dst->base_name);
8953 smb_fname_dst->base_name = destname;
8955 status = check_name(conn, smb_fname_src);
8956 if (!NT_STATUS_IS_OK(status)) {
8957 TALLOC_FREE(dir_hnd);
8958 TALLOC_FREE(talloced);
8959 reply_nterror(req, status);
8963 status = check_name(conn, smb_fname_dst);
8964 if (!NT_STATUS_IS_OK(status)) {
8965 TALLOC_FREE(dir_hnd);
8966 TALLOC_FREE(talloced);
8967 reply_nterror(req, status);
8971 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8972 smb_fname_src->base_name,
8973 smb_fname_dst->base_name));
8975 status = copy_file(ctx, conn, smb_fname_src,
8976 smb_fname_dst, ofun, count,
8977 target_is_directory);
8978 if (NT_STATUS_IS_OK(status)) {
8982 TALLOC_FREE(talloced);
8984 TALLOC_FREE(dir_hnd);
8988 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8992 reply_outbuf(req, 1, 0);
8993 SSVAL(req->outbuf,smb_vwv0,count);
8995 TALLOC_FREE(smb_fname_src);
8996 TALLOC_FREE(smb_fname_src_dir);
8997 TALLOC_FREE(smb_fname_dst);
8998 TALLOC_FREE(fname_src);
8999 TALLOC_FREE(fname_dst);
9000 TALLOC_FREE(fname_src_mask);
9001 TALLOC_FREE(fname_src_dir);
9003 END_PROFILE(SMBcopy);
9008 #define DBGC_CLASS DBGC_LOCKING
9010 /****************************************************************************
9011 Get a lock pid, dealing with large count requests.
9012 ****************************************************************************/
9014 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
9015 bool large_file_format)
9017 if(!large_file_format)
9018 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9020 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9023 /****************************************************************************
9024 Get a lock count, dealing with large count requests.
9025 ****************************************************************************/
9027 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9028 bool large_file_format)
9032 if(!large_file_format) {
9033 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9036 * No BVAL, this is reversed!
9038 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9039 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9045 /****************************************************************************
9046 Get a lock offset, dealing with large offset requests.
9047 ****************************************************************************/
9049 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9050 bool large_file_format)
9052 uint64_t offset = 0;
9054 if(!large_file_format) {
9055 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9058 * No BVAL, this is reversed!
9060 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9061 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9067 struct smbd_do_unlocking_state {
9068 struct files_struct *fsp;
9069 uint16_t num_ulocks;
9070 struct smbd_lock_element *ulocks;
9071 enum brl_flavour lock_flav;
9075 static void smbd_do_unlocking_fn(
9078 bool *pmodified_dependent,
9081 struct smbd_do_unlocking_state *state = private_data;
9082 struct files_struct *fsp = state->fsp;
9083 enum brl_flavour lock_flav = state->lock_flav;
9086 for (i = 0; i < state->num_ulocks; i++) {
9087 struct smbd_lock_element *e = &state->ulocks[i];
9089 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9090 "pid %"PRIu64", file %s\n",
9096 if (e->brltype != UNLOCK_LOCK) {
9097 /* this can only happen with SMB2 */
9098 state->status = NT_STATUS_INVALID_PARAMETER;
9102 state->status = do_unlock(
9103 fsp, e->smblctx, e->count, e->offset, lock_flav);
9105 DBG_DEBUG("do_unlock returned %s\n",
9106 nt_errstr(state->status));
9108 if (!NT_STATUS_IS_OK(state->status)) {
9113 *pmodified_dependent = true;
9116 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9118 uint16_t num_ulocks,
9119 struct smbd_lock_element *ulocks,
9120 enum brl_flavour lock_flav)
9122 struct smbd_do_unlocking_state state = {
9124 .num_ulocks = num_ulocks,
9126 .lock_flav = lock_flav,
9130 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9132 status = share_mode_do_locked(
9133 fsp->file_id, smbd_do_unlocking_fn, &state);
9135 if (!NT_STATUS_IS_OK(status)) {
9136 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9140 if (!NT_STATUS_IS_OK(state.status)) {
9141 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9143 return state.status;
9146 return NT_STATUS_OK;
9149 /****************************************************************************
9150 Reply to a lockingX request.
9151 ****************************************************************************/
9153 static void reply_lockingx_done(struct tevent_req *subreq);
9155 void reply_lockingX(struct smb_request *req)
9157 connection_struct *conn = req->conn;
9159 unsigned char locktype;
9160 enum brl_type brltype;
9161 unsigned char oplocklevel;
9162 uint16_t num_ulocks;
9164 int32_t lock_timeout;
9166 const uint8_t *data;
9167 bool large_file_format;
9168 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9169 struct smbd_lock_element *locks = NULL;
9170 struct tevent_req *subreq = NULL;
9172 START_PROFILE(SMBlockingX);
9175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9176 END_PROFILE(SMBlockingX);
9180 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9181 locktype = CVAL(req->vwv+3, 0);
9182 oplocklevel = CVAL(req->vwv+3, 1);
9183 num_ulocks = SVAL(req->vwv+6, 0);
9184 num_locks = SVAL(req->vwv+7, 0);
9185 lock_timeout = IVAL(req->vwv+4, 0);
9186 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9188 if (!check_fsp(conn, req, fsp)) {
9189 END_PROFILE(SMBlockingX);
9195 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9196 /* we don't support these - and CANCEL_LOCK makes w2k
9197 and XP reboot so I don't really want to be
9198 compatible! (tridge) */
9199 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9200 END_PROFILE(SMBlockingX);
9204 /* Check if this is an oplock break on a file
9205 we have granted an oplock on.
9207 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9208 /* Client can insist on breaking to none. */
9209 bool break_to_none = (oplocklevel == 0);
9212 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9213 "for %s\n", (unsigned int)oplocklevel,
9214 fsp_fnum_dbg(fsp)));
9217 * Make sure we have granted an exclusive or batch oplock on
9221 if (fsp->oplock_type == 0) {
9223 /* The Samba4 nbench simulator doesn't understand
9224 the difference between break to level2 and break
9225 to none from level2 - it sends oplock break
9226 replies in both cases. Don't keep logging an error
9227 message here - just ignore it. JRA. */
9229 DEBUG(5,("reply_lockingX: Error : oplock break from "
9230 "client for %s (oplock=%d) and no "
9231 "oplock granted on this file (%s).\n",
9232 fsp_fnum_dbg(fsp), fsp->oplock_type,
9235 /* if this is a pure oplock break request then don't
9237 if (num_locks == 0 && num_ulocks == 0) {
9238 END_PROFILE(SMBlockingX);
9242 END_PROFILE(SMBlockingX);
9243 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9247 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9249 result = remove_oplock(fsp);
9251 result = downgrade_oplock(fsp);
9255 DEBUG(0, ("reply_lockingX: error in removing "
9256 "oplock on file %s\n", fsp_str_dbg(fsp)));
9257 /* Hmmm. Is this panic justified? */
9258 smb_panic("internal tdb error");
9261 /* if this is a pure oplock break request then don't send a
9263 if (num_locks == 0 && num_ulocks == 0) {
9264 /* Sanity check - ensure a pure oplock break is not a
9266 if (CVAL(req->vwv+0, 0) != 0xff) {
9267 DEBUG(0,("reply_lockingX: Error : pure oplock "
9268 "break is a chained %d request !\n",
9269 (unsigned int)CVAL(req->vwv+0, 0)));
9271 END_PROFILE(SMBlockingX);
9277 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9279 END_PROFILE(SMBlockingX);
9283 if (num_ulocks != 0) {
9284 struct smbd_lock_element *ulocks = NULL;
9287 ulocks = talloc_array(
9288 req, struct smbd_lock_element, num_ulocks);
9289 if (ulocks == NULL) {
9290 reply_nterror(req, NT_STATUS_NO_MEMORY);
9291 END_PROFILE(SMBlockingX);
9296 * Data now points at the beginning of the list of
9297 * smb_unlkrng structs
9299 for (i = 0; i < num_ulocks; i++) {
9300 ulocks[i].req_guid = smbd_request_guid(req,
9302 ulocks[i].smblctx = get_lock_pid(
9303 data, i, large_file_format);
9304 ulocks[i].count = get_lock_count(
9305 data, i, large_file_format);
9306 ulocks[i].offset = get_lock_offset(
9307 data, i, large_file_format);
9308 ulocks[i].brltype = UNLOCK_LOCK;
9312 * Unlock cancels pending locks
9315 ok = smbd_smb1_brl_finish_by_lock(
9322 reply_outbuf(req, 2, 0);
9323 SSVAL(req->outbuf, smb_vwv0, 0xff);
9324 SSVAL(req->outbuf, smb_vwv1, 0);
9325 END_PROFILE(SMBlockingX);
9329 status = smbd_do_unlocking(
9330 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9331 TALLOC_FREE(ulocks);
9332 if (!NT_STATUS_IS_OK(status)) {
9333 END_PROFILE(SMBlockingX);
9334 reply_nterror(req, status);
9339 /* Now do any requested locks */
9340 data += ((large_file_format ? 20 : 10)*num_ulocks);
9342 /* Data now points at the beginning of the list
9343 of smb_lkrng structs */
9345 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9346 brltype = READ_LOCK;
9348 brltype = WRITE_LOCK;
9351 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9352 if (locks == NULL) {
9353 reply_nterror(req, NT_STATUS_NO_MEMORY);
9354 END_PROFILE(SMBlockingX);
9358 for (i = 0; i < num_locks; i++) {
9359 locks[i].req_guid = smbd_request_guid(req, i),
9360 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9361 locks[i].count = get_lock_count(data, i, large_file_format);
9362 locks[i].offset = get_lock_offset(data, i, large_file_format);
9363 locks[i].brltype = brltype;
9366 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9370 if (num_locks == 0) {
9371 /* See smbtorture3 lock11 test */
9372 reply_outbuf(req, 2, 0);
9373 /* andx chain ends */
9374 SSVAL(req->outbuf, smb_vwv0, 0xff);
9375 SSVAL(req->outbuf, smb_vwv1, 0);
9376 END_PROFILE(SMBlockingX);
9380 ok = smbd_smb1_brl_finish_by_lock(
9384 locks[0], /* Windows only cancels the first lock */
9385 NT_STATUS_FILE_LOCK_CONFLICT);
9388 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9389 END_PROFILE(SMBlockingX);
9393 reply_outbuf(req, 2, 0);
9394 SSVAL(req->outbuf, smb_vwv0, 0xff);
9395 SSVAL(req->outbuf, smb_vwv1, 0);
9396 END_PROFILE(SMBlockingX);
9400 subreq = smbd_smb1_do_locks_send(
9410 if (subreq == NULL) {
9411 reply_nterror(req, NT_STATUS_NO_MEMORY);
9412 END_PROFILE(SMBlockingX);
9415 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9416 END_PROFILE(SMBlockingX);
9419 static void reply_lockingx_done(struct tevent_req *subreq)
9421 struct smb_request *req = NULL;
9425 START_PROFILE(SMBlockingX);
9427 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9430 status = smbd_smb1_do_locks_recv(subreq);
9431 TALLOC_FREE(subreq);
9433 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9435 if (NT_STATUS_IS_OK(status)) {
9436 reply_outbuf(req, 2, 0);
9437 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9438 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9440 reply_nterror(req, status);
9443 ok = srv_send_smb(req->xconn,
9444 (char *)req->outbuf,
9447 IS_CONN_ENCRYPTED(req->conn),
9450 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9453 END_PROFILE(SMBlockingX);
9457 #define DBGC_CLASS DBGC_ALL
9459 /****************************************************************************
9460 Reply to a SMBreadbmpx (read block multiplex) request.
9461 Always reply with an error, if someone has a platform really needs this,
9462 please contact vl@samba.org
9463 ****************************************************************************/
9465 void reply_readbmpx(struct smb_request *req)
9467 START_PROFILE(SMBreadBmpx);
9468 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9469 END_PROFILE(SMBreadBmpx);
9473 /****************************************************************************
9474 Reply to a SMBreadbs (read block multiplex secondary) request.
9475 Always reply with an error, if someone has a platform really needs this,
9476 please contact vl@samba.org
9477 ****************************************************************************/
9479 void reply_readbs(struct smb_request *req)
9481 START_PROFILE(SMBreadBs);
9482 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9483 END_PROFILE(SMBreadBs);
9487 /****************************************************************************
9488 Reply to a SMBsetattrE.
9489 ****************************************************************************/
9491 void reply_setattrE(struct smb_request *req)
9493 connection_struct *conn = req->conn;
9494 struct smb_file_time ft;
9498 START_PROFILE(SMBsetattrE);
9499 init_smb_file_time(&ft);
9502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9506 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9508 if(!fsp || (fsp->conn != conn)) {
9509 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9514 * Convert the DOS times into unix times.
9517 ft.atime = time_t_to_full_timespec(
9518 srv_make_unix_date2(req->vwv+3));
9519 ft.mtime = time_t_to_full_timespec(
9520 srv_make_unix_date2(req->vwv+5));
9521 ft.create_time = time_t_to_full_timespec(
9522 srv_make_unix_date2(req->vwv+1));
9524 reply_outbuf(req, 0, 0);
9527 * Patch from Ray Frush <frush@engr.colostate.edu>
9528 * Sometimes times are sent as zero - ignore them.
9531 /* Ensure we have a valid stat struct for the source. */
9532 status = vfs_stat_fsp(fsp);
9533 if (!NT_STATUS_IS_OK(status)) {
9534 reply_nterror(req, status);
9538 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9539 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9543 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9544 if (!NT_STATUS_IS_OK(status)) {
9545 reply_nterror(req, status);
9549 if (fsp->fsp_flags.modified) {
9550 trigger_write_time_update_immediate(fsp);
9553 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9556 (unsigned int)ft.atime.tv_sec,
9557 (unsigned int)ft.mtime.tv_sec,
9558 (unsigned int)ft.create_time.tv_sec
9561 END_PROFILE(SMBsetattrE);
9566 /* Back from the dead for OS/2..... JRA. */
9568 /****************************************************************************
9569 Reply to a SMBwritebmpx (write block multiplex primary) request.
9570 Always reply with an error, if someone has a platform really needs this,
9571 please contact vl@samba.org
9572 ****************************************************************************/
9574 void reply_writebmpx(struct smb_request *req)
9576 START_PROFILE(SMBwriteBmpx);
9577 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9578 END_PROFILE(SMBwriteBmpx);
9582 /****************************************************************************
9583 Reply to a SMBwritebs (write block multiplex secondary) request.
9584 Always reply with an error, if someone has a platform really needs this,
9585 please contact vl@samba.org
9586 ****************************************************************************/
9588 void reply_writebs(struct smb_request *req)
9590 START_PROFILE(SMBwriteBs);
9591 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9592 END_PROFILE(SMBwriteBs);
9596 /****************************************************************************
9597 Reply to a SMBgetattrE.
9598 ****************************************************************************/
9600 void reply_getattrE(struct smb_request *req)
9602 connection_struct *conn = req->conn;
9605 struct timespec create_ts;
9608 START_PROFILE(SMBgetattrE);
9611 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9612 END_PROFILE(SMBgetattrE);
9616 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9618 if(!fsp || (fsp->conn != conn)) {
9619 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9620 END_PROFILE(SMBgetattrE);
9624 /* Do an fstat on this file */
9625 status = vfs_stat_fsp(fsp);
9626 if (!NT_STATUS_IS_OK(status)) {
9627 reply_nterror(req, status);
9628 END_PROFILE(SMBgetattrE);
9632 mode = dos_mode(conn, fsp->fsp_name);
9635 * Convert the times into dos times. Set create
9636 * date to be last modify date as UNIX doesn't save
9640 reply_outbuf(req, 11, 0);
9642 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9643 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9644 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9645 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9646 /* Should we check pending modtime here ? JRA */
9647 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9648 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9650 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9651 SIVAL(req->outbuf, smb_vwv6, 0);
9652 SIVAL(req->outbuf, smb_vwv8, 0);
9654 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9655 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9656 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9658 SSVAL(req->outbuf,smb_vwv10, mode);
9660 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9662 END_PROFILE(SMBgetattrE);