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->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->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->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, 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->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->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->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->is_directory ? "directory" : "file",
6036 fsp->fh->fd, fsp_fnum_dbg(fsp),
6037 conn->num_files_open);
6039 if (!fsp->is_directory) {
6043 * Take care of any time sent in the close.
6046 t = srv_make_unix_date3(smb1req->vwv+1);
6047 set_close_write_time(fsp, time_t_to_full_timespec(t));
6050 if (fsp->num_aio_requests != 0) {
6051 struct tevent_req *req;
6053 req = reply_close_send(smb1req, fsp);
6055 status = NT_STATUS_NO_MEMORY;
6058 /* We're async. This will complete later. */
6059 tevent_req_set_callback(req, reply_close_done, smb1req);
6060 END_PROFILE(SMBclose);
6065 * close_file() returns the unix errno if an error was detected on
6066 * close - normally this is due to a disk full error. If not then it
6067 * was probably an I/O error.
6070 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6072 if (!NT_STATUS_IS_OK(status)) {
6073 reply_nterror(smb1req, status);
6074 END_PROFILE(SMBclose);
6078 reply_outbuf(smb1req, 0, 0);
6079 END_PROFILE(SMBclose);
6083 struct reply_close_state {
6085 struct tevent_queue *wait_queue;
6088 static void reply_close_wait_done(struct tevent_req *subreq);
6090 /****************************************************************************
6092 Note, on failure here we deallocate and return NULL to allow the caller to
6093 SMB1 return an error of ERRnomem immediately.
6094 ****************************************************************************/
6096 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6099 struct tevent_req *req;
6100 struct reply_close_state *state;
6101 struct tevent_req *subreq;
6102 struct smbd_server_connection *sconn = smb1req->sconn;
6104 req = tevent_req_create(smb1req, &state,
6105 struct reply_close_state);
6109 state->wait_queue = tevent_queue_create(state,
6110 "reply_close_wait_queue");
6111 if (tevent_req_nomem(state->wait_queue, req)) {
6117 * Flag the file as close in progress.
6118 * This will prevent any more IO being
6121 fsp->closing = true;
6124 * Now wait until all aio requests on this fsp are
6127 * We don't set a callback, as we just want to block the
6128 * wait queue and the talloc_free() of fsp->aio_request
6129 * will remove the item from the wait queue.
6131 subreq = tevent_queue_wait_send(fsp->aio_requests,
6134 if (tevent_req_nomem(subreq, req)) {
6140 * Now we add our own waiter to the end of the queue,
6141 * this way we get notified when all pending requests are finished
6142 * and reply to the outstanding SMB1 request.
6144 subreq = tevent_queue_wait_send(state,
6147 if (tevent_req_nomem(subreq, req)) {
6153 * We're really going async - move the SMB1 request from
6154 * a talloc stackframe above us to the conn talloc-context.
6155 * We need this to stick around until the wait_done
6156 * callback is invoked.
6158 smb1req = talloc_move(sconn, &smb1req);
6160 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6165 static void reply_close_wait_done(struct tevent_req *subreq)
6167 struct tevent_req *req = tevent_req_callback_data(
6168 subreq, struct tevent_req);
6170 tevent_queue_wait_recv(subreq);
6171 TALLOC_FREE(subreq);
6172 tevent_req_done(req);
6175 static NTSTATUS reply_close_recv(struct tevent_req *req)
6177 return tevent_req_simple_recv_ntstatus(req);
6180 static void reply_close_done(struct tevent_req *req)
6182 struct smb_request *smb1req = tevent_req_callback_data(
6183 req, struct smb_request);
6184 struct reply_close_state *state = tevent_req_data(req,
6185 struct reply_close_state);
6188 status = reply_close_recv(req);
6190 if (!NT_STATUS_IS_OK(status)) {
6191 TALLOC_FREE(smb1req);
6192 exit_server(__location__ ": reply_close_recv failed");
6196 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6197 if (NT_STATUS_IS_OK(status)) {
6198 reply_outbuf(smb1req, 0, 0);
6200 reply_nterror(smb1req, status);
6203 * The following call is needed to push the
6204 * reply data back out the socket after async
6205 * return. Plus it frees smb1req.
6207 smb_request_done(smb1req);
6210 /****************************************************************************
6211 Reply to a writeclose (Core+ protocol).
6212 ****************************************************************************/
6214 void reply_writeclose(struct smb_request *req)
6216 connection_struct *conn = req->conn;
6219 ssize_t nwritten = -1;
6220 NTSTATUS close_status = NT_STATUS_OK;
6223 struct timespec mtime;
6225 struct lock_struct lock;
6227 START_PROFILE(SMBwriteclose);
6230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6231 END_PROFILE(SMBwriteclose);
6235 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6237 if (!check_fsp(conn, req, fsp)) {
6238 END_PROFILE(SMBwriteclose);
6241 if (!CHECK_WRITE(fsp)) {
6242 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6243 END_PROFILE(SMBwriteclose);
6247 numtowrite = SVAL(req->vwv+1, 0);
6248 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6249 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6250 data = (const char *)req->buf + 1;
6253 * Ensure client isn't asking us to write more than
6254 * they sent. CVE-2017-12163.
6256 remaining = smbreq_bufrem(req, data);
6257 if (numtowrite > remaining) {
6258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6259 END_PROFILE(SMBwriteclose);
6263 if (fsp->print_file == NULL) {
6264 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6265 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6268 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6269 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6270 END_PROFILE(SMBwriteclose);
6275 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6277 set_close_write_time(fsp, mtime);
6280 * More insanity. W2K only closes the file if writelen > 0.
6284 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6285 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6286 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6289 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6290 "file %s\n", fsp_str_dbg(fsp)));
6291 close_status = close_file(req, fsp, NORMAL_CLOSE);
6295 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6296 reply_nterror(req, NT_STATUS_DISK_FULL);
6300 if(!NT_STATUS_IS_OK(close_status)) {
6301 reply_nterror(req, close_status);
6305 reply_outbuf(req, 1, 0);
6307 SSVAL(req->outbuf,smb_vwv0,nwritten);
6311 END_PROFILE(SMBwriteclose);
6316 #define DBGC_CLASS DBGC_LOCKING
6318 /****************************************************************************
6320 ****************************************************************************/
6322 static void reply_lock_done(struct tevent_req *subreq);
6324 void reply_lock(struct smb_request *req)
6326 struct tevent_req *subreq = NULL;
6327 connection_struct *conn = req->conn;
6329 struct smbd_lock_element *lck = NULL;
6331 START_PROFILE(SMBlock);
6334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6335 END_PROFILE(SMBlock);
6339 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6341 if (!check_fsp(conn, req, fsp)) {
6342 END_PROFILE(SMBlock);
6346 lck = talloc(req, struct smbd_lock_element);
6348 reply_nterror(req, NT_STATUS_NO_MEMORY);
6349 END_PROFILE(SMBlock);
6353 *lck = (struct smbd_lock_element) {
6354 .req_guid = smbd_request_guid(req, 0),
6355 .smblctx = req->smbpid,
6356 .brltype = WRITE_LOCK,
6357 .count = IVAL(req->vwv+1, 0),
6358 .offset = IVAL(req->vwv+3, 0),
6361 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6367 subreq = smbd_smb1_do_locks_send(
6373 false, /* large_offset */
6377 if (subreq == NULL) {
6378 reply_nterror(req, NT_STATUS_NO_MEMORY);
6379 END_PROFILE(SMBlock);
6382 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6383 END_PROFILE(SMBlock);
6386 static void reply_lock_done(struct tevent_req *subreq)
6388 struct smb_request *req = NULL;
6392 START_PROFILE(SMBlock);
6394 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6397 status = smbd_smb1_do_locks_recv(subreq);
6398 TALLOC_FREE(subreq);
6400 if (NT_STATUS_IS_OK(status)) {
6401 reply_outbuf(req, 0, 0);
6403 reply_nterror(req, status);
6406 ok = srv_send_smb(req->xconn,
6407 (char *)req->outbuf,
6410 IS_CONN_ENCRYPTED(req->conn),
6413 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6416 END_PROFILE(SMBlock);
6419 /****************************************************************************
6421 ****************************************************************************/
6423 void reply_unlock(struct smb_request *req)
6425 connection_struct *conn = req->conn;
6428 struct smbd_lock_element lck;
6430 START_PROFILE(SMBunlock);
6433 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6434 END_PROFILE(SMBunlock);
6438 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6440 if (!check_fsp(conn, req, fsp)) {
6441 END_PROFILE(SMBunlock);
6445 lck = (struct smbd_lock_element) {
6446 .req_guid = smbd_request_guid(req, 0),
6447 .smblctx = req->smbpid,
6448 .brltype = UNLOCK_LOCK,
6449 .offset = IVAL(req->vwv+3, 0),
6450 .count = IVAL(req->vwv+1, 0),
6453 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6455 if (!NT_STATUS_IS_OK(status)) {
6456 reply_nterror(req, status);
6457 END_PROFILE(SMBunlock);
6461 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6467 reply_outbuf(req, 0, 0);
6469 END_PROFILE(SMBunlock);
6474 #define DBGC_CLASS DBGC_ALL
6476 /****************************************************************************
6478 conn POINTER CAN BE NULL HERE !
6479 ****************************************************************************/
6481 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6482 static void reply_tdis_done(struct tevent_req *req);
6484 void reply_tdis(struct smb_request *smb1req)
6486 connection_struct *conn = smb1req->conn;
6487 struct tevent_req *req;
6490 * Don't setup the profile charge here, take
6491 * it in reply_tdis_done(). Not strictly correct
6492 * but better than the other SMB1 async
6493 * code that double-charges at the moment.
6497 /* Not going async, profile here. */
6498 START_PROFILE(SMBtdis);
6499 DBG_INFO("Invalid connection in tdis\n");
6500 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6501 END_PROFILE(SMBtdis);
6505 req = reply_tdis_send(smb1req);
6507 /* Not going async, profile here. */
6508 START_PROFILE(SMBtdis);
6509 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6510 END_PROFILE(SMBtdis);
6513 /* We're async. This will complete later. */
6514 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6518 struct reply_tdis_state {
6519 struct tevent_queue *wait_queue;
6522 static void reply_tdis_wait_done(struct tevent_req *subreq);
6524 /****************************************************************************
6526 Note, on failure here we deallocate and return NULL to allow the caller to
6527 SMB1 return an error of ERRnomem immediately.
6528 ****************************************************************************/
6530 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6532 struct tevent_req *req;
6533 struct reply_tdis_state *state;
6534 struct tevent_req *subreq;
6535 connection_struct *conn = smb1req->conn;
6538 req = tevent_req_create(smb1req, &state,
6539 struct reply_tdis_state);
6543 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6544 if (tevent_req_nomem(state->wait_queue, req)) {
6550 * Make sure that no new request will be able to use this tcon.
6551 * This ensures that once all outstanding fsp->aio_requests
6552 * on this tcon are done, we are safe to close it.
6554 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6556 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6557 if (fsp->conn != conn) {
6561 * Flag the file as close in progress.
6562 * This will prevent any more IO being
6563 * done on it. Not strictly needed, but
6564 * doesn't hurt to flag it as closing.
6566 fsp->closing = true;
6568 if (fsp->num_aio_requests > 0) {
6570 * Now wait until all aio requests on this fsp are
6573 * We don't set a callback, as we just want to block the
6574 * wait queue and the talloc_free() of fsp->aio_request
6575 * will remove the item from the wait queue.
6577 subreq = tevent_queue_wait_send(fsp->aio_requests,
6578 conn->sconn->ev_ctx,
6580 if (tevent_req_nomem(subreq, req)) {
6588 * Now we add our own waiter to the end of the queue,
6589 * this way we get notified when all pending requests are finished
6590 * and reply to the outstanding SMB1 request.
6592 subreq = tevent_queue_wait_send(state,
6593 conn->sconn->ev_ctx,
6595 if (tevent_req_nomem(subreq, req)) {
6601 * We're really going async - move the SMB1 request from
6602 * a talloc stackframe above us to the sconn talloc-context.
6603 * We need this to stick around until the wait_done
6604 * callback is invoked.
6606 smb1req = talloc_move(smb1req->sconn, &smb1req);
6608 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6613 static void reply_tdis_wait_done(struct tevent_req *subreq)
6615 struct tevent_req *req = tevent_req_callback_data(
6616 subreq, struct tevent_req);
6618 tevent_queue_wait_recv(subreq);
6619 TALLOC_FREE(subreq);
6620 tevent_req_done(req);
6623 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6625 return tevent_req_simple_recv_ntstatus(req);
6628 static void reply_tdis_done(struct tevent_req *req)
6630 struct smb_request *smb1req = tevent_req_callback_data(
6631 req, struct smb_request);
6633 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6637 * Take the profile charge here. Not strictly
6638 * correct but better than the other SMB1 async
6639 * code that double-charges at the moment.
6641 START_PROFILE(SMBtdis);
6643 status = reply_tdis_recv(req);
6645 if (!NT_STATUS_IS_OK(status)) {
6646 TALLOC_FREE(smb1req);
6647 END_PROFILE(SMBtdis);
6648 exit_server(__location__ ": reply_tdis_recv failed");
6653 * As we've been awoken, we may have changed
6654 * directory in the meantime.
6655 * reply_tdis() has the DO_CHDIR flag set.
6657 ok = chdir_current_service(smb1req->conn);
6659 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6660 smb_request_done(smb1req);
6661 END_PROFILE(SMBtdis);
6664 status = smbXsrv_tcon_disconnect(tcon,
6666 if (!NT_STATUS_IS_OK(status)) {
6667 TALLOC_FREE(smb1req);
6668 END_PROFILE(SMBtdis);
6669 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6673 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6674 smb1req->conn = NULL;
6678 reply_outbuf(smb1req, 0, 0);
6680 * The following call is needed to push the
6681 * reply data back out the socket after async
6682 * return. Plus it frees smb1req.
6684 smb_request_done(smb1req);
6685 END_PROFILE(SMBtdis);
6688 /****************************************************************************
6690 conn POINTER CAN BE NULL HERE !
6691 ****************************************************************************/
6693 void reply_echo(struct smb_request *req)
6695 connection_struct *conn = req->conn;
6696 struct smb_perfcount_data local_pcd;
6697 struct smb_perfcount_data *cur_pcd;
6701 START_PROFILE(SMBecho);
6703 smb_init_perfcount_data(&local_pcd);
6706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6707 END_PROFILE(SMBecho);
6711 smb_reverb = SVAL(req->vwv+0, 0);
6713 reply_outbuf(req, 1, req->buflen);
6715 /* copy any incoming data back out */
6716 if (req->buflen > 0) {
6717 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6720 if (smb_reverb > 100) {
6721 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6725 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6727 /* this makes sure we catch the request pcd */
6728 if (seq_num == smb_reverb) {
6729 cur_pcd = &req->pcd;
6731 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6732 cur_pcd = &local_pcd;
6735 SSVAL(req->outbuf,smb_vwv0,seq_num);
6737 show_msg((char *)req->outbuf);
6738 if (!srv_send_smb(req->xconn,
6739 (char *)req->outbuf,
6740 true, req->seqnum+1,
6741 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6743 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6746 DEBUG(3,("echo %d times\n", smb_reverb));
6748 TALLOC_FREE(req->outbuf);
6750 END_PROFILE(SMBecho);
6754 /****************************************************************************
6755 Reply to a printopen.
6756 ****************************************************************************/
6758 void reply_printopen(struct smb_request *req)
6760 connection_struct *conn = req->conn;
6764 START_PROFILE(SMBsplopen);
6767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6768 END_PROFILE(SMBsplopen);
6772 if (!CAN_PRINT(conn)) {
6773 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6774 END_PROFILE(SMBsplopen);
6778 status = file_new(req, conn, &fsp);
6779 if(!NT_STATUS_IS_OK(status)) {
6780 reply_nterror(req, status);
6781 END_PROFILE(SMBsplopen);
6785 /* Open for exclusive use, write only. */
6786 status = print_spool_open(fsp, NULL, req->vuid);
6788 if (!NT_STATUS_IS_OK(status)) {
6789 file_free(req, fsp);
6790 reply_nterror(req, status);
6791 END_PROFILE(SMBsplopen);
6795 reply_outbuf(req, 1, 0);
6796 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6798 DEBUG(3,("openprint fd=%d %s\n",
6799 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6801 END_PROFILE(SMBsplopen);
6805 /****************************************************************************
6806 Reply to a printclose.
6807 ****************************************************************************/
6809 void reply_printclose(struct smb_request *req)
6811 connection_struct *conn = req->conn;
6815 START_PROFILE(SMBsplclose);
6818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6819 END_PROFILE(SMBsplclose);
6823 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6825 if (!check_fsp(conn, req, fsp)) {
6826 END_PROFILE(SMBsplclose);
6830 if (!CAN_PRINT(conn)) {
6831 reply_force_doserror(req, ERRSRV, ERRerror);
6832 END_PROFILE(SMBsplclose);
6836 DEBUG(3,("printclose fd=%d %s\n",
6837 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6839 status = close_file(req, fsp, NORMAL_CLOSE);
6841 if(!NT_STATUS_IS_OK(status)) {
6842 reply_nterror(req, status);
6843 END_PROFILE(SMBsplclose);
6847 reply_outbuf(req, 0, 0);
6849 END_PROFILE(SMBsplclose);
6853 /****************************************************************************
6854 Reply to a printqueue.
6855 ****************************************************************************/
6857 void reply_printqueue(struct smb_request *req)
6859 const struct loadparm_substitution *lp_sub =
6860 loadparm_s3_global_substitution();
6861 connection_struct *conn = req->conn;
6865 START_PROFILE(SMBsplretq);
6868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6869 END_PROFILE(SMBsplretq);
6873 max_count = SVAL(req->vwv+0, 0);
6874 start_index = SVAL(req->vwv+1, 0);
6876 /* we used to allow the client to get the cnum wrong, but that
6877 is really quite gross and only worked when there was only
6878 one printer - I think we should now only accept it if they
6879 get it right (tridge) */
6880 if (!CAN_PRINT(conn)) {
6881 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6882 END_PROFILE(SMBsplretq);
6886 reply_outbuf(req, 2, 3);
6887 SSVAL(req->outbuf,smb_vwv0,0);
6888 SSVAL(req->outbuf,smb_vwv1,0);
6889 SCVAL(smb_buf(req->outbuf),0,1);
6890 SSVAL(smb_buf(req->outbuf),1,0);
6892 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6893 start_index, max_count));
6896 TALLOC_CTX *mem_ctx = talloc_tos();
6899 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6900 struct rpc_pipe_client *cli = NULL;
6901 struct dcerpc_binding_handle *b = NULL;
6902 struct policy_handle handle;
6903 struct spoolss_DevmodeContainer devmode_ctr;
6904 union spoolss_JobInfo *info;
6906 uint32_t num_to_get;
6910 ZERO_STRUCT(handle);
6912 status = rpc_pipe_open_interface(mem_ctx,
6915 conn->sconn->remote_address,
6916 conn->sconn->local_address,
6917 conn->sconn->msg_ctx,
6919 if (!NT_STATUS_IS_OK(status)) {
6920 DEBUG(0, ("reply_printqueue: "
6921 "could not connect to spoolss: %s\n",
6922 nt_errstr(status)));
6923 reply_nterror(req, status);
6926 b = cli->binding_handle;
6928 ZERO_STRUCT(devmode_ctr);
6930 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6933 SEC_FLAG_MAXIMUM_ALLOWED,
6936 if (!NT_STATUS_IS_OK(status)) {
6937 reply_nterror(req, status);
6940 if (!W_ERROR_IS_OK(werr)) {
6941 reply_nterror(req, werror_to_ntstatus(werr));
6945 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6953 if (!W_ERROR_IS_OK(werr)) {
6954 reply_nterror(req, werror_to_ntstatus(werr));
6958 if (max_count > 0) {
6959 first = start_index;
6961 first = start_index + max_count + 1;
6964 if (first >= count) {
6967 num_to_get = first + MIN(ABS(max_count), count - first);
6970 for (i = first; i < num_to_get; i++) {
6973 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6976 uint16_t qrapjobid = pjobid_to_rap(sharename,
6977 info[i].info2.job_id);
6979 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6985 srv_put_dos_date2(p, 0, qtime);
6986 SCVAL(p, 4, qstatus);
6987 SSVAL(p, 5, qrapjobid);
6988 SIVAL(p, 7, info[i].info2.size);
6990 status = srvstr_push(blob, req->flags2, p+12,
6991 info[i].info2.notify_name, 16, STR_ASCII, &len);
6992 if (!NT_STATUS_IS_OK(status)) {
6993 reply_nterror(req, status);
6996 if (message_push_blob(
6999 blob, sizeof(blob))) == -1) {
7000 reply_nterror(req, NT_STATUS_NO_MEMORY);
7006 SSVAL(req->outbuf,smb_vwv0,count);
7007 SSVAL(req->outbuf,smb_vwv1,
7008 (max_count>0?first+count:first-1));
7009 SCVAL(smb_buf(req->outbuf),0,1);
7010 SSVAL(smb_buf(req->outbuf),1,28*count);
7014 DEBUG(3, ("%u entries returned in queue\n",
7018 if (b && is_valid_policy_hnd(&handle)) {
7019 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
7024 END_PROFILE(SMBsplretq);
7028 /****************************************************************************
7029 Reply to a printwrite.
7030 ****************************************************************************/
7032 void reply_printwrite(struct smb_request *req)
7034 connection_struct *conn = req->conn;
7039 START_PROFILE(SMBsplwr);
7042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7043 END_PROFILE(SMBsplwr);
7047 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7049 if (!check_fsp(conn, req, fsp)) {
7050 END_PROFILE(SMBsplwr);
7054 if (!fsp->print_file) {
7055 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7056 END_PROFILE(SMBsplwr);
7060 if (!CHECK_WRITE(fsp)) {
7061 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7062 END_PROFILE(SMBsplwr);
7066 numtowrite = SVAL(req->buf, 1);
7069 * This already protects us against CVE-2017-12163.
7071 if (req->buflen < numtowrite + 3) {
7072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7073 END_PROFILE(SMBsplwr);
7077 data = (const char *)req->buf + 3;
7079 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7080 reply_nterror(req, map_nt_error_from_unix(errno));
7081 END_PROFILE(SMBsplwr);
7085 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7087 END_PROFILE(SMBsplwr);
7091 /****************************************************************************
7093 ****************************************************************************/
7095 void reply_mkdir(struct smb_request *req)
7097 connection_struct *conn = req->conn;
7098 struct smb_filename *smb_dname = NULL;
7099 char *directory = NULL;
7102 TALLOC_CTX *ctx = talloc_tos();
7104 START_PROFILE(SMBmkdir);
7106 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7107 STR_TERMINATE, &status);
7108 if (!NT_STATUS_IS_OK(status)) {
7109 reply_nterror(req, status);
7113 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7114 status = filename_convert(ctx, conn,
7120 if (!NT_STATUS_IS_OK(status)) {
7121 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7122 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7123 ERRSRV, ERRbadpath);
7126 reply_nterror(req, status);
7130 status = create_directory(conn, req, smb_dname);
7132 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7134 if (!NT_STATUS_IS_OK(status)) {
7136 if (!use_nt_status()
7137 && NT_STATUS_EQUAL(status,
7138 NT_STATUS_OBJECT_NAME_COLLISION)) {
7140 * Yes, in the DOS error code case we get a
7141 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7142 * samba4 torture test.
7144 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7147 reply_nterror(req, status);
7151 reply_outbuf(req, 0, 0);
7153 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7155 TALLOC_FREE(smb_dname);
7156 END_PROFILE(SMBmkdir);
7160 /****************************************************************************
7162 ****************************************************************************/
7164 void reply_rmdir(struct smb_request *req)
7166 connection_struct *conn = req->conn;
7167 struct smb_filename *smb_dname = NULL;
7168 char *directory = NULL;
7170 TALLOC_CTX *ctx = talloc_tos();
7171 files_struct *fsp = NULL;
7173 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7175 START_PROFILE(SMBrmdir);
7177 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7178 STR_TERMINATE, &status);
7179 if (!NT_STATUS_IS_OK(status)) {
7180 reply_nterror(req, status);
7184 status = filename_convert(ctx, conn,
7190 if (!NT_STATUS_IS_OK(status)) {
7191 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7192 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7193 ERRSRV, ERRbadpath);
7196 reply_nterror(req, status);
7200 if (is_ntfs_stream_smb_fname(smb_dname)) {
7201 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7205 status = SMB_VFS_CREATE_FILE(
7208 0, /* root_dir_fid */
7209 smb_dname, /* fname */
7210 DELETE_ACCESS, /* access_mask */
7211 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7213 FILE_OPEN, /* create_disposition*/
7214 FILE_DIRECTORY_FILE, /* create_options */
7215 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7216 0, /* oplock_request */
7218 0, /* allocation_size */
7219 0, /* private_flags */
7224 NULL, NULL); /* create context */
7226 if (!NT_STATUS_IS_OK(status)) {
7227 if (open_was_deferred(req->xconn, req->mid)) {
7228 /* We have re-scheduled this call. */
7231 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7232 bool ok = defer_smb1_sharing_violation(req);
7237 reply_nterror(req, status);
7241 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7242 if (!NT_STATUS_IS_OK(status)) {
7243 close_file(req, fsp, ERROR_CLOSE);
7244 reply_nterror(req, status);
7248 if (!set_delete_on_close(fsp, true,
7249 conn->session_info->security_token,
7250 conn->session_info->unix_token)) {
7251 close_file(req, fsp, ERROR_CLOSE);
7252 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7256 status = close_file(req, fsp, NORMAL_CLOSE);
7257 if (!NT_STATUS_IS_OK(status)) {
7258 reply_nterror(req, status);
7260 reply_outbuf(req, 0, 0);
7263 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7265 TALLOC_FREE(smb_dname);
7266 END_PROFILE(SMBrmdir);
7270 /*******************************************************************
7271 Resolve wildcards in a filename rename.
7272 ********************************************************************/
7274 static bool resolve_wildcards(TALLOC_CTX *ctx,
7279 char *name2_copy = NULL;
7284 char *p,*p2, *pname1, *pname2;
7286 name2_copy = talloc_strdup(ctx, name2);
7291 pname1 = strrchr_m(name1,'/');
7292 pname2 = strrchr_m(name2_copy,'/');
7294 if (!pname1 || !pname2) {
7298 /* Truncate the copy of name2 at the last '/' */
7301 /* Now go past the '/' */
7305 root1 = talloc_strdup(ctx, pname1);
7306 root2 = talloc_strdup(ctx, pname2);
7308 if (!root1 || !root2) {
7312 p = strrchr_m(root1,'.');
7315 ext1 = talloc_strdup(ctx, p+1);
7317 ext1 = talloc_strdup(ctx, "");
7319 p = strrchr_m(root2,'.');
7322 ext2 = talloc_strdup(ctx, p+1);
7324 ext2 = talloc_strdup(ctx, "");
7327 if (!ext1 || !ext2) {
7335 /* Hmmm. Should this be mb-aware ? */
7338 } else if (*p2 == '*') {
7340 root2 = talloc_asprintf(ctx, "%s%s",
7359 /* Hmmm. Should this be mb-aware ? */
7362 } else if (*p2 == '*') {
7364 ext2 = talloc_asprintf(ctx, "%s%s",
7380 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7385 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7397 /****************************************************************************
7398 Ensure open files have their names updated. Updated to notify other smbd's
7400 ****************************************************************************/
7402 static void rename_open_files(connection_struct *conn,
7403 struct share_mode_lock *lck,
7405 uint32_t orig_name_hash,
7406 const struct smb_filename *smb_fname_dst)
7409 bool did_rename = False;
7411 uint32_t new_name_hash = 0;
7413 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7414 fsp = file_find_di_next(fsp)) {
7415 struct file_id_buf idbuf;
7416 /* fsp_name is a relative path under the fsp. To change this for other
7417 sharepaths we need to manipulate relative paths. */
7418 /* TODO - create the absolute path and manipulate the newname
7419 relative to the sharepath. */
7420 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7423 if (fsp->name_hash != orig_name_hash) {
7426 DBG_DEBUG("renaming file %s "
7427 "(file_id %s) from %s -> %s\n",
7429 file_id_str_buf(fsp->file_id, &idbuf),
7431 smb_fname_str_dbg(smb_fname_dst));
7433 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7434 if (NT_STATUS_IS_OK(status)) {
7436 new_name_hash = fsp->name_hash;
7441 struct file_id_buf idbuf;
7442 DBG_DEBUG("no open files on file_id %s "
7444 file_id_str_buf(id, &idbuf),
7445 smb_fname_str_dbg(smb_fname_dst));
7448 /* Send messages to all smbd's (not ourself) that the name has changed. */
7449 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7450 orig_name_hash, new_name_hash,
7455 /****************************************************************************
7456 We need to check if the source path is a parent directory of the destination
7457 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7458 refuse the rename with a sharing violation. Under UNIX the above call can
7459 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7460 probably need to check that the client is a Windows one before disallowing
7461 this as a UNIX client (one with UNIX extensions) can know the source is a
7462 symlink and make this decision intelligently. Found by an excellent bug
7463 report from <AndyLiebman@aol.com>.
7464 ****************************************************************************/
7466 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7467 const struct smb_filename *smb_fname_dst)
7469 const char *psrc = smb_fname_src->base_name;
7470 const char *pdst = smb_fname_dst->base_name;
7473 if (psrc[0] == '.' && psrc[1] == '/') {
7476 if (pdst[0] == '.' && pdst[1] == '/') {
7479 if ((slen = strlen(psrc)) > strlen(pdst)) {
7482 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7486 * Do the notify calls from a rename
7489 static void notify_rename(connection_struct *conn, bool is_dir,
7490 const struct smb_filename *smb_fname_src,
7491 const struct smb_filename *smb_fname_dst)
7493 char *parent_dir_src = NULL;
7494 char *parent_dir_dst = NULL;
7497 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7498 : FILE_NOTIFY_CHANGE_FILE_NAME;
7500 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7501 &parent_dir_src, NULL) ||
7502 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7503 &parent_dir_dst, NULL)) {
7507 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7508 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7509 smb_fname_src->base_name);
7510 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7511 smb_fname_dst->base_name);
7514 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7515 smb_fname_src->base_name);
7516 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7517 smb_fname_dst->base_name);
7520 /* this is a strange one. w2k3 gives an additional event for
7521 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7522 files, but not directories */
7524 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7525 FILE_NOTIFY_CHANGE_ATTRIBUTES
7526 |FILE_NOTIFY_CHANGE_CREATION,
7527 smb_fname_dst->base_name);
7530 TALLOC_FREE(parent_dir_src);
7531 TALLOC_FREE(parent_dir_dst);
7534 /****************************************************************************
7535 Returns an error if the parent directory for a filename is open in an
7537 ****************************************************************************/
7539 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7540 const struct smb_filename *smb_fname_dst_in)
7542 char *parent_dir = NULL;
7543 struct smb_filename smb_fname_parent;
7545 files_struct *fsp = NULL;
7548 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
7549 &parent_dir, NULL)) {
7550 return NT_STATUS_NO_MEMORY;
7552 ZERO_STRUCT(smb_fname_parent);
7553 smb_fname_parent.base_name = parent_dir;
7555 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
7557 return map_nt_error_from_unix(errno);
7561 * We're only checking on this smbd here, mostly good
7562 * enough.. and will pass tests.
7565 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
7566 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7567 fsp = file_find_di_next(fsp)) {
7568 if (fsp->access_mask & DELETE_ACCESS) {
7569 return NT_STATUS_SHARING_VIOLATION;
7572 return NT_STATUS_OK;
7575 /****************************************************************************
7576 Rename an open file - given an fsp.
7577 ****************************************************************************/
7579 NTSTATUS rename_internals_fsp(connection_struct *conn,
7581 const struct smb_filename *smb_fname_dst_in,
7582 const char *dst_original_lcomp,
7584 bool replace_if_exists)
7586 TALLOC_CTX *ctx = talloc_tos();
7587 struct smb_filename *smb_fname_dst = NULL;
7588 NTSTATUS status = NT_STATUS_OK;
7589 struct share_mode_lock *lck = NULL;
7590 uint32_t access_mask = SEC_DIR_ADD_FILE;
7591 bool dst_exists, old_is_stream, new_is_stream;
7594 status = check_name(conn, smb_fname_dst_in);
7595 if (!NT_STATUS_IS_OK(status)) {
7599 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7600 if (!NT_STATUS_IS_OK(status)) {
7604 if (file_has_open_streams(fsp)) {
7605 return NT_STATUS_ACCESS_DENIED;
7608 /* Make a copy of the dst smb_fname structs */
7610 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7611 if (smb_fname_dst == NULL) {
7612 status = NT_STATUS_NO_MEMORY;
7617 * Check for special case with case preserving and not
7618 * case sensitive. If the new last component differs from the original
7619 * last component only by case, then we should allow
7620 * the rename (user is trying to change the case of the
7623 if (!conn->case_sensitive && conn->case_preserve &&
7624 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7625 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7626 char *fname_dst_parent = NULL;
7627 const char *fname_dst_lcomp = NULL;
7628 char *orig_lcomp_path = NULL;
7629 char *orig_lcomp_stream = NULL;
7633 * Split off the last component of the processed
7634 * destination name. We will compare this to
7635 * the split components of dst_original_lcomp.
7637 if (!parent_dirname(ctx,
7638 smb_fname_dst->base_name,
7640 &fname_dst_lcomp)) {
7641 status = NT_STATUS_NO_MEMORY;
7646 * The dst_original_lcomp component contains
7647 * the last_component of the path + stream
7648 * name (if a stream exists).
7650 * Split off the stream name so we
7651 * can check them separately.
7654 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7655 /* POSIX - no stream component. */
7656 orig_lcomp_path = talloc_strdup(ctx,
7657 dst_original_lcomp);
7658 if (orig_lcomp_path == NULL) {
7662 ok = split_stream_filename(ctx,
7665 &orig_lcomp_stream);
7669 TALLOC_FREE(fname_dst_parent);
7670 status = NT_STATUS_NO_MEMORY;
7674 /* If the base names only differ by case, use original. */
7675 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7678 * Replace the modified last component with the
7681 if (!ISDOT(fname_dst_parent)) {
7682 tmp = talloc_asprintf(smb_fname_dst,
7687 tmp = talloc_strdup(smb_fname_dst,
7691 status = NT_STATUS_NO_MEMORY;
7692 TALLOC_FREE(fname_dst_parent);
7693 TALLOC_FREE(orig_lcomp_path);
7694 TALLOC_FREE(orig_lcomp_stream);
7697 TALLOC_FREE(smb_fname_dst->base_name);
7698 smb_fname_dst->base_name = tmp;
7701 /* If the stream_names only differ by case, use original. */
7702 if(!strcsequal(smb_fname_dst->stream_name,
7703 orig_lcomp_stream)) {
7704 /* Use the original stream. */
7705 char *tmp = talloc_strdup(smb_fname_dst,
7708 status = NT_STATUS_NO_MEMORY;
7709 TALLOC_FREE(fname_dst_parent);
7710 TALLOC_FREE(orig_lcomp_path);
7711 TALLOC_FREE(orig_lcomp_stream);
7714 TALLOC_FREE(smb_fname_dst->stream_name);
7715 smb_fname_dst->stream_name = tmp;
7717 TALLOC_FREE(fname_dst_parent);
7718 TALLOC_FREE(orig_lcomp_path);
7719 TALLOC_FREE(orig_lcomp_stream);
7723 * If the src and dest names are identical - including case,
7724 * don't do the rename, just return success.
7727 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7728 strcsequal(fsp->fsp_name->stream_name,
7729 smb_fname_dst->stream_name)) {
7730 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7731 "- returning success\n",
7732 smb_fname_str_dbg(smb_fname_dst)));
7733 status = NT_STATUS_OK;
7737 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7738 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7740 /* Return the correct error code if both names aren't streams. */
7741 if (!old_is_stream && new_is_stream) {
7742 status = NT_STATUS_OBJECT_NAME_INVALID;
7746 if (old_is_stream && !new_is_stream) {
7747 status = NT_STATUS_INVALID_PARAMETER;
7751 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7753 if(!replace_if_exists && dst_exists) {
7754 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7755 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7756 smb_fname_str_dbg(smb_fname_dst)));
7757 status = NT_STATUS_OBJECT_NAME_COLLISION;
7762 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7763 &smb_fname_dst->st);
7764 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7766 /* The file can be open when renaming a stream */
7767 if (dst_fsp && !new_is_stream) {
7768 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7769 status = NT_STATUS_ACCESS_DENIED;
7774 /* Ensure we have a valid stat struct for the source. */
7775 status = vfs_stat_fsp(fsp);
7776 if (!NT_STATUS_IS_OK(status)) {
7780 status = can_rename(conn, fsp, attrs);
7782 if (!NT_STATUS_IS_OK(status)) {
7783 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7784 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7785 smb_fname_str_dbg(smb_fname_dst)));
7786 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7787 status = NT_STATUS_ACCESS_DENIED;
7791 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7792 status = NT_STATUS_ACCESS_DENIED;
7796 /* Do we have rights to move into the destination ? */
7797 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7798 /* We're moving a directory. */
7799 access_mask = SEC_DIR_ADD_SUBDIR;
7801 status = check_parent_access(conn,
7804 if (!NT_STATUS_IS_OK(status)) {
7805 DBG_INFO("check_parent_access on "
7806 "dst %s returned %s\n",
7807 smb_fname_str_dbg(smb_fname_dst),
7812 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7815 * We have the file open ourselves, so not being able to get the
7816 * corresponding share mode lock is a fatal error.
7819 SMB_ASSERT(lck != NULL);
7821 ret = SMB_VFS_RENAMEAT(conn,
7827 uint32_t create_options = fsp->fh->private_options;
7829 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7830 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7831 smb_fname_str_dbg(smb_fname_dst)));
7833 if (!fsp->is_directory &&
7834 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7835 (lp_map_archive(SNUM(conn)) ||
7836 lp_store_dos_attributes(SNUM(conn)))) {
7837 /* We must set the archive bit on the newly
7839 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7840 uint32_t old_dosmode = dos_mode(conn,
7842 file_set_dosmode(conn,
7844 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7855 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7859 * A rename acts as a new file create w.r.t. allowing an initial delete
7860 * on close, probably because in Windows there is a new handle to the
7861 * new file. If initial delete on close was requested but not
7862 * originally set, we need to set it here. This is probably not 100% correct,
7863 * but will work for the CIFSFS client which in non-posix mode
7864 * depends on these semantics. JRA.
7867 if (create_options & FILE_DELETE_ON_CLOSE) {
7868 status = can_set_delete_on_close(fsp, 0);
7870 if (NT_STATUS_IS_OK(status)) {
7871 /* Note that here we set the *initial* delete on close flag,
7872 * not the regular one. The magic gets handled in close. */
7873 fsp->initial_delete_on_close = True;
7877 status = NT_STATUS_OK;
7883 if (errno == ENOTDIR || errno == EISDIR) {
7884 status = NT_STATUS_OBJECT_NAME_COLLISION;
7886 status = map_nt_error_from_unix(errno);
7889 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7890 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7891 smb_fname_str_dbg(smb_fname_dst)));
7894 TALLOC_FREE(smb_fname_dst);
7899 /****************************************************************************
7900 The guts of the rename command, split out so it may be called by the NT SMB
7902 ****************************************************************************/
7904 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7905 connection_struct *conn,
7906 struct smb_request *req,
7907 struct smb_filename *smb_fname_src,
7908 struct smb_filename *smb_fname_dst,
7909 const char *dst_original_lcomp,
7911 bool replace_if_exists,
7914 uint32_t access_mask)
7916 char *fname_src_dir = NULL;
7917 struct smb_filename *smb_fname_src_dir = NULL;
7918 char *fname_src_mask = NULL;
7920 NTSTATUS status = NT_STATUS_OK;
7921 struct smb_Dir *dir_hnd = NULL;
7922 const char *dname = NULL;
7923 char *talloced = NULL;
7925 int create_options = 0;
7926 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7927 struct smb2_create_blobs *posx = NULL;
7931 * Split the old name into directory and last component
7932 * strings. Note that unix_convert may have stripped off a
7933 * leading ./ from both name and newname if the rename is
7934 * at the root of the share. We need to make sure either both
7935 * name and newname contain a / character or neither of them do
7936 * as this is checked in resolve_wildcards().
7939 /* Split up the directory from the filename/mask. */
7940 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7941 &fname_src_dir, &fname_src_mask);
7942 if (!NT_STATUS_IS_OK(status)) {
7943 status = NT_STATUS_NO_MEMORY;
7948 * We should only check the mangled cache
7949 * here if unix_convert failed. This means
7950 * that the path in 'mask' doesn't exist
7951 * on the file system and so we need to look
7952 * for a possible mangle. This patch from
7953 * Tine Smukavec <valentin.smukavec@hermes.si>.
7956 if (!VALID_STAT(smb_fname_src->st) &&
7957 mangle_is_mangled(fname_src_mask, conn->params)) {
7958 char *new_mask = NULL;
7959 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7962 TALLOC_FREE(fname_src_mask);
7963 fname_src_mask = new_mask;
7967 if (posix_pathnames) {
7968 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7969 if (!NT_STATUS_IS_OK(status)) {
7970 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7976 if (!src_has_wild) {
7980 * Only one file needs to be renamed. Append the mask back
7981 * onto the directory.
7983 TALLOC_FREE(smb_fname_src->base_name);
7984 if (ISDOT(fname_src_dir)) {
7985 /* Ensure we use canonical names on open. */
7986 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7990 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7995 if (!smb_fname_src->base_name) {
7996 status = NT_STATUS_NO_MEMORY;
8000 DEBUG(3, ("rename_internals: case_sensitive = %d, "
8001 "case_preserve = %d, short case preserve = %d, "
8002 "directory = %s, newname = %s, "
8003 "last_component_dest = %s\n",
8004 conn->case_sensitive, conn->case_preserve,
8005 conn->short_case_preserve,
8006 smb_fname_str_dbg(smb_fname_src),
8007 smb_fname_str_dbg(smb_fname_dst),
8008 dst_original_lcomp));
8010 /* The dest name still may have wildcards. */
8011 if (dest_has_wild) {
8012 char *fname_dst_mod = NULL;
8013 if (!resolve_wildcards(smb_fname_dst,
8014 smb_fname_src->base_name,
8015 smb_fname_dst->base_name,
8017 DEBUG(6, ("rename_internals: resolve_wildcards "
8019 smb_fname_src->base_name,
8020 smb_fname_dst->base_name));
8021 status = NT_STATUS_NO_MEMORY;
8024 TALLOC_FREE(smb_fname_dst->base_name);
8025 smb_fname_dst->base_name = fname_dst_mod;
8028 ZERO_STRUCT(smb_fname_src->st);
8029 if (posix_pathnames) {
8030 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8032 rc = SMB_VFS_STAT(conn, smb_fname_src);
8035 status = map_nt_error_from_unix_common(errno);
8039 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8040 create_options |= FILE_DIRECTORY_FILE;
8043 status = SMB_VFS_CREATE_FILE(
8046 0, /* root_dir_fid */
8047 smb_fname_src, /* fname */
8048 access_mask, /* access_mask */
8049 (FILE_SHARE_READ | /* share_access */
8051 FILE_OPEN, /* create_disposition*/
8052 create_options, /* create_options */
8053 0, /* file_attributes */
8054 0, /* oplock_request */
8056 0, /* allocation_size */
8057 0, /* private_flags */
8062 posx, /* in_context_blobs */
8063 NULL); /* out_context_blobs */
8065 if (!NT_STATUS_IS_OK(status)) {
8066 DEBUG(3, ("Could not open rename source %s: %s\n",
8067 smb_fname_str_dbg(smb_fname_src),
8068 nt_errstr(status)));
8072 status = rename_internals_fsp(conn,
8079 close_file(req, fsp, NORMAL_CLOSE);
8081 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8082 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8083 smb_fname_str_dbg(smb_fname_dst)));
8089 * Wildcards - process each file that matches.
8091 if (strequal(fname_src_mask, "????????.???")) {
8092 TALLOC_FREE(fname_src_mask);
8093 fname_src_mask = talloc_strdup(ctx, "*");
8094 if (!fname_src_mask) {
8095 status = NT_STATUS_NO_MEMORY;
8100 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8104 smb_fname_src->flags);
8105 if (smb_fname_src_dir == NULL) {
8106 status = NT_STATUS_NO_MEMORY;
8110 status = check_name(conn, smb_fname_src_dir);
8111 if (!NT_STATUS_IS_OK(status)) {
8115 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8117 if (dir_hnd == NULL) {
8118 status = map_nt_error_from_unix(errno);
8122 status = NT_STATUS_NO_SUCH_FILE;
8124 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8125 * - gentest fix. JRA
8128 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8130 files_struct *fsp = NULL;
8131 char *destname = NULL;
8132 bool sysdir_entry = False;
8134 /* Quick check for "." and ".." */
8135 if (ISDOT(dname) || ISDOTDOT(dname)) {
8136 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8137 sysdir_entry = True;
8139 TALLOC_FREE(talloced);
8144 if (!is_visible_file(conn, fname_src_dir, dname,
8145 &smb_fname_src->st, false)) {
8146 TALLOC_FREE(talloced);
8150 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8151 TALLOC_FREE(talloced);
8156 status = NT_STATUS_OBJECT_NAME_INVALID;
8160 TALLOC_FREE(smb_fname_src->base_name);
8161 if (ISDOT(fname_src_dir)) {
8162 /* Ensure we use canonical names on open. */
8163 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8167 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8172 if (!smb_fname_src->base_name) {
8173 status = NT_STATUS_NO_MEMORY;
8177 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8178 smb_fname_dst->base_name,
8180 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8181 smb_fname_src->base_name, destname));
8182 TALLOC_FREE(talloced);
8186 status = NT_STATUS_NO_MEMORY;
8190 TALLOC_FREE(smb_fname_dst->base_name);
8191 smb_fname_dst->base_name = destname;
8193 ZERO_STRUCT(smb_fname_src->st);
8194 if (posix_pathnames) {
8195 SMB_VFS_LSTAT(conn, smb_fname_src);
8197 SMB_VFS_STAT(conn, smb_fname_src);
8202 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8203 create_options |= FILE_DIRECTORY_FILE;
8206 status = SMB_VFS_CREATE_FILE(
8209 0, /* root_dir_fid */
8210 smb_fname_src, /* fname */
8211 access_mask, /* access_mask */
8212 (FILE_SHARE_READ | /* share_access */
8214 FILE_OPEN, /* create_disposition*/
8215 create_options, /* create_options */
8216 0, /* file_attributes */
8217 0, /* oplock_request */
8219 0, /* allocation_size */
8220 0, /* private_flags */
8225 posx, /* in_context_blobs */
8226 NULL); /* out_context_blobs */
8228 if (!NT_STATUS_IS_OK(status)) {
8229 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8230 "returned %s rename %s -> %s\n",
8232 smb_fname_str_dbg(smb_fname_src),
8233 smb_fname_str_dbg(smb_fname_dst)));
8237 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8238 if (dst_original_lcomp == NULL) {
8239 status = NT_STATUS_NO_MEMORY;
8243 status = rename_internals_fsp(conn,
8250 close_file(req, fsp, NORMAL_CLOSE);
8252 if (!NT_STATUS_IS_OK(status)) {
8253 DEBUG(3, ("rename_internals_fsp returned %s for "
8254 "rename %s -> %s\n", nt_errstr(status),
8255 smb_fname_str_dbg(smb_fname_src),
8256 smb_fname_str_dbg(smb_fname_dst)));
8262 DEBUG(3,("rename_internals: doing rename on %s -> "
8263 "%s\n", smb_fname_str_dbg(smb_fname_src),
8264 smb_fname_str_dbg(smb_fname_src)));
8265 TALLOC_FREE(talloced);
8267 TALLOC_FREE(dir_hnd);
8269 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8270 status = map_nt_error_from_unix(errno);
8275 TALLOC_FREE(talloced);
8276 TALLOC_FREE(smb_fname_src_dir);
8277 TALLOC_FREE(fname_src_dir);
8278 TALLOC_FREE(fname_src_mask);
8282 /****************************************************************************
8284 ****************************************************************************/
8286 void reply_mv(struct smb_request *req)
8288 connection_struct *conn = req->conn;
8290 char *newname = NULL;
8294 bool src_has_wcard = False;
8295 bool dest_has_wcard = False;
8296 TALLOC_CTX *ctx = talloc_tos();
8297 struct smb_filename *smb_fname_src = NULL;
8298 struct smb_filename *smb_fname_dst = NULL;
8299 const char *dst_original_lcomp = NULL;
8300 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8301 (req->posix_pathnames ?
8302 UCF_UNIX_NAME_LOOKUP :
8303 UCF_COND_ALLOW_WCARD_LCOMP);
8304 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8305 (req->posix_pathnames ?
8307 UCF_COND_ALLOW_WCARD_LCOMP);
8308 bool stream_rename = false;
8310 START_PROFILE(SMBmv);
8313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8317 attrs = SVAL(req->vwv+0, 0);
8319 p = (const char *)req->buf + 1;
8320 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
8321 &status, &src_has_wcard);
8322 if (!NT_STATUS_IS_OK(status)) {
8323 reply_nterror(req, status);
8327 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
8328 &status, &dest_has_wcard);
8329 if (!NT_STATUS_IS_OK(status)) {
8330 reply_nterror(req, status);
8334 if (!req->posix_pathnames) {
8335 /* The newname must begin with a ':' if the
8336 name contains a ':'. */
8337 if (strchr_m(name, ':')) {
8338 if (newname[0] != ':') {
8339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8342 stream_rename = true;
8346 status = filename_convert(ctx,
8354 if (!NT_STATUS_IS_OK(status)) {
8355 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8356 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8357 ERRSRV, ERRbadpath);
8360 reply_nterror(req, status);
8364 status = filename_convert(ctx,
8372 if (!NT_STATUS_IS_OK(status)) {
8373 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8374 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8375 ERRSRV, ERRbadpath);
8378 reply_nterror(req, status);
8382 /* Get the last component of the destination for rename_internals(). */
8383 dst_original_lcomp = get_original_lcomp(ctx,
8387 if (dst_original_lcomp == NULL) {
8388 reply_nterror(req, NT_STATUS_NO_MEMORY);
8392 if (stream_rename) {
8393 /* smb_fname_dst->base_name must be the same as
8394 smb_fname_src->base_name. */
8395 TALLOC_FREE(smb_fname_dst->base_name);
8396 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8397 smb_fname_src->base_name);
8398 if (!smb_fname_dst->base_name) {
8399 reply_nterror(req, NT_STATUS_NO_MEMORY);
8404 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8405 smb_fname_str_dbg(smb_fname_dst)));
8407 status = rename_internals(ctx,
8418 if (!NT_STATUS_IS_OK(status)) {
8419 if (open_was_deferred(req->xconn, req->mid)) {
8420 /* We have re-scheduled this call. */
8423 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8424 bool ok = defer_smb1_sharing_violation(req);
8429 reply_nterror(req, status);
8433 reply_outbuf(req, 0, 0);
8435 TALLOC_FREE(smb_fname_src);
8436 TALLOC_FREE(smb_fname_dst);
8441 /*******************************************************************
8442 Copy a file as part of a reply_copy.
8443 ******************************************************************/
8446 * TODO: check error codes on all callers
8449 NTSTATUS copy_file(TALLOC_CTX *ctx,
8450 connection_struct *conn,
8451 struct smb_filename *smb_fname_src,
8452 struct smb_filename *smb_fname_dst,
8455 bool target_is_directory)
8457 struct smb_filename *smb_fname_dst_tmp = NULL;
8459 files_struct *fsp1,*fsp2;
8461 uint32_t new_create_disposition;
8465 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8466 if (smb_fname_dst_tmp == NULL) {
8467 return NT_STATUS_NO_MEMORY;
8471 * If the target is a directory, extract the last component from the
8472 * src filename and append it to the dst filename
8474 if (target_is_directory) {
8477 /* dest/target can't be a stream if it's a directory. */
8478 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8480 p = strrchr_m(smb_fname_src->base_name,'/');
8484 p = smb_fname_src->base_name;
8486 smb_fname_dst_tmp->base_name =
8487 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8489 if (!smb_fname_dst_tmp->base_name) {
8490 status = NT_STATUS_NO_MEMORY;
8495 status = vfs_file_exist(conn, smb_fname_src);
8496 if (!NT_STATUS_IS_OK(status)) {
8500 if (!target_is_directory && count) {
8501 new_create_disposition = FILE_OPEN;
8503 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8506 &new_create_disposition,
8509 status = NT_STATUS_INVALID_PARAMETER;
8514 /* Open the src file for reading. */
8515 status = SMB_VFS_CREATE_FILE(
8518 0, /* root_dir_fid */
8519 smb_fname_src, /* fname */
8520 FILE_GENERIC_READ, /* access_mask */
8521 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8522 FILE_OPEN, /* create_disposition*/
8523 0, /* create_options */
8524 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8525 INTERNAL_OPEN_ONLY, /* oplock_request */
8527 0, /* allocation_size */
8528 0, /* private_flags */
8533 NULL, NULL); /* create context */
8535 if (!NT_STATUS_IS_OK(status)) {
8539 dosattrs = dos_mode(conn, smb_fname_src);
8541 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8542 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8545 /* Open the dst file for writing. */
8546 status = SMB_VFS_CREATE_FILE(
8549 0, /* root_dir_fid */
8550 smb_fname_dst, /* fname */
8551 FILE_GENERIC_WRITE, /* access_mask */
8552 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8553 new_create_disposition, /* create_disposition*/
8554 0, /* create_options */
8555 dosattrs, /* file_attributes */
8556 INTERNAL_OPEN_ONLY, /* oplock_request */
8558 0, /* allocation_size */
8559 0, /* private_flags */
8564 NULL, NULL); /* create context */
8566 if (!NT_STATUS_IS_OK(status)) {
8567 close_file(NULL, fsp1, ERROR_CLOSE);
8571 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8572 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8574 DEBUG(0, ("error - vfs lseek returned error %s\n",
8576 status = map_nt_error_from_unix(errno);
8577 close_file(NULL, fsp1, ERROR_CLOSE);
8578 close_file(NULL, fsp2, ERROR_CLOSE);
8583 /* Do the actual copy. */
8584 if (smb_fname_src->st.st_ex_size) {
8585 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8590 close_file(NULL, fsp1, NORMAL_CLOSE);
8592 /* Ensure the modtime is set correctly on the destination file. */
8593 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8596 * As we are opening fsp1 read-only we only expect
8597 * an error on close on fsp2 if we are out of space.
8598 * Thus we don't look at the error return from the
8601 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8603 if (!NT_STATUS_IS_OK(status)) {
8607 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8608 status = NT_STATUS_DISK_FULL;
8612 status = NT_STATUS_OK;
8615 TALLOC_FREE(smb_fname_dst_tmp);
8619 /****************************************************************************
8620 Reply to a file copy.
8621 ****************************************************************************/
8623 void reply_copy(struct smb_request *req)
8625 connection_struct *conn = req->conn;
8626 struct smb_filename *smb_fname_src = NULL;
8627 struct smb_filename *smb_fname_src_dir = NULL;
8628 struct smb_filename *smb_fname_dst = NULL;
8629 char *fname_src = NULL;
8630 char *fname_dst = NULL;
8631 char *fname_src_mask = NULL;
8632 char *fname_src_dir = NULL;
8635 int error = ERRnoaccess;
8639 bool target_is_directory=False;
8640 bool source_has_wild = False;
8641 bool dest_has_wild = False;
8643 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
8644 ucf_flags_from_smb_request(req);
8645 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
8646 ucf_flags_from_smb_request(req);
8647 TALLOC_CTX *ctx = talloc_tos();
8649 START_PROFILE(SMBcopy);
8652 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8656 tid2 = SVAL(req->vwv+0, 0);
8657 ofun = SVAL(req->vwv+1, 0);
8658 flags = SVAL(req->vwv+2, 0);
8660 p = (const char *)req->buf;
8661 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8662 &status, &source_has_wild);
8663 if (!NT_STATUS_IS_OK(status)) {
8664 reply_nterror(req, status);
8667 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8668 &status, &dest_has_wild);
8669 if (!NT_STATUS_IS_OK(status)) {
8670 reply_nterror(req, status);
8674 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8676 if (tid2 != conn->cnum) {
8677 /* can't currently handle inter share copies XXXX */
8678 DEBUG(3,("Rejecting inter-share copy\n"));
8679 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8683 status = filename_convert(ctx, conn,
8689 if (!NT_STATUS_IS_OK(status)) {
8690 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8691 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8692 ERRSRV, ERRbadpath);
8695 reply_nterror(req, status);
8699 status = filename_convert(ctx, conn,
8705 if (!NT_STATUS_IS_OK(status)) {
8706 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8707 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8708 ERRSRV, ERRbadpath);
8711 reply_nterror(req, status);
8715 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8717 if ((flags&1) && target_is_directory) {
8718 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8722 if ((flags&2) && !target_is_directory) {
8723 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8727 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8728 /* wants a tree copy! XXXX */
8729 DEBUG(3,("Rejecting tree copy\n"));
8730 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8734 /* Split up the directory from the filename/mask. */
8735 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8736 &fname_src_dir, &fname_src_mask);
8737 if (!NT_STATUS_IS_OK(status)) {
8738 reply_nterror(req, NT_STATUS_NO_MEMORY);
8743 * We should only check the mangled cache
8744 * here if unix_convert failed. This means
8745 * that the path in 'mask' doesn't exist
8746 * on the file system and so we need to look
8747 * for a possible mangle. This patch from
8748 * Tine Smukavec <valentin.smukavec@hermes.si>.
8750 if (!VALID_STAT(smb_fname_src->st) &&
8751 mangle_is_mangled(fname_src_mask, conn->params)) {
8752 char *new_mask = NULL;
8753 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8754 &new_mask, conn->params);
8756 /* Use demangled name if one was successfully found. */
8758 TALLOC_FREE(fname_src_mask);
8759 fname_src_mask = new_mask;
8763 if (!source_has_wild) {
8766 * Only one file needs to be copied. Append the mask back onto
8769 TALLOC_FREE(smb_fname_src->base_name);
8770 if (ISDOT(fname_src_dir)) {
8771 /* Ensure we use canonical names on open. */
8772 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8776 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8781 if (!smb_fname_src->base_name) {
8782 reply_nterror(req, NT_STATUS_NO_MEMORY);
8786 if (dest_has_wild) {
8787 char *fname_dst_mod = NULL;
8788 if (!resolve_wildcards(smb_fname_dst,
8789 smb_fname_src->base_name,
8790 smb_fname_dst->base_name,
8792 reply_nterror(req, NT_STATUS_NO_MEMORY);
8795 TALLOC_FREE(smb_fname_dst->base_name);
8796 smb_fname_dst->base_name = fname_dst_mod;
8799 status = check_name(conn, smb_fname_src);
8800 if (!NT_STATUS_IS_OK(status)) {
8801 reply_nterror(req, status);
8805 status = check_name(conn, smb_fname_dst);
8806 if (!NT_STATUS_IS_OK(status)) {
8807 reply_nterror(req, status);
8811 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8812 ofun, count, target_is_directory);
8814 if(!NT_STATUS_IS_OK(status)) {
8815 reply_nterror(req, status);
8821 struct smb_Dir *dir_hnd = NULL;
8822 const char *dname = NULL;
8823 char *talloced = NULL;
8827 * There is a wildcard that requires us to actually read the
8828 * src dir and copy each file matching the mask to the dst.
8829 * Right now streams won't be copied, but this could
8830 * presumably be added with a nested loop for reach dir entry.
8832 SMB_ASSERT(!smb_fname_src->stream_name);
8833 SMB_ASSERT(!smb_fname_dst->stream_name);
8835 smb_fname_src->stream_name = NULL;
8836 smb_fname_dst->stream_name = NULL;
8838 if (strequal(fname_src_mask,"????????.???")) {
8839 TALLOC_FREE(fname_src_mask);
8840 fname_src_mask = talloc_strdup(ctx, "*");
8841 if (!fname_src_mask) {
8842 reply_nterror(req, NT_STATUS_NO_MEMORY);
8847 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8851 smb_fname_src->flags);
8852 if (smb_fname_src_dir == NULL) {
8853 reply_nterror(req, NT_STATUS_NO_MEMORY);
8857 status = check_name(conn, smb_fname_src_dir);
8858 if (!NT_STATUS_IS_OK(status)) {
8859 reply_nterror(req, status);
8863 dir_hnd = OpenDir(ctx,
8868 if (dir_hnd == NULL) {
8869 status = map_nt_error_from_unix(errno);
8870 reply_nterror(req, status);
8876 /* Iterate over the src dir copying each entry to the dst. */
8877 while ((dname = ReadDirName(dir_hnd, &offset,
8878 &smb_fname_src->st, &talloced))) {
8879 char *destname = NULL;
8881 if (ISDOT(dname) || ISDOTDOT(dname)) {
8882 TALLOC_FREE(talloced);
8886 if (!is_visible_file(conn, fname_src_dir, dname,
8887 &smb_fname_src->st, false)) {
8888 TALLOC_FREE(talloced);
8892 if(!mask_match(dname, fname_src_mask,
8893 conn->case_sensitive)) {
8894 TALLOC_FREE(talloced);
8898 error = ERRnoaccess;
8900 /* Get the src smb_fname struct setup. */
8901 TALLOC_FREE(smb_fname_src->base_name);
8902 if (ISDOT(fname_src_dir)) {
8903 /* Ensure we use canonical names on open. */
8904 smb_fname_src->base_name =
8905 talloc_asprintf(smb_fname_src, "%s",
8908 smb_fname_src->base_name =
8909 talloc_asprintf(smb_fname_src, "%s/%s",
8910 fname_src_dir, dname);
8913 if (!smb_fname_src->base_name) {
8914 TALLOC_FREE(dir_hnd);
8915 TALLOC_FREE(talloced);
8916 reply_nterror(req, NT_STATUS_NO_MEMORY);
8920 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8921 smb_fname_dst->base_name,
8923 TALLOC_FREE(talloced);
8927 TALLOC_FREE(dir_hnd);
8928 TALLOC_FREE(talloced);
8929 reply_nterror(req, NT_STATUS_NO_MEMORY);
8933 TALLOC_FREE(smb_fname_dst->base_name);
8934 smb_fname_dst->base_name = destname;
8936 status = check_name(conn, smb_fname_src);
8937 if (!NT_STATUS_IS_OK(status)) {
8938 TALLOC_FREE(dir_hnd);
8939 TALLOC_FREE(talloced);
8940 reply_nterror(req, status);
8944 status = check_name(conn, smb_fname_dst);
8945 if (!NT_STATUS_IS_OK(status)) {
8946 TALLOC_FREE(dir_hnd);
8947 TALLOC_FREE(talloced);
8948 reply_nterror(req, status);
8952 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8953 smb_fname_src->base_name,
8954 smb_fname_dst->base_name));
8956 status = copy_file(ctx, conn, smb_fname_src,
8957 smb_fname_dst, ofun, count,
8958 target_is_directory);
8959 if (NT_STATUS_IS_OK(status)) {
8963 TALLOC_FREE(talloced);
8965 TALLOC_FREE(dir_hnd);
8969 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8973 reply_outbuf(req, 1, 0);
8974 SSVAL(req->outbuf,smb_vwv0,count);
8976 TALLOC_FREE(smb_fname_src);
8977 TALLOC_FREE(smb_fname_src_dir);
8978 TALLOC_FREE(smb_fname_dst);
8979 TALLOC_FREE(fname_src);
8980 TALLOC_FREE(fname_dst);
8981 TALLOC_FREE(fname_src_mask);
8982 TALLOC_FREE(fname_src_dir);
8984 END_PROFILE(SMBcopy);
8989 #define DBGC_CLASS DBGC_LOCKING
8991 /****************************************************************************
8992 Get a lock pid, dealing with large count requests.
8993 ****************************************************************************/
8995 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8996 bool large_file_format)
8998 if(!large_file_format)
8999 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9001 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9004 /****************************************************************************
9005 Get a lock count, dealing with large count requests.
9006 ****************************************************************************/
9008 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9009 bool large_file_format)
9013 if(!large_file_format) {
9014 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9017 * No BVAL, this is reversed!
9019 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9020 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9026 /****************************************************************************
9027 Get a lock offset, dealing with large offset requests.
9028 ****************************************************************************/
9030 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9031 bool large_file_format)
9033 uint64_t offset = 0;
9035 if(!large_file_format) {
9036 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9039 * No BVAL, this is reversed!
9041 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9042 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9048 struct smbd_do_unlocking_state {
9049 struct files_struct *fsp;
9050 uint16_t num_ulocks;
9051 struct smbd_lock_element *ulocks;
9052 enum brl_flavour lock_flav;
9056 static void smbd_do_unlocking_fn(
9057 TDB_DATA value, bool *pmodified_dependent, void *private_data)
9059 struct smbd_do_unlocking_state *state = private_data;
9060 struct files_struct *fsp = state->fsp;
9061 enum brl_flavour lock_flav = state->lock_flav;
9064 for (i = 0; i < state->num_ulocks; i++) {
9065 struct smbd_lock_element *e = &state->ulocks[i];
9067 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9068 "pid %"PRIu64", file %s\n",
9074 if (e->brltype != UNLOCK_LOCK) {
9075 /* this can only happen with SMB2 */
9076 state->status = NT_STATUS_INVALID_PARAMETER;
9080 state->status = do_unlock(
9081 fsp, e->smblctx, e->count, e->offset, lock_flav);
9083 DBG_DEBUG("do_unlock returned %s\n",
9084 nt_errstr(state->status));
9086 if (!NT_STATUS_IS_OK(state->status)) {
9091 *pmodified_dependent = true;
9094 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9096 uint16_t num_ulocks,
9097 struct smbd_lock_element *ulocks,
9098 enum brl_flavour lock_flav)
9100 struct smbd_do_unlocking_state state = {
9102 .num_ulocks = num_ulocks,
9104 .lock_flav = lock_flav,
9108 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9110 status = share_mode_do_locked(
9111 fsp->file_id, smbd_do_unlocking_fn, &state);
9113 if (!NT_STATUS_IS_OK(status)) {
9114 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9118 if (!NT_STATUS_IS_OK(state.status)) {
9119 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9121 return state.status;
9124 return NT_STATUS_OK;
9127 /****************************************************************************
9128 Reply to a lockingX request.
9129 ****************************************************************************/
9131 static void reply_lockingx_done(struct tevent_req *subreq);
9133 void reply_lockingX(struct smb_request *req)
9135 connection_struct *conn = req->conn;
9137 unsigned char locktype;
9138 enum brl_type brltype;
9139 unsigned char oplocklevel;
9140 uint16_t num_ulocks;
9142 int32_t lock_timeout;
9144 const uint8_t *data;
9145 bool large_file_format;
9146 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9147 struct smbd_lock_element *locks = NULL;
9148 struct tevent_req *subreq = NULL;
9150 START_PROFILE(SMBlockingX);
9153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9154 END_PROFILE(SMBlockingX);
9158 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9159 locktype = CVAL(req->vwv+3, 0);
9160 oplocklevel = CVAL(req->vwv+3, 1);
9161 num_ulocks = SVAL(req->vwv+6, 0);
9162 num_locks = SVAL(req->vwv+7, 0);
9163 lock_timeout = IVAL(req->vwv+4, 0);
9164 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9166 if (!check_fsp(conn, req, fsp)) {
9167 END_PROFILE(SMBlockingX);
9173 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9174 /* we don't support these - and CANCEL_LOCK makes w2k
9175 and XP reboot so I don't really want to be
9176 compatible! (tridge) */
9177 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9178 END_PROFILE(SMBlockingX);
9182 /* Check if this is an oplock break on a file
9183 we have granted an oplock on.
9185 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9186 /* Client can insist on breaking to none. */
9187 bool break_to_none = (oplocklevel == 0);
9190 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9191 "for %s\n", (unsigned int)oplocklevel,
9192 fsp_fnum_dbg(fsp)));
9195 * Make sure we have granted an exclusive or batch oplock on
9199 if (fsp->oplock_type == 0) {
9201 /* The Samba4 nbench simulator doesn't understand
9202 the difference between break to level2 and break
9203 to none from level2 - it sends oplock break
9204 replies in both cases. Don't keep logging an error
9205 message here - just ignore it. JRA. */
9207 DEBUG(5,("reply_lockingX: Error : oplock break from "
9208 "client for %s (oplock=%d) and no "
9209 "oplock granted on this file (%s).\n",
9210 fsp_fnum_dbg(fsp), fsp->oplock_type,
9213 /* if this is a pure oplock break request then don't
9215 if (num_locks == 0 && num_ulocks == 0) {
9216 END_PROFILE(SMBlockingX);
9220 END_PROFILE(SMBlockingX);
9221 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9225 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9227 result = remove_oplock(fsp);
9229 result = downgrade_oplock(fsp);
9233 DEBUG(0, ("reply_lockingX: error in removing "
9234 "oplock on file %s\n", fsp_str_dbg(fsp)));
9235 /* Hmmm. Is this panic justified? */
9236 smb_panic("internal tdb error");
9239 /* if this is a pure oplock break request then don't send a
9241 if (num_locks == 0 && num_ulocks == 0) {
9242 /* Sanity check - ensure a pure oplock break is not a
9244 if (CVAL(req->vwv+0, 0) != 0xff) {
9245 DEBUG(0,("reply_lockingX: Error : pure oplock "
9246 "break is a chained %d request !\n",
9247 (unsigned int)CVAL(req->vwv+0, 0)));
9249 END_PROFILE(SMBlockingX);
9255 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9257 END_PROFILE(SMBlockingX);
9261 if (num_ulocks != 0) {
9262 struct smbd_lock_element *ulocks = NULL;
9265 ulocks = talloc_array(
9266 req, struct smbd_lock_element, num_ulocks);
9267 if (ulocks == NULL) {
9268 reply_nterror(req, NT_STATUS_NO_MEMORY);
9269 END_PROFILE(SMBlockingX);
9274 * Data now points at the beginning of the list of
9275 * smb_unlkrng structs
9277 for (i = 0; i < num_ulocks; i++) {
9278 ulocks[i].req_guid = smbd_request_guid(req,
9280 ulocks[i].smblctx = get_lock_pid(
9281 data, i, large_file_format);
9282 ulocks[i].count = get_lock_count(
9283 data, i, large_file_format);
9284 ulocks[i].offset = get_lock_offset(
9285 data, i, large_file_format);
9286 ulocks[i].brltype = UNLOCK_LOCK;
9290 * Unlock cancels pending locks
9293 ok = smbd_smb1_brl_finish_by_lock(
9300 reply_outbuf(req, 2, 0);
9301 SSVAL(req->outbuf, smb_vwv0, 0xff);
9302 SSVAL(req->outbuf, smb_vwv1, 0);
9303 END_PROFILE(SMBlockingX);
9307 status = smbd_do_unlocking(
9308 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9309 TALLOC_FREE(ulocks);
9310 if (!NT_STATUS_IS_OK(status)) {
9311 END_PROFILE(SMBlockingX);
9312 reply_nterror(req, status);
9317 /* Now do any requested locks */
9318 data += ((large_file_format ? 20 : 10)*num_ulocks);
9320 /* Data now points at the beginning of the list
9321 of smb_lkrng structs */
9323 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9324 brltype = READ_LOCK;
9326 brltype = WRITE_LOCK;
9329 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9330 if (locks == NULL) {
9331 reply_nterror(req, NT_STATUS_NO_MEMORY);
9332 END_PROFILE(SMBlockingX);
9336 for (i = 0; i < num_locks; i++) {
9337 locks[i].req_guid = smbd_request_guid(req, i),
9338 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9339 locks[i].count = get_lock_count(data, i, large_file_format);
9340 locks[i].offset = get_lock_offset(data, i, large_file_format);
9341 locks[i].brltype = brltype;
9344 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9348 if (num_locks == 0) {
9349 /* See smbtorture3 lock11 test */
9350 reply_outbuf(req, 2, 0);
9351 /* andx chain ends */
9352 SSVAL(req->outbuf, smb_vwv0, 0xff);
9353 SSVAL(req->outbuf, smb_vwv1, 0);
9354 END_PROFILE(SMBlockingX);
9358 ok = smbd_smb1_brl_finish_by_lock(
9362 locks[0], /* Windows only cancels the first lock */
9363 NT_STATUS_FILE_LOCK_CONFLICT);
9366 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9367 END_PROFILE(SMBlockingX);
9371 reply_outbuf(req, 2, 0);
9372 SSVAL(req->outbuf, smb_vwv0, 0xff);
9373 SSVAL(req->outbuf, smb_vwv1, 0);
9374 END_PROFILE(SMBlockingX);
9378 subreq = smbd_smb1_do_locks_send(
9388 if (subreq == NULL) {
9389 reply_nterror(req, NT_STATUS_NO_MEMORY);
9390 END_PROFILE(SMBlockingX);
9393 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9394 END_PROFILE(SMBlockingX);
9397 static void reply_lockingx_done(struct tevent_req *subreq)
9399 struct smb_request *req = NULL;
9403 START_PROFILE(SMBlockingX);
9405 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9408 status = smbd_smb1_do_locks_recv(subreq);
9409 TALLOC_FREE(subreq);
9411 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9413 if (NT_STATUS_IS_OK(status)) {
9414 reply_outbuf(req, 2, 0);
9415 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9416 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9418 reply_nterror(req, status);
9421 ok = srv_send_smb(req->xconn,
9422 (char *)req->outbuf,
9425 IS_CONN_ENCRYPTED(req->conn),
9428 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9431 END_PROFILE(SMBlockingX);
9435 #define DBGC_CLASS DBGC_ALL
9437 /****************************************************************************
9438 Reply to a SMBreadbmpx (read block multiplex) request.
9439 Always reply with an error, if someone has a platform really needs this,
9440 please contact vl@samba.org
9441 ****************************************************************************/
9443 void reply_readbmpx(struct smb_request *req)
9445 START_PROFILE(SMBreadBmpx);
9446 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9447 END_PROFILE(SMBreadBmpx);
9451 /****************************************************************************
9452 Reply to a SMBreadbs (read block multiplex secondary) request.
9453 Always reply with an error, if someone has a platform really needs this,
9454 please contact vl@samba.org
9455 ****************************************************************************/
9457 void reply_readbs(struct smb_request *req)
9459 START_PROFILE(SMBreadBs);
9460 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9461 END_PROFILE(SMBreadBs);
9465 /****************************************************************************
9466 Reply to a SMBsetattrE.
9467 ****************************************************************************/
9469 void reply_setattrE(struct smb_request *req)
9471 connection_struct *conn = req->conn;
9472 struct smb_file_time ft;
9476 START_PROFILE(SMBsetattrE);
9477 init_smb_file_time(&ft);
9480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9484 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9486 if(!fsp || (fsp->conn != conn)) {
9487 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9492 * Convert the DOS times into unix times.
9495 ft.atime = time_t_to_full_timespec(
9496 srv_make_unix_date2(req->vwv+3));
9497 ft.mtime = time_t_to_full_timespec(
9498 srv_make_unix_date2(req->vwv+5));
9499 ft.create_time = time_t_to_full_timespec(
9500 srv_make_unix_date2(req->vwv+1));
9502 reply_outbuf(req, 0, 0);
9505 * Patch from Ray Frush <frush@engr.colostate.edu>
9506 * Sometimes times are sent as zero - ignore them.
9509 /* Ensure we have a valid stat struct for the source. */
9510 status = vfs_stat_fsp(fsp);
9511 if (!NT_STATUS_IS_OK(status)) {
9512 reply_nterror(req, status);
9516 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9517 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9521 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9522 if (!NT_STATUS_IS_OK(status)) {
9523 reply_nterror(req, status);
9527 if (fsp->fsp_flags.modified) {
9528 trigger_write_time_update_immediate(fsp);
9531 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9534 (unsigned int)ft.atime.tv_sec,
9535 (unsigned int)ft.mtime.tv_sec,
9536 (unsigned int)ft.create_time.tv_sec
9539 END_PROFILE(SMBsetattrE);
9544 /* Back from the dead for OS/2..... JRA. */
9546 /****************************************************************************
9547 Reply to a SMBwritebmpx (write block multiplex primary) request.
9548 Always reply with an error, if someone has a platform really needs this,
9549 please contact vl@samba.org
9550 ****************************************************************************/
9552 void reply_writebmpx(struct smb_request *req)
9554 START_PROFILE(SMBwriteBmpx);
9555 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9556 END_PROFILE(SMBwriteBmpx);
9560 /****************************************************************************
9561 Reply to a SMBwritebs (write block multiplex secondary) request.
9562 Always reply with an error, if someone has a platform really needs this,
9563 please contact vl@samba.org
9564 ****************************************************************************/
9566 void reply_writebs(struct smb_request *req)
9568 START_PROFILE(SMBwriteBs);
9569 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9570 END_PROFILE(SMBwriteBs);
9574 /****************************************************************************
9575 Reply to a SMBgetattrE.
9576 ****************************************************************************/
9578 void reply_getattrE(struct smb_request *req)
9580 connection_struct *conn = req->conn;
9583 struct timespec create_ts;
9586 START_PROFILE(SMBgetattrE);
9589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9590 END_PROFILE(SMBgetattrE);
9594 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9596 if(!fsp || (fsp->conn != conn)) {
9597 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9598 END_PROFILE(SMBgetattrE);
9602 /* Do an fstat on this file */
9603 status = vfs_stat_fsp(fsp);
9604 if (!NT_STATUS_IS_OK(status)) {
9605 reply_nterror(req, status);
9606 END_PROFILE(SMBgetattrE);
9610 mode = dos_mode(conn, fsp->fsp_name);
9613 * Convert the times into dos times. Set create
9614 * date to be last modify date as UNIX doesn't save
9618 reply_outbuf(req, 11, 0);
9620 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9621 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9622 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9623 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9624 /* Should we check pending modtime here ? JRA */
9625 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9626 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9628 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9629 SIVAL(req->outbuf, smb_vwv6, 0);
9630 SIVAL(req->outbuf, smb_vwv8, 0);
9632 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9633 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9634 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9636 SSVAL(req->outbuf,smb_vwv10, mode);
9638 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9640 END_PROFILE(SMBgetattrE);