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 "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "librpc/gen_ndr/open_files.h"
48 #include "smb1_utils.h"
49 #include "libcli/smb/smb2_posix.h"
51 /****************************************************************************
52 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
53 path or anything including wildcards.
54 We're assuming here that '/' is not the second byte in any multibyte char
55 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
57 ****************************************************************************/
59 /* Custom version for processing POSIX paths. */
60 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
62 static NTSTATUS check_path_syntax_internal(char *path,
64 bool *p_last_component_contains_wcard)
68 NTSTATUS ret = NT_STATUS_OK;
69 bool start_of_name_component = True;
70 bool stream_started = false;
72 *p_last_component_contains_wcard = False;
79 return NT_STATUS_OBJECT_NAME_INVALID;
82 return NT_STATUS_OBJECT_NAME_INVALID;
84 if (strchr_m(&s[1], ':')) {
85 return NT_STATUS_OBJECT_NAME_INVALID;
91 if ((*s == ':') && !posix_path && !stream_started) {
92 if (*p_last_component_contains_wcard) {
93 return NT_STATUS_OBJECT_NAME_INVALID;
95 /* Stream names allow more characters than file names.
96 We're overloading posix_path here to allow a wider
97 range of characters. If stream_started is true this
98 is still a Windows path even if posix_path is true.
101 stream_started = true;
102 start_of_name_component = false;
106 return NT_STATUS_OBJECT_NAME_INVALID;
110 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
112 * Safe to assume is not the second part of a mb char
113 * as this is handled below.
115 /* Eat multiple '/' or '\\' */
116 while (IS_PATH_SEP(*s,posix_path)) {
119 if ((d != path) && (*s != '\0')) {
120 /* We only care about non-leading or trailing '/' or '\\' */
124 start_of_name_component = True;
126 *p_last_component_contains_wcard = False;
130 if (start_of_name_component) {
131 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
132 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
135 * No mb char starts with '.' so we're safe checking the directory separator here.
138 /* If we just added a '/' - delete it */
139 if ((d > path) && (*(d-1) == '/')) {
144 /* Are we at the start ? Can't go back further if so. */
146 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
149 /* Go back one level... */
150 /* We know this is safe as '/' cannot be part of a mb sequence. */
151 /* NOTE - if this assumption is invalid we are not in good shape... */
152 /* Decrement d first as d points to the *next* char to write into. */
153 for (d--; d > path; d--) {
157 s += 2; /* Else go past the .. */
158 /* We're still at the start of a name component, just the previous one. */
161 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
173 if (*s <= 0x1f || *s == '|') {
174 return NT_STATUS_OBJECT_NAME_INVALID;
182 *p_last_component_contains_wcard = True;
191 /* Get the size of the next MB character. */
192 next_codepoint(s,&siz);
210 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
212 return NT_STATUS_INVALID_PARAMETER;
215 start_of_name_component = False;
223 /****************************************************************************
224 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
225 No wildcards allowed.
226 ****************************************************************************/
228 NTSTATUS check_path_syntax(char *path)
231 return check_path_syntax_internal(path, False, &ignore);
234 /****************************************************************************
235 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
236 Wildcards allowed - p_contains_wcard returns true if the last component contained
238 ****************************************************************************/
240 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
242 return check_path_syntax_internal(path, False, p_contains_wcard);
245 /****************************************************************************
246 Check the path for a POSIX client.
247 We're assuming here that '/' is not the second byte in any multibyte char
248 set (a safe assumption).
249 ****************************************************************************/
251 NTSTATUS check_path_syntax_posix(char *path)
254 return check_path_syntax_internal(path, True, &ignore);
257 /****************************************************************************
258 Pull a string and check the path allowing a wildcard - provide for error return.
259 Passes in posix flag.
260 ****************************************************************************/
262 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
263 const char *base_ptr,
269 bool posix_pathnames,
271 bool *contains_wcard)
277 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
281 *err = NT_STATUS_INVALID_PARAMETER;
285 *contains_wcard = False;
287 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
289 * For a DFS path the function parse_dfs_path()
290 * will do the path processing, just make a copy.
296 if (posix_pathnames) {
297 *err = check_path_syntax_posix(*pp_dest);
299 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
305 /****************************************************************************
306 Pull a string and check the path allowing a wildcard - provide for error return.
307 ****************************************************************************/
309 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
310 const char *base_ptr,
317 bool *contains_wcard)
319 return srvstr_get_path_wcard_internal(ctx,
331 /****************************************************************************
332 Pull a string and check the path allowing a wildcard - provide for error return.
333 posix_pathnames version.
334 ****************************************************************************/
336 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
337 const char *base_ptr,
344 bool *contains_wcard)
346 return srvstr_get_path_wcard_internal(ctx,
358 /****************************************************************************
359 Pull a string and check the path - provide for error return.
360 ****************************************************************************/
362 size_t srvstr_get_path(TALLOC_CTX *ctx,
363 const char *base_ptr,
372 return srvstr_get_path_wcard_internal(ctx,
384 /****************************************************************************
385 Pull a string and check the path - provide for error return.
386 posix_pathnames version.
387 ****************************************************************************/
389 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
390 const char *base_ptr,
399 return srvstr_get_path_wcard_internal(ctx,
412 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
413 char **pp_dest, const char *src, int flags,
414 NTSTATUS *err, bool *contains_wcard)
416 ssize_t bufrem = smbreq_bufrem(req, src);
419 *err = NT_STATUS_INVALID_PARAMETER;
423 if (req->posix_pathnames) {
424 return srvstr_get_path_wcard_internal(mem_ctx,
425 (const char *)req->inbuf,
435 return srvstr_get_path_wcard_internal(mem_ctx,
436 (const char *)req->inbuf,
448 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
449 char **pp_dest, const char *src, int flags,
453 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
454 flags, err, &ignore);
458 * pull a string from the smb_buf part of a packet. In this case the
459 * string can either be null terminated or it can be terminated by the
460 * end of the smbbuf area
462 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
463 char **dest, const uint8_t *src, int flags)
465 ssize_t bufrem = smbreq_bufrem(req, src);
471 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
475 /****************************************************************************
476 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
477 ****************************************************************************/
479 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
482 if ((fsp == NULL) || (conn == NULL)) {
483 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
486 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
487 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
493 /****************************************************************************
494 Check if we have a correct fsp pointing to a file.
495 ****************************************************************************/
497 bool check_fsp(connection_struct *conn, struct smb_request *req,
500 if (!check_fsp_open(conn, req, fsp)) {
503 if (fsp->is_directory) {
504 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
507 if (fsp->fh->fd == -1) {
508 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
511 fsp->num_smb_operations++;
515 /****************************************************************************
516 Check if we have a correct fsp pointing to a quota fake file. Replacement for
517 the CHECK_NTQUOTA_HANDLE_OK macro.
518 ****************************************************************************/
520 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
523 if (!check_fsp_open(conn, req, fsp)) {
527 if (fsp->is_directory) {
531 if (fsp->fake_file_handle == NULL) {
535 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
539 if (fsp->fake_file_handle->private_data == NULL) {
546 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
547 const char *name, int name_type)
550 char *trim_name_type;
551 const char *retarget_parm;
554 int retarget_type = 0x20;
555 int retarget_port = NBT_SMB_PORT;
556 struct sockaddr_storage retarget_addr;
557 struct sockaddr_in *in_addr;
561 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
565 trim_name = talloc_strdup(talloc_tos(), name);
566 if (trim_name == NULL) {
569 trim_char(trim_name, ' ', ' ');
571 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
573 if (trim_name_type == NULL) {
577 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
578 trim_name_type, NULL);
579 if (retarget_parm == NULL) {
580 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
583 if (retarget_parm == NULL) {
587 retarget = talloc_strdup(trim_name, retarget_parm);
588 if (retarget == NULL) {
592 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
594 p = strchr(retarget, ':');
597 retarget_port = atoi(p);
600 p = strchr_m(retarget, '#');
603 if (sscanf(p, "%x", &retarget_type) != 1) {
608 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
610 DEBUG(10, ("could not resolve %s\n", retarget));
614 if (retarget_addr.ss_family != AF_INET) {
615 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
619 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
621 _smb_setlen(outbuf, 6);
622 SCVAL(outbuf, 0, 0x84);
623 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
624 *(uint16_t *)(outbuf+8) = htons(retarget_port);
626 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
628 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
634 TALLOC_FREE(trim_name);
638 static void reply_called_name_not_present(char *outbuf)
640 smb_setlen(outbuf, 1);
641 SCVAL(outbuf, 0, 0x83);
642 SCVAL(outbuf, 4, 0x82);
645 /****************************************************************************
646 Reply to a (netbios-level) special message.
647 ****************************************************************************/
649 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
651 struct smbd_server_connection *sconn = xconn->client->sconn;
652 int msg_type = CVAL(inbuf,0);
653 int msg_flags = CVAL(inbuf,1);
655 * We only really use 4 bytes of the outbuf, but for the smb_setlen
656 * calculation & friends (srv_send_smb uses that) we need the full smb
659 char outbuf[smb_size];
661 memset(outbuf, '\0', sizeof(outbuf));
663 smb_setlen(outbuf,0);
666 case NBSSrequest: /* session request */
668 /* inbuf_size is guarenteed to be at least 4. */
670 int name_type1, name_type2;
671 int name_len1, name_len2;
675 if (xconn->transport.nbt.got_session) {
676 exit_server_cleanly("multiple session request not permitted");
679 SCVAL(outbuf,0,NBSSpositive);
682 /* inbuf_size is guaranteed to be at least 4. */
683 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
684 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
685 DEBUG(0,("Invalid name length in session request\n"));
686 reply_called_name_not_present(outbuf);
689 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
690 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
691 DEBUG(0,("Invalid name length in session request\n"));
692 reply_called_name_not_present(outbuf);
696 name_type1 = name_extract((unsigned char *)inbuf,
697 inbuf_size,(unsigned int)4,name1);
698 name_type2 = name_extract((unsigned char *)inbuf,
699 inbuf_size,(unsigned int)(4 + name_len1),name2);
701 if (name_type1 == -1 || name_type2 == -1) {
702 DEBUG(0,("Invalid name type in session request\n"));
703 reply_called_name_not_present(outbuf);
707 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
708 name1, name_type1, name2, name_type2));
710 if (netbios_session_retarget(xconn, name1, name_type1)) {
711 exit_server_cleanly("retargeted client");
715 * Windows NT/2k uses "*SMBSERVER" and XP uses
716 * "*SMBSERV" arrggg!!!
718 if (strequal(name1, "*SMBSERVER ")
719 || strequal(name1, "*SMBSERV ")) {
722 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
725 exit_server_cleanly("could not allocate raddr");
728 fstrcpy(name1, raddr);
731 set_local_machine_name(name1, True);
732 set_remote_machine_name(name2, True);
734 if (is_ipaddress(sconn->remote_hostname)) {
735 char *p = discard_const_p(char, sconn->remote_hostname);
739 sconn->remote_hostname = talloc_strdup(sconn,
740 get_remote_machine_name());
741 if (sconn->remote_hostname == NULL) {
742 exit_server_cleanly("could not copy remote name");
744 xconn->remote_hostname = sconn->remote_hostname;
747 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
748 get_local_machine_name(), get_remote_machine_name(),
751 if (name_type2 == 'R') {
752 /* We are being asked for a pathworks session ---
754 reply_called_name_not_present(outbuf);
758 reload_services(sconn, conn_snum_used, true);
761 xconn->transport.nbt.got_session = true;
765 case 0x89: /* session keepalive request
766 (some old clients produce this?) */
767 SCVAL(outbuf,0,NBSSkeepalive);
771 case NBSSpositive: /* positive session response */
772 case NBSSnegative: /* negative session response */
773 case NBSSretarget: /* retarget session response */
774 DEBUG(0,("Unexpected session response\n"));
777 case NBSSkeepalive: /* session keepalive */
782 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
783 msg_type, msg_flags));
785 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
786 exit_server_cleanly("reply_special: srv_send_smb failed.");
789 if (CVAL(outbuf, 0) != 0x82) {
790 exit_server_cleanly("invalid netbios session");
795 /****************************************************************************
797 conn POINTER CAN BE NULL HERE !
798 ****************************************************************************/
800 void reply_tcon(struct smb_request *req)
802 connection_struct *conn = req->conn;
804 char *service_buf = NULL;
805 char *password = NULL;
811 TALLOC_CTX *ctx = talloc_tos();
812 struct smbXsrv_connection *xconn = req->xconn;
813 NTTIME now = timeval_to_nttime(&req->request_time);
815 START_PROFILE(SMBtcon);
817 if (req->buflen < 4) {
818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
819 END_PROFILE(SMBtcon);
824 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
826 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
828 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
831 if (service_buf == NULL || password == NULL || dev == NULL) {
832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
833 END_PROFILE(SMBtcon);
836 p2 = strrchr_m(service_buf,'\\');
840 service = service_buf;
843 conn = make_connection(req, now, service, dev,
844 req->vuid,&nt_status);
848 reply_nterror(req, nt_status);
849 END_PROFILE(SMBtcon);
853 reply_outbuf(req, 2, 0);
854 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
855 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
856 SSVAL(req->outbuf,smb_tid,conn->cnum);
858 DEBUG(3,("tcon service=%s cnum=%d\n",
859 service, conn->cnum));
861 END_PROFILE(SMBtcon);
865 /****************************************************************************
866 Reply to a tcon and X.
867 conn POINTER CAN BE NULL HERE !
868 ****************************************************************************/
870 void reply_tcon_and_X(struct smb_request *req)
872 const struct loadparm_substitution *lp_sub =
873 loadparm_s3_global_substitution();
874 connection_struct *conn = req->conn;
875 const char *service = NULL;
876 TALLOC_CTX *ctx = talloc_tos();
877 /* what the client thinks the device is */
878 char *client_devicetype = NULL;
879 /* what the server tells the client the share represents */
880 const char *server_devicetype;
887 struct smbXsrv_session *session = NULL;
888 NTTIME now = timeval_to_nttime(&req->request_time);
889 bool session_key_updated = false;
890 uint16_t optional_support = 0;
891 struct smbXsrv_connection *xconn = req->xconn;
893 START_PROFILE(SMBtconX);
896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
897 END_PROFILE(SMBtconX);
901 passlen = SVAL(req->vwv+3, 0);
902 tcon_flags = SVAL(req->vwv+2, 0);
904 /* we might have to close an old one */
905 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
906 struct smbXsrv_tcon *tcon;
914 * TODO: cancel all outstanding requests on the tcon
916 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
917 if (!NT_STATUS_IS_OK(status)) {
918 DEBUG(0, ("reply_tcon_and_X: "
919 "smbXsrv_tcon_disconnect() failed: %s\n",
922 * If we hit this case, there is something completely
923 * wrong, so we better disconnect the transport connection.
925 END_PROFILE(SMBtconX);
926 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
932 * This tree id is gone. Make sure we can't re-use it
938 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
939 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
940 END_PROFILE(SMBtconX);
944 if (xconn->smb1.negprot.encrypted_passwords) {
945 p = req->buf + passlen;
947 p = req->buf + passlen + 1;
950 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
954 END_PROFILE(SMBtconX);
959 * the service name can be either: \\server\share
960 * or share directly like on the DELL PowerVault 705
963 q = strchr_m(path+2,'\\');
965 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
966 END_PROFILE(SMBtconX);
974 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
975 &client_devicetype, p,
976 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
978 if (client_devicetype == NULL) {
979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
980 END_PROFILE(SMBtconX);
984 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
986 nt_status = smb1srv_session_lookup(xconn,
987 req->vuid, now, &session);
988 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
989 reply_force_doserror(req, ERRSRV, ERRbaduid);
990 END_PROFILE(SMBtconX);
993 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
994 reply_nterror(req, nt_status);
995 END_PROFILE(SMBtconX);
998 if (!NT_STATUS_IS_OK(nt_status)) {
999 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1000 END_PROFILE(SMBtconX);
1004 if (session->global->auth_session_info == NULL) {
1005 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1006 END_PROFILE(SMBtconX);
1011 * If there is no application key defined yet
1014 * This means we setup the application key on the
1015 * first tcon that happens via the given session.
1017 * Once the application key is defined, it does not
1020 if (session->global->application_key.length == 0 &&
1021 smb2_signing_key_valid(session->global->signing_key))
1023 struct smbXsrv_session *x = session;
1024 struct auth_session_info *session_info =
1025 session->global->auth_session_info;
1026 uint8_t session_key[16];
1028 ZERO_STRUCT(session_key);
1029 memcpy(session_key, x->global->signing_key->blob.data,
1030 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
1033 * The application key is truncated/padded to 16 bytes
1035 x->global->application_key = data_blob_talloc(x->global,
1037 sizeof(session_key));
1038 ZERO_STRUCT(session_key);
1039 if (x->global->application_key.data == NULL) {
1040 reply_nterror(req, NT_STATUS_NO_MEMORY);
1041 END_PROFILE(SMBtconX);
1045 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1048 status = smb_key_derivation(x->global->application_key.data,
1049 x->global->application_key.length,
1050 x->global->application_key.data);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 DBG_ERR("smb_key_derivation failed: %s\n",
1054 END_PROFILE(SMBtconX);
1057 optional_support |= SMB_EXTENDED_SIGNATURES;
1061 * Place the application key into the session_info
1063 data_blob_clear_free(&session_info->session_key);
1064 session_info->session_key = data_blob_dup_talloc(session_info,
1065 x->global->application_key);
1066 if (session_info->session_key.data == NULL) {
1067 data_blob_clear_free(&x->global->application_key);
1068 reply_nterror(req, NT_STATUS_NO_MEMORY);
1069 END_PROFILE(SMBtconX);
1072 session_key_updated = true;
1075 conn = make_connection(req, now, service, client_devicetype,
1076 req->vuid, &nt_status);
1080 if (session_key_updated) {
1081 struct smbXsrv_session *x = session;
1082 struct auth_session_info *session_info =
1083 session->global->auth_session_info;
1084 data_blob_clear_free(&x->global->application_key);
1085 data_blob_clear_free(&session_info->session_key);
1087 reply_nterror(req, nt_status);
1088 END_PROFILE(SMBtconX);
1093 server_devicetype = "IPC";
1094 else if ( IS_PRINT(conn) )
1095 server_devicetype = "LPT1:";
1097 server_devicetype = "A:";
1099 if (get_Protocol() < PROTOCOL_NT1) {
1100 reply_outbuf(req, 2, 0);
1101 if (message_push_string(&req->outbuf, server_devicetype,
1102 STR_TERMINATE|STR_ASCII) == -1) {
1103 reply_nterror(req, NT_STATUS_NO_MEMORY);
1104 END_PROFILE(SMBtconX);
1108 /* NT sets the fstype of IPC$ to the null string */
1109 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1111 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1112 /* Return permissions. */
1116 reply_outbuf(req, 7, 0);
1119 perm1 = FILE_ALL_ACCESS;
1120 perm2 = FILE_ALL_ACCESS;
1122 perm1 = conn->share_access;
1125 SIVAL(req->outbuf, smb_vwv3, perm1);
1126 SIVAL(req->outbuf, smb_vwv5, perm2);
1128 reply_outbuf(req, 3, 0);
1131 if ((message_push_string(&req->outbuf, server_devicetype,
1132 STR_TERMINATE|STR_ASCII) == -1)
1133 || (message_push_string(&req->outbuf, fstype,
1134 STR_TERMINATE) == -1)) {
1135 reply_nterror(req, NT_STATUS_NO_MEMORY);
1136 END_PROFILE(SMBtconX);
1140 /* what does setting this bit do? It is set by NT4 and
1141 may affect the ability to autorun mounted cdroms */
1142 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1144 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1146 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1147 DEBUG(2,("Serving %s as a Dfs root\n",
1148 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1149 optional_support |= SMB_SHARE_IN_DFS;
1152 SSVAL(req->outbuf, smb_vwv2, optional_support);
1155 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1156 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1158 DEBUG(3,("tconX service=%s \n",
1161 /* set the incoming and outgoing tid to the just created one */
1162 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1163 SSVAL(req->outbuf,smb_tid,conn->cnum);
1165 END_PROFILE(SMBtconX);
1167 req->tid = conn->cnum;
1170 /****************************************************************************
1171 Reply to an unknown type.
1172 ****************************************************************************/
1174 void reply_unknown_new(struct smb_request *req, uint8_t type)
1176 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1177 smb_fn_name(type), type, type));
1178 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1182 /****************************************************************************
1184 conn POINTER CAN BE NULL HERE !
1185 ****************************************************************************/
1187 void reply_ioctl(struct smb_request *req)
1189 const struct loadparm_substitution *lp_sub =
1190 loadparm_s3_global_substitution();
1191 connection_struct *conn = req->conn;
1194 uint32_t ioctl_code;
1198 START_PROFILE(SMBioctl);
1201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1202 END_PROFILE(SMBioctl);
1206 device = SVAL(req->vwv+1, 0);
1207 function = SVAL(req->vwv+2, 0);
1208 ioctl_code = (device << 16) + function;
1210 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1212 switch (ioctl_code) {
1213 case IOCTL_QUERY_JOB_INFO:
1217 reply_force_doserror(req, ERRSRV, ERRnosupport);
1218 END_PROFILE(SMBioctl);
1222 reply_outbuf(req, 8, replysize+1);
1223 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1224 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1225 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1226 p = smb_buf(req->outbuf);
1227 memset(p, '\0', replysize+1); /* valgrind-safe. */
1228 p += 1; /* Allow for alignment */
1230 switch (ioctl_code) {
1231 case IOCTL_QUERY_JOB_INFO:
1235 files_struct *fsp = file_fsp(
1236 req, SVAL(req->vwv+0, 0));
1238 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1239 END_PROFILE(SMBioctl);
1243 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1245 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1246 lp_netbios_name(), 15,
1247 STR_TERMINATE|STR_ASCII, &len);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 reply_nterror(req, status);
1250 END_PROFILE(SMBioctl);
1254 status = srvstr_push((char *)req->outbuf, req->flags2,
1256 lp_servicename(talloc_tos(),
1259 13, STR_TERMINATE|STR_ASCII, &len);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 reply_nterror(req, status);
1262 END_PROFILE(SMBioctl);
1266 memset(p+18, 0, 13);
1272 END_PROFILE(SMBioctl);
1276 /****************************************************************************
1277 Strange checkpath NTSTATUS mapping.
1278 ****************************************************************************/
1280 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1282 /* Strange DOS error code semantics only for checkpath... */
1283 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1284 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1285 /* We need to map to ERRbadpath */
1286 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1292 /****************************************************************************
1293 Reply to a checkpath.
1294 ****************************************************************************/
1296 void reply_checkpath(struct smb_request *req)
1298 connection_struct *conn = req->conn;
1299 struct smb_filename *smb_fname = NULL;
1302 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1303 TALLOC_CTX *ctx = talloc_tos();
1305 START_PROFILE(SMBcheckpath);
1307 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1308 STR_TERMINATE, &status);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 status = map_checkpath_error(req->flags2, status);
1312 reply_nterror(req, status);
1313 END_PROFILE(SMBcheckpath);
1317 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1319 status = filename_convert(ctx,
1327 if (!NT_STATUS_IS_OK(status)) {
1328 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1329 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1330 ERRSRV, ERRbadpath);
1331 END_PROFILE(SMBcheckpath);
1337 if (!VALID_STAT(smb_fname->st) &&
1338 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1339 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1340 smb_fname_str_dbg(smb_fname), strerror(errno)));
1341 status = map_nt_error_from_unix(errno);
1345 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1346 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1347 ERRDOS, ERRbadpath);
1351 reply_outbuf(req, 0, 0);
1354 /* We special case this - as when a Windows machine
1355 is parsing a path is steps through the components
1356 one at a time - if a component fails it expects
1357 ERRbadpath, not ERRbadfile.
1359 status = map_checkpath_error(req->flags2, status);
1360 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1362 * Windows returns different error codes if
1363 * the parent directory is valid but not the
1364 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1365 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1366 * if the path is invalid.
1368 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1369 ERRDOS, ERRbadpath);
1373 reply_nterror(req, status);
1376 TALLOC_FREE(smb_fname);
1377 END_PROFILE(SMBcheckpath);
1381 /****************************************************************************
1383 ****************************************************************************/
1385 void reply_getatr(struct smb_request *req)
1387 connection_struct *conn = req->conn;
1388 struct smb_filename *smb_fname = NULL;
1395 TALLOC_CTX *ctx = talloc_tos();
1396 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1398 START_PROFILE(SMBgetatr);
1400 p = (const char *)req->buf + 1;
1401 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1402 if (!NT_STATUS_IS_OK(status)) {
1403 reply_nterror(req, status);
1407 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1408 under WfWg - weird! */
1409 if (*fname == '\0') {
1410 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1411 if (!CAN_WRITE(conn)) {
1412 mode |= FILE_ATTRIBUTE_READONLY;
1417 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1418 status = filename_convert(ctx,
1425 if (!NT_STATUS_IS_OK(status)) {
1426 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1427 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1428 ERRSRV, ERRbadpath);
1431 reply_nterror(req, status);
1434 if (!VALID_STAT(smb_fname->st) &&
1435 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1436 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1437 smb_fname_str_dbg(smb_fname),
1439 reply_nterror(req, map_nt_error_from_unix(errno));
1443 mode = dos_mode(conn, smb_fname);
1444 size = smb_fname->st.st_ex_size;
1446 if (ask_sharemode) {
1447 struct timespec write_time_ts;
1448 struct file_id fileid;
1450 ZERO_STRUCT(write_time_ts);
1451 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1452 get_file_infos(fileid, 0, NULL, &write_time_ts);
1453 if (!is_omit_timespec(&write_time_ts)) {
1454 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1458 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1459 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1464 reply_outbuf(req, 10, 0);
1466 SSVAL(req->outbuf,smb_vwv0,mode);
1467 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1468 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1470 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1472 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1474 if (get_Protocol() >= PROTOCOL_NT1) {
1475 SSVAL(req->outbuf, smb_flg2,
1476 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1479 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1480 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1483 TALLOC_FREE(smb_fname);
1485 END_PROFILE(SMBgetatr);
1489 /****************************************************************************
1491 ****************************************************************************/
1493 void reply_setatr(struct smb_request *req)
1495 struct smb_file_time ft;
1496 connection_struct *conn = req->conn;
1497 struct smb_filename *smb_fname = NULL;
1503 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1504 TALLOC_CTX *ctx = talloc_tos();
1506 START_PROFILE(SMBsetatr);
1507 init_smb_file_time(&ft);
1510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1514 p = (const char *)req->buf + 1;
1515 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 reply_nterror(req, status);
1521 status = filename_convert(ctx,
1528 if (!NT_STATUS_IS_OK(status)) {
1529 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1530 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1531 ERRSRV, ERRbadpath);
1534 reply_nterror(req, status);
1538 if (ISDOT(smb_fname->base_name)) {
1540 * Not sure here is the right place to catch this
1541 * condition. Might be moved to somewhere else later -- vl
1543 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1547 mode = SVAL(req->vwv+0, 0);
1548 mtime = srv_make_unix_date3(req->vwv+1);
1550 if (mode != FILE_ATTRIBUTE_NORMAL) {
1551 if (VALID_STAT_OF_DIR(smb_fname->st))
1552 mode |= FILE_ATTRIBUTE_DIRECTORY;
1554 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1556 status = smbd_check_access_rights(
1557 conn, smb_fname, false, FILE_WRITE_ATTRIBUTES);
1558 if (!NT_STATUS_IS_OK(status)) {
1559 reply_nterror(req, status);
1563 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1565 reply_nterror(req, map_nt_error_from_unix(errno));
1570 ft.mtime = time_t_to_full_timespec(mtime);
1572 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1573 if (!NT_STATUS_IS_OK(status)) {
1574 reply_nterror(req, status);
1578 reply_outbuf(req, 0, 0);
1580 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1583 TALLOC_FREE(smb_fname);
1584 END_PROFILE(SMBsetatr);
1588 /****************************************************************************
1590 ****************************************************************************/
1592 void reply_dskattr(struct smb_request *req)
1594 connection_struct *conn = req->conn;
1596 uint64_t dfree,dsize,bsize;
1597 struct smb_filename smb_fname;
1598 START_PROFILE(SMBdskattr);
1600 ZERO_STRUCT(smb_fname);
1601 smb_fname.base_name = discard_const_p(char, ".");
1603 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1604 reply_nterror(req, map_nt_error_from_unix(errno));
1605 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1606 END_PROFILE(SMBdskattr);
1610 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1611 if (ret == (uint64_t)-1) {
1612 reply_nterror(req, map_nt_error_from_unix(errno));
1613 END_PROFILE(SMBdskattr);
1618 * Force max to fit in 16 bit fields.
1620 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1624 if (bsize > (WORDMAX*512)) {
1625 bsize = (WORDMAX*512);
1626 if (dsize > WORDMAX)
1628 if (dfree > WORDMAX)
1634 reply_outbuf(req, 5, 0);
1636 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1637 double total_space, free_space;
1638 /* we need to scale this to a number that DOS6 can handle. We
1639 use floating point so we can handle large drives on systems
1640 that don't have 64 bit integers
1642 we end up displaying a maximum of 2G to DOS systems
1644 total_space = dsize * (double)bsize;
1645 free_space = dfree * (double)bsize;
1647 dsize = (uint64_t)((total_space+63*512) / (64*512));
1648 dfree = (uint64_t)((free_space+63*512) / (64*512));
1650 if (dsize > 0xFFFF) dsize = 0xFFFF;
1651 if (dfree > 0xFFFF) dfree = 0xFFFF;
1653 SSVAL(req->outbuf,smb_vwv0,dsize);
1654 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1655 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1656 SSVAL(req->outbuf,smb_vwv3,dfree);
1658 SSVAL(req->outbuf,smb_vwv0,dsize);
1659 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1660 SSVAL(req->outbuf,smb_vwv2,512);
1661 SSVAL(req->outbuf,smb_vwv3,dfree);
1664 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1666 END_PROFILE(SMBdskattr);
1671 * Utility function to split the filename from the directory.
1673 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1674 char **fname_dir_out,
1675 char **fname_mask_out)
1677 const char *p = NULL;
1678 char *fname_dir = NULL;
1679 char *fname_mask = NULL;
1681 p = strrchr_m(fname_in, '/');
1683 fname_dir = talloc_strdup(ctx, ".");
1684 fname_mask = talloc_strdup(ctx, fname_in);
1686 fname_dir = talloc_strndup(ctx, fname_in,
1687 PTR_DIFF(p, fname_in));
1688 fname_mask = talloc_strdup(ctx, p+1);
1691 if (!fname_dir || !fname_mask) {
1692 TALLOC_FREE(fname_dir);
1693 TALLOC_FREE(fname_mask);
1694 return NT_STATUS_NO_MEMORY;
1697 *fname_dir_out = fname_dir;
1698 *fname_mask_out = fname_mask;
1699 return NT_STATUS_OK;
1702 /****************************************************************************
1704 ****************************************************************************/
1706 static bool make_dir_struct(TALLOC_CTX *ctx,
1716 char *mask2 = talloc_strdup(ctx, mask);
1722 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1726 memset(buf+1,' ',11);
1727 if ((p = strchr_m(mask2,'.')) != NULL) {
1729 push_ascii(buf+1,mask2,8, 0);
1730 push_ascii(buf+9,p+1,3, 0);
1733 push_ascii(buf+1,mask2,11, 0);
1736 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1738 srv_put_dos_date(buf,22,date);
1739 SSVAL(buf,26,size & 0xFFFF);
1740 SSVAL(buf,28,(size >> 16)&0xFFFF);
1741 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1742 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1743 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1744 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1748 /****************************************************************************
1750 Can be called from SMBsearch, SMBffirst or SMBfunique.
1751 ****************************************************************************/
1753 void reply_search(struct smb_request *req)
1755 connection_struct *conn = req->conn;
1758 char *directory = NULL;
1759 struct smb_filename *smb_fname = NULL;
1763 struct timespec date;
1765 unsigned int numentries = 0;
1766 unsigned int maxentries = 0;
1767 bool finished = False;
1772 bool check_descend = False;
1773 bool expect_close = False;
1775 bool mask_contains_wcard = False;
1776 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1777 TALLOC_CTX *ctx = talloc_tos();
1778 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1779 struct smbXsrv_connection *xconn = req->xconn;
1780 struct smbd_server_connection *sconn = req->sconn;
1781 files_struct *fsp = NULL;
1782 const struct loadparm_substitution *lp_sub =
1783 loadparm_s3_global_substitution();
1785 START_PROFILE(SMBsearch);
1788 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1792 if (req->posix_pathnames) {
1793 reply_unknown_new(req, req->cmd);
1797 /* If we were called as SMBffirst then we must expect close. */
1798 if(req->cmd == SMBffirst) {
1799 expect_close = True;
1802 reply_outbuf(req, 1, 3);
1803 maxentries = SVAL(req->vwv+0, 0);
1804 dirtype = SVAL(req->vwv+1, 0);
1805 p = (const char *)req->buf + 1;
1806 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1807 &nt_status, &mask_contains_wcard);
1808 if (!NT_STATUS_IS_OK(nt_status)) {
1809 reply_nterror(req, nt_status);
1813 if (smbreq_bufrem(req, p) < 3) {
1814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1819 status_len = SVAL(p, 0);
1822 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1824 if (status_len == 0) {
1826 struct smb_filename *smb_dname = NULL;
1827 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1828 ucf_flags_from_smb_request(req);
1829 nt_status = filename_convert(ctx, conn,
1833 &mask_contains_wcard,
1835 if (!NT_STATUS_IS_OK(nt_status)) {
1836 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1837 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1838 ERRSRV, ERRbadpath);
1841 reply_nterror(req, nt_status);
1845 directory = smb_fname->base_name;
1847 p = strrchr_m(directory,'/');
1848 if ((p != NULL) && (*directory != '/')) {
1849 mask = talloc_strdup(ctx, p + 1);
1850 directory = talloc_strndup(ctx, directory,
1851 PTR_DIFF(p, directory));
1853 mask = talloc_strdup(ctx, directory);
1854 directory = talloc_strdup(ctx,".");
1858 reply_nterror(req, NT_STATUS_NO_MEMORY);
1862 memset((char *)status,'\0',21);
1863 SCVAL(status,0,(dirtype & 0x1F));
1865 smb_dname = synthetic_smb_fname(talloc_tos(),
1870 if (smb_dname == NULL) {
1871 reply_nterror(req, NT_STATUS_NO_MEMORY);
1876 * As we've cut off the last component from
1877 * smb_fname we need to re-stat smb_dname
1878 * so FILE_OPEN disposition knows the directory
1881 if (req->posix_pathnames) {
1882 ret = SMB_VFS_LSTAT(conn, smb_dname);
1884 ret = SMB_VFS_STAT(conn, smb_dname);
1887 nt_status = map_nt_error_from_unix(errno);
1888 reply_nterror(req, nt_status);
1893 * Open an fsp on this directory for the dptr.
1895 nt_status = SMB_VFS_CREATE_FILE(
1898 0, /* root_dir_fid */
1899 smb_dname, /* dname */
1900 FILE_LIST_DIRECTORY, /* access_mask */
1902 FILE_SHARE_WRITE, /* share_access */
1903 FILE_OPEN, /* create_disposition*/
1904 FILE_DIRECTORY_FILE, /* create_options */
1905 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1906 NO_OPLOCK, /* oplock_request */
1908 0, /* allocation_size */
1909 0, /* private_flags */
1914 NULL, /* in_context */
1915 NULL);/* out_context */
1917 if (!NT_STATUS_IS_OK(nt_status)) {
1918 DBG_ERR("failed to open directory %s\n",
1919 smb_fname_str_dbg(smb_dname));
1920 reply_nterror(req, nt_status);
1924 nt_status = dptr_create(conn,
1931 mask_contains_wcard,
1935 TALLOC_FREE(smb_dname);
1937 if (!NT_STATUS_IS_OK(nt_status)) {
1939 * Use NULL here for the first parameter (req)
1940 * as this is not a client visible handle so
1941 * can'tbe part of an SMB1 chain.
1943 close_file(NULL, fsp, NORMAL_CLOSE);
1945 reply_nterror(req, nt_status);
1949 dptr_num = dptr_dnum(fsp->dptr);
1953 const char *dirpath;
1955 if (smbreq_bufrem(req, p) < 21) {
1956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1960 memcpy(status,p,21);
1961 status_dirtype = CVAL(status,0) & 0x1F;
1962 if (status_dirtype != (dirtype & 0x1F)) {
1963 dirtype = status_dirtype;
1966 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1970 dirpath = dptr_path(sconn, dptr_num);
1971 directory = talloc_strdup(ctx, dirpath);
1973 reply_nterror(req, NT_STATUS_NO_MEMORY);
1977 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1982 * For a 'continue' search we have no string. So
1983 * check from the initial saved string.
1985 if (!req->posix_pathnames) {
1986 mask_contains_wcard = ms_has_wild(mask);
1988 dirtype = dptr_attr(sconn, dptr_num);
1991 DEBUG(4,("dptr_num is %d\n",dptr_num));
1993 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1994 char buf[DIR_STRUCT_SIZE];
1995 memcpy(buf,status,21);
1996 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1997 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1998 reply_nterror(req, NT_STATUS_NO_MEMORY);
2001 dptr_fill(sconn, buf+12,dptr_num);
2002 if (dptr_zero(buf+12) && (status_len==0)) {
2007 if (message_push_blob(&req->outbuf,
2008 data_blob_const(buf, sizeof(buf)))
2010 reply_nterror(req, NT_STATUS_NO_MEMORY);
2015 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
2016 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
2018 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
2020 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2021 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
2022 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
2023 check_descend = True;
2026 for (i=numentries;(i<maxentries) && !finished;i++) {
2027 finished = !get_dir_entry(ctx,
2038 char buf[DIR_STRUCT_SIZE];
2039 memcpy(buf,status,21);
2040 if (!make_dir_struct(ctx,
2046 convert_timespec_to_time_t(date),
2047 !allow_long_path_components)) {
2048 reply_nterror(req, NT_STATUS_NO_MEMORY);
2051 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2054 if (message_push_blob(&req->outbuf,
2055 data_blob_const(buf, sizeof(buf)))
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2067 /* If we were called as SMBffirst with smb_search_id == NULL
2068 and no entries were found then return error and close fsp->dptr
2071 if (numentries == 0) {
2074 close_file(NULL, fsp, NORMAL_CLOSE);
2077 } else if(expect_close && status_len == 0) {
2078 /* Close the dptr - we know it's gone */
2081 close_file(NULL, fsp, NORMAL_CLOSE);
2086 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2087 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2089 /* fsp may have been closed above. */
2091 close_file(NULL, fsp, NORMAL_CLOSE);
2096 if ((numentries == 0) && !mask_contains_wcard) {
2097 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2101 SSVAL(req->outbuf,smb_vwv0,numentries);
2102 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2103 SCVAL(smb_buf(req->outbuf),0,5);
2104 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2106 /* The replies here are never long name. */
2107 SSVAL(req->outbuf, smb_flg2,
2108 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2109 if (!allow_long_path_components) {
2110 SSVAL(req->outbuf, smb_flg2,
2111 SVAL(req->outbuf, smb_flg2)
2112 & (~FLAGS2_LONG_PATH_COMPONENTS));
2115 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2116 SSVAL(req->outbuf, smb_flg2,
2117 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2119 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2120 smb_fn_name(req->cmd),
2127 TALLOC_FREE(directory);
2129 TALLOC_FREE(smb_fname);
2130 END_PROFILE(SMBsearch);
2134 /****************************************************************************
2135 Reply to a fclose (stop directory search).
2136 ****************************************************************************/
2138 void reply_fclose(struct smb_request *req)
2146 bool path_contains_wcard = False;
2147 TALLOC_CTX *ctx = talloc_tos();
2148 struct smbd_server_connection *sconn = req->sconn;
2149 files_struct *fsp = NULL;
2151 START_PROFILE(SMBfclose);
2153 if (req->posix_pathnames) {
2154 reply_unknown_new(req, req->cmd);
2155 END_PROFILE(SMBfclose);
2159 p = (const char *)req->buf + 1;
2160 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2161 &err, &path_contains_wcard);
2162 if (!NT_STATUS_IS_OK(err)) {
2163 reply_nterror(req, err);
2164 END_PROFILE(SMBfclose);
2168 if (smbreq_bufrem(req, p) < 3) {
2169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2170 END_PROFILE(SMBfclose);
2175 status_len = SVAL(p,0);
2178 if (status_len == 0) {
2179 reply_force_doserror(req, ERRSRV, ERRsrverror);
2180 END_PROFILE(SMBfclose);
2184 if (smbreq_bufrem(req, p) < 21) {
2185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2186 END_PROFILE(SMBfclose);
2190 memcpy(status,p,21);
2192 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2194 /* Close the file - we know it's gone */
2195 close_file(NULL, fsp, NORMAL_CLOSE);
2200 reply_outbuf(req, 1, 0);
2201 SSVAL(req->outbuf,smb_vwv0,0);
2203 DEBUG(3,("search close\n"));
2205 END_PROFILE(SMBfclose);
2209 /****************************************************************************
2211 ****************************************************************************/
2213 void reply_open(struct smb_request *req)
2215 connection_struct *conn = req->conn;
2216 struct smb_filename *smb_fname = NULL;
2226 uint32_t access_mask;
2227 uint32_t share_mode;
2228 uint32_t create_disposition;
2229 uint32_t create_options = 0;
2230 uint32_t private_flags = 0;
2233 TALLOC_CTX *ctx = talloc_tos();
2235 START_PROFILE(SMBopen);
2238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2242 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2243 deny_mode = SVAL(req->vwv+0, 0);
2244 dos_attr = SVAL(req->vwv+1, 0);
2246 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2247 STR_TERMINATE, &status);
2248 if (!NT_STATUS_IS_OK(status)) {
2249 reply_nterror(req, status);
2253 if (!map_open_params_to_ntcreate(fname, deny_mode,
2254 OPENX_FILE_EXISTS_OPEN, &access_mask,
2255 &share_mode, &create_disposition,
2256 &create_options, &private_flags)) {
2257 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2261 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2263 status = filename_convert(ctx,
2270 if (!NT_STATUS_IS_OK(status)) {
2271 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2272 reply_botherror(req,
2273 NT_STATUS_PATH_NOT_COVERED,
2274 ERRSRV, ERRbadpath);
2277 reply_nterror(req, status);
2281 status = SMB_VFS_CREATE_FILE(
2284 0, /* root_dir_fid */
2285 smb_fname, /* fname */
2286 access_mask, /* access_mask */
2287 share_mode, /* share_access */
2288 create_disposition, /* create_disposition*/
2289 create_options, /* create_options */
2290 dos_attr, /* file_attributes */
2291 oplock_request, /* oplock_request */
2293 0, /* allocation_size */
2299 NULL, NULL); /* create context */
2301 if (!NT_STATUS_IS_OK(status)) {
2302 if (open_was_deferred(req->xconn, req->mid)) {
2303 /* We have re-scheduled this call. */
2307 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2308 reply_openerror(req, status);
2312 fsp = fcb_or_dos_open(
2319 bool ok = defer_smb1_sharing_violation(req);
2323 reply_openerror(req, status);
2328 /* Ensure we're pointing at the correct stat struct. */
2329 TALLOC_FREE(smb_fname);
2330 smb_fname = fsp->fsp_name;
2332 size = smb_fname->st.st_ex_size;
2333 fattr = dos_mode(conn, smb_fname);
2335 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2337 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2338 DEBUG(3,("attempt to open a directory %s\n",
2340 close_file(req, fsp, ERROR_CLOSE);
2341 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2342 ERRDOS, ERRnoaccess);
2346 reply_outbuf(req, 7, 0);
2347 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2348 SSVAL(req->outbuf,smb_vwv1,fattr);
2349 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2350 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2352 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2354 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2355 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2357 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2358 SCVAL(req->outbuf,smb_flg,
2359 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2362 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2363 SCVAL(req->outbuf,smb_flg,
2364 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2367 END_PROFILE(SMBopen);
2371 /****************************************************************************
2372 Reply to an open and X.
2373 ****************************************************************************/
2375 void reply_open_and_X(struct smb_request *req)
2377 connection_struct *conn = req->conn;
2378 struct smb_filename *smb_fname = NULL;
2380 uint16_t open_flags;
2383 /* Breakout the oplock request bits so we can set the
2384 reply bits separately. */
2385 int ex_oplock_request;
2386 int core_oplock_request;
2389 int smb_sattr = SVAL(req->vwv+4, 0);
2390 uint32_t smb_time = make_unix_date3(req->vwv+6);
2398 uint64_t allocation_size;
2399 ssize_t retval = -1;
2400 uint32_t access_mask;
2401 uint32_t share_mode;
2402 uint32_t create_disposition;
2403 uint32_t create_options = 0;
2404 uint32_t private_flags = 0;
2406 TALLOC_CTX *ctx = talloc_tos();
2408 START_PROFILE(SMBopenX);
2410 if (req->wct < 15) {
2411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2415 open_flags = SVAL(req->vwv+2, 0);
2416 deny_mode = SVAL(req->vwv+3, 0);
2417 smb_attr = SVAL(req->vwv+5, 0);
2418 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2419 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2420 oplock_request = ex_oplock_request | core_oplock_request;
2421 smb_ofun = SVAL(req->vwv+8, 0);
2422 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2424 /* If it's an IPC, pass off the pipe handler. */
2426 if (lp_nt_pipe_support()) {
2427 reply_open_pipe_and_X(conn, req);
2429 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2434 /* XXXX we need to handle passed times, sattr and flags */
2435 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2436 STR_TERMINATE, &status);
2437 if (!NT_STATUS_IS_OK(status)) {
2438 reply_nterror(req, status);
2442 if (!map_open_params_to_ntcreate(fname, deny_mode,
2444 &access_mask, &share_mode,
2445 &create_disposition,
2448 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2452 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2454 status = filename_convert(ctx,
2461 if (!NT_STATUS_IS_OK(status)) {
2462 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2463 reply_botherror(req,
2464 NT_STATUS_PATH_NOT_COVERED,
2465 ERRSRV, ERRbadpath);
2468 reply_nterror(req, status);
2472 status = SMB_VFS_CREATE_FILE(
2475 0, /* root_dir_fid */
2476 smb_fname, /* fname */
2477 access_mask, /* access_mask */
2478 share_mode, /* share_access */
2479 create_disposition, /* create_disposition*/
2480 create_options, /* create_options */
2481 smb_attr, /* file_attributes */
2482 oplock_request, /* oplock_request */
2484 0, /* allocation_size */
2489 &smb_action, /* pinfo */
2490 NULL, NULL); /* create context */
2492 if (!NT_STATUS_IS_OK(status)) {
2493 if (open_was_deferred(req->xconn, req->mid)) {
2494 /* We have re-scheduled this call. */
2498 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2499 reply_openerror(req, status);
2503 fsp = fcb_or_dos_open(
2510 bool ok = defer_smb1_sharing_violation(req);
2514 reply_openerror(req, status);
2519 smb_action = FILE_WAS_OPENED;
2522 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2523 if the file is truncated or created. */
2524 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2525 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2526 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2527 close_file(req, fsp, ERROR_CLOSE);
2528 reply_nterror(req, NT_STATUS_DISK_FULL);
2531 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2533 close_file(req, fsp, ERROR_CLOSE);
2534 reply_nterror(req, NT_STATUS_DISK_FULL);
2537 status = vfs_stat_fsp(fsp);
2538 if (!NT_STATUS_IS_OK(status)) {
2539 close_file(req, fsp, ERROR_CLOSE);
2540 reply_nterror(req, status);
2545 fattr = dos_mode(conn, fsp->fsp_name);
2546 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2547 close_file(req, fsp, ERROR_CLOSE);
2548 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2551 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2553 /* If the caller set the extended oplock request bit
2554 and we granted one (by whatever means) - set the
2555 correct bit for extended oplock reply.
2558 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2559 smb_action |= EXTENDED_OPLOCK_GRANTED;
2562 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2563 smb_action |= EXTENDED_OPLOCK_GRANTED;
2566 /* If the caller set the core oplock request bit
2567 and we granted one (by whatever means) - set the
2568 correct bit for core oplock reply.
2571 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2572 reply_outbuf(req, 19, 0);
2574 reply_outbuf(req, 15, 0);
2577 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2578 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2580 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2581 SCVAL(req->outbuf, smb_flg,
2582 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2585 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2586 SCVAL(req->outbuf, smb_flg,
2587 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2590 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2591 SSVAL(req->outbuf,smb_vwv3,fattr);
2592 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2593 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2595 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2597 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2598 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2599 SSVAL(req->outbuf,smb_vwv11,smb_action);
2601 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2602 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2606 TALLOC_FREE(smb_fname);
2607 END_PROFILE(SMBopenX);
2611 /****************************************************************************
2612 Reply to a SMBulogoffX.
2613 ****************************************************************************/
2615 void reply_ulogoffX(struct smb_request *req)
2617 struct timeval now = timeval_current();
2618 struct smbXsrv_session *session = NULL;
2621 START_PROFILE(SMBulogoffX);
2623 status = smb1srv_session_lookup(req->xconn,
2625 timeval_to_nttime(&now),
2627 if (!NT_STATUS_IS_OK(status)) {
2628 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2629 (unsigned long long)req->vuid));
2631 req->vuid = UID_FIELD_INVALID;
2632 reply_force_doserror(req, ERRSRV, ERRbaduid);
2633 END_PROFILE(SMBulogoffX);
2638 * TODO: cancel all outstanding requests on the session
2640 status = smbXsrv_session_logoff(session);
2641 if (!NT_STATUS_IS_OK(status)) {
2642 DEBUG(0, ("reply_ulogoff: "
2643 "smbXsrv_session_logoff() failed: %s\n",
2644 nt_errstr(status)));
2646 * If we hit this case, there is something completely
2647 * wrong, so we better disconnect the transport connection.
2649 END_PROFILE(SMBulogoffX);
2650 exit_server(__location__ ": smbXsrv_session_logoff failed");
2654 TALLOC_FREE(session);
2656 reply_outbuf(req, 2, 0);
2657 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2658 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2660 DEBUG(3, ("ulogoffX vuid=%llu\n",
2661 (unsigned long long)req->vuid));
2663 END_PROFILE(SMBulogoffX);
2664 req->vuid = UID_FIELD_INVALID;
2667 /****************************************************************************
2668 Reply to a mknew or a create.
2669 ****************************************************************************/
2671 void reply_mknew(struct smb_request *req)
2673 connection_struct *conn = req->conn;
2674 struct smb_filename *smb_fname = NULL;
2677 struct smb_file_time ft;
2679 int oplock_request = 0;
2681 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2682 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2683 uint32_t create_disposition;
2684 uint32_t create_options = 0;
2686 TALLOC_CTX *ctx = talloc_tos();
2688 START_PROFILE(SMBcreate);
2689 init_smb_file_time(&ft);
2692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2696 fattr = SVAL(req->vwv+0, 0);
2697 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2699 if (req->cmd == SMBmknew) {
2700 /* We should fail if file exists. */
2701 create_disposition = FILE_CREATE;
2703 /* Create if file doesn't exist, truncate if it does. */
2704 create_disposition = FILE_OVERWRITE_IF;
2708 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2710 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2711 STR_TERMINATE, &status);
2712 if (!NT_STATUS_IS_OK(status)) {
2713 reply_nterror(req, status);
2717 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2718 status = filename_convert(ctx,
2725 if (!NT_STATUS_IS_OK(status)) {
2726 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2727 reply_botherror(req,
2728 NT_STATUS_PATH_NOT_COVERED,
2729 ERRSRV, ERRbadpath);
2732 reply_nterror(req, status);
2736 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2737 DEBUG(0,("Attempt to create file (%s) with volid set - "
2738 "please report this\n",
2739 smb_fname_str_dbg(smb_fname)));
2742 status = SMB_VFS_CREATE_FILE(
2745 0, /* root_dir_fid */
2746 smb_fname, /* fname */
2747 access_mask, /* access_mask */
2748 share_mode, /* share_access */
2749 create_disposition, /* create_disposition*/
2750 create_options, /* create_options */
2751 fattr, /* file_attributes */
2752 oplock_request, /* oplock_request */
2754 0, /* allocation_size */
2755 0, /* private_flags */
2760 NULL, NULL); /* create context */
2762 if (!NT_STATUS_IS_OK(status)) {
2763 if (open_was_deferred(req->xconn, req->mid)) {
2764 /* We have re-scheduled this call. */
2767 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2768 bool ok = defer_smb1_sharing_violation(req);
2773 reply_openerror(req, status);
2777 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2778 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2779 if (!NT_STATUS_IS_OK(status)) {
2780 END_PROFILE(SMBcreate);
2784 reply_outbuf(req, 1, 0);
2785 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2787 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2788 SCVAL(req->outbuf,smb_flg,
2789 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2792 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2793 SCVAL(req->outbuf,smb_flg,
2794 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2797 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2798 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2799 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2800 (unsigned int)fattr));
2803 TALLOC_FREE(smb_fname);
2804 END_PROFILE(SMBcreate);
2808 /****************************************************************************
2809 Reply to a create temporary file.
2810 ****************************************************************************/
2812 void reply_ctemp(struct smb_request *req)
2814 connection_struct *conn = req->conn;
2815 struct smb_filename *smb_fname = NULL;
2816 char *wire_name = NULL;
2825 TALLOC_CTX *ctx = talloc_tos();
2827 START_PROFILE(SMBctemp);
2830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2834 fattr = SVAL(req->vwv+0, 0);
2835 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2837 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2838 STR_TERMINATE, &status);
2839 if (!NT_STATUS_IS_OK(status)) {
2840 reply_nterror(req, status);
2844 for (i = 0; i < 10; i++) {
2846 fname = talloc_asprintf(ctx,
2849 generate_random_str_list(ctx, 5, "0123456789"));
2851 fname = talloc_asprintf(ctx,
2853 generate_random_str_list(ctx, 5, "0123456789"));
2857 reply_nterror(req, NT_STATUS_NO_MEMORY);
2861 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2862 status = filename_convert(ctx, conn,
2868 if (!NT_STATUS_IS_OK(status)) {
2869 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2870 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2871 ERRSRV, ERRbadpath);
2874 reply_nterror(req, status);
2878 /* Create the file. */
2879 status = SMB_VFS_CREATE_FILE(
2882 0, /* root_dir_fid */
2883 smb_fname, /* fname */
2884 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2885 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2886 FILE_CREATE, /* create_disposition*/
2887 0, /* create_options */
2888 fattr, /* file_attributes */
2889 oplock_request, /* oplock_request */
2891 0, /* allocation_size */
2892 0, /* private_flags */
2897 NULL, NULL); /* create context */
2899 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2901 TALLOC_FREE(smb_fname);
2905 if (!NT_STATUS_IS_OK(status)) {
2906 if (open_was_deferred(req->xconn, req->mid)) {
2907 /* We have re-scheduled this call. */
2910 if (NT_STATUS_EQUAL(
2911 status, NT_STATUS_SHARING_VIOLATION)) {
2912 bool ok = defer_smb1_sharing_violation(req);
2917 reply_openerror(req, status);
2925 /* Collision after 10 times... */
2926 reply_nterror(req, status);
2930 reply_outbuf(req, 1, 0);
2931 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2933 /* the returned filename is relative to the directory */
2934 s = strrchr_m(fsp->fsp_name->base_name, '/');
2936 s = fsp->fsp_name->base_name;
2942 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2943 thing in the byte section. JRA */
2944 SSVALS(p, 0, -1); /* what is this? not in spec */
2946 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2948 reply_nterror(req, NT_STATUS_NO_MEMORY);
2952 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2953 SCVAL(req->outbuf, smb_flg,
2954 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2957 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2958 SCVAL(req->outbuf, smb_flg,
2959 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2962 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2963 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2964 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2966 TALLOC_FREE(smb_fname);
2967 TALLOC_FREE(wire_name);
2968 END_PROFILE(SMBctemp);
2972 /*******************************************************************
2973 Check if a user is allowed to rename a file.
2974 ********************************************************************/
2976 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2979 if (!CAN_WRITE(conn)) {
2980 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2983 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2984 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2985 /* Only bother to read the DOS attribute if we might deny the
2986 rename on the grounds of attribute mismatch. */
2987 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2988 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2989 return NT_STATUS_NO_SUCH_FILE;
2993 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2994 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2995 return NT_STATUS_OK;
2998 /* If no pathnames are open below this
2999 directory, allow the rename. */
3001 if (lp_strict_rename(SNUM(conn))) {
3003 * Strict rename, check open file db.
3005 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3006 return NT_STATUS_ACCESS_DENIED;
3008 } else if (file_find_subpath(fsp)) {
3010 * No strict rename, just look in local process.
3012 return NT_STATUS_ACCESS_DENIED;
3014 return NT_STATUS_OK;
3017 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3018 return NT_STATUS_OK;
3021 return NT_STATUS_ACCESS_DENIED;
3024 /*******************************************************************
3025 * unlink a file with all relevant access checks
3026 *******************************************************************/
3028 static NTSTATUS do_unlink(connection_struct *conn,
3029 struct smb_request *req,
3030 struct smb_filename *smb_fname,
3035 uint32_t dirtype_orig = dirtype;
3038 bool posix_paths = (req != NULL && req->posix_pathnames);
3039 struct smb2_create_blobs *posx = NULL;
3041 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3042 smb_fname_str_dbg(smb_fname),
3045 if (!CAN_WRITE(conn)) {
3046 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3050 ret = SMB_VFS_LSTAT(conn, smb_fname);
3052 ret = SMB_VFS_STAT(conn, smb_fname);
3055 return map_nt_error_from_unix(errno);
3058 fattr = dos_mode(conn, smb_fname);
3060 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3061 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3064 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3066 return NT_STATUS_NO_SUCH_FILE;
3069 if (!dir_check_ftype(fattr, dirtype)) {
3070 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3071 return NT_STATUS_FILE_IS_A_DIRECTORY;
3073 return NT_STATUS_NO_SUCH_FILE;
3076 if (dirtype_orig & 0x8000) {
3077 /* These will never be set for POSIX. */
3078 return NT_STATUS_NO_SUCH_FILE;
3082 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3083 return NT_STATUS_FILE_IS_A_DIRECTORY;
3086 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3087 return NT_STATUS_NO_SUCH_FILE;
3090 if (dirtype & 0xFF00) {
3091 /* These will never be set for POSIX. */
3092 return NT_STATUS_NO_SUCH_FILE;
3097 return NT_STATUS_NO_SUCH_FILE;
3100 /* Can't delete a directory. */
3101 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3102 return NT_STATUS_FILE_IS_A_DIRECTORY;
3107 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3108 return NT_STATUS_OBJECT_NAME_INVALID;
3109 #endif /* JRATEST */
3112 status = make_smb2_posix_create_ctx(
3113 talloc_tos(), &posx, 0777);
3114 if (!NT_STATUS_IS_OK(status)) {
3115 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3121 /* On open checks the open itself will check the share mode, so
3122 don't do it here as we'll get it wrong. */
3124 status = SMB_VFS_CREATE_FILE
3127 0, /* root_dir_fid */
3128 smb_fname, /* fname */
3129 DELETE_ACCESS, /* access_mask */
3130 FILE_SHARE_NONE, /* share_access */
3131 FILE_OPEN, /* create_disposition*/
3132 FILE_NON_DIRECTORY_FILE, /* create_options */
3133 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3134 0, /* oplock_request */
3136 0, /* allocation_size */
3137 0, /* private_flags */
3142 posx, /* in_context_blobs */
3143 NULL); /* out_context_blobs */
3147 if (!NT_STATUS_IS_OK(status)) {
3148 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3149 nt_errstr(status)));
3153 status = can_set_delete_on_close(fsp, fattr);
3154 if (!NT_STATUS_IS_OK(status)) {
3155 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3157 smb_fname_str_dbg(smb_fname),
3158 nt_errstr(status)));
3159 close_file(req, fsp, NORMAL_CLOSE);
3163 /* The set is across all open files on this dev/inode pair. */
3164 if (!set_delete_on_close(fsp, True,
3165 conn->session_info->security_token,
3166 conn->session_info->unix_token)) {
3167 close_file(req, fsp, NORMAL_CLOSE);
3168 return NT_STATUS_ACCESS_DENIED;
3171 return close_file(req, fsp, NORMAL_CLOSE);
3174 /****************************************************************************
3175 The guts of the unlink command, split out so it may be called by the NT SMB
3177 ****************************************************************************/
3179 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3180 uint32_t dirtype, struct smb_filename *smb_fname,
3183 char *fname_dir = NULL;
3184 char *fname_mask = NULL;
3186 NTSTATUS status = NT_STATUS_OK;
3187 struct smb_filename *smb_fname_dir = NULL;
3188 TALLOC_CTX *ctx = talloc_tos();
3190 /* Split up the directory from the filename/mask. */
3191 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3192 &fname_dir, &fname_mask);
3193 if (!NT_STATUS_IS_OK(status)) {
3198 * We should only check the mangled cache
3199 * here if unix_convert failed. This means
3200 * that the path in 'mask' doesn't exist
3201 * on the file system and so we need to look
3202 * for a possible mangle. This patch from
3203 * Tine Smukavec <valentin.smukavec@hermes.si>.
3206 if (!VALID_STAT(smb_fname->st) &&
3207 mangle_is_mangled(fname_mask, conn->params)) {
3208 char *new_mask = NULL;
3209 mangle_lookup_name_from_8_3(ctx, fname_mask,
3210 &new_mask, conn->params);
3212 TALLOC_FREE(fname_mask);
3213 fname_mask = new_mask;
3220 * Only one file needs to be unlinked. Append the mask back
3221 * onto the directory.
3223 TALLOC_FREE(smb_fname->base_name);
3224 if (ISDOT(fname_dir)) {
3225 /* Ensure we use canonical names on open. */
3226 smb_fname->base_name = talloc_asprintf(smb_fname,
3230 smb_fname->base_name = talloc_asprintf(smb_fname,
3235 if (!smb_fname->base_name) {
3236 status = NT_STATUS_NO_MEMORY;
3240 dirtype = FILE_ATTRIBUTE_NORMAL;
3243 status = check_name(conn, smb_fname);
3244 if (!NT_STATUS_IS_OK(status)) {
3248 status = do_unlink(conn, req, smb_fname, dirtype);
3249 if (!NT_STATUS_IS_OK(status)) {
3255 struct smb_Dir *dir_hnd = NULL;
3257 const char *dname = NULL;
3258 char *talloced = NULL;
3260 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3261 status = NT_STATUS_OBJECT_NAME_INVALID;
3265 dirtype = FILE_ATTRIBUTE_NORMAL;
3268 if (strequal(fname_mask,"????????.???")) {
3269 TALLOC_FREE(fname_mask);
3270 fname_mask = talloc_strdup(ctx, "*");
3272 status = NT_STATUS_NO_MEMORY;
3277 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3282 if (smb_fname_dir == NULL) {
3283 status = NT_STATUS_NO_MEMORY;
3287 status = check_name(conn, smb_fname_dir);
3288 if (!NT_STATUS_IS_OK(status)) {
3292 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3294 if (dir_hnd == NULL) {
3295 status = map_nt_error_from_unix(errno);
3299 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3300 the pattern matches against the long name, otherwise the short name
3301 We don't implement this yet XXXX
3304 status = NT_STATUS_NO_SUCH_FILE;
3306 while ((dname = ReadDirName(dir_hnd, &offset,
3307 &smb_fname->st, &talloced))) {
3308 TALLOC_CTX *frame = talloc_stackframe();
3310 if (!is_visible_file(conn, fname_dir, dname,
3311 &smb_fname->st, true)) {
3313 TALLOC_FREE(talloced);
3317 /* Quick check for "." and ".." */
3318 if (ISDOT(dname) || ISDOTDOT(dname)) {
3320 TALLOC_FREE(talloced);
3324 if(!mask_match(dname, fname_mask,
3325 conn->case_sensitive)) {
3327 TALLOC_FREE(talloced);
3331 TALLOC_FREE(smb_fname->base_name);
3332 if (ISDOT(fname_dir)) {
3333 /* Ensure we use canonical names on open. */
3334 smb_fname->base_name =
3335 talloc_asprintf(smb_fname, "%s",
3338 smb_fname->base_name =
3339 talloc_asprintf(smb_fname, "%s/%s",
3343 if (!smb_fname->base_name) {
3344 TALLOC_FREE(dir_hnd);
3345 status = NT_STATUS_NO_MEMORY;
3347 TALLOC_FREE(talloced);
3351 status = check_name(conn, smb_fname);
3352 if (!NT_STATUS_IS_OK(status)) {
3353 TALLOC_FREE(dir_hnd);
3355 TALLOC_FREE(talloced);
3359 status = do_unlink(conn, req, smb_fname, dirtype);
3360 if (!NT_STATUS_IS_OK(status)) {
3361 TALLOC_FREE(dir_hnd);
3363 TALLOC_FREE(talloced);
3368 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3369 smb_fname->base_name));
3372 TALLOC_FREE(talloced);
3374 TALLOC_FREE(dir_hnd);
3377 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3378 status = map_nt_error_from_unix(errno);
3382 TALLOC_FREE(smb_fname_dir);
3383 TALLOC_FREE(fname_dir);
3384 TALLOC_FREE(fname_mask);
3388 /****************************************************************************
3390 ****************************************************************************/
3392 void reply_unlink(struct smb_request *req)
3394 connection_struct *conn = req->conn;
3396 struct smb_filename *smb_fname = NULL;
3399 bool path_contains_wcard = False;
3400 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3401 ucf_flags_from_smb_request(req);
3402 TALLOC_CTX *ctx = talloc_tos();
3404 START_PROFILE(SMBunlink);
3407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3411 dirtype = SVAL(req->vwv+0, 0);
3413 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3414 STR_TERMINATE, &status,
3415 &path_contains_wcard);
3416 if (!NT_STATUS_IS_OK(status)) {
3417 reply_nterror(req, status);
3421 status = filename_convert(ctx, conn,
3425 &path_contains_wcard,
3427 if (!NT_STATUS_IS_OK(status)) {
3428 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3429 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3430 ERRSRV, ERRbadpath);
3433 reply_nterror(req, status);
3437 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3439 status = unlink_internals(conn, req, dirtype, smb_fname,
3440 path_contains_wcard);
3441 if (!NT_STATUS_IS_OK(status)) {
3442 if (open_was_deferred(req->xconn, req->mid)) {
3443 /* We have re-scheduled this call. */
3446 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3447 bool ok = defer_smb1_sharing_violation(req);
3452 reply_nterror(req, status);
3456 reply_outbuf(req, 0, 0);
3458 TALLOC_FREE(smb_fname);
3459 END_PROFILE(SMBunlink);
3463 /****************************************************************************
3465 ****************************************************************************/
3467 static void fail_readraw(void)
3469 const char *errstr = talloc_asprintf(talloc_tos(),
3470 "FAIL ! reply_readbraw: socket write fail (%s)",
3475 exit_server_cleanly(errstr);
3478 /****************************************************************************
3479 Fake (read/write) sendfile. Returns -1 on read or write fail.
3480 ****************************************************************************/
3482 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3483 off_t startpos, size_t nread)
3486 size_t tosend = nread;
3493 bufsize = MIN(nread, 65536);
3495 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3499 while (tosend > 0) {
3503 cur_read = MIN(tosend, bufsize);
3504 ret = read_file(fsp,buf,startpos,cur_read);
3510 /* If we had a short read, fill with zeros. */
3511 if (ret < cur_read) {
3512 memset(buf + ret, '\0', cur_read - ret);
3515 ret = write_data(xconn->transport.sock, buf, cur_read);
3516 if (ret != cur_read) {
3517 int saved_errno = errno;
3519 * Try and give an error message saying what
3522 DEBUG(0, ("write_data failed for client %s. "
3524 smbXsrv_connection_dbg(xconn),
3525 strerror(saved_errno)));
3527 errno = saved_errno;
3531 startpos += cur_read;
3535 return (ssize_t)nread;
3538 /****************************************************************************
3539 Deal with the case of sendfile reading less bytes from the file than
3540 requested. Fill with zeros (all we can do). Returns 0 on success
3541 ****************************************************************************/
3543 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3549 #define SHORT_SEND_BUFSIZE 1024
3550 if (nread < headersize) {
3551 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3552 "header for file %s (%s). Terminating\n",
3553 fsp_str_dbg(fsp), strerror(errno)));
3557 nread -= headersize;
3559 if (nread < smb_maxcnt) {
3560 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3562 DEBUG(0,("sendfile_short_send: malloc failed "
3563 "for file %s (%s). Terminating\n",
3564 fsp_str_dbg(fsp), strerror(errno)));
3568 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3569 "with zeros !\n", fsp_str_dbg(fsp)));
3571 while (nread < smb_maxcnt) {
3573 * We asked for the real file size and told sendfile
3574 * to not go beyond the end of the file. But it can
3575 * happen that in between our fstat call and the
3576 * sendfile call the file was truncated. This is very
3577 * bad because we have already announced the larger
3578 * number of bytes to the client.
3580 * The best we can do now is to send 0-bytes, just as
3581 * a read from a hole in a sparse file would do.
3583 * This should happen rarely enough that I don't care
3584 * about efficiency here :-)
3589 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3590 ret = write_data(xconn->transport.sock, buf, to_write);
3591 if (ret != to_write) {
3592 int saved_errno = errno;
3594 * Try and give an error message saying what
3597 DEBUG(0, ("write_data failed for client %s. "
3599 smbXsrv_connection_dbg(xconn),
3600 strerror(saved_errno)));
3601 errno = saved_errno;
3612 /****************************************************************************
3613 Return a readbraw error (4 bytes of zero).
3614 ****************************************************************************/
3616 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3622 smbd_lock_socket(xconn);
3623 if (write_data(xconn->transport.sock,header,4) != 4) {
3624 int saved_errno = errno;
3626 * Try and give an error message saying what
3629 DEBUG(0, ("write_data failed for client %s. "
3631 smbXsrv_connection_dbg(xconn),
3632 strerror(saved_errno)));
3633 errno = saved_errno;
3637 smbd_unlock_socket(xconn);
3640 /*******************************************************************
3641 Ensure we don't use sendfile if server smb signing is active.
3642 ********************************************************************/
3644 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3646 bool sign_active = false;
3648 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3649 if (get_Protocol() < PROTOCOL_NT1) {
3652 if (signing_state) {
3653 sign_active = smb_signing_is_active(signing_state);
3655 return (lp__use_sendfile(snum) &&
3656 (get_remote_arch() != RA_WIN95) &&
3659 /****************************************************************************
3660 Use sendfile in readbraw.
3661 ****************************************************************************/
3663 static void send_file_readbraw(connection_struct *conn,
3664 struct smb_request *req,
3670 struct smbXsrv_connection *xconn = req->xconn;
3671 char *outbuf = NULL;
3675 * We can only use sendfile on a non-chained packet
3676 * but we can use on a non-oplocked file. tridge proved this
3677 * on a train in Germany :-). JRA.
3678 * reply_readbraw has already checked the length.
3681 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3682 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3683 ssize_t sendfile_read = -1;
3685 DATA_BLOB header_blob;
3687 _smb_setlen(header,nread);
3688 header_blob = data_blob_const(header, 4);
3690 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3691 &header_blob, startpos,
3693 if (sendfile_read == -1) {
3694 /* Returning ENOSYS means no data at all was sent.
3695 * Do this as a normal read. */
3696 if (errno == ENOSYS) {
3697 goto normal_readbraw;
3701 * Special hack for broken Linux with no working sendfile. If we
3702 * return EINTR we sent the header but not the rest of the data.
3703 * Fake this up by doing read/write calls.
3705 if (errno == EINTR) {
3706 /* Ensure we don't do this again. */
3707 set_use_sendfile(SNUM(conn), False);
3708 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3710 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3711 DEBUG(0,("send_file_readbraw: "
3712 "fake_sendfile failed for "
3716 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3721 DEBUG(0,("send_file_readbraw: sendfile failed for "
3722 "file %s (%s). Terminating\n",
3723 fsp_str_dbg(fsp), strerror(errno)));
3724 exit_server_cleanly("send_file_readbraw sendfile failed");
3725 } else if (sendfile_read == 0) {
3727 * Some sendfile implementations return 0 to indicate
3728 * that there was a short read, but nothing was
3729 * actually written to the socket. In this case,
3730 * fallback to the normal read path so the header gets
3731 * the correct byte count.
3733 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3734 "bytes falling back to the normal read: "
3735 "%s\n", fsp_str_dbg(fsp)));
3736 goto normal_readbraw;
3739 /* Deal with possible short send. */
3740 if (sendfile_read != 4+nread) {
3741 ret = sendfile_short_send(xconn, fsp,
3742 sendfile_read, 4, nread);
3752 outbuf = talloc_array(NULL, char, nread+4);
3754 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3755 (unsigned)(nread+4)));
3756 reply_readbraw_error(xconn);
3761 ret = read_file(fsp,outbuf+4,startpos,nread);
3762 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3771 _smb_setlen(outbuf,ret);
3772 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3773 int saved_errno = errno;
3775 * Try and give an error message saying what
3778 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3779 smbXsrv_connection_dbg(xconn),
3780 strerror(saved_errno)));
3781 errno = saved_errno;
3786 TALLOC_FREE(outbuf);
3789 /****************************************************************************
3790 Reply to a readbraw (core+ protocol).
3791 ****************************************************************************/
3793 void reply_readbraw(struct smb_request *req)
3795 connection_struct *conn = req->conn;
3796 struct smbXsrv_connection *xconn = req->xconn;
3797 ssize_t maxcount,mincount;
3801 struct lock_struct lock;
3805 START_PROFILE(SMBreadbraw);
3807 if (srv_is_signing_active(xconn) || req->encrypted) {
3808 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3809 "raw reads/writes are disallowed.");
3813 reply_readbraw_error(xconn);
3814 END_PROFILE(SMBreadbraw);
3818 if (xconn->smb1.echo_handler.trusted_fde) {
3819 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3820 "'async smb echo handler = yes'\n"));
3821 reply_readbraw_error(xconn);
3822 END_PROFILE(SMBreadbraw);
3827 * Special check if an oplock break has been issued
3828 * and the readraw request croses on the wire, we must
3829 * return a zero length response here.
3832 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3835 * We have to do a check_fsp by hand here, as
3836 * we must always return 4 zero bytes on error,
3840 if (!fsp || !conn || conn != fsp->conn ||
3841 req->vuid != fsp->vuid ||
3842 fsp->is_directory || fsp->fh->fd == -1) {
3844 * fsp could be NULL here so use the value from the packet. JRA.
3846 DEBUG(3,("reply_readbraw: fnum %d not valid "
3848 (int)SVAL(req->vwv+0, 0)));
3849 reply_readbraw_error(xconn);
3850 END_PROFILE(SMBreadbraw);
3854 /* Do a "by hand" version of CHECK_READ. */
3855 if (!(fsp->can_read ||
3856 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3857 (fsp->access_mask & FILE_EXECUTE)))) {
3858 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3859 (int)SVAL(req->vwv+0, 0)));
3860 reply_readbraw_error(xconn);
3861 END_PROFILE(SMBreadbraw);
3865 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3866 if(req->wct == 10) {
3868 * This is a large offset (64 bit) read.
3871 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3874 DEBUG(0,("reply_readbraw: negative 64 bit "
3875 "readraw offset (%.0f) !\n",
3876 (double)startpos ));
3877 reply_readbraw_error(xconn);
3878 END_PROFILE(SMBreadbraw);
3883 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3884 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3886 /* ensure we don't overrun the packet size */
3887 maxcount = MIN(65535,maxcount);
3889 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3890 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3893 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3894 reply_readbraw_error(xconn);
3895 END_PROFILE(SMBreadbraw);
3899 status = vfs_stat_fsp(fsp);
3900 if (NT_STATUS_IS_OK(status)) {
3901 size = fsp->fsp_name->st.st_ex_size;
3904 if (startpos >= size) {
3907 nread = MIN(maxcount,(size - startpos));
3910 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3911 if (nread < mincount)
3915 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3916 "min=%lu nread=%lu\n",
3917 fsp_fnum_dbg(fsp), (double)startpos,
3918 (unsigned long)maxcount,
3919 (unsigned long)mincount,
3920 (unsigned long)nread ) );
3922 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3924 DEBUG(5,("reply_readbraw finished\n"));
3926 END_PROFILE(SMBreadbraw);
3931 #define DBGC_CLASS DBGC_LOCKING
3933 /****************************************************************************
3934 Reply to a lockread (core+ protocol).
3935 ****************************************************************************/
3937 static void reply_lockread_locked(struct tevent_req *subreq);
3939 void reply_lockread(struct smb_request *req)
3941 struct tevent_req *subreq = NULL;
3942 connection_struct *conn = req->conn;
3944 struct smbd_lock_element *lck = NULL;
3946 START_PROFILE(SMBlockread);
3949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3950 END_PROFILE(SMBlockread);
3954 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3956 if (!check_fsp(conn, req, fsp)) {
3957 END_PROFILE(SMBlockread);
3961 if (!CHECK_READ(fsp,req)) {
3962 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3963 END_PROFILE(SMBlockread);
3967 lck = talloc(req, struct smbd_lock_element);
3969 reply_nterror(req, NT_STATUS_NO_MEMORY);
3970 END_PROFILE(SMBlockread);
3975 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3976 * protocol request that predates the read/write lock concept.
3977 * Thus instead of asking for a read lock here we need to ask
3978 * for a write lock. JRA.
3979 * Note that the requested lock size is unaffected by max_send.
3982 *lck = (struct smbd_lock_element) {
3983 .req_guid = smbd_request_guid(req, 0),
3984 .smblctx = req->smbpid,
3985 .brltype = WRITE_LOCK,
3986 .count = SVAL(req->vwv+1, 0),
3987 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3990 subreq = smbd_smb1_do_locks_send(
3996 false, /* large_offset */
4000 if (subreq == NULL) {
4001 reply_nterror(req, NT_STATUS_NO_MEMORY);
4002 END_PROFILE(SMBlockread);
4005 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4006 END_PROFILE(SMBlockread);
4009 static void reply_lockread_locked(struct tevent_req *subreq)
4011 struct smb_request *req = NULL;
4017 size_t numtoread, maxtoread;
4018 struct files_struct *fsp = NULL;
4021 START_PROFILE(SMBlockread);
4023 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4026 status = smbd_smb1_do_locks_recv(subreq);
4027 TALLOC_FREE(subreq);
4029 if (!NT_STATUS_IS_OK(status)) {
4030 reply_nterror(req, status);
4034 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4036 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4040 numtoread = SVAL(req->vwv+1, 0);
4041 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4044 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4046 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4048 if (numtoread > maxtoread) {
4049 DBG_WARNING("requested read size (%zu) is greater than "
4050 "maximum allowed (%zu/%d). "
4051 "Returning short read of maximum allowed for "
4052 "compatibility with Windows 2000.\n",
4055 req->xconn->smb1.sessions.max_send);
4056 numtoread = maxtoread;
4059 reply_outbuf(req, 5, numtoread + 3);
4061 data = smb_buf(req->outbuf) + 3;
4063 nread = read_file(fsp,data,startpos,numtoread);
4066 reply_nterror(req, map_nt_error_from_unix(errno));
4070 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4072 SSVAL(req->outbuf,smb_vwv0,nread);
4073 SSVAL(req->outbuf,smb_vwv5,nread+3);
4074 p = smb_buf(req->outbuf);
4075 SCVAL(p,0,0); /* pad byte. */
4078 DEBUG(3,("lockread %s num=%d nread=%d\n",
4079 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4082 ok = srv_send_smb(req->xconn,
4083 (char *)req->outbuf,
4086 IS_CONN_ENCRYPTED(req->conn),
4089 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4092 END_PROFILE(SMBlockread);
4097 #define DBGC_CLASS DBGC_ALL
4099 /****************************************************************************
4101 ****************************************************************************/
4103 void reply_read(struct smb_request *req)
4105 connection_struct *conn = req->conn;
4112 struct lock_struct lock;
4113 struct smbXsrv_connection *xconn = req->xconn;
4115 START_PROFILE(SMBread);
4118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4119 END_PROFILE(SMBread);
4123 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4125 if (!check_fsp(conn, req, fsp)) {
4126 END_PROFILE(SMBread);
4130 if (!CHECK_READ(fsp,req)) {
4131 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4132 END_PROFILE(SMBread);
4136 numtoread = SVAL(req->vwv+1, 0);
4137 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4140 * The requested read size cannot be greater than max_send. JRA.
4142 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4144 if (numtoread > maxtoread) {
4145 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4146 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4147 (unsigned int)numtoread, (unsigned int)maxtoread,
4148 (unsigned int)xconn->smb1.sessions.max_send));
4149 numtoread = maxtoread;
4152 reply_outbuf(req, 5, numtoread+3);
4154 data = smb_buf(req->outbuf) + 3;
4156 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4157 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4160 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4161 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4162 END_PROFILE(SMBread);
4167 nread = read_file(fsp,data,startpos,numtoread);
4170 reply_nterror(req, map_nt_error_from_unix(errno));
4174 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4176 SSVAL(req->outbuf,smb_vwv0,nread);
4177 SSVAL(req->outbuf,smb_vwv5,nread+3);
4178 SCVAL(smb_buf(req->outbuf),0,1);
4179 SSVAL(smb_buf(req->outbuf),1,nread);
4181 DEBUG(3, ("read %s num=%d nread=%d\n",
4182 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4185 END_PROFILE(SMBread);
4189 /****************************************************************************
4191 ****************************************************************************/
4193 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4197 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4200 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4202 SCVAL(outbuf,smb_vwv0,0xFF);
4203 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4204 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4205 SSVAL(outbuf,smb_vwv6,
4206 (smb_wct - 4) /* offset from smb header to wct */
4207 + 1 /* the wct field */
4208 + 12 * sizeof(uint16_t) /* vwv */
4209 + 2 /* the buflen field */
4210 + 1); /* padding byte */
4211 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4212 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4213 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4214 _smb_setlen_large(outbuf,
4215 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4219 /****************************************************************************
4220 Reply to a read and X - possibly using sendfile.
4221 ****************************************************************************/
4223 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4224 files_struct *fsp, off_t startpos,
4227 struct smbXsrv_connection *xconn = req->xconn;
4229 struct lock_struct lock;
4230 int saved_errno = 0;
4233 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4234 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4237 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4238 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4243 * We can only use sendfile on a non-chained packet
4244 * but we can use on a non-oplocked file. tridge proved this
4245 * on a train in Germany :-). JRA.
4248 if (!req_is_in_chain(req) &&
4250 (fsp->base_fsp == NULL) &&
4251 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4252 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4255 status = vfs_stat_fsp(fsp);
4256 if (!NT_STATUS_IS_OK(status)) {
4257 reply_nterror(req, status);
4261 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4262 (startpos > fsp->fsp_name->st.st_ex_size) ||
4263 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4265 * We already know that we would do a short read, so don't
4266 * try the sendfile() path.
4268 goto nosendfile_read;
4272 * Set up the packet header before send. We
4273 * assume here the sendfile will work (get the
4274 * correct amount of data).
4277 header = data_blob_const(headerbuf, sizeof(headerbuf));
4279 construct_reply_common_req(req, (char *)headerbuf);
4280 setup_readX_header((char *)headerbuf, smb_maxcnt);
4282 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4283 startpos, smb_maxcnt);
4285 saved_errno = errno;
4287 /* Returning ENOSYS means no data at all was sent.
4288 Do this as a normal read. */
4289 if (errno == ENOSYS) {
4294 * Special hack for broken Linux with no working sendfile. If we
4295 * return EINTR we sent the header but not the rest of the data.
4296 * Fake this up by doing read/write calls.
4299 if (errno == EINTR) {
4300 /* Ensure we don't do this again. */
4301 set_use_sendfile(SNUM(conn), False);
4302 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4303 nread = fake_sendfile(xconn, fsp, startpos,
4306 saved_errno = errno;
4307 DEBUG(0,("send_file_readX: "
4308 "fake_sendfile failed for "
4309 "file %s (%s) for client %s. "
4312 smbXsrv_connection_dbg(xconn),
4313 strerror(saved_errno)));
4314 errno = saved_errno;
4315 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4317 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4318 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4319 /* No outbuf here means successful sendfile. */
4323 DEBUG(0,("send_file_readX: sendfile failed for file "
4324 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4326 exit_server_cleanly("send_file_readX sendfile failed");
4327 } else if (nread == 0) {
4329 * Some sendfile implementations return 0 to indicate
4330 * that there was a short read, but nothing was
4331 * actually written to the socket. In this case,
4332 * fallback to the normal read path so the header gets
4333 * the correct byte count.
4335 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4336 "falling back to the normal read: %s\n",
4341 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4342 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4344 /* Deal with possible short send. */
4345 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4348 ret = sendfile_short_send(xconn, fsp, nread,
4349 sizeof(headerbuf), smb_maxcnt);
4352 r = "send_file_readX: sendfile_short_send failed";
4353 DEBUG(0,("%s for file %s (%s).\n",
4354 r, fsp_str_dbg(fsp), strerror(errno)));
4355 exit_server_cleanly(r);
4358 /* No outbuf here means successful sendfile. */
4359 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4360 SMB_PERFCOUNT_END(&req->pcd);
4366 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4367 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4370 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4371 (startpos > fsp->fsp_name->st.st_ex_size) ||
4372 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4374 * We already know that we would do a short
4375 * read, so don't try the sendfile() path.
4377 goto nosendfile_read;
4380 construct_reply_common_req(req, (char *)headerbuf);
4381 setup_readX_header((char *)headerbuf, smb_maxcnt);
4383 /* Send out the header. */
4384 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4386 if (ret != sizeof(headerbuf)) {
4387 saved_errno = errno;
4389 * Try and give an error message saying what
4392 DEBUG(0,("send_file_readX: write_data failed for file "
4393 "%s (%s) for client %s. Terminating\n",
4395 smbXsrv_connection_dbg(xconn),
4396 strerror(saved_errno)));
4397 errno = saved_errno;
4398 exit_server_cleanly("send_file_readX sendfile failed");
4400 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4402 saved_errno = errno;
4403 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4404 "%s (%s) for client %s. Terminating\n",
4406 smbXsrv_connection_dbg(xconn),
4407 strerror(saved_errno)));
4408 errno = saved_errno;
4409 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4416 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4417 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4418 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4420 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4421 startpos, smb_maxcnt);
4422 saved_errno = errno;
4425 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4429 setup_readX_header((char *)req->outbuf, nread);
4431 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4432 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4436 TALLOC_FREE(req->outbuf);
4440 /****************************************************************************
4441 Work out how much space we have for a read return.
4442 ****************************************************************************/
4444 static size_t calc_max_read_pdu(const struct smb_request *req)
4446 struct smbXsrv_connection *xconn = req->xconn;
4448 if (xconn->protocol < PROTOCOL_NT1) {
4449 return xconn->smb1.sessions.max_send;
4452 if (!lp_large_readwrite()) {
4453 return xconn->smb1.sessions.max_send;
4456 if (req_is_in_chain(req)) {
4457 return xconn->smb1.sessions.max_send;
4460 if (req->encrypted) {
4462 * Don't take encrypted traffic up to the
4463 * limit. There are padding considerations
4464 * that make that tricky.
4466 return xconn->smb1.sessions.max_send;
4469 if (srv_is_signing_active(xconn)) {
4473 if (!lp_unix_extensions()) {
4478 * We can do ultra-large POSIX reads.
4483 /****************************************************************************
4484 Calculate how big a read can be. Copes with all clients. It's always
4485 safe to return a short read - Windows does this.
4486 ****************************************************************************/
4488 static size_t calc_read_size(const struct smb_request *req,
4492 struct smbXsrv_connection *xconn = req->xconn;
4493 size_t max_pdu = calc_max_read_pdu(req);
4494 size_t total_size = 0;
4495 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4496 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4499 * Windows explicitly ignores upper size of 0xFFFF.
4500 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4501 * We must do the same as these will never fit even in
4502 * an extended size NetBIOS packet.
4504 if (upper_size == 0xFFFF) {
4508 if (xconn->protocol < PROTOCOL_NT1) {
4512 total_size = ((upper_size<<16) | lower_size);
4515 * LARGE_READX test shows it's always safe to return
4516 * a short read. Windows does so.
4518 return MIN(total_size, max_len);
4521 /****************************************************************************
4522 Reply to a read and X.
4523 ****************************************************************************/
4525 void reply_read_and_X(struct smb_request *req)
4527 connection_struct *conn = req->conn;
4532 bool big_readX = False;
4534 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4537 START_PROFILE(SMBreadX);
4539 if ((req->wct != 10) && (req->wct != 12)) {
4540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4544 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4545 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4546 smb_maxcnt = SVAL(req->vwv+5, 0);
4548 /* If it's an IPC, pass off the pipe handler. */
4550 reply_pipe_read_and_X(req);
4551 END_PROFILE(SMBreadX);
4555 if (!check_fsp(conn, req, fsp)) {
4556 END_PROFILE(SMBreadX);
4560 if (!CHECK_READ(fsp,req)) {
4561 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4562 END_PROFILE(SMBreadX);
4566 upper_size = SVAL(req->vwv+7, 0);
4567 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4568 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4570 * This is a heuristic to avoid keeping large
4571 * outgoing buffers around over long-lived aio
4577 if (req->wct == 12) {
4579 * This is a large offset (64 bit) read.
4581 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4586 NTSTATUS status = schedule_aio_read_and_X(conn,
4591 if (NT_STATUS_IS_OK(status)) {
4592 /* Read scheduled - we're done. */
4595 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4596 /* Real error - report to client. */
4597 END_PROFILE(SMBreadX);
4598 reply_nterror(req, status);
4601 /* NT_STATUS_RETRY - fall back to sync read. */
4604 smbd_lock_socket(req->xconn);
4605 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4606 smbd_unlock_socket(req->xconn);
4609 END_PROFILE(SMBreadX);
4613 /****************************************************************************
4614 Error replies to writebraw must have smb_wct == 1. Fix this up.
4615 ****************************************************************************/
4617 void error_to_writebrawerr(struct smb_request *req)
4619 uint8_t *old_outbuf = req->outbuf;
4621 reply_outbuf(req, 1, 0);
4623 memcpy(req->outbuf, old_outbuf, smb_size);
4624 TALLOC_FREE(old_outbuf);
4627 /****************************************************************************
4628 Read 4 bytes of a smb packet and return the smb length of the packet.
4629 Store the result in the buffer. This version of the function will
4630 never return a session keepalive (length of zero).
4631 Timeout is in milliseconds.
4632 ****************************************************************************/
4634 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4637 uint8_t msgtype = NBSSkeepalive;
4639 while (msgtype == NBSSkeepalive) {
4642 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4644 if (!NT_STATUS_IS_OK(status)) {
4645 char addr[INET6_ADDRSTRLEN];
4646 /* Try and give an error message
4647 * saying what client failed. */
4648 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4649 "client %s read error = %s.\n",
4650 get_peer_addr(fd,addr,sizeof(addr)),
4651 nt_errstr(status)));
4655 msgtype = CVAL(inbuf, 0);
4658 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4659 (unsigned long)len));
4661 return NT_STATUS_OK;
4664 /****************************************************************************
4665 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4666 ****************************************************************************/
4668 void reply_writebraw(struct smb_request *req)
4670 connection_struct *conn = req->conn;
4671 struct smbXsrv_connection *xconn = req->xconn;
4674 ssize_t total_written=0;
4675 size_t numtowrite=0;
4678 const char *data=NULL;
4681 struct lock_struct lock;
4684 START_PROFILE(SMBwritebraw);
4687 * If we ever reply with an error, it must have the SMB command
4688 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4691 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4693 if (srv_is_signing_active(xconn)) {
4694 END_PROFILE(SMBwritebraw);
4695 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4696 "raw reads/writes are disallowed.");
4699 if (req->wct < 12) {
4700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4701 error_to_writebrawerr(req);
4702 END_PROFILE(SMBwritebraw);
4706 if (xconn->smb1.echo_handler.trusted_fde) {
4707 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4708 "'async smb echo handler = yes'\n"));
4709 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4710 error_to_writebrawerr(req);
4711 END_PROFILE(SMBwritebraw);
4715 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4716 if (!check_fsp(conn, req, fsp)) {
4717 error_to_writebrawerr(req);
4718 END_PROFILE(SMBwritebraw);
4722 if (!CHECK_WRITE(fsp)) {
4723 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4724 error_to_writebrawerr(req);
4725 END_PROFILE(SMBwritebraw);
4729 tcount = IVAL(req->vwv+1, 0);
4730 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4731 write_through = BITSETW(req->vwv+7,0);
4733 /* We have to deal with slightly different formats depending
4734 on whether we are using the core+ or lanman1.0 protocol */
4736 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4737 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4738 data = smb_buf_const(req->inbuf);
4740 numtowrite = SVAL(req->vwv+10, 0);
4741 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4744 /* Ensure we don't write bytes past the end of this packet. */
4746 * This already protects us against CVE-2017-12163.
4748 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4750 error_to_writebrawerr(req);
4751 END_PROFILE(SMBwritebraw);
4755 if (!fsp->print_file) {
4756 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4757 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4760 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4761 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4762 error_to_writebrawerr(req);
4763 END_PROFILE(SMBwritebraw);
4769 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4772 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4773 "wrote=%d sync=%d\n",
4774 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4775 (int)nwritten, (int)write_through));
4777 if (nwritten < (ssize_t)numtowrite) {
4778 reply_nterror(req, NT_STATUS_DISK_FULL);
4779 error_to_writebrawerr(req);
4783 total_written = nwritten;
4785 /* Allocate a buffer of 64k + length. */
4786 buf = talloc_array(NULL, char, 65540);
4788 reply_nterror(req, NT_STATUS_NO_MEMORY);
4789 error_to_writebrawerr(req);
4793 /* Return a SMBwritebraw message to the redirector to tell
4794 * it to send more bytes */
4796 memcpy(buf, req->inbuf, smb_size);
4797 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4798 SCVAL(buf,smb_com,SMBwritebraw);
4799 SSVALS(buf,smb_vwv0,0xFFFF);
4801 if (!srv_send_smb(req->xconn,
4803 false, 0, /* no signing */
4804 IS_CONN_ENCRYPTED(conn),
4806 exit_server_cleanly("reply_writebraw: srv_send_smb "
4810 /* Now read the raw data into the buffer and write it */
4811 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4813 if (!NT_STATUS_IS_OK(status)) {
4814 exit_server_cleanly("secondary writebraw failed");
4817 /* Set up outbuf to return the correct size */
4818 reply_outbuf(req, 1, 0);
4820 if (numtowrite != 0) {
4822 if (numtowrite > 0xFFFF) {
4823 DEBUG(0,("reply_writebraw: Oversize secondary write "
4824 "raw requested (%u). Terminating\n",
4825 (unsigned int)numtowrite ));
4826 exit_server_cleanly("secondary writebraw failed");
4829 if (tcount > nwritten+numtowrite) {
4830 DEBUG(3,("reply_writebraw: Client overestimated the "
4832 (int)tcount,(int)nwritten,(int)numtowrite));
4835 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4838 if (!NT_STATUS_IS_OK(status)) {
4839 /* Try and give an error message
4840 * saying what client failed. */
4841 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4842 "raw read failed (%s) for client %s. "
4843 "Terminating\n", nt_errstr(status),
4844 smbXsrv_connection_dbg(xconn)));
4845 exit_server_cleanly("secondary writebraw failed");
4849 * We are not vulnerable to CVE-2017-12163
4850 * here as we are guaranteed to have numtowrite
4851 * bytes available - we just read from the client.
4853 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4854 if (nwritten == -1) {
4856 reply_nterror(req, map_nt_error_from_unix(errno));
4857 error_to_writebrawerr(req);
4861 if (nwritten < (ssize_t)numtowrite) {
4862 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4863 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4867 total_written += nwritten;
4872 SSVAL(req->outbuf,smb_vwv0,total_written);
4874 status = sync_file(conn, fsp, write_through);
4875 if (!NT_STATUS_IS_OK(status)) {
4876 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4877 fsp_str_dbg(fsp), nt_errstr(status)));
4878 reply_nterror(req, status);
4879 error_to_writebrawerr(req);
4883 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4885 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4886 (int)total_written));
4888 /* We won't return a status if write through is not selected - this
4889 * follows what WfWg does */
4890 END_PROFILE(SMBwritebraw);
4892 if (!write_through && total_written==tcount) {
4894 #if RABBIT_PELLET_FIX
4896 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4897 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4900 if (!send_keepalive(xconn->transport.sock)) {
4901 exit_server_cleanly("reply_writebraw: send of "
4902 "keepalive failed");
4905 TALLOC_FREE(req->outbuf);
4910 END_PROFILE(SMBwritebraw);
4915 #define DBGC_CLASS DBGC_LOCKING
4917 /****************************************************************************
4918 Reply to a writeunlock (core+).
4919 ****************************************************************************/
4921 void reply_writeunlock(struct smb_request *req)
4923 connection_struct *conn = req->conn;
4924 ssize_t nwritten = -1;
4929 NTSTATUS status = NT_STATUS_OK;
4931 struct lock_struct lock;
4932 int saved_errno = 0;
4934 START_PROFILE(SMBwriteunlock);
4937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4938 END_PROFILE(SMBwriteunlock);
4942 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4944 if (!check_fsp(conn, req, fsp)) {
4945 END_PROFILE(SMBwriteunlock);
4949 if (!CHECK_WRITE(fsp)) {
4950 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4951 END_PROFILE(SMBwriteunlock);
4955 numtowrite = SVAL(req->vwv+1, 0);
4956 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4957 data = (const char *)req->buf + 3;
4960 * Ensure client isn't asking us to write more than
4961 * they sent. CVE-2017-12163.
4963 remaining = smbreq_bufrem(req, data);
4964 if (numtowrite > remaining) {
4965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4966 END_PROFILE(SMBwriteunlock);
4970 if (!fsp->print_file && numtowrite > 0) {
4971 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4972 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4975 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4976 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4977 END_PROFILE(SMBwriteunlock);
4982 /* The special X/Open SMB protocol handling of
4983 zero length writes is *NOT* done for
4985 if(numtowrite == 0) {
4988 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4989 saved_errno = errno;
4992 status = sync_file(conn, fsp, False /* write through */);
4993 if (!NT_STATUS_IS_OK(status)) {
4994 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4995 fsp_str_dbg(fsp), nt_errstr(status)));
4996 reply_nterror(req, status);
5001 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5005 if((nwritten < numtowrite) && (numtowrite != 0)) {
5006 reply_nterror(req, NT_STATUS_DISK_FULL);
5010 if (numtowrite && !fsp->print_file) {
5011 struct smbd_lock_element l = {
5012 .req_guid = smbd_request_guid(req, 0),
5013 .smblctx = req->smbpid,
5014 .brltype = UNLOCK_LOCK,
5016 .count = numtowrite,
5018 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5019 if (NT_STATUS_V(status)) {
5020 reply_nterror(req, status);
5025 reply_outbuf(req, 1, 0);
5027 SSVAL(req->outbuf,smb_vwv0,nwritten);
5029 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5030 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5033 END_PROFILE(SMBwriteunlock);
5038 #define DBGC_CLASS DBGC_ALL
5040 /****************************************************************************
5042 ****************************************************************************/
5044 void reply_write(struct smb_request *req)
5046 connection_struct *conn = req->conn;
5049 ssize_t nwritten = -1;
5053 struct lock_struct lock;
5055 int saved_errno = 0;
5057 START_PROFILE(SMBwrite);
5060 END_PROFILE(SMBwrite);
5061 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5065 /* If it's an IPC, pass off the pipe handler. */
5067 reply_pipe_write(req);
5068 END_PROFILE(SMBwrite);
5072 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5074 if (!check_fsp(conn, req, fsp)) {
5075 END_PROFILE(SMBwrite);
5079 if (!CHECK_WRITE(fsp)) {
5080 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5081 END_PROFILE(SMBwrite);
5085 numtowrite = SVAL(req->vwv+1, 0);
5086 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5087 data = (const char *)req->buf + 3;
5090 * Ensure client isn't asking us to write more than
5091 * they sent. CVE-2017-12163.
5093 remaining = smbreq_bufrem(req, data);
5094 if (numtowrite > remaining) {
5095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5096 END_PROFILE(SMBwrite);
5100 if (!fsp->print_file) {
5101 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5102 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5105 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5106 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5107 END_PROFILE(SMBwrite);
5113 * X/Open SMB protocol says that if smb_vwv1 is
5114 * zero then the file size should be extended or
5115 * truncated to the size given in smb_vwv[2-3].
5118 if(numtowrite == 0) {
5120 * This is actually an allocate call, and set EOF. JRA.
5122 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5124 reply_nterror(req, NT_STATUS_DISK_FULL);
5127 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5129 reply_nterror(req, NT_STATUS_DISK_FULL);
5132 trigger_write_time_update_immediate(fsp);
5134 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5137 status = sync_file(conn, fsp, False);
5138 if (!NT_STATUS_IS_OK(status)) {
5139 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5140 fsp_str_dbg(fsp), nt_errstr(status)));
5141 reply_nterror(req, status);
5146 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5150 if((nwritten == 0) && (numtowrite != 0)) {
5151 reply_nterror(req, NT_STATUS_DISK_FULL);
5155 reply_outbuf(req, 1, 0);
5157 SSVAL(req->outbuf,smb_vwv0,nwritten);
5159 if (nwritten < (ssize_t)numtowrite) {
5160 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5161 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5164 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5167 END_PROFILE(SMBwrite);
5171 /****************************************************************************
5172 Ensure a buffer is a valid writeX for recvfile purposes.
5173 ****************************************************************************/
5175 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5176 (2*14) + /* word count (including bcc) */ \
5179 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5180 const uint8_t *inbuf)
5183 unsigned int doff = 0;
5184 size_t len = smb_len_large(inbuf);
5186 struct smbXsrv_open *op = NULL;
5187 struct files_struct *fsp = NULL;
5190 if (is_encrypted_packet(inbuf)) {
5191 /* Can't do this on encrypted
5196 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5200 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5201 CVAL(inbuf,smb_wct) != 14) {
5202 DEBUG(10,("is_valid_writeX_buffer: chained or "
5203 "invalid word length.\n"));
5207 fnum = SVAL(inbuf, smb_vwv2);
5208 status = smb1srv_open_lookup(xconn,
5212 if (!NT_STATUS_IS_OK(status)) {
5213 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5218 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5221 if (fsp->conn == NULL) {
5222 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5226 if (IS_IPC(fsp->conn)) {
5227 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5230 if (IS_PRINT(fsp->conn)) {
5231 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5234 if (fsp->base_fsp != NULL) {
5235 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5238 doff = SVAL(inbuf,smb_vwv11);
5240 numtowrite = SVAL(inbuf,smb_vwv10);
5242 if (len > doff && len - doff > 0xFFFF) {
5243 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5246 if (numtowrite == 0) {
5247 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5251 /* Ensure the sizes match up. */
5252 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5253 /* no pad byte...old smbclient :-( */
5254 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5256 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5260 if (len - doff != numtowrite) {
5261 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5262 "len = %u, doff = %u, numtowrite = %u\n",
5265 (unsigned int)numtowrite ));
5269 DEBUG(10,("is_valid_writeX_buffer: true "
5270 "len = %u, doff = %u, numtowrite = %u\n",
5273 (unsigned int)numtowrite ));
5278 /****************************************************************************
5279 Reply to a write and X.
5280 ****************************************************************************/
5282 void reply_write_and_X(struct smb_request *req)
5284 connection_struct *conn = req->conn;
5285 struct smbXsrv_connection *xconn = req->xconn;
5287 struct lock_struct lock;
5292 unsigned int smb_doff;
5293 unsigned int smblen;
5296 int saved_errno = 0;
5298 START_PROFILE(SMBwriteX);
5300 if ((req->wct != 12) && (req->wct != 14)) {
5301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5305 numtowrite = SVAL(req->vwv+10, 0);
5306 smb_doff = SVAL(req->vwv+11, 0);
5307 smblen = smb_len(req->inbuf);
5309 if (req->unread_bytes > 0xFFFF ||
5310 (smblen > smb_doff &&
5311 smblen - smb_doff > 0xFFFF)) {
5312 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5315 if (req->unread_bytes) {
5316 /* Can't do a recvfile write on IPC$ */
5318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5321 if (numtowrite != req->unread_bytes) {
5322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5327 * This already protects us against CVE-2017-12163.
5329 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5330 smb_doff + numtowrite > smblen) {
5331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5336 /* If it's an IPC, pass off the pipe handler. */
5338 if (req->unread_bytes) {
5339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5342 reply_pipe_write_and_X(req);
5346 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5347 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5348 write_through = BITSETW(req->vwv+7,0);
5350 if (!check_fsp(conn, req, fsp)) {
5354 if (!CHECK_WRITE(fsp)) {
5355 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5359 data = smb_base(req->inbuf) + smb_doff;
5361 if(req->wct == 14) {
5363 * This is a large offset (64 bit) write.
5365 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5369 /* X/Open SMB protocol says that, unlike SMBwrite
5370 if the length is zero then NO truncation is
5371 done, just a write of zero. To truncate a file,
5374 if(numtowrite == 0) {
5377 if (req->unread_bytes == 0) {
5378 status = schedule_aio_write_and_X(conn,
5385 if (NT_STATUS_IS_OK(status)) {
5386 /* write scheduled - we're done. */
5389 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5390 /* Real error - report to client. */
5391 reply_nterror(req, status);
5394 /* NT_STATUS_RETRY - fall through to sync write. */
5397 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5398 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5401 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5402 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5406 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5407 saved_errno = errno;
5411 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5415 if((nwritten == 0) && (numtowrite != 0)) {
5416 reply_nterror(req, NT_STATUS_DISK_FULL);
5420 reply_outbuf(req, 6, 0);
5421 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5422 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5423 SSVAL(req->outbuf,smb_vwv2,nwritten);
5424 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5426 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5427 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5429 status = sync_file(conn, fsp, write_through);
5430 if (!NT_STATUS_IS_OK(status)) {
5431 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5432 fsp_str_dbg(fsp), nt_errstr(status)));
5433 reply_nterror(req, status);
5437 END_PROFILE(SMBwriteX);
5441 if (req->unread_bytes) {
5442 /* writeX failed. drain socket. */
5443 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5444 req->unread_bytes) {
5445 smb_panic("failed to drain pending bytes");
5447 req->unread_bytes = 0;
5450 END_PROFILE(SMBwriteX);
5454 /****************************************************************************
5456 ****************************************************************************/
5458 void reply_lseek(struct smb_request *req)
5460 connection_struct *conn = req->conn;
5467 START_PROFILE(SMBlseek);
5470 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5471 END_PROFILE(SMBlseek);
5475 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5477 if (!check_fsp(conn, req, fsp)) {
5481 mode = SVAL(req->vwv+1, 0) & 3;
5482 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5483 startpos = (off_t)IVALS(req->vwv+2, 0);
5492 res = fsp->fh->pos + startpos;
5503 if (umode == SEEK_END) {
5504 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5505 if(errno == EINVAL) {
5506 off_t current_pos = startpos;
5508 status = vfs_stat_fsp(fsp);
5509 if (!NT_STATUS_IS_OK(status)) {
5510 reply_nterror(req, status);
5511 END_PROFILE(SMBlseek);
5515 current_pos += fsp->fsp_name->st.st_ex_size;
5517 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5522 reply_nterror(req, map_nt_error_from_unix(errno));
5523 END_PROFILE(SMBlseek);
5530 reply_outbuf(req, 2, 0);
5531 SIVAL(req->outbuf,smb_vwv0,res);
5533 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5534 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5536 END_PROFILE(SMBlseek);
5540 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5543 connection_struct *conn = talloc_get_type_abort(
5544 private_data, connection_struct);
5546 if (conn != fsp->conn) {
5549 if (fsp->fh->fd == -1) {
5552 sync_file(conn, fsp, True /* write through */);
5557 /****************************************************************************
5559 ****************************************************************************/
5561 void reply_flush(struct smb_request *req)
5563 connection_struct *conn = req->conn;
5567 START_PROFILE(SMBflush);
5570 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5574 fnum = SVAL(req->vwv+0, 0);
5575 fsp = file_fsp(req, fnum);
5577 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5582 files_forall(req->sconn, file_sync_one_fn, conn);
5584 NTSTATUS status = sync_file(conn, fsp, True);
5585 if (!NT_STATUS_IS_OK(status)) {
5586 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5587 fsp_str_dbg(fsp), nt_errstr(status)));
5588 reply_nterror(req, status);
5589 END_PROFILE(SMBflush);
5594 reply_outbuf(req, 0, 0);
5596 DEBUG(3,("flush\n"));
5597 END_PROFILE(SMBflush);
5601 /****************************************************************************
5603 conn POINTER CAN BE NULL HERE !
5604 ****************************************************************************/
5606 void reply_exit(struct smb_request *req)
5608 START_PROFILE(SMBexit);
5610 file_close_pid(req->sconn, req->smbpid, req->vuid);
5612 reply_outbuf(req, 0, 0);
5614 DEBUG(3,("exit\n"));
5616 END_PROFILE(SMBexit);
5620 struct reply_close_state {
5622 struct smb_request *smbreq;
5625 static void do_smb1_close(struct tevent_req *req);
5627 void reply_close(struct smb_request *req)
5629 connection_struct *conn = req->conn;
5630 NTSTATUS status = NT_STATUS_OK;
5631 files_struct *fsp = NULL;
5632 START_PROFILE(SMBclose);
5635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5636 END_PROFILE(SMBclose);
5640 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5643 * We can only use check_fsp if we know it's not a directory.
5646 if (!check_fsp_open(conn, req, fsp)) {
5647 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5648 END_PROFILE(SMBclose);
5652 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5653 fsp->is_directory ? "directory" : "file",
5654 fsp->fh->fd, fsp_fnum_dbg(fsp),
5655 conn->num_files_open));
5657 if (!fsp->is_directory) {
5661 * Take care of any time sent in the close.
5664 t = srv_make_unix_date3(req->vwv+1);
5665 set_close_write_time(fsp, time_t_to_full_timespec(t));
5668 if (fsp->num_aio_requests != 0) {
5670 struct reply_close_state *state;
5672 DEBUG(10, ("closing with aio %u requests pending\n",
5673 fsp->num_aio_requests));
5676 * We depend on the aio_extra destructor to take care of this
5677 * close request once fsp->num_aio_request drops to 0.
5680 fsp->deferred_close = tevent_wait_send(
5681 fsp, fsp->conn->sconn->ev_ctx);
5682 if (fsp->deferred_close == NULL) {
5683 status = NT_STATUS_NO_MEMORY;
5687 state = talloc(fsp, struct reply_close_state);
5688 if (state == NULL) {
5689 TALLOC_FREE(fsp->deferred_close);
5690 status = NT_STATUS_NO_MEMORY;
5694 state->smbreq = talloc_move(fsp, &req);
5695 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5697 END_PROFILE(SMBclose);
5702 * close_file() returns the unix errno if an error was detected on
5703 * close - normally this is due to a disk full error. If not then it
5704 * was probably an I/O error.
5707 status = close_file(req, fsp, NORMAL_CLOSE);
5709 if (!NT_STATUS_IS_OK(status)) {
5710 reply_nterror(req, status);
5711 END_PROFILE(SMBclose);
5715 reply_outbuf(req, 0, 0);
5716 END_PROFILE(SMBclose);
5720 static void do_smb1_close(struct tevent_req *req)
5722 struct reply_close_state *state = tevent_req_callback_data(
5723 req, struct reply_close_state);
5724 struct smb_request *smbreq;
5728 ret = tevent_wait_recv(req);
5731 DEBUG(10, ("tevent_wait_recv returned %s\n",
5734 * Continue anyway, this should never happen
5739 * fsp->smb2_close_request right now is a talloc grandchild of
5740 * fsp. When we close_file(fsp), it would go with it. No chance to
5743 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5745 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5746 if (NT_STATUS_IS_OK(status)) {
5747 reply_outbuf(smbreq, 0, 0);
5749 reply_nterror(smbreq, status);
5751 if (!srv_send_smb(smbreq->xconn,
5752 (char *)smbreq->outbuf,
5755 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5757 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5760 TALLOC_FREE(smbreq);
5763 /****************************************************************************
5764 Reply to a writeclose (Core+ protocol).
5765 ****************************************************************************/
5767 void reply_writeclose(struct smb_request *req)
5769 connection_struct *conn = req->conn;
5772 ssize_t nwritten = -1;
5773 NTSTATUS close_status = NT_STATUS_OK;
5776 struct timespec mtime;
5778 struct lock_struct lock;
5780 START_PROFILE(SMBwriteclose);
5783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5784 END_PROFILE(SMBwriteclose);
5788 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5790 if (!check_fsp(conn, req, fsp)) {
5791 END_PROFILE(SMBwriteclose);
5794 if (!CHECK_WRITE(fsp)) {
5795 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5796 END_PROFILE(SMBwriteclose);
5800 numtowrite = SVAL(req->vwv+1, 0);
5801 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5802 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
5803 data = (const char *)req->buf + 1;
5806 * Ensure client isn't asking us to write more than
5807 * they sent. CVE-2017-12163.
5809 remaining = smbreq_bufrem(req, data);
5810 if (numtowrite > remaining) {
5811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5812 END_PROFILE(SMBwriteclose);
5816 if (fsp->print_file == NULL) {
5817 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5818 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5821 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5822 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5823 END_PROFILE(SMBwriteclose);
5828 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5830 set_close_write_time(fsp, mtime);
5833 * More insanity. W2K only closes the file if writelen > 0.
5837 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5838 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5839 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5842 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5843 "file %s\n", fsp_str_dbg(fsp)));
5844 close_status = close_file(req, fsp, NORMAL_CLOSE);
5848 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5849 reply_nterror(req, NT_STATUS_DISK_FULL);
5853 if(!NT_STATUS_IS_OK(close_status)) {
5854 reply_nterror(req, close_status);
5858 reply_outbuf(req, 1, 0);
5860 SSVAL(req->outbuf,smb_vwv0,nwritten);
5864 END_PROFILE(SMBwriteclose);
5869 #define DBGC_CLASS DBGC_LOCKING
5871 /****************************************************************************
5873 ****************************************************************************/
5875 static void reply_lock_done(struct tevent_req *subreq);
5877 void reply_lock(struct smb_request *req)
5879 struct tevent_req *subreq = NULL;
5880 connection_struct *conn = req->conn;
5882 struct smbd_lock_element *lck = NULL;
5884 START_PROFILE(SMBlock);
5887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5888 END_PROFILE(SMBlock);
5892 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5894 if (!check_fsp(conn, req, fsp)) {
5895 END_PROFILE(SMBlock);
5899 lck = talloc(req, struct smbd_lock_element);
5901 reply_nterror(req, NT_STATUS_NO_MEMORY);
5902 END_PROFILE(SMBlock);
5906 *lck = (struct smbd_lock_element) {
5907 .req_guid = smbd_request_guid(req, 0),
5908 .smblctx = req->smbpid,
5909 .brltype = WRITE_LOCK,
5910 .count = IVAL(req->vwv+1, 0),
5911 .offset = IVAL(req->vwv+3, 0),
5914 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5920 subreq = smbd_smb1_do_locks_send(
5926 false, /* large_offset */
5930 if (subreq == NULL) {
5931 reply_nterror(req, NT_STATUS_NO_MEMORY);
5932 END_PROFILE(SMBlock);
5935 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5936 END_PROFILE(SMBlock);
5939 static void reply_lock_done(struct tevent_req *subreq)
5941 struct smb_request *req = NULL;
5945 START_PROFILE(SMBlock);
5947 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5950 status = smbd_smb1_do_locks_recv(subreq);
5951 TALLOC_FREE(subreq);
5953 if (NT_STATUS_IS_OK(status)) {
5954 reply_outbuf(req, 0, 0);
5956 reply_nterror(req, status);
5959 ok = srv_send_smb(req->xconn,
5960 (char *)req->outbuf,
5963 IS_CONN_ENCRYPTED(req->conn),
5966 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
5969 END_PROFILE(SMBlock);
5972 /****************************************************************************
5974 ****************************************************************************/
5976 void reply_unlock(struct smb_request *req)
5978 connection_struct *conn = req->conn;
5981 struct smbd_lock_element lck;
5983 START_PROFILE(SMBunlock);
5986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5987 END_PROFILE(SMBunlock);
5991 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5993 if (!check_fsp(conn, req, fsp)) {
5994 END_PROFILE(SMBunlock);
5998 lck = (struct smbd_lock_element) {
5999 .req_guid = smbd_request_guid(req, 0),
6000 .smblctx = req->smbpid,
6001 .brltype = UNLOCK_LOCK,
6002 .offset = IVAL(req->vwv+3, 0),
6003 .count = IVAL(req->vwv+1, 0),
6006 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6008 if (!NT_STATUS_IS_OK(status)) {
6009 reply_nterror(req, status);
6010 END_PROFILE(SMBunlock);
6014 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6020 reply_outbuf(req, 0, 0);
6022 END_PROFILE(SMBunlock);
6027 #define DBGC_CLASS DBGC_ALL
6029 /****************************************************************************
6031 conn POINTER CAN BE NULL HERE !
6032 ****************************************************************************/
6034 void reply_tdis(struct smb_request *req)
6037 connection_struct *conn = req->conn;
6038 struct smbXsrv_tcon *tcon;
6040 START_PROFILE(SMBtdis);
6043 DEBUG(4,("Invalid connection in tdis\n"));
6044 reply_force_doserror(req, ERRSRV, ERRinvnid);
6045 END_PROFILE(SMBtdis);
6053 * TODO: cancel all outstanding requests on the tcon
6055 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
6056 if (!NT_STATUS_IS_OK(status)) {
6057 DEBUG(0, ("reply_tdis: "
6058 "smbXsrv_tcon_disconnect() failed: %s\n",
6059 nt_errstr(status)));
6061 * If we hit this case, there is something completely
6062 * wrong, so we better disconnect the transport connection.
6064 END_PROFILE(SMBtdis);
6065 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6071 reply_outbuf(req, 0, 0);
6072 END_PROFILE(SMBtdis);
6076 /****************************************************************************
6078 conn POINTER CAN BE NULL HERE !
6079 ****************************************************************************/
6081 void reply_echo(struct smb_request *req)
6083 connection_struct *conn = req->conn;
6084 struct smb_perfcount_data local_pcd;
6085 struct smb_perfcount_data *cur_pcd;
6089 START_PROFILE(SMBecho);
6091 smb_init_perfcount_data(&local_pcd);
6094 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6095 END_PROFILE(SMBecho);
6099 smb_reverb = SVAL(req->vwv+0, 0);
6101 reply_outbuf(req, 1, req->buflen);
6103 /* copy any incoming data back out */
6104 if (req->buflen > 0) {
6105 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6108 if (smb_reverb > 100) {
6109 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6113 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6115 /* this makes sure we catch the request pcd */
6116 if (seq_num == smb_reverb) {
6117 cur_pcd = &req->pcd;
6119 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6120 cur_pcd = &local_pcd;
6123 SSVAL(req->outbuf,smb_vwv0,seq_num);
6125 show_msg((char *)req->outbuf);
6126 if (!srv_send_smb(req->xconn,
6127 (char *)req->outbuf,
6128 true, req->seqnum+1,
6129 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6131 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6134 DEBUG(3,("echo %d times\n", smb_reverb));
6136 TALLOC_FREE(req->outbuf);
6138 END_PROFILE(SMBecho);
6142 /****************************************************************************
6143 Reply to a printopen.
6144 ****************************************************************************/
6146 void reply_printopen(struct smb_request *req)
6148 connection_struct *conn = req->conn;
6152 START_PROFILE(SMBsplopen);
6155 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6156 END_PROFILE(SMBsplopen);
6160 if (!CAN_PRINT(conn)) {
6161 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6162 END_PROFILE(SMBsplopen);
6166 status = file_new(req, conn, &fsp);
6167 if(!NT_STATUS_IS_OK(status)) {
6168 reply_nterror(req, status);
6169 END_PROFILE(SMBsplopen);
6173 /* Open for exclusive use, write only. */
6174 status = print_spool_open(fsp, NULL, req->vuid);
6176 if (!NT_STATUS_IS_OK(status)) {
6177 file_free(req, fsp);
6178 reply_nterror(req, status);
6179 END_PROFILE(SMBsplopen);
6183 reply_outbuf(req, 1, 0);
6184 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6186 DEBUG(3,("openprint fd=%d %s\n",
6187 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6189 END_PROFILE(SMBsplopen);
6193 /****************************************************************************
6194 Reply to a printclose.
6195 ****************************************************************************/
6197 void reply_printclose(struct smb_request *req)
6199 connection_struct *conn = req->conn;
6203 START_PROFILE(SMBsplclose);
6206 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6207 END_PROFILE(SMBsplclose);
6211 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6213 if (!check_fsp(conn, req, fsp)) {
6214 END_PROFILE(SMBsplclose);
6218 if (!CAN_PRINT(conn)) {
6219 reply_force_doserror(req, ERRSRV, ERRerror);
6220 END_PROFILE(SMBsplclose);
6224 DEBUG(3,("printclose fd=%d %s\n",
6225 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6227 status = close_file(req, fsp, NORMAL_CLOSE);
6229 if(!NT_STATUS_IS_OK(status)) {
6230 reply_nterror(req, status);
6231 END_PROFILE(SMBsplclose);
6235 reply_outbuf(req, 0, 0);
6237 END_PROFILE(SMBsplclose);
6241 /****************************************************************************
6242 Reply to a printqueue.
6243 ****************************************************************************/
6245 void reply_printqueue(struct smb_request *req)
6247 const struct loadparm_substitution *lp_sub =
6248 loadparm_s3_global_substitution();
6249 connection_struct *conn = req->conn;
6253 START_PROFILE(SMBsplretq);
6256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6257 END_PROFILE(SMBsplretq);
6261 max_count = SVAL(req->vwv+0, 0);
6262 start_index = SVAL(req->vwv+1, 0);
6264 /* we used to allow the client to get the cnum wrong, but that
6265 is really quite gross and only worked when there was only
6266 one printer - I think we should now only accept it if they
6267 get it right (tridge) */
6268 if (!CAN_PRINT(conn)) {
6269 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6270 END_PROFILE(SMBsplretq);
6274 reply_outbuf(req, 2, 3);
6275 SSVAL(req->outbuf,smb_vwv0,0);
6276 SSVAL(req->outbuf,smb_vwv1,0);
6277 SCVAL(smb_buf(req->outbuf),0,1);
6278 SSVAL(smb_buf(req->outbuf),1,0);
6280 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6281 start_index, max_count));
6284 TALLOC_CTX *mem_ctx = talloc_tos();
6287 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6288 struct rpc_pipe_client *cli = NULL;
6289 struct dcerpc_binding_handle *b = NULL;
6290 struct policy_handle handle;
6291 struct spoolss_DevmodeContainer devmode_ctr;
6292 union spoolss_JobInfo *info;
6294 uint32_t num_to_get;
6298 ZERO_STRUCT(handle);
6300 status = rpc_pipe_open_interface(mem_ctx,
6303 conn->sconn->remote_address,
6304 conn->sconn->local_address,
6305 conn->sconn->msg_ctx,
6307 if (!NT_STATUS_IS_OK(status)) {
6308 DEBUG(0, ("reply_printqueue: "
6309 "could not connect to spoolss: %s\n",
6310 nt_errstr(status)));
6311 reply_nterror(req, status);
6314 b = cli->binding_handle;
6316 ZERO_STRUCT(devmode_ctr);
6318 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6321 SEC_FLAG_MAXIMUM_ALLOWED,
6324 if (!NT_STATUS_IS_OK(status)) {
6325 reply_nterror(req, status);
6328 if (!W_ERROR_IS_OK(werr)) {
6329 reply_nterror(req, werror_to_ntstatus(werr));
6333 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6341 if (!W_ERROR_IS_OK(werr)) {
6342 reply_nterror(req, werror_to_ntstatus(werr));
6346 if (max_count > 0) {
6347 first = start_index;
6349 first = start_index + max_count + 1;
6352 if (first >= count) {
6355 num_to_get = first + MIN(ABS(max_count), count - first);
6358 for (i = first; i < num_to_get; i++) {
6361 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6364 uint16_t qrapjobid = pjobid_to_rap(sharename,
6365 info[i].info2.job_id);
6367 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6373 srv_put_dos_date2(p, 0, qtime);
6374 SCVAL(p, 4, qstatus);
6375 SSVAL(p, 5, qrapjobid);
6376 SIVAL(p, 7, info[i].info2.size);
6378 status = srvstr_push(blob, req->flags2, p+12,
6379 info[i].info2.notify_name, 16, STR_ASCII, &len);
6380 if (!NT_STATUS_IS_OK(status)) {
6381 reply_nterror(req, status);
6384 if (message_push_blob(
6387 blob, sizeof(blob))) == -1) {
6388 reply_nterror(req, NT_STATUS_NO_MEMORY);
6394 SSVAL(req->outbuf,smb_vwv0,count);
6395 SSVAL(req->outbuf,smb_vwv1,
6396 (max_count>0?first+count:first-1));
6397 SCVAL(smb_buf(req->outbuf),0,1);
6398 SSVAL(smb_buf(req->outbuf),1,28*count);
6402 DEBUG(3, ("%u entries returned in queue\n",
6406 if (b && is_valid_policy_hnd(&handle)) {
6407 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6412 END_PROFILE(SMBsplretq);
6416 /****************************************************************************
6417 Reply to a printwrite.
6418 ****************************************************************************/
6420 void reply_printwrite(struct smb_request *req)
6422 connection_struct *conn = req->conn;
6427 START_PROFILE(SMBsplwr);
6430 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6431 END_PROFILE(SMBsplwr);
6435 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6437 if (!check_fsp(conn, req, fsp)) {
6438 END_PROFILE(SMBsplwr);
6442 if (!fsp->print_file) {
6443 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6444 END_PROFILE(SMBsplwr);
6448 if (!CHECK_WRITE(fsp)) {
6449 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6450 END_PROFILE(SMBsplwr);
6454 numtowrite = SVAL(req->buf, 1);
6457 * This already protects us against CVE-2017-12163.
6459 if (req->buflen < numtowrite + 3) {
6460 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6461 END_PROFILE(SMBsplwr);
6465 data = (const char *)req->buf + 3;
6467 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6468 reply_nterror(req, map_nt_error_from_unix(errno));
6469 END_PROFILE(SMBsplwr);
6473 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6475 END_PROFILE(SMBsplwr);
6479 /****************************************************************************
6481 ****************************************************************************/
6483 void reply_mkdir(struct smb_request *req)
6485 connection_struct *conn = req->conn;
6486 struct smb_filename *smb_dname = NULL;
6487 char *directory = NULL;
6490 TALLOC_CTX *ctx = talloc_tos();
6492 START_PROFILE(SMBmkdir);
6494 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6495 STR_TERMINATE, &status);
6496 if (!NT_STATUS_IS_OK(status)) {
6497 reply_nterror(req, status);
6501 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6502 status = filename_convert(ctx, conn,
6508 if (!NT_STATUS_IS_OK(status)) {
6509 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6510 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6511 ERRSRV, ERRbadpath);
6514 reply_nterror(req, status);
6518 status = create_directory(conn, req, smb_dname);
6520 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6522 if (!NT_STATUS_IS_OK(status)) {
6524 if (!use_nt_status()
6525 && NT_STATUS_EQUAL(status,
6526 NT_STATUS_OBJECT_NAME_COLLISION)) {
6528 * Yes, in the DOS error code case we get a
6529 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6530 * samba4 torture test.
6532 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6535 reply_nterror(req, status);
6539 reply_outbuf(req, 0, 0);
6541 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6543 TALLOC_FREE(smb_dname);
6544 END_PROFILE(SMBmkdir);
6548 /****************************************************************************
6550 ****************************************************************************/
6552 void reply_rmdir(struct smb_request *req)
6554 connection_struct *conn = req->conn;
6555 struct smb_filename *smb_dname = NULL;
6556 char *directory = NULL;
6558 TALLOC_CTX *ctx = talloc_tos();
6559 files_struct *fsp = NULL;
6561 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6563 START_PROFILE(SMBrmdir);
6565 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6566 STR_TERMINATE, &status);
6567 if (!NT_STATUS_IS_OK(status)) {
6568 reply_nterror(req, status);
6572 status = filename_convert(ctx, conn,
6578 if (!NT_STATUS_IS_OK(status)) {
6579 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6580 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6581 ERRSRV, ERRbadpath);
6584 reply_nterror(req, status);
6588 if (is_ntfs_stream_smb_fname(smb_dname)) {
6589 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6593 status = SMB_VFS_CREATE_FILE(
6596 0, /* root_dir_fid */
6597 smb_dname, /* fname */
6598 DELETE_ACCESS, /* access_mask */
6599 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6601 FILE_OPEN, /* create_disposition*/
6602 FILE_DIRECTORY_FILE, /* create_options */
6603 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6604 0, /* oplock_request */
6606 0, /* allocation_size */
6607 0, /* private_flags */
6612 NULL, NULL); /* create context */
6614 if (!NT_STATUS_IS_OK(status)) {
6615 if (open_was_deferred(req->xconn, req->mid)) {
6616 /* We have re-scheduled this call. */
6619 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6620 bool ok = defer_smb1_sharing_violation(req);
6625 reply_nterror(req, status);
6629 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6630 if (!NT_STATUS_IS_OK(status)) {
6631 close_file(req, fsp, ERROR_CLOSE);
6632 reply_nterror(req, status);
6636 if (!set_delete_on_close(fsp, true,
6637 conn->session_info->security_token,
6638 conn->session_info->unix_token)) {
6639 close_file(req, fsp, ERROR_CLOSE);
6640 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6644 status = close_file(req, fsp, NORMAL_CLOSE);
6645 if (!NT_STATUS_IS_OK(status)) {
6646 reply_nterror(req, status);
6648 reply_outbuf(req, 0, 0);
6651 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6653 TALLOC_FREE(smb_dname);
6654 END_PROFILE(SMBrmdir);
6658 /*******************************************************************
6659 Resolve wildcards in a filename rename.
6660 ********************************************************************/
6662 static bool resolve_wildcards(TALLOC_CTX *ctx,
6667 char *name2_copy = NULL;
6672 char *p,*p2, *pname1, *pname2;
6674 name2_copy = talloc_strdup(ctx, name2);
6679 pname1 = strrchr_m(name1,'/');
6680 pname2 = strrchr_m(name2_copy,'/');
6682 if (!pname1 || !pname2) {
6686 /* Truncate the copy of name2 at the last '/' */
6689 /* Now go past the '/' */
6693 root1 = talloc_strdup(ctx, pname1);
6694 root2 = talloc_strdup(ctx, pname2);
6696 if (!root1 || !root2) {
6700 p = strrchr_m(root1,'.');
6703 ext1 = talloc_strdup(ctx, p+1);
6705 ext1 = talloc_strdup(ctx, "");
6707 p = strrchr_m(root2,'.');
6710 ext2 = talloc_strdup(ctx, p+1);
6712 ext2 = talloc_strdup(ctx, "");
6715 if (!ext1 || !ext2) {
6723 /* Hmmm. Should this be mb-aware ? */
6726 } else if (*p2 == '*') {
6728 root2 = talloc_asprintf(ctx, "%s%s",
6747 /* Hmmm. Should this be mb-aware ? */
6750 } else if (*p2 == '*') {
6752 ext2 = talloc_asprintf(ctx, "%s%s",
6768 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6773 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6785 /****************************************************************************
6786 Ensure open files have their names updated. Updated to notify other smbd's
6788 ****************************************************************************/
6790 static void rename_open_files(connection_struct *conn,
6791 struct share_mode_lock *lck,
6793 uint32_t orig_name_hash,
6794 const struct smb_filename *smb_fname_dst)
6797 bool did_rename = False;
6799 uint32_t new_name_hash = 0;
6801 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6802 fsp = file_find_di_next(fsp)) {
6803 struct file_id_buf idbuf;
6804 /* fsp_name is a relative path under the fsp. To change this for other
6805 sharepaths we need to manipulate relative paths. */
6806 /* TODO - create the absolute path and manipulate the newname
6807 relative to the sharepath. */
6808 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6811 if (fsp->name_hash != orig_name_hash) {
6814 DBG_DEBUG("renaming file %s "
6815 "(file_id %s) from %s -> %s\n",
6817 file_id_str_buf(fsp->file_id, &idbuf),
6819 smb_fname_str_dbg(smb_fname_dst));
6821 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6822 if (NT_STATUS_IS_OK(status)) {
6824 new_name_hash = fsp->name_hash;
6829 struct file_id_buf idbuf;
6830 DBG_DEBUG("no open files on file_id %s "
6832 file_id_str_buf(id, &idbuf),
6833 smb_fname_str_dbg(smb_fname_dst));
6836 /* Send messages to all smbd's (not ourself) that the name has changed. */
6837 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6838 orig_name_hash, new_name_hash,
6843 /****************************************************************************
6844 We need to check if the source path is a parent directory of the destination
6845 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6846 refuse the rename with a sharing violation. Under UNIX the above call can
6847 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6848 probably need to check that the client is a Windows one before disallowing
6849 this as a UNIX client (one with UNIX extensions) can know the source is a
6850 symlink and make this decision intelligently. Found by an excellent bug
6851 report from <AndyLiebman@aol.com>.
6852 ****************************************************************************/
6854 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6855 const struct smb_filename *smb_fname_dst)
6857 const char *psrc = smb_fname_src->base_name;
6858 const char *pdst = smb_fname_dst->base_name;
6861 if (psrc[0] == '.' && psrc[1] == '/') {
6864 if (pdst[0] == '.' && pdst[1] == '/') {
6867 if ((slen = strlen(psrc)) > strlen(pdst)) {
6870 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6874 * Do the notify calls from a rename
6877 static void notify_rename(connection_struct *conn, bool is_dir,
6878 const struct smb_filename *smb_fname_src,
6879 const struct smb_filename *smb_fname_dst)
6881 char *parent_dir_src = NULL;
6882 char *parent_dir_dst = NULL;
6885 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6886 : FILE_NOTIFY_CHANGE_FILE_NAME;
6888 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6889 &parent_dir_src, NULL) ||
6890 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6891 &parent_dir_dst, NULL)) {
6895 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6896 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6897 smb_fname_src->base_name);
6898 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6899 smb_fname_dst->base_name);
6902 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6903 smb_fname_src->base_name);
6904 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6905 smb_fname_dst->base_name);
6908 /* this is a strange one. w2k3 gives an additional event for
6909 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6910 files, but not directories */
6912 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6913 FILE_NOTIFY_CHANGE_ATTRIBUTES
6914 |FILE_NOTIFY_CHANGE_CREATION,
6915 smb_fname_dst->base_name);
6918 TALLOC_FREE(parent_dir_src);
6919 TALLOC_FREE(parent_dir_dst);
6922 /****************************************************************************
6923 Returns an error if the parent directory for a filename is open in an
6925 ****************************************************************************/
6927 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6928 const struct smb_filename *smb_fname_dst_in)
6930 char *parent_dir = NULL;
6931 struct smb_filename smb_fname_parent;
6933 files_struct *fsp = NULL;
6936 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6937 &parent_dir, NULL)) {
6938 return NT_STATUS_NO_MEMORY;
6940 ZERO_STRUCT(smb_fname_parent);
6941 smb_fname_parent.base_name = parent_dir;
6943 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6945 return map_nt_error_from_unix(errno);
6949 * We're only checking on this smbd here, mostly good
6950 * enough.. and will pass tests.
6953 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6954 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6955 fsp = file_find_di_next(fsp)) {
6956 if (fsp->access_mask & DELETE_ACCESS) {
6957 return NT_STATUS_SHARING_VIOLATION;
6960 return NT_STATUS_OK;
6963 /****************************************************************************
6964 Rename an open file - given an fsp.
6965 ****************************************************************************/
6967 NTSTATUS rename_internals_fsp(connection_struct *conn,
6969 const struct smb_filename *smb_fname_dst_in,
6971 bool replace_if_exists)
6973 TALLOC_CTX *ctx = talloc_tos();
6974 struct smb_filename *smb_fname_dst = NULL;
6975 NTSTATUS status = NT_STATUS_OK;
6976 struct share_mode_lock *lck = NULL;
6977 uint32_t access_mask = SEC_DIR_ADD_FILE;
6978 bool dst_exists, old_is_stream, new_is_stream;
6981 status = check_name(conn, smb_fname_dst_in);
6982 if (!NT_STATUS_IS_OK(status)) {
6986 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6987 if (!NT_STATUS_IS_OK(status)) {
6991 if (file_has_open_streams(fsp)) {
6992 return NT_STATUS_ACCESS_DENIED;
6995 /* Make a copy of the dst smb_fname structs */
6997 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6998 if (smb_fname_dst == NULL) {
6999 status = NT_STATUS_NO_MEMORY;
7004 * Check for special case with case preserving and not
7005 * case sensitive. If the new last component differs from the original
7006 * last component only by case, then we should allow
7007 * the rename (user is trying to change the case of the
7010 if (!conn->case_sensitive && conn->case_preserve &&
7011 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7012 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7013 char *fname_dst_parent = NULL;
7014 const char *fname_dst_lcomp = NULL;
7015 char *orig_lcomp_path = NULL;
7016 char *orig_lcomp_stream = NULL;
7020 * Split off the last component of the processed
7021 * destination name. We will compare this to
7022 * the split components of smb_fname_dst->original_lcomp.
7024 if (!parent_dirname(ctx,
7025 smb_fname_dst->base_name,
7027 &fname_dst_lcomp)) {
7028 status = NT_STATUS_NO_MEMORY;
7033 * The original_lcomp component contains
7034 * the last_component of the path + stream
7035 * name (if a stream exists).
7037 * Split off the stream name so we
7038 * can check them separately.
7041 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7042 /* POSIX - no stream component. */
7043 orig_lcomp_path = talloc_strdup(ctx,
7044 smb_fname_dst->original_lcomp);
7045 if (orig_lcomp_path == NULL) {
7049 ok = split_stream_filename(ctx,
7050 smb_fname_dst->original_lcomp,
7052 &orig_lcomp_stream);
7056 TALLOC_FREE(fname_dst_parent);
7057 status = NT_STATUS_NO_MEMORY;
7061 /* If the base names only differ by case, use original. */
7062 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7065 * Replace the modified last component with the
7068 if (!ISDOT(fname_dst_parent)) {
7069 tmp = talloc_asprintf(smb_fname_dst,
7074 tmp = talloc_strdup(smb_fname_dst,
7078 status = NT_STATUS_NO_MEMORY;
7079 TALLOC_FREE(fname_dst_parent);
7080 TALLOC_FREE(orig_lcomp_path);
7081 TALLOC_FREE(orig_lcomp_stream);
7084 TALLOC_FREE(smb_fname_dst->base_name);
7085 smb_fname_dst->base_name = tmp;
7088 /* If the stream_names only differ by case, use original. */
7089 if(!strcsequal(smb_fname_dst->stream_name,
7090 orig_lcomp_stream)) {
7091 /* Use the original stream. */
7092 char *tmp = talloc_strdup(smb_fname_dst,
7095 status = NT_STATUS_NO_MEMORY;
7096 TALLOC_FREE(fname_dst_parent);
7097 TALLOC_FREE(orig_lcomp_path);
7098 TALLOC_FREE(orig_lcomp_stream);
7101 TALLOC_FREE(smb_fname_dst->stream_name);
7102 smb_fname_dst->stream_name = tmp;
7104 TALLOC_FREE(fname_dst_parent);
7105 TALLOC_FREE(orig_lcomp_path);
7106 TALLOC_FREE(orig_lcomp_stream);
7110 * If the src and dest names are identical - including case,
7111 * don't do the rename, just return success.
7114 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7115 strcsequal(fsp->fsp_name->stream_name,
7116 smb_fname_dst->stream_name)) {
7117 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7118 "- returning success\n",
7119 smb_fname_str_dbg(smb_fname_dst)));
7120 status = NT_STATUS_OK;
7124 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7125 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7127 /* Return the correct error code if both names aren't streams. */
7128 if (!old_is_stream && new_is_stream) {
7129 status = NT_STATUS_OBJECT_NAME_INVALID;
7133 if (old_is_stream && !new_is_stream) {
7134 status = NT_STATUS_INVALID_PARAMETER;
7138 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7140 if(!replace_if_exists && dst_exists) {
7141 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7142 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7143 smb_fname_str_dbg(smb_fname_dst)));
7144 status = NT_STATUS_OBJECT_NAME_COLLISION;
7149 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7150 &smb_fname_dst->st);
7151 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7153 /* The file can be open when renaming a stream */
7154 if (dst_fsp && !new_is_stream) {
7155 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7156 status = NT_STATUS_ACCESS_DENIED;
7161 /* Ensure we have a valid stat struct for the source. */
7162 status = vfs_stat_fsp(fsp);
7163 if (!NT_STATUS_IS_OK(status)) {
7167 status = can_rename(conn, fsp, attrs);
7169 if (!NT_STATUS_IS_OK(status)) {
7170 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7171 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7172 smb_fname_str_dbg(smb_fname_dst)));
7173 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7174 status = NT_STATUS_ACCESS_DENIED;
7178 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7179 status = NT_STATUS_ACCESS_DENIED;
7183 /* Do we have rights to move into the destination ? */
7184 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7185 /* We're moving a directory. */
7186 access_mask = SEC_DIR_ADD_SUBDIR;
7188 status = check_parent_access(conn,
7191 if (!NT_STATUS_IS_OK(status)) {
7192 DBG_INFO("check_parent_access on "
7193 "dst %s returned %s\n",
7194 smb_fname_str_dbg(smb_fname_dst),
7199 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7202 * We have the file open ourselves, so not being able to get the
7203 * corresponding share mode lock is a fatal error.
7206 SMB_ASSERT(lck != NULL);
7208 ret = SMB_VFS_RENAMEAT(conn,
7214 uint32_t create_options = fsp->fh->private_options;
7216 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7217 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7218 smb_fname_str_dbg(smb_fname_dst)));
7220 if (!fsp->is_directory &&
7221 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7222 (lp_map_archive(SNUM(conn)) ||
7223 lp_store_dos_attributes(SNUM(conn)))) {
7224 /* We must set the archive bit on the newly
7226 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7227 uint32_t old_dosmode = dos_mode(conn,
7229 file_set_dosmode(conn,
7231 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7237 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
7240 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7244 * A rename acts as a new file create w.r.t. allowing an initial delete
7245 * on close, probably because in Windows there is a new handle to the
7246 * new file. If initial delete on close was requested but not
7247 * originally set, we need to set it here. This is probably not 100% correct,
7248 * but will work for the CIFSFS client which in non-posix mode
7249 * depends on these semantics. JRA.
7252 if (create_options & FILE_DELETE_ON_CLOSE) {
7253 status = can_set_delete_on_close(fsp, 0);
7255 if (NT_STATUS_IS_OK(status)) {
7256 /* Note that here we set the *initial* delete on close flag,
7257 * not the regular one. The magic gets handled in close. */
7258 fsp->initial_delete_on_close = True;
7262 status = NT_STATUS_OK;
7268 if (errno == ENOTDIR || errno == EISDIR) {
7269 status = NT_STATUS_OBJECT_NAME_COLLISION;
7271 status = map_nt_error_from_unix(errno);
7274 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7275 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7276 smb_fname_str_dbg(smb_fname_dst)));
7279 TALLOC_FREE(smb_fname_dst);
7284 /****************************************************************************
7285 The guts of the rename command, split out so it may be called by the NT SMB
7287 ****************************************************************************/
7289 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7290 connection_struct *conn,
7291 struct smb_request *req,
7292 struct smb_filename *smb_fname_src,
7293 struct smb_filename *smb_fname_dst,
7295 bool replace_if_exists,
7298 uint32_t access_mask)
7300 char *fname_src_dir = NULL;
7301 struct smb_filename *smb_fname_src_dir = NULL;
7302 char *fname_src_mask = NULL;
7304 NTSTATUS status = NT_STATUS_OK;
7305 struct smb_Dir *dir_hnd = NULL;
7306 const char *dname = NULL;
7307 char *talloced = NULL;
7309 int create_options = 0;
7310 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7311 struct smb2_create_blobs *posx = NULL;
7315 * Split the old name into directory and last component
7316 * strings. Note that unix_convert may have stripped off a
7317 * leading ./ from both name and newname if the rename is
7318 * at the root of the share. We need to make sure either both
7319 * name and newname contain a / character or neither of them do
7320 * as this is checked in resolve_wildcards().
7323 /* Split up the directory from the filename/mask. */
7324 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7325 &fname_src_dir, &fname_src_mask);
7326 if (!NT_STATUS_IS_OK(status)) {
7327 status = NT_STATUS_NO_MEMORY;
7332 * We should only check the mangled cache
7333 * here if unix_convert failed. This means
7334 * that the path in 'mask' doesn't exist
7335 * on the file system and so we need to look
7336 * for a possible mangle. This patch from
7337 * Tine Smukavec <valentin.smukavec@hermes.si>.
7340 if (!VALID_STAT(smb_fname_src->st) &&
7341 mangle_is_mangled(fname_src_mask, conn->params)) {
7342 char *new_mask = NULL;
7343 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7346 TALLOC_FREE(fname_src_mask);
7347 fname_src_mask = new_mask;
7351 if (posix_pathnames) {
7352 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7353 if (!NT_STATUS_IS_OK(status)) {
7354 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7360 if (!src_has_wild) {
7364 * Only one file needs to be renamed. Append the mask back
7365 * onto the directory.
7367 TALLOC_FREE(smb_fname_src->base_name);
7368 if (ISDOT(fname_src_dir)) {
7369 /* Ensure we use canonical names on open. */
7370 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7374 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7379 if (!smb_fname_src->base_name) {
7380 status = NT_STATUS_NO_MEMORY;
7384 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7385 "case_preserve = %d, short case preserve = %d, "
7386 "directory = %s, newname = %s, "
7387 "last_component_dest = %s\n",
7388 conn->case_sensitive, conn->case_preserve,
7389 conn->short_case_preserve,
7390 smb_fname_str_dbg(smb_fname_src),
7391 smb_fname_str_dbg(smb_fname_dst),
7392 smb_fname_dst->original_lcomp));
7394 /* The dest name still may have wildcards. */
7395 if (dest_has_wild) {
7396 char *fname_dst_mod = NULL;
7397 if (!resolve_wildcards(smb_fname_dst,
7398 smb_fname_src->base_name,
7399 smb_fname_dst->base_name,
7401 DEBUG(6, ("rename_internals: resolve_wildcards "
7403 smb_fname_src->base_name,
7404 smb_fname_dst->base_name));
7405 status = NT_STATUS_NO_MEMORY;
7408 TALLOC_FREE(smb_fname_dst->base_name);
7409 smb_fname_dst->base_name = fname_dst_mod;
7412 ZERO_STRUCT(smb_fname_src->st);
7413 if (posix_pathnames) {
7414 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7416 rc = SMB_VFS_STAT(conn, smb_fname_src);
7419 status = map_nt_error_from_unix_common(errno);
7423 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7424 create_options |= FILE_DIRECTORY_FILE;
7427 status = SMB_VFS_CREATE_FILE(
7430 0, /* root_dir_fid */
7431 smb_fname_src, /* fname */
7432 access_mask, /* access_mask */
7433 (FILE_SHARE_READ | /* share_access */
7435 FILE_OPEN, /* create_disposition*/
7436 create_options, /* create_options */
7437 0, /* file_attributes */
7438 0, /* oplock_request */
7440 0, /* allocation_size */
7441 0, /* private_flags */
7446 posx, /* in_context_blobs */
7447 NULL); /* out_context_blobs */
7449 if (!NT_STATUS_IS_OK(status)) {
7450 DEBUG(3, ("Could not open rename source %s: %s\n",
7451 smb_fname_str_dbg(smb_fname_src),
7452 nt_errstr(status)));
7456 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7457 attrs, replace_if_exists);
7459 close_file(req, fsp, NORMAL_CLOSE);
7461 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7462 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7463 smb_fname_str_dbg(smb_fname_dst)));
7469 * Wildcards - process each file that matches.
7471 if (strequal(fname_src_mask, "????????.???")) {
7472 TALLOC_FREE(fname_src_mask);
7473 fname_src_mask = talloc_strdup(ctx, "*");
7474 if (!fname_src_mask) {
7475 status = NT_STATUS_NO_MEMORY;
7480 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7484 smb_fname_src->flags);
7485 if (smb_fname_src_dir == NULL) {
7486 status = NT_STATUS_NO_MEMORY;
7490 status = check_name(conn, smb_fname_src_dir);
7491 if (!NT_STATUS_IS_OK(status)) {
7495 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7497 if (dir_hnd == NULL) {
7498 status = map_nt_error_from_unix(errno);
7502 status = NT_STATUS_NO_SUCH_FILE;
7504 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7505 * - gentest fix. JRA
7508 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7510 files_struct *fsp = NULL;
7511 char *destname = NULL;
7512 bool sysdir_entry = False;
7514 /* Quick check for "." and ".." */
7515 if (ISDOT(dname) || ISDOTDOT(dname)) {
7516 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7517 sysdir_entry = True;
7519 TALLOC_FREE(talloced);
7524 if (!is_visible_file(conn, fname_src_dir, dname,
7525 &smb_fname_src->st, false)) {
7526 TALLOC_FREE(talloced);
7530 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7531 TALLOC_FREE(talloced);
7536 status = NT_STATUS_OBJECT_NAME_INVALID;
7540 TALLOC_FREE(smb_fname_src->base_name);
7541 if (ISDOT(fname_src_dir)) {
7542 /* Ensure we use canonical names on open. */
7543 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7547 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7552 if (!smb_fname_src->base_name) {
7553 status = NT_STATUS_NO_MEMORY;
7557 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7558 smb_fname_dst->base_name,
7560 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7561 smb_fname_src->base_name, destname));
7562 TALLOC_FREE(talloced);
7566 status = NT_STATUS_NO_MEMORY;
7570 TALLOC_FREE(smb_fname_dst->base_name);
7571 smb_fname_dst->base_name = destname;
7573 ZERO_STRUCT(smb_fname_src->st);
7574 if (posix_pathnames) {
7575 SMB_VFS_LSTAT(conn, smb_fname_src);
7577 SMB_VFS_STAT(conn, smb_fname_src);
7582 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7583 create_options |= FILE_DIRECTORY_FILE;
7586 status = SMB_VFS_CREATE_FILE(
7589 0, /* root_dir_fid */
7590 smb_fname_src, /* fname */
7591 access_mask, /* access_mask */
7592 (FILE_SHARE_READ | /* share_access */
7594 FILE_OPEN, /* create_disposition*/
7595 create_options, /* create_options */
7596 0, /* file_attributes */
7597 0, /* oplock_request */
7599 0, /* allocation_size */
7600 0, /* private_flags */
7605 posx, /* in_context_blobs */
7606 NULL); /* out_context_blobs */
7608 if (!NT_STATUS_IS_OK(status)) {
7609 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7610 "returned %s rename %s -> %s\n",
7612 smb_fname_str_dbg(smb_fname_src),
7613 smb_fname_str_dbg(smb_fname_dst)));
7617 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7619 if (!smb_fname_dst->original_lcomp) {
7620 status = NT_STATUS_NO_MEMORY;
7624 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7625 attrs, replace_if_exists);
7627 close_file(req, fsp, NORMAL_CLOSE);
7629 if (!NT_STATUS_IS_OK(status)) {
7630 DEBUG(3, ("rename_internals_fsp returned %s for "
7631 "rename %s -> %s\n", nt_errstr(status),
7632 smb_fname_str_dbg(smb_fname_src),
7633 smb_fname_str_dbg(smb_fname_dst)));
7639 DEBUG(3,("rename_internals: doing rename on %s -> "
7640 "%s\n", smb_fname_str_dbg(smb_fname_src),
7641 smb_fname_str_dbg(smb_fname_src)));
7642 TALLOC_FREE(talloced);
7644 TALLOC_FREE(dir_hnd);
7646 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7647 status = map_nt_error_from_unix(errno);
7652 TALLOC_FREE(talloced);
7653 TALLOC_FREE(smb_fname_src_dir);
7654 TALLOC_FREE(fname_src_dir);
7655 TALLOC_FREE(fname_src_mask);
7659 /****************************************************************************
7661 ****************************************************************************/
7663 void reply_mv(struct smb_request *req)
7665 connection_struct *conn = req->conn;
7667 char *newname = NULL;
7671 bool src_has_wcard = False;
7672 bool dest_has_wcard = False;
7673 TALLOC_CTX *ctx = talloc_tos();
7674 struct smb_filename *smb_fname_src = NULL;
7675 struct smb_filename *smb_fname_dst = NULL;
7676 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7677 (req->posix_pathnames ?
7678 UCF_UNIX_NAME_LOOKUP :
7679 UCF_COND_ALLOW_WCARD_LCOMP);
7680 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7682 (req->posix_pathnames ?
7684 UCF_COND_ALLOW_WCARD_LCOMP);
7685 bool stream_rename = false;
7687 START_PROFILE(SMBmv);
7690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7694 attrs = SVAL(req->vwv+0, 0);
7696 p = (const char *)req->buf + 1;
7697 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7698 &status, &src_has_wcard);
7699 if (!NT_STATUS_IS_OK(status)) {
7700 reply_nterror(req, status);
7704 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7705 &status, &dest_has_wcard);
7706 if (!NT_STATUS_IS_OK(status)) {
7707 reply_nterror(req, status);
7711 if (!req->posix_pathnames) {
7712 /* The newname must begin with a ':' if the
7713 name contains a ':'. */
7714 if (strchr_m(name, ':')) {
7715 if (newname[0] != ':') {
7716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7719 stream_rename = true;
7723 status = filename_convert(ctx,
7731 if (!NT_STATUS_IS_OK(status)) {
7732 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7733 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7734 ERRSRV, ERRbadpath);
7737 reply_nterror(req, status);
7741 status = filename_convert(ctx,
7749 if (!NT_STATUS_IS_OK(status)) {
7750 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7751 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7752 ERRSRV, ERRbadpath);
7755 reply_nterror(req, status);
7759 if (stream_rename) {
7760 /* smb_fname_dst->base_name must be the same as
7761 smb_fname_src->base_name. */
7762 TALLOC_FREE(smb_fname_dst->base_name);
7763 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7764 smb_fname_src->base_name);
7765 if (!smb_fname_dst->base_name) {
7766 reply_nterror(req, NT_STATUS_NO_MEMORY);
7771 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7772 smb_fname_str_dbg(smb_fname_dst)));
7774 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7775 attrs, False, src_has_wcard, dest_has_wcard,
7777 if (!NT_STATUS_IS_OK(status)) {
7778 if (open_was_deferred(req->xconn, req->mid)) {
7779 /* We have re-scheduled this call. */
7782 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7783 bool ok = defer_smb1_sharing_violation(req);
7788 reply_nterror(req, status);
7792 reply_outbuf(req, 0, 0);
7794 TALLOC_FREE(smb_fname_src);
7795 TALLOC_FREE(smb_fname_dst);
7800 /*******************************************************************
7801 Copy a file as part of a reply_copy.
7802 ******************************************************************/
7805 * TODO: check error codes on all callers
7808 NTSTATUS copy_file(TALLOC_CTX *ctx,
7809 connection_struct *conn,
7810 struct smb_filename *smb_fname_src,
7811 struct smb_filename *smb_fname_dst,
7814 bool target_is_directory)
7816 struct smb_filename *smb_fname_dst_tmp = NULL;
7818 files_struct *fsp1,*fsp2;
7820 uint32_t new_create_disposition;
7824 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7825 if (smb_fname_dst_tmp == NULL) {
7826 return NT_STATUS_NO_MEMORY;
7830 * If the target is a directory, extract the last component from the
7831 * src filename and append it to the dst filename
7833 if (target_is_directory) {
7836 /* dest/target can't be a stream if it's a directory. */
7837 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7839 p = strrchr_m(smb_fname_src->base_name,'/');
7843 p = smb_fname_src->base_name;
7845 smb_fname_dst_tmp->base_name =
7846 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7848 if (!smb_fname_dst_tmp->base_name) {
7849 status = NT_STATUS_NO_MEMORY;
7854 status = vfs_file_exist(conn, smb_fname_src);
7855 if (!NT_STATUS_IS_OK(status)) {
7859 if (!target_is_directory && count) {
7860 new_create_disposition = FILE_OPEN;
7862 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7865 &new_create_disposition,
7868 status = NT_STATUS_INVALID_PARAMETER;
7873 /* Open the src file for reading. */
7874 status = SMB_VFS_CREATE_FILE(
7877 0, /* root_dir_fid */
7878 smb_fname_src, /* fname */
7879 FILE_GENERIC_READ, /* access_mask */
7880 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7881 FILE_OPEN, /* create_disposition*/
7882 0, /* create_options */
7883 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7884 INTERNAL_OPEN_ONLY, /* oplock_request */
7886 0, /* allocation_size */
7887 0, /* private_flags */
7892 NULL, NULL); /* create context */
7894 if (!NT_STATUS_IS_OK(status)) {
7898 dosattrs = dos_mode(conn, smb_fname_src);
7900 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7901 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7904 /* Open the dst file for writing. */
7905 status = SMB_VFS_CREATE_FILE(
7908 0, /* root_dir_fid */
7909 smb_fname_dst, /* fname */
7910 FILE_GENERIC_WRITE, /* access_mask */
7911 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7912 new_create_disposition, /* create_disposition*/
7913 0, /* create_options */
7914 dosattrs, /* file_attributes */
7915 INTERNAL_OPEN_ONLY, /* oplock_request */
7917 0, /* allocation_size */
7918 0, /* private_flags */
7923 NULL, NULL); /* create context */
7925 if (!NT_STATUS_IS_OK(status)) {
7926 close_file(NULL, fsp1, ERROR_CLOSE);
7930 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7931 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7933 DEBUG(0, ("error - vfs lseek returned error %s\n",
7935 status = map_nt_error_from_unix(errno);
7936 close_file(NULL, fsp1, ERROR_CLOSE);
7937 close_file(NULL, fsp2, ERROR_CLOSE);
7942 /* Do the actual copy. */
7943 if (smb_fname_src->st.st_ex_size) {
7944 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7949 close_file(NULL, fsp1, NORMAL_CLOSE);
7951 /* Ensure the modtime is set correctly on the destination file. */
7952 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7955 * As we are opening fsp1 read-only we only expect
7956 * an error on close on fsp2 if we are out of space.
7957 * Thus we don't look at the error return from the
7960 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7962 if (!NT_STATUS_IS_OK(status)) {
7966 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7967 status = NT_STATUS_DISK_FULL;
7971 status = NT_STATUS_OK;
7974 TALLOC_FREE(smb_fname_dst_tmp);
7978 /****************************************************************************
7979 Reply to a file copy.
7980 ****************************************************************************/
7982 void reply_copy(struct smb_request *req)
7984 connection_struct *conn = req->conn;
7985 struct smb_filename *smb_fname_src = NULL;
7986 struct smb_filename *smb_fname_src_dir = NULL;
7987 struct smb_filename *smb_fname_dst = NULL;
7988 char *fname_src = NULL;
7989 char *fname_dst = NULL;
7990 char *fname_src_mask = NULL;
7991 char *fname_src_dir = NULL;
7994 int error = ERRnoaccess;
7998 bool target_is_directory=False;
7999 bool source_has_wild = False;
8000 bool dest_has_wild = False;
8002 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
8003 ucf_flags_from_smb_request(req);
8004 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
8005 ucf_flags_from_smb_request(req);
8006 TALLOC_CTX *ctx = talloc_tos();
8008 START_PROFILE(SMBcopy);
8011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8015 tid2 = SVAL(req->vwv+0, 0);
8016 ofun = SVAL(req->vwv+1, 0);
8017 flags = SVAL(req->vwv+2, 0);
8019 p = (const char *)req->buf;
8020 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8021 &status, &source_has_wild);
8022 if (!NT_STATUS_IS_OK(status)) {
8023 reply_nterror(req, status);
8026 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8027 &status, &dest_has_wild);
8028 if (!NT_STATUS_IS_OK(status)) {
8029 reply_nterror(req, status);
8033 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8035 if (tid2 != conn->cnum) {
8036 /* can't currently handle inter share copies XXXX */
8037 DEBUG(3,("Rejecting inter-share copy\n"));
8038 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8042 status = filename_convert(ctx, conn,
8048 if (!NT_STATUS_IS_OK(status)) {
8049 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8050 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8051 ERRSRV, ERRbadpath);
8054 reply_nterror(req, status);
8058 status = filename_convert(ctx, conn,
8064 if (!NT_STATUS_IS_OK(status)) {
8065 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8066 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8067 ERRSRV, ERRbadpath);
8070 reply_nterror(req, status);
8074 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8076 if ((flags&1) && target_is_directory) {
8077 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8081 if ((flags&2) && !target_is_directory) {
8082 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8086 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8087 /* wants a tree copy! XXXX */
8088 DEBUG(3,("Rejecting tree copy\n"));
8089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8093 /* Split up the directory from the filename/mask. */
8094 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8095 &fname_src_dir, &fname_src_mask);
8096 if (!NT_STATUS_IS_OK(status)) {
8097 reply_nterror(req, NT_STATUS_NO_MEMORY);
8102 * We should only check the mangled cache
8103 * here if unix_convert failed. This means
8104 * that the path in 'mask' doesn't exist
8105 * on the file system and so we need to look
8106 * for a possible mangle. This patch from
8107 * Tine Smukavec <valentin.smukavec@hermes.si>.
8109 if (!VALID_STAT(smb_fname_src->st) &&
8110 mangle_is_mangled(fname_src_mask, conn->params)) {
8111 char *new_mask = NULL;
8112 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8113 &new_mask, conn->params);
8115 /* Use demangled name if one was successfully found. */
8117 TALLOC_FREE(fname_src_mask);
8118 fname_src_mask = new_mask;
8122 if (!source_has_wild) {
8125 * Only one file needs to be copied. Append the mask back onto
8128 TALLOC_FREE(smb_fname_src->base_name);
8129 if (ISDOT(fname_src_dir)) {
8130 /* Ensure we use canonical names on open. */
8131 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8135 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8140 if (!smb_fname_src->base_name) {
8141 reply_nterror(req, NT_STATUS_NO_MEMORY);
8145 if (dest_has_wild) {
8146 char *fname_dst_mod = NULL;
8147 if (!resolve_wildcards(smb_fname_dst,
8148 smb_fname_src->base_name,
8149 smb_fname_dst->base_name,
8151 reply_nterror(req, NT_STATUS_NO_MEMORY);
8154 TALLOC_FREE(smb_fname_dst->base_name);
8155 smb_fname_dst->base_name = fname_dst_mod;
8158 status = check_name(conn, smb_fname_src);
8159 if (!NT_STATUS_IS_OK(status)) {
8160 reply_nterror(req, status);
8164 status = check_name(conn, smb_fname_dst);
8165 if (!NT_STATUS_IS_OK(status)) {
8166 reply_nterror(req, status);
8170 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8171 ofun, count, target_is_directory);
8173 if(!NT_STATUS_IS_OK(status)) {
8174 reply_nterror(req, status);
8180 struct smb_Dir *dir_hnd = NULL;
8181 const char *dname = NULL;
8182 char *talloced = NULL;
8186 * There is a wildcard that requires us to actually read the
8187 * src dir and copy each file matching the mask to the dst.
8188 * Right now streams won't be copied, but this could
8189 * presumably be added with a nested loop for reach dir entry.
8191 SMB_ASSERT(!smb_fname_src->stream_name);
8192 SMB_ASSERT(!smb_fname_dst->stream_name);
8194 smb_fname_src->stream_name = NULL;
8195 smb_fname_dst->stream_name = NULL;
8197 if (strequal(fname_src_mask,"????????.???")) {
8198 TALLOC_FREE(fname_src_mask);
8199 fname_src_mask = talloc_strdup(ctx, "*");
8200 if (!fname_src_mask) {
8201 reply_nterror(req, NT_STATUS_NO_MEMORY);
8206 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8210 smb_fname_src->flags);
8211 if (smb_fname_src_dir == NULL) {
8212 reply_nterror(req, NT_STATUS_NO_MEMORY);
8216 status = check_name(conn, smb_fname_src_dir);
8217 if (!NT_STATUS_IS_OK(status)) {
8218 reply_nterror(req, status);
8222 dir_hnd = OpenDir(ctx,
8227 if (dir_hnd == NULL) {
8228 status = map_nt_error_from_unix(errno);
8229 reply_nterror(req, status);
8235 /* Iterate over the src dir copying each entry to the dst. */
8236 while ((dname = ReadDirName(dir_hnd, &offset,
8237 &smb_fname_src->st, &talloced))) {
8238 char *destname = NULL;
8240 if (ISDOT(dname) || ISDOTDOT(dname)) {
8241 TALLOC_FREE(talloced);
8245 if (!is_visible_file(conn, fname_src_dir, dname,
8246 &smb_fname_src->st, false)) {
8247 TALLOC_FREE(talloced);
8251 if(!mask_match(dname, fname_src_mask,
8252 conn->case_sensitive)) {
8253 TALLOC_FREE(talloced);
8257 error = ERRnoaccess;
8259 /* Get the src smb_fname struct setup. */
8260 TALLOC_FREE(smb_fname_src->base_name);
8261 if (ISDOT(fname_src_dir)) {
8262 /* Ensure we use canonical names on open. */
8263 smb_fname_src->base_name =
8264 talloc_asprintf(smb_fname_src, "%s",
8267 smb_fname_src->base_name =
8268 talloc_asprintf(smb_fname_src, "%s/%s",
8269 fname_src_dir, dname);
8272 if (!smb_fname_src->base_name) {
8273 TALLOC_FREE(dir_hnd);
8274 TALLOC_FREE(talloced);
8275 reply_nterror(req, NT_STATUS_NO_MEMORY);
8279 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8280 smb_fname_dst->base_name,
8282 TALLOC_FREE(talloced);
8286 TALLOC_FREE(dir_hnd);
8287 TALLOC_FREE(talloced);
8288 reply_nterror(req, NT_STATUS_NO_MEMORY);
8292 TALLOC_FREE(smb_fname_dst->base_name);
8293 smb_fname_dst->base_name = destname;
8295 status = check_name(conn, smb_fname_src);
8296 if (!NT_STATUS_IS_OK(status)) {
8297 TALLOC_FREE(dir_hnd);
8298 TALLOC_FREE(talloced);
8299 reply_nterror(req, status);
8303 status = check_name(conn, smb_fname_dst);
8304 if (!NT_STATUS_IS_OK(status)) {
8305 TALLOC_FREE(dir_hnd);
8306 TALLOC_FREE(talloced);
8307 reply_nterror(req, status);
8311 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8312 smb_fname_src->base_name,
8313 smb_fname_dst->base_name));
8315 status = copy_file(ctx, conn, smb_fname_src,
8316 smb_fname_dst, ofun, count,
8317 target_is_directory);
8318 if (NT_STATUS_IS_OK(status)) {
8322 TALLOC_FREE(talloced);
8324 TALLOC_FREE(dir_hnd);
8328 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8332 reply_outbuf(req, 1, 0);
8333 SSVAL(req->outbuf,smb_vwv0,count);
8335 TALLOC_FREE(smb_fname_src);
8336 TALLOC_FREE(smb_fname_src_dir);
8337 TALLOC_FREE(smb_fname_dst);
8338 TALLOC_FREE(fname_src);
8339 TALLOC_FREE(fname_dst);
8340 TALLOC_FREE(fname_src_mask);
8341 TALLOC_FREE(fname_src_dir);
8343 END_PROFILE(SMBcopy);
8348 #define DBGC_CLASS DBGC_LOCKING
8350 /****************************************************************************
8351 Get a lock pid, dealing with large count requests.
8352 ****************************************************************************/
8354 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8355 bool large_file_format)
8357 if(!large_file_format)
8358 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8360 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8363 /****************************************************************************
8364 Get a lock count, dealing with large count requests.
8365 ****************************************************************************/
8367 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8368 bool large_file_format)
8372 if(!large_file_format) {
8373 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8376 * No BVAL, this is reversed!
8378 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8379 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8385 /****************************************************************************
8386 Get a lock offset, dealing with large offset requests.
8387 ****************************************************************************/
8389 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8390 bool large_file_format)
8392 uint64_t offset = 0;
8394 if(!large_file_format) {
8395 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8398 * No BVAL, this is reversed!
8400 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8401 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8407 struct smbd_do_unlocking_state {
8408 struct files_struct *fsp;
8409 uint16_t num_ulocks;
8410 struct smbd_lock_element *ulocks;
8411 enum brl_flavour lock_flav;
8415 static void smbd_do_unlocking_fn(
8416 TDB_DATA value, bool *pmodified_dependent, void *private_data)
8418 struct smbd_do_unlocking_state *state = private_data;
8419 struct files_struct *fsp = state->fsp;
8420 enum brl_flavour lock_flav = state->lock_flav;
8423 for (i = 0; i < state->num_ulocks; i++) {
8424 struct smbd_lock_element *e = &state->ulocks[i];
8426 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
8427 "pid %"PRIu64", file %s\n",
8433 if (e->brltype != UNLOCK_LOCK) {
8434 /* this can only happen with SMB2 */
8435 state->status = NT_STATUS_INVALID_PARAMETER;
8439 state->status = do_unlock(
8440 fsp, e->smblctx, e->count, e->offset, lock_flav);
8442 DBG_DEBUG("do_unlock returned %s\n",
8443 nt_errstr(state->status));
8445 if (!NT_STATUS_IS_OK(state->status)) {
8450 *pmodified_dependent = true;
8453 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8455 uint16_t num_ulocks,
8456 struct smbd_lock_element *ulocks,
8457 enum brl_flavour lock_flav)
8459 struct smbd_do_unlocking_state state = {
8461 .num_ulocks = num_ulocks,
8463 .lock_flav = lock_flav,
8467 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
8469 status = share_mode_do_locked(
8470 fsp->file_id, smbd_do_unlocking_fn, &state);
8472 if (!NT_STATUS_IS_OK(status)) {
8473 DBG_DEBUG("share_mode_do_locked failed: %s\n",
8477 if (!NT_STATUS_IS_OK(state.status)) {
8478 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
8480 return state.status;
8483 return NT_STATUS_OK;
8486 /****************************************************************************
8487 Reply to a lockingX request.
8488 ****************************************************************************/
8490 static void reply_lockingx_done(struct tevent_req *subreq);
8492 void reply_lockingX(struct smb_request *req)
8494 connection_struct *conn = req->conn;
8496 unsigned char locktype;
8497 enum brl_type brltype;
8498 unsigned char oplocklevel;
8499 uint16_t num_ulocks;
8501 int32_t lock_timeout;
8503 const uint8_t *data;
8504 bool large_file_format;
8505 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8506 struct smbd_lock_element *locks = NULL;
8507 struct tevent_req *subreq = NULL;
8509 START_PROFILE(SMBlockingX);
8512 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8513 END_PROFILE(SMBlockingX);
8517 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8518 locktype = CVAL(req->vwv+3, 0);
8519 oplocklevel = CVAL(req->vwv+3, 1);
8520 num_ulocks = SVAL(req->vwv+6, 0);
8521 num_locks = SVAL(req->vwv+7, 0);
8522 lock_timeout = IVAL(req->vwv+4, 0);
8523 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8525 if (!check_fsp(conn, req, fsp)) {
8526 END_PROFILE(SMBlockingX);
8532 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8533 /* we don't support these - and CANCEL_LOCK makes w2k
8534 and XP reboot so I don't really want to be
8535 compatible! (tridge) */
8536 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8537 END_PROFILE(SMBlockingX);
8541 /* Check if this is an oplock break on a file
8542 we have granted an oplock on.
8544 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8545 /* Client can insist on breaking to none. */
8546 bool break_to_none = (oplocklevel == 0);
8549 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8550 "for %s\n", (unsigned int)oplocklevel,
8551 fsp_fnum_dbg(fsp)));
8554 * Make sure we have granted an exclusive or batch oplock on
8558 if (fsp->oplock_type == 0) {
8560 /* The Samba4 nbench simulator doesn't understand
8561 the difference between break to level2 and break
8562 to none from level2 - it sends oplock break
8563 replies in both cases. Don't keep logging an error
8564 message here - just ignore it. JRA. */
8566 DEBUG(5,("reply_lockingX: Error : oplock break from "
8567 "client for %s (oplock=%d) and no "
8568 "oplock granted on this file (%s).\n",
8569 fsp_fnum_dbg(fsp), fsp->oplock_type,
8572 /* if this is a pure oplock break request then don't
8574 if (num_locks == 0 && num_ulocks == 0) {
8575 END_PROFILE(SMBlockingX);
8579 END_PROFILE(SMBlockingX);
8580 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8584 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8586 result = remove_oplock(fsp);
8588 result = downgrade_oplock(fsp);
8592 DEBUG(0, ("reply_lockingX: error in removing "
8593 "oplock on file %s\n", fsp_str_dbg(fsp)));
8594 /* Hmmm. Is this panic justified? */
8595 smb_panic("internal tdb error");
8598 /* if this is a pure oplock break request then don't send a
8600 if (num_locks == 0 && num_ulocks == 0) {
8601 /* Sanity check - ensure a pure oplock break is not a
8603 if (CVAL(req->vwv+0, 0) != 0xff) {
8604 DEBUG(0,("reply_lockingX: Error : pure oplock "
8605 "break is a chained %d request !\n",
8606 (unsigned int)CVAL(req->vwv+0, 0)));
8608 END_PROFILE(SMBlockingX);
8614 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8616 END_PROFILE(SMBlockingX);
8620 if (num_ulocks != 0) {
8621 struct smbd_lock_element *ulocks = NULL;
8624 ulocks = talloc_array(
8625 req, struct smbd_lock_element, num_ulocks);
8626 if (ulocks == NULL) {
8627 reply_nterror(req, NT_STATUS_NO_MEMORY);
8628 END_PROFILE(SMBlockingX);
8633 * Data now points at the beginning of the list of
8634 * smb_unlkrng structs
8636 for (i = 0; i < num_ulocks; i++) {
8637 ulocks[i].req_guid = smbd_request_guid(req,
8639 ulocks[i].smblctx = get_lock_pid(
8640 data, i, large_file_format);
8641 ulocks[i].count = get_lock_count(
8642 data, i, large_file_format);
8643 ulocks[i].offset = get_lock_offset(
8644 data, i, large_file_format);
8645 ulocks[i].brltype = UNLOCK_LOCK;
8649 * Unlock cancels pending locks
8652 ok = smbd_smb1_brl_finish_by_lock(
8659 reply_outbuf(req, 2, 0);
8660 SSVAL(req->outbuf, smb_vwv0, 0xff);
8661 SSVAL(req->outbuf, smb_vwv1, 0);
8662 END_PROFILE(SMBlockingX);
8666 status = smbd_do_unlocking(
8667 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
8668 TALLOC_FREE(ulocks);
8669 if (!NT_STATUS_IS_OK(status)) {
8670 END_PROFILE(SMBlockingX);
8671 reply_nterror(req, status);
8676 /* Now do any requested locks */
8677 data += ((large_file_format ? 20 : 10)*num_ulocks);
8679 /* Data now points at the beginning of the list
8680 of smb_lkrng structs */
8682 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8683 brltype = READ_LOCK;
8685 brltype = WRITE_LOCK;
8688 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8689 if (locks == NULL) {
8690 reply_nterror(req, NT_STATUS_NO_MEMORY);
8691 END_PROFILE(SMBlockingX);
8695 for (i = 0; i < num_locks; i++) {
8696 locks[i].req_guid = smbd_request_guid(req, i),
8697 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8698 locks[i].count = get_lock_count(data, i, large_file_format);
8699 locks[i].offset = get_lock_offset(data, i, large_file_format);
8700 locks[i].brltype = brltype;
8703 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8707 if (num_locks == 0) {
8708 /* See smbtorture3 lock11 test */
8709 reply_outbuf(req, 2, 0);
8710 /* andx chain ends */
8711 SSVAL(req->outbuf, smb_vwv0, 0xff);
8712 SSVAL(req->outbuf, smb_vwv1, 0);
8713 END_PROFILE(SMBlockingX);
8717 ok = smbd_smb1_brl_finish_by_lock(
8721 locks[0], /* Windows only cancels the first lock */
8722 NT_STATUS_FILE_LOCK_CONFLICT);
8725 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
8726 END_PROFILE(SMBlockingX);
8730 reply_outbuf(req, 2, 0);
8731 SSVAL(req->outbuf, smb_vwv0, 0xff);
8732 SSVAL(req->outbuf, smb_vwv1, 0);
8733 END_PROFILE(SMBlockingX);
8737 subreq = smbd_smb1_do_locks_send(
8747 if (subreq == NULL) {
8748 reply_nterror(req, NT_STATUS_NO_MEMORY);
8749 END_PROFILE(SMBlockingX);
8752 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
8753 END_PROFILE(SMBlockingX);
8756 static void reply_lockingx_done(struct tevent_req *subreq)
8758 struct smb_request *req = NULL;
8762 START_PROFILE(SMBlockingX);
8764 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
8767 status = smbd_smb1_do_locks_recv(subreq);
8768 TALLOC_FREE(subreq);
8770 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
8772 if (NT_STATUS_IS_OK(status)) {
8773 reply_outbuf(req, 2, 0);
8774 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8775 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8777 reply_nterror(req, status);
8780 ok = srv_send_smb(req->xconn,
8781 (char *)req->outbuf,
8784 IS_CONN_ENCRYPTED(req->conn),
8787 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
8790 END_PROFILE(SMBlockingX);
8794 #define DBGC_CLASS DBGC_ALL
8796 /****************************************************************************
8797 Reply to a SMBreadbmpx (read block multiplex) request.
8798 Always reply with an error, if someone has a platform really needs this,
8799 please contact vl@samba.org
8800 ****************************************************************************/
8802 void reply_readbmpx(struct smb_request *req)
8804 START_PROFILE(SMBreadBmpx);
8805 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8806 END_PROFILE(SMBreadBmpx);
8810 /****************************************************************************
8811 Reply to a SMBreadbs (read block multiplex secondary) request.
8812 Always reply with an error, if someone has a platform really needs this,
8813 please contact vl@samba.org
8814 ****************************************************************************/
8816 void reply_readbs(struct smb_request *req)
8818 START_PROFILE(SMBreadBs);
8819 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8820 END_PROFILE(SMBreadBs);
8824 /****************************************************************************
8825 Reply to a SMBsetattrE.
8826 ****************************************************************************/
8828 void reply_setattrE(struct smb_request *req)
8830 connection_struct *conn = req->conn;
8831 struct smb_file_time ft;
8835 START_PROFILE(SMBsetattrE);
8836 init_smb_file_time(&ft);
8839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8843 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8845 if(!fsp || (fsp->conn != conn)) {
8846 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8851 * Convert the DOS times into unix times.
8854 ft.atime = time_t_to_full_timespec(
8855 srv_make_unix_date2(req->vwv+3));
8856 ft.mtime = time_t_to_full_timespec(
8857 srv_make_unix_date2(req->vwv+5));
8858 ft.create_time = time_t_to_full_timespec(
8859 srv_make_unix_date2(req->vwv+1));
8861 reply_outbuf(req, 0, 0);
8864 * Patch from Ray Frush <frush@engr.colostate.edu>
8865 * Sometimes times are sent as zero - ignore them.
8868 /* Ensure we have a valid stat struct for the source. */
8869 status = vfs_stat_fsp(fsp);
8870 if (!NT_STATUS_IS_OK(status)) {
8871 reply_nterror(req, status);
8875 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8876 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8880 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8881 if (!NT_STATUS_IS_OK(status)) {
8882 reply_nterror(req, status);
8886 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8889 (unsigned int)ft.atime.tv_sec,
8890 (unsigned int)ft.mtime.tv_sec,
8891 (unsigned int)ft.create_time.tv_sec
8894 END_PROFILE(SMBsetattrE);
8899 /* Back from the dead for OS/2..... JRA. */
8901 /****************************************************************************
8902 Reply to a SMBwritebmpx (write block multiplex primary) request.
8903 Always reply with an error, if someone has a platform really needs this,
8904 please contact vl@samba.org
8905 ****************************************************************************/
8907 void reply_writebmpx(struct smb_request *req)
8909 START_PROFILE(SMBwriteBmpx);
8910 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8911 END_PROFILE(SMBwriteBmpx);
8915 /****************************************************************************
8916 Reply to a SMBwritebs (write block multiplex secondary) request.
8917 Always reply with an error, if someone has a platform really needs this,
8918 please contact vl@samba.org
8919 ****************************************************************************/
8921 void reply_writebs(struct smb_request *req)
8923 START_PROFILE(SMBwriteBs);
8924 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8925 END_PROFILE(SMBwriteBs);
8929 /****************************************************************************
8930 Reply to a SMBgetattrE.
8931 ****************************************************************************/
8933 void reply_getattrE(struct smb_request *req)
8935 connection_struct *conn = req->conn;
8938 struct timespec create_ts;
8941 START_PROFILE(SMBgetattrE);
8944 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8945 END_PROFILE(SMBgetattrE);
8949 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8951 if(!fsp || (fsp->conn != conn)) {
8952 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8953 END_PROFILE(SMBgetattrE);
8957 /* Do an fstat on this file */
8958 status = vfs_stat_fsp(fsp);
8959 if (!NT_STATUS_IS_OK(status)) {
8960 reply_nterror(req, status);
8961 END_PROFILE(SMBgetattrE);
8965 mode = dos_mode(conn, fsp->fsp_name);
8968 * Convert the times into dos times. Set create
8969 * date to be last modify date as UNIX doesn't save
8973 reply_outbuf(req, 11, 0);
8975 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8976 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8977 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8978 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8979 /* Should we check pending modtime here ? JRA */
8980 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8981 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8983 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8984 SIVAL(req->outbuf, smb_vwv6, 0);
8985 SIVAL(req->outbuf, smb_vwv8, 0);
8987 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8988 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8989 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8991 SSVAL(req->outbuf,smb_vwv10, mode);
8993 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8995 END_PROFILE(SMBgetattrE);