2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "lib/util/tevent_ntstatus.h"
46 #include "libcli/smb/smb_signing.h"
47 #include "lib/util/sys_rw_data.h"
48 #include "librpc/gen_ndr/open_files.h"
49 #include "smb1_utils.h"
50 #include "libcli/smb/smb2_posix.h"
52 /****************************************************************************
53 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
54 path or anything including wildcards.
55 We're assuming here that '/' is not the second byte in any multibyte char
56 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
58 ****************************************************************************/
60 /* Custom version for processing POSIX paths. */
61 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
63 static NTSTATUS check_path_syntax_internal(char *path,
65 bool *p_last_component_contains_wcard)
69 NTSTATUS ret = NT_STATUS_OK;
70 bool start_of_name_component = True;
71 bool stream_started = false;
73 *p_last_component_contains_wcard = False;
80 return NT_STATUS_OBJECT_NAME_INVALID;
83 return NT_STATUS_OBJECT_NAME_INVALID;
85 if (strchr_m(&s[1], ':')) {
86 return NT_STATUS_OBJECT_NAME_INVALID;
92 if ((*s == ':') && !posix_path && !stream_started) {
93 if (*p_last_component_contains_wcard) {
94 return NT_STATUS_OBJECT_NAME_INVALID;
96 /* Stream names allow more characters than file names.
97 We're overloading posix_path here to allow a wider
98 range of characters. If stream_started is true this
99 is still a Windows path even if posix_path is true.
102 stream_started = true;
103 start_of_name_component = false;
107 return NT_STATUS_OBJECT_NAME_INVALID;
111 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
113 * Safe to assume is not the second part of a mb char
114 * as this is handled below.
116 /* Eat multiple '/' or '\\' */
117 while (IS_PATH_SEP(*s,posix_path)) {
120 if ((d != path) && (*s != '\0')) {
121 /* We only care about non-leading or trailing '/' or '\\' */
125 start_of_name_component = True;
127 *p_last_component_contains_wcard = False;
131 if (start_of_name_component) {
132 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
133 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
136 * No mb char starts with '.' so we're safe checking the directory separator here.
139 /* If we just added a '/' - delete it */
140 if ((d > path) && (*(d-1) == '/')) {
145 /* Are we at the start ? Can't go back further if so. */
147 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
150 /* Go back one level... */
151 /* We know this is safe as '/' cannot be part of a mb sequence. */
152 /* NOTE - if this assumption is invalid we are not in good shape... */
153 /* Decrement d first as d points to the *next* char to write into. */
154 for (d--; d > path; d--) {
158 s += 2; /* Else go past the .. */
159 /* We're still at the start of a name component, just the previous one. */
162 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
174 if (*s <= 0x1f || *s == '|') {
175 return NT_STATUS_OBJECT_NAME_INVALID;
183 *p_last_component_contains_wcard = True;
192 /* Get the size of the next MB character. */
193 next_codepoint(s,&siz);
211 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
213 return NT_STATUS_INVALID_PARAMETER;
216 start_of_name_component = False;
224 /****************************************************************************
225 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
226 No wildcards allowed.
227 ****************************************************************************/
229 NTSTATUS check_path_syntax(char *path)
232 return check_path_syntax_internal(path, False, &ignore);
235 /****************************************************************************
236 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
237 Wildcards allowed - p_contains_wcard returns true if the last component contained
239 ****************************************************************************/
241 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
243 return check_path_syntax_internal(path, False, p_contains_wcard);
246 /****************************************************************************
247 Check the path for a POSIX client.
248 We're assuming here that '/' is not the second byte in any multibyte char
249 set (a safe assumption).
250 ****************************************************************************/
252 NTSTATUS check_path_syntax_posix(char *path)
255 return check_path_syntax_internal(path, True, &ignore);
258 /****************************************************************************
259 Pull a string and check the path allowing a wildcard - provide for error return.
260 Passes in posix flag.
261 ****************************************************************************/
263 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
264 const char *base_ptr,
270 bool posix_pathnames,
272 bool *contains_wcard)
278 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
282 *err = NT_STATUS_INVALID_PARAMETER;
286 *contains_wcard = False;
288 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
290 * For a DFS path the function parse_dfs_path()
291 * will do the path processing, just make a copy.
297 if (posix_pathnames) {
298 *err = check_path_syntax_posix(*pp_dest);
300 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
306 /****************************************************************************
307 Pull a string and check the path allowing a wildcard - provide for error return.
308 ****************************************************************************/
310 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
311 const char *base_ptr,
318 bool *contains_wcard)
320 return srvstr_get_path_wcard_internal(ctx,
332 /****************************************************************************
333 Pull a string and check the path allowing a wildcard - provide for error return.
334 posix_pathnames version.
335 ****************************************************************************/
337 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
338 const char *base_ptr,
345 bool *contains_wcard)
347 return srvstr_get_path_wcard_internal(ctx,
359 /****************************************************************************
360 Pull a string and check the path - provide for error return.
361 ****************************************************************************/
363 size_t srvstr_get_path(TALLOC_CTX *ctx,
364 const char *base_ptr,
373 return srvstr_get_path_wcard_internal(ctx,
385 /****************************************************************************
386 Pull a string and check the path - provide for error return.
387 posix_pathnames version.
388 ****************************************************************************/
390 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
391 const char *base_ptr,
400 return srvstr_get_path_wcard_internal(ctx,
413 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
414 char **pp_dest, const char *src, int flags,
415 NTSTATUS *err, bool *contains_wcard)
417 ssize_t bufrem = smbreq_bufrem(req, src);
420 *err = NT_STATUS_INVALID_PARAMETER;
424 if (req->posix_pathnames) {
425 return srvstr_get_path_wcard_internal(mem_ctx,
426 (const char *)req->inbuf,
436 return srvstr_get_path_wcard_internal(mem_ctx,
437 (const char *)req->inbuf,
449 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
450 char **pp_dest, const char *src, int flags,
454 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
455 flags, err, &ignore);
459 * pull a string from the smb_buf part of a packet. In this case the
460 * string can either be null terminated or it can be terminated by the
461 * end of the smbbuf area
463 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
464 char **dest, const uint8_t *src, int flags)
466 ssize_t bufrem = smbreq_bufrem(req, src);
472 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
476 /****************************************************************************
477 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
478 ****************************************************************************/
480 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
483 if ((fsp == NULL) || (conn == NULL)) {
484 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
487 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
488 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
494 /****************************************************************************
495 Check if we have a correct fsp pointing to a file.
496 ****************************************************************************/
498 bool check_fsp(connection_struct *conn, struct smb_request *req,
501 if (!check_fsp_open(conn, req, fsp)) {
504 if (fsp->is_directory) {
505 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
508 if (fsp->fh->fd == -1) {
509 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
512 fsp->num_smb_operations++;
516 /****************************************************************************
517 Check if we have a correct fsp pointing to a quota fake file. Replacement for
518 the CHECK_NTQUOTA_HANDLE_OK macro.
519 ****************************************************************************/
521 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
524 if (!check_fsp_open(conn, req, fsp)) {
528 if (fsp->is_directory) {
532 if (fsp->fake_file_handle == NULL) {
536 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
540 if (fsp->fake_file_handle->private_data == NULL) {
547 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
548 const char *name, int name_type)
551 char *trim_name_type;
552 const char *retarget_parm;
555 int retarget_type = 0x20;
556 int retarget_port = NBT_SMB_PORT;
557 struct sockaddr_storage retarget_addr;
558 struct sockaddr_in *in_addr;
562 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
566 trim_name = talloc_strdup(talloc_tos(), name);
567 if (trim_name == NULL) {
570 trim_char(trim_name, ' ', ' ');
572 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
574 if (trim_name_type == NULL) {
578 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
579 trim_name_type, NULL);
580 if (retarget_parm == NULL) {
581 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
584 if (retarget_parm == NULL) {
588 retarget = talloc_strdup(trim_name, retarget_parm);
589 if (retarget == NULL) {
593 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
595 p = strchr(retarget, ':');
598 retarget_port = atoi(p);
601 p = strchr_m(retarget, '#');
604 if (sscanf(p, "%x", &retarget_type) != 1) {
609 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
611 DEBUG(10, ("could not resolve %s\n", retarget));
615 if (retarget_addr.ss_family != AF_INET) {
616 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
620 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
622 _smb_setlen(outbuf, 6);
623 SCVAL(outbuf, 0, 0x84);
624 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
625 *(uint16_t *)(outbuf+8) = htons(retarget_port);
627 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
629 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
635 TALLOC_FREE(trim_name);
639 static void reply_called_name_not_present(char *outbuf)
641 smb_setlen(outbuf, 1);
642 SCVAL(outbuf, 0, 0x83);
643 SCVAL(outbuf, 4, 0x82);
646 /****************************************************************************
647 Reply to a (netbios-level) special message.
648 ****************************************************************************/
650 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
652 struct smbd_server_connection *sconn = xconn->client->sconn;
653 int msg_type = CVAL(inbuf,0);
654 int msg_flags = CVAL(inbuf,1);
656 * We only really use 4 bytes of the outbuf, but for the smb_setlen
657 * calculation & friends (srv_send_smb uses that) we need the full smb
660 char outbuf[smb_size];
662 memset(outbuf, '\0', sizeof(outbuf));
664 smb_setlen(outbuf,0);
667 case NBSSrequest: /* session request */
669 /* inbuf_size is guarenteed to be at least 4. */
671 int name_type1, name_type2;
672 int name_len1, name_len2;
676 if (xconn->transport.nbt.got_session) {
677 exit_server_cleanly("multiple session request not permitted");
680 SCVAL(outbuf,0,NBSSpositive);
683 /* inbuf_size is guaranteed to be at least 4. */
684 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
685 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
686 DEBUG(0,("Invalid name length in session request\n"));
687 reply_called_name_not_present(outbuf);
690 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
691 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
692 DEBUG(0,("Invalid name length in session request\n"));
693 reply_called_name_not_present(outbuf);
697 name_type1 = name_extract((unsigned char *)inbuf,
698 inbuf_size,(unsigned int)4,name1);
699 name_type2 = name_extract((unsigned char *)inbuf,
700 inbuf_size,(unsigned int)(4 + name_len1),name2);
702 if (name_type1 == -1 || name_type2 == -1) {
703 DEBUG(0,("Invalid name type in session request\n"));
704 reply_called_name_not_present(outbuf);
708 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
709 name1, name_type1, name2, name_type2));
711 if (netbios_session_retarget(xconn, name1, name_type1)) {
712 exit_server_cleanly("retargeted client");
716 * Windows NT/2k uses "*SMBSERVER" and XP uses
717 * "*SMBSERV" arrggg!!!
719 if (strequal(name1, "*SMBSERVER ")
720 || strequal(name1, "*SMBSERV ")) {
723 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
726 exit_server_cleanly("could not allocate raddr");
729 fstrcpy(name1, raddr);
732 set_local_machine_name(name1, True);
733 set_remote_machine_name(name2, True);
735 if (is_ipaddress(sconn->remote_hostname)) {
736 char *p = discard_const_p(char, sconn->remote_hostname);
740 sconn->remote_hostname = talloc_strdup(sconn,
741 get_remote_machine_name());
742 if (sconn->remote_hostname == NULL) {
743 exit_server_cleanly("could not copy remote name");
745 xconn->remote_hostname = sconn->remote_hostname;
748 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
749 get_local_machine_name(), get_remote_machine_name(),
752 if (name_type2 == 'R') {
753 /* We are being asked for a pathworks session ---
755 reply_called_name_not_present(outbuf);
759 reload_services(sconn, conn_snum_used, true);
762 xconn->transport.nbt.got_session = true;
766 case 0x89: /* session keepalive request
767 (some old clients produce this?) */
768 SCVAL(outbuf,0,NBSSkeepalive);
772 case NBSSpositive: /* positive session response */
773 case NBSSnegative: /* negative session response */
774 case NBSSretarget: /* retarget session response */
775 DEBUG(0,("Unexpected session response\n"));
778 case NBSSkeepalive: /* session keepalive */
783 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
784 msg_type, msg_flags));
786 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
787 exit_server_cleanly("reply_special: srv_send_smb failed.");
790 if (CVAL(outbuf, 0) != 0x82) {
791 exit_server_cleanly("invalid netbios session");
796 /****************************************************************************
798 conn POINTER CAN BE NULL HERE !
799 ****************************************************************************/
801 void reply_tcon(struct smb_request *req)
803 connection_struct *conn = req->conn;
805 char *service_buf = NULL;
806 char *password = NULL;
812 TALLOC_CTX *ctx = talloc_tos();
813 struct smbXsrv_connection *xconn = req->xconn;
814 NTTIME now = timeval_to_nttime(&req->request_time);
816 START_PROFILE(SMBtcon);
818 if (req->buflen < 4) {
819 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
820 END_PROFILE(SMBtcon);
825 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
827 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
829 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
832 if (service_buf == NULL || password == NULL || dev == NULL) {
833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
834 END_PROFILE(SMBtcon);
837 p2 = strrchr_m(service_buf,'\\');
841 service = service_buf;
844 conn = make_connection(req, now, service, dev,
845 req->vuid,&nt_status);
849 reply_nterror(req, nt_status);
850 END_PROFILE(SMBtcon);
854 reply_outbuf(req, 2, 0);
855 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
856 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
857 SSVAL(req->outbuf,smb_tid,conn->cnum);
859 DEBUG(3,("tcon service=%s cnum=%d\n",
860 service, conn->cnum));
862 END_PROFILE(SMBtcon);
866 /****************************************************************************
867 Reply to a tcon and X.
868 conn POINTER CAN BE NULL HERE !
869 ****************************************************************************/
871 void reply_tcon_and_X(struct smb_request *req)
873 const struct loadparm_substitution *lp_sub =
874 loadparm_s3_global_substitution();
875 connection_struct *conn = req->conn;
876 const char *service = NULL;
877 TALLOC_CTX *ctx = talloc_tos();
878 /* what the client thinks the device is */
879 char *client_devicetype = NULL;
880 /* what the server tells the client the share represents */
881 const char *server_devicetype;
888 struct smbXsrv_session *session = NULL;
889 NTTIME now = timeval_to_nttime(&req->request_time);
890 bool session_key_updated = false;
891 uint16_t optional_support = 0;
892 struct smbXsrv_connection *xconn = req->xconn;
894 START_PROFILE(SMBtconX);
897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
898 END_PROFILE(SMBtconX);
902 passlen = SVAL(req->vwv+3, 0);
903 tcon_flags = SVAL(req->vwv+2, 0);
905 /* we might have to close an old one */
906 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
907 struct smbXsrv_tcon *tcon;
915 * TODO: cancel all outstanding requests on the tcon
917 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
918 if (!NT_STATUS_IS_OK(status)) {
919 DEBUG(0, ("reply_tcon_and_X: "
920 "smbXsrv_tcon_disconnect() failed: %s\n",
923 * If we hit this case, there is something completely
924 * wrong, so we better disconnect the transport connection.
926 END_PROFILE(SMBtconX);
927 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
933 * This tree id is gone. Make sure we can't re-use it
939 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
940 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
941 END_PROFILE(SMBtconX);
945 if (xconn->smb1.negprot.encrypted_passwords) {
946 p = req->buf + passlen;
948 p = req->buf + passlen + 1;
951 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
955 END_PROFILE(SMBtconX);
960 * the service name can be either: \\server\share
961 * or share directly like on the DELL PowerVault 705
964 q = strchr_m(path+2,'\\');
966 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
967 END_PROFILE(SMBtconX);
975 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
976 &client_devicetype, p,
977 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
979 if (client_devicetype == NULL) {
980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
981 END_PROFILE(SMBtconX);
985 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
987 nt_status = smb1srv_session_lookup(xconn,
988 req->vuid, now, &session);
989 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
990 reply_force_doserror(req, ERRSRV, ERRbaduid);
991 END_PROFILE(SMBtconX);
994 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
995 reply_nterror(req, nt_status);
996 END_PROFILE(SMBtconX);
999 if (!NT_STATUS_IS_OK(nt_status)) {
1000 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1001 END_PROFILE(SMBtconX);
1005 if (session->global->auth_session_info == NULL) {
1006 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1007 END_PROFILE(SMBtconX);
1012 * If there is no application key defined yet
1015 * This means we setup the application key on the
1016 * first tcon that happens via the given session.
1018 * Once the application key is defined, it does not
1021 if (session->global->application_key.length == 0 &&
1022 smb2_signing_key_valid(session->global->signing_key))
1024 struct smbXsrv_session *x = session;
1025 struct auth_session_info *session_info =
1026 session->global->auth_session_info;
1027 uint8_t session_key[16];
1029 ZERO_STRUCT(session_key);
1030 memcpy(session_key, x->global->signing_key->blob.data,
1031 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
1034 * The application key is truncated/padded to 16 bytes
1036 x->global->application_key = data_blob_talloc(x->global,
1038 sizeof(session_key));
1039 ZERO_STRUCT(session_key);
1040 if (x->global->application_key.data == NULL) {
1041 reply_nterror(req, NT_STATUS_NO_MEMORY);
1042 END_PROFILE(SMBtconX);
1046 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1049 status = smb_key_derivation(x->global->application_key.data,
1050 x->global->application_key.length,
1051 x->global->application_key.data);
1052 if (!NT_STATUS_IS_OK(status)) {
1053 DBG_ERR("smb_key_derivation failed: %s\n",
1055 END_PROFILE(SMBtconX);
1058 optional_support |= SMB_EXTENDED_SIGNATURES;
1062 * Place the application key into the session_info
1064 data_blob_clear_free(&session_info->session_key);
1065 session_info->session_key = data_blob_dup_talloc(session_info,
1066 x->global->application_key);
1067 if (session_info->session_key.data == NULL) {
1068 data_blob_clear_free(&x->global->application_key);
1069 reply_nterror(req, NT_STATUS_NO_MEMORY);
1070 END_PROFILE(SMBtconX);
1073 session_key_updated = true;
1076 conn = make_connection(req, now, service, client_devicetype,
1077 req->vuid, &nt_status);
1081 if (session_key_updated) {
1082 struct smbXsrv_session *x = session;
1083 struct auth_session_info *session_info =
1084 session->global->auth_session_info;
1085 data_blob_clear_free(&x->global->application_key);
1086 data_blob_clear_free(&session_info->session_key);
1088 reply_nterror(req, nt_status);
1089 END_PROFILE(SMBtconX);
1094 server_devicetype = "IPC";
1095 else if ( IS_PRINT(conn) )
1096 server_devicetype = "LPT1:";
1098 server_devicetype = "A:";
1100 if (get_Protocol() < PROTOCOL_NT1) {
1101 reply_outbuf(req, 2, 0);
1102 if (message_push_string(&req->outbuf, server_devicetype,
1103 STR_TERMINATE|STR_ASCII) == -1) {
1104 reply_nterror(req, NT_STATUS_NO_MEMORY);
1105 END_PROFILE(SMBtconX);
1109 /* NT sets the fstype of IPC$ to the null string */
1110 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1112 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1113 /* Return permissions. */
1117 reply_outbuf(req, 7, 0);
1120 perm1 = FILE_ALL_ACCESS;
1121 perm2 = FILE_ALL_ACCESS;
1123 perm1 = conn->share_access;
1126 SIVAL(req->outbuf, smb_vwv3, perm1);
1127 SIVAL(req->outbuf, smb_vwv5, perm2);
1129 reply_outbuf(req, 3, 0);
1132 if ((message_push_string(&req->outbuf, server_devicetype,
1133 STR_TERMINATE|STR_ASCII) == -1)
1134 || (message_push_string(&req->outbuf, fstype,
1135 STR_TERMINATE) == -1)) {
1136 reply_nterror(req, NT_STATUS_NO_MEMORY);
1137 END_PROFILE(SMBtconX);
1141 /* what does setting this bit do? It is set by NT4 and
1142 may affect the ability to autorun mounted cdroms */
1143 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1145 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1147 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1148 DEBUG(2,("Serving %s as a Dfs root\n",
1149 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1150 optional_support |= SMB_SHARE_IN_DFS;
1153 SSVAL(req->outbuf, smb_vwv2, optional_support);
1156 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1157 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1159 DEBUG(3,("tconX service=%s \n",
1162 /* set the incoming and outgoing tid to the just created one */
1163 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1164 SSVAL(req->outbuf,smb_tid,conn->cnum);
1166 END_PROFILE(SMBtconX);
1168 req->tid = conn->cnum;
1171 /****************************************************************************
1172 Reply to an unknown type.
1173 ****************************************************************************/
1175 void reply_unknown_new(struct smb_request *req, uint8_t type)
1177 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1178 smb_fn_name(type), type, type));
1179 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1183 /****************************************************************************
1185 conn POINTER CAN BE NULL HERE !
1186 ****************************************************************************/
1188 void reply_ioctl(struct smb_request *req)
1190 const struct loadparm_substitution *lp_sub =
1191 loadparm_s3_global_substitution();
1192 connection_struct *conn = req->conn;
1195 uint32_t ioctl_code;
1199 START_PROFILE(SMBioctl);
1202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1203 END_PROFILE(SMBioctl);
1207 device = SVAL(req->vwv+1, 0);
1208 function = SVAL(req->vwv+2, 0);
1209 ioctl_code = (device << 16) + function;
1211 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1213 switch (ioctl_code) {
1214 case IOCTL_QUERY_JOB_INFO:
1218 reply_force_doserror(req, ERRSRV, ERRnosupport);
1219 END_PROFILE(SMBioctl);
1223 reply_outbuf(req, 8, replysize+1);
1224 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1225 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1226 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1227 p = smb_buf(req->outbuf);
1228 memset(p, '\0', replysize+1); /* valgrind-safe. */
1229 p += 1; /* Allow for alignment */
1231 switch (ioctl_code) {
1232 case IOCTL_QUERY_JOB_INFO:
1236 files_struct *fsp = file_fsp(
1237 req, SVAL(req->vwv+0, 0));
1239 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1240 END_PROFILE(SMBioctl);
1244 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1246 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1247 lp_netbios_name(), 15,
1248 STR_TERMINATE|STR_ASCII, &len);
1249 if (!NT_STATUS_IS_OK(status)) {
1250 reply_nterror(req, status);
1251 END_PROFILE(SMBioctl);
1255 status = srvstr_push((char *)req->outbuf, req->flags2,
1257 lp_servicename(talloc_tos(),
1260 13, STR_TERMINATE|STR_ASCII, &len);
1261 if (!NT_STATUS_IS_OK(status)) {
1262 reply_nterror(req, status);
1263 END_PROFILE(SMBioctl);
1267 memset(p+18, 0, 13);
1273 END_PROFILE(SMBioctl);
1277 /****************************************************************************
1278 Strange checkpath NTSTATUS mapping.
1279 ****************************************************************************/
1281 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1283 /* Strange DOS error code semantics only for checkpath... */
1284 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1285 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1286 /* We need to map to ERRbadpath */
1287 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1293 /****************************************************************************
1294 Reply to a checkpath.
1295 ****************************************************************************/
1297 void reply_checkpath(struct smb_request *req)
1299 connection_struct *conn = req->conn;
1300 struct smb_filename *smb_fname = NULL;
1303 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1304 TALLOC_CTX *ctx = talloc_tos();
1306 START_PROFILE(SMBcheckpath);
1308 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1309 STR_TERMINATE, &status);
1311 if (!NT_STATUS_IS_OK(status)) {
1312 status = map_checkpath_error(req->flags2, status);
1313 reply_nterror(req, status);
1314 END_PROFILE(SMBcheckpath);
1318 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1320 status = filename_convert(ctx,
1328 if (!NT_STATUS_IS_OK(status)) {
1329 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1330 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1331 ERRSRV, ERRbadpath);
1332 END_PROFILE(SMBcheckpath);
1338 if (!VALID_STAT(smb_fname->st) &&
1339 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1340 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1341 smb_fname_str_dbg(smb_fname), strerror(errno)));
1342 status = map_nt_error_from_unix(errno);
1346 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1347 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1348 ERRDOS, ERRbadpath);
1352 reply_outbuf(req, 0, 0);
1355 /* We special case this - as when a Windows machine
1356 is parsing a path is steps through the components
1357 one at a time - if a component fails it expects
1358 ERRbadpath, not ERRbadfile.
1360 status = map_checkpath_error(req->flags2, status);
1361 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1363 * Windows returns different error codes if
1364 * the parent directory is valid but not the
1365 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1366 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1367 * if the path is invalid.
1369 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1370 ERRDOS, ERRbadpath);
1374 reply_nterror(req, status);
1377 TALLOC_FREE(smb_fname);
1378 END_PROFILE(SMBcheckpath);
1382 /****************************************************************************
1384 ****************************************************************************/
1386 void reply_getatr(struct smb_request *req)
1388 connection_struct *conn = req->conn;
1389 struct smb_filename *smb_fname = NULL;
1396 TALLOC_CTX *ctx = talloc_tos();
1397 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1399 START_PROFILE(SMBgetatr);
1401 p = (const char *)req->buf + 1;
1402 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1403 if (!NT_STATUS_IS_OK(status)) {
1404 reply_nterror(req, status);
1408 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1409 under WfWg - weird! */
1410 if (*fname == '\0') {
1411 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1412 if (!CAN_WRITE(conn)) {
1413 mode |= FILE_ATTRIBUTE_READONLY;
1418 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1419 status = filename_convert(ctx,
1426 if (!NT_STATUS_IS_OK(status)) {
1427 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1428 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1429 ERRSRV, ERRbadpath);
1432 reply_nterror(req, status);
1435 if (!VALID_STAT(smb_fname->st) &&
1436 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1437 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1438 smb_fname_str_dbg(smb_fname),
1440 reply_nterror(req, map_nt_error_from_unix(errno));
1444 mode = dos_mode(conn, smb_fname);
1445 size = smb_fname->st.st_ex_size;
1447 if (ask_sharemode) {
1448 struct timespec write_time_ts;
1449 struct file_id fileid;
1451 ZERO_STRUCT(write_time_ts);
1452 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1453 get_file_infos(fileid, 0, NULL, &write_time_ts);
1454 if (!is_omit_timespec(&write_time_ts)) {
1455 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1459 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1460 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1465 reply_outbuf(req, 10, 0);
1467 SSVAL(req->outbuf,smb_vwv0,mode);
1468 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1469 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1471 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1473 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1475 if (get_Protocol() >= PROTOCOL_NT1) {
1476 SSVAL(req->outbuf, smb_flg2,
1477 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1480 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1481 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1484 TALLOC_FREE(smb_fname);
1486 END_PROFILE(SMBgetatr);
1490 /****************************************************************************
1492 ****************************************************************************/
1494 void reply_setatr(struct smb_request *req)
1496 struct smb_file_time ft;
1497 connection_struct *conn = req->conn;
1498 struct smb_filename *smb_fname = NULL;
1504 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1505 TALLOC_CTX *ctx = talloc_tos();
1507 START_PROFILE(SMBsetatr);
1508 init_smb_file_time(&ft);
1511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1515 p = (const char *)req->buf + 1;
1516 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1517 if (!NT_STATUS_IS_OK(status)) {
1518 reply_nterror(req, status);
1522 status = filename_convert(ctx,
1529 if (!NT_STATUS_IS_OK(status)) {
1530 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1531 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1532 ERRSRV, ERRbadpath);
1535 reply_nterror(req, status);
1539 if (ISDOT(smb_fname->base_name)) {
1541 * Not sure here is the right place to catch this
1542 * condition. Might be moved to somewhere else later -- vl
1544 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1548 mode = SVAL(req->vwv+0, 0);
1549 mtime = srv_make_unix_date3(req->vwv+1);
1551 if (mode != FILE_ATTRIBUTE_NORMAL) {
1552 if (VALID_STAT_OF_DIR(smb_fname->st))
1553 mode |= FILE_ATTRIBUTE_DIRECTORY;
1555 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1557 status = smbd_check_access_rights(
1558 conn, smb_fname, false, FILE_WRITE_ATTRIBUTES);
1559 if (!NT_STATUS_IS_OK(status)) {
1560 reply_nterror(req, status);
1564 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1566 reply_nterror(req, map_nt_error_from_unix(errno));
1571 ft.mtime = time_t_to_full_timespec(mtime);
1573 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1574 if (!NT_STATUS_IS_OK(status)) {
1575 reply_nterror(req, status);
1579 reply_outbuf(req, 0, 0);
1581 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1584 TALLOC_FREE(smb_fname);
1585 END_PROFILE(SMBsetatr);
1589 /****************************************************************************
1591 ****************************************************************************/
1593 void reply_dskattr(struct smb_request *req)
1595 connection_struct *conn = req->conn;
1597 uint64_t dfree,dsize,bsize;
1598 struct smb_filename smb_fname;
1599 START_PROFILE(SMBdskattr);
1601 ZERO_STRUCT(smb_fname);
1602 smb_fname.base_name = discard_const_p(char, ".");
1604 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1605 reply_nterror(req, map_nt_error_from_unix(errno));
1606 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1607 END_PROFILE(SMBdskattr);
1611 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1612 if (ret == (uint64_t)-1) {
1613 reply_nterror(req, map_nt_error_from_unix(errno));
1614 END_PROFILE(SMBdskattr);
1619 * Force max to fit in 16 bit fields.
1621 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1625 if (bsize > (WORDMAX*512)) {
1626 bsize = (WORDMAX*512);
1627 if (dsize > WORDMAX)
1629 if (dfree > WORDMAX)
1635 reply_outbuf(req, 5, 0);
1637 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1638 double total_space, free_space;
1639 /* we need to scale this to a number that DOS6 can handle. We
1640 use floating point so we can handle large drives on systems
1641 that don't have 64 bit integers
1643 we end up displaying a maximum of 2G to DOS systems
1645 total_space = dsize * (double)bsize;
1646 free_space = dfree * (double)bsize;
1648 dsize = (uint64_t)((total_space+63*512) / (64*512));
1649 dfree = (uint64_t)((free_space+63*512) / (64*512));
1651 if (dsize > 0xFFFF) dsize = 0xFFFF;
1652 if (dfree > 0xFFFF) dfree = 0xFFFF;
1654 SSVAL(req->outbuf,smb_vwv0,dsize);
1655 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1656 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1657 SSVAL(req->outbuf,smb_vwv3,dfree);
1659 SSVAL(req->outbuf,smb_vwv0,dsize);
1660 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1661 SSVAL(req->outbuf,smb_vwv2,512);
1662 SSVAL(req->outbuf,smb_vwv3,dfree);
1665 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1667 END_PROFILE(SMBdskattr);
1672 * Utility function to split the filename from the directory.
1674 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1675 char **fname_dir_out,
1676 char **fname_mask_out)
1678 const char *p = NULL;
1679 char *fname_dir = NULL;
1680 char *fname_mask = NULL;
1682 p = strrchr_m(fname_in, '/');
1684 fname_dir = talloc_strdup(ctx, ".");
1685 fname_mask = talloc_strdup(ctx, fname_in);
1687 fname_dir = talloc_strndup(ctx, fname_in,
1688 PTR_DIFF(p, fname_in));
1689 fname_mask = talloc_strdup(ctx, p+1);
1692 if (!fname_dir || !fname_mask) {
1693 TALLOC_FREE(fname_dir);
1694 TALLOC_FREE(fname_mask);
1695 return NT_STATUS_NO_MEMORY;
1698 *fname_dir_out = fname_dir;
1699 *fname_mask_out = fname_mask;
1700 return NT_STATUS_OK;
1703 /****************************************************************************
1705 ****************************************************************************/
1707 static bool make_dir_struct(TALLOC_CTX *ctx,
1717 char *mask2 = talloc_strdup(ctx, mask);
1723 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1727 memset(buf+1,' ',11);
1728 if ((p = strchr_m(mask2,'.')) != NULL) {
1730 push_ascii(buf+1,mask2,8, 0);
1731 push_ascii(buf+9,p+1,3, 0);
1734 push_ascii(buf+1,mask2,11, 0);
1737 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1739 srv_put_dos_date(buf,22,date);
1740 SSVAL(buf,26,size & 0xFFFF);
1741 SSVAL(buf,28,(size >> 16)&0xFFFF);
1742 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1743 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1744 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1745 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1749 /****************************************************************************
1751 Can be called from SMBsearch, SMBffirst or SMBfunique.
1752 ****************************************************************************/
1754 void reply_search(struct smb_request *req)
1756 connection_struct *conn = req->conn;
1759 char *directory = NULL;
1760 struct smb_filename *smb_fname = NULL;
1764 struct timespec date;
1766 unsigned int numentries = 0;
1767 unsigned int maxentries = 0;
1768 bool finished = False;
1773 bool check_descend = False;
1774 bool expect_close = False;
1776 bool mask_contains_wcard = False;
1777 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1778 TALLOC_CTX *ctx = talloc_tos();
1779 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1780 struct smbXsrv_connection *xconn = req->xconn;
1781 struct smbd_server_connection *sconn = req->sconn;
1782 files_struct *fsp = NULL;
1783 const struct loadparm_substitution *lp_sub =
1784 loadparm_s3_global_substitution();
1786 START_PROFILE(SMBsearch);
1789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1793 if (req->posix_pathnames) {
1794 reply_unknown_new(req, req->cmd);
1798 /* If we were called as SMBffirst then we must expect close. */
1799 if(req->cmd == SMBffirst) {
1800 expect_close = True;
1803 reply_outbuf(req, 1, 3);
1804 maxentries = SVAL(req->vwv+0, 0);
1805 dirtype = SVAL(req->vwv+1, 0);
1806 p = (const char *)req->buf + 1;
1807 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1808 &nt_status, &mask_contains_wcard);
1809 if (!NT_STATUS_IS_OK(nt_status)) {
1810 reply_nterror(req, nt_status);
1814 if (smbreq_bufrem(req, p) < 3) {
1815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1820 status_len = SVAL(p, 0);
1823 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1825 if (status_len == 0) {
1827 struct smb_filename *smb_dname = NULL;
1828 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1829 ucf_flags_from_smb_request(req);
1830 nt_status = filename_convert(ctx, conn,
1834 &mask_contains_wcard,
1836 if (!NT_STATUS_IS_OK(nt_status)) {
1837 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1838 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1839 ERRSRV, ERRbadpath);
1842 reply_nterror(req, nt_status);
1846 directory = smb_fname->base_name;
1848 p = strrchr_m(directory,'/');
1849 if ((p != NULL) && (*directory != '/')) {
1850 mask = talloc_strdup(ctx, p + 1);
1851 directory = talloc_strndup(ctx, directory,
1852 PTR_DIFF(p, directory));
1854 mask = talloc_strdup(ctx, directory);
1855 directory = talloc_strdup(ctx,".");
1859 reply_nterror(req, NT_STATUS_NO_MEMORY);
1863 memset((char *)status,'\0',21);
1864 SCVAL(status,0,(dirtype & 0x1F));
1866 smb_dname = synthetic_smb_fname(talloc_tos(),
1871 if (smb_dname == NULL) {
1872 reply_nterror(req, NT_STATUS_NO_MEMORY);
1877 * As we've cut off the last component from
1878 * smb_fname we need to re-stat smb_dname
1879 * so FILE_OPEN disposition knows the directory
1882 if (req->posix_pathnames) {
1883 ret = SMB_VFS_LSTAT(conn, smb_dname);
1885 ret = SMB_VFS_STAT(conn, smb_dname);
1888 nt_status = map_nt_error_from_unix(errno);
1889 reply_nterror(req, nt_status);
1894 * Open an fsp on this directory for the dptr.
1896 nt_status = SMB_VFS_CREATE_FILE(
1899 0, /* root_dir_fid */
1900 smb_dname, /* dname */
1901 FILE_LIST_DIRECTORY, /* access_mask */
1903 FILE_SHARE_WRITE, /* share_access */
1904 FILE_OPEN, /* create_disposition*/
1905 FILE_DIRECTORY_FILE, /* create_options */
1906 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1907 NO_OPLOCK, /* oplock_request */
1909 0, /* allocation_size */
1910 0, /* private_flags */
1915 NULL, /* in_context */
1916 NULL);/* out_context */
1918 if (!NT_STATUS_IS_OK(nt_status)) {
1919 DBG_ERR("failed to open directory %s\n",
1920 smb_fname_str_dbg(smb_dname));
1921 reply_nterror(req, nt_status);
1925 nt_status = dptr_create(conn,
1932 mask_contains_wcard,
1936 TALLOC_FREE(smb_dname);
1938 if (!NT_STATUS_IS_OK(nt_status)) {
1940 * Use NULL here for the first parameter (req)
1941 * as this is not a client visible handle so
1942 * can'tbe part of an SMB1 chain.
1944 close_file(NULL, fsp, NORMAL_CLOSE);
1946 reply_nterror(req, nt_status);
1950 dptr_num = dptr_dnum(fsp->dptr);
1954 const char *dirpath;
1956 if (smbreq_bufrem(req, p) < 21) {
1957 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1961 memcpy(status,p,21);
1962 status_dirtype = CVAL(status,0) & 0x1F;
1963 if (status_dirtype != (dirtype & 0x1F)) {
1964 dirtype = status_dirtype;
1967 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1971 dirpath = dptr_path(sconn, dptr_num);
1972 directory = talloc_strdup(ctx, dirpath);
1974 reply_nterror(req, NT_STATUS_NO_MEMORY);
1978 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1983 * For a 'continue' search we have no string. So
1984 * check from the initial saved string.
1986 if (!req->posix_pathnames) {
1987 mask_contains_wcard = ms_has_wild(mask);
1989 dirtype = dptr_attr(sconn, dptr_num);
1992 DEBUG(4,("dptr_num is %d\n",dptr_num));
1994 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1995 char buf[DIR_STRUCT_SIZE];
1996 memcpy(buf,status,21);
1997 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1998 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1999 reply_nterror(req, NT_STATUS_NO_MEMORY);
2002 dptr_fill(sconn, buf+12,dptr_num);
2003 if (dptr_zero(buf+12) && (status_len==0)) {
2008 if (message_push_blob(&req->outbuf,
2009 data_blob_const(buf, sizeof(buf)))
2011 reply_nterror(req, NT_STATUS_NO_MEMORY);
2016 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
2017 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
2019 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
2021 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2022 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
2023 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
2024 check_descend = True;
2027 for (i=numentries;(i<maxentries) && !finished;i++) {
2028 finished = !get_dir_entry(ctx,
2039 char buf[DIR_STRUCT_SIZE];
2040 memcpy(buf,status,21);
2041 if (!make_dir_struct(ctx,
2047 convert_timespec_to_time_t(date),
2048 !allow_long_path_components)) {
2049 reply_nterror(req, NT_STATUS_NO_MEMORY);
2052 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2055 if (message_push_blob(&req->outbuf,
2056 data_blob_const(buf, sizeof(buf)))
2058 reply_nterror(req, NT_STATUS_NO_MEMORY);
2068 /* If we were called as SMBffirst with smb_search_id == NULL
2069 and no entries were found then return error and close fsp->dptr
2072 if (numentries == 0) {
2075 close_file(NULL, fsp, NORMAL_CLOSE);
2078 } else if(expect_close && status_len == 0) {
2079 /* Close the dptr - we know it's gone */
2082 close_file(NULL, fsp, NORMAL_CLOSE);
2087 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2088 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2090 /* fsp may have been closed above. */
2092 close_file(NULL, fsp, NORMAL_CLOSE);
2097 if ((numentries == 0) && !mask_contains_wcard) {
2098 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2102 SSVAL(req->outbuf,smb_vwv0,numentries);
2103 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2104 SCVAL(smb_buf(req->outbuf),0,5);
2105 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2107 /* The replies here are never long name. */
2108 SSVAL(req->outbuf, smb_flg2,
2109 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2110 if (!allow_long_path_components) {
2111 SSVAL(req->outbuf, smb_flg2,
2112 SVAL(req->outbuf, smb_flg2)
2113 & (~FLAGS2_LONG_PATH_COMPONENTS));
2116 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2117 SSVAL(req->outbuf, smb_flg2,
2118 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2120 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2121 smb_fn_name(req->cmd),
2128 TALLOC_FREE(directory);
2130 TALLOC_FREE(smb_fname);
2131 END_PROFILE(SMBsearch);
2135 /****************************************************************************
2136 Reply to a fclose (stop directory search).
2137 ****************************************************************************/
2139 void reply_fclose(struct smb_request *req)
2147 bool path_contains_wcard = False;
2148 TALLOC_CTX *ctx = talloc_tos();
2149 struct smbd_server_connection *sconn = req->sconn;
2150 files_struct *fsp = NULL;
2152 START_PROFILE(SMBfclose);
2154 if (req->posix_pathnames) {
2155 reply_unknown_new(req, req->cmd);
2156 END_PROFILE(SMBfclose);
2160 p = (const char *)req->buf + 1;
2161 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2162 &err, &path_contains_wcard);
2163 if (!NT_STATUS_IS_OK(err)) {
2164 reply_nterror(req, err);
2165 END_PROFILE(SMBfclose);
2169 if (smbreq_bufrem(req, p) < 3) {
2170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2171 END_PROFILE(SMBfclose);
2176 status_len = SVAL(p,0);
2179 if (status_len == 0) {
2180 reply_force_doserror(req, ERRSRV, ERRsrverror);
2181 END_PROFILE(SMBfclose);
2185 if (smbreq_bufrem(req, p) < 21) {
2186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2187 END_PROFILE(SMBfclose);
2191 memcpy(status,p,21);
2193 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2195 /* Close the file - we know it's gone */
2196 close_file(NULL, fsp, NORMAL_CLOSE);
2201 reply_outbuf(req, 1, 0);
2202 SSVAL(req->outbuf,smb_vwv0,0);
2204 DEBUG(3,("search close\n"));
2206 END_PROFILE(SMBfclose);
2210 /****************************************************************************
2212 ****************************************************************************/
2214 void reply_open(struct smb_request *req)
2216 connection_struct *conn = req->conn;
2217 struct smb_filename *smb_fname = NULL;
2227 uint32_t access_mask;
2228 uint32_t share_mode;
2229 uint32_t create_disposition;
2230 uint32_t create_options = 0;
2231 uint32_t private_flags = 0;
2234 TALLOC_CTX *ctx = talloc_tos();
2236 START_PROFILE(SMBopen);
2239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2243 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2244 deny_mode = SVAL(req->vwv+0, 0);
2245 dos_attr = SVAL(req->vwv+1, 0);
2247 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2248 STR_TERMINATE, &status);
2249 if (!NT_STATUS_IS_OK(status)) {
2250 reply_nterror(req, status);
2254 if (!map_open_params_to_ntcreate(fname, deny_mode,
2255 OPENX_FILE_EXISTS_OPEN, &access_mask,
2256 &share_mode, &create_disposition,
2257 &create_options, &private_flags)) {
2258 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2262 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2264 status = filename_convert(ctx,
2271 if (!NT_STATUS_IS_OK(status)) {
2272 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2273 reply_botherror(req,
2274 NT_STATUS_PATH_NOT_COVERED,
2275 ERRSRV, ERRbadpath);
2278 reply_nterror(req, status);
2282 status = SMB_VFS_CREATE_FILE(
2285 0, /* root_dir_fid */
2286 smb_fname, /* fname */
2287 access_mask, /* access_mask */
2288 share_mode, /* share_access */
2289 create_disposition, /* create_disposition*/
2290 create_options, /* create_options */
2291 dos_attr, /* file_attributes */
2292 oplock_request, /* oplock_request */
2294 0, /* allocation_size */
2300 NULL, NULL); /* create context */
2302 if (!NT_STATUS_IS_OK(status)) {
2303 if (open_was_deferred(req->xconn, req->mid)) {
2304 /* We have re-scheduled this call. */
2308 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2309 reply_openerror(req, status);
2313 fsp = fcb_or_dos_open(
2320 bool ok = defer_smb1_sharing_violation(req);
2324 reply_openerror(req, status);
2329 /* Ensure we're pointing at the correct stat struct. */
2330 TALLOC_FREE(smb_fname);
2331 smb_fname = fsp->fsp_name;
2333 size = smb_fname->st.st_ex_size;
2334 fattr = dos_mode(conn, smb_fname);
2336 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2338 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2339 DEBUG(3,("attempt to open a directory %s\n",
2341 close_file(req, fsp, ERROR_CLOSE);
2342 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2343 ERRDOS, ERRnoaccess);
2347 reply_outbuf(req, 7, 0);
2348 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2349 SSVAL(req->outbuf,smb_vwv1,fattr);
2350 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2351 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2353 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2355 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2356 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2358 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2359 SCVAL(req->outbuf,smb_flg,
2360 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2363 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2364 SCVAL(req->outbuf,smb_flg,
2365 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2368 END_PROFILE(SMBopen);
2372 /****************************************************************************
2373 Reply to an open and X.
2374 ****************************************************************************/
2376 void reply_open_and_X(struct smb_request *req)
2378 connection_struct *conn = req->conn;
2379 struct smb_filename *smb_fname = NULL;
2381 uint16_t open_flags;
2384 /* Breakout the oplock request bits so we can set the
2385 reply bits separately. */
2386 int ex_oplock_request;
2387 int core_oplock_request;
2390 int smb_sattr = SVAL(req->vwv+4, 0);
2391 uint32_t smb_time = make_unix_date3(req->vwv+6);
2399 uint64_t allocation_size;
2400 ssize_t retval = -1;
2401 uint32_t access_mask;
2402 uint32_t share_mode;
2403 uint32_t create_disposition;
2404 uint32_t create_options = 0;
2405 uint32_t private_flags = 0;
2407 TALLOC_CTX *ctx = talloc_tos();
2409 START_PROFILE(SMBopenX);
2411 if (req->wct < 15) {
2412 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2416 open_flags = SVAL(req->vwv+2, 0);
2417 deny_mode = SVAL(req->vwv+3, 0);
2418 smb_attr = SVAL(req->vwv+5, 0);
2419 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2420 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2421 oplock_request = ex_oplock_request | core_oplock_request;
2422 smb_ofun = SVAL(req->vwv+8, 0);
2423 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2425 /* If it's an IPC, pass off the pipe handler. */
2427 if (lp_nt_pipe_support()) {
2428 reply_open_pipe_and_X(conn, req);
2430 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2435 /* XXXX we need to handle passed times, sattr and flags */
2436 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2437 STR_TERMINATE, &status);
2438 if (!NT_STATUS_IS_OK(status)) {
2439 reply_nterror(req, status);
2443 if (!map_open_params_to_ntcreate(fname, deny_mode,
2445 &access_mask, &share_mode,
2446 &create_disposition,
2449 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2453 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2455 status = filename_convert(ctx,
2462 if (!NT_STATUS_IS_OK(status)) {
2463 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2464 reply_botherror(req,
2465 NT_STATUS_PATH_NOT_COVERED,
2466 ERRSRV, ERRbadpath);
2469 reply_nterror(req, status);
2473 status = SMB_VFS_CREATE_FILE(
2476 0, /* root_dir_fid */
2477 smb_fname, /* fname */
2478 access_mask, /* access_mask */
2479 share_mode, /* share_access */
2480 create_disposition, /* create_disposition*/
2481 create_options, /* create_options */
2482 smb_attr, /* file_attributes */
2483 oplock_request, /* oplock_request */
2485 0, /* allocation_size */
2490 &smb_action, /* pinfo */
2491 NULL, NULL); /* create context */
2493 if (!NT_STATUS_IS_OK(status)) {
2494 if (open_was_deferred(req->xconn, req->mid)) {
2495 /* We have re-scheduled this call. */
2499 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2500 reply_openerror(req, status);
2504 fsp = fcb_or_dos_open(
2511 bool ok = defer_smb1_sharing_violation(req);
2515 reply_openerror(req, status);
2520 smb_action = FILE_WAS_OPENED;
2523 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2524 if the file is truncated or created. */
2525 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2526 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2527 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2528 close_file(req, fsp, ERROR_CLOSE);
2529 reply_nterror(req, NT_STATUS_DISK_FULL);
2532 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2534 close_file(req, fsp, ERROR_CLOSE);
2535 reply_nterror(req, NT_STATUS_DISK_FULL);
2538 status = vfs_stat_fsp(fsp);
2539 if (!NT_STATUS_IS_OK(status)) {
2540 close_file(req, fsp, ERROR_CLOSE);
2541 reply_nterror(req, status);
2546 fattr = dos_mode(conn, fsp->fsp_name);
2547 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2548 close_file(req, fsp, ERROR_CLOSE);
2549 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2552 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2554 /* If the caller set the extended oplock request bit
2555 and we granted one (by whatever means) - set the
2556 correct bit for extended oplock reply.
2559 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2560 smb_action |= EXTENDED_OPLOCK_GRANTED;
2563 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2564 smb_action |= EXTENDED_OPLOCK_GRANTED;
2567 /* If the caller set the core oplock request bit
2568 and we granted one (by whatever means) - set the
2569 correct bit for core oplock reply.
2572 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2573 reply_outbuf(req, 19, 0);
2575 reply_outbuf(req, 15, 0);
2578 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2579 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2581 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2582 SCVAL(req->outbuf, smb_flg,
2583 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2586 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2587 SCVAL(req->outbuf, smb_flg,
2588 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2591 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2592 SSVAL(req->outbuf,smb_vwv3,fattr);
2593 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2594 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2596 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2598 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2599 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2600 SSVAL(req->outbuf,smb_vwv11,smb_action);
2602 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2603 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2607 TALLOC_FREE(smb_fname);
2608 END_PROFILE(SMBopenX);
2612 /****************************************************************************
2613 Reply to a SMBulogoffX.
2614 ****************************************************************************/
2616 void reply_ulogoffX(struct smb_request *req)
2618 struct timeval now = timeval_current();
2619 struct smbXsrv_session *session = NULL;
2622 START_PROFILE(SMBulogoffX);
2624 status = smb1srv_session_lookup(req->xconn,
2626 timeval_to_nttime(&now),
2628 if (!NT_STATUS_IS_OK(status)) {
2629 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2630 (unsigned long long)req->vuid));
2632 req->vuid = UID_FIELD_INVALID;
2633 reply_force_doserror(req, ERRSRV, ERRbaduid);
2634 END_PROFILE(SMBulogoffX);
2639 * TODO: cancel all outstanding requests on the session
2641 status = smbXsrv_session_logoff(session);
2642 if (!NT_STATUS_IS_OK(status)) {
2643 DEBUG(0, ("reply_ulogoff: "
2644 "smbXsrv_session_logoff() failed: %s\n",
2645 nt_errstr(status)));
2647 * If we hit this case, there is something completely
2648 * wrong, so we better disconnect the transport connection.
2650 END_PROFILE(SMBulogoffX);
2651 exit_server(__location__ ": smbXsrv_session_logoff failed");
2655 TALLOC_FREE(session);
2657 reply_outbuf(req, 2, 0);
2658 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2659 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2661 DEBUG(3, ("ulogoffX vuid=%llu\n",
2662 (unsigned long long)req->vuid));
2664 END_PROFILE(SMBulogoffX);
2665 req->vuid = UID_FIELD_INVALID;
2668 /****************************************************************************
2669 Reply to a mknew or a create.
2670 ****************************************************************************/
2672 void reply_mknew(struct smb_request *req)
2674 connection_struct *conn = req->conn;
2675 struct smb_filename *smb_fname = NULL;
2678 struct smb_file_time ft;
2680 int oplock_request = 0;
2682 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2683 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2684 uint32_t create_disposition;
2685 uint32_t create_options = 0;
2687 TALLOC_CTX *ctx = talloc_tos();
2689 START_PROFILE(SMBcreate);
2690 init_smb_file_time(&ft);
2693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2697 fattr = SVAL(req->vwv+0, 0);
2698 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2700 if (req->cmd == SMBmknew) {
2701 /* We should fail if file exists. */
2702 create_disposition = FILE_CREATE;
2704 /* Create if file doesn't exist, truncate if it does. */
2705 create_disposition = FILE_OVERWRITE_IF;
2709 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2711 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2712 STR_TERMINATE, &status);
2713 if (!NT_STATUS_IS_OK(status)) {
2714 reply_nterror(req, status);
2718 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2719 status = filename_convert(ctx,
2726 if (!NT_STATUS_IS_OK(status)) {
2727 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2728 reply_botherror(req,
2729 NT_STATUS_PATH_NOT_COVERED,
2730 ERRSRV, ERRbadpath);
2733 reply_nterror(req, status);
2737 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2738 DEBUG(0,("Attempt to create file (%s) with volid set - "
2739 "please report this\n",
2740 smb_fname_str_dbg(smb_fname)));
2743 status = SMB_VFS_CREATE_FILE(
2746 0, /* root_dir_fid */
2747 smb_fname, /* fname */
2748 access_mask, /* access_mask */
2749 share_mode, /* share_access */
2750 create_disposition, /* create_disposition*/
2751 create_options, /* create_options */
2752 fattr, /* file_attributes */
2753 oplock_request, /* oplock_request */
2755 0, /* allocation_size */
2756 0, /* private_flags */
2761 NULL, NULL); /* create context */
2763 if (!NT_STATUS_IS_OK(status)) {
2764 if (open_was_deferred(req->xconn, req->mid)) {
2765 /* We have re-scheduled this call. */
2768 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2769 bool ok = defer_smb1_sharing_violation(req);
2774 reply_openerror(req, status);
2778 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2779 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2780 if (!NT_STATUS_IS_OK(status)) {
2781 END_PROFILE(SMBcreate);
2785 reply_outbuf(req, 1, 0);
2786 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2788 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2789 SCVAL(req->outbuf,smb_flg,
2790 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2793 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2794 SCVAL(req->outbuf,smb_flg,
2795 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2798 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2799 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2800 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2801 (unsigned int)fattr));
2804 TALLOC_FREE(smb_fname);
2805 END_PROFILE(SMBcreate);
2809 /****************************************************************************
2810 Reply to a create temporary file.
2811 ****************************************************************************/
2813 void reply_ctemp(struct smb_request *req)
2815 connection_struct *conn = req->conn;
2816 struct smb_filename *smb_fname = NULL;
2817 char *wire_name = NULL;
2826 TALLOC_CTX *ctx = talloc_tos();
2828 START_PROFILE(SMBctemp);
2831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2835 fattr = SVAL(req->vwv+0, 0);
2836 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2838 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2839 STR_TERMINATE, &status);
2840 if (!NT_STATUS_IS_OK(status)) {
2841 reply_nterror(req, status);
2845 for (i = 0; i < 10; i++) {
2847 fname = talloc_asprintf(ctx,
2850 generate_random_str_list(ctx, 5, "0123456789"));
2852 fname = talloc_asprintf(ctx,
2854 generate_random_str_list(ctx, 5, "0123456789"));
2858 reply_nterror(req, NT_STATUS_NO_MEMORY);
2862 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2863 status = filename_convert(ctx, conn,
2869 if (!NT_STATUS_IS_OK(status)) {
2870 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2871 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2872 ERRSRV, ERRbadpath);
2875 reply_nterror(req, status);
2879 /* Create the file. */
2880 status = SMB_VFS_CREATE_FILE(
2883 0, /* root_dir_fid */
2884 smb_fname, /* fname */
2885 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2886 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2887 FILE_CREATE, /* create_disposition*/
2888 0, /* create_options */
2889 fattr, /* file_attributes */
2890 oplock_request, /* oplock_request */
2892 0, /* allocation_size */
2893 0, /* private_flags */
2898 NULL, NULL); /* create context */
2900 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2902 TALLOC_FREE(smb_fname);
2906 if (!NT_STATUS_IS_OK(status)) {
2907 if (open_was_deferred(req->xconn, req->mid)) {
2908 /* We have re-scheduled this call. */
2911 if (NT_STATUS_EQUAL(
2912 status, NT_STATUS_SHARING_VIOLATION)) {
2913 bool ok = defer_smb1_sharing_violation(req);
2918 reply_openerror(req, status);
2926 /* Collision after 10 times... */
2927 reply_nterror(req, status);
2931 reply_outbuf(req, 1, 0);
2932 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2934 /* the returned filename is relative to the directory */
2935 s = strrchr_m(fsp->fsp_name->base_name, '/');
2937 s = fsp->fsp_name->base_name;
2943 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2944 thing in the byte section. JRA */
2945 SSVALS(p, 0, -1); /* what is this? not in spec */
2947 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2949 reply_nterror(req, NT_STATUS_NO_MEMORY);
2953 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2954 SCVAL(req->outbuf, smb_flg,
2955 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2958 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2959 SCVAL(req->outbuf, smb_flg,
2960 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2963 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2964 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2965 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2967 TALLOC_FREE(smb_fname);
2968 TALLOC_FREE(wire_name);
2969 END_PROFILE(SMBctemp);
2973 /*******************************************************************
2974 Check if a user is allowed to rename a file.
2975 ********************************************************************/
2977 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2980 if (!CAN_WRITE(conn)) {
2981 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2984 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2985 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2986 /* Only bother to read the DOS attribute if we might deny the
2987 rename on the grounds of attribute mismatch. */
2988 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2989 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2990 return NT_STATUS_NO_SUCH_FILE;
2994 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2995 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2996 return NT_STATUS_OK;
2999 /* If no pathnames are open below this
3000 directory, allow the rename. */
3002 if (lp_strict_rename(SNUM(conn))) {
3004 * Strict rename, check open file db.
3006 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3007 return NT_STATUS_ACCESS_DENIED;
3009 } else if (file_find_subpath(fsp)) {
3011 * No strict rename, just look in local process.
3013 return NT_STATUS_ACCESS_DENIED;
3015 return NT_STATUS_OK;
3018 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3019 return NT_STATUS_OK;
3022 return NT_STATUS_ACCESS_DENIED;
3025 /*******************************************************************
3026 * unlink a file with all relevant access checks
3027 *******************************************************************/
3029 static NTSTATUS do_unlink(connection_struct *conn,
3030 struct smb_request *req,
3031 struct smb_filename *smb_fname,
3036 uint32_t dirtype_orig = dirtype;
3039 bool posix_paths = (req != NULL && req->posix_pathnames);
3040 struct smb2_create_blobs *posx = NULL;
3042 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3043 smb_fname_str_dbg(smb_fname),
3046 if (!CAN_WRITE(conn)) {
3047 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3051 ret = SMB_VFS_LSTAT(conn, smb_fname);
3053 ret = SMB_VFS_STAT(conn, smb_fname);
3056 return map_nt_error_from_unix(errno);
3059 fattr = dos_mode(conn, smb_fname);
3061 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3062 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3065 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3067 return NT_STATUS_NO_SUCH_FILE;
3070 if (!dir_check_ftype(fattr, dirtype)) {
3071 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3072 return NT_STATUS_FILE_IS_A_DIRECTORY;
3074 return NT_STATUS_NO_SUCH_FILE;
3077 if (dirtype_orig & 0x8000) {
3078 /* These will never be set for POSIX. */
3079 return NT_STATUS_NO_SUCH_FILE;
3083 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3084 return NT_STATUS_FILE_IS_A_DIRECTORY;
3087 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3088 return NT_STATUS_NO_SUCH_FILE;
3091 if (dirtype & 0xFF00) {
3092 /* These will never be set for POSIX. */
3093 return NT_STATUS_NO_SUCH_FILE;
3098 return NT_STATUS_NO_SUCH_FILE;
3101 /* Can't delete a directory. */
3102 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3103 return NT_STATUS_FILE_IS_A_DIRECTORY;
3108 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3109 return NT_STATUS_OBJECT_NAME_INVALID;
3110 #endif /* JRATEST */
3113 status = make_smb2_posix_create_ctx(
3114 talloc_tos(), &posx, 0777);
3115 if (!NT_STATUS_IS_OK(status)) {
3116 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3122 /* On open checks the open itself will check the share mode, so
3123 don't do it here as we'll get it wrong. */
3125 status = SMB_VFS_CREATE_FILE
3128 0, /* root_dir_fid */
3129 smb_fname, /* fname */
3130 DELETE_ACCESS, /* access_mask */
3131 FILE_SHARE_NONE, /* share_access */
3132 FILE_OPEN, /* create_disposition*/
3133 FILE_NON_DIRECTORY_FILE, /* create_options */
3134 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3135 0, /* oplock_request */
3137 0, /* allocation_size */
3138 0, /* private_flags */
3143 posx, /* in_context_blobs */
3144 NULL); /* out_context_blobs */
3148 if (!NT_STATUS_IS_OK(status)) {
3149 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3150 nt_errstr(status)));
3154 status = can_set_delete_on_close(fsp, fattr);
3155 if (!NT_STATUS_IS_OK(status)) {
3156 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3158 smb_fname_str_dbg(smb_fname),
3159 nt_errstr(status)));
3160 close_file(req, fsp, NORMAL_CLOSE);
3164 /* The set is across all open files on this dev/inode pair. */
3165 if (!set_delete_on_close(fsp, True,
3166 conn->session_info->security_token,
3167 conn->session_info->unix_token)) {
3168 close_file(req, fsp, NORMAL_CLOSE);
3169 return NT_STATUS_ACCESS_DENIED;
3172 return close_file(req, fsp, NORMAL_CLOSE);
3175 /****************************************************************************
3176 The guts of the unlink command, split out so it may be called by the NT SMB
3178 ****************************************************************************/
3180 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3181 uint32_t dirtype, struct smb_filename *smb_fname,
3184 char *fname_dir = NULL;
3185 char *fname_mask = NULL;
3187 NTSTATUS status = NT_STATUS_OK;
3188 struct smb_filename *smb_fname_dir = NULL;
3189 TALLOC_CTX *ctx = talloc_tos();
3191 /* Split up the directory from the filename/mask. */
3192 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3193 &fname_dir, &fname_mask);
3194 if (!NT_STATUS_IS_OK(status)) {
3199 * We should only check the mangled cache
3200 * here if unix_convert failed. This means
3201 * that the path in 'mask' doesn't exist
3202 * on the file system and so we need to look
3203 * for a possible mangle. This patch from
3204 * Tine Smukavec <valentin.smukavec@hermes.si>.
3207 if (!VALID_STAT(smb_fname->st) &&
3208 mangle_is_mangled(fname_mask, conn->params)) {
3209 char *new_mask = NULL;
3210 mangle_lookup_name_from_8_3(ctx, fname_mask,
3211 &new_mask, conn->params);
3213 TALLOC_FREE(fname_mask);
3214 fname_mask = new_mask;
3221 * Only one file needs to be unlinked. Append the mask back
3222 * onto the directory.
3224 TALLOC_FREE(smb_fname->base_name);
3225 if (ISDOT(fname_dir)) {
3226 /* Ensure we use canonical names on open. */
3227 smb_fname->base_name = talloc_asprintf(smb_fname,
3231 smb_fname->base_name = talloc_asprintf(smb_fname,
3236 if (!smb_fname->base_name) {
3237 status = NT_STATUS_NO_MEMORY;
3241 dirtype = FILE_ATTRIBUTE_NORMAL;
3244 status = check_name(conn, smb_fname);
3245 if (!NT_STATUS_IS_OK(status)) {
3249 status = do_unlink(conn, req, smb_fname, dirtype);
3250 if (!NT_STATUS_IS_OK(status)) {
3256 struct smb_Dir *dir_hnd = NULL;
3258 const char *dname = NULL;
3259 char *talloced = NULL;
3261 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3262 status = NT_STATUS_OBJECT_NAME_INVALID;
3266 dirtype = FILE_ATTRIBUTE_NORMAL;
3269 if (strequal(fname_mask,"????????.???")) {
3270 TALLOC_FREE(fname_mask);
3271 fname_mask = talloc_strdup(ctx, "*");
3273 status = NT_STATUS_NO_MEMORY;
3278 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3283 if (smb_fname_dir == NULL) {
3284 status = NT_STATUS_NO_MEMORY;
3288 status = check_name(conn, smb_fname_dir);
3289 if (!NT_STATUS_IS_OK(status)) {
3293 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3295 if (dir_hnd == NULL) {
3296 status = map_nt_error_from_unix(errno);
3300 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3301 the pattern matches against the long name, otherwise the short name
3302 We don't implement this yet XXXX
3305 status = NT_STATUS_NO_SUCH_FILE;
3307 while ((dname = ReadDirName(dir_hnd, &offset,
3308 &smb_fname->st, &talloced))) {
3309 TALLOC_CTX *frame = talloc_stackframe();
3311 if (!is_visible_file(conn, fname_dir, dname,
3312 &smb_fname->st, true)) {
3314 TALLOC_FREE(talloced);
3318 /* Quick check for "." and ".." */
3319 if (ISDOT(dname) || ISDOTDOT(dname)) {
3321 TALLOC_FREE(talloced);
3325 if(!mask_match(dname, fname_mask,
3326 conn->case_sensitive)) {
3328 TALLOC_FREE(talloced);
3332 TALLOC_FREE(smb_fname->base_name);
3333 if (ISDOT(fname_dir)) {
3334 /* Ensure we use canonical names on open. */
3335 smb_fname->base_name =
3336 talloc_asprintf(smb_fname, "%s",
3339 smb_fname->base_name =
3340 talloc_asprintf(smb_fname, "%s/%s",
3344 if (!smb_fname->base_name) {
3345 TALLOC_FREE(dir_hnd);
3346 status = NT_STATUS_NO_MEMORY;
3348 TALLOC_FREE(talloced);
3352 status = check_name(conn, smb_fname);
3353 if (!NT_STATUS_IS_OK(status)) {
3354 TALLOC_FREE(dir_hnd);
3356 TALLOC_FREE(talloced);
3360 status = do_unlink(conn, req, smb_fname, dirtype);
3361 if (!NT_STATUS_IS_OK(status)) {
3362 TALLOC_FREE(dir_hnd);
3364 TALLOC_FREE(talloced);
3369 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3370 smb_fname->base_name));
3373 TALLOC_FREE(talloced);
3375 TALLOC_FREE(dir_hnd);
3378 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3379 status = map_nt_error_from_unix(errno);
3383 TALLOC_FREE(smb_fname_dir);
3384 TALLOC_FREE(fname_dir);
3385 TALLOC_FREE(fname_mask);
3389 /****************************************************************************
3391 ****************************************************************************/
3393 void reply_unlink(struct smb_request *req)
3395 connection_struct *conn = req->conn;
3397 struct smb_filename *smb_fname = NULL;
3400 bool path_contains_wcard = False;
3401 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3402 ucf_flags_from_smb_request(req);
3403 TALLOC_CTX *ctx = talloc_tos();
3405 START_PROFILE(SMBunlink);
3408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3412 dirtype = SVAL(req->vwv+0, 0);
3414 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3415 STR_TERMINATE, &status,
3416 &path_contains_wcard);
3417 if (!NT_STATUS_IS_OK(status)) {
3418 reply_nterror(req, status);
3422 status = filename_convert(ctx, conn,
3426 &path_contains_wcard,
3428 if (!NT_STATUS_IS_OK(status)) {
3429 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3430 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3431 ERRSRV, ERRbadpath);
3434 reply_nterror(req, status);
3438 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3440 status = unlink_internals(conn, req, dirtype, smb_fname,
3441 path_contains_wcard);
3442 if (!NT_STATUS_IS_OK(status)) {
3443 if (open_was_deferred(req->xconn, req->mid)) {
3444 /* We have re-scheduled this call. */
3447 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3448 bool ok = defer_smb1_sharing_violation(req);
3453 reply_nterror(req, status);
3457 reply_outbuf(req, 0, 0);
3459 TALLOC_FREE(smb_fname);
3460 END_PROFILE(SMBunlink);
3464 /****************************************************************************
3466 ****************************************************************************/
3468 static void fail_readraw(void)
3470 const char *errstr = talloc_asprintf(talloc_tos(),
3471 "FAIL ! reply_readbraw: socket write fail (%s)",
3476 exit_server_cleanly(errstr);
3479 /****************************************************************************
3480 Fake (read/write) sendfile. Returns -1 on read or write fail.
3481 ****************************************************************************/
3483 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3484 off_t startpos, size_t nread)
3487 size_t tosend = nread;
3494 bufsize = MIN(nread, 65536);
3496 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3500 while (tosend > 0) {
3504 cur_read = MIN(tosend, bufsize);
3505 ret = read_file(fsp,buf,startpos,cur_read);
3511 /* If we had a short read, fill with zeros. */
3512 if (ret < cur_read) {
3513 memset(buf + ret, '\0', cur_read - ret);
3516 ret = write_data(xconn->transport.sock, buf, cur_read);
3517 if (ret != cur_read) {
3518 int saved_errno = errno;
3520 * Try and give an error message saying what
3523 DEBUG(0, ("write_data failed for client %s. "
3525 smbXsrv_connection_dbg(xconn),
3526 strerror(saved_errno)));
3528 errno = saved_errno;
3532 startpos += cur_read;
3536 return (ssize_t)nread;
3539 /****************************************************************************
3540 Deal with the case of sendfile reading less bytes from the file than
3541 requested. Fill with zeros (all we can do). Returns 0 on success
3542 ****************************************************************************/
3544 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3550 #define SHORT_SEND_BUFSIZE 1024
3551 if (nread < headersize) {
3552 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3553 "header for file %s (%s). Terminating\n",
3554 fsp_str_dbg(fsp), strerror(errno)));
3558 nread -= headersize;
3560 if (nread < smb_maxcnt) {
3561 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3563 DEBUG(0,("sendfile_short_send: malloc failed "
3564 "for file %s (%s). Terminating\n",
3565 fsp_str_dbg(fsp), strerror(errno)));
3569 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3570 "with zeros !\n", fsp_str_dbg(fsp)));
3572 while (nread < smb_maxcnt) {
3574 * We asked for the real file size and told sendfile
3575 * to not go beyond the end of the file. But it can
3576 * happen that in between our fstat call and the
3577 * sendfile call the file was truncated. This is very
3578 * bad because we have already announced the larger
3579 * number of bytes to the client.
3581 * The best we can do now is to send 0-bytes, just as
3582 * a read from a hole in a sparse file would do.
3584 * This should happen rarely enough that I don't care
3585 * about efficiency here :-)
3590 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3591 ret = write_data(xconn->transport.sock, buf, to_write);
3592 if (ret != to_write) {
3593 int saved_errno = errno;
3595 * Try and give an error message saying what
3598 DEBUG(0, ("write_data failed for client %s. "
3600 smbXsrv_connection_dbg(xconn),
3601 strerror(saved_errno)));
3602 errno = saved_errno;
3613 /****************************************************************************
3614 Return a readbraw error (4 bytes of zero).
3615 ****************************************************************************/
3617 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3623 smbd_lock_socket(xconn);
3624 if (write_data(xconn->transport.sock,header,4) != 4) {
3625 int saved_errno = errno;
3627 * Try and give an error message saying what
3630 DEBUG(0, ("write_data failed for client %s. "
3632 smbXsrv_connection_dbg(xconn),
3633 strerror(saved_errno)));
3634 errno = saved_errno;
3638 smbd_unlock_socket(xconn);
3641 /*******************************************************************
3642 Ensure we don't use sendfile if server smb signing is active.
3643 ********************************************************************/
3645 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3647 bool sign_active = false;
3649 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3650 if (get_Protocol() < PROTOCOL_NT1) {
3653 if (signing_state) {
3654 sign_active = smb_signing_is_active(signing_state);
3656 return (lp__use_sendfile(snum) &&
3657 (get_remote_arch() != RA_WIN95) &&
3660 /****************************************************************************
3661 Use sendfile in readbraw.
3662 ****************************************************************************/
3664 static void send_file_readbraw(connection_struct *conn,
3665 struct smb_request *req,
3671 struct smbXsrv_connection *xconn = req->xconn;
3672 char *outbuf = NULL;
3676 * We can only use sendfile on a non-chained packet
3677 * but we can use on a non-oplocked file. tridge proved this
3678 * on a train in Germany :-). JRA.
3679 * reply_readbraw has already checked the length.
3682 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3683 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3684 ssize_t sendfile_read = -1;
3686 DATA_BLOB header_blob;
3688 _smb_setlen(header,nread);
3689 header_blob = data_blob_const(header, 4);
3691 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3692 &header_blob, startpos,
3694 if (sendfile_read == -1) {
3695 /* Returning ENOSYS means no data at all was sent.
3696 * Do this as a normal read. */
3697 if (errno == ENOSYS) {
3698 goto normal_readbraw;
3702 * Special hack for broken Linux with no working sendfile. If we
3703 * return EINTR we sent the header but not the rest of the data.
3704 * Fake this up by doing read/write calls.
3706 if (errno == EINTR) {
3707 /* Ensure we don't do this again. */
3708 set_use_sendfile(SNUM(conn), False);
3709 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3711 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3712 DEBUG(0,("send_file_readbraw: "
3713 "fake_sendfile failed for "
3717 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3722 DEBUG(0,("send_file_readbraw: sendfile failed for "
3723 "file %s (%s). Terminating\n",
3724 fsp_str_dbg(fsp), strerror(errno)));
3725 exit_server_cleanly("send_file_readbraw sendfile failed");
3726 } else if (sendfile_read == 0) {
3728 * Some sendfile implementations return 0 to indicate
3729 * that there was a short read, but nothing was
3730 * actually written to the socket. In this case,
3731 * fallback to the normal read path so the header gets
3732 * the correct byte count.
3734 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3735 "bytes falling back to the normal read: "
3736 "%s\n", fsp_str_dbg(fsp)));
3737 goto normal_readbraw;
3740 /* Deal with possible short send. */
3741 if (sendfile_read != 4+nread) {
3742 ret = sendfile_short_send(xconn, fsp,
3743 sendfile_read, 4, nread);
3753 outbuf = talloc_array(NULL, char, nread+4);
3755 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3756 (unsigned)(nread+4)));
3757 reply_readbraw_error(xconn);
3762 ret = read_file(fsp,outbuf+4,startpos,nread);
3763 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3772 _smb_setlen(outbuf,ret);
3773 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3774 int saved_errno = errno;
3776 * Try and give an error message saying what
3779 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3780 smbXsrv_connection_dbg(xconn),
3781 strerror(saved_errno)));
3782 errno = saved_errno;
3787 TALLOC_FREE(outbuf);
3790 /****************************************************************************
3791 Reply to a readbraw (core+ protocol).
3792 ****************************************************************************/
3794 void reply_readbraw(struct smb_request *req)
3796 connection_struct *conn = req->conn;
3797 struct smbXsrv_connection *xconn = req->xconn;
3798 ssize_t maxcount,mincount;
3802 struct lock_struct lock;
3806 START_PROFILE(SMBreadbraw);
3808 if (srv_is_signing_active(xconn) || req->encrypted) {
3809 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3810 "raw reads/writes are disallowed.");
3814 reply_readbraw_error(xconn);
3815 END_PROFILE(SMBreadbraw);
3819 if (xconn->smb1.echo_handler.trusted_fde) {
3820 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3821 "'async smb echo handler = yes'\n"));
3822 reply_readbraw_error(xconn);
3823 END_PROFILE(SMBreadbraw);
3828 * Special check if an oplock break has been issued
3829 * and the readraw request croses on the wire, we must
3830 * return a zero length response here.
3833 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3836 * We have to do a check_fsp by hand here, as
3837 * we must always return 4 zero bytes on error,
3841 if (!fsp || !conn || conn != fsp->conn ||
3842 req->vuid != fsp->vuid ||
3843 fsp->is_directory || fsp->fh->fd == -1) {
3845 * fsp could be NULL here so use the value from the packet. JRA.
3847 DEBUG(3,("reply_readbraw: fnum %d not valid "
3849 (int)SVAL(req->vwv+0, 0)));
3850 reply_readbraw_error(xconn);
3851 END_PROFILE(SMBreadbraw);
3855 /* Do a "by hand" version of CHECK_READ. */
3856 if (!(fsp->can_read ||
3857 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3858 (fsp->access_mask & FILE_EXECUTE)))) {
3859 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3860 (int)SVAL(req->vwv+0, 0)));
3861 reply_readbraw_error(xconn);
3862 END_PROFILE(SMBreadbraw);
3866 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3867 if(req->wct == 10) {
3869 * This is a large offset (64 bit) read.
3872 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3875 DEBUG(0,("reply_readbraw: negative 64 bit "
3876 "readraw offset (%.0f) !\n",
3877 (double)startpos ));
3878 reply_readbraw_error(xconn);
3879 END_PROFILE(SMBreadbraw);
3884 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3885 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3887 /* ensure we don't overrun the packet size */
3888 maxcount = MIN(65535,maxcount);
3890 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3891 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3894 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3895 reply_readbraw_error(xconn);
3896 END_PROFILE(SMBreadbraw);
3900 status = vfs_stat_fsp(fsp);
3901 if (NT_STATUS_IS_OK(status)) {
3902 size = fsp->fsp_name->st.st_ex_size;
3905 if (startpos >= size) {
3908 nread = MIN(maxcount,(size - startpos));
3911 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3912 if (nread < mincount)
3916 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3917 "min=%lu nread=%lu\n",
3918 fsp_fnum_dbg(fsp), (double)startpos,
3919 (unsigned long)maxcount,
3920 (unsigned long)mincount,
3921 (unsigned long)nread ) );
3923 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3925 DEBUG(5,("reply_readbraw finished\n"));
3927 END_PROFILE(SMBreadbraw);
3932 #define DBGC_CLASS DBGC_LOCKING
3934 /****************************************************************************
3935 Reply to a lockread (core+ protocol).
3936 ****************************************************************************/
3938 static void reply_lockread_locked(struct tevent_req *subreq);
3940 void reply_lockread(struct smb_request *req)
3942 struct tevent_req *subreq = NULL;
3943 connection_struct *conn = req->conn;
3945 struct smbd_lock_element *lck = NULL;
3947 START_PROFILE(SMBlockread);
3950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3951 END_PROFILE(SMBlockread);
3955 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3957 if (!check_fsp(conn, req, fsp)) {
3958 END_PROFILE(SMBlockread);
3962 if (!CHECK_READ(fsp,req)) {
3963 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3964 END_PROFILE(SMBlockread);
3968 lck = talloc(req, struct smbd_lock_element);
3970 reply_nterror(req, NT_STATUS_NO_MEMORY);
3971 END_PROFILE(SMBlockread);
3976 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3977 * protocol request that predates the read/write lock concept.
3978 * Thus instead of asking for a read lock here we need to ask
3979 * for a write lock. JRA.
3980 * Note that the requested lock size is unaffected by max_send.
3983 *lck = (struct smbd_lock_element) {
3984 .req_guid = smbd_request_guid(req, 0),
3985 .smblctx = req->smbpid,
3986 .brltype = WRITE_LOCK,
3987 .count = SVAL(req->vwv+1, 0),
3988 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3991 subreq = smbd_smb1_do_locks_send(
3997 false, /* large_offset */
4001 if (subreq == NULL) {
4002 reply_nterror(req, NT_STATUS_NO_MEMORY);
4003 END_PROFILE(SMBlockread);
4006 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4007 END_PROFILE(SMBlockread);
4010 static void reply_lockread_locked(struct tevent_req *subreq)
4012 struct smb_request *req = NULL;
4018 size_t numtoread, maxtoread;
4019 struct files_struct *fsp = NULL;
4022 START_PROFILE(SMBlockread);
4024 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4027 status = smbd_smb1_do_locks_recv(subreq);
4028 TALLOC_FREE(subreq);
4030 if (!NT_STATUS_IS_OK(status)) {
4031 reply_nterror(req, status);
4035 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4037 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4041 numtoread = SVAL(req->vwv+1, 0);
4042 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4045 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4047 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4049 if (numtoread > maxtoread) {
4050 DBG_WARNING("requested read size (%zu) is greater than "
4051 "maximum allowed (%zu/%d). "
4052 "Returning short read of maximum allowed for "
4053 "compatibility with Windows 2000.\n",
4056 req->xconn->smb1.sessions.max_send);
4057 numtoread = maxtoread;
4060 reply_outbuf(req, 5, numtoread + 3);
4062 data = smb_buf(req->outbuf) + 3;
4064 nread = read_file(fsp,data,startpos,numtoread);
4067 reply_nterror(req, map_nt_error_from_unix(errno));
4071 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4073 SSVAL(req->outbuf,smb_vwv0,nread);
4074 SSVAL(req->outbuf,smb_vwv5,nread+3);
4075 p = smb_buf(req->outbuf);
4076 SCVAL(p,0,0); /* pad byte. */
4079 DEBUG(3,("lockread %s num=%d nread=%d\n",
4080 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4083 ok = srv_send_smb(req->xconn,
4084 (char *)req->outbuf,
4087 IS_CONN_ENCRYPTED(req->conn),
4090 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4093 END_PROFILE(SMBlockread);
4098 #define DBGC_CLASS DBGC_ALL
4100 /****************************************************************************
4102 ****************************************************************************/
4104 void reply_read(struct smb_request *req)
4106 connection_struct *conn = req->conn;
4113 struct lock_struct lock;
4114 struct smbXsrv_connection *xconn = req->xconn;
4116 START_PROFILE(SMBread);
4119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4120 END_PROFILE(SMBread);
4124 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4126 if (!check_fsp(conn, req, fsp)) {
4127 END_PROFILE(SMBread);
4131 if (!CHECK_READ(fsp,req)) {
4132 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4133 END_PROFILE(SMBread);
4137 numtoread = SVAL(req->vwv+1, 0);
4138 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4141 * The requested read size cannot be greater than max_send. JRA.
4143 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4145 if (numtoread > maxtoread) {
4146 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4147 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4148 (unsigned int)numtoread, (unsigned int)maxtoread,
4149 (unsigned int)xconn->smb1.sessions.max_send));
4150 numtoread = maxtoread;
4153 reply_outbuf(req, 5, numtoread+3);
4155 data = smb_buf(req->outbuf) + 3;
4157 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4158 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4161 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4162 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4163 END_PROFILE(SMBread);
4168 nread = read_file(fsp,data,startpos,numtoread);
4171 reply_nterror(req, map_nt_error_from_unix(errno));
4175 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4177 SSVAL(req->outbuf,smb_vwv0,nread);
4178 SSVAL(req->outbuf,smb_vwv5,nread+3);
4179 SCVAL(smb_buf(req->outbuf),0,1);
4180 SSVAL(smb_buf(req->outbuf),1,nread);
4182 DEBUG(3, ("read %s num=%d nread=%d\n",
4183 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4186 END_PROFILE(SMBread);
4190 /****************************************************************************
4192 ****************************************************************************/
4194 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4198 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4201 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4203 SCVAL(outbuf,smb_vwv0,0xFF);
4204 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4205 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4206 SSVAL(outbuf,smb_vwv6,
4207 (smb_wct - 4) /* offset from smb header to wct */
4208 + 1 /* the wct field */
4209 + 12 * sizeof(uint16_t) /* vwv */
4210 + 2 /* the buflen field */
4211 + 1); /* padding byte */
4212 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4213 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4214 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4215 _smb_setlen_large(outbuf,
4216 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4220 /****************************************************************************
4221 Reply to a read and X - possibly using sendfile.
4222 ****************************************************************************/
4224 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4225 files_struct *fsp, off_t startpos,
4228 struct smbXsrv_connection *xconn = req->xconn;
4230 struct lock_struct lock;
4231 int saved_errno = 0;
4234 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4235 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4238 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4239 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4244 * We can only use sendfile on a non-chained packet
4245 * but we can use on a non-oplocked file. tridge proved this
4246 * on a train in Germany :-). JRA.
4249 if (!req_is_in_chain(req) &&
4251 (fsp->base_fsp == NULL) &&
4252 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4253 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4256 status = vfs_stat_fsp(fsp);
4257 if (!NT_STATUS_IS_OK(status)) {
4258 reply_nterror(req, status);
4262 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4263 (startpos > fsp->fsp_name->st.st_ex_size) ||
4264 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4266 * We already know that we would do a short read, so don't
4267 * try the sendfile() path.
4269 goto nosendfile_read;
4273 * Set up the packet header before send. We
4274 * assume here the sendfile will work (get the
4275 * correct amount of data).
4278 header = data_blob_const(headerbuf, sizeof(headerbuf));
4280 construct_reply_common_req(req, (char *)headerbuf);
4281 setup_readX_header((char *)headerbuf, smb_maxcnt);
4283 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4284 startpos, smb_maxcnt);
4286 saved_errno = errno;
4288 /* Returning ENOSYS means no data at all was sent.
4289 Do this as a normal read. */
4290 if (errno == ENOSYS) {
4295 * Special hack for broken Linux with no working sendfile. If we
4296 * return EINTR we sent the header but not the rest of the data.
4297 * Fake this up by doing read/write calls.
4300 if (errno == EINTR) {
4301 /* Ensure we don't do this again. */
4302 set_use_sendfile(SNUM(conn), False);
4303 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4304 nread = fake_sendfile(xconn, fsp, startpos,
4307 saved_errno = errno;
4308 DEBUG(0,("send_file_readX: "
4309 "fake_sendfile failed for "
4310 "file %s (%s) for client %s. "
4313 smbXsrv_connection_dbg(xconn),
4314 strerror(saved_errno)));
4315 errno = saved_errno;
4316 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4318 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4319 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4320 /* No outbuf here means successful sendfile. */
4324 DEBUG(0,("send_file_readX: sendfile failed for file "
4325 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4327 exit_server_cleanly("send_file_readX sendfile failed");
4328 } else if (nread == 0) {
4330 * Some sendfile implementations return 0 to indicate
4331 * that there was a short read, but nothing was
4332 * actually written to the socket. In this case,
4333 * fallback to the normal read path so the header gets
4334 * the correct byte count.
4336 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4337 "falling back to the normal read: %s\n",
4342 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4343 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4345 /* Deal with possible short send. */
4346 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4349 ret = sendfile_short_send(xconn, fsp, nread,
4350 sizeof(headerbuf), smb_maxcnt);
4353 r = "send_file_readX: sendfile_short_send failed";
4354 DEBUG(0,("%s for file %s (%s).\n",
4355 r, fsp_str_dbg(fsp), strerror(errno)));
4356 exit_server_cleanly(r);
4359 /* No outbuf here means successful sendfile. */
4360 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4361 SMB_PERFCOUNT_END(&req->pcd);
4367 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4368 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4371 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4372 (startpos > fsp->fsp_name->st.st_ex_size) ||
4373 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4375 * We already know that we would do a short
4376 * read, so don't try the sendfile() path.
4378 goto nosendfile_read;
4381 construct_reply_common_req(req, (char *)headerbuf);
4382 setup_readX_header((char *)headerbuf, smb_maxcnt);
4384 /* Send out the header. */
4385 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4387 if (ret != sizeof(headerbuf)) {
4388 saved_errno = errno;
4390 * Try and give an error message saying what
4393 DEBUG(0,("send_file_readX: write_data failed for file "
4394 "%s (%s) for client %s. Terminating\n",
4396 smbXsrv_connection_dbg(xconn),
4397 strerror(saved_errno)));
4398 errno = saved_errno;
4399 exit_server_cleanly("send_file_readX sendfile failed");
4401 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4403 saved_errno = errno;
4404 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4405 "%s (%s) for client %s. Terminating\n",
4407 smbXsrv_connection_dbg(xconn),
4408 strerror(saved_errno)));
4409 errno = saved_errno;
4410 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4417 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4418 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4419 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4421 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4422 startpos, smb_maxcnt);
4423 saved_errno = errno;
4426 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4430 setup_readX_header((char *)req->outbuf, nread);
4432 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4433 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4437 TALLOC_FREE(req->outbuf);
4441 /****************************************************************************
4442 Work out how much space we have for a read return.
4443 ****************************************************************************/
4445 static size_t calc_max_read_pdu(const struct smb_request *req)
4447 struct smbXsrv_connection *xconn = req->xconn;
4449 if (xconn->protocol < PROTOCOL_NT1) {
4450 return xconn->smb1.sessions.max_send;
4453 if (!lp_large_readwrite()) {
4454 return xconn->smb1.sessions.max_send;
4457 if (req_is_in_chain(req)) {
4458 return xconn->smb1.sessions.max_send;
4461 if (req->encrypted) {
4463 * Don't take encrypted traffic up to the
4464 * limit. There are padding considerations
4465 * that make that tricky.
4467 return xconn->smb1.sessions.max_send;
4470 if (srv_is_signing_active(xconn)) {
4474 if (!lp_unix_extensions()) {
4479 * We can do ultra-large POSIX reads.
4484 /****************************************************************************
4485 Calculate how big a read can be. Copes with all clients. It's always
4486 safe to return a short read - Windows does this.
4487 ****************************************************************************/
4489 static size_t calc_read_size(const struct smb_request *req,
4493 struct smbXsrv_connection *xconn = req->xconn;
4494 size_t max_pdu = calc_max_read_pdu(req);
4495 size_t total_size = 0;
4496 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4497 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4500 * Windows explicitly ignores upper size of 0xFFFF.
4501 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4502 * We must do the same as these will never fit even in
4503 * an extended size NetBIOS packet.
4505 if (upper_size == 0xFFFF) {
4509 if (xconn->protocol < PROTOCOL_NT1) {
4513 total_size = ((upper_size<<16) | lower_size);
4516 * LARGE_READX test shows it's always safe to return
4517 * a short read. Windows does so.
4519 return MIN(total_size, max_len);
4522 /****************************************************************************
4523 Reply to a read and X.
4524 ****************************************************************************/
4526 void reply_read_and_X(struct smb_request *req)
4528 connection_struct *conn = req->conn;
4533 bool big_readX = False;
4535 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4538 START_PROFILE(SMBreadX);
4540 if ((req->wct != 10) && (req->wct != 12)) {
4541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4545 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4546 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4547 smb_maxcnt = SVAL(req->vwv+5, 0);
4549 /* If it's an IPC, pass off the pipe handler. */
4551 reply_pipe_read_and_X(req);
4552 END_PROFILE(SMBreadX);
4556 if (!check_fsp(conn, req, fsp)) {
4557 END_PROFILE(SMBreadX);
4561 if (!CHECK_READ(fsp,req)) {
4562 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4563 END_PROFILE(SMBreadX);
4567 upper_size = SVAL(req->vwv+7, 0);
4568 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4569 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4571 * This is a heuristic to avoid keeping large
4572 * outgoing buffers around over long-lived aio
4578 if (req->wct == 12) {
4580 * This is a large offset (64 bit) read.
4582 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4587 NTSTATUS status = schedule_aio_read_and_X(conn,
4592 if (NT_STATUS_IS_OK(status)) {
4593 /* Read scheduled - we're done. */
4596 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4597 /* Real error - report to client. */
4598 END_PROFILE(SMBreadX);
4599 reply_nterror(req, status);
4602 /* NT_STATUS_RETRY - fall back to sync read. */
4605 smbd_lock_socket(req->xconn);
4606 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4607 smbd_unlock_socket(req->xconn);
4610 END_PROFILE(SMBreadX);
4614 /****************************************************************************
4615 Error replies to writebraw must have smb_wct == 1. Fix this up.
4616 ****************************************************************************/
4618 void error_to_writebrawerr(struct smb_request *req)
4620 uint8_t *old_outbuf = req->outbuf;
4622 reply_outbuf(req, 1, 0);
4624 memcpy(req->outbuf, old_outbuf, smb_size);
4625 TALLOC_FREE(old_outbuf);
4628 /****************************************************************************
4629 Read 4 bytes of a smb packet and return the smb length of the packet.
4630 Store the result in the buffer. This version of the function will
4631 never return a session keepalive (length of zero).
4632 Timeout is in milliseconds.
4633 ****************************************************************************/
4635 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4638 uint8_t msgtype = NBSSkeepalive;
4640 while (msgtype == NBSSkeepalive) {
4643 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4645 if (!NT_STATUS_IS_OK(status)) {
4646 char addr[INET6_ADDRSTRLEN];
4647 /* Try and give an error message
4648 * saying what client failed. */
4649 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4650 "client %s read error = %s.\n",
4651 get_peer_addr(fd,addr,sizeof(addr)),
4652 nt_errstr(status)));
4656 msgtype = CVAL(inbuf, 0);
4659 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4660 (unsigned long)len));
4662 return NT_STATUS_OK;
4665 /****************************************************************************
4666 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4667 ****************************************************************************/
4669 void reply_writebraw(struct smb_request *req)
4671 connection_struct *conn = req->conn;
4672 struct smbXsrv_connection *xconn = req->xconn;
4675 ssize_t total_written=0;
4676 size_t numtowrite=0;
4679 const char *data=NULL;
4682 struct lock_struct lock;
4685 START_PROFILE(SMBwritebraw);
4688 * If we ever reply with an error, it must have the SMB command
4689 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4692 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4694 if (srv_is_signing_active(xconn)) {
4695 END_PROFILE(SMBwritebraw);
4696 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4697 "raw reads/writes are disallowed.");
4700 if (req->wct < 12) {
4701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4702 error_to_writebrawerr(req);
4703 END_PROFILE(SMBwritebraw);
4707 if (xconn->smb1.echo_handler.trusted_fde) {
4708 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4709 "'async smb echo handler = yes'\n"));
4710 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4711 error_to_writebrawerr(req);
4712 END_PROFILE(SMBwritebraw);
4716 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4717 if (!check_fsp(conn, req, fsp)) {
4718 error_to_writebrawerr(req);
4719 END_PROFILE(SMBwritebraw);
4723 if (!CHECK_WRITE(fsp)) {
4724 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4725 error_to_writebrawerr(req);
4726 END_PROFILE(SMBwritebraw);
4730 tcount = IVAL(req->vwv+1, 0);
4731 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4732 write_through = BITSETW(req->vwv+7,0);
4734 /* We have to deal with slightly different formats depending
4735 on whether we are using the core+ or lanman1.0 protocol */
4737 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4738 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4739 data = smb_buf_const(req->inbuf);
4741 numtowrite = SVAL(req->vwv+10, 0);
4742 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4745 /* Ensure we don't write bytes past the end of this packet. */
4747 * This already protects us against CVE-2017-12163.
4749 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4751 error_to_writebrawerr(req);
4752 END_PROFILE(SMBwritebraw);
4756 if (!fsp->print_file) {
4757 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4758 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4761 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4762 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4763 error_to_writebrawerr(req);
4764 END_PROFILE(SMBwritebraw);
4770 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4773 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4774 "wrote=%d sync=%d\n",
4775 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4776 (int)nwritten, (int)write_through));
4778 if (nwritten < (ssize_t)numtowrite) {
4779 reply_nterror(req, NT_STATUS_DISK_FULL);
4780 error_to_writebrawerr(req);
4784 total_written = nwritten;
4786 /* Allocate a buffer of 64k + length. */
4787 buf = talloc_array(NULL, char, 65540);
4789 reply_nterror(req, NT_STATUS_NO_MEMORY);
4790 error_to_writebrawerr(req);
4794 /* Return a SMBwritebraw message to the redirector to tell
4795 * it to send more bytes */
4797 memcpy(buf, req->inbuf, smb_size);
4798 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4799 SCVAL(buf,smb_com,SMBwritebraw);
4800 SSVALS(buf,smb_vwv0,0xFFFF);
4802 if (!srv_send_smb(req->xconn,
4804 false, 0, /* no signing */
4805 IS_CONN_ENCRYPTED(conn),
4807 exit_server_cleanly("reply_writebraw: srv_send_smb "
4811 /* Now read the raw data into the buffer and write it */
4812 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4814 if (!NT_STATUS_IS_OK(status)) {
4815 exit_server_cleanly("secondary writebraw failed");
4818 /* Set up outbuf to return the correct size */
4819 reply_outbuf(req, 1, 0);
4821 if (numtowrite != 0) {
4823 if (numtowrite > 0xFFFF) {
4824 DEBUG(0,("reply_writebraw: Oversize secondary write "
4825 "raw requested (%u). Terminating\n",
4826 (unsigned int)numtowrite ));
4827 exit_server_cleanly("secondary writebraw failed");
4830 if (tcount > nwritten+numtowrite) {
4831 DEBUG(3,("reply_writebraw: Client overestimated the "
4833 (int)tcount,(int)nwritten,(int)numtowrite));
4836 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4839 if (!NT_STATUS_IS_OK(status)) {
4840 /* Try and give an error message
4841 * saying what client failed. */
4842 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4843 "raw read failed (%s) for client %s. "
4844 "Terminating\n", nt_errstr(status),
4845 smbXsrv_connection_dbg(xconn)));
4846 exit_server_cleanly("secondary writebraw failed");
4850 * We are not vulnerable to CVE-2017-12163
4851 * here as we are guaranteed to have numtowrite
4852 * bytes available - we just read from the client.
4854 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4855 if (nwritten == -1) {
4857 reply_nterror(req, map_nt_error_from_unix(errno));
4858 error_to_writebrawerr(req);
4862 if (nwritten < (ssize_t)numtowrite) {
4863 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4864 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4868 total_written += nwritten;
4873 SSVAL(req->outbuf,smb_vwv0,total_written);
4875 status = sync_file(conn, fsp, write_through);
4876 if (!NT_STATUS_IS_OK(status)) {
4877 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4878 fsp_str_dbg(fsp), nt_errstr(status)));
4879 reply_nterror(req, status);
4880 error_to_writebrawerr(req);
4884 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4886 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4887 (int)total_written));
4889 /* We won't return a status if write through is not selected - this
4890 * follows what WfWg does */
4891 END_PROFILE(SMBwritebraw);
4893 if (!write_through && total_written==tcount) {
4895 #if RABBIT_PELLET_FIX
4897 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4898 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4901 if (!send_keepalive(xconn->transport.sock)) {
4902 exit_server_cleanly("reply_writebraw: send of "
4903 "keepalive failed");
4906 TALLOC_FREE(req->outbuf);
4911 END_PROFILE(SMBwritebraw);
4916 #define DBGC_CLASS DBGC_LOCKING
4918 /****************************************************************************
4919 Reply to a writeunlock (core+).
4920 ****************************************************************************/
4922 void reply_writeunlock(struct smb_request *req)
4924 connection_struct *conn = req->conn;
4925 ssize_t nwritten = -1;
4930 NTSTATUS status = NT_STATUS_OK;
4932 struct lock_struct lock;
4933 int saved_errno = 0;
4935 START_PROFILE(SMBwriteunlock);
4938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4939 END_PROFILE(SMBwriteunlock);
4943 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4945 if (!check_fsp(conn, req, fsp)) {
4946 END_PROFILE(SMBwriteunlock);
4950 if (!CHECK_WRITE(fsp)) {
4951 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4952 END_PROFILE(SMBwriteunlock);
4956 numtowrite = SVAL(req->vwv+1, 0);
4957 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4958 data = (const char *)req->buf + 3;
4961 * Ensure client isn't asking us to write more than
4962 * they sent. CVE-2017-12163.
4964 remaining = smbreq_bufrem(req, data);
4965 if (numtowrite > remaining) {
4966 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4967 END_PROFILE(SMBwriteunlock);
4971 if (!fsp->print_file && numtowrite > 0) {
4972 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4973 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4976 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4977 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4978 END_PROFILE(SMBwriteunlock);
4983 /* The special X/Open SMB protocol handling of
4984 zero length writes is *NOT* done for
4986 if(numtowrite == 0) {
4989 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4990 saved_errno = errno;
4993 status = sync_file(conn, fsp, False /* write through */);
4994 if (!NT_STATUS_IS_OK(status)) {
4995 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4996 fsp_str_dbg(fsp), nt_errstr(status)));
4997 reply_nterror(req, status);
5002 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5006 if((nwritten < numtowrite) && (numtowrite != 0)) {
5007 reply_nterror(req, NT_STATUS_DISK_FULL);
5011 if (numtowrite && !fsp->print_file) {
5012 struct smbd_lock_element l = {
5013 .req_guid = smbd_request_guid(req, 0),
5014 .smblctx = req->smbpid,
5015 .brltype = UNLOCK_LOCK,
5017 .count = numtowrite,
5019 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5020 if (NT_STATUS_V(status)) {
5021 reply_nterror(req, status);
5026 reply_outbuf(req, 1, 0);
5028 SSVAL(req->outbuf,smb_vwv0,nwritten);
5030 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5031 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5034 END_PROFILE(SMBwriteunlock);
5039 #define DBGC_CLASS DBGC_ALL
5041 /****************************************************************************
5043 ****************************************************************************/
5045 void reply_write(struct smb_request *req)
5047 connection_struct *conn = req->conn;
5050 ssize_t nwritten = -1;
5054 struct lock_struct lock;
5056 int saved_errno = 0;
5058 START_PROFILE(SMBwrite);
5061 END_PROFILE(SMBwrite);
5062 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5066 /* If it's an IPC, pass off the pipe handler. */
5068 reply_pipe_write(req);
5069 END_PROFILE(SMBwrite);
5073 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5075 if (!check_fsp(conn, req, fsp)) {
5076 END_PROFILE(SMBwrite);
5080 if (!CHECK_WRITE(fsp)) {
5081 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5082 END_PROFILE(SMBwrite);
5086 numtowrite = SVAL(req->vwv+1, 0);
5087 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5088 data = (const char *)req->buf + 3;
5091 * Ensure client isn't asking us to write more than
5092 * they sent. CVE-2017-12163.
5094 remaining = smbreq_bufrem(req, data);
5095 if (numtowrite > remaining) {
5096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5097 END_PROFILE(SMBwrite);
5101 if (!fsp->print_file) {
5102 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5103 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5106 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5107 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5108 END_PROFILE(SMBwrite);
5114 * X/Open SMB protocol says that if smb_vwv1 is
5115 * zero then the file size should be extended or
5116 * truncated to the size given in smb_vwv[2-3].
5119 if(numtowrite == 0) {
5121 * This is actually an allocate call, and set EOF. JRA.
5123 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5125 reply_nterror(req, NT_STATUS_DISK_FULL);
5128 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5130 reply_nterror(req, NT_STATUS_DISK_FULL);
5133 trigger_write_time_update_immediate(fsp);
5135 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5138 status = sync_file(conn, fsp, False);
5139 if (!NT_STATUS_IS_OK(status)) {
5140 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5141 fsp_str_dbg(fsp), nt_errstr(status)));
5142 reply_nterror(req, status);
5147 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5151 if((nwritten == 0) && (numtowrite != 0)) {
5152 reply_nterror(req, NT_STATUS_DISK_FULL);
5156 reply_outbuf(req, 1, 0);
5158 SSVAL(req->outbuf,smb_vwv0,nwritten);
5160 if (nwritten < (ssize_t)numtowrite) {
5161 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5162 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5165 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5168 END_PROFILE(SMBwrite);
5172 /****************************************************************************
5173 Ensure a buffer is a valid writeX for recvfile purposes.
5174 ****************************************************************************/
5176 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5177 (2*14) + /* word count (including bcc) */ \
5180 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5181 const uint8_t *inbuf)
5184 unsigned int doff = 0;
5185 size_t len = smb_len_large(inbuf);
5187 struct smbXsrv_open *op = NULL;
5188 struct files_struct *fsp = NULL;
5191 if (is_encrypted_packet(inbuf)) {
5192 /* Can't do this on encrypted
5197 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5201 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5202 CVAL(inbuf,smb_wct) != 14) {
5203 DEBUG(10,("is_valid_writeX_buffer: chained or "
5204 "invalid word length.\n"));
5208 fnum = SVAL(inbuf, smb_vwv2);
5209 status = smb1srv_open_lookup(xconn,
5213 if (!NT_STATUS_IS_OK(status)) {
5214 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5219 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5222 if (fsp->conn == NULL) {
5223 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5227 if (IS_IPC(fsp->conn)) {
5228 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5231 if (IS_PRINT(fsp->conn)) {
5232 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5235 if (fsp->base_fsp != NULL) {
5236 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5239 doff = SVAL(inbuf,smb_vwv11);
5241 numtowrite = SVAL(inbuf,smb_vwv10);
5243 if (len > doff && len - doff > 0xFFFF) {
5244 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5247 if (numtowrite == 0) {
5248 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5252 /* Ensure the sizes match up. */
5253 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5254 /* no pad byte...old smbclient :-( */
5255 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5257 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5261 if (len - doff != numtowrite) {
5262 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5263 "len = %u, doff = %u, numtowrite = %u\n",
5266 (unsigned int)numtowrite ));
5270 DEBUG(10,("is_valid_writeX_buffer: true "
5271 "len = %u, doff = %u, numtowrite = %u\n",
5274 (unsigned int)numtowrite ));
5279 /****************************************************************************
5280 Reply to a write and X.
5281 ****************************************************************************/
5283 void reply_write_and_X(struct smb_request *req)
5285 connection_struct *conn = req->conn;
5286 struct smbXsrv_connection *xconn = req->xconn;
5288 struct lock_struct lock;
5293 unsigned int smb_doff;
5294 unsigned int smblen;
5297 int saved_errno = 0;
5299 START_PROFILE(SMBwriteX);
5301 if ((req->wct != 12) && (req->wct != 14)) {
5302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5306 numtowrite = SVAL(req->vwv+10, 0);
5307 smb_doff = SVAL(req->vwv+11, 0);
5308 smblen = smb_len(req->inbuf);
5310 if (req->unread_bytes > 0xFFFF ||
5311 (smblen > smb_doff &&
5312 smblen - smb_doff > 0xFFFF)) {
5313 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5316 if (req->unread_bytes) {
5317 /* Can't do a recvfile write on IPC$ */
5319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5322 if (numtowrite != req->unread_bytes) {
5323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5328 * This already protects us against CVE-2017-12163.
5330 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5331 smb_doff + numtowrite > smblen) {
5332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5337 /* If it's an IPC, pass off the pipe handler. */
5339 if (req->unread_bytes) {
5340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5343 reply_pipe_write_and_X(req);
5347 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5348 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5349 write_through = BITSETW(req->vwv+7,0);
5351 if (!check_fsp(conn, req, fsp)) {
5355 if (!CHECK_WRITE(fsp)) {
5356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5360 data = smb_base(req->inbuf) + smb_doff;
5362 if(req->wct == 14) {
5364 * This is a large offset (64 bit) write.
5366 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5370 /* X/Open SMB protocol says that, unlike SMBwrite
5371 if the length is zero then NO truncation is
5372 done, just a write of zero. To truncate a file,
5375 if(numtowrite == 0) {
5378 if (req->unread_bytes == 0) {
5379 status = schedule_aio_write_and_X(conn,
5386 if (NT_STATUS_IS_OK(status)) {
5387 /* write scheduled - we're done. */
5390 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5391 /* Real error - report to client. */
5392 reply_nterror(req, status);
5395 /* NT_STATUS_RETRY - fall through to sync write. */
5398 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5399 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5402 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5403 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5407 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5408 saved_errno = errno;
5412 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5416 if((nwritten == 0) && (numtowrite != 0)) {
5417 reply_nterror(req, NT_STATUS_DISK_FULL);
5421 reply_outbuf(req, 6, 0);
5422 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5423 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5424 SSVAL(req->outbuf,smb_vwv2,nwritten);
5425 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5427 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5428 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5430 status = sync_file(conn, fsp, write_through);
5431 if (!NT_STATUS_IS_OK(status)) {
5432 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5433 fsp_str_dbg(fsp), nt_errstr(status)));
5434 reply_nterror(req, status);
5438 END_PROFILE(SMBwriteX);
5442 if (req->unread_bytes) {
5443 /* writeX failed. drain socket. */
5444 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5445 req->unread_bytes) {
5446 smb_panic("failed to drain pending bytes");
5448 req->unread_bytes = 0;
5451 END_PROFILE(SMBwriteX);
5455 /****************************************************************************
5457 ****************************************************************************/
5459 void reply_lseek(struct smb_request *req)
5461 connection_struct *conn = req->conn;
5468 START_PROFILE(SMBlseek);
5471 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5472 END_PROFILE(SMBlseek);
5476 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5478 if (!check_fsp(conn, req, fsp)) {
5482 mode = SVAL(req->vwv+1, 0) & 3;
5483 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5484 startpos = (off_t)IVALS(req->vwv+2, 0);
5493 res = fsp->fh->pos + startpos;
5504 if (umode == SEEK_END) {
5505 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5506 if(errno == EINVAL) {
5507 off_t current_pos = startpos;
5509 status = vfs_stat_fsp(fsp);
5510 if (!NT_STATUS_IS_OK(status)) {
5511 reply_nterror(req, status);
5512 END_PROFILE(SMBlseek);
5516 current_pos += fsp->fsp_name->st.st_ex_size;
5518 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5523 reply_nterror(req, map_nt_error_from_unix(errno));
5524 END_PROFILE(SMBlseek);
5531 reply_outbuf(req, 2, 0);
5532 SIVAL(req->outbuf,smb_vwv0,res);
5534 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5535 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5537 END_PROFILE(SMBlseek);
5541 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5544 connection_struct *conn = talloc_get_type_abort(
5545 private_data, connection_struct);
5547 if (conn != fsp->conn) {
5550 if (fsp->fh->fd == -1) {
5553 sync_file(conn, fsp, True /* write through */);
5558 /****************************************************************************
5560 ****************************************************************************/
5562 void reply_flush(struct smb_request *req)
5564 connection_struct *conn = req->conn;
5568 START_PROFILE(SMBflush);
5571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5575 fnum = SVAL(req->vwv+0, 0);
5576 fsp = file_fsp(req, fnum);
5578 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5583 files_forall(req->sconn, file_sync_one_fn, conn);
5585 NTSTATUS status = sync_file(conn, fsp, True);
5586 if (!NT_STATUS_IS_OK(status)) {
5587 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5588 fsp_str_dbg(fsp), nt_errstr(status)));
5589 reply_nterror(req, status);
5590 END_PROFILE(SMBflush);
5595 reply_outbuf(req, 0, 0);
5597 DEBUG(3,("flush\n"));
5598 END_PROFILE(SMBflush);
5602 /****************************************************************************
5604 conn POINTER CAN BE NULL HERE !
5605 ****************************************************************************/
5607 void reply_exit(struct smb_request *req)
5609 START_PROFILE(SMBexit);
5611 file_close_pid(req->sconn, req->smbpid, req->vuid);
5613 reply_outbuf(req, 0, 0);
5615 DEBUG(3,("exit\n"));
5617 END_PROFILE(SMBexit);
5621 struct reply_close_state {
5623 struct smb_request *smbreq;
5626 static void do_smb1_close(struct tevent_req *req);
5628 void reply_close(struct smb_request *req)
5630 connection_struct *conn = req->conn;
5631 NTSTATUS status = NT_STATUS_OK;
5632 files_struct *fsp = NULL;
5633 START_PROFILE(SMBclose);
5636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5637 END_PROFILE(SMBclose);
5641 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5644 * We can only use check_fsp if we know it's not a directory.
5647 if (!check_fsp_open(conn, req, fsp)) {
5648 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5649 END_PROFILE(SMBclose);
5653 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5654 fsp->is_directory ? "directory" : "file",
5655 fsp->fh->fd, fsp_fnum_dbg(fsp),
5656 conn->num_files_open));
5658 if (!fsp->is_directory) {
5662 * Take care of any time sent in the close.
5665 t = srv_make_unix_date3(req->vwv+1);
5666 set_close_write_time(fsp, time_t_to_full_timespec(t));
5669 if (fsp->num_aio_requests != 0) {
5671 struct reply_close_state *state;
5673 DEBUG(10, ("closing with aio %u requests pending\n",
5674 fsp->num_aio_requests));
5677 * Flag the file as close in progress.
5678 * This will prevent any more IO being
5681 fsp->closing = true;
5684 * We depend on the aio_extra destructor to take care of this
5685 * close request once fsp->num_aio_request drops to 0.
5688 fsp->deferred_close = tevent_wait_send(
5689 fsp, fsp->conn->sconn->ev_ctx);
5690 if (fsp->deferred_close == NULL) {
5691 status = NT_STATUS_NO_MEMORY;
5695 state = talloc(fsp, struct reply_close_state);
5696 if (state == NULL) {
5697 TALLOC_FREE(fsp->deferred_close);
5698 status = NT_STATUS_NO_MEMORY;
5702 state->smbreq = talloc_move(fsp, &req);
5703 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5705 END_PROFILE(SMBclose);
5710 * close_file() returns the unix errno if an error was detected on
5711 * close - normally this is due to a disk full error. If not then it
5712 * was probably an I/O error.
5715 status = close_file(req, fsp, NORMAL_CLOSE);
5717 if (!NT_STATUS_IS_OK(status)) {
5718 reply_nterror(req, status);
5719 END_PROFILE(SMBclose);
5723 reply_outbuf(req, 0, 0);
5724 END_PROFILE(SMBclose);
5728 static void do_smb1_close(struct tevent_req *req)
5730 struct reply_close_state *state = tevent_req_callback_data(
5731 req, struct reply_close_state);
5732 struct smb_request *smbreq;
5736 ret = tevent_wait_recv(req);
5739 DEBUG(10, ("tevent_wait_recv returned %s\n",
5742 * Continue anyway, this should never happen
5747 * fsp->smb2_close_request right now is a talloc grandchild of
5748 * fsp. When we close_file(fsp), it would go with it. No chance to
5751 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5753 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5754 if (NT_STATUS_IS_OK(status)) {
5755 reply_outbuf(smbreq, 0, 0);
5757 reply_nterror(smbreq, status);
5759 if (!srv_send_smb(smbreq->xconn,
5760 (char *)smbreq->outbuf,
5763 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5765 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5768 TALLOC_FREE(smbreq);
5771 /****************************************************************************
5772 Reply to a writeclose (Core+ protocol).
5773 ****************************************************************************/
5775 void reply_writeclose(struct smb_request *req)
5777 connection_struct *conn = req->conn;
5780 ssize_t nwritten = -1;
5781 NTSTATUS close_status = NT_STATUS_OK;
5784 struct timespec mtime;
5786 struct lock_struct lock;
5788 START_PROFILE(SMBwriteclose);
5791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5792 END_PROFILE(SMBwriteclose);
5796 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5798 if (!check_fsp(conn, req, fsp)) {
5799 END_PROFILE(SMBwriteclose);
5802 if (!CHECK_WRITE(fsp)) {
5803 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5804 END_PROFILE(SMBwriteclose);
5808 numtowrite = SVAL(req->vwv+1, 0);
5809 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5810 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
5811 data = (const char *)req->buf + 1;
5814 * Ensure client isn't asking us to write more than
5815 * they sent. CVE-2017-12163.
5817 remaining = smbreq_bufrem(req, data);
5818 if (numtowrite > remaining) {
5819 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5820 END_PROFILE(SMBwriteclose);
5824 if (fsp->print_file == NULL) {
5825 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5826 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5829 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5830 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5831 END_PROFILE(SMBwriteclose);
5836 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5838 set_close_write_time(fsp, mtime);
5841 * More insanity. W2K only closes the file if writelen > 0.
5845 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5846 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5847 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5850 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5851 "file %s\n", fsp_str_dbg(fsp)));
5852 close_status = close_file(req, fsp, NORMAL_CLOSE);
5856 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5857 reply_nterror(req, NT_STATUS_DISK_FULL);
5861 if(!NT_STATUS_IS_OK(close_status)) {
5862 reply_nterror(req, close_status);
5866 reply_outbuf(req, 1, 0);
5868 SSVAL(req->outbuf,smb_vwv0,nwritten);
5872 END_PROFILE(SMBwriteclose);
5877 #define DBGC_CLASS DBGC_LOCKING
5879 /****************************************************************************
5881 ****************************************************************************/
5883 static void reply_lock_done(struct tevent_req *subreq);
5885 void reply_lock(struct smb_request *req)
5887 struct tevent_req *subreq = NULL;
5888 connection_struct *conn = req->conn;
5890 struct smbd_lock_element *lck = NULL;
5892 START_PROFILE(SMBlock);
5895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5896 END_PROFILE(SMBlock);
5900 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5902 if (!check_fsp(conn, req, fsp)) {
5903 END_PROFILE(SMBlock);
5907 lck = talloc(req, struct smbd_lock_element);
5909 reply_nterror(req, NT_STATUS_NO_MEMORY);
5910 END_PROFILE(SMBlock);
5914 *lck = (struct smbd_lock_element) {
5915 .req_guid = smbd_request_guid(req, 0),
5916 .smblctx = req->smbpid,
5917 .brltype = WRITE_LOCK,
5918 .count = IVAL(req->vwv+1, 0),
5919 .offset = IVAL(req->vwv+3, 0),
5922 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5928 subreq = smbd_smb1_do_locks_send(
5934 false, /* large_offset */
5938 if (subreq == NULL) {
5939 reply_nterror(req, NT_STATUS_NO_MEMORY);
5940 END_PROFILE(SMBlock);
5943 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5944 END_PROFILE(SMBlock);
5947 static void reply_lock_done(struct tevent_req *subreq)
5949 struct smb_request *req = NULL;
5953 START_PROFILE(SMBlock);
5955 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5958 status = smbd_smb1_do_locks_recv(subreq);
5959 TALLOC_FREE(subreq);
5961 if (NT_STATUS_IS_OK(status)) {
5962 reply_outbuf(req, 0, 0);
5964 reply_nterror(req, status);
5967 ok = srv_send_smb(req->xconn,
5968 (char *)req->outbuf,
5971 IS_CONN_ENCRYPTED(req->conn),
5974 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
5977 END_PROFILE(SMBlock);
5980 /****************************************************************************
5982 ****************************************************************************/
5984 void reply_unlock(struct smb_request *req)
5986 connection_struct *conn = req->conn;
5989 struct smbd_lock_element lck;
5991 START_PROFILE(SMBunlock);
5994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5995 END_PROFILE(SMBunlock);
5999 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6001 if (!check_fsp(conn, req, fsp)) {
6002 END_PROFILE(SMBunlock);
6006 lck = (struct smbd_lock_element) {
6007 .req_guid = smbd_request_guid(req, 0),
6008 .smblctx = req->smbpid,
6009 .brltype = UNLOCK_LOCK,
6010 .offset = IVAL(req->vwv+3, 0),
6011 .count = IVAL(req->vwv+1, 0),
6014 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6016 if (!NT_STATUS_IS_OK(status)) {
6017 reply_nterror(req, status);
6018 END_PROFILE(SMBunlock);
6022 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6028 reply_outbuf(req, 0, 0);
6030 END_PROFILE(SMBunlock);
6035 #define DBGC_CLASS DBGC_ALL
6037 /****************************************************************************
6039 conn POINTER CAN BE NULL HERE !
6040 ****************************************************************************/
6042 void reply_tdis(struct smb_request *smb1req)
6045 connection_struct *conn = smb1req->conn;
6046 struct smbXsrv_tcon *tcon;
6048 START_PROFILE(SMBtdis);
6051 DBG_INFO("Invalid connection in tdis\n");
6052 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6053 END_PROFILE(SMBtdis);
6058 smb1req->conn = NULL;
6061 * TODO: cancel all outstanding requests on the tcon
6063 status = smbXsrv_tcon_disconnect(tcon, smb1req->vuid);
6064 if (!NT_STATUS_IS_OK(status)) {
6065 DEBUG(0, ("reply_tdis: "
6066 "smbXsrv_tcon_disconnect() failed: %s\n",
6067 nt_errstr(status)));
6069 * If we hit this case, there is something completely
6070 * wrong, so we better disconnect the transport connection.
6072 END_PROFILE(SMBtdis);
6073 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6079 reply_outbuf(smb1req, 0, 0);
6080 END_PROFILE(SMBtdis);
6085 struct reply_tdis_state {
6086 struct tevent_queue *wait_queue;
6089 static void reply_tdis_wait_done(struct tevent_req *subreq);
6091 /****************************************************************************
6093 Note, on failure here we deallocate and return NULL to allow the caller to
6094 SMB1 return an error of ERRnomem immediately.
6095 ****************************************************************************/
6097 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6099 struct tevent_req *req;
6100 struct reply_tdis_state *state;
6101 struct tevent_req *subreq;
6102 connection_struct *conn = smb1req->conn;
6105 req = tevent_req_create(smb1req, &state,
6106 struct reply_tdis_state);
6110 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6111 if (tevent_req_nomem(state->wait_queue, req)) {
6117 * Make sure that no new request will be able to use this tcon.
6118 * This ensures that once all outstanding fsp->aio_requests
6119 * on this tcon are done, we are safe to close it.
6121 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6123 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6124 if (fsp->conn != conn) {
6128 * Flag the file as close in progress.
6129 * This will prevent any more IO being
6130 * done on it. Not strictly needed, but
6131 * doesn't hurt to flag it as closing.
6133 fsp->closing = true;
6135 if (fsp->num_aio_requests > 0) {
6137 * Now wait until all aio requests on this fsp are
6140 * We don't set a callback, as we just want to block the
6141 * wait queue and the talloc_free() of fsp->aio_request
6142 * will remove the item from the wait queue.
6144 subreq = tevent_queue_wait_send(fsp->aio_requests,
6145 conn->sconn->ev_ctx,
6147 if (tevent_req_nomem(subreq, req)) {
6155 * Now we add our own waiter to the end of the queue,
6156 * this way we get notified when all pending requests are finished
6157 * and reply to the outstanding SMB1 request.
6159 subreq = tevent_queue_wait_send(state,
6160 conn->sconn->ev_ctx,
6162 if (tevent_req_nomem(subreq, req)) {
6168 * We're really going async - move the SMB1 request from
6169 * a talloc stackframe above us to the sconn talloc-context.
6170 * We need this to stick around until the wait_done
6171 * callback is invoked.
6173 smb1req = talloc_move(smb1req->sconn, &smb1req);
6175 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6180 static void reply_tdis_wait_done(struct tevent_req *subreq)
6182 struct tevent_req *req = tevent_req_callback_data(
6183 subreq, struct tevent_req);
6185 tevent_queue_wait_recv(subreq);
6186 TALLOC_FREE(subreq);
6187 tevent_req_done(req);
6190 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6192 return tevent_req_simple_recv_ntstatus(req);
6195 static void reply_tdis_done(struct tevent_req *req)
6197 struct smb_request *smb1req = tevent_req_callback_data(
6198 req, struct smb_request);
6200 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6204 * Take the profile charge here. Not strictly
6205 * correct but better than the other SMB1 async
6206 * code that double-charges at the moment.
6208 START_PROFILE(SMBtdis);
6210 status = reply_tdis_recv(req);
6212 if (!NT_STATUS_IS_OK(status)) {
6213 TALLOC_FREE(smb1req);
6214 END_PROFILE(SMBtdis);
6215 exit_server(__location__ ": reply_tdis_recv failed");
6220 * As we've been awoken, we may have changed
6221 * directory in the meantime.
6222 * reply_tdis() has the DO_CHDIR flag set.
6224 ok = chdir_current_service(smb1req->conn);
6226 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6227 smb_request_done(smb1req);
6228 END_PROFILE(SMBtdis);
6231 status = smbXsrv_tcon_disconnect(tcon,
6233 if (!NT_STATUS_IS_OK(status)) {
6234 TALLOC_FREE(smb1req);
6235 END_PROFILE(SMBtdis);
6236 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6240 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6241 smb1req->conn = NULL;
6245 reply_outbuf(smb1req, 0, 0);
6247 * The following call is needed to push the
6248 * reply data back out the socket after async
6249 * return. Plus it frees smb1req.
6251 smb_request_done(smb1req);
6252 END_PROFILE(SMBtdis);
6256 /****************************************************************************
6258 conn POINTER CAN BE NULL HERE !
6259 ****************************************************************************/
6261 void reply_echo(struct smb_request *req)
6263 connection_struct *conn = req->conn;
6264 struct smb_perfcount_data local_pcd;
6265 struct smb_perfcount_data *cur_pcd;
6269 START_PROFILE(SMBecho);
6271 smb_init_perfcount_data(&local_pcd);
6274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6275 END_PROFILE(SMBecho);
6279 smb_reverb = SVAL(req->vwv+0, 0);
6281 reply_outbuf(req, 1, req->buflen);
6283 /* copy any incoming data back out */
6284 if (req->buflen > 0) {
6285 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6288 if (smb_reverb > 100) {
6289 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6293 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6295 /* this makes sure we catch the request pcd */
6296 if (seq_num == smb_reverb) {
6297 cur_pcd = &req->pcd;
6299 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6300 cur_pcd = &local_pcd;
6303 SSVAL(req->outbuf,smb_vwv0,seq_num);
6305 show_msg((char *)req->outbuf);
6306 if (!srv_send_smb(req->xconn,
6307 (char *)req->outbuf,
6308 true, req->seqnum+1,
6309 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6311 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6314 DEBUG(3,("echo %d times\n", smb_reverb));
6316 TALLOC_FREE(req->outbuf);
6318 END_PROFILE(SMBecho);
6322 /****************************************************************************
6323 Reply to a printopen.
6324 ****************************************************************************/
6326 void reply_printopen(struct smb_request *req)
6328 connection_struct *conn = req->conn;
6332 START_PROFILE(SMBsplopen);
6335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6336 END_PROFILE(SMBsplopen);
6340 if (!CAN_PRINT(conn)) {
6341 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6342 END_PROFILE(SMBsplopen);
6346 status = file_new(req, conn, &fsp);
6347 if(!NT_STATUS_IS_OK(status)) {
6348 reply_nterror(req, status);
6349 END_PROFILE(SMBsplopen);
6353 /* Open for exclusive use, write only. */
6354 status = print_spool_open(fsp, NULL, req->vuid);
6356 if (!NT_STATUS_IS_OK(status)) {
6357 file_free(req, fsp);
6358 reply_nterror(req, status);
6359 END_PROFILE(SMBsplopen);
6363 reply_outbuf(req, 1, 0);
6364 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6366 DEBUG(3,("openprint fd=%d %s\n",
6367 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6369 END_PROFILE(SMBsplopen);
6373 /****************************************************************************
6374 Reply to a printclose.
6375 ****************************************************************************/
6377 void reply_printclose(struct smb_request *req)
6379 connection_struct *conn = req->conn;
6383 START_PROFILE(SMBsplclose);
6386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6387 END_PROFILE(SMBsplclose);
6391 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6393 if (!check_fsp(conn, req, fsp)) {
6394 END_PROFILE(SMBsplclose);
6398 if (!CAN_PRINT(conn)) {
6399 reply_force_doserror(req, ERRSRV, ERRerror);
6400 END_PROFILE(SMBsplclose);
6404 DEBUG(3,("printclose fd=%d %s\n",
6405 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6407 status = close_file(req, fsp, NORMAL_CLOSE);
6409 if(!NT_STATUS_IS_OK(status)) {
6410 reply_nterror(req, status);
6411 END_PROFILE(SMBsplclose);
6415 reply_outbuf(req, 0, 0);
6417 END_PROFILE(SMBsplclose);
6421 /****************************************************************************
6422 Reply to a printqueue.
6423 ****************************************************************************/
6425 void reply_printqueue(struct smb_request *req)
6427 const struct loadparm_substitution *lp_sub =
6428 loadparm_s3_global_substitution();
6429 connection_struct *conn = req->conn;
6433 START_PROFILE(SMBsplretq);
6436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6437 END_PROFILE(SMBsplretq);
6441 max_count = SVAL(req->vwv+0, 0);
6442 start_index = SVAL(req->vwv+1, 0);
6444 /* we used to allow the client to get the cnum wrong, but that
6445 is really quite gross and only worked when there was only
6446 one printer - I think we should now only accept it if they
6447 get it right (tridge) */
6448 if (!CAN_PRINT(conn)) {
6449 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6450 END_PROFILE(SMBsplretq);
6454 reply_outbuf(req, 2, 3);
6455 SSVAL(req->outbuf,smb_vwv0,0);
6456 SSVAL(req->outbuf,smb_vwv1,0);
6457 SCVAL(smb_buf(req->outbuf),0,1);
6458 SSVAL(smb_buf(req->outbuf),1,0);
6460 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6461 start_index, max_count));
6464 TALLOC_CTX *mem_ctx = talloc_tos();
6467 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6468 struct rpc_pipe_client *cli = NULL;
6469 struct dcerpc_binding_handle *b = NULL;
6470 struct policy_handle handle;
6471 struct spoolss_DevmodeContainer devmode_ctr;
6472 union spoolss_JobInfo *info;
6474 uint32_t num_to_get;
6478 ZERO_STRUCT(handle);
6480 status = rpc_pipe_open_interface(mem_ctx,
6483 conn->sconn->remote_address,
6484 conn->sconn->local_address,
6485 conn->sconn->msg_ctx,
6487 if (!NT_STATUS_IS_OK(status)) {
6488 DEBUG(0, ("reply_printqueue: "
6489 "could not connect to spoolss: %s\n",
6490 nt_errstr(status)));
6491 reply_nterror(req, status);
6494 b = cli->binding_handle;
6496 ZERO_STRUCT(devmode_ctr);
6498 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6501 SEC_FLAG_MAXIMUM_ALLOWED,
6504 if (!NT_STATUS_IS_OK(status)) {
6505 reply_nterror(req, status);
6508 if (!W_ERROR_IS_OK(werr)) {
6509 reply_nterror(req, werror_to_ntstatus(werr));
6513 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6521 if (!W_ERROR_IS_OK(werr)) {
6522 reply_nterror(req, werror_to_ntstatus(werr));
6526 if (max_count > 0) {
6527 first = start_index;
6529 first = start_index + max_count + 1;
6532 if (first >= count) {
6535 num_to_get = first + MIN(ABS(max_count), count - first);
6538 for (i = first; i < num_to_get; i++) {
6541 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6544 uint16_t qrapjobid = pjobid_to_rap(sharename,
6545 info[i].info2.job_id);
6547 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6553 srv_put_dos_date2(p, 0, qtime);
6554 SCVAL(p, 4, qstatus);
6555 SSVAL(p, 5, qrapjobid);
6556 SIVAL(p, 7, info[i].info2.size);
6558 status = srvstr_push(blob, req->flags2, p+12,
6559 info[i].info2.notify_name, 16, STR_ASCII, &len);
6560 if (!NT_STATUS_IS_OK(status)) {
6561 reply_nterror(req, status);
6564 if (message_push_blob(
6567 blob, sizeof(blob))) == -1) {
6568 reply_nterror(req, NT_STATUS_NO_MEMORY);
6574 SSVAL(req->outbuf,smb_vwv0,count);
6575 SSVAL(req->outbuf,smb_vwv1,
6576 (max_count>0?first+count:first-1));
6577 SCVAL(smb_buf(req->outbuf),0,1);
6578 SSVAL(smb_buf(req->outbuf),1,28*count);
6582 DEBUG(3, ("%u entries returned in queue\n",
6586 if (b && is_valid_policy_hnd(&handle)) {
6587 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6592 END_PROFILE(SMBsplretq);
6596 /****************************************************************************
6597 Reply to a printwrite.
6598 ****************************************************************************/
6600 void reply_printwrite(struct smb_request *req)
6602 connection_struct *conn = req->conn;
6607 START_PROFILE(SMBsplwr);
6610 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6611 END_PROFILE(SMBsplwr);
6615 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6617 if (!check_fsp(conn, req, fsp)) {
6618 END_PROFILE(SMBsplwr);
6622 if (!fsp->print_file) {
6623 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6624 END_PROFILE(SMBsplwr);
6628 if (!CHECK_WRITE(fsp)) {
6629 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6630 END_PROFILE(SMBsplwr);
6634 numtowrite = SVAL(req->buf, 1);
6637 * This already protects us against CVE-2017-12163.
6639 if (req->buflen < numtowrite + 3) {
6640 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6641 END_PROFILE(SMBsplwr);
6645 data = (const char *)req->buf + 3;
6647 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6648 reply_nterror(req, map_nt_error_from_unix(errno));
6649 END_PROFILE(SMBsplwr);
6653 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6655 END_PROFILE(SMBsplwr);
6659 /****************************************************************************
6661 ****************************************************************************/
6663 void reply_mkdir(struct smb_request *req)
6665 connection_struct *conn = req->conn;
6666 struct smb_filename *smb_dname = NULL;
6667 char *directory = NULL;
6670 TALLOC_CTX *ctx = talloc_tos();
6672 START_PROFILE(SMBmkdir);
6674 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6675 STR_TERMINATE, &status);
6676 if (!NT_STATUS_IS_OK(status)) {
6677 reply_nterror(req, status);
6681 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6682 status = filename_convert(ctx, conn,
6688 if (!NT_STATUS_IS_OK(status)) {
6689 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6690 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6691 ERRSRV, ERRbadpath);
6694 reply_nterror(req, status);
6698 status = create_directory(conn, req, smb_dname);
6700 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6702 if (!NT_STATUS_IS_OK(status)) {
6704 if (!use_nt_status()
6705 && NT_STATUS_EQUAL(status,
6706 NT_STATUS_OBJECT_NAME_COLLISION)) {
6708 * Yes, in the DOS error code case we get a
6709 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6710 * samba4 torture test.
6712 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6715 reply_nterror(req, status);
6719 reply_outbuf(req, 0, 0);
6721 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6723 TALLOC_FREE(smb_dname);
6724 END_PROFILE(SMBmkdir);
6728 /****************************************************************************
6730 ****************************************************************************/
6732 void reply_rmdir(struct smb_request *req)
6734 connection_struct *conn = req->conn;
6735 struct smb_filename *smb_dname = NULL;
6736 char *directory = NULL;
6738 TALLOC_CTX *ctx = talloc_tos();
6739 files_struct *fsp = NULL;
6741 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6743 START_PROFILE(SMBrmdir);
6745 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6746 STR_TERMINATE, &status);
6747 if (!NT_STATUS_IS_OK(status)) {
6748 reply_nterror(req, status);
6752 status = filename_convert(ctx, conn,
6758 if (!NT_STATUS_IS_OK(status)) {
6759 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6760 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6761 ERRSRV, ERRbadpath);
6764 reply_nterror(req, status);
6768 if (is_ntfs_stream_smb_fname(smb_dname)) {
6769 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6773 status = SMB_VFS_CREATE_FILE(
6776 0, /* root_dir_fid */
6777 smb_dname, /* fname */
6778 DELETE_ACCESS, /* access_mask */
6779 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6781 FILE_OPEN, /* create_disposition*/
6782 FILE_DIRECTORY_FILE, /* create_options */
6783 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6784 0, /* oplock_request */
6786 0, /* allocation_size */
6787 0, /* private_flags */
6792 NULL, NULL); /* create context */
6794 if (!NT_STATUS_IS_OK(status)) {
6795 if (open_was_deferred(req->xconn, req->mid)) {
6796 /* We have re-scheduled this call. */
6799 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6800 bool ok = defer_smb1_sharing_violation(req);
6805 reply_nterror(req, status);
6809 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6810 if (!NT_STATUS_IS_OK(status)) {
6811 close_file(req, fsp, ERROR_CLOSE);
6812 reply_nterror(req, status);
6816 if (!set_delete_on_close(fsp, true,
6817 conn->session_info->security_token,
6818 conn->session_info->unix_token)) {
6819 close_file(req, fsp, ERROR_CLOSE);
6820 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6824 status = close_file(req, fsp, NORMAL_CLOSE);
6825 if (!NT_STATUS_IS_OK(status)) {
6826 reply_nterror(req, status);
6828 reply_outbuf(req, 0, 0);
6831 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6833 TALLOC_FREE(smb_dname);
6834 END_PROFILE(SMBrmdir);
6838 /*******************************************************************
6839 Resolve wildcards in a filename rename.
6840 ********************************************************************/
6842 static bool resolve_wildcards(TALLOC_CTX *ctx,
6847 char *name2_copy = NULL;
6852 char *p,*p2, *pname1, *pname2;
6854 name2_copy = talloc_strdup(ctx, name2);
6859 pname1 = strrchr_m(name1,'/');
6860 pname2 = strrchr_m(name2_copy,'/');
6862 if (!pname1 || !pname2) {
6866 /* Truncate the copy of name2 at the last '/' */
6869 /* Now go past the '/' */
6873 root1 = talloc_strdup(ctx, pname1);
6874 root2 = talloc_strdup(ctx, pname2);
6876 if (!root1 || !root2) {
6880 p = strrchr_m(root1,'.');
6883 ext1 = talloc_strdup(ctx, p+1);
6885 ext1 = talloc_strdup(ctx, "");
6887 p = strrchr_m(root2,'.');
6890 ext2 = talloc_strdup(ctx, p+1);
6892 ext2 = talloc_strdup(ctx, "");
6895 if (!ext1 || !ext2) {
6903 /* Hmmm. Should this be mb-aware ? */
6906 } else if (*p2 == '*') {
6908 root2 = talloc_asprintf(ctx, "%s%s",
6927 /* Hmmm. Should this be mb-aware ? */
6930 } else if (*p2 == '*') {
6932 ext2 = talloc_asprintf(ctx, "%s%s",
6948 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6953 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6965 /****************************************************************************
6966 Ensure open files have their names updated. Updated to notify other smbd's
6968 ****************************************************************************/
6970 static void rename_open_files(connection_struct *conn,
6971 struct share_mode_lock *lck,
6973 uint32_t orig_name_hash,
6974 const struct smb_filename *smb_fname_dst)
6977 bool did_rename = False;
6979 uint32_t new_name_hash = 0;
6981 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6982 fsp = file_find_di_next(fsp)) {
6983 struct file_id_buf idbuf;
6984 /* fsp_name is a relative path under the fsp. To change this for other
6985 sharepaths we need to manipulate relative paths. */
6986 /* TODO - create the absolute path and manipulate the newname
6987 relative to the sharepath. */
6988 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6991 if (fsp->name_hash != orig_name_hash) {
6994 DBG_DEBUG("renaming file %s "
6995 "(file_id %s) from %s -> %s\n",
6997 file_id_str_buf(fsp->file_id, &idbuf),
6999 smb_fname_str_dbg(smb_fname_dst));
7001 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7002 if (NT_STATUS_IS_OK(status)) {
7004 new_name_hash = fsp->name_hash;
7009 struct file_id_buf idbuf;
7010 DBG_DEBUG("no open files on file_id %s "
7012 file_id_str_buf(id, &idbuf),
7013 smb_fname_str_dbg(smb_fname_dst));
7016 /* Send messages to all smbd's (not ourself) that the name has changed. */
7017 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7018 orig_name_hash, new_name_hash,
7023 /****************************************************************************
7024 We need to check if the source path is a parent directory of the destination
7025 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7026 refuse the rename with a sharing violation. Under UNIX the above call can
7027 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7028 probably need to check that the client is a Windows one before disallowing
7029 this as a UNIX client (one with UNIX extensions) can know the source is a
7030 symlink and make this decision intelligently. Found by an excellent bug
7031 report from <AndyLiebman@aol.com>.
7032 ****************************************************************************/
7034 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7035 const struct smb_filename *smb_fname_dst)
7037 const char *psrc = smb_fname_src->base_name;
7038 const char *pdst = smb_fname_dst->base_name;
7041 if (psrc[0] == '.' && psrc[1] == '/') {
7044 if (pdst[0] == '.' && pdst[1] == '/') {
7047 if ((slen = strlen(psrc)) > strlen(pdst)) {
7050 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7054 * Do the notify calls from a rename
7057 static void notify_rename(connection_struct *conn, bool is_dir,
7058 const struct smb_filename *smb_fname_src,
7059 const struct smb_filename *smb_fname_dst)
7061 char *parent_dir_src = NULL;
7062 char *parent_dir_dst = NULL;
7065 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7066 : FILE_NOTIFY_CHANGE_FILE_NAME;
7068 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7069 &parent_dir_src, NULL) ||
7070 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7071 &parent_dir_dst, NULL)) {
7075 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7076 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7077 smb_fname_src->base_name);
7078 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7079 smb_fname_dst->base_name);
7082 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7083 smb_fname_src->base_name);
7084 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7085 smb_fname_dst->base_name);
7088 /* this is a strange one. w2k3 gives an additional event for
7089 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7090 files, but not directories */
7092 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7093 FILE_NOTIFY_CHANGE_ATTRIBUTES
7094 |FILE_NOTIFY_CHANGE_CREATION,
7095 smb_fname_dst->base_name);
7098 TALLOC_FREE(parent_dir_src);
7099 TALLOC_FREE(parent_dir_dst);
7102 /****************************************************************************
7103 Returns an error if the parent directory for a filename is open in an
7105 ****************************************************************************/
7107 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7108 const struct smb_filename *smb_fname_dst_in)
7110 char *parent_dir = NULL;
7111 struct smb_filename smb_fname_parent;
7113 files_struct *fsp = NULL;
7116 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
7117 &parent_dir, NULL)) {
7118 return NT_STATUS_NO_MEMORY;
7120 ZERO_STRUCT(smb_fname_parent);
7121 smb_fname_parent.base_name = parent_dir;
7123 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
7125 return map_nt_error_from_unix(errno);
7129 * We're only checking on this smbd here, mostly good
7130 * enough.. and will pass tests.
7133 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
7134 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7135 fsp = file_find_di_next(fsp)) {
7136 if (fsp->access_mask & DELETE_ACCESS) {
7137 return NT_STATUS_SHARING_VIOLATION;
7140 return NT_STATUS_OK;
7143 /****************************************************************************
7144 Rename an open file - given an fsp.
7145 ****************************************************************************/
7147 NTSTATUS rename_internals_fsp(connection_struct *conn,
7149 const struct smb_filename *smb_fname_dst_in,
7151 bool replace_if_exists)
7153 TALLOC_CTX *ctx = talloc_tos();
7154 struct smb_filename *smb_fname_dst = NULL;
7155 NTSTATUS status = NT_STATUS_OK;
7156 struct share_mode_lock *lck = NULL;
7157 uint32_t access_mask = SEC_DIR_ADD_FILE;
7158 bool dst_exists, old_is_stream, new_is_stream;
7161 status = check_name(conn, smb_fname_dst_in);
7162 if (!NT_STATUS_IS_OK(status)) {
7166 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7167 if (!NT_STATUS_IS_OK(status)) {
7171 if (file_has_open_streams(fsp)) {
7172 return NT_STATUS_ACCESS_DENIED;
7175 /* Make a copy of the dst smb_fname structs */
7177 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7178 if (smb_fname_dst == NULL) {
7179 status = NT_STATUS_NO_MEMORY;
7184 * Check for special case with case preserving and not
7185 * case sensitive. If the new last component differs from the original
7186 * last component only by case, then we should allow
7187 * the rename (user is trying to change the case of the
7190 if (!conn->case_sensitive && conn->case_preserve &&
7191 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7192 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7193 char *fname_dst_parent = NULL;
7194 const char *fname_dst_lcomp = NULL;
7195 char *orig_lcomp_path = NULL;
7196 char *orig_lcomp_stream = NULL;
7200 * Split off the last component of the processed
7201 * destination name. We will compare this to
7202 * the split components of smb_fname_dst->original_lcomp.
7204 if (!parent_dirname(ctx,
7205 smb_fname_dst->base_name,
7207 &fname_dst_lcomp)) {
7208 status = NT_STATUS_NO_MEMORY;
7213 * The original_lcomp component contains
7214 * the last_component of the path + stream
7215 * name (if a stream exists).
7217 * Split off the stream name so we
7218 * can check them separately.
7221 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7222 /* POSIX - no stream component. */
7223 orig_lcomp_path = talloc_strdup(ctx,
7224 smb_fname_dst->original_lcomp);
7225 if (orig_lcomp_path == NULL) {
7229 ok = split_stream_filename(ctx,
7230 smb_fname_dst->original_lcomp,
7232 &orig_lcomp_stream);
7236 TALLOC_FREE(fname_dst_parent);
7237 status = NT_STATUS_NO_MEMORY;
7241 /* If the base names only differ by case, use original. */
7242 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7245 * Replace the modified last component with the
7248 if (!ISDOT(fname_dst_parent)) {
7249 tmp = talloc_asprintf(smb_fname_dst,
7254 tmp = talloc_strdup(smb_fname_dst,
7258 status = NT_STATUS_NO_MEMORY;
7259 TALLOC_FREE(fname_dst_parent);
7260 TALLOC_FREE(orig_lcomp_path);
7261 TALLOC_FREE(orig_lcomp_stream);
7264 TALLOC_FREE(smb_fname_dst->base_name);
7265 smb_fname_dst->base_name = tmp;
7268 /* If the stream_names only differ by case, use original. */
7269 if(!strcsequal(smb_fname_dst->stream_name,
7270 orig_lcomp_stream)) {
7271 /* Use the original stream. */
7272 char *tmp = talloc_strdup(smb_fname_dst,
7275 status = NT_STATUS_NO_MEMORY;
7276 TALLOC_FREE(fname_dst_parent);
7277 TALLOC_FREE(orig_lcomp_path);
7278 TALLOC_FREE(orig_lcomp_stream);
7281 TALLOC_FREE(smb_fname_dst->stream_name);
7282 smb_fname_dst->stream_name = tmp;
7284 TALLOC_FREE(fname_dst_parent);
7285 TALLOC_FREE(orig_lcomp_path);
7286 TALLOC_FREE(orig_lcomp_stream);
7290 * If the src and dest names are identical - including case,
7291 * don't do the rename, just return success.
7294 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7295 strcsequal(fsp->fsp_name->stream_name,
7296 smb_fname_dst->stream_name)) {
7297 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7298 "- returning success\n",
7299 smb_fname_str_dbg(smb_fname_dst)));
7300 status = NT_STATUS_OK;
7304 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7305 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7307 /* Return the correct error code if both names aren't streams. */
7308 if (!old_is_stream && new_is_stream) {
7309 status = NT_STATUS_OBJECT_NAME_INVALID;
7313 if (old_is_stream && !new_is_stream) {
7314 status = NT_STATUS_INVALID_PARAMETER;
7318 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7320 if(!replace_if_exists && dst_exists) {
7321 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7322 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7323 smb_fname_str_dbg(smb_fname_dst)));
7324 status = NT_STATUS_OBJECT_NAME_COLLISION;
7329 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7330 &smb_fname_dst->st);
7331 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7333 /* The file can be open when renaming a stream */
7334 if (dst_fsp && !new_is_stream) {
7335 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7336 status = NT_STATUS_ACCESS_DENIED;
7341 /* Ensure we have a valid stat struct for the source. */
7342 status = vfs_stat_fsp(fsp);
7343 if (!NT_STATUS_IS_OK(status)) {
7347 status = can_rename(conn, fsp, attrs);
7349 if (!NT_STATUS_IS_OK(status)) {
7350 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7351 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7352 smb_fname_str_dbg(smb_fname_dst)));
7353 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7354 status = NT_STATUS_ACCESS_DENIED;
7358 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7359 status = NT_STATUS_ACCESS_DENIED;
7363 /* Do we have rights to move into the destination ? */
7364 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7365 /* We're moving a directory. */
7366 access_mask = SEC_DIR_ADD_SUBDIR;
7368 status = check_parent_access(conn,
7371 if (!NT_STATUS_IS_OK(status)) {
7372 DBG_INFO("check_parent_access on "
7373 "dst %s returned %s\n",
7374 smb_fname_str_dbg(smb_fname_dst),
7379 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7382 * We have the file open ourselves, so not being able to get the
7383 * corresponding share mode lock is a fatal error.
7386 SMB_ASSERT(lck != NULL);
7388 ret = SMB_VFS_RENAMEAT(conn,
7394 uint32_t create_options = fsp->fh->private_options;
7396 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7397 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7398 smb_fname_str_dbg(smb_fname_dst)));
7400 if (!fsp->is_directory &&
7401 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7402 (lp_map_archive(SNUM(conn)) ||
7403 lp_store_dos_attributes(SNUM(conn)))) {
7404 /* We must set the archive bit on the newly
7406 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7407 uint32_t old_dosmode = dos_mode(conn,
7409 file_set_dosmode(conn,
7411 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7417 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
7420 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7424 * A rename acts as a new file create w.r.t. allowing an initial delete
7425 * on close, probably because in Windows there is a new handle to the
7426 * new file. If initial delete on close was requested but not
7427 * originally set, we need to set it here. This is probably not 100% correct,
7428 * but will work for the CIFSFS client which in non-posix mode
7429 * depends on these semantics. JRA.
7432 if (create_options & FILE_DELETE_ON_CLOSE) {
7433 status = can_set_delete_on_close(fsp, 0);
7435 if (NT_STATUS_IS_OK(status)) {
7436 /* Note that here we set the *initial* delete on close flag,
7437 * not the regular one. The magic gets handled in close. */
7438 fsp->initial_delete_on_close = True;
7442 status = NT_STATUS_OK;
7448 if (errno == ENOTDIR || errno == EISDIR) {
7449 status = NT_STATUS_OBJECT_NAME_COLLISION;
7451 status = map_nt_error_from_unix(errno);
7454 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7455 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7456 smb_fname_str_dbg(smb_fname_dst)));
7459 TALLOC_FREE(smb_fname_dst);
7464 /****************************************************************************
7465 The guts of the rename command, split out so it may be called by the NT SMB
7467 ****************************************************************************/
7469 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7470 connection_struct *conn,
7471 struct smb_request *req,
7472 struct smb_filename *smb_fname_src,
7473 struct smb_filename *smb_fname_dst,
7475 bool replace_if_exists,
7478 uint32_t access_mask)
7480 char *fname_src_dir = NULL;
7481 struct smb_filename *smb_fname_src_dir = NULL;
7482 char *fname_src_mask = NULL;
7484 NTSTATUS status = NT_STATUS_OK;
7485 struct smb_Dir *dir_hnd = NULL;
7486 const char *dname = NULL;
7487 char *talloced = NULL;
7489 int create_options = 0;
7490 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7491 struct smb2_create_blobs *posx = NULL;
7495 * Split the old name into directory and last component
7496 * strings. Note that unix_convert may have stripped off a
7497 * leading ./ from both name and newname if the rename is
7498 * at the root of the share. We need to make sure either both
7499 * name and newname contain a / character or neither of them do
7500 * as this is checked in resolve_wildcards().
7503 /* Split up the directory from the filename/mask. */
7504 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7505 &fname_src_dir, &fname_src_mask);
7506 if (!NT_STATUS_IS_OK(status)) {
7507 status = NT_STATUS_NO_MEMORY;
7512 * We should only check the mangled cache
7513 * here if unix_convert failed. This means
7514 * that the path in 'mask' doesn't exist
7515 * on the file system and so we need to look
7516 * for a possible mangle. This patch from
7517 * Tine Smukavec <valentin.smukavec@hermes.si>.
7520 if (!VALID_STAT(smb_fname_src->st) &&
7521 mangle_is_mangled(fname_src_mask, conn->params)) {
7522 char *new_mask = NULL;
7523 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7526 TALLOC_FREE(fname_src_mask);
7527 fname_src_mask = new_mask;
7531 if (posix_pathnames) {
7532 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7533 if (!NT_STATUS_IS_OK(status)) {
7534 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7540 if (!src_has_wild) {
7544 * Only one file needs to be renamed. Append the mask back
7545 * onto the directory.
7547 TALLOC_FREE(smb_fname_src->base_name);
7548 if (ISDOT(fname_src_dir)) {
7549 /* Ensure we use canonical names on open. */
7550 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7554 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7559 if (!smb_fname_src->base_name) {
7560 status = NT_STATUS_NO_MEMORY;
7564 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7565 "case_preserve = %d, short case preserve = %d, "
7566 "directory = %s, newname = %s, "
7567 "last_component_dest = %s\n",
7568 conn->case_sensitive, conn->case_preserve,
7569 conn->short_case_preserve,
7570 smb_fname_str_dbg(smb_fname_src),
7571 smb_fname_str_dbg(smb_fname_dst),
7572 smb_fname_dst->original_lcomp));
7574 /* The dest name still may have wildcards. */
7575 if (dest_has_wild) {
7576 char *fname_dst_mod = NULL;
7577 if (!resolve_wildcards(smb_fname_dst,
7578 smb_fname_src->base_name,
7579 smb_fname_dst->base_name,
7581 DEBUG(6, ("rename_internals: resolve_wildcards "
7583 smb_fname_src->base_name,
7584 smb_fname_dst->base_name));
7585 status = NT_STATUS_NO_MEMORY;
7588 TALLOC_FREE(smb_fname_dst->base_name);
7589 smb_fname_dst->base_name = fname_dst_mod;
7592 ZERO_STRUCT(smb_fname_src->st);
7593 if (posix_pathnames) {
7594 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7596 rc = SMB_VFS_STAT(conn, smb_fname_src);
7599 status = map_nt_error_from_unix_common(errno);
7603 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7604 create_options |= FILE_DIRECTORY_FILE;
7607 status = SMB_VFS_CREATE_FILE(
7610 0, /* root_dir_fid */
7611 smb_fname_src, /* fname */
7612 access_mask, /* access_mask */
7613 (FILE_SHARE_READ | /* share_access */
7615 FILE_OPEN, /* create_disposition*/
7616 create_options, /* create_options */
7617 0, /* file_attributes */
7618 0, /* oplock_request */
7620 0, /* allocation_size */
7621 0, /* private_flags */
7626 posx, /* in_context_blobs */
7627 NULL); /* out_context_blobs */
7629 if (!NT_STATUS_IS_OK(status)) {
7630 DEBUG(3, ("Could not open rename source %s: %s\n",
7631 smb_fname_str_dbg(smb_fname_src),
7632 nt_errstr(status)));
7636 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7637 attrs, replace_if_exists);
7639 close_file(req, fsp, NORMAL_CLOSE);
7641 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7642 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7643 smb_fname_str_dbg(smb_fname_dst)));
7649 * Wildcards - process each file that matches.
7651 if (strequal(fname_src_mask, "????????.???")) {
7652 TALLOC_FREE(fname_src_mask);
7653 fname_src_mask = talloc_strdup(ctx, "*");
7654 if (!fname_src_mask) {
7655 status = NT_STATUS_NO_MEMORY;
7660 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7664 smb_fname_src->flags);
7665 if (smb_fname_src_dir == NULL) {
7666 status = NT_STATUS_NO_MEMORY;
7670 status = check_name(conn, smb_fname_src_dir);
7671 if (!NT_STATUS_IS_OK(status)) {
7675 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7677 if (dir_hnd == NULL) {
7678 status = map_nt_error_from_unix(errno);
7682 status = NT_STATUS_NO_SUCH_FILE;
7684 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7685 * - gentest fix. JRA
7688 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7690 files_struct *fsp = NULL;
7691 char *destname = NULL;
7692 bool sysdir_entry = False;
7694 /* Quick check for "." and ".." */
7695 if (ISDOT(dname) || ISDOTDOT(dname)) {
7696 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7697 sysdir_entry = True;
7699 TALLOC_FREE(talloced);
7704 if (!is_visible_file(conn, fname_src_dir, dname,
7705 &smb_fname_src->st, false)) {
7706 TALLOC_FREE(talloced);
7710 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7711 TALLOC_FREE(talloced);
7716 status = NT_STATUS_OBJECT_NAME_INVALID;
7720 TALLOC_FREE(smb_fname_src->base_name);
7721 if (ISDOT(fname_src_dir)) {
7722 /* Ensure we use canonical names on open. */
7723 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7727 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7732 if (!smb_fname_src->base_name) {
7733 status = NT_STATUS_NO_MEMORY;
7737 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7738 smb_fname_dst->base_name,
7740 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7741 smb_fname_src->base_name, destname));
7742 TALLOC_FREE(talloced);
7746 status = NT_STATUS_NO_MEMORY;
7750 TALLOC_FREE(smb_fname_dst->base_name);
7751 smb_fname_dst->base_name = destname;
7753 ZERO_STRUCT(smb_fname_src->st);
7754 if (posix_pathnames) {
7755 SMB_VFS_LSTAT(conn, smb_fname_src);
7757 SMB_VFS_STAT(conn, smb_fname_src);
7762 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7763 create_options |= FILE_DIRECTORY_FILE;
7766 status = SMB_VFS_CREATE_FILE(
7769 0, /* root_dir_fid */
7770 smb_fname_src, /* fname */
7771 access_mask, /* access_mask */
7772 (FILE_SHARE_READ | /* share_access */
7774 FILE_OPEN, /* create_disposition*/
7775 create_options, /* create_options */
7776 0, /* file_attributes */
7777 0, /* oplock_request */
7779 0, /* allocation_size */
7780 0, /* private_flags */
7785 posx, /* in_context_blobs */
7786 NULL); /* out_context_blobs */
7788 if (!NT_STATUS_IS_OK(status)) {
7789 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7790 "returned %s rename %s -> %s\n",
7792 smb_fname_str_dbg(smb_fname_src),
7793 smb_fname_str_dbg(smb_fname_dst)));
7797 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7799 if (!smb_fname_dst->original_lcomp) {
7800 status = NT_STATUS_NO_MEMORY;
7804 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7805 attrs, replace_if_exists);
7807 close_file(req, fsp, NORMAL_CLOSE);
7809 if (!NT_STATUS_IS_OK(status)) {
7810 DEBUG(3, ("rename_internals_fsp returned %s for "
7811 "rename %s -> %s\n", nt_errstr(status),
7812 smb_fname_str_dbg(smb_fname_src),
7813 smb_fname_str_dbg(smb_fname_dst)));
7819 DEBUG(3,("rename_internals: doing rename on %s -> "
7820 "%s\n", smb_fname_str_dbg(smb_fname_src),
7821 smb_fname_str_dbg(smb_fname_src)));
7822 TALLOC_FREE(talloced);
7824 TALLOC_FREE(dir_hnd);
7826 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7827 status = map_nt_error_from_unix(errno);
7832 TALLOC_FREE(talloced);
7833 TALLOC_FREE(smb_fname_src_dir);
7834 TALLOC_FREE(fname_src_dir);
7835 TALLOC_FREE(fname_src_mask);
7839 /****************************************************************************
7841 ****************************************************************************/
7843 void reply_mv(struct smb_request *req)
7845 connection_struct *conn = req->conn;
7847 char *newname = NULL;
7851 bool src_has_wcard = False;
7852 bool dest_has_wcard = False;
7853 TALLOC_CTX *ctx = talloc_tos();
7854 struct smb_filename *smb_fname_src = NULL;
7855 struct smb_filename *smb_fname_dst = NULL;
7856 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7857 (req->posix_pathnames ?
7858 UCF_UNIX_NAME_LOOKUP :
7859 UCF_COND_ALLOW_WCARD_LCOMP);
7860 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7862 (req->posix_pathnames ?
7864 UCF_COND_ALLOW_WCARD_LCOMP);
7865 bool stream_rename = false;
7867 START_PROFILE(SMBmv);
7870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7874 attrs = SVAL(req->vwv+0, 0);
7876 p = (const char *)req->buf + 1;
7877 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7878 &status, &src_has_wcard);
7879 if (!NT_STATUS_IS_OK(status)) {
7880 reply_nterror(req, status);
7884 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7885 &status, &dest_has_wcard);
7886 if (!NT_STATUS_IS_OK(status)) {
7887 reply_nterror(req, status);
7891 if (!req->posix_pathnames) {
7892 /* The newname must begin with a ':' if the
7893 name contains a ':'. */
7894 if (strchr_m(name, ':')) {
7895 if (newname[0] != ':') {
7896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7899 stream_rename = true;
7903 status = filename_convert(ctx,
7911 if (!NT_STATUS_IS_OK(status)) {
7912 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7913 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7914 ERRSRV, ERRbadpath);
7917 reply_nterror(req, status);
7921 status = filename_convert(ctx,
7929 if (!NT_STATUS_IS_OK(status)) {
7930 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7931 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7932 ERRSRV, ERRbadpath);
7935 reply_nterror(req, status);
7939 if (stream_rename) {
7940 /* smb_fname_dst->base_name must be the same as
7941 smb_fname_src->base_name. */
7942 TALLOC_FREE(smb_fname_dst->base_name);
7943 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7944 smb_fname_src->base_name);
7945 if (!smb_fname_dst->base_name) {
7946 reply_nterror(req, NT_STATUS_NO_MEMORY);
7951 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7952 smb_fname_str_dbg(smb_fname_dst)));
7954 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7955 attrs, False, src_has_wcard, dest_has_wcard,
7957 if (!NT_STATUS_IS_OK(status)) {
7958 if (open_was_deferred(req->xconn, req->mid)) {
7959 /* We have re-scheduled this call. */
7962 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7963 bool ok = defer_smb1_sharing_violation(req);
7968 reply_nterror(req, status);
7972 reply_outbuf(req, 0, 0);
7974 TALLOC_FREE(smb_fname_src);
7975 TALLOC_FREE(smb_fname_dst);
7980 /*******************************************************************
7981 Copy a file as part of a reply_copy.
7982 ******************************************************************/
7985 * TODO: check error codes on all callers
7988 NTSTATUS copy_file(TALLOC_CTX *ctx,
7989 connection_struct *conn,
7990 struct smb_filename *smb_fname_src,
7991 struct smb_filename *smb_fname_dst,
7994 bool target_is_directory)
7996 struct smb_filename *smb_fname_dst_tmp = NULL;
7998 files_struct *fsp1,*fsp2;
8000 uint32_t new_create_disposition;
8004 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8005 if (smb_fname_dst_tmp == NULL) {
8006 return NT_STATUS_NO_MEMORY;
8010 * If the target is a directory, extract the last component from the
8011 * src filename and append it to the dst filename
8013 if (target_is_directory) {
8016 /* dest/target can't be a stream if it's a directory. */
8017 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8019 p = strrchr_m(smb_fname_src->base_name,'/');
8023 p = smb_fname_src->base_name;
8025 smb_fname_dst_tmp->base_name =
8026 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8028 if (!smb_fname_dst_tmp->base_name) {
8029 status = NT_STATUS_NO_MEMORY;
8034 status = vfs_file_exist(conn, smb_fname_src);
8035 if (!NT_STATUS_IS_OK(status)) {
8039 if (!target_is_directory && count) {
8040 new_create_disposition = FILE_OPEN;
8042 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8045 &new_create_disposition,
8048 status = NT_STATUS_INVALID_PARAMETER;
8053 /* Open the src file for reading. */
8054 status = SMB_VFS_CREATE_FILE(
8057 0, /* root_dir_fid */
8058 smb_fname_src, /* fname */
8059 FILE_GENERIC_READ, /* access_mask */
8060 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8061 FILE_OPEN, /* create_disposition*/
8062 0, /* create_options */
8063 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8064 INTERNAL_OPEN_ONLY, /* oplock_request */
8066 0, /* allocation_size */
8067 0, /* private_flags */
8072 NULL, NULL); /* create context */
8074 if (!NT_STATUS_IS_OK(status)) {
8078 dosattrs = dos_mode(conn, smb_fname_src);
8080 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8081 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8084 /* Open the dst file for writing. */
8085 status = SMB_VFS_CREATE_FILE(
8088 0, /* root_dir_fid */
8089 smb_fname_dst, /* fname */
8090 FILE_GENERIC_WRITE, /* access_mask */
8091 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8092 new_create_disposition, /* create_disposition*/
8093 0, /* create_options */
8094 dosattrs, /* file_attributes */
8095 INTERNAL_OPEN_ONLY, /* oplock_request */
8097 0, /* allocation_size */
8098 0, /* private_flags */
8103 NULL, NULL); /* create context */
8105 if (!NT_STATUS_IS_OK(status)) {
8106 close_file(NULL, fsp1, ERROR_CLOSE);
8110 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8111 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8113 DEBUG(0, ("error - vfs lseek returned error %s\n",
8115 status = map_nt_error_from_unix(errno);
8116 close_file(NULL, fsp1, ERROR_CLOSE);
8117 close_file(NULL, fsp2, ERROR_CLOSE);
8122 /* Do the actual copy. */
8123 if (smb_fname_src->st.st_ex_size) {
8124 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8129 close_file(NULL, fsp1, NORMAL_CLOSE);
8131 /* Ensure the modtime is set correctly on the destination file. */
8132 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8135 * As we are opening fsp1 read-only we only expect
8136 * an error on close on fsp2 if we are out of space.
8137 * Thus we don't look at the error return from the
8140 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8142 if (!NT_STATUS_IS_OK(status)) {
8146 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8147 status = NT_STATUS_DISK_FULL;
8151 status = NT_STATUS_OK;
8154 TALLOC_FREE(smb_fname_dst_tmp);
8158 /****************************************************************************
8159 Reply to a file copy.
8160 ****************************************************************************/
8162 void reply_copy(struct smb_request *req)
8164 connection_struct *conn = req->conn;
8165 struct smb_filename *smb_fname_src = NULL;
8166 struct smb_filename *smb_fname_src_dir = NULL;
8167 struct smb_filename *smb_fname_dst = NULL;
8168 char *fname_src = NULL;
8169 char *fname_dst = NULL;
8170 char *fname_src_mask = NULL;
8171 char *fname_src_dir = NULL;
8174 int error = ERRnoaccess;
8178 bool target_is_directory=False;
8179 bool source_has_wild = False;
8180 bool dest_has_wild = False;
8182 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
8183 ucf_flags_from_smb_request(req);
8184 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
8185 ucf_flags_from_smb_request(req);
8186 TALLOC_CTX *ctx = talloc_tos();
8188 START_PROFILE(SMBcopy);
8191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8195 tid2 = SVAL(req->vwv+0, 0);
8196 ofun = SVAL(req->vwv+1, 0);
8197 flags = SVAL(req->vwv+2, 0);
8199 p = (const char *)req->buf;
8200 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8201 &status, &source_has_wild);
8202 if (!NT_STATUS_IS_OK(status)) {
8203 reply_nterror(req, status);
8206 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8207 &status, &dest_has_wild);
8208 if (!NT_STATUS_IS_OK(status)) {
8209 reply_nterror(req, status);
8213 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8215 if (tid2 != conn->cnum) {
8216 /* can't currently handle inter share copies XXXX */
8217 DEBUG(3,("Rejecting inter-share copy\n"));
8218 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8222 status = filename_convert(ctx, conn,
8228 if (!NT_STATUS_IS_OK(status)) {
8229 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8230 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8231 ERRSRV, ERRbadpath);
8234 reply_nterror(req, status);
8238 status = filename_convert(ctx, conn,
8244 if (!NT_STATUS_IS_OK(status)) {
8245 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8246 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8247 ERRSRV, ERRbadpath);
8250 reply_nterror(req, status);
8254 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8256 if ((flags&1) && target_is_directory) {
8257 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8261 if ((flags&2) && !target_is_directory) {
8262 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8266 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8267 /* wants a tree copy! XXXX */
8268 DEBUG(3,("Rejecting tree copy\n"));
8269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8273 /* Split up the directory from the filename/mask. */
8274 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8275 &fname_src_dir, &fname_src_mask);
8276 if (!NT_STATUS_IS_OK(status)) {
8277 reply_nterror(req, NT_STATUS_NO_MEMORY);
8282 * We should only check the mangled cache
8283 * here if unix_convert failed. This means
8284 * that the path in 'mask' doesn't exist
8285 * on the file system and so we need to look
8286 * for a possible mangle. This patch from
8287 * Tine Smukavec <valentin.smukavec@hermes.si>.
8289 if (!VALID_STAT(smb_fname_src->st) &&
8290 mangle_is_mangled(fname_src_mask, conn->params)) {
8291 char *new_mask = NULL;
8292 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8293 &new_mask, conn->params);
8295 /* Use demangled name if one was successfully found. */
8297 TALLOC_FREE(fname_src_mask);
8298 fname_src_mask = new_mask;
8302 if (!source_has_wild) {
8305 * Only one file needs to be copied. Append the mask back onto
8308 TALLOC_FREE(smb_fname_src->base_name);
8309 if (ISDOT(fname_src_dir)) {
8310 /* Ensure we use canonical names on open. */
8311 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8315 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8320 if (!smb_fname_src->base_name) {
8321 reply_nterror(req, NT_STATUS_NO_MEMORY);
8325 if (dest_has_wild) {
8326 char *fname_dst_mod = NULL;
8327 if (!resolve_wildcards(smb_fname_dst,
8328 smb_fname_src->base_name,
8329 smb_fname_dst->base_name,
8331 reply_nterror(req, NT_STATUS_NO_MEMORY);
8334 TALLOC_FREE(smb_fname_dst->base_name);
8335 smb_fname_dst->base_name = fname_dst_mod;
8338 status = check_name(conn, smb_fname_src);
8339 if (!NT_STATUS_IS_OK(status)) {
8340 reply_nterror(req, status);
8344 status = check_name(conn, smb_fname_dst);
8345 if (!NT_STATUS_IS_OK(status)) {
8346 reply_nterror(req, status);
8350 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8351 ofun, count, target_is_directory);
8353 if(!NT_STATUS_IS_OK(status)) {
8354 reply_nterror(req, status);
8360 struct smb_Dir *dir_hnd = NULL;
8361 const char *dname = NULL;
8362 char *talloced = NULL;
8366 * There is a wildcard that requires us to actually read the
8367 * src dir and copy each file matching the mask to the dst.
8368 * Right now streams won't be copied, but this could
8369 * presumably be added with a nested loop for reach dir entry.
8371 SMB_ASSERT(!smb_fname_src->stream_name);
8372 SMB_ASSERT(!smb_fname_dst->stream_name);
8374 smb_fname_src->stream_name = NULL;
8375 smb_fname_dst->stream_name = NULL;
8377 if (strequal(fname_src_mask,"????????.???")) {
8378 TALLOC_FREE(fname_src_mask);
8379 fname_src_mask = talloc_strdup(ctx, "*");
8380 if (!fname_src_mask) {
8381 reply_nterror(req, NT_STATUS_NO_MEMORY);
8386 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8390 smb_fname_src->flags);
8391 if (smb_fname_src_dir == NULL) {
8392 reply_nterror(req, NT_STATUS_NO_MEMORY);
8396 status = check_name(conn, smb_fname_src_dir);
8397 if (!NT_STATUS_IS_OK(status)) {
8398 reply_nterror(req, status);
8402 dir_hnd = OpenDir(ctx,
8407 if (dir_hnd == NULL) {
8408 status = map_nt_error_from_unix(errno);
8409 reply_nterror(req, status);
8415 /* Iterate over the src dir copying each entry to the dst. */
8416 while ((dname = ReadDirName(dir_hnd, &offset,
8417 &smb_fname_src->st, &talloced))) {
8418 char *destname = NULL;
8420 if (ISDOT(dname) || ISDOTDOT(dname)) {
8421 TALLOC_FREE(talloced);
8425 if (!is_visible_file(conn, fname_src_dir, dname,
8426 &smb_fname_src->st, false)) {
8427 TALLOC_FREE(talloced);
8431 if(!mask_match(dname, fname_src_mask,
8432 conn->case_sensitive)) {
8433 TALLOC_FREE(talloced);
8437 error = ERRnoaccess;
8439 /* Get the src smb_fname struct setup. */
8440 TALLOC_FREE(smb_fname_src->base_name);
8441 if (ISDOT(fname_src_dir)) {
8442 /* Ensure we use canonical names on open. */
8443 smb_fname_src->base_name =
8444 talloc_asprintf(smb_fname_src, "%s",
8447 smb_fname_src->base_name =
8448 talloc_asprintf(smb_fname_src, "%s/%s",
8449 fname_src_dir, dname);
8452 if (!smb_fname_src->base_name) {
8453 TALLOC_FREE(dir_hnd);
8454 TALLOC_FREE(talloced);
8455 reply_nterror(req, NT_STATUS_NO_MEMORY);
8459 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8460 smb_fname_dst->base_name,
8462 TALLOC_FREE(talloced);
8466 TALLOC_FREE(dir_hnd);
8467 TALLOC_FREE(talloced);
8468 reply_nterror(req, NT_STATUS_NO_MEMORY);
8472 TALLOC_FREE(smb_fname_dst->base_name);
8473 smb_fname_dst->base_name = destname;
8475 status = check_name(conn, smb_fname_src);
8476 if (!NT_STATUS_IS_OK(status)) {
8477 TALLOC_FREE(dir_hnd);
8478 TALLOC_FREE(talloced);
8479 reply_nterror(req, status);
8483 status = check_name(conn, smb_fname_dst);
8484 if (!NT_STATUS_IS_OK(status)) {
8485 TALLOC_FREE(dir_hnd);
8486 TALLOC_FREE(talloced);
8487 reply_nterror(req, status);
8491 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8492 smb_fname_src->base_name,
8493 smb_fname_dst->base_name));
8495 status = copy_file(ctx, conn, smb_fname_src,
8496 smb_fname_dst, ofun, count,
8497 target_is_directory);
8498 if (NT_STATUS_IS_OK(status)) {
8502 TALLOC_FREE(talloced);
8504 TALLOC_FREE(dir_hnd);
8508 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8512 reply_outbuf(req, 1, 0);
8513 SSVAL(req->outbuf,smb_vwv0,count);
8515 TALLOC_FREE(smb_fname_src);
8516 TALLOC_FREE(smb_fname_src_dir);
8517 TALLOC_FREE(smb_fname_dst);
8518 TALLOC_FREE(fname_src);
8519 TALLOC_FREE(fname_dst);
8520 TALLOC_FREE(fname_src_mask);
8521 TALLOC_FREE(fname_src_dir);
8523 END_PROFILE(SMBcopy);
8528 #define DBGC_CLASS DBGC_LOCKING
8530 /****************************************************************************
8531 Get a lock pid, dealing with large count requests.
8532 ****************************************************************************/
8534 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8535 bool large_file_format)
8537 if(!large_file_format)
8538 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8540 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8543 /****************************************************************************
8544 Get a lock count, dealing with large count requests.
8545 ****************************************************************************/
8547 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8548 bool large_file_format)
8552 if(!large_file_format) {
8553 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8556 * No BVAL, this is reversed!
8558 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8559 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8565 /****************************************************************************
8566 Get a lock offset, dealing with large offset requests.
8567 ****************************************************************************/
8569 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8570 bool large_file_format)
8572 uint64_t offset = 0;
8574 if(!large_file_format) {
8575 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8578 * No BVAL, this is reversed!
8580 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8581 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8587 struct smbd_do_unlocking_state {
8588 struct files_struct *fsp;
8589 uint16_t num_ulocks;
8590 struct smbd_lock_element *ulocks;
8591 enum brl_flavour lock_flav;
8595 static void smbd_do_unlocking_fn(
8596 TDB_DATA value, bool *pmodified_dependent, void *private_data)
8598 struct smbd_do_unlocking_state *state = private_data;
8599 struct files_struct *fsp = state->fsp;
8600 enum brl_flavour lock_flav = state->lock_flav;
8603 for (i = 0; i < state->num_ulocks; i++) {
8604 struct smbd_lock_element *e = &state->ulocks[i];
8606 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
8607 "pid %"PRIu64", file %s\n",
8613 if (e->brltype != UNLOCK_LOCK) {
8614 /* this can only happen with SMB2 */
8615 state->status = NT_STATUS_INVALID_PARAMETER;
8619 state->status = do_unlock(
8620 fsp, e->smblctx, e->count, e->offset, lock_flav);
8622 DBG_DEBUG("do_unlock returned %s\n",
8623 nt_errstr(state->status));
8625 if (!NT_STATUS_IS_OK(state->status)) {
8630 *pmodified_dependent = true;
8633 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8635 uint16_t num_ulocks,
8636 struct smbd_lock_element *ulocks,
8637 enum brl_flavour lock_flav)
8639 struct smbd_do_unlocking_state state = {
8641 .num_ulocks = num_ulocks,
8643 .lock_flav = lock_flav,
8647 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
8649 status = share_mode_do_locked(
8650 fsp->file_id, smbd_do_unlocking_fn, &state);
8652 if (!NT_STATUS_IS_OK(status)) {
8653 DBG_DEBUG("share_mode_do_locked failed: %s\n",
8657 if (!NT_STATUS_IS_OK(state.status)) {
8658 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
8660 return state.status;
8663 return NT_STATUS_OK;
8666 /****************************************************************************
8667 Reply to a lockingX request.
8668 ****************************************************************************/
8670 static void reply_lockingx_done(struct tevent_req *subreq);
8672 void reply_lockingX(struct smb_request *req)
8674 connection_struct *conn = req->conn;
8676 unsigned char locktype;
8677 enum brl_type brltype;
8678 unsigned char oplocklevel;
8679 uint16_t num_ulocks;
8681 int32_t lock_timeout;
8683 const uint8_t *data;
8684 bool large_file_format;
8685 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8686 struct smbd_lock_element *locks = NULL;
8687 struct tevent_req *subreq = NULL;
8689 START_PROFILE(SMBlockingX);
8692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8693 END_PROFILE(SMBlockingX);
8697 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8698 locktype = CVAL(req->vwv+3, 0);
8699 oplocklevel = CVAL(req->vwv+3, 1);
8700 num_ulocks = SVAL(req->vwv+6, 0);
8701 num_locks = SVAL(req->vwv+7, 0);
8702 lock_timeout = IVAL(req->vwv+4, 0);
8703 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8705 if (!check_fsp(conn, req, fsp)) {
8706 END_PROFILE(SMBlockingX);
8712 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8713 /* we don't support these - and CANCEL_LOCK makes w2k
8714 and XP reboot so I don't really want to be
8715 compatible! (tridge) */
8716 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8717 END_PROFILE(SMBlockingX);
8721 /* Check if this is an oplock break on a file
8722 we have granted an oplock on.
8724 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8725 /* Client can insist on breaking to none. */
8726 bool break_to_none = (oplocklevel == 0);
8729 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8730 "for %s\n", (unsigned int)oplocklevel,
8731 fsp_fnum_dbg(fsp)));
8734 * Make sure we have granted an exclusive or batch oplock on
8738 if (fsp->oplock_type == 0) {
8740 /* The Samba4 nbench simulator doesn't understand
8741 the difference between break to level2 and break
8742 to none from level2 - it sends oplock break
8743 replies in both cases. Don't keep logging an error
8744 message here - just ignore it. JRA. */
8746 DEBUG(5,("reply_lockingX: Error : oplock break from "
8747 "client for %s (oplock=%d) and no "
8748 "oplock granted on this file (%s).\n",
8749 fsp_fnum_dbg(fsp), fsp->oplock_type,
8752 /* if this is a pure oplock break request then don't
8754 if (num_locks == 0 && num_ulocks == 0) {
8755 END_PROFILE(SMBlockingX);
8759 END_PROFILE(SMBlockingX);
8760 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8764 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8766 result = remove_oplock(fsp);
8768 result = downgrade_oplock(fsp);
8772 DEBUG(0, ("reply_lockingX: error in removing "
8773 "oplock on file %s\n", fsp_str_dbg(fsp)));
8774 /* Hmmm. Is this panic justified? */
8775 smb_panic("internal tdb error");
8778 /* if this is a pure oplock break request then don't send a
8780 if (num_locks == 0 && num_ulocks == 0) {
8781 /* Sanity check - ensure a pure oplock break is not a
8783 if (CVAL(req->vwv+0, 0) != 0xff) {
8784 DEBUG(0,("reply_lockingX: Error : pure oplock "
8785 "break is a chained %d request !\n",
8786 (unsigned int)CVAL(req->vwv+0, 0)));
8788 END_PROFILE(SMBlockingX);
8794 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8796 END_PROFILE(SMBlockingX);
8800 if (num_ulocks != 0) {
8801 struct smbd_lock_element *ulocks = NULL;
8804 ulocks = talloc_array(
8805 req, struct smbd_lock_element, num_ulocks);
8806 if (ulocks == NULL) {
8807 reply_nterror(req, NT_STATUS_NO_MEMORY);
8808 END_PROFILE(SMBlockingX);
8813 * Data now points at the beginning of the list of
8814 * smb_unlkrng structs
8816 for (i = 0; i < num_ulocks; i++) {
8817 ulocks[i].req_guid = smbd_request_guid(req,
8819 ulocks[i].smblctx = get_lock_pid(
8820 data, i, large_file_format);
8821 ulocks[i].count = get_lock_count(
8822 data, i, large_file_format);
8823 ulocks[i].offset = get_lock_offset(
8824 data, i, large_file_format);
8825 ulocks[i].brltype = UNLOCK_LOCK;
8829 * Unlock cancels pending locks
8832 ok = smbd_smb1_brl_finish_by_lock(
8839 reply_outbuf(req, 2, 0);
8840 SSVAL(req->outbuf, smb_vwv0, 0xff);
8841 SSVAL(req->outbuf, smb_vwv1, 0);
8842 END_PROFILE(SMBlockingX);
8846 status = smbd_do_unlocking(
8847 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
8848 TALLOC_FREE(ulocks);
8849 if (!NT_STATUS_IS_OK(status)) {
8850 END_PROFILE(SMBlockingX);
8851 reply_nterror(req, status);
8856 /* Now do any requested locks */
8857 data += ((large_file_format ? 20 : 10)*num_ulocks);
8859 /* Data now points at the beginning of the list
8860 of smb_lkrng structs */
8862 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8863 brltype = READ_LOCK;
8865 brltype = WRITE_LOCK;
8868 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8869 if (locks == NULL) {
8870 reply_nterror(req, NT_STATUS_NO_MEMORY);
8871 END_PROFILE(SMBlockingX);
8875 for (i = 0; i < num_locks; i++) {
8876 locks[i].req_guid = smbd_request_guid(req, i),
8877 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8878 locks[i].count = get_lock_count(data, i, large_file_format);
8879 locks[i].offset = get_lock_offset(data, i, large_file_format);
8880 locks[i].brltype = brltype;
8883 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8887 if (num_locks == 0) {
8888 /* See smbtorture3 lock11 test */
8889 reply_outbuf(req, 2, 0);
8890 /* andx chain ends */
8891 SSVAL(req->outbuf, smb_vwv0, 0xff);
8892 SSVAL(req->outbuf, smb_vwv1, 0);
8893 END_PROFILE(SMBlockingX);
8897 ok = smbd_smb1_brl_finish_by_lock(
8901 locks[0], /* Windows only cancels the first lock */
8902 NT_STATUS_FILE_LOCK_CONFLICT);
8905 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
8906 END_PROFILE(SMBlockingX);
8910 reply_outbuf(req, 2, 0);
8911 SSVAL(req->outbuf, smb_vwv0, 0xff);
8912 SSVAL(req->outbuf, smb_vwv1, 0);
8913 END_PROFILE(SMBlockingX);
8917 subreq = smbd_smb1_do_locks_send(
8927 if (subreq == NULL) {
8928 reply_nterror(req, NT_STATUS_NO_MEMORY);
8929 END_PROFILE(SMBlockingX);
8932 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
8933 END_PROFILE(SMBlockingX);
8936 static void reply_lockingx_done(struct tevent_req *subreq)
8938 struct smb_request *req = NULL;
8942 START_PROFILE(SMBlockingX);
8944 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
8947 status = smbd_smb1_do_locks_recv(subreq);
8948 TALLOC_FREE(subreq);
8950 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
8952 if (NT_STATUS_IS_OK(status)) {
8953 reply_outbuf(req, 2, 0);
8954 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8955 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8957 reply_nterror(req, status);
8960 ok = srv_send_smb(req->xconn,
8961 (char *)req->outbuf,
8964 IS_CONN_ENCRYPTED(req->conn),
8967 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
8970 END_PROFILE(SMBlockingX);
8974 #define DBGC_CLASS DBGC_ALL
8976 /****************************************************************************
8977 Reply to a SMBreadbmpx (read block multiplex) request.
8978 Always reply with an error, if someone has a platform really needs this,
8979 please contact vl@samba.org
8980 ****************************************************************************/
8982 void reply_readbmpx(struct smb_request *req)
8984 START_PROFILE(SMBreadBmpx);
8985 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8986 END_PROFILE(SMBreadBmpx);
8990 /****************************************************************************
8991 Reply to a SMBreadbs (read block multiplex secondary) request.
8992 Always reply with an error, if someone has a platform really needs this,
8993 please contact vl@samba.org
8994 ****************************************************************************/
8996 void reply_readbs(struct smb_request *req)
8998 START_PROFILE(SMBreadBs);
8999 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9000 END_PROFILE(SMBreadBs);
9004 /****************************************************************************
9005 Reply to a SMBsetattrE.
9006 ****************************************************************************/
9008 void reply_setattrE(struct smb_request *req)
9010 connection_struct *conn = req->conn;
9011 struct smb_file_time ft;
9015 START_PROFILE(SMBsetattrE);
9016 init_smb_file_time(&ft);
9019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9023 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9025 if(!fsp || (fsp->conn != conn)) {
9026 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9031 * Convert the DOS times into unix times.
9034 ft.atime = time_t_to_full_timespec(
9035 srv_make_unix_date2(req->vwv+3));
9036 ft.mtime = time_t_to_full_timespec(
9037 srv_make_unix_date2(req->vwv+5));
9038 ft.create_time = time_t_to_full_timespec(
9039 srv_make_unix_date2(req->vwv+1));
9041 reply_outbuf(req, 0, 0);
9044 * Patch from Ray Frush <frush@engr.colostate.edu>
9045 * Sometimes times are sent as zero - ignore them.
9048 /* Ensure we have a valid stat struct for the source. */
9049 status = vfs_stat_fsp(fsp);
9050 if (!NT_STATUS_IS_OK(status)) {
9051 reply_nterror(req, status);
9055 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9056 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9060 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9061 if (!NT_STATUS_IS_OK(status)) {
9062 reply_nterror(req, status);
9066 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9069 (unsigned int)ft.atime.tv_sec,
9070 (unsigned int)ft.mtime.tv_sec,
9071 (unsigned int)ft.create_time.tv_sec
9074 END_PROFILE(SMBsetattrE);
9079 /* Back from the dead for OS/2..... JRA. */
9081 /****************************************************************************
9082 Reply to a SMBwritebmpx (write block multiplex primary) request.
9083 Always reply with an error, if someone has a platform really needs this,
9084 please contact vl@samba.org
9085 ****************************************************************************/
9087 void reply_writebmpx(struct smb_request *req)
9089 START_PROFILE(SMBwriteBmpx);
9090 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9091 END_PROFILE(SMBwriteBmpx);
9095 /****************************************************************************
9096 Reply to a SMBwritebs (write block multiplex secondary) request.
9097 Always reply with an error, if someone has a platform really needs this,
9098 please contact vl@samba.org
9099 ****************************************************************************/
9101 void reply_writebs(struct smb_request *req)
9103 START_PROFILE(SMBwriteBs);
9104 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9105 END_PROFILE(SMBwriteBs);
9109 /****************************************************************************
9110 Reply to a SMBgetattrE.
9111 ****************************************************************************/
9113 void reply_getattrE(struct smb_request *req)
9115 connection_struct *conn = req->conn;
9118 struct timespec create_ts;
9121 START_PROFILE(SMBgetattrE);
9124 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9125 END_PROFILE(SMBgetattrE);
9129 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9131 if(!fsp || (fsp->conn != conn)) {
9132 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9133 END_PROFILE(SMBgetattrE);
9137 /* Do an fstat on this file */
9138 status = vfs_stat_fsp(fsp);
9139 if (!NT_STATUS_IS_OK(status)) {
9140 reply_nterror(req, status);
9141 END_PROFILE(SMBgetattrE);
9145 mode = dos_mode(conn, fsp->fsp_name);
9148 * Convert the times into dos times. Set create
9149 * date to be last modify date as UNIX doesn't save
9153 reply_outbuf(req, 11, 0);
9155 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9156 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9157 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9158 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9159 /* Should we check pending modtime here ? JRA */
9160 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9161 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9163 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9164 SIVAL(req->outbuf, smb_vwv6, 0);
9165 SIVAL(req->outbuf, smb_vwv8, 0);
9167 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9168 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9169 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9171 SSVAL(req->outbuf,smb_vwv10, mode);
9173 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9175 END_PROFILE(SMBgetattrE);