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(
1557 conn, smb_fname, false, FILE_WRITE_ATTRIBUTES);
1558 if (!NT_STATUS_IS_OK(status)) {
1559 reply_nterror(req, status);
1563 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1565 reply_nterror(req, map_nt_error_from_unix(errno));
1570 ft.mtime = time_t_to_full_timespec(mtime);
1572 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1573 if (!NT_STATUS_IS_OK(status)) {
1574 reply_nterror(req, status);
1578 reply_outbuf(req, 0, 0);
1580 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1583 TALLOC_FREE(smb_fname);
1584 END_PROFILE(SMBsetatr);
1588 /****************************************************************************
1590 ****************************************************************************/
1592 void reply_dskattr(struct smb_request *req)
1594 connection_struct *conn = req->conn;
1596 uint64_t dfree,dsize,bsize;
1597 struct smb_filename smb_fname;
1598 START_PROFILE(SMBdskattr);
1600 ZERO_STRUCT(smb_fname);
1601 smb_fname.base_name = discard_const_p(char, ".");
1603 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1604 reply_nterror(req, map_nt_error_from_unix(errno));
1605 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1606 END_PROFILE(SMBdskattr);
1610 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1611 if (ret == (uint64_t)-1) {
1612 reply_nterror(req, map_nt_error_from_unix(errno));
1613 END_PROFILE(SMBdskattr);
1618 * Force max to fit in 16 bit fields.
1620 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1624 if (bsize > (WORDMAX*512)) {
1625 bsize = (WORDMAX*512);
1626 if (dsize > WORDMAX)
1628 if (dfree > WORDMAX)
1634 reply_outbuf(req, 5, 0);
1636 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1637 double total_space, free_space;
1638 /* we need to scale this to a number that DOS6 can handle. We
1639 use floating point so we can handle large drives on systems
1640 that don't have 64 bit integers
1642 we end up displaying a maximum of 2G to DOS systems
1644 total_space = dsize * (double)bsize;
1645 free_space = dfree * (double)bsize;
1647 dsize = (uint64_t)((total_space+63*512) / (64*512));
1648 dfree = (uint64_t)((free_space+63*512) / (64*512));
1650 if (dsize > 0xFFFF) dsize = 0xFFFF;
1651 if (dfree > 0xFFFF) dfree = 0xFFFF;
1653 SSVAL(req->outbuf,smb_vwv0,dsize);
1654 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1655 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1656 SSVAL(req->outbuf,smb_vwv3,dfree);
1658 SSVAL(req->outbuf,smb_vwv0,dsize);
1659 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1660 SSVAL(req->outbuf,smb_vwv2,512);
1661 SSVAL(req->outbuf,smb_vwv3,dfree);
1664 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1666 END_PROFILE(SMBdskattr);
1671 * Utility function to split the filename from the directory.
1673 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1674 char **fname_dir_out,
1675 char **fname_mask_out)
1677 const char *p = NULL;
1678 char *fname_dir = NULL;
1679 char *fname_mask = NULL;
1681 p = strrchr_m(fname_in, '/');
1683 fname_dir = talloc_strdup(ctx, ".");
1684 fname_mask = talloc_strdup(ctx, fname_in);
1686 fname_dir = talloc_strndup(ctx, fname_in,
1687 PTR_DIFF(p, fname_in));
1688 fname_mask = talloc_strdup(ctx, p+1);
1691 if (!fname_dir || !fname_mask) {
1692 TALLOC_FREE(fname_dir);
1693 TALLOC_FREE(fname_mask);
1694 return NT_STATUS_NO_MEMORY;
1697 *fname_dir_out = fname_dir;
1698 *fname_mask_out = fname_mask;
1699 return NT_STATUS_OK;
1702 /****************************************************************************
1704 ****************************************************************************/
1706 static bool make_dir_struct(TALLOC_CTX *ctx,
1716 char *mask2 = talloc_strdup(ctx, mask);
1722 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1726 memset(buf+1,' ',11);
1727 if ((p = strchr_m(mask2,'.')) != NULL) {
1729 push_ascii(buf+1,mask2,8, 0);
1730 push_ascii(buf+9,p+1,3, 0);
1733 push_ascii(buf+1,mask2,11, 0);
1736 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1738 srv_put_dos_date(buf,22,date);
1739 SSVAL(buf,26,size & 0xFFFF);
1740 SSVAL(buf,28,(size >> 16)&0xFFFF);
1741 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1742 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1743 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1744 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1748 /****************************************************************************
1750 Can be called from SMBsearch, SMBffirst or SMBfunique.
1751 ****************************************************************************/
1753 void reply_search(struct smb_request *req)
1755 connection_struct *conn = req->conn;
1758 char *directory = NULL;
1759 struct smb_filename *smb_fname = NULL;
1763 struct timespec date;
1765 unsigned int numentries = 0;
1766 unsigned int maxentries = 0;
1767 bool finished = False;
1772 bool check_descend = False;
1773 bool expect_close = False;
1775 bool mask_contains_wcard = False;
1776 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1777 TALLOC_CTX *ctx = talloc_tos();
1778 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1779 struct smbXsrv_connection *xconn = req->xconn;
1780 struct smbd_server_connection *sconn = req->sconn;
1781 files_struct *fsp = NULL;
1782 const struct loadparm_substitution *lp_sub =
1783 loadparm_s3_global_substitution();
1785 START_PROFILE(SMBsearch);
1788 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1792 if (req->posix_pathnames) {
1793 reply_unknown_new(req, req->cmd);
1797 /* If we were called as SMBffirst then we must expect close. */
1798 if(req->cmd == SMBffirst) {
1799 expect_close = True;
1802 reply_outbuf(req, 1, 3);
1803 maxentries = SVAL(req->vwv+0, 0);
1804 dirtype = SVAL(req->vwv+1, 0);
1805 p = (const char *)req->buf + 1;
1806 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1807 &nt_status, &mask_contains_wcard);
1808 if (!NT_STATUS_IS_OK(nt_status)) {
1809 reply_nterror(req, nt_status);
1813 if (smbreq_bufrem(req, p) < 3) {
1814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1819 status_len = SVAL(p, 0);
1822 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1824 if (status_len == 0) {
1826 struct smb_filename *smb_dname = NULL;
1827 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1828 ucf_flags_from_smb_request(req);
1829 nt_status = filename_convert(ctx, conn,
1833 &mask_contains_wcard,
1835 if (!NT_STATUS_IS_OK(nt_status)) {
1836 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1837 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1838 ERRSRV, ERRbadpath);
1841 reply_nterror(req, nt_status);
1845 directory = smb_fname->base_name;
1847 p = strrchr_m(directory,'/');
1848 if ((p != NULL) && (*directory != '/')) {
1849 mask = talloc_strdup(ctx, p + 1);
1850 directory = talloc_strndup(ctx, directory,
1851 PTR_DIFF(p, directory));
1853 mask = talloc_strdup(ctx, directory);
1854 directory = talloc_strdup(ctx,".");
1858 reply_nterror(req, NT_STATUS_NO_MEMORY);
1862 memset((char *)status,'\0',21);
1863 SCVAL(status,0,(dirtype & 0x1F));
1865 smb_dname = synthetic_smb_fname(talloc_tos(),
1870 if (smb_dname == NULL) {
1871 reply_nterror(req, NT_STATUS_NO_MEMORY);
1876 * As we've cut off the last component from
1877 * smb_fname we need to re-stat smb_dname
1878 * so FILE_OPEN disposition knows the directory
1881 if (req->posix_pathnames) {
1882 ret = SMB_VFS_LSTAT(conn, smb_dname);
1884 ret = SMB_VFS_STAT(conn, smb_dname);
1887 nt_status = map_nt_error_from_unix(errno);
1888 reply_nterror(req, nt_status);
1893 * Open an fsp on this directory for the dptr.
1895 nt_status = SMB_VFS_CREATE_FILE(
1898 0, /* root_dir_fid */
1899 smb_dname, /* dname */
1900 FILE_LIST_DIRECTORY, /* access_mask */
1902 FILE_SHARE_WRITE, /* share_access */
1903 FILE_OPEN, /* create_disposition*/
1904 FILE_DIRECTORY_FILE, /* create_options */
1905 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1906 NO_OPLOCK, /* oplock_request */
1908 0, /* allocation_size */
1909 0, /* private_flags */
1914 NULL, /* in_context */
1915 NULL);/* out_context */
1917 if (!NT_STATUS_IS_OK(nt_status)) {
1918 DBG_ERR("failed to open directory %s\n",
1919 smb_fname_str_dbg(smb_dname));
1920 reply_nterror(req, nt_status);
1924 nt_status = dptr_create(conn,
1931 mask_contains_wcard,
1935 TALLOC_FREE(smb_dname);
1937 if (!NT_STATUS_IS_OK(nt_status)) {
1939 * Use NULL here for the first parameter (req)
1940 * as this is not a client visible handle so
1941 * can'tbe part of an SMB1 chain.
1943 close_file(NULL, fsp, NORMAL_CLOSE);
1945 reply_nterror(req, nt_status);
1949 dptr_num = dptr_dnum(fsp->dptr);
1953 const char *dirpath;
1955 if (smbreq_bufrem(req, p) < 21) {
1956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1960 memcpy(status,p,21);
1961 status_dirtype = CVAL(status,0) & 0x1F;
1962 if (status_dirtype != (dirtype & 0x1F)) {
1963 dirtype = status_dirtype;
1966 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1970 dirpath = dptr_path(sconn, dptr_num);
1971 directory = talloc_strdup(ctx, dirpath);
1973 reply_nterror(req, NT_STATUS_NO_MEMORY);
1977 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1982 * For a 'continue' search we have no string. So
1983 * check from the initial saved string.
1985 if (!req->posix_pathnames) {
1986 mask_contains_wcard = ms_has_wild(mask);
1988 dirtype = dptr_attr(sconn, dptr_num);
1991 DEBUG(4,("dptr_num is %d\n",dptr_num));
1993 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1994 char buf[DIR_STRUCT_SIZE];
1995 memcpy(buf,status,21);
1996 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1997 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1998 reply_nterror(req, NT_STATUS_NO_MEMORY);
2001 dptr_fill(sconn, buf+12,dptr_num);
2002 if (dptr_zero(buf+12) && (status_len==0)) {
2007 if (message_push_blob(&req->outbuf,
2008 data_blob_const(buf, sizeof(buf)))
2010 reply_nterror(req, NT_STATUS_NO_MEMORY);
2015 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
2016 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
2018 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
2020 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2021 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
2022 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
2023 check_descend = True;
2026 for (i=numentries;(i<maxentries) && !finished;i++) {
2027 finished = !get_dir_entry(ctx,
2038 char buf[DIR_STRUCT_SIZE];
2039 memcpy(buf,status,21);
2040 if (!make_dir_struct(ctx,
2046 convert_timespec_to_time_t(date),
2047 !allow_long_path_components)) {
2048 reply_nterror(req, NT_STATUS_NO_MEMORY);
2051 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2054 if (message_push_blob(&req->outbuf,
2055 data_blob_const(buf, sizeof(buf)))
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2067 /* If we were called as SMBffirst with smb_search_id == NULL
2068 and no entries were found then return error and close fsp->dptr
2071 if (numentries == 0) {
2074 close_file(NULL, fsp, NORMAL_CLOSE);
2077 } else if(expect_close && status_len == 0) {
2078 /* Close the dptr - we know it's gone */
2081 close_file(NULL, fsp, NORMAL_CLOSE);
2086 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2087 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2089 /* fsp may have been closed above. */
2091 close_file(NULL, fsp, NORMAL_CLOSE);
2096 if ((numentries == 0) && !mask_contains_wcard) {
2097 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2101 SSVAL(req->outbuf,smb_vwv0,numentries);
2102 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2103 SCVAL(smb_buf(req->outbuf),0,5);
2104 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2106 /* The replies here are never long name. */
2107 SSVAL(req->outbuf, smb_flg2,
2108 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2109 if (!allow_long_path_components) {
2110 SSVAL(req->outbuf, smb_flg2,
2111 SVAL(req->outbuf, smb_flg2)
2112 & (~FLAGS2_LONG_PATH_COMPONENTS));
2115 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2116 SSVAL(req->outbuf, smb_flg2,
2117 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2119 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2120 smb_fn_name(req->cmd),
2127 TALLOC_FREE(directory);
2129 TALLOC_FREE(smb_fname);
2130 END_PROFILE(SMBsearch);
2134 /****************************************************************************
2135 Reply to a fclose (stop directory search).
2136 ****************************************************************************/
2138 void reply_fclose(struct smb_request *req)
2146 bool path_contains_wcard = False;
2147 TALLOC_CTX *ctx = talloc_tos();
2148 struct smbd_server_connection *sconn = req->sconn;
2149 files_struct *fsp = NULL;
2151 START_PROFILE(SMBfclose);
2153 if (req->posix_pathnames) {
2154 reply_unknown_new(req, req->cmd);
2155 END_PROFILE(SMBfclose);
2159 p = (const char *)req->buf + 1;
2160 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2161 &err, &path_contains_wcard);
2162 if (!NT_STATUS_IS_OK(err)) {
2163 reply_nterror(req, err);
2164 END_PROFILE(SMBfclose);
2168 if (smbreq_bufrem(req, p) < 3) {
2169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2170 END_PROFILE(SMBfclose);
2175 status_len = SVAL(p,0);
2178 if (status_len == 0) {
2179 reply_force_doserror(req, ERRSRV, ERRsrverror);
2180 END_PROFILE(SMBfclose);
2184 if (smbreq_bufrem(req, p) < 21) {
2185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2186 END_PROFILE(SMBfclose);
2190 memcpy(status,p,21);
2192 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2194 /* Close the file - we know it's gone */
2195 close_file(NULL, fsp, NORMAL_CLOSE);
2200 reply_outbuf(req, 1, 0);
2201 SSVAL(req->outbuf,smb_vwv0,0);
2203 DEBUG(3,("search close\n"));
2205 END_PROFILE(SMBfclose);
2209 /****************************************************************************
2211 ****************************************************************************/
2213 void reply_open(struct smb_request *req)
2215 connection_struct *conn = req->conn;
2216 struct smb_filename *smb_fname = NULL;
2226 uint32_t access_mask;
2227 uint32_t share_mode;
2228 uint32_t create_disposition;
2229 uint32_t create_options = 0;
2230 uint32_t private_flags = 0;
2233 TALLOC_CTX *ctx = talloc_tos();
2235 START_PROFILE(SMBopen);
2238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2242 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2243 deny_mode = SVAL(req->vwv+0, 0);
2244 dos_attr = SVAL(req->vwv+1, 0);
2246 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2247 STR_TERMINATE, &status);
2248 if (!NT_STATUS_IS_OK(status)) {
2249 reply_nterror(req, status);
2253 if (!map_open_params_to_ntcreate(fname, deny_mode,
2254 OPENX_FILE_EXISTS_OPEN, &access_mask,
2255 &share_mode, &create_disposition,
2256 &create_options, &private_flags)) {
2257 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2261 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2263 status = filename_convert(ctx,
2270 if (!NT_STATUS_IS_OK(status)) {
2271 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2272 reply_botherror(req,
2273 NT_STATUS_PATH_NOT_COVERED,
2274 ERRSRV, ERRbadpath);
2277 reply_nterror(req, status);
2281 status = SMB_VFS_CREATE_FILE(
2284 0, /* root_dir_fid */
2285 smb_fname, /* fname */
2286 access_mask, /* access_mask */
2287 share_mode, /* share_access */
2288 create_disposition, /* create_disposition*/
2289 create_options, /* create_options */
2290 dos_attr, /* file_attributes */
2291 oplock_request, /* oplock_request */
2293 0, /* allocation_size */
2299 NULL, NULL); /* create context */
2301 if (!NT_STATUS_IS_OK(status)) {
2302 if (open_was_deferred(req->xconn, req->mid)) {
2303 /* We have re-scheduled this call. */
2307 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2308 reply_openerror(req, status);
2312 fsp = fcb_or_dos_open(
2319 bool ok = defer_smb1_sharing_violation(req);
2323 reply_openerror(req, status);
2328 /* Ensure we're pointing at the correct stat struct. */
2329 TALLOC_FREE(smb_fname);
2330 smb_fname = fsp->fsp_name;
2332 size = smb_fname->st.st_ex_size;
2333 fattr = dos_mode(conn, smb_fname);
2335 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2337 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2338 DEBUG(3,("attempt to open a directory %s\n",
2340 close_file(req, fsp, ERROR_CLOSE);
2341 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2342 ERRDOS, ERRnoaccess);
2346 reply_outbuf(req, 7, 0);
2347 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2348 SSVAL(req->outbuf,smb_vwv1,fattr);
2349 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2350 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2352 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2354 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2355 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2357 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2358 SCVAL(req->outbuf,smb_flg,
2359 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2362 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2363 SCVAL(req->outbuf,smb_flg,
2364 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2367 END_PROFILE(SMBopen);
2371 /****************************************************************************
2372 Reply to an open and X.
2373 ****************************************************************************/
2375 void reply_open_and_X(struct smb_request *req)
2377 connection_struct *conn = req->conn;
2378 struct smb_filename *smb_fname = NULL;
2380 uint16_t open_flags;
2383 /* Breakout the oplock request bits so we can set the
2384 reply bits separately. */
2385 int ex_oplock_request;
2386 int core_oplock_request;
2389 int smb_sattr = SVAL(req->vwv+4, 0);
2390 uint32_t smb_time = make_unix_date3(req->vwv+6);
2398 uint64_t allocation_size;
2399 ssize_t retval = -1;
2400 uint32_t access_mask;
2401 uint32_t share_mode;
2402 uint32_t create_disposition;
2403 uint32_t create_options = 0;
2404 uint32_t private_flags = 0;
2406 TALLOC_CTX *ctx = talloc_tos();
2408 START_PROFILE(SMBopenX);
2410 if (req->wct < 15) {
2411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2415 open_flags = SVAL(req->vwv+2, 0);
2416 deny_mode = SVAL(req->vwv+3, 0);
2417 smb_attr = SVAL(req->vwv+5, 0);
2418 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2419 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2420 oplock_request = ex_oplock_request | core_oplock_request;
2421 smb_ofun = SVAL(req->vwv+8, 0);
2422 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2424 /* If it's an IPC, pass off the pipe handler. */
2426 if (lp_nt_pipe_support()) {
2427 reply_open_pipe_and_X(conn, req);
2429 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2434 /* XXXX we need to handle passed times, sattr and flags */
2435 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2436 STR_TERMINATE, &status);
2437 if (!NT_STATUS_IS_OK(status)) {
2438 reply_nterror(req, status);
2442 if (!map_open_params_to_ntcreate(fname, deny_mode,
2444 &access_mask, &share_mode,
2445 &create_disposition,
2448 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2452 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2454 status = filename_convert(ctx,
2461 if (!NT_STATUS_IS_OK(status)) {
2462 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2463 reply_botherror(req,
2464 NT_STATUS_PATH_NOT_COVERED,
2465 ERRSRV, ERRbadpath);
2468 reply_nterror(req, status);
2472 status = SMB_VFS_CREATE_FILE(
2475 0, /* root_dir_fid */
2476 smb_fname, /* fname */
2477 access_mask, /* access_mask */
2478 share_mode, /* share_access */
2479 create_disposition, /* create_disposition*/
2480 create_options, /* create_options */
2481 smb_attr, /* file_attributes */
2482 oplock_request, /* oplock_request */
2484 0, /* allocation_size */
2489 &smb_action, /* pinfo */
2490 NULL, NULL); /* create context */
2492 if (!NT_STATUS_IS_OK(status)) {
2493 if (open_was_deferred(req->xconn, req->mid)) {
2494 /* We have re-scheduled this call. */
2498 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2499 reply_openerror(req, status);
2503 fsp = fcb_or_dos_open(
2510 bool ok = defer_smb1_sharing_violation(req);
2514 reply_openerror(req, status);
2519 smb_action = FILE_WAS_OPENED;
2522 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2523 if the file is truncated or created. */
2524 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2525 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2526 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2527 close_file(req, fsp, ERROR_CLOSE);
2528 reply_nterror(req, NT_STATUS_DISK_FULL);
2531 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2533 close_file(req, fsp, ERROR_CLOSE);
2534 reply_nterror(req, NT_STATUS_DISK_FULL);
2537 status = vfs_stat_fsp(fsp);
2538 if (!NT_STATUS_IS_OK(status)) {
2539 close_file(req, fsp, ERROR_CLOSE);
2540 reply_nterror(req, status);
2545 fattr = dos_mode(conn, fsp->fsp_name);
2546 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2547 close_file(req, fsp, ERROR_CLOSE);
2548 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2551 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2553 /* If the caller set the extended oplock request bit
2554 and we granted one (by whatever means) - set the
2555 correct bit for extended oplock reply.
2558 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2559 smb_action |= EXTENDED_OPLOCK_GRANTED;
2562 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2563 smb_action |= EXTENDED_OPLOCK_GRANTED;
2566 /* If the caller set the core oplock request bit
2567 and we granted one (by whatever means) - set the
2568 correct bit for core oplock reply.
2571 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2572 reply_outbuf(req, 19, 0);
2574 reply_outbuf(req, 15, 0);
2577 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2578 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2580 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2581 SCVAL(req->outbuf, smb_flg,
2582 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2585 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2586 SCVAL(req->outbuf, smb_flg,
2587 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2590 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2591 SSVAL(req->outbuf,smb_vwv3,fattr);
2592 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2593 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2595 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2597 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2598 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2599 SSVAL(req->outbuf,smb_vwv11,smb_action);
2601 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2602 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2606 TALLOC_FREE(smb_fname);
2607 END_PROFILE(SMBopenX);
2611 /****************************************************************************
2612 Reply to a SMBulogoffX.
2613 ****************************************************************************/
2615 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2616 struct smbXsrv_session *session);
2617 static void reply_ulogoffX_done(struct tevent_req *req);
2619 void reply_ulogoffX(struct smb_request *smb1req)
2621 struct timeval now = timeval_current();
2622 struct smbXsrv_session *session = NULL;
2623 struct tevent_req *req;
2627 * Don't setup the profile charge here, take
2628 * it in reply_ulogoffX_done(). Not strictly correct
2629 * but better than the other SMB1 async
2630 * code that double-charges at the moment.
2633 status = smb1srv_session_lookup(smb1req->xconn,
2635 timeval_to_nttime(&now),
2637 if (!NT_STATUS_IS_OK(status)) {
2638 /* Not going async, profile here. */
2639 START_PROFILE(SMBulogoffX);
2640 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2641 (unsigned long long)smb1req->vuid);
2643 smb1req->vuid = UID_FIELD_INVALID;
2644 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2645 END_PROFILE(SMBulogoffX);
2649 req = reply_ulogoffX_send(smb1req, session);
2651 /* Not going async, profile here. */
2652 START_PROFILE(SMBulogoffX);
2653 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2654 END_PROFILE(SMBulogoffX);
2658 /* We're async. This will complete later. */
2659 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2663 struct reply_ulogoffX_state {
2664 struct tevent_queue *wait_queue;
2665 struct smbXsrv_session *session;
2668 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2670 /****************************************************************************
2671 Async SMB1 ulogoffX.
2672 Note, on failure here we deallocate and return NULL to allow the caller to
2673 SMB1 return an error of ERRnomem immediately.
2674 ****************************************************************************/
2676 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2677 struct smbXsrv_session *session)
2679 struct tevent_req *req;
2680 struct reply_ulogoffX_state *state;
2681 struct tevent_req *subreq;
2683 struct smbd_server_connection *sconn = session->client->sconn;
2684 uint64_t vuid = session->global->session_wire_id;
2686 req = tevent_req_create(smb1req, &state,
2687 struct reply_ulogoffX_state);
2691 state->wait_queue = tevent_queue_create(state,
2692 "reply_ulogoffX_wait_queue");
2693 if (tevent_req_nomem(state->wait_queue, req)) {
2697 state->session = session;
2700 * Make sure that no new request will be able to use this session.
2701 * This ensures that once all outstanding fsp->aio_requests
2702 * on this session are done, we are safe to close it.
2704 session->status = NT_STATUS_USER_SESSION_DELETED;
2706 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2707 if (fsp->vuid != vuid) {
2711 * Flag the file as close in progress.
2712 * This will prevent any more IO being
2715 fsp->fsp_flags.closing = true;
2717 if (fsp->num_aio_requests > 0) {
2719 * Now wait until all aio requests on this fsp are
2722 * We don't set a callback, as we just want to block the
2723 * wait queue and the talloc_free() of fsp->aio_request
2724 * will remove the item from the wait queue.
2726 subreq = tevent_queue_wait_send(fsp->aio_requests,
2729 if (tevent_req_nomem(subreq, req)) {
2737 * Now we add our own waiter to the end of the queue,
2738 * this way we get notified when all pending requests are finished
2739 * and reply to the outstanding SMB1 request.
2741 subreq = tevent_queue_wait_send(state,
2744 if (tevent_req_nomem(subreq, req)) {
2750 * We're really going async - move the SMB1 request from
2751 * a talloc stackframe above us to the sconn talloc-context.
2752 * We need this to stick around until the wait_done
2753 * callback is invoked.
2755 smb1req = talloc_move(sconn, &smb1req);
2757 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2762 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2764 struct tevent_req *req = tevent_req_callback_data(
2765 subreq, struct tevent_req);
2767 tevent_queue_wait_recv(subreq);
2768 TALLOC_FREE(subreq);
2769 tevent_req_done(req);
2772 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2774 return tevent_req_simple_recv_ntstatus(req);
2777 static void reply_ulogoffX_done(struct tevent_req *req)
2779 struct smb_request *smb1req = tevent_req_callback_data(
2780 req, struct smb_request);
2781 struct reply_ulogoffX_state *state = tevent_req_data(req,
2782 struct reply_ulogoffX_state);
2783 struct smbXsrv_session *session = state->session;
2787 * Take the profile charge here. Not strictly
2788 * correct but better than the other SMB1 async
2789 * code that double-charges at the moment.
2791 START_PROFILE(SMBulogoffX);
2793 status = reply_ulogoffX_recv(req);
2795 if (!NT_STATUS_IS_OK(status)) {
2796 TALLOC_FREE(smb1req);
2797 END_PROFILE(SMBulogoffX);
2798 exit_server(__location__ ": reply_ulogoffX_recv failed");
2802 status = smbXsrv_session_logoff(session);
2803 if (!NT_STATUS_IS_OK(status)) {
2804 TALLOC_FREE(smb1req);
2805 END_PROFILE(SMBulogoffX);
2806 exit_server(__location__ ": smbXsrv_session_logoff failed");
2810 TALLOC_FREE(session);
2812 reply_outbuf(smb1req, 2, 0);
2813 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2814 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2816 DBG_NOTICE("ulogoffX vuid=%llu\n",
2817 (unsigned long long)smb1req->vuid);
2819 smb1req->vuid = UID_FIELD_INVALID;
2821 * The following call is needed to push the
2822 * reply data back out the socket after async
2823 * return. Plus it frees smb1req.
2825 smb_request_done(smb1req);
2826 END_PROFILE(SMBulogoffX);
2829 /****************************************************************************
2830 Reply to a mknew or a create.
2831 ****************************************************************************/
2833 void reply_mknew(struct smb_request *req)
2835 connection_struct *conn = req->conn;
2836 struct smb_filename *smb_fname = NULL;
2839 struct smb_file_time ft;
2841 int oplock_request = 0;
2843 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2844 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2845 uint32_t create_disposition;
2846 uint32_t create_options = 0;
2848 TALLOC_CTX *ctx = talloc_tos();
2850 START_PROFILE(SMBcreate);
2851 init_smb_file_time(&ft);
2854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2858 fattr = SVAL(req->vwv+0, 0);
2859 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2861 if (req->cmd == SMBmknew) {
2862 /* We should fail if file exists. */
2863 create_disposition = FILE_CREATE;
2865 /* Create if file doesn't exist, truncate if it does. */
2866 create_disposition = FILE_OVERWRITE_IF;
2870 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2872 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2873 STR_TERMINATE, &status);
2874 if (!NT_STATUS_IS_OK(status)) {
2875 reply_nterror(req, status);
2879 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2880 status = filename_convert(ctx,
2887 if (!NT_STATUS_IS_OK(status)) {
2888 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2889 reply_botherror(req,
2890 NT_STATUS_PATH_NOT_COVERED,
2891 ERRSRV, ERRbadpath);
2894 reply_nterror(req, status);
2898 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2899 DEBUG(0,("Attempt to create file (%s) with volid set - "
2900 "please report this\n",
2901 smb_fname_str_dbg(smb_fname)));
2904 status = SMB_VFS_CREATE_FILE(
2907 0, /* root_dir_fid */
2908 smb_fname, /* fname */
2909 access_mask, /* access_mask */
2910 share_mode, /* share_access */
2911 create_disposition, /* create_disposition*/
2912 create_options, /* create_options */
2913 fattr, /* file_attributes */
2914 oplock_request, /* oplock_request */
2916 0, /* allocation_size */
2917 0, /* private_flags */
2922 NULL, NULL); /* create context */
2924 if (!NT_STATUS_IS_OK(status)) {
2925 if (open_was_deferred(req->xconn, req->mid)) {
2926 /* We have re-scheduled this call. */
2929 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2930 bool ok = defer_smb1_sharing_violation(req);
2935 reply_openerror(req, status);
2939 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2940 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2941 if (!NT_STATUS_IS_OK(status)) {
2942 END_PROFILE(SMBcreate);
2946 reply_outbuf(req, 1, 0);
2947 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2949 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2950 SCVAL(req->outbuf,smb_flg,
2951 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2954 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2955 SCVAL(req->outbuf,smb_flg,
2956 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2959 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2960 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2961 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2962 (unsigned int)fattr));
2965 TALLOC_FREE(smb_fname);
2966 END_PROFILE(SMBcreate);
2970 /****************************************************************************
2971 Reply to a create temporary file.
2972 ****************************************************************************/
2974 void reply_ctemp(struct smb_request *req)
2976 connection_struct *conn = req->conn;
2977 struct smb_filename *smb_fname = NULL;
2978 char *wire_name = NULL;
2987 TALLOC_CTX *ctx = talloc_tos();
2989 START_PROFILE(SMBctemp);
2992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2996 fattr = SVAL(req->vwv+0, 0);
2997 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2999 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
3000 STR_TERMINATE, &status);
3001 if (!NT_STATUS_IS_OK(status)) {
3002 reply_nterror(req, status);
3006 for (i = 0; i < 10; i++) {
3008 fname = talloc_asprintf(ctx,
3011 generate_random_str_list(ctx, 5, "0123456789"));
3013 fname = talloc_asprintf(ctx,
3015 generate_random_str_list(ctx, 5, "0123456789"));
3019 reply_nterror(req, NT_STATUS_NO_MEMORY);
3023 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
3024 status = filename_convert(ctx, conn,
3030 if (!NT_STATUS_IS_OK(status)) {
3031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3032 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3033 ERRSRV, ERRbadpath);
3036 reply_nterror(req, status);
3040 /* Create the file. */
3041 status = SMB_VFS_CREATE_FILE(
3044 0, /* root_dir_fid */
3045 smb_fname, /* fname */
3046 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
3047 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
3048 FILE_CREATE, /* create_disposition*/
3049 0, /* create_options */
3050 fattr, /* file_attributes */
3051 oplock_request, /* oplock_request */
3053 0, /* allocation_size */
3054 0, /* private_flags */
3059 NULL, NULL); /* create context */
3061 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3063 TALLOC_FREE(smb_fname);
3067 if (!NT_STATUS_IS_OK(status)) {
3068 if (open_was_deferred(req->xconn, req->mid)) {
3069 /* We have re-scheduled this call. */
3072 if (NT_STATUS_EQUAL(
3073 status, NT_STATUS_SHARING_VIOLATION)) {
3074 bool ok = defer_smb1_sharing_violation(req);
3079 reply_openerror(req, status);
3087 /* Collision after 10 times... */
3088 reply_nterror(req, status);
3092 reply_outbuf(req, 1, 0);
3093 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3095 /* the returned filename is relative to the directory */
3096 s = strrchr_m(fsp->fsp_name->base_name, '/');
3098 s = fsp->fsp_name->base_name;
3104 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3105 thing in the byte section. JRA */
3106 SSVALS(p, 0, -1); /* what is this? not in spec */
3108 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3110 reply_nterror(req, NT_STATUS_NO_MEMORY);
3114 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3115 SCVAL(req->outbuf, smb_flg,
3116 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3119 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3120 SCVAL(req->outbuf, smb_flg,
3121 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3124 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3125 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3126 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
3128 TALLOC_FREE(smb_fname);
3129 TALLOC_FREE(wire_name);
3130 END_PROFILE(SMBctemp);
3134 /*******************************************************************
3135 Check if a user is allowed to rename a file.
3136 ********************************************************************/
3138 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3141 if (!CAN_WRITE(conn)) {
3142 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3145 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3146 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3147 /* Only bother to read the DOS attribute if we might deny the
3148 rename on the grounds of attribute mismatch. */
3149 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3150 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3151 return NT_STATUS_NO_SUCH_FILE;
3155 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3156 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3157 return NT_STATUS_OK;
3160 /* If no pathnames are open below this
3161 directory, allow the rename. */
3163 if (lp_strict_rename(SNUM(conn))) {
3165 * Strict rename, check open file db.
3167 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3168 return NT_STATUS_ACCESS_DENIED;
3170 } else if (file_find_subpath(fsp)) {
3172 * No strict rename, just look in local process.
3174 return NT_STATUS_ACCESS_DENIED;
3176 return NT_STATUS_OK;
3179 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3180 return NT_STATUS_OK;
3183 return NT_STATUS_ACCESS_DENIED;
3186 /*******************************************************************
3187 * unlink a file with all relevant access checks
3188 *******************************************************************/
3190 static NTSTATUS do_unlink(connection_struct *conn,
3191 struct smb_request *req,
3192 struct smb_filename *smb_fname,
3197 uint32_t dirtype_orig = dirtype;
3200 bool posix_paths = (req != NULL && req->posix_pathnames);
3201 struct smb2_create_blobs *posx = NULL;
3203 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3204 smb_fname_str_dbg(smb_fname),
3207 if (!CAN_WRITE(conn)) {
3208 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3212 ret = SMB_VFS_LSTAT(conn, smb_fname);
3214 ret = SMB_VFS_STAT(conn, smb_fname);
3217 return map_nt_error_from_unix(errno);
3220 fattr = dos_mode(conn, smb_fname);
3222 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3223 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3226 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3228 return NT_STATUS_NO_SUCH_FILE;
3231 if (!dir_check_ftype(fattr, dirtype)) {
3232 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3233 return NT_STATUS_FILE_IS_A_DIRECTORY;
3235 return NT_STATUS_NO_SUCH_FILE;
3238 if (dirtype_orig & 0x8000) {
3239 /* These will never be set for POSIX. */
3240 return NT_STATUS_NO_SUCH_FILE;
3244 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3245 return NT_STATUS_FILE_IS_A_DIRECTORY;
3248 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3249 return NT_STATUS_NO_SUCH_FILE;
3252 if (dirtype & 0xFF00) {
3253 /* These will never be set for POSIX. */
3254 return NT_STATUS_NO_SUCH_FILE;
3259 return NT_STATUS_NO_SUCH_FILE;
3262 /* Can't delete a directory. */
3263 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3264 return NT_STATUS_FILE_IS_A_DIRECTORY;
3269 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3270 return NT_STATUS_OBJECT_NAME_INVALID;
3271 #endif /* JRATEST */
3274 status = make_smb2_posix_create_ctx(
3275 talloc_tos(), &posx, 0777);
3276 if (!NT_STATUS_IS_OK(status)) {
3277 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3283 /* On open checks the open itself will check the share mode, so
3284 don't do it here as we'll get it wrong. */
3286 status = SMB_VFS_CREATE_FILE
3289 0, /* root_dir_fid */
3290 smb_fname, /* fname */
3291 DELETE_ACCESS, /* access_mask */
3292 FILE_SHARE_NONE, /* share_access */
3293 FILE_OPEN, /* create_disposition*/
3294 FILE_NON_DIRECTORY_FILE, /* create_options */
3295 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3296 0, /* oplock_request */
3298 0, /* allocation_size */
3299 0, /* private_flags */
3304 posx, /* in_context_blobs */
3305 NULL); /* out_context_blobs */
3309 if (!NT_STATUS_IS_OK(status)) {
3310 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3311 nt_errstr(status)));
3315 status = can_set_delete_on_close(fsp, fattr);
3316 if (!NT_STATUS_IS_OK(status)) {
3317 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3319 smb_fname_str_dbg(smb_fname),
3320 nt_errstr(status)));
3321 close_file(req, fsp, NORMAL_CLOSE);
3325 /* The set is across all open files on this dev/inode pair. */
3326 if (!set_delete_on_close(fsp, True,
3327 conn->session_info->security_token,
3328 conn->session_info->unix_token)) {
3329 close_file(req, fsp, NORMAL_CLOSE);
3330 return NT_STATUS_ACCESS_DENIED;
3333 return close_file(req, fsp, NORMAL_CLOSE);
3336 /****************************************************************************
3337 The guts of the unlink command, split out so it may be called by the NT SMB
3339 ****************************************************************************/
3341 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3342 uint32_t dirtype, struct smb_filename *smb_fname,
3345 char *fname_dir = NULL;
3346 char *fname_mask = NULL;
3348 NTSTATUS status = NT_STATUS_OK;
3349 struct smb_filename *smb_fname_dir = NULL;
3350 TALLOC_CTX *ctx = talloc_tos();
3352 /* Split up the directory from the filename/mask. */
3353 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3354 &fname_dir, &fname_mask);
3355 if (!NT_STATUS_IS_OK(status)) {
3360 * We should only check the mangled cache
3361 * here if unix_convert failed. This means
3362 * that the path in 'mask' doesn't exist
3363 * on the file system and so we need to look
3364 * for a possible mangle. This patch from
3365 * Tine Smukavec <valentin.smukavec@hermes.si>.
3368 if (!VALID_STAT(smb_fname->st) &&
3369 mangle_is_mangled(fname_mask, conn->params)) {
3370 char *new_mask = NULL;
3371 mangle_lookup_name_from_8_3(ctx, fname_mask,
3372 &new_mask, conn->params);
3374 TALLOC_FREE(fname_mask);
3375 fname_mask = new_mask;
3382 * Only one file needs to be unlinked. Append the mask back
3383 * onto the directory.
3385 TALLOC_FREE(smb_fname->base_name);
3386 if (ISDOT(fname_dir)) {
3387 /* Ensure we use canonical names on open. */
3388 smb_fname->base_name = talloc_asprintf(smb_fname,
3392 smb_fname->base_name = talloc_asprintf(smb_fname,
3397 if (!smb_fname->base_name) {
3398 status = NT_STATUS_NO_MEMORY;
3402 dirtype = FILE_ATTRIBUTE_NORMAL;
3405 status = check_name(conn, smb_fname);
3406 if (!NT_STATUS_IS_OK(status)) {
3410 status = do_unlink(conn, req, smb_fname, dirtype);
3411 if (!NT_STATUS_IS_OK(status)) {
3417 struct smb_Dir *dir_hnd = NULL;
3419 const char *dname = NULL;
3420 char *talloced = NULL;
3422 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3423 status = NT_STATUS_OBJECT_NAME_INVALID;
3427 dirtype = FILE_ATTRIBUTE_NORMAL;
3430 if (strequal(fname_mask,"????????.???")) {
3431 TALLOC_FREE(fname_mask);
3432 fname_mask = talloc_strdup(ctx, "*");
3434 status = NT_STATUS_NO_MEMORY;
3439 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3444 if (smb_fname_dir == NULL) {
3445 status = NT_STATUS_NO_MEMORY;
3449 status = check_name(conn, smb_fname_dir);
3450 if (!NT_STATUS_IS_OK(status)) {
3454 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3456 if (dir_hnd == NULL) {
3457 status = map_nt_error_from_unix(errno);
3461 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3462 the pattern matches against the long name, otherwise the short name
3463 We don't implement this yet XXXX
3466 status = NT_STATUS_NO_SUCH_FILE;
3468 while ((dname = ReadDirName(dir_hnd, &offset,
3469 &smb_fname->st, &talloced))) {
3470 TALLOC_CTX *frame = talloc_stackframe();
3472 if (!is_visible_file(conn, smb_fname_dir, dname,
3473 &smb_fname->st, true)) {
3475 TALLOC_FREE(talloced);
3479 /* Quick check for "." and ".." */
3480 if (ISDOT(dname) || ISDOTDOT(dname)) {
3482 TALLOC_FREE(talloced);
3486 if(!mask_match(dname, fname_mask,
3487 conn->case_sensitive)) {
3489 TALLOC_FREE(talloced);
3493 TALLOC_FREE(smb_fname->base_name);
3494 if (ISDOT(fname_dir)) {
3495 /* Ensure we use canonical names on open. */
3496 smb_fname->base_name =
3497 talloc_asprintf(smb_fname, "%s",
3500 smb_fname->base_name =
3501 talloc_asprintf(smb_fname, "%s/%s",
3505 if (!smb_fname->base_name) {
3506 TALLOC_FREE(dir_hnd);
3507 status = NT_STATUS_NO_MEMORY;
3509 TALLOC_FREE(talloced);
3513 status = check_name(conn, smb_fname);
3514 if (!NT_STATUS_IS_OK(status)) {
3515 TALLOC_FREE(dir_hnd);
3517 TALLOC_FREE(talloced);
3521 status = do_unlink(conn, req, smb_fname, dirtype);
3522 if (!NT_STATUS_IS_OK(status)) {
3523 TALLOC_FREE(dir_hnd);
3525 TALLOC_FREE(talloced);
3530 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3531 smb_fname->base_name));
3534 TALLOC_FREE(talloced);
3536 TALLOC_FREE(dir_hnd);
3539 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3540 status = map_nt_error_from_unix(errno);
3544 TALLOC_FREE(smb_fname_dir);
3545 TALLOC_FREE(fname_dir);
3546 TALLOC_FREE(fname_mask);
3550 /****************************************************************************
3552 ****************************************************************************/
3554 void reply_unlink(struct smb_request *req)
3556 connection_struct *conn = req->conn;
3558 struct smb_filename *smb_fname = NULL;
3561 bool path_contains_wcard = False;
3562 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3563 ucf_flags_from_smb_request(req);
3564 TALLOC_CTX *ctx = talloc_tos();
3566 START_PROFILE(SMBunlink);
3569 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3573 dirtype = SVAL(req->vwv+0, 0);
3575 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3576 STR_TERMINATE, &status,
3577 &path_contains_wcard);
3578 if (!NT_STATUS_IS_OK(status)) {
3579 reply_nterror(req, status);
3583 status = filename_convert(ctx, conn,
3587 &path_contains_wcard,
3589 if (!NT_STATUS_IS_OK(status)) {
3590 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3591 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3592 ERRSRV, ERRbadpath);
3595 reply_nterror(req, status);
3599 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3601 status = unlink_internals(conn, req, dirtype, smb_fname,
3602 path_contains_wcard);
3603 if (!NT_STATUS_IS_OK(status)) {
3604 if (open_was_deferred(req->xconn, req->mid)) {
3605 /* We have re-scheduled this call. */
3608 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3609 bool ok = defer_smb1_sharing_violation(req);
3614 reply_nterror(req, status);
3618 reply_outbuf(req, 0, 0);
3620 TALLOC_FREE(smb_fname);
3621 END_PROFILE(SMBunlink);
3625 /****************************************************************************
3627 ****************************************************************************/
3629 static void fail_readraw(void)
3631 const char *errstr = talloc_asprintf(talloc_tos(),
3632 "FAIL ! reply_readbraw: socket write fail (%s)",
3637 exit_server_cleanly(errstr);
3640 /****************************************************************************
3641 Fake (read/write) sendfile. Returns -1 on read or write fail.
3642 ****************************************************************************/
3644 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3645 off_t startpos, size_t nread)
3648 size_t tosend = nread;
3655 bufsize = MIN(nread, 65536);
3657 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3661 while (tosend > 0) {
3665 cur_read = MIN(tosend, bufsize);
3666 ret = read_file(fsp,buf,startpos,cur_read);
3672 /* If we had a short read, fill with zeros. */
3673 if (ret < cur_read) {
3674 memset(buf + ret, '\0', cur_read - ret);
3677 ret = write_data(xconn->transport.sock, buf, cur_read);
3678 if (ret != cur_read) {
3679 int saved_errno = errno;
3681 * Try and give an error message saying what
3684 DEBUG(0, ("write_data failed for client %s. "
3686 smbXsrv_connection_dbg(xconn),
3687 strerror(saved_errno)));
3689 errno = saved_errno;
3693 startpos += cur_read;
3697 return (ssize_t)nread;
3700 /****************************************************************************
3701 Deal with the case of sendfile reading less bytes from the file than
3702 requested. Fill with zeros (all we can do). Returns 0 on success
3703 ****************************************************************************/
3705 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3711 #define SHORT_SEND_BUFSIZE 1024
3712 if (nread < headersize) {
3713 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3714 "header for file %s (%s). Terminating\n",
3715 fsp_str_dbg(fsp), strerror(errno)));
3719 nread -= headersize;
3721 if (nread < smb_maxcnt) {
3722 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3724 DEBUG(0,("sendfile_short_send: malloc failed "
3725 "for file %s (%s). Terminating\n",
3726 fsp_str_dbg(fsp), strerror(errno)));
3730 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3731 "with zeros !\n", fsp_str_dbg(fsp)));
3733 while (nread < smb_maxcnt) {
3735 * We asked for the real file size and told sendfile
3736 * to not go beyond the end of the file. But it can
3737 * happen that in between our fstat call and the
3738 * sendfile call the file was truncated. This is very
3739 * bad because we have already announced the larger
3740 * number of bytes to the client.
3742 * The best we can do now is to send 0-bytes, just as
3743 * a read from a hole in a sparse file would do.
3745 * This should happen rarely enough that I don't care
3746 * about efficiency here :-)
3751 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3752 ret = write_data(xconn->transport.sock, buf, to_write);
3753 if (ret != to_write) {
3754 int saved_errno = errno;
3756 * Try and give an error message saying what
3759 DEBUG(0, ("write_data failed for client %s. "
3761 smbXsrv_connection_dbg(xconn),
3762 strerror(saved_errno)));
3763 errno = saved_errno;
3774 /****************************************************************************
3775 Return a readbraw error (4 bytes of zero).
3776 ****************************************************************************/
3778 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3784 smbd_lock_socket(xconn);
3785 if (write_data(xconn->transport.sock,header,4) != 4) {
3786 int saved_errno = errno;
3788 * Try and give an error message saying what
3791 DEBUG(0, ("write_data failed for client %s. "
3793 smbXsrv_connection_dbg(xconn),
3794 strerror(saved_errno)));
3795 errno = saved_errno;
3799 smbd_unlock_socket(xconn);
3802 /*******************************************************************
3803 Ensure we don't use sendfile if server smb signing is active.
3804 ********************************************************************/
3806 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3808 bool sign_active = false;
3810 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3811 if (get_Protocol() < PROTOCOL_NT1) {
3814 if (signing_state) {
3815 sign_active = smb_signing_is_active(signing_state);
3817 return (lp__use_sendfile(snum) &&
3818 (get_remote_arch() != RA_WIN95) &&
3821 /****************************************************************************
3822 Use sendfile in readbraw.
3823 ****************************************************************************/
3825 static void send_file_readbraw(connection_struct *conn,
3826 struct smb_request *req,
3832 struct smbXsrv_connection *xconn = req->xconn;
3833 char *outbuf = NULL;
3837 * We can only use sendfile on a non-chained packet
3838 * but we can use on a non-oplocked file. tridge proved this
3839 * on a train in Germany :-). JRA.
3840 * reply_readbraw has already checked the length.
3843 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3844 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3845 ssize_t sendfile_read = -1;
3847 DATA_BLOB header_blob;
3849 _smb_setlen(header,nread);
3850 header_blob = data_blob_const(header, 4);
3852 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3853 &header_blob, startpos,
3855 if (sendfile_read == -1) {
3856 /* Returning ENOSYS means no data at all was sent.
3857 * Do this as a normal read. */
3858 if (errno == ENOSYS) {
3859 goto normal_readbraw;
3863 * Special hack for broken Linux with no working sendfile. If we
3864 * return EINTR we sent the header but not the rest of the data.
3865 * Fake this up by doing read/write calls.
3867 if (errno == EINTR) {
3868 /* Ensure we don't do this again. */
3869 set_use_sendfile(SNUM(conn), False);
3870 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3872 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3873 DEBUG(0,("send_file_readbraw: "
3874 "fake_sendfile failed for "
3878 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3883 DEBUG(0,("send_file_readbraw: sendfile failed for "
3884 "file %s (%s). Terminating\n",
3885 fsp_str_dbg(fsp), strerror(errno)));
3886 exit_server_cleanly("send_file_readbraw sendfile failed");
3887 } else if (sendfile_read == 0) {
3889 * Some sendfile implementations return 0 to indicate
3890 * that there was a short read, but nothing was
3891 * actually written to the socket. In this case,
3892 * fallback to the normal read path so the header gets
3893 * the correct byte count.
3895 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3896 "bytes falling back to the normal read: "
3897 "%s\n", fsp_str_dbg(fsp)));
3898 goto normal_readbraw;
3901 /* Deal with possible short send. */
3902 if (sendfile_read != 4+nread) {
3903 ret = sendfile_short_send(xconn, fsp,
3904 sendfile_read, 4, nread);
3914 outbuf = talloc_array(NULL, char, nread+4);
3916 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3917 (unsigned)(nread+4)));
3918 reply_readbraw_error(xconn);
3923 ret = read_file(fsp,outbuf+4,startpos,nread);
3924 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3933 _smb_setlen(outbuf,ret);
3934 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3935 int saved_errno = errno;
3937 * Try and give an error message saying what
3940 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3941 smbXsrv_connection_dbg(xconn),
3942 strerror(saved_errno)));
3943 errno = saved_errno;
3948 TALLOC_FREE(outbuf);
3951 /****************************************************************************
3952 Reply to a readbraw (core+ protocol).
3953 ****************************************************************************/
3955 void reply_readbraw(struct smb_request *req)
3957 connection_struct *conn = req->conn;
3958 struct smbXsrv_connection *xconn = req->xconn;
3959 ssize_t maxcount,mincount;
3963 struct lock_struct lock;
3967 START_PROFILE(SMBreadbraw);
3969 if (srv_is_signing_active(xconn) || req->encrypted) {
3970 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3971 "raw reads/writes are disallowed.");
3975 reply_readbraw_error(xconn);
3976 END_PROFILE(SMBreadbraw);
3980 if (xconn->smb1.echo_handler.trusted_fde) {
3981 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3982 "'async smb echo handler = yes'\n"));
3983 reply_readbraw_error(xconn);
3984 END_PROFILE(SMBreadbraw);
3989 * Special check if an oplock break has been issued
3990 * and the readraw request croses on the wire, we must
3991 * return a zero length response here.
3994 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3997 * We have to do a check_fsp by hand here, as
3998 * we must always return 4 zero bytes on error,
4004 conn != fsp->conn ||
4005 req->vuid != fsp->vuid ||
4006 fsp->fsp_flags.is_directory ||
4010 * fsp could be NULL here so use the value from the packet. JRA.
4012 DEBUG(3,("reply_readbraw: fnum %d not valid "
4014 (int)SVAL(req->vwv+0, 0)));
4015 reply_readbraw_error(xconn);
4016 END_PROFILE(SMBreadbraw);
4020 /* Do a "by hand" version of CHECK_READ. */
4021 if (!(fsp->fsp_flags.can_read ||
4022 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
4023 (fsp->access_mask & FILE_EXECUTE)))) {
4024 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4025 (int)SVAL(req->vwv+0, 0)));
4026 reply_readbraw_error(xconn);
4027 END_PROFILE(SMBreadbraw);
4031 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
4032 if(req->wct == 10) {
4034 * This is a large offset (64 bit) read.
4037 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4040 DEBUG(0,("reply_readbraw: negative 64 bit "
4041 "readraw offset (%.0f) !\n",
4042 (double)startpos ));
4043 reply_readbraw_error(xconn);
4044 END_PROFILE(SMBreadbraw);
4049 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4050 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4052 /* ensure we don't overrun the packet size */
4053 maxcount = MIN(65535,maxcount);
4055 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4056 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4059 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4060 reply_readbraw_error(xconn);
4061 END_PROFILE(SMBreadbraw);
4065 status = vfs_stat_fsp(fsp);
4066 if (NT_STATUS_IS_OK(status)) {
4067 size = fsp->fsp_name->st.st_ex_size;
4070 if (startpos >= size) {
4073 nread = MIN(maxcount,(size - startpos));
4076 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4077 if (nread < mincount)
4081 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4082 "min=%lu nread=%lu\n",
4083 fsp_fnum_dbg(fsp), (double)startpos,
4084 (unsigned long)maxcount,
4085 (unsigned long)mincount,
4086 (unsigned long)nread ) );
4088 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4090 DEBUG(5,("reply_readbraw finished\n"));
4092 END_PROFILE(SMBreadbraw);
4097 #define DBGC_CLASS DBGC_LOCKING
4099 /****************************************************************************
4100 Reply to a lockread (core+ protocol).
4101 ****************************************************************************/
4103 static void reply_lockread_locked(struct tevent_req *subreq);
4105 void reply_lockread(struct smb_request *req)
4107 struct tevent_req *subreq = NULL;
4108 connection_struct *conn = req->conn;
4110 struct smbd_lock_element *lck = NULL;
4112 START_PROFILE(SMBlockread);
4115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4116 END_PROFILE(SMBlockread);
4120 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4122 if (!check_fsp(conn, req, fsp)) {
4123 END_PROFILE(SMBlockread);
4127 if (!CHECK_READ(fsp,req)) {
4128 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4129 END_PROFILE(SMBlockread);
4133 lck = talloc(req, struct smbd_lock_element);
4135 reply_nterror(req, NT_STATUS_NO_MEMORY);
4136 END_PROFILE(SMBlockread);
4141 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4142 * protocol request that predates the read/write lock concept.
4143 * Thus instead of asking for a read lock here we need to ask
4144 * for a write lock. JRA.
4145 * Note that the requested lock size is unaffected by max_send.
4148 *lck = (struct smbd_lock_element) {
4149 .req_guid = smbd_request_guid(req, 0),
4150 .smblctx = req->smbpid,
4151 .brltype = WRITE_LOCK,
4152 .count = SVAL(req->vwv+1, 0),
4153 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4156 subreq = smbd_smb1_do_locks_send(
4162 false, /* large_offset */
4166 if (subreq == NULL) {
4167 reply_nterror(req, NT_STATUS_NO_MEMORY);
4168 END_PROFILE(SMBlockread);
4171 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4172 END_PROFILE(SMBlockread);
4175 static void reply_lockread_locked(struct tevent_req *subreq)
4177 struct smb_request *req = NULL;
4183 size_t numtoread, maxtoread;
4184 struct files_struct *fsp = NULL;
4187 START_PROFILE(SMBlockread);
4189 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4192 status = smbd_smb1_do_locks_recv(subreq);
4193 TALLOC_FREE(subreq);
4195 if (!NT_STATUS_IS_OK(status)) {
4196 reply_nterror(req, status);
4200 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4202 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4206 numtoread = SVAL(req->vwv+1, 0);
4207 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4210 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4212 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4214 if (numtoread > maxtoread) {
4215 DBG_WARNING("requested read size (%zu) is greater than "
4216 "maximum allowed (%zu/%d). "
4217 "Returning short read of maximum allowed for "
4218 "compatibility with Windows 2000.\n",
4221 req->xconn->smb1.sessions.max_send);
4222 numtoread = maxtoread;
4225 reply_outbuf(req, 5, numtoread + 3);
4227 data = smb_buf(req->outbuf) + 3;
4229 nread = read_file(fsp,data,startpos,numtoread);
4232 reply_nterror(req, map_nt_error_from_unix(errno));
4236 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4238 SSVAL(req->outbuf,smb_vwv0,nread);
4239 SSVAL(req->outbuf,smb_vwv5,nread+3);
4240 p = smb_buf(req->outbuf);
4241 SCVAL(p,0,0); /* pad byte. */
4244 DEBUG(3,("lockread %s num=%d nread=%d\n",
4245 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4248 ok = srv_send_smb(req->xconn,
4249 (char *)req->outbuf,
4252 IS_CONN_ENCRYPTED(req->conn),
4255 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4258 END_PROFILE(SMBlockread);
4263 #define DBGC_CLASS DBGC_ALL
4265 /****************************************************************************
4267 ****************************************************************************/
4269 void reply_read(struct smb_request *req)
4271 connection_struct *conn = req->conn;
4278 struct lock_struct lock;
4279 struct smbXsrv_connection *xconn = req->xconn;
4281 START_PROFILE(SMBread);
4284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4285 END_PROFILE(SMBread);
4289 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4291 if (!check_fsp(conn, req, fsp)) {
4292 END_PROFILE(SMBread);
4296 if (!CHECK_READ(fsp,req)) {
4297 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4298 END_PROFILE(SMBread);
4302 numtoread = SVAL(req->vwv+1, 0);
4303 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4306 * The requested read size cannot be greater than max_send. JRA.
4308 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4310 if (numtoread > maxtoread) {
4311 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4312 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4313 (unsigned int)numtoread, (unsigned int)maxtoread,
4314 (unsigned int)xconn->smb1.sessions.max_send));
4315 numtoread = maxtoread;
4318 reply_outbuf(req, 5, numtoread+3);
4320 data = smb_buf(req->outbuf) + 3;
4322 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4323 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4326 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4327 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4328 END_PROFILE(SMBread);
4333 nread = read_file(fsp,data,startpos,numtoread);
4336 reply_nterror(req, map_nt_error_from_unix(errno));
4340 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4342 SSVAL(req->outbuf,smb_vwv0,nread);
4343 SSVAL(req->outbuf,smb_vwv5,nread+3);
4344 SCVAL(smb_buf(req->outbuf),0,1);
4345 SSVAL(smb_buf(req->outbuf),1,nread);
4347 DEBUG(3, ("read %s num=%d nread=%d\n",
4348 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4351 END_PROFILE(SMBread);
4355 /****************************************************************************
4357 ****************************************************************************/
4359 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4363 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4366 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4368 SCVAL(outbuf,smb_vwv0,0xFF);
4369 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4370 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4371 SSVAL(outbuf,smb_vwv6,
4372 (smb_wct - 4) /* offset from smb header to wct */
4373 + 1 /* the wct field */
4374 + 12 * sizeof(uint16_t) /* vwv */
4375 + 2 /* the buflen field */
4376 + 1); /* padding byte */
4377 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4378 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4379 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4380 _smb_setlen_large(outbuf,
4381 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4385 /****************************************************************************
4386 Reply to a read and X - possibly using sendfile.
4387 ****************************************************************************/
4389 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4390 files_struct *fsp, off_t startpos,
4393 struct smbXsrv_connection *xconn = req->xconn;
4395 struct lock_struct lock;
4396 int saved_errno = 0;
4399 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4400 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4403 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4404 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4409 * We can only use sendfile on a non-chained packet
4410 * but we can use on a non-oplocked file. tridge proved this
4411 * on a train in Germany :-). JRA.
4414 if (!req_is_in_chain(req) &&
4416 (fsp->base_fsp == NULL) &&
4417 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4418 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4421 status = vfs_stat_fsp(fsp);
4422 if (!NT_STATUS_IS_OK(status)) {
4423 reply_nterror(req, status);
4427 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4428 (startpos > fsp->fsp_name->st.st_ex_size) ||
4429 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4431 * We already know that we would do a short read, so don't
4432 * try the sendfile() path.
4434 goto nosendfile_read;
4438 * Set up the packet header before send. We
4439 * assume here the sendfile will work (get the
4440 * correct amount of data).
4443 header = data_blob_const(headerbuf, sizeof(headerbuf));
4445 construct_reply_common_req(req, (char *)headerbuf);
4446 setup_readX_header((char *)headerbuf, smb_maxcnt);
4448 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4449 startpos, smb_maxcnt);
4451 saved_errno = errno;
4453 /* Returning ENOSYS means no data at all was sent.
4454 Do this as a normal read. */
4455 if (errno == ENOSYS) {
4460 * Special hack for broken Linux with no working sendfile. If we
4461 * return EINTR we sent the header but not the rest of the data.
4462 * Fake this up by doing read/write calls.
4465 if (errno == EINTR) {
4466 /* Ensure we don't do this again. */
4467 set_use_sendfile(SNUM(conn), False);
4468 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4469 nread = fake_sendfile(xconn, fsp, startpos,
4472 saved_errno = errno;
4473 DEBUG(0,("send_file_readX: "
4474 "fake_sendfile failed for "
4475 "file %s (%s) for client %s. "
4478 smbXsrv_connection_dbg(xconn),
4479 strerror(saved_errno)));
4480 errno = saved_errno;
4481 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4483 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4484 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4485 /* No outbuf here means successful sendfile. */
4489 DEBUG(0,("send_file_readX: sendfile failed for file "
4490 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4492 exit_server_cleanly("send_file_readX sendfile failed");
4493 } else if (nread == 0) {
4495 * Some sendfile implementations return 0 to indicate
4496 * that there was a short read, but nothing was
4497 * actually written to the socket. In this case,
4498 * fallback to the normal read path so the header gets
4499 * the correct byte count.
4501 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4502 "falling back to the normal read: %s\n",
4507 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4508 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4510 /* Deal with possible short send. */
4511 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4514 ret = sendfile_short_send(xconn, fsp, nread,
4515 sizeof(headerbuf), smb_maxcnt);
4518 r = "send_file_readX: sendfile_short_send failed";
4519 DEBUG(0,("%s for file %s (%s).\n",
4520 r, fsp_str_dbg(fsp), strerror(errno)));
4521 exit_server_cleanly(r);
4524 /* No outbuf here means successful sendfile. */
4525 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4526 SMB_PERFCOUNT_END(&req->pcd);
4532 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4533 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4536 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4537 (startpos > fsp->fsp_name->st.st_ex_size) ||
4538 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4540 * We already know that we would do a short
4541 * read, so don't try the sendfile() path.
4543 goto nosendfile_read;
4546 construct_reply_common_req(req, (char *)headerbuf);
4547 setup_readX_header((char *)headerbuf, smb_maxcnt);
4549 /* Send out the header. */
4550 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4552 if (ret != sizeof(headerbuf)) {
4553 saved_errno = errno;
4555 * Try and give an error message saying what
4558 DEBUG(0,("send_file_readX: write_data failed for file "
4559 "%s (%s) for client %s. Terminating\n",
4561 smbXsrv_connection_dbg(xconn),
4562 strerror(saved_errno)));
4563 errno = saved_errno;
4564 exit_server_cleanly("send_file_readX sendfile failed");
4566 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4568 saved_errno = errno;
4569 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4570 "%s (%s) for client %s. Terminating\n",
4572 smbXsrv_connection_dbg(xconn),
4573 strerror(saved_errno)));
4574 errno = saved_errno;
4575 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4582 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4583 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4584 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4586 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4587 startpos, smb_maxcnt);
4588 saved_errno = errno;
4591 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4595 setup_readX_header((char *)req->outbuf, nread);
4597 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4598 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4602 TALLOC_FREE(req->outbuf);
4606 /****************************************************************************
4607 Work out how much space we have for a read return.
4608 ****************************************************************************/
4610 static size_t calc_max_read_pdu(const struct smb_request *req)
4612 struct smbXsrv_connection *xconn = req->xconn;
4614 if (xconn->protocol < PROTOCOL_NT1) {
4615 return xconn->smb1.sessions.max_send;
4618 if (!lp_large_readwrite()) {
4619 return xconn->smb1.sessions.max_send;
4622 if (req_is_in_chain(req)) {
4623 return xconn->smb1.sessions.max_send;
4626 if (req->encrypted) {
4628 * Don't take encrypted traffic up to the
4629 * limit. There are padding considerations
4630 * that make that tricky.
4632 return xconn->smb1.sessions.max_send;
4635 if (srv_is_signing_active(xconn)) {
4639 if (!lp_unix_extensions()) {
4644 * We can do ultra-large POSIX reads.
4649 /****************************************************************************
4650 Calculate how big a read can be. Copes with all clients. It's always
4651 safe to return a short read - Windows does this.
4652 ****************************************************************************/
4654 static size_t calc_read_size(const struct smb_request *req,
4658 struct smbXsrv_connection *xconn = req->xconn;
4659 size_t max_pdu = calc_max_read_pdu(req);
4660 size_t total_size = 0;
4661 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4662 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4665 * Windows explicitly ignores upper size of 0xFFFF.
4666 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4667 * We must do the same as these will never fit even in
4668 * an extended size NetBIOS packet.
4670 if (upper_size == 0xFFFF) {
4674 if (xconn->protocol < PROTOCOL_NT1) {
4678 total_size = ((upper_size<<16) | lower_size);
4681 * LARGE_READX test shows it's always safe to return
4682 * a short read. Windows does so.
4684 return MIN(total_size, max_len);
4687 /****************************************************************************
4688 Reply to a read and X.
4689 ****************************************************************************/
4691 void reply_read_and_X(struct smb_request *req)
4693 connection_struct *conn = req->conn;
4698 bool big_readX = False;
4700 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4703 START_PROFILE(SMBreadX);
4705 if ((req->wct != 10) && (req->wct != 12)) {
4706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4710 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4711 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4712 smb_maxcnt = SVAL(req->vwv+5, 0);
4714 /* If it's an IPC, pass off the pipe handler. */
4716 reply_pipe_read_and_X(req);
4717 END_PROFILE(SMBreadX);
4721 if (!check_fsp(conn, req, fsp)) {
4722 END_PROFILE(SMBreadX);
4726 if (!CHECK_READ(fsp,req)) {
4727 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4728 END_PROFILE(SMBreadX);
4732 upper_size = SVAL(req->vwv+7, 0);
4733 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4734 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4736 * This is a heuristic to avoid keeping large
4737 * outgoing buffers around over long-lived aio
4743 if (req->wct == 12) {
4745 * This is a large offset (64 bit) read.
4747 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4752 NTSTATUS status = schedule_aio_read_and_X(conn,
4757 if (NT_STATUS_IS_OK(status)) {
4758 /* Read scheduled - we're done. */
4761 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4762 /* Real error - report to client. */
4763 END_PROFILE(SMBreadX);
4764 reply_nterror(req, status);
4767 /* NT_STATUS_RETRY - fall back to sync read. */
4770 smbd_lock_socket(req->xconn);
4771 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4772 smbd_unlock_socket(req->xconn);
4775 END_PROFILE(SMBreadX);
4779 /****************************************************************************
4780 Error replies to writebraw must have smb_wct == 1. Fix this up.
4781 ****************************************************************************/
4783 void error_to_writebrawerr(struct smb_request *req)
4785 uint8_t *old_outbuf = req->outbuf;
4787 reply_outbuf(req, 1, 0);
4789 memcpy(req->outbuf, old_outbuf, smb_size);
4790 TALLOC_FREE(old_outbuf);
4793 /****************************************************************************
4794 Read 4 bytes of a smb packet and return the smb length of the packet.
4795 Store the result in the buffer. This version of the function will
4796 never return a session keepalive (length of zero).
4797 Timeout is in milliseconds.
4798 ****************************************************************************/
4800 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4803 uint8_t msgtype = NBSSkeepalive;
4805 while (msgtype == NBSSkeepalive) {
4808 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4810 if (!NT_STATUS_IS_OK(status)) {
4811 char addr[INET6_ADDRSTRLEN];
4812 /* Try and give an error message
4813 * saying what client failed. */
4814 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4815 "client %s read error = %s.\n",
4816 get_peer_addr(fd,addr,sizeof(addr)),
4817 nt_errstr(status)));
4821 msgtype = CVAL(inbuf, 0);
4824 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4825 (unsigned long)len));
4827 return NT_STATUS_OK;
4830 /****************************************************************************
4831 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4832 ****************************************************************************/
4834 void reply_writebraw(struct smb_request *req)
4836 connection_struct *conn = req->conn;
4837 struct smbXsrv_connection *xconn = req->xconn;
4840 ssize_t total_written=0;
4841 size_t numtowrite=0;
4844 const char *data=NULL;
4847 struct lock_struct lock;
4850 START_PROFILE(SMBwritebraw);
4853 * If we ever reply with an error, it must have the SMB command
4854 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4857 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4859 if (srv_is_signing_active(xconn)) {
4860 END_PROFILE(SMBwritebraw);
4861 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4862 "raw reads/writes are disallowed.");
4865 if (req->wct < 12) {
4866 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4867 error_to_writebrawerr(req);
4868 END_PROFILE(SMBwritebraw);
4872 if (xconn->smb1.echo_handler.trusted_fde) {
4873 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4874 "'async smb echo handler = yes'\n"));
4875 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4876 error_to_writebrawerr(req);
4877 END_PROFILE(SMBwritebraw);
4881 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4882 if (!check_fsp(conn, req, fsp)) {
4883 error_to_writebrawerr(req);
4884 END_PROFILE(SMBwritebraw);
4888 if (!CHECK_WRITE(fsp)) {
4889 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4890 error_to_writebrawerr(req);
4891 END_PROFILE(SMBwritebraw);
4895 tcount = IVAL(req->vwv+1, 0);
4896 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4897 write_through = BITSETW(req->vwv+7,0);
4899 /* We have to deal with slightly different formats depending
4900 on whether we are using the core+ or lanman1.0 protocol */
4902 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4903 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4904 data = smb_buf_const(req->inbuf);
4906 numtowrite = SVAL(req->vwv+10, 0);
4907 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4910 /* Ensure we don't write bytes past the end of this packet. */
4912 * This already protects us against CVE-2017-12163.
4914 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4916 error_to_writebrawerr(req);
4917 END_PROFILE(SMBwritebraw);
4921 if (!fsp->print_file) {
4922 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4923 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4926 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4927 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4928 error_to_writebrawerr(req);
4929 END_PROFILE(SMBwritebraw);
4935 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4938 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4939 "wrote=%d sync=%d\n",
4940 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4941 (int)nwritten, (int)write_through));
4943 if (nwritten < (ssize_t)numtowrite) {
4944 reply_nterror(req, NT_STATUS_DISK_FULL);
4945 error_to_writebrawerr(req);
4949 total_written = nwritten;
4951 /* Allocate a buffer of 64k + length. */
4952 buf = talloc_array(NULL, char, 65540);
4954 reply_nterror(req, NT_STATUS_NO_MEMORY);
4955 error_to_writebrawerr(req);
4959 /* Return a SMBwritebraw message to the redirector to tell
4960 * it to send more bytes */
4962 memcpy(buf, req->inbuf, smb_size);
4963 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4964 SCVAL(buf,smb_com,SMBwritebraw);
4965 SSVALS(buf,smb_vwv0,0xFFFF);
4967 if (!srv_send_smb(req->xconn,
4969 false, 0, /* no signing */
4970 IS_CONN_ENCRYPTED(conn),
4972 exit_server_cleanly("reply_writebraw: srv_send_smb "
4976 /* Now read the raw data into the buffer and write it */
4977 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4979 if (!NT_STATUS_IS_OK(status)) {
4980 exit_server_cleanly("secondary writebraw failed");
4983 /* Set up outbuf to return the correct size */
4984 reply_outbuf(req, 1, 0);
4986 if (numtowrite != 0) {
4988 if (numtowrite > 0xFFFF) {
4989 DEBUG(0,("reply_writebraw: Oversize secondary write "
4990 "raw requested (%u). Terminating\n",
4991 (unsigned int)numtowrite ));
4992 exit_server_cleanly("secondary writebraw failed");
4995 if (tcount > nwritten+numtowrite) {
4996 DEBUG(3,("reply_writebraw: Client overestimated the "
4998 (int)tcount,(int)nwritten,(int)numtowrite));
5001 status = read_data_ntstatus(xconn->transport.sock, buf+4,
5004 if (!NT_STATUS_IS_OK(status)) {
5005 /* Try and give an error message
5006 * saying what client failed. */
5007 DEBUG(0, ("reply_writebraw: Oversize secondary write "
5008 "raw read failed (%s) for client %s. "
5009 "Terminating\n", nt_errstr(status),
5010 smbXsrv_connection_dbg(xconn)));
5011 exit_server_cleanly("secondary writebraw failed");
5015 * We are not vulnerable to CVE-2017-12163
5016 * here as we are guaranteed to have numtowrite
5017 * bytes available - we just read from the client.
5019 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
5020 if (nwritten == -1) {
5022 reply_nterror(req, map_nt_error_from_unix(errno));
5023 error_to_writebrawerr(req);
5027 if (nwritten < (ssize_t)numtowrite) {
5028 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5029 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5033 total_written += nwritten;
5038 SSVAL(req->outbuf,smb_vwv0,total_written);
5040 status = sync_file(conn, fsp, write_through);
5041 if (!NT_STATUS_IS_OK(status)) {
5042 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5043 fsp_str_dbg(fsp), nt_errstr(status)));
5044 reply_nterror(req, status);
5045 error_to_writebrawerr(req);
5049 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5051 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5052 (int)total_written));
5054 /* We won't return a status if write through is not selected - this
5055 * follows what WfWg does */
5056 END_PROFILE(SMBwritebraw);
5058 if (!write_through && total_written==tcount) {
5060 #if RABBIT_PELLET_FIX
5062 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5063 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5066 if (!send_keepalive(xconn->transport.sock)) {
5067 exit_server_cleanly("reply_writebraw: send of "
5068 "keepalive failed");
5071 TALLOC_FREE(req->outbuf);
5076 END_PROFILE(SMBwritebraw);
5081 #define DBGC_CLASS DBGC_LOCKING
5083 /****************************************************************************
5084 Reply to a writeunlock (core+).
5085 ****************************************************************************/
5087 void reply_writeunlock(struct smb_request *req)
5089 connection_struct *conn = req->conn;
5090 ssize_t nwritten = -1;
5095 NTSTATUS status = NT_STATUS_OK;
5097 struct lock_struct lock;
5098 int saved_errno = 0;
5100 START_PROFILE(SMBwriteunlock);
5103 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5104 END_PROFILE(SMBwriteunlock);
5108 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5110 if (!check_fsp(conn, req, fsp)) {
5111 END_PROFILE(SMBwriteunlock);
5115 if (!CHECK_WRITE(fsp)) {
5116 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5117 END_PROFILE(SMBwriteunlock);
5121 numtowrite = SVAL(req->vwv+1, 0);
5122 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5123 data = (const char *)req->buf + 3;
5126 * Ensure client isn't asking us to write more than
5127 * they sent. CVE-2017-12163.
5129 remaining = smbreq_bufrem(req, data);
5130 if (numtowrite > remaining) {
5131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5132 END_PROFILE(SMBwriteunlock);
5136 if (!fsp->print_file && numtowrite > 0) {
5137 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5138 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5141 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5142 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5143 END_PROFILE(SMBwriteunlock);
5148 /* The special X/Open SMB protocol handling of
5149 zero length writes is *NOT* done for
5151 if(numtowrite == 0) {
5154 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5155 saved_errno = errno;
5158 status = sync_file(conn, fsp, False /* write through */);
5159 if (!NT_STATUS_IS_OK(status)) {
5160 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5161 fsp_str_dbg(fsp), nt_errstr(status)));
5162 reply_nterror(req, status);
5167 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5171 if((nwritten < numtowrite) && (numtowrite != 0)) {
5172 reply_nterror(req, NT_STATUS_DISK_FULL);
5176 if (numtowrite && !fsp->print_file) {
5177 struct smbd_lock_element l = {
5178 .req_guid = smbd_request_guid(req, 0),
5179 .smblctx = req->smbpid,
5180 .brltype = UNLOCK_LOCK,
5182 .count = numtowrite,
5184 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5185 if (NT_STATUS_V(status)) {
5186 reply_nterror(req, status);
5191 reply_outbuf(req, 1, 0);
5193 SSVAL(req->outbuf,smb_vwv0,nwritten);
5195 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5196 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5199 END_PROFILE(SMBwriteunlock);
5204 #define DBGC_CLASS DBGC_ALL
5206 /****************************************************************************
5208 ****************************************************************************/
5210 void reply_write(struct smb_request *req)
5212 connection_struct *conn = req->conn;
5215 ssize_t nwritten = -1;
5219 struct lock_struct lock;
5221 int saved_errno = 0;
5223 START_PROFILE(SMBwrite);
5226 END_PROFILE(SMBwrite);
5227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5231 /* If it's an IPC, pass off the pipe handler. */
5233 reply_pipe_write(req);
5234 END_PROFILE(SMBwrite);
5238 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5240 if (!check_fsp(conn, req, fsp)) {
5241 END_PROFILE(SMBwrite);
5245 if (!CHECK_WRITE(fsp)) {
5246 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5247 END_PROFILE(SMBwrite);
5251 numtowrite = SVAL(req->vwv+1, 0);
5252 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5253 data = (const char *)req->buf + 3;
5256 * Ensure client isn't asking us to write more than
5257 * they sent. CVE-2017-12163.
5259 remaining = smbreq_bufrem(req, data);
5260 if (numtowrite > remaining) {
5261 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5262 END_PROFILE(SMBwrite);
5266 if (!fsp->print_file) {
5267 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5268 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5271 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5272 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5273 END_PROFILE(SMBwrite);
5279 * X/Open SMB protocol says that if smb_vwv1 is
5280 * zero then the file size should be extended or
5281 * truncated to the size given in smb_vwv[2-3].
5284 if(numtowrite == 0) {
5286 * This is actually an allocate call, and set EOF. JRA.
5288 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5290 reply_nterror(req, NT_STATUS_DISK_FULL);
5293 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5295 reply_nterror(req, NT_STATUS_DISK_FULL);
5298 trigger_write_time_update_immediate(fsp);
5300 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5303 status = sync_file(conn, fsp, False);
5304 if (!NT_STATUS_IS_OK(status)) {
5305 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5306 fsp_str_dbg(fsp), nt_errstr(status)));
5307 reply_nterror(req, status);
5312 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5316 if((nwritten == 0) && (numtowrite != 0)) {
5317 reply_nterror(req, NT_STATUS_DISK_FULL);
5321 reply_outbuf(req, 1, 0);
5323 SSVAL(req->outbuf,smb_vwv0,nwritten);
5325 if (nwritten < (ssize_t)numtowrite) {
5326 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5327 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5330 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5333 END_PROFILE(SMBwrite);
5337 /****************************************************************************
5338 Ensure a buffer is a valid writeX for recvfile purposes.
5339 ****************************************************************************/
5341 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5342 (2*14) + /* word count (including bcc) */ \
5345 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5346 const uint8_t *inbuf)
5349 unsigned int doff = 0;
5350 size_t len = smb_len_large(inbuf);
5352 struct smbXsrv_open *op = NULL;
5353 struct files_struct *fsp = NULL;
5356 if (is_encrypted_packet(inbuf)) {
5357 /* Can't do this on encrypted
5362 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5366 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5367 CVAL(inbuf,smb_wct) != 14) {
5368 DEBUG(10,("is_valid_writeX_buffer: chained or "
5369 "invalid word length.\n"));
5373 fnum = SVAL(inbuf, smb_vwv2);
5374 status = smb1srv_open_lookup(xconn,
5378 if (!NT_STATUS_IS_OK(status)) {
5379 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5384 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5387 if (fsp->conn == NULL) {
5388 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5392 if (IS_IPC(fsp->conn)) {
5393 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5396 if (IS_PRINT(fsp->conn)) {
5397 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5400 if (fsp->base_fsp != NULL) {
5401 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5404 doff = SVAL(inbuf,smb_vwv11);
5406 numtowrite = SVAL(inbuf,smb_vwv10);
5408 if (len > doff && len - doff > 0xFFFF) {
5409 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5412 if (numtowrite == 0) {
5413 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5417 /* Ensure the sizes match up. */
5418 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5419 /* no pad byte...old smbclient :-( */
5420 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5422 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5426 if (len - doff != numtowrite) {
5427 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5428 "len = %u, doff = %u, numtowrite = %u\n",
5431 (unsigned int)numtowrite ));
5435 DEBUG(10,("is_valid_writeX_buffer: true "
5436 "len = %u, doff = %u, numtowrite = %u\n",
5439 (unsigned int)numtowrite ));
5444 /****************************************************************************
5445 Reply to a write and X.
5446 ****************************************************************************/
5448 void reply_write_and_X(struct smb_request *req)
5450 connection_struct *conn = req->conn;
5451 struct smbXsrv_connection *xconn = req->xconn;
5453 struct lock_struct lock;
5458 unsigned int smb_doff;
5459 unsigned int smblen;
5462 int saved_errno = 0;
5464 START_PROFILE(SMBwriteX);
5466 if ((req->wct != 12) && (req->wct != 14)) {
5467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5471 numtowrite = SVAL(req->vwv+10, 0);
5472 smb_doff = SVAL(req->vwv+11, 0);
5473 smblen = smb_len(req->inbuf);
5475 if (req->unread_bytes > 0xFFFF ||
5476 (smblen > smb_doff &&
5477 smblen - smb_doff > 0xFFFF)) {
5478 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5481 if (req->unread_bytes) {
5482 /* Can't do a recvfile write on IPC$ */
5484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5487 if (numtowrite != req->unread_bytes) {
5488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5493 * This already protects us against CVE-2017-12163.
5495 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5496 smb_doff + numtowrite > smblen) {
5497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5502 /* If it's an IPC, pass off the pipe handler. */
5504 if (req->unread_bytes) {
5505 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5508 reply_pipe_write_and_X(req);
5512 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5513 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5514 write_through = BITSETW(req->vwv+7,0);
5516 if (!check_fsp(conn, req, fsp)) {
5520 if (!CHECK_WRITE(fsp)) {
5521 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5525 data = smb_base(req->inbuf) + smb_doff;
5527 if(req->wct == 14) {
5529 * This is a large offset (64 bit) write.
5531 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5535 /* X/Open SMB protocol says that, unlike SMBwrite
5536 if the length is zero then NO truncation is
5537 done, just a write of zero. To truncate a file,
5540 if(numtowrite == 0) {
5543 if (req->unread_bytes == 0) {
5544 status = schedule_aio_write_and_X(conn,
5551 if (NT_STATUS_IS_OK(status)) {
5552 /* write scheduled - we're done. */
5555 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5556 /* Real error - report to client. */
5557 reply_nterror(req, status);
5560 /* NT_STATUS_RETRY - fall through to sync write. */
5563 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5564 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5567 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5568 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5572 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5573 saved_errno = errno;
5577 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5581 if((nwritten == 0) && (numtowrite != 0)) {
5582 reply_nterror(req, NT_STATUS_DISK_FULL);
5586 reply_outbuf(req, 6, 0);
5587 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5588 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5589 SSVAL(req->outbuf,smb_vwv2,nwritten);
5590 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5592 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5593 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5595 status = sync_file(conn, fsp, write_through);
5596 if (!NT_STATUS_IS_OK(status)) {
5597 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5598 fsp_str_dbg(fsp), nt_errstr(status)));
5599 reply_nterror(req, status);
5603 END_PROFILE(SMBwriteX);
5607 if (req->unread_bytes) {
5608 /* writeX failed. drain socket. */
5609 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5610 req->unread_bytes) {
5611 smb_panic("failed to drain pending bytes");
5613 req->unread_bytes = 0;
5616 END_PROFILE(SMBwriteX);
5620 /****************************************************************************
5622 ****************************************************************************/
5624 void reply_lseek(struct smb_request *req)
5626 connection_struct *conn = req->conn;
5633 START_PROFILE(SMBlseek);
5636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5637 END_PROFILE(SMBlseek);
5641 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5643 if (!check_fsp(conn, req, fsp)) {
5647 mode = SVAL(req->vwv+1, 0) & 3;
5648 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5649 startpos = (off_t)IVALS(req->vwv+2, 0);
5658 res = fsp->fh->pos + startpos;
5669 if (umode == SEEK_END) {
5670 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5671 if(errno == EINVAL) {
5672 off_t current_pos = startpos;
5674 status = vfs_stat_fsp(fsp);
5675 if (!NT_STATUS_IS_OK(status)) {
5676 reply_nterror(req, status);
5677 END_PROFILE(SMBlseek);
5681 current_pos += fsp->fsp_name->st.st_ex_size;
5683 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5688 reply_nterror(req, map_nt_error_from_unix(errno));
5689 END_PROFILE(SMBlseek);
5696 reply_outbuf(req, 2, 0);
5697 SIVAL(req->outbuf,smb_vwv0,res);
5699 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5700 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5702 END_PROFILE(SMBlseek);
5706 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5709 connection_struct *conn = talloc_get_type_abort(
5710 private_data, connection_struct);
5712 if (conn != fsp->conn) {
5715 if (fsp->fh->fd == -1) {
5718 sync_file(conn, fsp, True /* write through */);
5720 if (fsp->fsp_flags.modified) {
5721 trigger_write_time_update_immediate(fsp);
5727 /****************************************************************************
5729 ****************************************************************************/
5731 void reply_flush(struct smb_request *req)
5733 connection_struct *conn = req->conn;
5737 START_PROFILE(SMBflush);
5740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5744 fnum = SVAL(req->vwv+0, 0);
5745 fsp = file_fsp(req, fnum);
5747 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5752 files_forall(req->sconn, file_sync_one_fn, conn);
5754 NTSTATUS status = sync_file(conn, fsp, True);
5755 if (!NT_STATUS_IS_OK(status)) {
5756 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5757 fsp_str_dbg(fsp), nt_errstr(status)));
5758 reply_nterror(req, status);
5759 END_PROFILE(SMBflush);
5762 if (fsp->fsp_flags.modified) {
5763 trigger_write_time_update_immediate(fsp);
5767 reply_outbuf(req, 0, 0);
5769 DEBUG(3,("flush\n"));
5770 END_PROFILE(SMBflush);
5774 /****************************************************************************
5776 conn POINTER CAN BE NULL HERE !
5777 ****************************************************************************/
5779 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5780 static void reply_exit_done(struct tevent_req *req);
5782 void reply_exit(struct smb_request *smb1req)
5784 struct tevent_req *req;
5787 * Don't setup the profile charge here, take
5788 * it in reply_exit_done(). Not strictly correct
5789 * but better than the other SMB1 async
5790 * code that double-charges at the moment.
5792 req = reply_exit_send(smb1req);
5794 /* Not going async, profile here. */
5795 START_PROFILE(SMBexit);
5796 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5797 END_PROFILE(SMBexit);
5801 /* We're async. This will complete later. */
5802 tevent_req_set_callback(req, reply_exit_done, smb1req);
5806 struct reply_exit_state {
5807 struct tevent_queue *wait_queue;
5810 static void reply_exit_wait_done(struct tevent_req *subreq);
5812 /****************************************************************************
5814 Note, on failure here we deallocate and return NULL to allow the caller to
5815 SMB1 return an error of ERRnomem immediately.
5816 ****************************************************************************/
5818 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5820 struct tevent_req *req;
5821 struct reply_exit_state *state;
5822 struct tevent_req *subreq;
5824 struct smbd_server_connection *sconn = smb1req->sconn;
5826 req = tevent_req_create(smb1req, &state,
5827 struct reply_exit_state);
5831 state->wait_queue = tevent_queue_create(state,
5832 "reply_exit_wait_queue");
5833 if (tevent_req_nomem(state->wait_queue, req)) {
5838 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5839 if (fsp->file_pid != smb1req->smbpid) {
5842 if (fsp->vuid != smb1req->vuid) {
5846 * Flag the file as close in progress.
5847 * This will prevent any more IO being
5850 fsp->fsp_flags.closing = true;
5852 if (fsp->num_aio_requests > 0) {
5854 * Now wait until all aio requests on this fsp are
5857 * We don't set a callback, as we just want to block the
5858 * wait queue and the talloc_free() of fsp->aio_request
5859 * will remove the item from the wait queue.
5861 subreq = tevent_queue_wait_send(fsp->aio_requests,
5864 if (tevent_req_nomem(subreq, req)) {
5872 * Now we add our own waiter to the end of the queue,
5873 * this way we get notified when all pending requests are finished
5874 * and reply to the outstanding SMB1 request.
5876 subreq = tevent_queue_wait_send(state,
5879 if (tevent_req_nomem(subreq, req)) {
5885 * We're really going async - move the SMB1 request from
5886 * a talloc stackframe above us to the conn talloc-context.
5887 * We need this to stick around until the wait_done
5888 * callback is invoked.
5890 smb1req = talloc_move(sconn, &smb1req);
5892 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5897 static void reply_exit_wait_done(struct tevent_req *subreq)
5899 struct tevent_req *req = tevent_req_callback_data(
5900 subreq, struct tevent_req);
5902 tevent_queue_wait_recv(subreq);
5903 TALLOC_FREE(subreq);
5904 tevent_req_done(req);
5907 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5909 return tevent_req_simple_recv_ntstatus(req);
5912 static void reply_exit_done(struct tevent_req *req)
5914 struct smb_request *smb1req = tevent_req_callback_data(
5915 req, struct smb_request);
5916 struct smbd_server_connection *sconn = smb1req->sconn;
5917 struct smbXsrv_connection *xconn = smb1req->xconn;
5918 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5919 struct smbXsrv_session *session = NULL;
5920 files_struct *fsp, *next;
5924 * Take the profile charge here. Not strictly
5925 * correct but better than the other SMB1 async
5926 * code that double-charges at the moment.
5928 START_PROFILE(SMBexit);
5930 status = reply_exit_recv(req);
5932 if (!NT_STATUS_IS_OK(status)) {
5933 TALLOC_FREE(smb1req);
5934 END_PROFILE(SMBexit);
5935 exit_server(__location__ ": reply_exit_recv failed");
5940 * Ensure the session is still valid.
5942 status = smb1srv_session_lookup(xconn,
5946 if (!NT_STATUS_IS_OK(status)) {
5947 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5948 smb_request_done(smb1req);
5949 END_PROFILE(SMBexit);
5953 * Ensure the vuid is still valid - no one
5954 * called reply_ulogoffX() in the meantime.
5955 * reply_exit() doesn't have AS_USER set, so
5956 * use set_current_user_info() directly.
5957 * This is the same logic as in switch_message().
5959 if (session->global->auth_session_info != NULL) {
5960 set_current_user_info(
5961 session->global->auth_session_info->unix_info->sanitized_username,
5962 session->global->auth_session_info->unix_info->unix_name,
5963 session->global->auth_session_info->info->domain_name);
5966 /* No more aio - do the actual closes. */
5967 for (fsp = sconn->files; fsp; fsp = next) {
5971 if (fsp->file_pid != smb1req->smbpid) {
5974 if (fsp->vuid != smb1req->vuid) {
5977 if (!fsp->fsp_flags.closing) {
5982 * reply_exit() has the DO_CHDIR flag set.
5984 ok = chdir_current_service(fsp->conn);
5986 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5987 smb_request_done(smb1req);
5988 END_PROFILE(SMBexit);
5990 close_file(NULL, fsp, SHUTDOWN_CLOSE);
5993 reply_outbuf(smb1req, 0, 0);
5995 * The following call is needed to push the
5996 * reply data back out the socket after async
5997 * return. Plus it frees smb1req.
5999 smb_request_done(smb1req);
6000 DBG_INFO("reply_exit complete\n");
6001 END_PROFILE(SMBexit);
6005 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6007 static void reply_close_done(struct tevent_req *req);
6009 void reply_close(struct smb_request *smb1req)
6011 connection_struct *conn = smb1req->conn;
6012 NTSTATUS status = NT_STATUS_OK;
6013 files_struct *fsp = NULL;
6014 START_PROFILE(SMBclose);
6016 if (smb1req->wct < 3) {
6017 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
6018 END_PROFILE(SMBclose);
6022 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
6025 * We can only use check_fsp if we know it's not a directory.
6028 if (!check_fsp_open(conn, smb1req, fsp)) {
6029 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
6030 END_PROFILE(SMBclose);
6034 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6035 fsp->fsp_flags.is_directory ?
6036 "directory" : "file",
6037 fsp->fh->fd, fsp_fnum_dbg(fsp),
6038 conn->num_files_open);
6040 if (!fsp->fsp_flags.is_directory) {
6044 * Take care of any time sent in the close.
6047 t = srv_make_unix_date3(smb1req->vwv+1);
6048 set_close_write_time(fsp, time_t_to_full_timespec(t));
6051 if (fsp->num_aio_requests != 0) {
6052 struct tevent_req *req;
6054 req = reply_close_send(smb1req, fsp);
6056 status = NT_STATUS_NO_MEMORY;
6059 /* We're async. This will complete later. */
6060 tevent_req_set_callback(req, reply_close_done, smb1req);
6061 END_PROFILE(SMBclose);
6066 * close_file() returns the unix errno if an error was detected on
6067 * close - normally this is due to a disk full error. If not then it
6068 * was probably an I/O error.
6071 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6073 if (!NT_STATUS_IS_OK(status)) {
6074 reply_nterror(smb1req, status);
6075 END_PROFILE(SMBclose);
6079 reply_outbuf(smb1req, 0, 0);
6080 END_PROFILE(SMBclose);
6084 struct reply_close_state {
6086 struct tevent_queue *wait_queue;
6089 static void reply_close_wait_done(struct tevent_req *subreq);
6091 /****************************************************************************
6093 Note, on failure here we deallocate and return NULL to allow the caller to
6094 SMB1 return an error of ERRnomem immediately.
6095 ****************************************************************************/
6097 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6100 struct tevent_req *req;
6101 struct reply_close_state *state;
6102 struct tevent_req *subreq;
6103 struct smbd_server_connection *sconn = smb1req->sconn;
6105 req = tevent_req_create(smb1req, &state,
6106 struct reply_close_state);
6110 state->wait_queue = tevent_queue_create(state,
6111 "reply_close_wait_queue");
6112 if (tevent_req_nomem(state->wait_queue, req)) {
6118 * Flag the file as close in progress.
6119 * This will prevent any more IO being
6122 fsp->fsp_flags.closing = true;
6125 * Now wait until all aio requests on this fsp are
6128 * We don't set a callback, as we just want to block the
6129 * wait queue and the talloc_free() of fsp->aio_request
6130 * will remove the item from the wait queue.
6132 subreq = tevent_queue_wait_send(fsp->aio_requests,
6135 if (tevent_req_nomem(subreq, req)) {
6141 * Now we add our own waiter to the end of the queue,
6142 * this way we get notified when all pending requests are finished
6143 * and reply to the outstanding SMB1 request.
6145 subreq = tevent_queue_wait_send(state,
6148 if (tevent_req_nomem(subreq, req)) {
6154 * We're really going async - move the SMB1 request from
6155 * a talloc stackframe above us to the conn talloc-context.
6156 * We need this to stick around until the wait_done
6157 * callback is invoked.
6159 smb1req = talloc_move(sconn, &smb1req);
6161 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6166 static void reply_close_wait_done(struct tevent_req *subreq)
6168 struct tevent_req *req = tevent_req_callback_data(
6169 subreq, struct tevent_req);
6171 tevent_queue_wait_recv(subreq);
6172 TALLOC_FREE(subreq);
6173 tevent_req_done(req);
6176 static NTSTATUS reply_close_recv(struct tevent_req *req)
6178 return tevent_req_simple_recv_ntstatus(req);
6181 static void reply_close_done(struct tevent_req *req)
6183 struct smb_request *smb1req = tevent_req_callback_data(
6184 req, struct smb_request);
6185 struct reply_close_state *state = tevent_req_data(req,
6186 struct reply_close_state);
6189 status = reply_close_recv(req);
6191 if (!NT_STATUS_IS_OK(status)) {
6192 TALLOC_FREE(smb1req);
6193 exit_server(__location__ ": reply_close_recv failed");
6197 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6198 if (NT_STATUS_IS_OK(status)) {
6199 reply_outbuf(smb1req, 0, 0);
6201 reply_nterror(smb1req, status);
6204 * The following call is needed to push the
6205 * reply data back out the socket after async
6206 * return. Plus it frees smb1req.
6208 smb_request_done(smb1req);
6211 /****************************************************************************
6212 Reply to a writeclose (Core+ protocol).
6213 ****************************************************************************/
6215 void reply_writeclose(struct smb_request *req)
6217 connection_struct *conn = req->conn;
6220 ssize_t nwritten = -1;
6221 NTSTATUS close_status = NT_STATUS_OK;
6224 struct timespec mtime;
6226 struct lock_struct lock;
6228 START_PROFILE(SMBwriteclose);
6231 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6232 END_PROFILE(SMBwriteclose);
6236 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6238 if (!check_fsp(conn, req, fsp)) {
6239 END_PROFILE(SMBwriteclose);
6242 if (!CHECK_WRITE(fsp)) {
6243 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6244 END_PROFILE(SMBwriteclose);
6248 numtowrite = SVAL(req->vwv+1, 0);
6249 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6250 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6251 data = (const char *)req->buf + 1;
6254 * Ensure client isn't asking us to write more than
6255 * they sent. CVE-2017-12163.
6257 remaining = smbreq_bufrem(req, data);
6258 if (numtowrite > remaining) {
6259 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6260 END_PROFILE(SMBwriteclose);
6264 if (fsp->print_file == NULL) {
6265 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6266 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6269 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6270 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6271 END_PROFILE(SMBwriteclose);
6276 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6278 set_close_write_time(fsp, mtime);
6281 * More insanity. W2K only closes the file if writelen > 0.
6285 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6286 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6287 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6290 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6291 "file %s\n", fsp_str_dbg(fsp)));
6292 close_status = close_file(req, fsp, NORMAL_CLOSE);
6296 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6297 reply_nterror(req, NT_STATUS_DISK_FULL);
6301 if(!NT_STATUS_IS_OK(close_status)) {
6302 reply_nterror(req, close_status);
6306 reply_outbuf(req, 1, 0);
6308 SSVAL(req->outbuf,smb_vwv0,nwritten);
6312 END_PROFILE(SMBwriteclose);
6317 #define DBGC_CLASS DBGC_LOCKING
6319 /****************************************************************************
6321 ****************************************************************************/
6323 static void reply_lock_done(struct tevent_req *subreq);
6325 void reply_lock(struct smb_request *req)
6327 struct tevent_req *subreq = NULL;
6328 connection_struct *conn = req->conn;
6330 struct smbd_lock_element *lck = NULL;
6332 START_PROFILE(SMBlock);
6335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6336 END_PROFILE(SMBlock);
6340 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6342 if (!check_fsp(conn, req, fsp)) {
6343 END_PROFILE(SMBlock);
6347 lck = talloc(req, struct smbd_lock_element);
6349 reply_nterror(req, NT_STATUS_NO_MEMORY);
6350 END_PROFILE(SMBlock);
6354 *lck = (struct smbd_lock_element) {
6355 .req_guid = smbd_request_guid(req, 0),
6356 .smblctx = req->smbpid,
6357 .brltype = WRITE_LOCK,
6358 .count = IVAL(req->vwv+1, 0),
6359 .offset = IVAL(req->vwv+3, 0),
6362 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6368 subreq = smbd_smb1_do_locks_send(
6374 false, /* large_offset */
6378 if (subreq == NULL) {
6379 reply_nterror(req, NT_STATUS_NO_MEMORY);
6380 END_PROFILE(SMBlock);
6383 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6384 END_PROFILE(SMBlock);
6387 static void reply_lock_done(struct tevent_req *subreq)
6389 struct smb_request *req = NULL;
6393 START_PROFILE(SMBlock);
6395 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6398 status = smbd_smb1_do_locks_recv(subreq);
6399 TALLOC_FREE(subreq);
6401 if (NT_STATUS_IS_OK(status)) {
6402 reply_outbuf(req, 0, 0);
6404 reply_nterror(req, status);
6407 ok = srv_send_smb(req->xconn,
6408 (char *)req->outbuf,
6411 IS_CONN_ENCRYPTED(req->conn),
6414 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6417 END_PROFILE(SMBlock);
6420 /****************************************************************************
6422 ****************************************************************************/
6424 void reply_unlock(struct smb_request *req)
6426 connection_struct *conn = req->conn;
6429 struct smbd_lock_element lck;
6431 START_PROFILE(SMBunlock);
6434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6435 END_PROFILE(SMBunlock);
6439 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6441 if (!check_fsp(conn, req, fsp)) {
6442 END_PROFILE(SMBunlock);
6446 lck = (struct smbd_lock_element) {
6447 .req_guid = smbd_request_guid(req, 0),
6448 .smblctx = req->smbpid,
6449 .brltype = UNLOCK_LOCK,
6450 .offset = IVAL(req->vwv+3, 0),
6451 .count = IVAL(req->vwv+1, 0),
6454 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6456 if (!NT_STATUS_IS_OK(status)) {
6457 reply_nterror(req, status);
6458 END_PROFILE(SMBunlock);
6462 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6468 reply_outbuf(req, 0, 0);
6470 END_PROFILE(SMBunlock);
6475 #define DBGC_CLASS DBGC_ALL
6477 /****************************************************************************
6479 conn POINTER CAN BE NULL HERE !
6480 ****************************************************************************/
6482 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6483 static void reply_tdis_done(struct tevent_req *req);
6485 void reply_tdis(struct smb_request *smb1req)
6487 connection_struct *conn = smb1req->conn;
6488 struct tevent_req *req;
6491 * Don't setup the profile charge here, take
6492 * it in reply_tdis_done(). Not strictly correct
6493 * but better than the other SMB1 async
6494 * code that double-charges at the moment.
6498 /* Not going async, profile here. */
6499 START_PROFILE(SMBtdis);
6500 DBG_INFO("Invalid connection in tdis\n");
6501 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6502 END_PROFILE(SMBtdis);
6506 req = reply_tdis_send(smb1req);
6508 /* Not going async, profile here. */
6509 START_PROFILE(SMBtdis);
6510 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6511 END_PROFILE(SMBtdis);
6514 /* We're async. This will complete later. */
6515 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6519 struct reply_tdis_state {
6520 struct tevent_queue *wait_queue;
6523 static void reply_tdis_wait_done(struct tevent_req *subreq);
6525 /****************************************************************************
6527 Note, on failure here we deallocate and return NULL to allow the caller to
6528 SMB1 return an error of ERRnomem immediately.
6529 ****************************************************************************/
6531 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6533 struct tevent_req *req;
6534 struct reply_tdis_state *state;
6535 struct tevent_req *subreq;
6536 connection_struct *conn = smb1req->conn;
6539 req = tevent_req_create(smb1req, &state,
6540 struct reply_tdis_state);
6544 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6545 if (tevent_req_nomem(state->wait_queue, req)) {
6551 * Make sure that no new request will be able to use this tcon.
6552 * This ensures that once all outstanding fsp->aio_requests
6553 * on this tcon are done, we are safe to close it.
6555 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6557 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6558 if (fsp->conn != conn) {
6562 * Flag the file as close in progress.
6563 * This will prevent any more IO being
6564 * done on it. Not strictly needed, but
6565 * doesn't hurt to flag it as closing.
6567 fsp->fsp_flags.closing = true;
6569 if (fsp->num_aio_requests > 0) {
6571 * Now wait until all aio requests on this fsp are
6574 * We don't set a callback, as we just want to block the
6575 * wait queue and the talloc_free() of fsp->aio_request
6576 * will remove the item from the wait queue.
6578 subreq = tevent_queue_wait_send(fsp->aio_requests,
6579 conn->sconn->ev_ctx,
6581 if (tevent_req_nomem(subreq, req)) {
6589 * Now we add our own waiter to the end of the queue,
6590 * this way we get notified when all pending requests are finished
6591 * and reply to the outstanding SMB1 request.
6593 subreq = tevent_queue_wait_send(state,
6594 conn->sconn->ev_ctx,
6596 if (tevent_req_nomem(subreq, req)) {
6602 * We're really going async - move the SMB1 request from
6603 * a talloc stackframe above us to the sconn talloc-context.
6604 * We need this to stick around until the wait_done
6605 * callback is invoked.
6607 smb1req = talloc_move(smb1req->sconn, &smb1req);
6609 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6614 static void reply_tdis_wait_done(struct tevent_req *subreq)
6616 struct tevent_req *req = tevent_req_callback_data(
6617 subreq, struct tevent_req);
6619 tevent_queue_wait_recv(subreq);
6620 TALLOC_FREE(subreq);
6621 tevent_req_done(req);
6624 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6626 return tevent_req_simple_recv_ntstatus(req);
6629 static void reply_tdis_done(struct tevent_req *req)
6631 struct smb_request *smb1req = tevent_req_callback_data(
6632 req, struct smb_request);
6634 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6638 * Take the profile charge here. Not strictly
6639 * correct but better than the other SMB1 async
6640 * code that double-charges at the moment.
6642 START_PROFILE(SMBtdis);
6644 status = reply_tdis_recv(req);
6646 if (!NT_STATUS_IS_OK(status)) {
6647 TALLOC_FREE(smb1req);
6648 END_PROFILE(SMBtdis);
6649 exit_server(__location__ ": reply_tdis_recv failed");
6654 * As we've been awoken, we may have changed
6655 * directory in the meantime.
6656 * reply_tdis() has the DO_CHDIR flag set.
6658 ok = chdir_current_service(smb1req->conn);
6660 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6661 smb_request_done(smb1req);
6662 END_PROFILE(SMBtdis);
6665 status = smbXsrv_tcon_disconnect(tcon,
6667 if (!NT_STATUS_IS_OK(status)) {
6668 TALLOC_FREE(smb1req);
6669 END_PROFILE(SMBtdis);
6670 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6674 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6675 smb1req->conn = NULL;
6679 reply_outbuf(smb1req, 0, 0);
6681 * The following call is needed to push the
6682 * reply data back out the socket after async
6683 * return. Plus it frees smb1req.
6685 smb_request_done(smb1req);
6686 END_PROFILE(SMBtdis);
6689 /****************************************************************************
6691 conn POINTER CAN BE NULL HERE !
6692 ****************************************************************************/
6694 void reply_echo(struct smb_request *req)
6696 connection_struct *conn = req->conn;
6697 struct smb_perfcount_data local_pcd;
6698 struct smb_perfcount_data *cur_pcd;
6702 START_PROFILE(SMBecho);
6704 smb_init_perfcount_data(&local_pcd);
6707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6708 END_PROFILE(SMBecho);
6712 smb_reverb = SVAL(req->vwv+0, 0);
6714 reply_outbuf(req, 1, req->buflen);
6716 /* copy any incoming data back out */
6717 if (req->buflen > 0) {
6718 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6721 if (smb_reverb > 100) {
6722 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6726 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6728 /* this makes sure we catch the request pcd */
6729 if (seq_num == smb_reverb) {
6730 cur_pcd = &req->pcd;
6732 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6733 cur_pcd = &local_pcd;
6736 SSVAL(req->outbuf,smb_vwv0,seq_num);
6738 show_msg((char *)req->outbuf);
6739 if (!srv_send_smb(req->xconn,
6740 (char *)req->outbuf,
6741 true, req->seqnum+1,
6742 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6744 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6747 DEBUG(3,("echo %d times\n", smb_reverb));
6749 TALLOC_FREE(req->outbuf);
6751 END_PROFILE(SMBecho);
6755 /****************************************************************************
6756 Reply to a printopen.
6757 ****************************************************************************/
6759 void reply_printopen(struct smb_request *req)
6761 connection_struct *conn = req->conn;
6765 START_PROFILE(SMBsplopen);
6768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6769 END_PROFILE(SMBsplopen);
6773 if (!CAN_PRINT(conn)) {
6774 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6775 END_PROFILE(SMBsplopen);
6779 status = file_new(req, conn, &fsp);
6780 if(!NT_STATUS_IS_OK(status)) {
6781 reply_nterror(req, status);
6782 END_PROFILE(SMBsplopen);
6786 /* Open for exclusive use, write only. */
6787 status = print_spool_open(fsp, NULL, req->vuid);
6789 if (!NT_STATUS_IS_OK(status)) {
6790 file_free(req, fsp);
6791 reply_nterror(req, status);
6792 END_PROFILE(SMBsplopen);
6796 reply_outbuf(req, 1, 0);
6797 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6799 DEBUG(3,("openprint fd=%d %s\n",
6800 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6802 END_PROFILE(SMBsplopen);
6806 /****************************************************************************
6807 Reply to a printclose.
6808 ****************************************************************************/
6810 void reply_printclose(struct smb_request *req)
6812 connection_struct *conn = req->conn;
6816 START_PROFILE(SMBsplclose);
6819 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6820 END_PROFILE(SMBsplclose);
6824 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6826 if (!check_fsp(conn, req, fsp)) {
6827 END_PROFILE(SMBsplclose);
6831 if (!CAN_PRINT(conn)) {
6832 reply_force_doserror(req, ERRSRV, ERRerror);
6833 END_PROFILE(SMBsplclose);
6837 DEBUG(3,("printclose fd=%d %s\n",
6838 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6840 status = close_file(req, fsp, NORMAL_CLOSE);
6842 if(!NT_STATUS_IS_OK(status)) {
6843 reply_nterror(req, status);
6844 END_PROFILE(SMBsplclose);
6848 reply_outbuf(req, 0, 0);
6850 END_PROFILE(SMBsplclose);
6854 /****************************************************************************
6855 Reply to a printqueue.
6856 ****************************************************************************/
6858 void reply_printqueue(struct smb_request *req)
6860 const struct loadparm_substitution *lp_sub =
6861 loadparm_s3_global_substitution();
6862 connection_struct *conn = req->conn;
6866 START_PROFILE(SMBsplretq);
6869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6870 END_PROFILE(SMBsplretq);
6874 max_count = SVAL(req->vwv+0, 0);
6875 start_index = SVAL(req->vwv+1, 0);
6877 /* we used to allow the client to get the cnum wrong, but that
6878 is really quite gross and only worked when there was only
6879 one printer - I think we should now only accept it if they
6880 get it right (tridge) */
6881 if (!CAN_PRINT(conn)) {
6882 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6883 END_PROFILE(SMBsplretq);
6887 reply_outbuf(req, 2, 3);
6888 SSVAL(req->outbuf,smb_vwv0,0);
6889 SSVAL(req->outbuf,smb_vwv1,0);
6890 SCVAL(smb_buf(req->outbuf),0,1);
6891 SSVAL(smb_buf(req->outbuf),1,0);
6893 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6894 start_index, max_count));
6897 TALLOC_CTX *mem_ctx = talloc_tos();
6900 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6901 struct rpc_pipe_client *cli = NULL;
6902 struct dcerpc_binding_handle *b = NULL;
6903 struct policy_handle handle;
6904 struct spoolss_DevmodeContainer devmode_ctr;
6905 union spoolss_JobInfo *info;
6907 uint32_t num_to_get;
6911 ZERO_STRUCT(handle);
6913 status = rpc_pipe_open_interface(mem_ctx,
6916 conn->sconn->remote_address,
6917 conn->sconn->local_address,
6918 conn->sconn->msg_ctx,
6920 if (!NT_STATUS_IS_OK(status)) {
6921 DEBUG(0, ("reply_printqueue: "
6922 "could not connect to spoolss: %s\n",
6923 nt_errstr(status)));
6924 reply_nterror(req, status);
6927 b = cli->binding_handle;
6929 ZERO_STRUCT(devmode_ctr);
6931 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6934 SEC_FLAG_MAXIMUM_ALLOWED,
6937 if (!NT_STATUS_IS_OK(status)) {
6938 reply_nterror(req, status);
6941 if (!W_ERROR_IS_OK(werr)) {
6942 reply_nterror(req, werror_to_ntstatus(werr));
6946 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6954 if (!W_ERROR_IS_OK(werr)) {
6955 reply_nterror(req, werror_to_ntstatus(werr));
6959 if (max_count > 0) {
6960 first = start_index;
6962 first = start_index + max_count + 1;
6965 if (first >= count) {
6968 num_to_get = first + MIN(ABS(max_count), count - first);
6971 for (i = first; i < num_to_get; i++) {
6974 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6977 uint16_t qrapjobid = pjobid_to_rap(sharename,
6978 info[i].info2.job_id);
6980 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6986 srv_put_dos_date2(p, 0, qtime);
6987 SCVAL(p, 4, qstatus);
6988 SSVAL(p, 5, qrapjobid);
6989 SIVAL(p, 7, info[i].info2.size);
6991 status = srvstr_push(blob, req->flags2, p+12,
6992 info[i].info2.notify_name, 16, STR_ASCII, &len);
6993 if (!NT_STATUS_IS_OK(status)) {
6994 reply_nterror(req, status);
6997 if (message_push_blob(
7000 blob, sizeof(blob))) == -1) {
7001 reply_nterror(req, NT_STATUS_NO_MEMORY);
7007 SSVAL(req->outbuf,smb_vwv0,count);
7008 SSVAL(req->outbuf,smb_vwv1,
7009 (max_count>0?first+count:first-1));
7010 SCVAL(smb_buf(req->outbuf),0,1);
7011 SSVAL(smb_buf(req->outbuf),1,28*count);
7015 DEBUG(3, ("%u entries returned in queue\n",
7019 if (b && is_valid_policy_hnd(&handle)) {
7020 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
7025 END_PROFILE(SMBsplretq);
7029 /****************************************************************************
7030 Reply to a printwrite.
7031 ****************************************************************************/
7033 void reply_printwrite(struct smb_request *req)
7035 connection_struct *conn = req->conn;
7040 START_PROFILE(SMBsplwr);
7043 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7044 END_PROFILE(SMBsplwr);
7048 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7050 if (!check_fsp(conn, req, fsp)) {
7051 END_PROFILE(SMBsplwr);
7055 if (!fsp->print_file) {
7056 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7057 END_PROFILE(SMBsplwr);
7061 if (!CHECK_WRITE(fsp)) {
7062 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7063 END_PROFILE(SMBsplwr);
7067 numtowrite = SVAL(req->buf, 1);
7070 * This already protects us against CVE-2017-12163.
7072 if (req->buflen < numtowrite + 3) {
7073 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7074 END_PROFILE(SMBsplwr);
7078 data = (const char *)req->buf + 3;
7080 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7081 reply_nterror(req, map_nt_error_from_unix(errno));
7082 END_PROFILE(SMBsplwr);
7086 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7088 END_PROFILE(SMBsplwr);
7092 /****************************************************************************
7094 ****************************************************************************/
7096 void reply_mkdir(struct smb_request *req)
7098 connection_struct *conn = req->conn;
7099 struct smb_filename *smb_dname = NULL;
7100 char *directory = NULL;
7103 TALLOC_CTX *ctx = talloc_tos();
7105 START_PROFILE(SMBmkdir);
7107 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7108 STR_TERMINATE, &status);
7109 if (!NT_STATUS_IS_OK(status)) {
7110 reply_nterror(req, status);
7114 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7115 status = filename_convert(ctx, conn,
7121 if (!NT_STATUS_IS_OK(status)) {
7122 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7123 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7124 ERRSRV, ERRbadpath);
7127 reply_nterror(req, status);
7131 status = create_directory(conn, req, smb_dname);
7133 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7135 if (!NT_STATUS_IS_OK(status)) {
7137 if (!use_nt_status()
7138 && NT_STATUS_EQUAL(status,
7139 NT_STATUS_OBJECT_NAME_COLLISION)) {
7141 * Yes, in the DOS error code case we get a
7142 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7143 * samba4 torture test.
7145 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7148 reply_nterror(req, status);
7152 reply_outbuf(req, 0, 0);
7154 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7156 TALLOC_FREE(smb_dname);
7157 END_PROFILE(SMBmkdir);
7161 /****************************************************************************
7163 ****************************************************************************/
7165 void reply_rmdir(struct smb_request *req)
7167 connection_struct *conn = req->conn;
7168 struct smb_filename *smb_dname = NULL;
7169 char *directory = NULL;
7171 TALLOC_CTX *ctx = talloc_tos();
7172 files_struct *fsp = NULL;
7174 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7176 START_PROFILE(SMBrmdir);
7178 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7179 STR_TERMINATE, &status);
7180 if (!NT_STATUS_IS_OK(status)) {
7181 reply_nterror(req, status);
7185 status = filename_convert(ctx, conn,
7191 if (!NT_STATUS_IS_OK(status)) {
7192 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7193 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7194 ERRSRV, ERRbadpath);
7197 reply_nterror(req, status);
7201 if (is_ntfs_stream_smb_fname(smb_dname)) {
7202 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7206 status = SMB_VFS_CREATE_FILE(
7209 0, /* root_dir_fid */
7210 smb_dname, /* fname */
7211 DELETE_ACCESS, /* access_mask */
7212 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7214 FILE_OPEN, /* create_disposition*/
7215 FILE_DIRECTORY_FILE, /* create_options */
7216 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7217 0, /* oplock_request */
7219 0, /* allocation_size */
7220 0, /* private_flags */
7225 NULL, NULL); /* create context */
7227 if (!NT_STATUS_IS_OK(status)) {
7228 if (open_was_deferred(req->xconn, req->mid)) {
7229 /* We have re-scheduled this call. */
7232 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7233 bool ok = defer_smb1_sharing_violation(req);
7238 reply_nterror(req, status);
7242 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7243 if (!NT_STATUS_IS_OK(status)) {
7244 close_file(req, fsp, ERROR_CLOSE);
7245 reply_nterror(req, status);
7249 if (!set_delete_on_close(fsp, true,
7250 conn->session_info->security_token,
7251 conn->session_info->unix_token)) {
7252 close_file(req, fsp, ERROR_CLOSE);
7253 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7257 status = close_file(req, fsp, NORMAL_CLOSE);
7258 if (!NT_STATUS_IS_OK(status)) {
7259 reply_nterror(req, status);
7261 reply_outbuf(req, 0, 0);
7264 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7266 TALLOC_FREE(smb_dname);
7267 END_PROFILE(SMBrmdir);
7271 /*******************************************************************
7272 Resolve wildcards in a filename rename.
7273 ********************************************************************/
7275 static bool resolve_wildcards(TALLOC_CTX *ctx,
7280 char *name2_copy = NULL;
7285 char *p,*p2, *pname1, *pname2;
7287 name2_copy = talloc_strdup(ctx, name2);
7292 pname1 = strrchr_m(name1,'/');
7293 pname2 = strrchr_m(name2_copy,'/');
7295 if (!pname1 || !pname2) {
7299 /* Truncate the copy of name2 at the last '/' */
7302 /* Now go past the '/' */
7306 root1 = talloc_strdup(ctx, pname1);
7307 root2 = talloc_strdup(ctx, pname2);
7309 if (!root1 || !root2) {
7313 p = strrchr_m(root1,'.');
7316 ext1 = talloc_strdup(ctx, p+1);
7318 ext1 = talloc_strdup(ctx, "");
7320 p = strrchr_m(root2,'.');
7323 ext2 = talloc_strdup(ctx, p+1);
7325 ext2 = talloc_strdup(ctx, "");
7328 if (!ext1 || !ext2) {
7336 /* Hmmm. Should this be mb-aware ? */
7339 } else if (*p2 == '*') {
7341 root2 = talloc_asprintf(ctx, "%s%s",
7360 /* Hmmm. Should this be mb-aware ? */
7363 } else if (*p2 == '*') {
7365 ext2 = talloc_asprintf(ctx, "%s%s",
7381 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7386 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7398 /****************************************************************************
7399 Ensure open files have their names updated. Updated to notify other smbd's
7401 ****************************************************************************/
7403 static void rename_open_files(connection_struct *conn,
7404 struct share_mode_lock *lck,
7406 uint32_t orig_name_hash,
7407 const struct smb_filename *smb_fname_dst)
7410 bool did_rename = False;
7412 uint32_t new_name_hash = 0;
7414 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7415 fsp = file_find_di_next(fsp)) {
7416 struct file_id_buf idbuf;
7417 /* fsp_name is a relative path under the fsp. To change this for other
7418 sharepaths we need to manipulate relative paths. */
7419 /* TODO - create the absolute path and manipulate the newname
7420 relative to the sharepath. */
7421 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7424 if (fsp->name_hash != orig_name_hash) {
7427 DBG_DEBUG("renaming file %s "
7428 "(file_id %s) from %s -> %s\n",
7430 file_id_str_buf(fsp->file_id, &idbuf),
7432 smb_fname_str_dbg(smb_fname_dst));
7434 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7435 if (NT_STATUS_IS_OK(status)) {
7437 new_name_hash = fsp->name_hash;
7442 struct file_id_buf idbuf;
7443 DBG_DEBUG("no open files on file_id %s "
7445 file_id_str_buf(id, &idbuf),
7446 smb_fname_str_dbg(smb_fname_dst));
7449 /* Send messages to all smbd's (not ourself) that the name has changed. */
7450 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7451 orig_name_hash, new_name_hash,
7456 /****************************************************************************
7457 We need to check if the source path is a parent directory of the destination
7458 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7459 refuse the rename with a sharing violation. Under UNIX the above call can
7460 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7461 probably need to check that the client is a Windows one before disallowing
7462 this as a UNIX client (one with UNIX extensions) can know the source is a
7463 symlink and make this decision intelligently. Found by an excellent bug
7464 report from <AndyLiebman@aol.com>.
7465 ****************************************************************************/
7467 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7468 const struct smb_filename *smb_fname_dst)
7470 const char *psrc = smb_fname_src->base_name;
7471 const char *pdst = smb_fname_dst->base_name;
7474 if (psrc[0] == '.' && psrc[1] == '/') {
7477 if (pdst[0] == '.' && pdst[1] == '/') {
7480 if ((slen = strlen(psrc)) > strlen(pdst)) {
7483 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7487 * Do the notify calls from a rename
7490 static void notify_rename(connection_struct *conn, bool is_dir,
7491 const struct smb_filename *smb_fname_src,
7492 const struct smb_filename *smb_fname_dst)
7494 char *parent_dir_src = NULL;
7495 char *parent_dir_dst = NULL;
7498 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7499 : FILE_NOTIFY_CHANGE_FILE_NAME;
7501 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7502 &parent_dir_src, NULL) ||
7503 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7504 &parent_dir_dst, NULL)) {
7508 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7509 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7510 smb_fname_src->base_name);
7511 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7512 smb_fname_dst->base_name);
7515 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7516 smb_fname_src->base_name);
7517 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7518 smb_fname_dst->base_name);
7521 /* this is a strange one. w2k3 gives an additional event for
7522 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7523 files, but not directories */
7525 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7526 FILE_NOTIFY_CHANGE_ATTRIBUTES
7527 |FILE_NOTIFY_CHANGE_CREATION,
7528 smb_fname_dst->base_name);
7531 TALLOC_FREE(parent_dir_src);
7532 TALLOC_FREE(parent_dir_dst);
7535 /****************************************************************************
7536 Returns an error if the parent directory for a filename is open in an
7538 ****************************************************************************/
7540 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7541 const struct smb_filename *smb_fname_dst_in)
7543 struct smb_filename *smb_fname_parent = NULL;
7545 files_struct *fsp = NULL;
7549 ok = parent_smb_fname(talloc_tos(),
7554 return NT_STATUS_NO_MEMORY;
7557 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7559 return map_nt_error_from_unix(errno);
7563 * We're only checking on this smbd here, mostly good
7564 * enough.. and will pass tests.
7567 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7568 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7569 fsp = file_find_di_next(fsp)) {
7570 if (fsp->access_mask & DELETE_ACCESS) {
7571 return NT_STATUS_SHARING_VIOLATION;
7574 return NT_STATUS_OK;
7577 /****************************************************************************
7578 Rename an open file - given an fsp.
7579 ****************************************************************************/
7581 NTSTATUS rename_internals_fsp(connection_struct *conn,
7583 const struct smb_filename *smb_fname_dst_in,
7584 const char *dst_original_lcomp,
7586 bool replace_if_exists)
7588 TALLOC_CTX *ctx = talloc_tos();
7589 struct smb_filename *smb_fname_dst = NULL;
7590 NTSTATUS status = NT_STATUS_OK;
7591 struct share_mode_lock *lck = NULL;
7592 uint32_t access_mask = SEC_DIR_ADD_FILE;
7593 bool dst_exists, old_is_stream, new_is_stream;
7596 status = check_name(conn, smb_fname_dst_in);
7597 if (!NT_STATUS_IS_OK(status)) {
7601 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7602 if (!NT_STATUS_IS_OK(status)) {
7606 if (file_has_open_streams(fsp)) {
7607 return NT_STATUS_ACCESS_DENIED;
7610 /* Make a copy of the dst smb_fname structs */
7612 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7613 if (smb_fname_dst == NULL) {
7614 status = NT_STATUS_NO_MEMORY;
7619 * Check for special case with case preserving and not
7620 * case sensitive. If the new last component differs from the original
7621 * last component only by case, then we should allow
7622 * the rename (user is trying to change the case of the
7625 if (!conn->case_sensitive && conn->case_preserve &&
7626 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7627 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7628 char *fname_dst_parent = NULL;
7629 const char *fname_dst_lcomp = NULL;
7630 char *orig_lcomp_path = NULL;
7631 char *orig_lcomp_stream = NULL;
7635 * Split off the last component of the processed
7636 * destination name. We will compare this to
7637 * the split components of dst_original_lcomp.
7639 if (!parent_dirname(ctx,
7640 smb_fname_dst->base_name,
7642 &fname_dst_lcomp)) {
7643 status = NT_STATUS_NO_MEMORY;
7648 * The dst_original_lcomp component contains
7649 * the last_component of the path + stream
7650 * name (if a stream exists).
7652 * Split off the stream name so we
7653 * can check them separately.
7656 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7657 /* POSIX - no stream component. */
7658 orig_lcomp_path = talloc_strdup(ctx,
7659 dst_original_lcomp);
7660 if (orig_lcomp_path == NULL) {
7664 ok = split_stream_filename(ctx,
7667 &orig_lcomp_stream);
7671 TALLOC_FREE(fname_dst_parent);
7672 status = NT_STATUS_NO_MEMORY;
7676 /* If the base names only differ by case, use original. */
7677 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7680 * Replace the modified last component with the
7683 if (!ISDOT(fname_dst_parent)) {
7684 tmp = talloc_asprintf(smb_fname_dst,
7689 tmp = talloc_strdup(smb_fname_dst,
7693 status = NT_STATUS_NO_MEMORY;
7694 TALLOC_FREE(fname_dst_parent);
7695 TALLOC_FREE(orig_lcomp_path);
7696 TALLOC_FREE(orig_lcomp_stream);
7699 TALLOC_FREE(smb_fname_dst->base_name);
7700 smb_fname_dst->base_name = tmp;
7703 /* If the stream_names only differ by case, use original. */
7704 if(!strcsequal(smb_fname_dst->stream_name,
7705 orig_lcomp_stream)) {
7706 /* Use the original stream. */
7707 char *tmp = talloc_strdup(smb_fname_dst,
7710 status = NT_STATUS_NO_MEMORY;
7711 TALLOC_FREE(fname_dst_parent);
7712 TALLOC_FREE(orig_lcomp_path);
7713 TALLOC_FREE(orig_lcomp_stream);
7716 TALLOC_FREE(smb_fname_dst->stream_name);
7717 smb_fname_dst->stream_name = tmp;
7719 TALLOC_FREE(fname_dst_parent);
7720 TALLOC_FREE(orig_lcomp_path);
7721 TALLOC_FREE(orig_lcomp_stream);
7725 * If the src and dest names are identical - including case,
7726 * don't do the rename, just return success.
7729 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7730 strcsequal(fsp->fsp_name->stream_name,
7731 smb_fname_dst->stream_name)) {
7732 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7733 "- returning success\n",
7734 smb_fname_str_dbg(smb_fname_dst)));
7735 status = NT_STATUS_OK;
7739 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7740 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7742 /* Return the correct error code if both names aren't streams. */
7743 if (!old_is_stream && new_is_stream) {
7744 status = NT_STATUS_OBJECT_NAME_INVALID;
7748 if (old_is_stream && !new_is_stream) {
7749 status = NT_STATUS_INVALID_PARAMETER;
7753 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7755 if(!replace_if_exists && dst_exists) {
7756 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7757 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7758 smb_fname_str_dbg(smb_fname_dst)));
7759 status = NT_STATUS_OBJECT_NAME_COLLISION;
7764 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7765 &smb_fname_dst->st);
7766 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7768 /* The file can be open when renaming a stream */
7769 if (dst_fsp && !new_is_stream) {
7770 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7771 status = NT_STATUS_ACCESS_DENIED;
7776 /* Ensure we have a valid stat struct for the source. */
7777 status = vfs_stat_fsp(fsp);
7778 if (!NT_STATUS_IS_OK(status)) {
7782 status = can_rename(conn, fsp, attrs);
7784 if (!NT_STATUS_IS_OK(status)) {
7785 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7786 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7787 smb_fname_str_dbg(smb_fname_dst)));
7788 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7789 status = NT_STATUS_ACCESS_DENIED;
7793 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7794 status = NT_STATUS_ACCESS_DENIED;
7798 /* Do we have rights to move into the destination ? */
7799 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7800 /* We're moving a directory. */
7801 access_mask = SEC_DIR_ADD_SUBDIR;
7803 status = check_parent_access(conn,
7806 if (!NT_STATUS_IS_OK(status)) {
7807 DBG_INFO("check_parent_access on "
7808 "dst %s returned %s\n",
7809 smb_fname_str_dbg(smb_fname_dst),
7814 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7817 * We have the file open ourselves, so not being able to get the
7818 * corresponding share mode lock is a fatal error.
7821 SMB_ASSERT(lck != NULL);
7823 ret = SMB_VFS_RENAMEAT(conn,
7829 uint32_t create_options = fsp->fh->private_options;
7831 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7832 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7833 smb_fname_str_dbg(smb_fname_dst)));
7835 if (!fsp->fsp_flags.is_directory &&
7836 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7837 (lp_map_archive(SNUM(conn)) ||
7838 lp_store_dos_attributes(SNUM(conn)))) {
7839 /* We must set the archive bit on the newly
7841 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7842 uint32_t old_dosmode = dos_mode(conn,
7844 file_set_dosmode(conn,
7846 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7853 fsp->fsp_flags.is_directory,
7857 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7861 * A rename acts as a new file create w.r.t. allowing an initial delete
7862 * on close, probably because in Windows there is a new handle to the
7863 * new file. If initial delete on close was requested but not
7864 * originally set, we need to set it here. This is probably not 100% correct,
7865 * but will work for the CIFSFS client which in non-posix mode
7866 * depends on these semantics. JRA.
7869 if (create_options & FILE_DELETE_ON_CLOSE) {
7870 status = can_set_delete_on_close(fsp, 0);
7872 if (NT_STATUS_IS_OK(status)) {
7873 /* Note that here we set the *initial* delete on close flag,
7874 * not the regular one. The magic gets handled in close. */
7875 fsp->fsp_flags.initial_delete_on_close = true;
7879 status = NT_STATUS_OK;
7885 if (errno == ENOTDIR || errno == EISDIR) {
7886 status = NT_STATUS_OBJECT_NAME_COLLISION;
7888 status = map_nt_error_from_unix(errno);
7891 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7892 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7893 smb_fname_str_dbg(smb_fname_dst)));
7896 TALLOC_FREE(smb_fname_dst);
7901 /****************************************************************************
7902 The guts of the rename command, split out so it may be called by the NT SMB
7904 ****************************************************************************/
7906 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7907 connection_struct *conn,
7908 struct smb_request *req,
7909 struct smb_filename *smb_fname_src,
7910 struct smb_filename *smb_fname_dst,
7911 const char *dst_original_lcomp,
7913 bool replace_if_exists,
7916 uint32_t access_mask)
7918 char *fname_src_dir = NULL;
7919 struct smb_filename *smb_fname_src_dir = NULL;
7920 char *fname_src_mask = NULL;
7922 NTSTATUS status = NT_STATUS_OK;
7923 struct smb_Dir *dir_hnd = NULL;
7924 const char *dname = NULL;
7925 char *talloced = NULL;
7927 int create_options = 0;
7928 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7929 struct smb2_create_blobs *posx = NULL;
7933 * Split the old name into directory and last component
7934 * strings. Note that unix_convert may have stripped off a
7935 * leading ./ from both name and newname if the rename is
7936 * at the root of the share. We need to make sure either both
7937 * name and newname contain a / character or neither of them do
7938 * as this is checked in resolve_wildcards().
7941 /* Split up the directory from the filename/mask. */
7942 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7943 &fname_src_dir, &fname_src_mask);
7944 if (!NT_STATUS_IS_OK(status)) {
7945 status = NT_STATUS_NO_MEMORY;
7950 * We should only check the mangled cache
7951 * here if unix_convert failed. This means
7952 * that the path in 'mask' doesn't exist
7953 * on the file system and so we need to look
7954 * for a possible mangle. This patch from
7955 * Tine Smukavec <valentin.smukavec@hermes.si>.
7958 if (!VALID_STAT(smb_fname_src->st) &&
7959 mangle_is_mangled(fname_src_mask, conn->params)) {
7960 char *new_mask = NULL;
7961 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7964 TALLOC_FREE(fname_src_mask);
7965 fname_src_mask = new_mask;
7969 if (posix_pathnames) {
7970 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7971 if (!NT_STATUS_IS_OK(status)) {
7972 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7978 if (!src_has_wild) {
7982 * Only one file needs to be renamed. Append the mask back
7983 * onto the directory.
7985 TALLOC_FREE(smb_fname_src->base_name);
7986 if (ISDOT(fname_src_dir)) {
7987 /* Ensure we use canonical names on open. */
7988 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7992 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7997 if (!smb_fname_src->base_name) {
7998 status = NT_STATUS_NO_MEMORY;
8002 DEBUG(3, ("rename_internals: case_sensitive = %d, "
8003 "case_preserve = %d, short case preserve = %d, "
8004 "directory = %s, newname = %s, "
8005 "last_component_dest = %s\n",
8006 conn->case_sensitive, conn->case_preserve,
8007 conn->short_case_preserve,
8008 smb_fname_str_dbg(smb_fname_src),
8009 smb_fname_str_dbg(smb_fname_dst),
8010 dst_original_lcomp));
8012 /* The dest name still may have wildcards. */
8013 if (dest_has_wild) {
8014 char *fname_dst_mod = NULL;
8015 if (!resolve_wildcards(smb_fname_dst,
8016 smb_fname_src->base_name,
8017 smb_fname_dst->base_name,
8019 DEBUG(6, ("rename_internals: resolve_wildcards "
8021 smb_fname_src->base_name,
8022 smb_fname_dst->base_name));
8023 status = NT_STATUS_NO_MEMORY;
8026 TALLOC_FREE(smb_fname_dst->base_name);
8027 smb_fname_dst->base_name = fname_dst_mod;
8030 ZERO_STRUCT(smb_fname_src->st);
8031 if (posix_pathnames) {
8032 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8034 rc = SMB_VFS_STAT(conn, smb_fname_src);
8037 status = map_nt_error_from_unix_common(errno);
8041 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8042 create_options |= FILE_DIRECTORY_FILE;
8045 status = SMB_VFS_CREATE_FILE(
8048 0, /* root_dir_fid */
8049 smb_fname_src, /* fname */
8050 access_mask, /* access_mask */
8051 (FILE_SHARE_READ | /* share_access */
8053 FILE_OPEN, /* create_disposition*/
8054 create_options, /* create_options */
8055 0, /* file_attributes */
8056 0, /* oplock_request */
8058 0, /* allocation_size */
8059 0, /* private_flags */
8064 posx, /* in_context_blobs */
8065 NULL); /* out_context_blobs */
8067 if (!NT_STATUS_IS_OK(status)) {
8068 DEBUG(3, ("Could not open rename source %s: %s\n",
8069 smb_fname_str_dbg(smb_fname_src),
8070 nt_errstr(status)));
8074 status = rename_internals_fsp(conn,
8081 close_file(req, fsp, NORMAL_CLOSE);
8083 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8084 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8085 smb_fname_str_dbg(smb_fname_dst)));
8091 * Wildcards - process each file that matches.
8093 if (strequal(fname_src_mask, "????????.???")) {
8094 TALLOC_FREE(fname_src_mask);
8095 fname_src_mask = talloc_strdup(ctx, "*");
8096 if (!fname_src_mask) {
8097 status = NT_STATUS_NO_MEMORY;
8102 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8106 smb_fname_src->flags);
8107 if (smb_fname_src_dir == NULL) {
8108 status = NT_STATUS_NO_MEMORY;
8112 status = check_name(conn, smb_fname_src_dir);
8113 if (!NT_STATUS_IS_OK(status)) {
8117 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8119 if (dir_hnd == NULL) {
8120 status = map_nt_error_from_unix(errno);
8124 status = NT_STATUS_NO_SUCH_FILE;
8126 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8127 * - gentest fix. JRA
8130 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8132 files_struct *fsp = NULL;
8133 char *destname = NULL;
8134 bool sysdir_entry = False;
8136 /* Quick check for "." and ".." */
8137 if (ISDOT(dname) || ISDOTDOT(dname)) {
8138 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8139 sysdir_entry = True;
8141 TALLOC_FREE(talloced);
8146 if (!is_visible_file(conn, smb_fname_src_dir, dname,
8147 &smb_fname_src->st, false)) {
8148 TALLOC_FREE(talloced);
8152 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8153 TALLOC_FREE(talloced);
8158 status = NT_STATUS_OBJECT_NAME_INVALID;
8162 TALLOC_FREE(smb_fname_src->base_name);
8163 if (ISDOT(fname_src_dir)) {
8164 /* Ensure we use canonical names on open. */
8165 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8169 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8174 if (!smb_fname_src->base_name) {
8175 status = NT_STATUS_NO_MEMORY;
8179 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8180 smb_fname_dst->base_name,
8182 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8183 smb_fname_src->base_name, destname));
8184 TALLOC_FREE(talloced);
8188 status = NT_STATUS_NO_MEMORY;
8192 TALLOC_FREE(smb_fname_dst->base_name);
8193 smb_fname_dst->base_name = destname;
8195 ZERO_STRUCT(smb_fname_src->st);
8196 if (posix_pathnames) {
8197 SMB_VFS_LSTAT(conn, smb_fname_src);
8199 SMB_VFS_STAT(conn, smb_fname_src);
8204 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8205 create_options |= FILE_DIRECTORY_FILE;
8208 status = SMB_VFS_CREATE_FILE(
8211 0, /* root_dir_fid */
8212 smb_fname_src, /* fname */
8213 access_mask, /* access_mask */
8214 (FILE_SHARE_READ | /* share_access */
8216 FILE_OPEN, /* create_disposition*/
8217 create_options, /* create_options */
8218 0, /* file_attributes */
8219 0, /* oplock_request */
8221 0, /* allocation_size */
8222 0, /* private_flags */
8227 posx, /* in_context_blobs */
8228 NULL); /* out_context_blobs */
8230 if (!NT_STATUS_IS_OK(status)) {
8231 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8232 "returned %s rename %s -> %s\n",
8234 smb_fname_str_dbg(smb_fname_src),
8235 smb_fname_str_dbg(smb_fname_dst)));
8239 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8240 if (dst_original_lcomp == NULL) {
8241 status = NT_STATUS_NO_MEMORY;
8245 status = rename_internals_fsp(conn,
8252 close_file(req, fsp, NORMAL_CLOSE);
8254 if (!NT_STATUS_IS_OK(status)) {
8255 DEBUG(3, ("rename_internals_fsp returned %s for "
8256 "rename %s -> %s\n", nt_errstr(status),
8257 smb_fname_str_dbg(smb_fname_src),
8258 smb_fname_str_dbg(smb_fname_dst)));
8264 DEBUG(3,("rename_internals: doing rename on %s -> "
8265 "%s\n", smb_fname_str_dbg(smb_fname_src),
8266 smb_fname_str_dbg(smb_fname_src)));
8267 TALLOC_FREE(talloced);
8269 TALLOC_FREE(dir_hnd);
8271 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8272 status = map_nt_error_from_unix(errno);
8277 TALLOC_FREE(talloced);
8278 TALLOC_FREE(smb_fname_src_dir);
8279 TALLOC_FREE(fname_src_dir);
8280 TALLOC_FREE(fname_src_mask);
8284 /****************************************************************************
8286 ****************************************************************************/
8288 void reply_mv(struct smb_request *req)
8290 connection_struct *conn = req->conn;
8292 char *newname = NULL;
8296 bool src_has_wcard = False;
8297 bool dest_has_wcard = False;
8298 TALLOC_CTX *ctx = talloc_tos();
8299 struct smb_filename *smb_fname_src = NULL;
8300 struct smb_filename *smb_fname_dst = NULL;
8301 const char *dst_original_lcomp = NULL;
8302 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8303 (req->posix_pathnames ?
8304 UCF_UNIX_NAME_LOOKUP :
8305 UCF_COND_ALLOW_WCARD_LCOMP);
8306 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8307 (req->posix_pathnames ?
8309 UCF_COND_ALLOW_WCARD_LCOMP);
8310 bool stream_rename = false;
8312 START_PROFILE(SMBmv);
8315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8319 attrs = SVAL(req->vwv+0, 0);
8321 p = (const char *)req->buf + 1;
8322 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
8323 &status, &src_has_wcard);
8324 if (!NT_STATUS_IS_OK(status)) {
8325 reply_nterror(req, status);
8329 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
8330 &status, &dest_has_wcard);
8331 if (!NT_STATUS_IS_OK(status)) {
8332 reply_nterror(req, status);
8336 if (!req->posix_pathnames) {
8337 /* The newname must begin with a ':' if the
8338 name contains a ':'. */
8339 if (strchr_m(name, ':')) {
8340 if (newname[0] != ':') {
8341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8344 stream_rename = true;
8348 status = filename_convert(ctx,
8356 if (!NT_STATUS_IS_OK(status)) {
8357 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8358 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8359 ERRSRV, ERRbadpath);
8362 reply_nterror(req, status);
8366 status = filename_convert(ctx,
8374 if (!NT_STATUS_IS_OK(status)) {
8375 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8376 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8377 ERRSRV, ERRbadpath);
8380 reply_nterror(req, status);
8384 /* Get the last component of the destination for rename_internals(). */
8385 dst_original_lcomp = get_original_lcomp(ctx,
8389 if (dst_original_lcomp == NULL) {
8390 reply_nterror(req, NT_STATUS_NO_MEMORY);
8394 if (stream_rename) {
8395 /* smb_fname_dst->base_name must be the same as
8396 smb_fname_src->base_name. */
8397 TALLOC_FREE(smb_fname_dst->base_name);
8398 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8399 smb_fname_src->base_name);
8400 if (!smb_fname_dst->base_name) {
8401 reply_nterror(req, NT_STATUS_NO_MEMORY);
8406 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8407 smb_fname_str_dbg(smb_fname_dst)));
8409 status = rename_internals(ctx,
8420 if (!NT_STATUS_IS_OK(status)) {
8421 if (open_was_deferred(req->xconn, req->mid)) {
8422 /* We have re-scheduled this call. */
8425 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8426 bool ok = defer_smb1_sharing_violation(req);
8431 reply_nterror(req, status);
8435 reply_outbuf(req, 0, 0);
8437 TALLOC_FREE(smb_fname_src);
8438 TALLOC_FREE(smb_fname_dst);
8443 /*******************************************************************
8444 Copy a file as part of a reply_copy.
8445 ******************************************************************/
8448 * TODO: check error codes on all callers
8451 NTSTATUS copy_file(TALLOC_CTX *ctx,
8452 connection_struct *conn,
8453 struct smb_filename *smb_fname_src,
8454 struct smb_filename *smb_fname_dst,
8457 bool target_is_directory)
8459 struct smb_filename *smb_fname_dst_tmp = NULL;
8461 files_struct *fsp1,*fsp2;
8463 uint32_t new_create_disposition;
8467 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8468 if (smb_fname_dst_tmp == NULL) {
8469 return NT_STATUS_NO_MEMORY;
8473 * If the target is a directory, extract the last component from the
8474 * src filename and append it to the dst filename
8476 if (target_is_directory) {
8479 /* dest/target can't be a stream if it's a directory. */
8480 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8482 p = strrchr_m(smb_fname_src->base_name,'/');
8486 p = smb_fname_src->base_name;
8488 smb_fname_dst_tmp->base_name =
8489 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8491 if (!smb_fname_dst_tmp->base_name) {
8492 status = NT_STATUS_NO_MEMORY;
8497 status = vfs_file_exist(conn, smb_fname_src);
8498 if (!NT_STATUS_IS_OK(status)) {
8502 if (!target_is_directory && count) {
8503 new_create_disposition = FILE_OPEN;
8505 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8508 &new_create_disposition,
8511 status = NT_STATUS_INVALID_PARAMETER;
8516 /* Open the src file for reading. */
8517 status = SMB_VFS_CREATE_FILE(
8520 0, /* root_dir_fid */
8521 smb_fname_src, /* fname */
8522 FILE_GENERIC_READ, /* access_mask */
8523 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8524 FILE_OPEN, /* create_disposition*/
8525 0, /* create_options */
8526 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8527 INTERNAL_OPEN_ONLY, /* oplock_request */
8529 0, /* allocation_size */
8530 0, /* private_flags */
8535 NULL, NULL); /* create context */
8537 if (!NT_STATUS_IS_OK(status)) {
8541 dosattrs = dos_mode(conn, smb_fname_src);
8543 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8544 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8547 /* Open the dst file for writing. */
8548 status = SMB_VFS_CREATE_FILE(
8551 0, /* root_dir_fid */
8552 smb_fname_dst, /* fname */
8553 FILE_GENERIC_WRITE, /* access_mask */
8554 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8555 new_create_disposition, /* create_disposition*/
8556 0, /* create_options */
8557 dosattrs, /* file_attributes */
8558 INTERNAL_OPEN_ONLY, /* oplock_request */
8560 0, /* allocation_size */
8561 0, /* private_flags */
8566 NULL, NULL); /* create context */
8568 if (!NT_STATUS_IS_OK(status)) {
8569 close_file(NULL, fsp1, ERROR_CLOSE);
8573 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8574 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8576 DEBUG(0, ("error - vfs lseek returned error %s\n",
8578 status = map_nt_error_from_unix(errno);
8579 close_file(NULL, fsp1, ERROR_CLOSE);
8580 close_file(NULL, fsp2, ERROR_CLOSE);
8585 /* Do the actual copy. */
8586 if (smb_fname_src->st.st_ex_size) {
8587 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8592 close_file(NULL, fsp1, NORMAL_CLOSE);
8594 /* Ensure the modtime is set correctly on the destination file. */
8595 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8598 * As we are opening fsp1 read-only we only expect
8599 * an error on close on fsp2 if we are out of space.
8600 * Thus we don't look at the error return from the
8603 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8605 if (!NT_STATUS_IS_OK(status)) {
8609 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8610 status = NT_STATUS_DISK_FULL;
8614 status = NT_STATUS_OK;
8617 TALLOC_FREE(smb_fname_dst_tmp);
8621 /****************************************************************************
8622 Reply to a file copy.
8623 ****************************************************************************/
8625 void reply_copy(struct smb_request *req)
8627 connection_struct *conn = req->conn;
8628 struct smb_filename *smb_fname_src = NULL;
8629 struct smb_filename *smb_fname_src_dir = NULL;
8630 struct smb_filename *smb_fname_dst = NULL;
8631 char *fname_src = NULL;
8632 char *fname_dst = NULL;
8633 char *fname_src_mask = NULL;
8634 char *fname_src_dir = NULL;
8637 int error = ERRnoaccess;
8641 bool target_is_directory=False;
8642 bool source_has_wild = False;
8643 bool dest_has_wild = False;
8645 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
8646 ucf_flags_from_smb_request(req);
8647 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
8648 ucf_flags_from_smb_request(req);
8649 TALLOC_CTX *ctx = talloc_tos();
8651 START_PROFILE(SMBcopy);
8654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8658 tid2 = SVAL(req->vwv+0, 0);
8659 ofun = SVAL(req->vwv+1, 0);
8660 flags = SVAL(req->vwv+2, 0);
8662 p = (const char *)req->buf;
8663 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8664 &status, &source_has_wild);
8665 if (!NT_STATUS_IS_OK(status)) {
8666 reply_nterror(req, status);
8669 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8670 &status, &dest_has_wild);
8671 if (!NT_STATUS_IS_OK(status)) {
8672 reply_nterror(req, status);
8676 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8678 if (tid2 != conn->cnum) {
8679 /* can't currently handle inter share copies XXXX */
8680 DEBUG(3,("Rejecting inter-share copy\n"));
8681 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8685 status = filename_convert(ctx, conn,
8691 if (!NT_STATUS_IS_OK(status)) {
8692 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8693 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8694 ERRSRV, ERRbadpath);
8697 reply_nterror(req, status);
8701 status = filename_convert(ctx, conn,
8707 if (!NT_STATUS_IS_OK(status)) {
8708 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8709 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8710 ERRSRV, ERRbadpath);
8713 reply_nterror(req, status);
8717 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8719 if ((flags&1) && target_is_directory) {
8720 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8724 if ((flags&2) && !target_is_directory) {
8725 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8729 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8730 /* wants a tree copy! XXXX */
8731 DEBUG(3,("Rejecting tree copy\n"));
8732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8736 /* Split up the directory from the filename/mask. */
8737 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8738 &fname_src_dir, &fname_src_mask);
8739 if (!NT_STATUS_IS_OK(status)) {
8740 reply_nterror(req, NT_STATUS_NO_MEMORY);
8745 * We should only check the mangled cache
8746 * here if unix_convert failed. This means
8747 * that the path in 'mask' doesn't exist
8748 * on the file system and so we need to look
8749 * for a possible mangle. This patch from
8750 * Tine Smukavec <valentin.smukavec@hermes.si>.
8752 if (!VALID_STAT(smb_fname_src->st) &&
8753 mangle_is_mangled(fname_src_mask, conn->params)) {
8754 char *new_mask = NULL;
8755 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8756 &new_mask, conn->params);
8758 /* Use demangled name if one was successfully found. */
8760 TALLOC_FREE(fname_src_mask);
8761 fname_src_mask = new_mask;
8765 if (!source_has_wild) {
8768 * Only one file needs to be copied. Append the mask back onto
8771 TALLOC_FREE(smb_fname_src->base_name);
8772 if (ISDOT(fname_src_dir)) {
8773 /* Ensure we use canonical names on open. */
8774 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8778 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8783 if (!smb_fname_src->base_name) {
8784 reply_nterror(req, NT_STATUS_NO_MEMORY);
8788 if (dest_has_wild) {
8789 char *fname_dst_mod = NULL;
8790 if (!resolve_wildcards(smb_fname_dst,
8791 smb_fname_src->base_name,
8792 smb_fname_dst->base_name,
8794 reply_nterror(req, NT_STATUS_NO_MEMORY);
8797 TALLOC_FREE(smb_fname_dst->base_name);
8798 smb_fname_dst->base_name = fname_dst_mod;
8801 status = check_name(conn, smb_fname_src);
8802 if (!NT_STATUS_IS_OK(status)) {
8803 reply_nterror(req, status);
8807 status = check_name(conn, smb_fname_dst);
8808 if (!NT_STATUS_IS_OK(status)) {
8809 reply_nterror(req, status);
8813 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8814 ofun, count, target_is_directory);
8816 if(!NT_STATUS_IS_OK(status)) {
8817 reply_nterror(req, status);
8823 struct smb_Dir *dir_hnd = NULL;
8824 const char *dname = NULL;
8825 char *talloced = NULL;
8829 * There is a wildcard that requires us to actually read the
8830 * src dir and copy each file matching the mask to the dst.
8831 * Right now streams won't be copied, but this could
8832 * presumably be added with a nested loop for reach dir entry.
8834 SMB_ASSERT(!smb_fname_src->stream_name);
8835 SMB_ASSERT(!smb_fname_dst->stream_name);
8837 smb_fname_src->stream_name = NULL;
8838 smb_fname_dst->stream_name = NULL;
8840 if (strequal(fname_src_mask,"????????.???")) {
8841 TALLOC_FREE(fname_src_mask);
8842 fname_src_mask = talloc_strdup(ctx, "*");
8843 if (!fname_src_mask) {
8844 reply_nterror(req, NT_STATUS_NO_MEMORY);
8849 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8853 smb_fname_src->flags);
8854 if (smb_fname_src_dir == NULL) {
8855 reply_nterror(req, NT_STATUS_NO_MEMORY);
8859 status = check_name(conn, smb_fname_src_dir);
8860 if (!NT_STATUS_IS_OK(status)) {
8861 reply_nterror(req, status);
8865 dir_hnd = OpenDir(ctx,
8870 if (dir_hnd == NULL) {
8871 status = map_nt_error_from_unix(errno);
8872 reply_nterror(req, status);
8878 /* Iterate over the src dir copying each entry to the dst. */
8879 while ((dname = ReadDirName(dir_hnd, &offset,
8880 &smb_fname_src->st, &talloced))) {
8881 char *destname = NULL;
8883 if (ISDOT(dname) || ISDOTDOT(dname)) {
8884 TALLOC_FREE(talloced);
8888 if (!is_visible_file(conn, smb_fname_src_dir, dname,
8889 &smb_fname_src->st, false)) {
8890 TALLOC_FREE(talloced);
8894 if(!mask_match(dname, fname_src_mask,
8895 conn->case_sensitive)) {
8896 TALLOC_FREE(talloced);
8900 error = ERRnoaccess;
8902 /* Get the src smb_fname struct setup. */
8903 TALLOC_FREE(smb_fname_src->base_name);
8904 if (ISDOT(fname_src_dir)) {
8905 /* Ensure we use canonical names on open. */
8906 smb_fname_src->base_name =
8907 talloc_asprintf(smb_fname_src, "%s",
8910 smb_fname_src->base_name =
8911 talloc_asprintf(smb_fname_src, "%s/%s",
8912 fname_src_dir, dname);
8915 if (!smb_fname_src->base_name) {
8916 TALLOC_FREE(dir_hnd);
8917 TALLOC_FREE(talloced);
8918 reply_nterror(req, NT_STATUS_NO_MEMORY);
8922 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8923 smb_fname_dst->base_name,
8925 TALLOC_FREE(talloced);
8929 TALLOC_FREE(dir_hnd);
8930 TALLOC_FREE(talloced);
8931 reply_nterror(req, NT_STATUS_NO_MEMORY);
8935 TALLOC_FREE(smb_fname_dst->base_name);
8936 smb_fname_dst->base_name = destname;
8938 status = check_name(conn, smb_fname_src);
8939 if (!NT_STATUS_IS_OK(status)) {
8940 TALLOC_FREE(dir_hnd);
8941 TALLOC_FREE(talloced);
8942 reply_nterror(req, status);
8946 status = check_name(conn, smb_fname_dst);
8947 if (!NT_STATUS_IS_OK(status)) {
8948 TALLOC_FREE(dir_hnd);
8949 TALLOC_FREE(talloced);
8950 reply_nterror(req, status);
8954 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8955 smb_fname_src->base_name,
8956 smb_fname_dst->base_name));
8958 status = copy_file(ctx, conn, smb_fname_src,
8959 smb_fname_dst, ofun, count,
8960 target_is_directory);
8961 if (NT_STATUS_IS_OK(status)) {
8965 TALLOC_FREE(talloced);
8967 TALLOC_FREE(dir_hnd);
8971 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8975 reply_outbuf(req, 1, 0);
8976 SSVAL(req->outbuf,smb_vwv0,count);
8978 TALLOC_FREE(smb_fname_src);
8979 TALLOC_FREE(smb_fname_src_dir);
8980 TALLOC_FREE(smb_fname_dst);
8981 TALLOC_FREE(fname_src);
8982 TALLOC_FREE(fname_dst);
8983 TALLOC_FREE(fname_src_mask);
8984 TALLOC_FREE(fname_src_dir);
8986 END_PROFILE(SMBcopy);
8991 #define DBGC_CLASS DBGC_LOCKING
8993 /****************************************************************************
8994 Get a lock pid, dealing with large count requests.
8995 ****************************************************************************/
8997 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8998 bool large_file_format)
9000 if(!large_file_format)
9001 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9003 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9006 /****************************************************************************
9007 Get a lock count, dealing with large count requests.
9008 ****************************************************************************/
9010 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9011 bool large_file_format)
9015 if(!large_file_format) {
9016 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9019 * No BVAL, this is reversed!
9021 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9022 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9028 /****************************************************************************
9029 Get a lock offset, dealing with large offset requests.
9030 ****************************************************************************/
9032 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9033 bool large_file_format)
9035 uint64_t offset = 0;
9037 if(!large_file_format) {
9038 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9041 * No BVAL, this is reversed!
9043 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9044 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9050 struct smbd_do_unlocking_state {
9051 struct files_struct *fsp;
9052 uint16_t num_ulocks;
9053 struct smbd_lock_element *ulocks;
9054 enum brl_flavour lock_flav;
9058 static void smbd_do_unlocking_fn(
9059 TDB_DATA value, bool *pmodified_dependent, void *private_data)
9061 struct smbd_do_unlocking_state *state = private_data;
9062 struct files_struct *fsp = state->fsp;
9063 enum brl_flavour lock_flav = state->lock_flav;
9066 for (i = 0; i < state->num_ulocks; i++) {
9067 struct smbd_lock_element *e = &state->ulocks[i];
9069 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9070 "pid %"PRIu64", file %s\n",
9076 if (e->brltype != UNLOCK_LOCK) {
9077 /* this can only happen with SMB2 */
9078 state->status = NT_STATUS_INVALID_PARAMETER;
9082 state->status = do_unlock(
9083 fsp, e->smblctx, e->count, e->offset, lock_flav);
9085 DBG_DEBUG("do_unlock returned %s\n",
9086 nt_errstr(state->status));
9088 if (!NT_STATUS_IS_OK(state->status)) {
9093 *pmodified_dependent = true;
9096 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9098 uint16_t num_ulocks,
9099 struct smbd_lock_element *ulocks,
9100 enum brl_flavour lock_flav)
9102 struct smbd_do_unlocking_state state = {
9104 .num_ulocks = num_ulocks,
9106 .lock_flav = lock_flav,
9110 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9112 status = share_mode_do_locked(
9113 fsp->file_id, smbd_do_unlocking_fn, &state);
9115 if (!NT_STATUS_IS_OK(status)) {
9116 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9120 if (!NT_STATUS_IS_OK(state.status)) {
9121 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9123 return state.status;
9126 return NT_STATUS_OK;
9129 /****************************************************************************
9130 Reply to a lockingX request.
9131 ****************************************************************************/
9133 static void reply_lockingx_done(struct tevent_req *subreq);
9135 void reply_lockingX(struct smb_request *req)
9137 connection_struct *conn = req->conn;
9139 unsigned char locktype;
9140 enum brl_type brltype;
9141 unsigned char oplocklevel;
9142 uint16_t num_ulocks;
9144 int32_t lock_timeout;
9146 const uint8_t *data;
9147 bool large_file_format;
9148 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9149 struct smbd_lock_element *locks = NULL;
9150 struct tevent_req *subreq = NULL;
9152 START_PROFILE(SMBlockingX);
9155 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9156 END_PROFILE(SMBlockingX);
9160 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9161 locktype = CVAL(req->vwv+3, 0);
9162 oplocklevel = CVAL(req->vwv+3, 1);
9163 num_ulocks = SVAL(req->vwv+6, 0);
9164 num_locks = SVAL(req->vwv+7, 0);
9165 lock_timeout = IVAL(req->vwv+4, 0);
9166 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9168 if (!check_fsp(conn, req, fsp)) {
9169 END_PROFILE(SMBlockingX);
9175 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9176 /* we don't support these - and CANCEL_LOCK makes w2k
9177 and XP reboot so I don't really want to be
9178 compatible! (tridge) */
9179 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9180 END_PROFILE(SMBlockingX);
9184 /* Check if this is an oplock break on a file
9185 we have granted an oplock on.
9187 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9188 /* Client can insist on breaking to none. */
9189 bool break_to_none = (oplocklevel == 0);
9192 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9193 "for %s\n", (unsigned int)oplocklevel,
9194 fsp_fnum_dbg(fsp)));
9197 * Make sure we have granted an exclusive or batch oplock on
9201 if (fsp->oplock_type == 0) {
9203 /* The Samba4 nbench simulator doesn't understand
9204 the difference between break to level2 and break
9205 to none from level2 - it sends oplock break
9206 replies in both cases. Don't keep logging an error
9207 message here - just ignore it. JRA. */
9209 DEBUG(5,("reply_lockingX: Error : oplock break from "
9210 "client for %s (oplock=%d) and no "
9211 "oplock granted on this file (%s).\n",
9212 fsp_fnum_dbg(fsp), fsp->oplock_type,
9215 /* if this is a pure oplock break request then don't
9217 if (num_locks == 0 && num_ulocks == 0) {
9218 END_PROFILE(SMBlockingX);
9222 END_PROFILE(SMBlockingX);
9223 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9227 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9229 result = remove_oplock(fsp);
9231 result = downgrade_oplock(fsp);
9235 DEBUG(0, ("reply_lockingX: error in removing "
9236 "oplock on file %s\n", fsp_str_dbg(fsp)));
9237 /* Hmmm. Is this panic justified? */
9238 smb_panic("internal tdb error");
9241 /* if this is a pure oplock break request then don't send a
9243 if (num_locks == 0 && num_ulocks == 0) {
9244 /* Sanity check - ensure a pure oplock break is not a
9246 if (CVAL(req->vwv+0, 0) != 0xff) {
9247 DEBUG(0,("reply_lockingX: Error : pure oplock "
9248 "break is a chained %d request !\n",
9249 (unsigned int)CVAL(req->vwv+0, 0)));
9251 END_PROFILE(SMBlockingX);
9257 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9259 END_PROFILE(SMBlockingX);
9263 if (num_ulocks != 0) {
9264 struct smbd_lock_element *ulocks = NULL;
9267 ulocks = talloc_array(
9268 req, struct smbd_lock_element, num_ulocks);
9269 if (ulocks == NULL) {
9270 reply_nterror(req, NT_STATUS_NO_MEMORY);
9271 END_PROFILE(SMBlockingX);
9276 * Data now points at the beginning of the list of
9277 * smb_unlkrng structs
9279 for (i = 0; i < num_ulocks; i++) {
9280 ulocks[i].req_guid = smbd_request_guid(req,
9282 ulocks[i].smblctx = get_lock_pid(
9283 data, i, large_file_format);
9284 ulocks[i].count = get_lock_count(
9285 data, i, large_file_format);
9286 ulocks[i].offset = get_lock_offset(
9287 data, i, large_file_format);
9288 ulocks[i].brltype = UNLOCK_LOCK;
9292 * Unlock cancels pending locks
9295 ok = smbd_smb1_brl_finish_by_lock(
9302 reply_outbuf(req, 2, 0);
9303 SSVAL(req->outbuf, smb_vwv0, 0xff);
9304 SSVAL(req->outbuf, smb_vwv1, 0);
9305 END_PROFILE(SMBlockingX);
9309 status = smbd_do_unlocking(
9310 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9311 TALLOC_FREE(ulocks);
9312 if (!NT_STATUS_IS_OK(status)) {
9313 END_PROFILE(SMBlockingX);
9314 reply_nterror(req, status);
9319 /* Now do any requested locks */
9320 data += ((large_file_format ? 20 : 10)*num_ulocks);
9322 /* Data now points at the beginning of the list
9323 of smb_lkrng structs */
9325 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9326 brltype = READ_LOCK;
9328 brltype = WRITE_LOCK;
9331 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9332 if (locks == NULL) {
9333 reply_nterror(req, NT_STATUS_NO_MEMORY);
9334 END_PROFILE(SMBlockingX);
9338 for (i = 0; i < num_locks; i++) {
9339 locks[i].req_guid = smbd_request_guid(req, i),
9340 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9341 locks[i].count = get_lock_count(data, i, large_file_format);
9342 locks[i].offset = get_lock_offset(data, i, large_file_format);
9343 locks[i].brltype = brltype;
9346 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9350 if (num_locks == 0) {
9351 /* See smbtorture3 lock11 test */
9352 reply_outbuf(req, 2, 0);
9353 /* andx chain ends */
9354 SSVAL(req->outbuf, smb_vwv0, 0xff);
9355 SSVAL(req->outbuf, smb_vwv1, 0);
9356 END_PROFILE(SMBlockingX);
9360 ok = smbd_smb1_brl_finish_by_lock(
9364 locks[0], /* Windows only cancels the first lock */
9365 NT_STATUS_FILE_LOCK_CONFLICT);
9368 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9369 END_PROFILE(SMBlockingX);
9373 reply_outbuf(req, 2, 0);
9374 SSVAL(req->outbuf, smb_vwv0, 0xff);
9375 SSVAL(req->outbuf, smb_vwv1, 0);
9376 END_PROFILE(SMBlockingX);
9380 subreq = smbd_smb1_do_locks_send(
9390 if (subreq == NULL) {
9391 reply_nterror(req, NT_STATUS_NO_MEMORY);
9392 END_PROFILE(SMBlockingX);
9395 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9396 END_PROFILE(SMBlockingX);
9399 static void reply_lockingx_done(struct tevent_req *subreq)
9401 struct smb_request *req = NULL;
9405 START_PROFILE(SMBlockingX);
9407 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9410 status = smbd_smb1_do_locks_recv(subreq);
9411 TALLOC_FREE(subreq);
9413 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9415 if (NT_STATUS_IS_OK(status)) {
9416 reply_outbuf(req, 2, 0);
9417 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9418 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9420 reply_nterror(req, status);
9423 ok = srv_send_smb(req->xconn,
9424 (char *)req->outbuf,
9427 IS_CONN_ENCRYPTED(req->conn),
9430 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9433 END_PROFILE(SMBlockingX);
9437 #define DBGC_CLASS DBGC_ALL
9439 /****************************************************************************
9440 Reply to a SMBreadbmpx (read block multiplex) request.
9441 Always reply with an error, if someone has a platform really needs this,
9442 please contact vl@samba.org
9443 ****************************************************************************/
9445 void reply_readbmpx(struct smb_request *req)
9447 START_PROFILE(SMBreadBmpx);
9448 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9449 END_PROFILE(SMBreadBmpx);
9453 /****************************************************************************
9454 Reply to a SMBreadbs (read block multiplex secondary) request.
9455 Always reply with an error, if someone has a platform really needs this,
9456 please contact vl@samba.org
9457 ****************************************************************************/
9459 void reply_readbs(struct smb_request *req)
9461 START_PROFILE(SMBreadBs);
9462 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9463 END_PROFILE(SMBreadBs);
9467 /****************************************************************************
9468 Reply to a SMBsetattrE.
9469 ****************************************************************************/
9471 void reply_setattrE(struct smb_request *req)
9473 connection_struct *conn = req->conn;
9474 struct smb_file_time ft;
9478 START_PROFILE(SMBsetattrE);
9479 init_smb_file_time(&ft);
9482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9486 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9488 if(!fsp || (fsp->conn != conn)) {
9489 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9494 * Convert the DOS times into unix times.
9497 ft.atime = time_t_to_full_timespec(
9498 srv_make_unix_date2(req->vwv+3));
9499 ft.mtime = time_t_to_full_timespec(
9500 srv_make_unix_date2(req->vwv+5));
9501 ft.create_time = time_t_to_full_timespec(
9502 srv_make_unix_date2(req->vwv+1));
9504 reply_outbuf(req, 0, 0);
9507 * Patch from Ray Frush <frush@engr.colostate.edu>
9508 * Sometimes times are sent as zero - ignore them.
9511 /* Ensure we have a valid stat struct for the source. */
9512 status = vfs_stat_fsp(fsp);
9513 if (!NT_STATUS_IS_OK(status)) {
9514 reply_nterror(req, status);
9518 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9519 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9523 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9524 if (!NT_STATUS_IS_OK(status)) {
9525 reply_nterror(req, status);
9529 if (fsp->fsp_flags.modified) {
9530 trigger_write_time_update_immediate(fsp);
9533 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9536 (unsigned int)ft.atime.tv_sec,
9537 (unsigned int)ft.mtime.tv_sec,
9538 (unsigned int)ft.create_time.tv_sec
9541 END_PROFILE(SMBsetattrE);
9546 /* Back from the dead for OS/2..... JRA. */
9548 /****************************************************************************
9549 Reply to a SMBwritebmpx (write block multiplex primary) request.
9550 Always reply with an error, if someone has a platform really needs this,
9551 please contact vl@samba.org
9552 ****************************************************************************/
9554 void reply_writebmpx(struct smb_request *req)
9556 START_PROFILE(SMBwriteBmpx);
9557 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9558 END_PROFILE(SMBwriteBmpx);
9562 /****************************************************************************
9563 Reply to a SMBwritebs (write block multiplex secondary) request.
9564 Always reply with an error, if someone has a platform really needs this,
9565 please contact vl@samba.org
9566 ****************************************************************************/
9568 void reply_writebs(struct smb_request *req)
9570 START_PROFILE(SMBwriteBs);
9571 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9572 END_PROFILE(SMBwriteBs);
9576 /****************************************************************************
9577 Reply to a SMBgetattrE.
9578 ****************************************************************************/
9580 void reply_getattrE(struct smb_request *req)
9582 connection_struct *conn = req->conn;
9585 struct timespec create_ts;
9588 START_PROFILE(SMBgetattrE);
9591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9592 END_PROFILE(SMBgetattrE);
9596 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9598 if(!fsp || (fsp->conn != conn)) {
9599 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9600 END_PROFILE(SMBgetattrE);
9604 /* Do an fstat on this file */
9605 status = vfs_stat_fsp(fsp);
9606 if (!NT_STATUS_IS_OK(status)) {
9607 reply_nterror(req, status);
9608 END_PROFILE(SMBgetattrE);
9612 mode = dos_mode(conn, fsp->fsp_name);
9615 * Convert the times into dos times. Set create
9616 * date to be last modify date as UNIX doesn't save
9620 reply_outbuf(req, 11, 0);
9622 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9623 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9624 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9625 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9626 /* Should we check pending modtime here ? JRA */
9627 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9628 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9630 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9631 SIVAL(req->outbuf, smb_vwv6, 0);
9632 SIVAL(req->outbuf, smb_vwv8, 0);
9634 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9635 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9636 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9638 SSVAL(req->outbuf,smb_vwv10, mode);
9640 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9642 END_PROFILE(SMBgetattrE);