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"
50 /****************************************************************************
51 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
52 path or anything including wildcards.
53 We're assuming here that '/' is not the second byte in any multibyte char
54 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
56 ****************************************************************************/
58 /* Custom version for processing POSIX paths. */
59 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
61 static NTSTATUS check_path_syntax_internal(char *path,
63 bool *p_last_component_contains_wcard)
67 NTSTATUS ret = NT_STATUS_OK;
68 bool start_of_name_component = True;
69 bool stream_started = false;
71 *p_last_component_contains_wcard = False;
78 return NT_STATUS_OBJECT_NAME_INVALID;
81 return NT_STATUS_OBJECT_NAME_INVALID;
83 if (strchr_m(&s[1], ':')) {
84 return NT_STATUS_OBJECT_NAME_INVALID;
90 if ((*s == ':') && !posix_path && !stream_started) {
91 if (*p_last_component_contains_wcard) {
92 return NT_STATUS_OBJECT_NAME_INVALID;
94 /* Stream names allow more characters than file names.
95 We're overloading posix_path here to allow a wider
96 range of characters. If stream_started is true this
97 is still a Windows path even if posix_path is true.
100 stream_started = true;
101 start_of_name_component = false;
105 return NT_STATUS_OBJECT_NAME_INVALID;
109 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
111 * Safe to assume is not the second part of a mb char
112 * as this is handled below.
114 /* Eat multiple '/' or '\\' */
115 while (IS_PATH_SEP(*s,posix_path)) {
118 if ((d != path) && (*s != '\0')) {
119 /* We only care about non-leading or trailing '/' or '\\' */
123 start_of_name_component = True;
125 *p_last_component_contains_wcard = False;
129 if (start_of_name_component) {
130 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
131 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
134 * No mb char starts with '.' so we're safe checking the directory separator here.
137 /* If we just added a '/' - delete it */
138 if ((d > path) && (*(d-1) == '/')) {
143 /* Are we at the start ? Can't go back further if so. */
145 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
148 /* Go back one level... */
149 /* We know this is safe as '/' cannot be part of a mb sequence. */
150 /* NOTE - if this assumption is invalid we are not in good shape... */
151 /* Decrement d first as d points to the *next* char to write into. */
152 for (d--; d > path; d--) {
156 s += 2; /* Else go past the .. */
157 /* We're still at the start of a name component, just the previous one. */
160 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
172 if (*s <= 0x1f || *s == '|') {
173 return NT_STATUS_OBJECT_NAME_INVALID;
181 *p_last_component_contains_wcard = True;
190 /* Get the size of the next MB character. */
191 next_codepoint(s,&siz);
209 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
211 return NT_STATUS_INVALID_PARAMETER;
214 start_of_name_component = False;
222 /****************************************************************************
223 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
224 No wildcards allowed.
225 ****************************************************************************/
227 NTSTATUS check_path_syntax(char *path)
230 return check_path_syntax_internal(path, False, &ignore);
233 /****************************************************************************
234 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
235 Wildcards allowed - p_contains_wcard returns true if the last component contained
237 ****************************************************************************/
239 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
241 return check_path_syntax_internal(path, False, p_contains_wcard);
244 /****************************************************************************
245 Check the path for a POSIX client.
246 We're assuming here that '/' is not the second byte in any multibyte char
247 set (a safe assumption).
248 ****************************************************************************/
250 NTSTATUS check_path_syntax_posix(char *path)
253 return check_path_syntax_internal(path, True, &ignore);
256 /****************************************************************************
257 Pull a string and check the path allowing a wilcard - provide for error return.
258 Passes in posix flag.
259 ****************************************************************************/
261 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
262 const char *base_ptr,
268 bool posix_pathnames,
270 bool *contains_wcard)
276 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
280 *err = NT_STATUS_INVALID_PARAMETER;
284 *contains_wcard = False;
286 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
288 * For a DFS path the function parse_dfs_path()
289 * will do the path processing, just make a copy.
295 if (posix_pathnames) {
296 *err = check_path_syntax_posix(*pp_dest);
298 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
304 /****************************************************************************
305 Pull a string and check the path allowing a wilcard - provide for error return.
306 ****************************************************************************/
308 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
309 const char *base_ptr,
316 bool *contains_wcard)
318 return srvstr_get_path_wcard_internal(ctx,
330 /****************************************************************************
331 Pull a string and check the path allowing a wilcard - provide for error return.
332 posix_pathnames version.
333 ****************************************************************************/
335 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
336 const char *base_ptr,
343 bool *contains_wcard)
345 return srvstr_get_path_wcard_internal(ctx,
357 /****************************************************************************
358 Pull a string and check the path - provide for error return.
359 ****************************************************************************/
361 size_t srvstr_get_path(TALLOC_CTX *ctx,
362 const char *base_ptr,
371 return srvstr_get_path_wcard_internal(ctx,
383 /****************************************************************************
384 Pull a string and check the path - provide for error return.
385 posix_pathnames version.
386 ****************************************************************************/
388 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
389 const char *base_ptr,
398 return srvstr_get_path_wcard_internal(ctx,
411 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
412 char **pp_dest, const char *src, int flags,
413 NTSTATUS *err, bool *contains_wcard)
415 ssize_t bufrem = smbreq_bufrem(req, src);
418 *err = NT_STATUS_INVALID_PARAMETER;
422 if (req->posix_pathnames) {
423 return srvstr_get_path_wcard_internal(mem_ctx,
424 (const char *)req->inbuf,
434 return srvstr_get_path_wcard_internal(mem_ctx,
435 (const char *)req->inbuf,
447 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
448 char **pp_dest, const char *src, int flags,
452 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
453 flags, err, &ignore);
457 * pull a string from the smb_buf part of a packet. In this case the
458 * string can either be null terminated or it can be terminated by the
459 * end of the smbbuf area
461 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
462 char **dest, const uint8_t *src, int flags)
464 ssize_t bufrem = smbreq_bufrem(req, src);
470 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
474 /****************************************************************************
475 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
476 ****************************************************************************/
478 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
481 if ((fsp == NULL) || (conn == NULL)) {
482 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
485 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
486 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
492 /****************************************************************************
493 Check if we have a correct fsp pointing to a file.
494 ****************************************************************************/
496 bool check_fsp(connection_struct *conn, struct smb_request *req,
499 if (!check_fsp_open(conn, req, fsp)) {
502 if (fsp->is_directory) {
503 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
506 if (fsp->fh->fd == -1) {
507 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
510 fsp->num_smb_operations++;
514 /****************************************************************************
515 Check if we have a correct fsp pointing to a quota fake file. Replacement for
516 the CHECK_NTQUOTA_HANDLE_OK macro.
517 ****************************************************************************/
519 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
522 if (!check_fsp_open(conn, req, fsp)) {
526 if (fsp->is_directory) {
530 if (fsp->fake_file_handle == NULL) {
534 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
538 if (fsp->fake_file_handle->private_data == NULL) {
545 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
546 const char *name, int name_type)
549 char *trim_name_type;
550 const char *retarget_parm;
553 int retarget_type = 0x20;
554 int retarget_port = NBT_SMB_PORT;
555 struct sockaddr_storage retarget_addr;
556 struct sockaddr_in *in_addr;
560 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
564 trim_name = talloc_strdup(talloc_tos(), name);
565 if (trim_name == NULL) {
568 trim_char(trim_name, ' ', ' ');
570 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
572 if (trim_name_type == NULL) {
576 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
577 trim_name_type, NULL);
578 if (retarget_parm == NULL) {
579 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
582 if (retarget_parm == NULL) {
586 retarget = talloc_strdup(trim_name, retarget_parm);
587 if (retarget == NULL) {
591 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
593 p = strchr(retarget, ':');
596 retarget_port = atoi(p);
599 p = strchr_m(retarget, '#');
602 if (sscanf(p, "%x", &retarget_type) != 1) {
607 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
609 DEBUG(10, ("could not resolve %s\n", retarget));
613 if (retarget_addr.ss_family != AF_INET) {
614 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
618 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
620 _smb_setlen(outbuf, 6);
621 SCVAL(outbuf, 0, 0x84);
622 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
623 *(uint16_t *)(outbuf+8) = htons(retarget_port);
625 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
627 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
633 TALLOC_FREE(trim_name);
637 static void reply_called_name_not_present(char *outbuf)
639 smb_setlen(outbuf, 1);
640 SCVAL(outbuf, 0, 0x83);
641 SCVAL(outbuf, 4, 0x82);
644 /****************************************************************************
645 Reply to a (netbios-level) special message.
646 ****************************************************************************/
648 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
650 struct smbd_server_connection *sconn = xconn->client->sconn;
651 int msg_type = CVAL(inbuf,0);
652 int msg_flags = CVAL(inbuf,1);
654 * We only really use 4 bytes of the outbuf, but for the smb_setlen
655 * calculation & friends (srv_send_smb uses that) we need the full smb
658 char outbuf[smb_size];
660 memset(outbuf, '\0', sizeof(outbuf));
662 smb_setlen(outbuf,0);
665 case NBSSrequest: /* session request */
667 /* inbuf_size is guarenteed to be at least 4. */
669 int name_type1, name_type2;
670 int name_len1, name_len2;
674 if (xconn->transport.nbt.got_session) {
675 exit_server_cleanly("multiple session request not permitted");
678 SCVAL(outbuf,0,NBSSpositive);
681 /* inbuf_size is guaranteed to be at least 4. */
682 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
683 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
684 DEBUG(0,("Invalid name length in session request\n"));
685 reply_called_name_not_present(outbuf);
688 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
689 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
690 DEBUG(0,("Invalid name length in session request\n"));
691 reply_called_name_not_present(outbuf);
695 name_type1 = name_extract((unsigned char *)inbuf,
696 inbuf_size,(unsigned int)4,name1);
697 name_type2 = name_extract((unsigned char *)inbuf,
698 inbuf_size,(unsigned int)(4 + name_len1),name2);
700 if (name_type1 == -1 || name_type2 == -1) {
701 DEBUG(0,("Invalid name type in session request\n"));
702 reply_called_name_not_present(outbuf);
706 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
707 name1, name_type1, name2, name_type2));
709 if (netbios_session_retarget(xconn, name1, name_type1)) {
710 exit_server_cleanly("retargeted client");
714 * Windows NT/2k uses "*SMBSERVER" and XP uses
715 * "*SMBSERV" arrggg!!!
717 if (strequal(name1, "*SMBSERVER ")
718 || strequal(name1, "*SMBSERV ")) {
721 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
724 exit_server_cleanly("could not allocate raddr");
727 fstrcpy(name1, raddr);
730 set_local_machine_name(name1, True);
731 set_remote_machine_name(name2, True);
733 if (is_ipaddress(sconn->remote_hostname)) {
734 char *p = discard_const_p(char, sconn->remote_hostname);
738 sconn->remote_hostname = talloc_strdup(sconn,
739 get_remote_machine_name());
740 if (sconn->remote_hostname == NULL) {
741 exit_server_cleanly("could not copy remote name");
743 xconn->remote_hostname = sconn->remote_hostname;
746 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
747 get_local_machine_name(), get_remote_machine_name(),
750 if (name_type2 == 'R') {
751 /* We are being asked for a pathworks session ---
753 reply_called_name_not_present(outbuf);
757 reload_services(sconn, conn_snum_used, true);
760 xconn->transport.nbt.got_session = true;
764 case 0x89: /* session keepalive request
765 (some old clients produce this?) */
766 SCVAL(outbuf,0,NBSSkeepalive);
770 case NBSSpositive: /* positive session response */
771 case NBSSnegative: /* negative session response */
772 case NBSSretarget: /* retarget session response */
773 DEBUG(0,("Unexpected session response\n"));
776 case NBSSkeepalive: /* session keepalive */
781 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
782 msg_type, msg_flags));
784 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
785 exit_server_cleanly("reply_special: srv_send_smb failed.");
788 if (CVAL(outbuf, 0) != 0x82) {
789 exit_server_cleanly("invalid netbios session");
794 /****************************************************************************
796 conn POINTER CAN BE NULL HERE !
797 ****************************************************************************/
799 void reply_tcon(struct smb_request *req)
801 connection_struct *conn = req->conn;
803 char *service_buf = NULL;
804 char *password = NULL;
810 TALLOC_CTX *ctx = talloc_tos();
811 struct smbXsrv_connection *xconn = req->xconn;
812 NTTIME now = timeval_to_nttime(&req->request_time);
814 START_PROFILE(SMBtcon);
816 if (req->buflen < 4) {
817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
818 END_PROFILE(SMBtcon);
823 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
825 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
827 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
830 if (service_buf == NULL || password == NULL || dev == NULL) {
831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
832 END_PROFILE(SMBtcon);
835 p2 = strrchr_m(service_buf,'\\');
839 service = service_buf;
842 conn = make_connection(req, now, service, dev,
843 req->vuid,&nt_status);
847 reply_nterror(req, nt_status);
848 END_PROFILE(SMBtcon);
852 reply_outbuf(req, 2, 0);
853 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
854 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
855 SSVAL(req->outbuf,smb_tid,conn->cnum);
857 DEBUG(3,("tcon service=%s cnum=%d\n",
858 service, conn->cnum));
860 END_PROFILE(SMBtcon);
864 /****************************************************************************
865 Reply to a tcon and X.
866 conn POINTER CAN BE NULL HERE !
867 ****************************************************************************/
869 void reply_tcon_and_X(struct smb_request *req)
871 connection_struct *conn = req->conn;
872 const char *service = NULL;
873 TALLOC_CTX *ctx = talloc_tos();
874 /* what the client thinks the device is */
875 char *client_devicetype = NULL;
876 /* what the server tells the client the share represents */
877 const char *server_devicetype;
884 struct smbXsrv_session *session = NULL;
885 NTTIME now = timeval_to_nttime(&req->request_time);
886 bool session_key_updated = false;
887 uint16_t optional_support = 0;
888 struct smbXsrv_connection *xconn = req->xconn;
890 START_PROFILE(SMBtconX);
893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
894 END_PROFILE(SMBtconX);
898 passlen = SVAL(req->vwv+3, 0);
899 tcon_flags = SVAL(req->vwv+2, 0);
901 /* we might have to close an old one */
902 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
903 struct smbXsrv_tcon *tcon;
911 * TODO: cancel all outstanding requests on the tcon
913 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
914 if (!NT_STATUS_IS_OK(status)) {
915 DEBUG(0, ("reply_tcon_and_X: "
916 "smbXsrv_tcon_disconnect() failed: %s\n",
919 * If we hit this case, there is something completely
920 * wrong, so we better disconnect the transport connection.
922 END_PROFILE(SMBtconX);
923 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
929 * This tree id is gone. Make sure we can't re-use it
935 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
936 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
937 END_PROFILE(SMBtconX);
941 if (xconn->smb1.negprot.encrypted_passwords) {
942 p = req->buf + passlen;
944 p = req->buf + passlen + 1;
947 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
951 END_PROFILE(SMBtconX);
956 * the service name can be either: \\server\share
957 * or share directly like on the DELL PowerVault 705
960 q = strchr_m(path+2,'\\');
962 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
963 END_PROFILE(SMBtconX);
971 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
972 &client_devicetype, p,
973 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
975 if (client_devicetype == NULL) {
976 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
977 END_PROFILE(SMBtconX);
981 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
983 nt_status = smb1srv_session_lookup(xconn,
984 req->vuid, now, &session);
985 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
986 reply_force_doserror(req, ERRSRV, ERRbaduid);
987 END_PROFILE(SMBtconX);
990 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
991 reply_nterror(req, nt_status);
992 END_PROFILE(SMBtconX);
995 if (!NT_STATUS_IS_OK(nt_status)) {
996 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
997 END_PROFILE(SMBtconX);
1001 if (session->global->auth_session_info == NULL) {
1002 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1003 END_PROFILE(SMBtconX);
1008 * If there is no application key defined yet
1011 * This means we setup the application key on the
1012 * first tcon that happens via the given session.
1014 * Once the application key is defined, it does not
1017 if (session->global->application_key.length == 0 &&
1018 smb2_signing_key_valid(session->global->signing_key))
1020 struct smbXsrv_session *x = session;
1021 struct auth_session_info *session_info =
1022 session->global->auth_session_info;
1023 uint8_t session_key[16];
1025 ZERO_STRUCT(session_key);
1026 memcpy(session_key, x->global->signing_key->blob.data,
1027 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
1030 * The application key is truncated/padded to 16 bytes
1032 x->global->application_key = data_blob_talloc(x->global,
1034 sizeof(session_key));
1035 ZERO_STRUCT(session_key);
1036 if (x->global->application_key.data == NULL) {
1037 reply_nterror(req, NT_STATUS_NO_MEMORY);
1038 END_PROFILE(SMBtconX);
1042 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1045 status = smb_key_derivation(x->global->application_key.data,
1046 x->global->application_key.length,
1047 x->global->application_key.data);
1048 if (!NT_STATUS_IS_OK(status)) {
1049 DBG_ERR("smb_key_derivation failed: %s\n",
1053 optional_support |= SMB_EXTENDED_SIGNATURES;
1057 * Place the application key into the session_info
1059 data_blob_clear_free(&session_info->session_key);
1060 session_info->session_key = data_blob_dup_talloc(session_info,
1061 x->global->application_key);
1062 if (session_info->session_key.data == NULL) {
1063 data_blob_clear_free(&x->global->application_key);
1064 reply_nterror(req, NT_STATUS_NO_MEMORY);
1065 END_PROFILE(SMBtconX);
1068 session_key_updated = true;
1071 conn = make_connection(req, now, service, client_devicetype,
1072 req->vuid, &nt_status);
1076 if (session_key_updated) {
1077 struct smbXsrv_session *x = session;
1078 struct auth_session_info *session_info =
1079 session->global->auth_session_info;
1080 data_blob_clear_free(&x->global->application_key);
1081 data_blob_clear_free(&session_info->session_key);
1083 reply_nterror(req, nt_status);
1084 END_PROFILE(SMBtconX);
1089 server_devicetype = "IPC";
1090 else if ( IS_PRINT(conn) )
1091 server_devicetype = "LPT1:";
1093 server_devicetype = "A:";
1095 if (get_Protocol() < PROTOCOL_NT1) {
1096 reply_outbuf(req, 2, 0);
1097 if (message_push_string(&req->outbuf, server_devicetype,
1098 STR_TERMINATE|STR_ASCII) == -1) {
1099 reply_nterror(req, NT_STATUS_NO_MEMORY);
1100 END_PROFILE(SMBtconX);
1104 /* NT sets the fstype of IPC$ to the null string */
1105 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1107 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1108 /* Return permissions. */
1112 reply_outbuf(req, 7, 0);
1115 perm1 = FILE_ALL_ACCESS;
1116 perm2 = FILE_ALL_ACCESS;
1118 perm1 = conn->share_access;
1121 SIVAL(req->outbuf, smb_vwv3, perm1);
1122 SIVAL(req->outbuf, smb_vwv5, perm2);
1124 reply_outbuf(req, 3, 0);
1127 if ((message_push_string(&req->outbuf, server_devicetype,
1128 STR_TERMINATE|STR_ASCII) == -1)
1129 || (message_push_string(&req->outbuf, fstype,
1130 STR_TERMINATE) == -1)) {
1131 reply_nterror(req, NT_STATUS_NO_MEMORY);
1132 END_PROFILE(SMBtconX);
1136 /* what does setting this bit do? It is set by NT4 and
1137 may affect the ability to autorun mounted cdroms */
1138 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1140 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1142 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1143 DEBUG(2,("Serving %s as a Dfs root\n",
1144 lp_servicename(ctx, SNUM(conn)) ));
1145 optional_support |= SMB_SHARE_IN_DFS;
1148 SSVAL(req->outbuf, smb_vwv2, optional_support);
1151 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1152 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1154 DEBUG(3,("tconX service=%s \n",
1157 /* set the incoming and outgoing tid to the just created one */
1158 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1159 SSVAL(req->outbuf,smb_tid,conn->cnum);
1161 END_PROFILE(SMBtconX);
1163 req->tid = conn->cnum;
1166 /****************************************************************************
1167 Reply to an unknown type.
1168 ****************************************************************************/
1170 void reply_unknown_new(struct smb_request *req, uint8_t type)
1172 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1173 smb_fn_name(type), type, type));
1174 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1178 /****************************************************************************
1180 conn POINTER CAN BE NULL HERE !
1181 ****************************************************************************/
1183 void reply_ioctl(struct smb_request *req)
1185 connection_struct *conn = req->conn;
1188 uint32_t ioctl_code;
1192 START_PROFILE(SMBioctl);
1195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1196 END_PROFILE(SMBioctl);
1200 device = SVAL(req->vwv+1, 0);
1201 function = SVAL(req->vwv+2, 0);
1202 ioctl_code = (device << 16) + function;
1204 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1206 switch (ioctl_code) {
1207 case IOCTL_QUERY_JOB_INFO:
1211 reply_force_doserror(req, ERRSRV, ERRnosupport);
1212 END_PROFILE(SMBioctl);
1216 reply_outbuf(req, 8, replysize+1);
1217 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1218 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1219 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1220 p = smb_buf(req->outbuf);
1221 memset(p, '\0', replysize+1); /* valgrind-safe. */
1222 p += 1; /* Allow for alignment */
1224 switch (ioctl_code) {
1225 case IOCTL_QUERY_JOB_INFO:
1229 files_struct *fsp = file_fsp(
1230 req, SVAL(req->vwv+0, 0));
1232 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1233 END_PROFILE(SMBioctl);
1237 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1239 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1240 lp_netbios_name(), 15,
1241 STR_TERMINATE|STR_ASCII, &len);
1242 if (!NT_STATUS_IS_OK(status)) {
1243 reply_nterror(req, status);
1244 END_PROFILE(SMBioctl);
1248 status = srvstr_push((char *)req->outbuf, req->flags2,
1250 lp_servicename(talloc_tos(),
1252 13, STR_TERMINATE|STR_ASCII, &len);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 reply_nterror(req, status);
1255 END_PROFILE(SMBioctl);
1259 memset(p+18, 0, 13);
1265 END_PROFILE(SMBioctl);
1269 /****************************************************************************
1270 Strange checkpath NTSTATUS mapping.
1271 ****************************************************************************/
1273 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1275 /* Strange DOS error code semantics only for checkpath... */
1276 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1277 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1278 /* We need to map to ERRbadpath */
1279 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1285 /****************************************************************************
1286 Reply to a checkpath.
1287 ****************************************************************************/
1289 void reply_checkpath(struct smb_request *req)
1291 connection_struct *conn = req->conn;
1292 struct smb_filename *smb_fname = NULL;
1295 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1296 TALLOC_CTX *ctx = talloc_tos();
1298 START_PROFILE(SMBcheckpath);
1300 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1301 STR_TERMINATE, &status);
1303 if (!NT_STATUS_IS_OK(status)) {
1304 status = map_checkpath_error(req->flags2, status);
1305 reply_nterror(req, status);
1306 END_PROFILE(SMBcheckpath);
1310 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1312 status = filename_convert(ctx,
1320 if (!NT_STATUS_IS_OK(status)) {
1321 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1322 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1323 ERRSRV, ERRbadpath);
1324 END_PROFILE(SMBcheckpath);
1330 if (!VALID_STAT(smb_fname->st) &&
1331 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1332 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1333 smb_fname_str_dbg(smb_fname), strerror(errno)));
1334 status = map_nt_error_from_unix(errno);
1338 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1339 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1340 ERRDOS, ERRbadpath);
1344 reply_outbuf(req, 0, 0);
1347 /* We special case this - as when a Windows machine
1348 is parsing a path is steps through the components
1349 one at a time - if a component fails it expects
1350 ERRbadpath, not ERRbadfile.
1352 status = map_checkpath_error(req->flags2, status);
1353 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1355 * Windows returns different error codes if
1356 * the parent directory is valid but not the
1357 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1358 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1359 * if the path is invalid.
1361 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1362 ERRDOS, ERRbadpath);
1366 reply_nterror(req, status);
1369 TALLOC_FREE(smb_fname);
1370 END_PROFILE(SMBcheckpath);
1374 /****************************************************************************
1376 ****************************************************************************/
1378 void reply_getatr(struct smb_request *req)
1380 connection_struct *conn = req->conn;
1381 struct smb_filename *smb_fname = NULL;
1388 TALLOC_CTX *ctx = talloc_tos();
1389 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1391 START_PROFILE(SMBgetatr);
1393 p = (const char *)req->buf + 1;
1394 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1395 if (!NT_STATUS_IS_OK(status)) {
1396 reply_nterror(req, status);
1400 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1401 under WfWg - weird! */
1402 if (*fname == '\0') {
1403 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1404 if (!CAN_WRITE(conn)) {
1405 mode |= FILE_ATTRIBUTE_READONLY;
1410 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1411 status = filename_convert(ctx,
1418 if (!NT_STATUS_IS_OK(status)) {
1419 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1420 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1421 ERRSRV, ERRbadpath);
1424 reply_nterror(req, status);
1427 if (!VALID_STAT(smb_fname->st) &&
1428 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1429 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1430 smb_fname_str_dbg(smb_fname),
1432 reply_nterror(req, map_nt_error_from_unix(errno));
1436 mode = dos_mode(conn, smb_fname);
1437 size = smb_fname->st.st_ex_size;
1439 if (ask_sharemode) {
1440 struct timespec write_time_ts;
1441 struct file_id fileid;
1443 ZERO_STRUCT(write_time_ts);
1444 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1445 get_file_infos(fileid, 0, NULL, &write_time_ts);
1446 if (!null_timespec(write_time_ts)) {
1447 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1451 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1452 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1457 reply_outbuf(req, 10, 0);
1459 SSVAL(req->outbuf,smb_vwv0,mode);
1460 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1461 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1463 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1465 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1467 if (get_Protocol() >= PROTOCOL_NT1) {
1468 SSVAL(req->outbuf, smb_flg2,
1469 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1472 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1473 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1476 TALLOC_FREE(smb_fname);
1478 END_PROFILE(SMBgetatr);
1482 /****************************************************************************
1484 ****************************************************************************/
1486 void reply_setatr(struct smb_request *req)
1488 struct smb_file_time ft;
1489 connection_struct *conn = req->conn;
1490 struct smb_filename *smb_fname = NULL;
1496 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1497 TALLOC_CTX *ctx = talloc_tos();
1499 START_PROFILE(SMBsetatr);
1502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1506 p = (const char *)req->buf + 1;
1507 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1508 if (!NT_STATUS_IS_OK(status)) {
1509 reply_nterror(req, status);
1513 status = filename_convert(ctx,
1520 if (!NT_STATUS_IS_OK(status)) {
1521 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1522 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1523 ERRSRV, ERRbadpath);
1526 reply_nterror(req, status);
1530 if (ISDOT(smb_fname->base_name)) {
1532 * Not sure here is the right place to catch this
1533 * condition. Might be moved to somewhere else later -- vl
1535 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1539 mode = SVAL(req->vwv+0, 0);
1540 mtime = srv_make_unix_date3(req->vwv+1);
1542 if (mode != FILE_ATTRIBUTE_NORMAL) {
1543 if (VALID_STAT_OF_DIR(smb_fname->st))
1544 mode |= FILE_ATTRIBUTE_DIRECTORY;
1546 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1548 status = smbd_check_access_rights(
1549 conn, smb_fname, false, FILE_WRITE_ATTRIBUTES);
1550 if (!NT_STATUS_IS_OK(status)) {
1551 reply_nterror(req, status);
1555 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1557 reply_nterror(req, map_nt_error_from_unix(errno));
1562 ft = (struct smb_file_time) {
1563 .mtime = convert_time_t_to_timespec(mtime)
1566 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 reply_nterror(req, status);
1572 reply_outbuf(req, 0, 0);
1574 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1577 TALLOC_FREE(smb_fname);
1578 END_PROFILE(SMBsetatr);
1582 /****************************************************************************
1584 ****************************************************************************/
1586 void reply_dskattr(struct smb_request *req)
1588 connection_struct *conn = req->conn;
1590 uint64_t dfree,dsize,bsize;
1591 struct smb_filename smb_fname;
1592 START_PROFILE(SMBdskattr);
1594 ZERO_STRUCT(smb_fname);
1595 smb_fname.base_name = discard_const_p(char, ".");
1597 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1598 reply_nterror(req, map_nt_error_from_unix(errno));
1599 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1600 END_PROFILE(SMBdskattr);
1604 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1605 if (ret == (uint64_t)-1) {
1606 reply_nterror(req, map_nt_error_from_unix(errno));
1607 END_PROFILE(SMBdskattr);
1612 * Force max to fit in 16 bit fields.
1614 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1618 if (bsize > (WORDMAX*512)) {
1619 bsize = (WORDMAX*512);
1620 if (dsize > WORDMAX)
1622 if (dfree > WORDMAX)
1628 reply_outbuf(req, 5, 0);
1630 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1631 double total_space, free_space;
1632 /* we need to scale this to a number that DOS6 can handle. We
1633 use floating point so we can handle large drives on systems
1634 that don't have 64 bit integers
1636 we end up displaying a maximum of 2G to DOS systems
1638 total_space = dsize * (double)bsize;
1639 free_space = dfree * (double)bsize;
1641 dsize = (uint64_t)((total_space+63*512) / (64*512));
1642 dfree = (uint64_t)((free_space+63*512) / (64*512));
1644 if (dsize > 0xFFFF) dsize = 0xFFFF;
1645 if (dfree > 0xFFFF) dfree = 0xFFFF;
1647 SSVAL(req->outbuf,smb_vwv0,dsize);
1648 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1649 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1650 SSVAL(req->outbuf,smb_vwv3,dfree);
1652 SSVAL(req->outbuf,smb_vwv0,dsize);
1653 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1654 SSVAL(req->outbuf,smb_vwv2,512);
1655 SSVAL(req->outbuf,smb_vwv3,dfree);
1658 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1660 END_PROFILE(SMBdskattr);
1665 * Utility function to split the filename from the directory.
1667 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1668 char **fname_dir_out,
1669 char **fname_mask_out)
1671 const char *p = NULL;
1672 char *fname_dir = NULL;
1673 char *fname_mask = NULL;
1675 p = strrchr_m(fname_in, '/');
1677 fname_dir = talloc_strdup(ctx, ".");
1678 fname_mask = talloc_strdup(ctx, fname_in);
1680 fname_dir = talloc_strndup(ctx, fname_in,
1681 PTR_DIFF(p, fname_in));
1682 fname_mask = talloc_strdup(ctx, p+1);
1685 if (!fname_dir || !fname_mask) {
1686 TALLOC_FREE(fname_dir);
1687 TALLOC_FREE(fname_mask);
1688 return NT_STATUS_NO_MEMORY;
1691 *fname_dir_out = fname_dir;
1692 *fname_mask_out = fname_mask;
1693 return NT_STATUS_OK;
1696 /****************************************************************************
1698 ****************************************************************************/
1700 static bool make_dir_struct(TALLOC_CTX *ctx,
1710 char *mask2 = talloc_strdup(ctx, mask);
1716 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1720 memset(buf+1,' ',11);
1721 if ((p = strchr_m(mask2,'.')) != NULL) {
1723 push_ascii(buf+1,mask2,8, 0);
1724 push_ascii(buf+9,p+1,3, 0);
1727 push_ascii(buf+1,mask2,11, 0);
1730 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1732 srv_put_dos_date(buf,22,date);
1733 SSVAL(buf,26,size & 0xFFFF);
1734 SSVAL(buf,28,(size >> 16)&0xFFFF);
1735 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1736 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1737 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1738 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1742 /****************************************************************************
1744 Can be called from SMBsearch, SMBffirst or SMBfunique.
1745 ****************************************************************************/
1747 void reply_search(struct smb_request *req)
1749 connection_struct *conn = req->conn;
1752 char *directory = NULL;
1753 struct smb_filename *smb_fname = NULL;
1757 struct timespec date;
1759 unsigned int numentries = 0;
1760 unsigned int maxentries = 0;
1761 bool finished = False;
1766 bool check_descend = False;
1767 bool expect_close = False;
1769 bool mask_contains_wcard = False;
1770 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1771 TALLOC_CTX *ctx = talloc_tos();
1772 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1773 struct smbXsrv_connection *xconn = req->xconn;
1774 struct smbd_server_connection *sconn = req->sconn;
1775 files_struct *fsp = NULL;
1777 START_PROFILE(SMBsearch);
1780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1784 if (req->posix_pathnames) {
1785 reply_unknown_new(req, req->cmd);
1789 /* If we were called as SMBffirst then we must expect close. */
1790 if(req->cmd == SMBffirst) {
1791 expect_close = True;
1794 reply_outbuf(req, 1, 3);
1795 maxentries = SVAL(req->vwv+0, 0);
1796 dirtype = SVAL(req->vwv+1, 0);
1797 p = (const char *)req->buf + 1;
1798 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1799 &nt_status, &mask_contains_wcard);
1800 if (!NT_STATUS_IS_OK(nt_status)) {
1801 reply_nterror(req, nt_status);
1805 if (smbreq_bufrem(req, p) < 3) {
1806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1811 status_len = SVAL(p, 0);
1814 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1816 if (status_len == 0) {
1818 struct smb_filename *smb_dname = NULL;
1819 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1820 ucf_flags_from_smb_request(req);
1821 nt_status = filename_convert(ctx, conn,
1825 &mask_contains_wcard,
1827 if (!NT_STATUS_IS_OK(nt_status)) {
1828 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1829 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1830 ERRSRV, ERRbadpath);
1833 reply_nterror(req, nt_status);
1837 directory = smb_fname->base_name;
1839 p = strrchr_m(directory,'/');
1840 if ((p != NULL) && (*directory != '/')) {
1841 mask = talloc_strdup(ctx, p + 1);
1842 directory = talloc_strndup(ctx, directory,
1843 PTR_DIFF(p, directory));
1845 mask = talloc_strdup(ctx, directory);
1846 directory = talloc_strdup(ctx,".");
1850 reply_nterror(req, NT_STATUS_NO_MEMORY);
1854 memset((char *)status,'\0',21);
1855 SCVAL(status,0,(dirtype & 0x1F));
1857 smb_dname = synthetic_smb_fname(talloc_tos(),
1862 if (smb_dname == NULL) {
1863 reply_nterror(req, NT_STATUS_NO_MEMORY);
1868 * As we've cut off the last component from
1869 * smb_fname we need to re-stat smb_dname
1870 * so FILE_OPEN disposition knows the directory
1873 if (req->posix_pathnames) {
1874 ret = SMB_VFS_LSTAT(conn, smb_dname);
1876 ret = SMB_VFS_STAT(conn, smb_dname);
1879 nt_status = map_nt_error_from_unix(errno);
1880 reply_nterror(req, nt_status);
1885 * Open an fsp on this directory for the dptr.
1887 nt_status = SMB_VFS_CREATE_FILE(
1890 0, /* root_dir_fid */
1891 smb_dname, /* dname */
1892 FILE_LIST_DIRECTORY, /* access_mask */
1894 FILE_SHARE_WRITE, /* share_access */
1895 FILE_OPEN, /* create_disposition*/
1896 FILE_DIRECTORY_FILE, /* create_options */
1897 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1898 NO_OPLOCK, /* oplock_request */
1900 0, /* allocation_size */
1901 0, /* private_flags */
1906 NULL, /* in_context */
1907 NULL);/* out_context */
1909 if (!NT_STATUS_IS_OK(nt_status)) {
1910 DBG_ERR("failed to open directory %s\n",
1911 smb_fname_str_dbg(smb_dname));
1912 reply_nterror(req, nt_status);
1916 nt_status = dptr_create(conn,
1923 mask_contains_wcard,
1927 TALLOC_FREE(smb_dname);
1929 if (!NT_STATUS_IS_OK(nt_status)) {
1931 * Use NULL here for the first parameter (req)
1932 * as this is not a client visible handle so
1933 * can'tbe part of an SMB1 chain.
1935 close_file(NULL, fsp, NORMAL_CLOSE);
1937 reply_nterror(req, nt_status);
1941 dptr_num = dptr_dnum(fsp->dptr);
1945 const char *dirpath;
1947 if (smbreq_bufrem(req, p) < 21) {
1948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1952 memcpy(status,p,21);
1953 status_dirtype = CVAL(status,0) & 0x1F;
1954 if (status_dirtype != (dirtype & 0x1F)) {
1955 dirtype = status_dirtype;
1958 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1962 dirpath = dptr_path(sconn, dptr_num);
1963 directory = talloc_strdup(ctx, dirpath);
1965 reply_nterror(req, NT_STATUS_NO_MEMORY);
1969 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1974 * For a 'continue' search we have no string. So
1975 * check from the initial saved string.
1977 if (!req->posix_pathnames) {
1978 mask_contains_wcard = ms_has_wild(mask);
1980 dirtype = dptr_attr(sconn, dptr_num);
1983 DEBUG(4,("dptr_num is %d\n",dptr_num));
1985 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1986 char buf[DIR_STRUCT_SIZE];
1987 memcpy(buf,status,21);
1988 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1989 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1990 reply_nterror(req, NT_STATUS_NO_MEMORY);
1993 dptr_fill(sconn, buf+12,dptr_num);
1994 if (dptr_zero(buf+12) && (status_len==0)) {
1999 if (message_push_blob(&req->outbuf,
2000 data_blob_const(buf, sizeof(buf)))
2002 reply_nterror(req, NT_STATUS_NO_MEMORY);
2007 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
2008 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
2010 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
2012 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2013 directory,lp_dont_descend(ctx, SNUM(conn))));
2014 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
2015 check_descend = True;
2018 for (i=numentries;(i<maxentries) && !finished;i++) {
2019 finished = !get_dir_entry(ctx,
2030 char buf[DIR_STRUCT_SIZE];
2031 memcpy(buf,status,21);
2032 if (!make_dir_struct(ctx,
2038 convert_timespec_to_time_t(date),
2039 !allow_long_path_components)) {
2040 reply_nterror(req, NT_STATUS_NO_MEMORY);
2043 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2046 if (message_push_blob(&req->outbuf,
2047 data_blob_const(buf, sizeof(buf)))
2049 reply_nterror(req, NT_STATUS_NO_MEMORY);
2059 /* If we were called as SMBffirst with smb_search_id == NULL
2060 and no entries were found then return error and close fsp->dptr
2063 if (numentries == 0) {
2066 close_file(NULL, fsp, NORMAL_CLOSE);
2069 } else if(expect_close && status_len == 0) {
2070 /* Close the dptr - we know it's gone */
2073 close_file(NULL, fsp, NORMAL_CLOSE);
2078 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2079 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2081 /* fsp may have been closed above. */
2083 close_file(NULL, fsp, NORMAL_CLOSE);
2088 if ((numentries == 0) && !mask_contains_wcard) {
2089 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2093 SSVAL(req->outbuf,smb_vwv0,numentries);
2094 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2095 SCVAL(smb_buf(req->outbuf),0,5);
2096 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2098 /* The replies here are never long name. */
2099 SSVAL(req->outbuf, smb_flg2,
2100 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2101 if (!allow_long_path_components) {
2102 SSVAL(req->outbuf, smb_flg2,
2103 SVAL(req->outbuf, smb_flg2)
2104 & (~FLAGS2_LONG_PATH_COMPONENTS));
2107 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2108 SSVAL(req->outbuf, smb_flg2,
2109 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2111 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2112 smb_fn_name(req->cmd),
2119 TALLOC_FREE(directory);
2121 TALLOC_FREE(smb_fname);
2122 END_PROFILE(SMBsearch);
2126 /****************************************************************************
2127 Reply to a fclose (stop directory search).
2128 ****************************************************************************/
2130 void reply_fclose(struct smb_request *req)
2138 bool path_contains_wcard = False;
2139 TALLOC_CTX *ctx = talloc_tos();
2140 struct smbd_server_connection *sconn = req->sconn;
2141 files_struct *fsp = NULL;
2143 START_PROFILE(SMBfclose);
2145 if (req->posix_pathnames) {
2146 reply_unknown_new(req, req->cmd);
2147 END_PROFILE(SMBfclose);
2151 p = (const char *)req->buf + 1;
2152 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2153 &err, &path_contains_wcard);
2154 if (!NT_STATUS_IS_OK(err)) {
2155 reply_nterror(req, err);
2156 END_PROFILE(SMBfclose);
2160 if (smbreq_bufrem(req, p) < 3) {
2161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2162 END_PROFILE(SMBfclose);
2167 status_len = SVAL(p,0);
2170 if (status_len == 0) {
2171 reply_force_doserror(req, ERRSRV, ERRsrverror);
2172 END_PROFILE(SMBfclose);
2176 if (smbreq_bufrem(req, p) < 21) {
2177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2178 END_PROFILE(SMBfclose);
2182 memcpy(status,p,21);
2184 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2186 /* Close the file - we know it's gone */
2187 close_file(NULL, fsp, NORMAL_CLOSE);
2192 reply_outbuf(req, 1, 0);
2193 SSVAL(req->outbuf,smb_vwv0,0);
2195 DEBUG(3,("search close\n"));
2197 END_PROFILE(SMBfclose);
2201 /****************************************************************************
2203 ****************************************************************************/
2205 void reply_open(struct smb_request *req)
2207 connection_struct *conn = req->conn;
2208 struct smb_filename *smb_fname = NULL;
2218 uint32_t access_mask;
2219 uint32_t share_mode;
2220 uint32_t create_disposition;
2221 uint32_t create_options = 0;
2222 uint32_t private_flags = 0;
2225 TALLOC_CTX *ctx = talloc_tos();
2227 START_PROFILE(SMBopen);
2230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2234 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2235 deny_mode = SVAL(req->vwv+0, 0);
2236 dos_attr = SVAL(req->vwv+1, 0);
2238 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2239 STR_TERMINATE, &status);
2240 if (!NT_STATUS_IS_OK(status)) {
2241 reply_nterror(req, status);
2245 if (!map_open_params_to_ntcreate(fname, deny_mode,
2246 OPENX_FILE_EXISTS_OPEN, &access_mask,
2247 &share_mode, &create_disposition,
2248 &create_options, &private_flags)) {
2249 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2253 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2255 status = filename_convert(ctx,
2262 if (!NT_STATUS_IS_OK(status)) {
2263 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2264 reply_botherror(req,
2265 NT_STATUS_PATH_NOT_COVERED,
2266 ERRSRV, ERRbadpath);
2269 reply_nterror(req, status);
2273 status = SMB_VFS_CREATE_FILE(
2276 0, /* root_dir_fid */
2277 smb_fname, /* fname */
2278 access_mask, /* access_mask */
2279 share_mode, /* share_access */
2280 create_disposition, /* create_disposition*/
2281 create_options, /* create_options */
2282 dos_attr, /* file_attributes */
2283 oplock_request, /* oplock_request */
2285 0, /* allocation_size */
2291 NULL, NULL); /* create context */
2293 if (!NT_STATUS_IS_OK(status)) {
2294 if (open_was_deferred(req->xconn, req->mid)) {
2295 /* We have re-scheduled this call. */
2299 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2300 reply_openerror(req, status);
2304 fsp = fcb_or_dos_open(
2311 bool ok = defer_smb1_sharing_violation(req);
2315 reply_openerror(req, status);
2320 /* Ensure we're pointing at the correct stat struct. */
2321 TALLOC_FREE(smb_fname);
2322 smb_fname = fsp->fsp_name;
2324 size = smb_fname->st.st_ex_size;
2325 fattr = dos_mode(conn, smb_fname);
2327 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2329 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2330 DEBUG(3,("attempt to open a directory %s\n",
2332 close_file(req, fsp, ERROR_CLOSE);
2333 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2334 ERRDOS, ERRnoaccess);
2338 reply_outbuf(req, 7, 0);
2339 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2340 SSVAL(req->outbuf,smb_vwv1,fattr);
2341 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2342 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2344 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2346 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2347 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2349 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2350 SCVAL(req->outbuf,smb_flg,
2351 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2354 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2355 SCVAL(req->outbuf,smb_flg,
2356 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2359 END_PROFILE(SMBopen);
2363 /****************************************************************************
2364 Reply to an open and X.
2365 ****************************************************************************/
2367 void reply_open_and_X(struct smb_request *req)
2369 connection_struct *conn = req->conn;
2370 struct smb_filename *smb_fname = NULL;
2372 uint16_t open_flags;
2375 /* Breakout the oplock request bits so we can set the
2376 reply bits separately. */
2377 int ex_oplock_request;
2378 int core_oplock_request;
2381 int smb_sattr = SVAL(req->vwv+4, 0);
2382 uint32_t smb_time = make_unix_date3(req->vwv+6);
2390 uint64_t allocation_size;
2391 ssize_t retval = -1;
2392 uint32_t access_mask;
2393 uint32_t share_mode;
2394 uint32_t create_disposition;
2395 uint32_t create_options = 0;
2396 uint32_t private_flags = 0;
2398 TALLOC_CTX *ctx = talloc_tos();
2400 START_PROFILE(SMBopenX);
2402 if (req->wct < 15) {
2403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2407 open_flags = SVAL(req->vwv+2, 0);
2408 deny_mode = SVAL(req->vwv+3, 0);
2409 smb_attr = SVAL(req->vwv+5, 0);
2410 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2411 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2412 oplock_request = ex_oplock_request | core_oplock_request;
2413 smb_ofun = SVAL(req->vwv+8, 0);
2414 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2416 /* If it's an IPC, pass off the pipe handler. */
2418 if (lp_nt_pipe_support()) {
2419 reply_open_pipe_and_X(conn, req);
2421 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2426 /* XXXX we need to handle passed times, sattr and flags */
2427 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2428 STR_TERMINATE, &status);
2429 if (!NT_STATUS_IS_OK(status)) {
2430 reply_nterror(req, status);
2434 if (!map_open_params_to_ntcreate(fname, deny_mode,
2436 &access_mask, &share_mode,
2437 &create_disposition,
2440 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2444 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2446 status = filename_convert(ctx,
2453 if (!NT_STATUS_IS_OK(status)) {
2454 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2455 reply_botherror(req,
2456 NT_STATUS_PATH_NOT_COVERED,
2457 ERRSRV, ERRbadpath);
2460 reply_nterror(req, status);
2464 status = SMB_VFS_CREATE_FILE(
2467 0, /* root_dir_fid */
2468 smb_fname, /* fname */
2469 access_mask, /* access_mask */
2470 share_mode, /* share_access */
2471 create_disposition, /* create_disposition*/
2472 create_options, /* create_options */
2473 smb_attr, /* file_attributes */
2474 oplock_request, /* oplock_request */
2476 0, /* allocation_size */
2481 &smb_action, /* pinfo */
2482 NULL, NULL); /* create context */
2484 if (!NT_STATUS_IS_OK(status)) {
2485 if (open_was_deferred(req->xconn, req->mid)) {
2486 /* We have re-scheduled this call. */
2490 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2491 reply_openerror(req, status);
2495 fsp = fcb_or_dos_open(
2502 bool ok = defer_smb1_sharing_violation(req);
2506 reply_openerror(req, status);
2511 smb_action = FILE_WAS_OPENED;
2514 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2515 if the file is truncated or created. */
2516 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2517 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2518 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2519 close_file(req, fsp, ERROR_CLOSE);
2520 reply_nterror(req, NT_STATUS_DISK_FULL);
2523 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2525 close_file(req, fsp, ERROR_CLOSE);
2526 reply_nterror(req, NT_STATUS_DISK_FULL);
2529 status = vfs_stat_fsp(fsp);
2530 if (!NT_STATUS_IS_OK(status)) {
2531 close_file(req, fsp, ERROR_CLOSE);
2532 reply_nterror(req, status);
2537 fattr = dos_mode(conn, fsp->fsp_name);
2538 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2539 close_file(req, fsp, ERROR_CLOSE);
2540 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2543 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2545 /* If the caller set the extended oplock request bit
2546 and we granted one (by whatever means) - set the
2547 correct bit for extended oplock reply.
2550 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2551 smb_action |= EXTENDED_OPLOCK_GRANTED;
2554 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2555 smb_action |= EXTENDED_OPLOCK_GRANTED;
2558 /* If the caller set the core oplock request bit
2559 and we granted one (by whatever means) - set the
2560 correct bit for core oplock reply.
2563 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2564 reply_outbuf(req, 19, 0);
2566 reply_outbuf(req, 15, 0);
2569 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2570 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2572 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2573 SCVAL(req->outbuf, smb_flg,
2574 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2577 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2578 SCVAL(req->outbuf, smb_flg,
2579 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2582 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2583 SSVAL(req->outbuf,smb_vwv3,fattr);
2584 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2585 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2587 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2589 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2590 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2591 SSVAL(req->outbuf,smb_vwv11,smb_action);
2593 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2594 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2598 TALLOC_FREE(smb_fname);
2599 END_PROFILE(SMBopenX);
2603 /****************************************************************************
2604 Reply to a SMBulogoffX.
2605 ****************************************************************************/
2607 void reply_ulogoffX(struct smb_request *req)
2609 struct smbd_server_connection *sconn = req->sconn;
2610 struct user_struct *vuser;
2611 struct smbXsrv_session *session = NULL;
2614 START_PROFILE(SMBulogoffX);
2616 vuser = get_valid_user_struct(sconn, req->vuid);
2619 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2620 (unsigned long long)req->vuid));
2622 req->vuid = UID_FIELD_INVALID;
2623 reply_force_doserror(req, ERRSRV, ERRbaduid);
2624 END_PROFILE(SMBulogoffX);
2628 session = vuser->session;
2632 * TODO: cancel all outstanding requests on the session
2634 status = smbXsrv_session_logoff(session);
2635 if (!NT_STATUS_IS_OK(status)) {
2636 DEBUG(0, ("reply_ulogoff: "
2637 "smbXsrv_session_logoff() failed: %s\n",
2638 nt_errstr(status)));
2640 * If we hit this case, there is something completely
2641 * wrong, so we better disconnect the transport connection.
2643 END_PROFILE(SMBulogoffX);
2644 exit_server(__location__ ": smbXsrv_session_logoff failed");
2648 TALLOC_FREE(session);
2650 reply_outbuf(req, 2, 0);
2651 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2652 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2654 DEBUG(3, ("ulogoffX vuid=%llu\n",
2655 (unsigned long long)req->vuid));
2657 END_PROFILE(SMBulogoffX);
2658 req->vuid = UID_FIELD_INVALID;
2661 /****************************************************************************
2662 Reply to a mknew or a create.
2663 ****************************************************************************/
2665 void reply_mknew(struct smb_request *req)
2667 connection_struct *conn = req->conn;
2668 struct smb_filename *smb_fname = NULL;
2671 struct smb_file_time ft;
2673 int oplock_request = 0;
2675 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2676 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2677 uint32_t create_disposition;
2678 uint32_t create_options = 0;
2680 TALLOC_CTX *ctx = talloc_tos();
2682 START_PROFILE(SMBcreate);
2686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2690 fattr = SVAL(req->vwv+0, 0);
2691 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2693 if (req->cmd == SMBmknew) {
2694 /* We should fail if file exists. */
2695 create_disposition = FILE_CREATE;
2697 /* Create if file doesn't exist, truncate if it does. */
2698 create_disposition = FILE_OVERWRITE_IF;
2702 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2704 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2705 STR_TERMINATE, &status);
2706 if (!NT_STATUS_IS_OK(status)) {
2707 reply_nterror(req, status);
2711 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2712 status = filename_convert(ctx,
2719 if (!NT_STATUS_IS_OK(status)) {
2720 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2721 reply_botherror(req,
2722 NT_STATUS_PATH_NOT_COVERED,
2723 ERRSRV, ERRbadpath);
2726 reply_nterror(req, status);
2730 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2731 DEBUG(0,("Attempt to create file (%s) with volid set - "
2732 "please report this\n",
2733 smb_fname_str_dbg(smb_fname)));
2736 status = SMB_VFS_CREATE_FILE(
2739 0, /* root_dir_fid */
2740 smb_fname, /* fname */
2741 access_mask, /* access_mask */
2742 share_mode, /* share_access */
2743 create_disposition, /* create_disposition*/
2744 create_options, /* create_options */
2745 fattr, /* file_attributes */
2746 oplock_request, /* oplock_request */
2748 0, /* allocation_size */
2749 0, /* private_flags */
2754 NULL, NULL); /* create context */
2756 if (!NT_STATUS_IS_OK(status)) {
2757 if (open_was_deferred(req->xconn, req->mid)) {
2758 /* We have re-scheduled this call. */
2761 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2762 bool ok = defer_smb1_sharing_violation(req);
2767 reply_openerror(req, status);
2771 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2772 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2773 if (!NT_STATUS_IS_OK(status)) {
2774 END_PROFILE(SMBcreate);
2778 reply_outbuf(req, 1, 0);
2779 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2781 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2782 SCVAL(req->outbuf,smb_flg,
2783 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2786 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2787 SCVAL(req->outbuf,smb_flg,
2788 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2791 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2792 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2793 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2794 (unsigned int)fattr));
2797 TALLOC_FREE(smb_fname);
2798 END_PROFILE(SMBcreate);
2802 /****************************************************************************
2803 Reply to a create temporary file.
2804 ****************************************************************************/
2806 void reply_ctemp(struct smb_request *req)
2808 connection_struct *conn = req->conn;
2809 struct smb_filename *smb_fname = NULL;
2810 char *wire_name = NULL;
2819 TALLOC_CTX *ctx = talloc_tos();
2821 START_PROFILE(SMBctemp);
2824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2828 fattr = SVAL(req->vwv+0, 0);
2829 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2831 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2832 STR_TERMINATE, &status);
2833 if (!NT_STATUS_IS_OK(status)) {
2834 reply_nterror(req, status);
2838 for (i = 0; i < 10; i++) {
2840 fname = talloc_asprintf(ctx,
2843 generate_random_str_list(ctx, 5, "0123456789"));
2845 fname = talloc_asprintf(ctx,
2847 generate_random_str_list(ctx, 5, "0123456789"));
2851 reply_nterror(req, NT_STATUS_NO_MEMORY);
2855 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2856 status = filename_convert(ctx, conn,
2862 if (!NT_STATUS_IS_OK(status)) {
2863 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2864 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2865 ERRSRV, ERRbadpath);
2868 reply_nterror(req, status);
2872 /* Create the file. */
2873 status = SMB_VFS_CREATE_FILE(
2876 0, /* root_dir_fid */
2877 smb_fname, /* fname */
2878 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2879 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2880 FILE_CREATE, /* create_disposition*/
2881 0, /* create_options */
2882 fattr, /* file_attributes */
2883 oplock_request, /* oplock_request */
2885 0, /* allocation_size */
2886 0, /* private_flags */
2891 NULL, NULL); /* create context */
2893 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2895 TALLOC_FREE(smb_fname);
2899 if (!NT_STATUS_IS_OK(status)) {
2900 if (open_was_deferred(req->xconn, req->mid)) {
2901 /* We have re-scheduled this call. */
2904 if (NT_STATUS_EQUAL(
2905 status, NT_STATUS_SHARING_VIOLATION)) {
2906 bool ok = defer_smb1_sharing_violation(req);
2911 reply_openerror(req, status);
2919 /* Collision after 10 times... */
2920 reply_nterror(req, status);
2924 reply_outbuf(req, 1, 0);
2925 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2927 /* the returned filename is relative to the directory */
2928 s = strrchr_m(fsp->fsp_name->base_name, '/');
2930 s = fsp->fsp_name->base_name;
2936 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2937 thing in the byte section. JRA */
2938 SSVALS(p, 0, -1); /* what is this? not in spec */
2940 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2942 reply_nterror(req, NT_STATUS_NO_MEMORY);
2946 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2947 SCVAL(req->outbuf, smb_flg,
2948 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2951 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2952 SCVAL(req->outbuf, smb_flg,
2953 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2956 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2957 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2958 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2960 TALLOC_FREE(smb_fname);
2961 TALLOC_FREE(wire_name);
2962 END_PROFILE(SMBctemp);
2966 /*******************************************************************
2967 Check if a user is allowed to rename a file.
2968 ********************************************************************/
2970 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2973 if (!CAN_WRITE(conn)) {
2974 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2977 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2978 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2979 /* Only bother to read the DOS attribute if we might deny the
2980 rename on the grounds of attribute mismatch. */
2981 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2982 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2983 return NT_STATUS_NO_SUCH_FILE;
2987 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2988 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2989 return NT_STATUS_OK;
2992 /* If no pathnames are open below this
2993 directory, allow the rename. */
2995 if (lp_strict_rename(SNUM(conn))) {
2997 * Strict rename, check open file db.
2999 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3000 return NT_STATUS_ACCESS_DENIED;
3002 } else if (file_find_subpath(fsp)) {
3004 * No strict rename, just look in local process.
3006 return NT_STATUS_ACCESS_DENIED;
3008 return NT_STATUS_OK;
3011 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3012 return NT_STATUS_OK;
3015 return NT_STATUS_ACCESS_DENIED;
3018 /*******************************************************************
3019 * unlink a file with all relevant access checks
3020 *******************************************************************/
3022 static NTSTATUS do_unlink(connection_struct *conn,
3023 struct smb_request *req,
3024 struct smb_filename *smb_fname,
3029 uint32_t dirtype_orig = dirtype;
3032 bool posix_paths = (req != NULL && req->posix_pathnames);
3034 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3035 smb_fname_str_dbg(smb_fname),
3038 if (!CAN_WRITE(conn)) {
3039 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3043 ret = SMB_VFS_LSTAT(conn, smb_fname);
3045 ret = SMB_VFS_STAT(conn, smb_fname);
3048 return map_nt_error_from_unix(errno);
3051 fattr = dos_mode(conn, smb_fname);
3053 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3054 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3057 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3059 return NT_STATUS_NO_SUCH_FILE;
3062 if (!dir_check_ftype(fattr, dirtype)) {
3063 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3064 return NT_STATUS_FILE_IS_A_DIRECTORY;
3066 return NT_STATUS_NO_SUCH_FILE;
3069 if (dirtype_orig & 0x8000) {
3070 /* These will never be set for POSIX. */
3071 return NT_STATUS_NO_SUCH_FILE;
3075 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3076 return NT_STATUS_FILE_IS_A_DIRECTORY;
3079 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3080 return NT_STATUS_NO_SUCH_FILE;
3083 if (dirtype & 0xFF00) {
3084 /* These will never be set for POSIX. */
3085 return NT_STATUS_NO_SUCH_FILE;
3090 return NT_STATUS_NO_SUCH_FILE;
3093 /* Can't delete a directory. */
3094 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3095 return NT_STATUS_FILE_IS_A_DIRECTORY;
3100 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3101 return NT_STATUS_OBJECT_NAME_INVALID;
3102 #endif /* JRATEST */
3104 /* On open checks the open itself will check the share mode, so
3105 don't do it here as we'll get it wrong. */
3107 status = SMB_VFS_CREATE_FILE
3110 0, /* root_dir_fid */
3111 smb_fname, /* fname */
3112 DELETE_ACCESS, /* access_mask */
3113 FILE_SHARE_NONE, /* share_access */
3114 FILE_OPEN, /* create_disposition*/
3115 FILE_NON_DIRECTORY_FILE, /* create_options */
3116 /* file_attributes */
3117 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
3118 FILE_ATTRIBUTE_NORMAL,
3119 0, /* oplock_request */
3121 0, /* allocation_size */
3122 0, /* private_flags */
3127 NULL, NULL); /* create context */
3129 if (!NT_STATUS_IS_OK(status)) {
3130 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3131 nt_errstr(status)));
3135 status = can_set_delete_on_close(fsp, fattr);
3136 if (!NT_STATUS_IS_OK(status)) {
3137 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3139 smb_fname_str_dbg(smb_fname),
3140 nt_errstr(status)));
3141 close_file(req, fsp, NORMAL_CLOSE);
3145 /* The set is across all open files on this dev/inode pair. */
3146 if (!set_delete_on_close(fsp, True,
3147 conn->session_info->security_token,
3148 conn->session_info->unix_token)) {
3149 close_file(req, fsp, NORMAL_CLOSE);
3150 return NT_STATUS_ACCESS_DENIED;
3153 return close_file(req, fsp, NORMAL_CLOSE);
3156 /****************************************************************************
3157 The guts of the unlink command, split out so it may be called by the NT SMB
3159 ****************************************************************************/
3161 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3162 uint32_t dirtype, struct smb_filename *smb_fname,
3165 char *fname_dir = NULL;
3166 char *fname_mask = NULL;
3168 NTSTATUS status = NT_STATUS_OK;
3169 struct smb_filename *smb_fname_dir = NULL;
3170 TALLOC_CTX *ctx = talloc_tos();
3172 /* Split up the directory from the filename/mask. */
3173 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3174 &fname_dir, &fname_mask);
3175 if (!NT_STATUS_IS_OK(status)) {
3180 * We should only check the mangled cache
3181 * here if unix_convert failed. This means
3182 * that the path in 'mask' doesn't exist
3183 * on the file system and so we need to look
3184 * for a possible mangle. This patch from
3185 * Tine Smukavec <valentin.smukavec@hermes.si>.
3188 if (!VALID_STAT(smb_fname->st) &&
3189 mangle_is_mangled(fname_mask, conn->params)) {
3190 char *new_mask = NULL;
3191 mangle_lookup_name_from_8_3(ctx, fname_mask,
3192 &new_mask, conn->params);
3194 TALLOC_FREE(fname_mask);
3195 fname_mask = new_mask;
3202 * Only one file needs to be unlinked. Append the mask back
3203 * onto the directory.
3205 TALLOC_FREE(smb_fname->base_name);
3206 if (ISDOT(fname_dir)) {
3207 /* Ensure we use canonical names on open. */
3208 smb_fname->base_name = talloc_asprintf(smb_fname,
3212 smb_fname->base_name = talloc_asprintf(smb_fname,
3217 if (!smb_fname->base_name) {
3218 status = NT_STATUS_NO_MEMORY;
3222 dirtype = FILE_ATTRIBUTE_NORMAL;
3225 status = check_name(conn, smb_fname);
3226 if (!NT_STATUS_IS_OK(status)) {
3230 status = do_unlink(conn, req, smb_fname, dirtype);
3231 if (!NT_STATUS_IS_OK(status)) {
3237 struct smb_Dir *dir_hnd = NULL;
3239 const char *dname = NULL;
3240 char *talloced = NULL;
3242 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3243 status = NT_STATUS_OBJECT_NAME_INVALID;
3247 dirtype = FILE_ATTRIBUTE_NORMAL;
3250 if (strequal(fname_mask,"????????.???")) {
3251 TALLOC_FREE(fname_mask);
3252 fname_mask = talloc_strdup(ctx, "*");
3254 status = NT_STATUS_NO_MEMORY;
3259 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3264 if (smb_fname_dir == NULL) {
3265 status = NT_STATUS_NO_MEMORY;
3269 status = check_name(conn, smb_fname_dir);
3270 if (!NT_STATUS_IS_OK(status)) {
3274 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3276 if (dir_hnd == NULL) {
3277 status = map_nt_error_from_unix(errno);
3281 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3282 the pattern matches against the long name, otherwise the short name
3283 We don't implement this yet XXXX
3286 status = NT_STATUS_NO_SUCH_FILE;
3288 while ((dname = ReadDirName(dir_hnd, &offset,
3289 &smb_fname->st, &talloced))) {
3290 TALLOC_CTX *frame = talloc_stackframe();
3292 if (!is_visible_file(conn, fname_dir, dname,
3293 &smb_fname->st, true)) {
3295 TALLOC_FREE(talloced);
3299 /* Quick check for "." and ".." */
3300 if (ISDOT(dname) || ISDOTDOT(dname)) {
3302 TALLOC_FREE(talloced);
3306 if(!mask_match(dname, fname_mask,
3307 conn->case_sensitive)) {
3309 TALLOC_FREE(talloced);
3313 TALLOC_FREE(smb_fname->base_name);
3314 if (ISDOT(fname_dir)) {
3315 /* Ensure we use canonical names on open. */
3316 smb_fname->base_name =
3317 talloc_asprintf(smb_fname, "%s",
3320 smb_fname->base_name =
3321 talloc_asprintf(smb_fname, "%s/%s",
3325 if (!smb_fname->base_name) {
3326 TALLOC_FREE(dir_hnd);
3327 status = NT_STATUS_NO_MEMORY;
3329 TALLOC_FREE(talloced);
3333 status = check_name(conn, smb_fname);
3334 if (!NT_STATUS_IS_OK(status)) {
3335 TALLOC_FREE(dir_hnd);
3337 TALLOC_FREE(talloced);
3341 status = do_unlink(conn, req, smb_fname, dirtype);
3342 if (!NT_STATUS_IS_OK(status)) {
3343 TALLOC_FREE(dir_hnd);
3345 TALLOC_FREE(talloced);
3350 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3351 smb_fname->base_name));
3354 TALLOC_FREE(talloced);
3356 TALLOC_FREE(dir_hnd);
3359 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3360 status = map_nt_error_from_unix(errno);
3364 TALLOC_FREE(smb_fname_dir);
3365 TALLOC_FREE(fname_dir);
3366 TALLOC_FREE(fname_mask);
3370 /****************************************************************************
3372 ****************************************************************************/
3374 void reply_unlink(struct smb_request *req)
3376 connection_struct *conn = req->conn;
3378 struct smb_filename *smb_fname = NULL;
3381 bool path_contains_wcard = False;
3382 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3383 ucf_flags_from_smb_request(req);
3384 TALLOC_CTX *ctx = talloc_tos();
3386 START_PROFILE(SMBunlink);
3389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3393 dirtype = SVAL(req->vwv+0, 0);
3395 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3396 STR_TERMINATE, &status,
3397 &path_contains_wcard);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 reply_nterror(req, status);
3403 status = filename_convert(ctx, conn,
3407 &path_contains_wcard,
3409 if (!NT_STATUS_IS_OK(status)) {
3410 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3411 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3412 ERRSRV, ERRbadpath);
3415 reply_nterror(req, status);
3419 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3421 status = unlink_internals(conn, req, dirtype, smb_fname,
3422 path_contains_wcard);
3423 if (!NT_STATUS_IS_OK(status)) {
3424 if (open_was_deferred(req->xconn, req->mid)) {
3425 /* We have re-scheduled this call. */
3428 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3429 bool ok = defer_smb1_sharing_violation(req);
3434 reply_nterror(req, status);
3438 reply_outbuf(req, 0, 0);
3440 TALLOC_FREE(smb_fname);
3441 END_PROFILE(SMBunlink);
3445 /****************************************************************************
3447 ****************************************************************************/
3449 static void fail_readraw(void)
3451 const char *errstr = talloc_asprintf(talloc_tos(),
3452 "FAIL ! reply_readbraw: socket write fail (%s)",
3457 exit_server_cleanly(errstr);
3460 /****************************************************************************
3461 Fake (read/write) sendfile. Returns -1 on read or write fail.
3462 ****************************************************************************/
3464 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3465 off_t startpos, size_t nread)
3468 size_t tosend = nread;
3475 bufsize = MIN(nread, 65536);
3477 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3481 while (tosend > 0) {
3485 cur_read = MIN(tosend, bufsize);
3486 ret = read_file(fsp,buf,startpos,cur_read);
3492 /* If we had a short read, fill with zeros. */
3493 if (ret < cur_read) {
3494 memset(buf + ret, '\0', cur_read - ret);
3497 ret = write_data(xconn->transport.sock, buf, cur_read);
3498 if (ret != cur_read) {
3499 int saved_errno = errno;
3501 * Try and give an error message saying what
3504 DEBUG(0, ("write_data failed for client %s. "
3506 smbXsrv_connection_dbg(xconn),
3507 strerror(saved_errno)));
3509 errno = saved_errno;
3513 startpos += cur_read;
3517 return (ssize_t)nread;
3520 /****************************************************************************
3521 Deal with the case of sendfile reading less bytes from the file than
3522 requested. Fill with zeros (all we can do). Returns 0 on success
3523 ****************************************************************************/
3525 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3531 #define SHORT_SEND_BUFSIZE 1024
3532 if (nread < headersize) {
3533 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3534 "header for file %s (%s). Terminating\n",
3535 fsp_str_dbg(fsp), strerror(errno)));
3539 nread -= headersize;
3541 if (nread < smb_maxcnt) {
3542 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3544 DEBUG(0,("sendfile_short_send: malloc failed "
3545 "for file %s (%s). Terminating\n",
3546 fsp_str_dbg(fsp), strerror(errno)));
3550 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3551 "with zeros !\n", fsp_str_dbg(fsp)));
3553 while (nread < smb_maxcnt) {
3555 * We asked for the real file size and told sendfile
3556 * to not go beyond the end of the file. But it can
3557 * happen that in between our fstat call and the
3558 * sendfile call the file was truncated. This is very
3559 * bad because we have already announced the larger
3560 * number of bytes to the client.
3562 * The best we can do now is to send 0-bytes, just as
3563 * a read from a hole in a sparse file would do.
3565 * This should happen rarely enough that I don't care
3566 * about efficiency here :-)
3571 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3572 ret = write_data(xconn->transport.sock, buf, to_write);
3573 if (ret != to_write) {
3574 int saved_errno = errno;
3576 * Try and give an error message saying what
3579 DEBUG(0, ("write_data failed for client %s. "
3581 smbXsrv_connection_dbg(xconn),
3582 strerror(saved_errno)));
3583 errno = saved_errno;
3594 /****************************************************************************
3595 Return a readbraw error (4 bytes of zero).
3596 ****************************************************************************/
3598 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3604 smbd_lock_socket(xconn);
3605 if (write_data(xconn->transport.sock,header,4) != 4) {
3606 int saved_errno = errno;
3608 * Try and give an error message saying what
3611 DEBUG(0, ("write_data failed for client %s. "
3613 smbXsrv_connection_dbg(xconn),
3614 strerror(saved_errno)));
3615 errno = saved_errno;
3619 smbd_unlock_socket(xconn);
3622 /****************************************************************************
3623 Use sendfile in readbraw.
3624 ****************************************************************************/
3626 static void send_file_readbraw(connection_struct *conn,
3627 struct smb_request *req,
3633 struct smbXsrv_connection *xconn = req->xconn;
3634 char *outbuf = NULL;
3638 * We can only use sendfile on a non-chained packet
3639 * but we can use on a non-oplocked file. tridge proved this
3640 * on a train in Germany :-). JRA.
3641 * reply_readbraw has already checked the length.
3644 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3645 (fsp->wcp == NULL) &&
3646 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3647 ssize_t sendfile_read = -1;
3649 DATA_BLOB header_blob;
3651 _smb_setlen(header,nread);
3652 header_blob = data_blob_const(header, 4);
3654 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3655 &header_blob, startpos,
3657 if (sendfile_read == -1) {
3658 /* Returning ENOSYS means no data at all was sent.
3659 * Do this as a normal read. */
3660 if (errno == ENOSYS) {
3661 goto normal_readbraw;
3665 * Special hack for broken Linux with no working sendfile. If we
3666 * return EINTR we sent the header but not the rest of the data.
3667 * Fake this up by doing read/write calls.
3669 if (errno == EINTR) {
3670 /* Ensure we don't do this again. */
3671 set_use_sendfile(SNUM(conn), False);
3672 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3674 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3675 DEBUG(0,("send_file_readbraw: "
3676 "fake_sendfile failed for "
3680 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3685 DEBUG(0,("send_file_readbraw: sendfile failed for "
3686 "file %s (%s). Terminating\n",
3687 fsp_str_dbg(fsp), strerror(errno)));
3688 exit_server_cleanly("send_file_readbraw sendfile failed");
3689 } else if (sendfile_read == 0) {
3691 * Some sendfile implementations return 0 to indicate
3692 * that there was a short read, but nothing was
3693 * actually written to the socket. In this case,
3694 * fallback to the normal read path so the header gets
3695 * the correct byte count.
3697 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3698 "bytes falling back to the normal read: "
3699 "%s\n", fsp_str_dbg(fsp)));
3700 goto normal_readbraw;
3703 /* Deal with possible short send. */
3704 if (sendfile_read != 4+nread) {
3705 ret = sendfile_short_send(xconn, fsp,
3706 sendfile_read, 4, nread);
3716 outbuf = talloc_array(NULL, char, nread+4);
3718 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3719 (unsigned)(nread+4)));
3720 reply_readbraw_error(xconn);
3725 ret = read_file(fsp,outbuf+4,startpos,nread);
3726 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3735 _smb_setlen(outbuf,ret);
3736 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3737 int saved_errno = errno;
3739 * Try and give an error message saying what
3742 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3743 smbXsrv_connection_dbg(xconn),
3744 strerror(saved_errno)));
3745 errno = saved_errno;
3750 TALLOC_FREE(outbuf);
3753 /****************************************************************************
3754 Reply to a readbraw (core+ protocol).
3755 ****************************************************************************/
3757 void reply_readbraw(struct smb_request *req)
3759 connection_struct *conn = req->conn;
3760 struct smbXsrv_connection *xconn = req->xconn;
3761 ssize_t maxcount,mincount;
3765 struct lock_struct lock;
3768 START_PROFILE(SMBreadbraw);
3770 if (srv_is_signing_active(xconn) || req->encrypted) {
3771 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3772 "raw reads/writes are disallowed.");
3776 reply_readbraw_error(xconn);
3777 END_PROFILE(SMBreadbraw);
3781 if (xconn->smb1.echo_handler.trusted_fde) {
3782 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3783 "'async smb echo handler = yes'\n"));
3784 reply_readbraw_error(xconn);
3785 END_PROFILE(SMBreadbraw);
3790 * Special check if an oplock break has been issued
3791 * and the readraw request croses on the wire, we must
3792 * return a zero length response here.
3795 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3798 * We have to do a check_fsp by hand here, as
3799 * we must always return 4 zero bytes on error,
3803 if (!fsp || !conn || conn != fsp->conn ||
3804 req->vuid != fsp->vuid ||
3805 fsp->is_directory || fsp->fh->fd == -1) {
3807 * fsp could be NULL here so use the value from the packet. JRA.
3809 DEBUG(3,("reply_readbraw: fnum %d not valid "
3811 (int)SVAL(req->vwv+0, 0)));
3812 reply_readbraw_error(xconn);
3813 END_PROFILE(SMBreadbraw);
3817 /* Do a "by hand" version of CHECK_READ. */
3818 if (!(fsp->can_read ||
3819 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3820 (fsp->access_mask & FILE_EXECUTE)))) {
3821 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3822 (int)SVAL(req->vwv+0, 0)));
3823 reply_readbraw_error(xconn);
3824 END_PROFILE(SMBreadbraw);
3828 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3830 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3831 if(req->wct == 10) {
3833 * This is a large offset (64 bit) read.
3836 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3839 DEBUG(0,("reply_readbraw: negative 64 bit "
3840 "readraw offset (%.0f) !\n",
3841 (double)startpos ));
3842 reply_readbraw_error(xconn);
3843 END_PROFILE(SMBreadbraw);
3848 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3849 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3851 /* ensure we don't overrun the packet size */
3852 maxcount = MIN(65535,maxcount);
3854 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3855 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3858 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3859 reply_readbraw_error(xconn);
3860 END_PROFILE(SMBreadbraw);
3864 if (fsp_stat(fsp) == 0) {
3865 size = fsp->fsp_name->st.st_ex_size;
3868 if (startpos >= size) {
3871 nread = MIN(maxcount,(size - startpos));
3874 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3875 if (nread < mincount)
3879 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3880 "min=%lu nread=%lu\n",
3881 fsp_fnum_dbg(fsp), (double)startpos,
3882 (unsigned long)maxcount,
3883 (unsigned long)mincount,
3884 (unsigned long)nread ) );
3886 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3888 DEBUG(5,("reply_readbraw finished\n"));
3890 END_PROFILE(SMBreadbraw);
3895 #define DBGC_CLASS DBGC_LOCKING
3897 /****************************************************************************
3898 Reply to a lockread (core+ protocol).
3899 ****************************************************************************/
3901 static void reply_lockread_locked(struct tevent_req *subreq);
3903 void reply_lockread(struct smb_request *req)
3905 struct tevent_req *subreq = NULL;
3906 connection_struct *conn = req->conn;
3908 struct smbd_lock_element *lck = NULL;
3910 START_PROFILE(SMBlockread);
3913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3914 END_PROFILE(SMBlockread);
3918 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3920 if (!check_fsp(conn, req, fsp)) {
3921 END_PROFILE(SMBlockread);
3925 if (!CHECK_READ(fsp,req)) {
3926 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3927 END_PROFILE(SMBlockread);
3931 lck = talloc(req, struct smbd_lock_element);
3933 reply_nterror(req, NT_STATUS_NO_MEMORY);
3934 END_PROFILE(SMBlockread);
3939 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3940 * protocol request that predates the read/write lock concept.
3941 * Thus instead of asking for a read lock here we need to ask
3942 * for a write lock. JRA.
3943 * Note that the requested lock size is unaffected by max_send.
3946 *lck = (struct smbd_lock_element) {
3947 .smblctx = req->smbpid,
3948 .brltype = WRITE_LOCK,
3949 .count = SVAL(req->vwv+1, 0),
3950 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3953 subreq = smbd_smb1_do_locks_send(
3959 false, /* large_offset */
3963 if (subreq == NULL) {
3964 reply_nterror(req, NT_STATUS_NO_MEMORY);
3965 END_PROFILE(SMBlockread);
3968 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3969 END_PROFILE(SMBlockread);
3972 static void reply_lockread_locked(struct tevent_req *subreq)
3974 struct smb_request *req = NULL;
3980 size_t numtoread, maxtoread;
3981 struct files_struct *fsp = NULL;
3984 START_PROFILE(SMBlockread);
3986 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3989 status = smbd_smb1_do_locks_recv(subreq);
3990 TALLOC_FREE(subreq);
3992 if (!NT_STATUS_IS_OK(status)) {
3993 reply_nterror(req, status);
3997 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3999 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4003 numtoread = SVAL(req->vwv+1, 0);
4004 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4007 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4009 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4011 if (numtoread > maxtoread) {
4012 DBG_WARNING("requested read size (%zu) is greater than "
4013 "maximum allowed (%zu/%d). "
4014 "Returning short read of maximum allowed for "
4015 "compatibility with Windows 2000.\n",
4018 req->xconn->smb1.sessions.max_send);
4019 numtoread = maxtoread;
4022 reply_outbuf(req, 5, numtoread + 3);
4024 data = smb_buf(req->outbuf) + 3;
4026 nread = read_file(fsp,data,startpos,numtoread);
4029 reply_nterror(req, map_nt_error_from_unix(errno));
4033 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4035 SSVAL(req->outbuf,smb_vwv0,nread);
4036 SSVAL(req->outbuf,smb_vwv5,nread+3);
4037 p = smb_buf(req->outbuf);
4038 SCVAL(p,0,0); /* pad byte. */
4041 DEBUG(3,("lockread %s num=%d nread=%d\n",
4042 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4045 ok = srv_send_smb(req->xconn,
4046 (char *)req->outbuf,
4049 IS_CONN_ENCRYPTED(req->conn),
4052 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4055 END_PROFILE(SMBlockread);
4060 #define DBGC_CLASS DBGC_ALL
4062 /****************************************************************************
4064 ****************************************************************************/
4066 void reply_read(struct smb_request *req)
4068 connection_struct *conn = req->conn;
4075 struct lock_struct lock;
4076 struct smbXsrv_connection *xconn = req->xconn;
4078 START_PROFILE(SMBread);
4081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4082 END_PROFILE(SMBread);
4086 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4088 if (!check_fsp(conn, req, fsp)) {
4089 END_PROFILE(SMBread);
4093 if (!CHECK_READ(fsp,req)) {
4094 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4095 END_PROFILE(SMBread);
4099 numtoread = SVAL(req->vwv+1, 0);
4100 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4103 * The requested read size cannot be greater than max_send. JRA.
4105 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4107 if (numtoread > maxtoread) {
4108 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4109 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4110 (unsigned int)numtoread, (unsigned int)maxtoread,
4111 (unsigned int)xconn->smb1.sessions.max_send));
4112 numtoread = maxtoread;
4115 reply_outbuf(req, 5, numtoread+3);
4117 data = smb_buf(req->outbuf) + 3;
4119 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4120 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4123 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4124 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4125 END_PROFILE(SMBread);
4130 nread = read_file(fsp,data,startpos,numtoread);
4133 reply_nterror(req, map_nt_error_from_unix(errno));
4137 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4139 SSVAL(req->outbuf,smb_vwv0,nread);
4140 SSVAL(req->outbuf,smb_vwv5,nread+3);
4141 SCVAL(smb_buf(req->outbuf),0,1);
4142 SSVAL(smb_buf(req->outbuf),1,nread);
4144 DEBUG(3, ("read %s num=%d nread=%d\n",
4145 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4148 END_PROFILE(SMBread);
4152 /****************************************************************************
4154 ****************************************************************************/
4156 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4160 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4163 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4165 SCVAL(outbuf,smb_vwv0,0xFF);
4166 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4167 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4168 SSVAL(outbuf,smb_vwv6,
4169 (smb_wct - 4) /* offset from smb header to wct */
4170 + 1 /* the wct field */
4171 + 12 * sizeof(uint16_t) /* vwv */
4172 + 2 /* the buflen field */
4173 + 1); /* padding byte */
4174 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4175 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4176 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4177 _smb_setlen_large(outbuf,
4178 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4182 /****************************************************************************
4183 Reply to a read and X - possibly using sendfile.
4184 ****************************************************************************/
4186 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4187 files_struct *fsp, off_t startpos,
4190 struct smbXsrv_connection *xconn = req->xconn;
4192 struct lock_struct lock;
4193 int saved_errno = 0;
4195 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4196 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4199 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4200 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4205 * We can only use sendfile on a non-chained packet
4206 * but we can use on a non-oplocked file. tridge proved this
4207 * on a train in Germany :-). JRA.
4210 if (!req_is_in_chain(req) &&
4212 (fsp->base_fsp == NULL) &&
4213 (fsp->wcp == NULL) &&
4214 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4215 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4218 if(fsp_stat(fsp) == -1) {
4219 reply_nterror(req, map_nt_error_from_unix(errno));
4223 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4224 (startpos > fsp->fsp_name->st.st_ex_size) ||
4225 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4227 * We already know that we would do a short read, so don't
4228 * try the sendfile() path.
4230 goto nosendfile_read;
4234 * Set up the packet header before send. We
4235 * assume here the sendfile will work (get the
4236 * correct amount of data).
4239 header = data_blob_const(headerbuf, sizeof(headerbuf));
4241 construct_reply_common_req(req, (char *)headerbuf);
4242 setup_readX_header((char *)headerbuf, smb_maxcnt);
4244 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4245 startpos, smb_maxcnt);
4247 saved_errno = errno;
4249 /* Returning ENOSYS means no data at all was sent.
4250 Do this as a normal read. */
4251 if (errno == ENOSYS) {
4256 * Special hack for broken Linux with no working sendfile. If we
4257 * return EINTR we sent the header but not the rest of the data.
4258 * Fake this up by doing read/write calls.
4261 if (errno == EINTR) {
4262 /* Ensure we don't do this again. */
4263 set_use_sendfile(SNUM(conn), False);
4264 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4265 nread = fake_sendfile(xconn, fsp, startpos,
4268 saved_errno = errno;
4269 DEBUG(0,("send_file_readX: "
4270 "fake_sendfile failed for "
4271 "file %s (%s) for client %s. "
4274 smbXsrv_connection_dbg(xconn),
4275 strerror(saved_errno)));
4276 errno = saved_errno;
4277 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4279 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4280 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4281 /* No outbuf here means successful sendfile. */
4285 DEBUG(0,("send_file_readX: sendfile failed for file "
4286 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4288 exit_server_cleanly("send_file_readX sendfile failed");
4289 } else if (nread == 0) {
4291 * Some sendfile implementations return 0 to indicate
4292 * that there was a short read, but nothing was
4293 * actually written to the socket. In this case,
4294 * fallback to the normal read path so the header gets
4295 * the correct byte count.
4297 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4298 "falling back to the normal read: %s\n",
4303 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4304 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4306 /* Deal with possible short send. */
4307 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4310 ret = sendfile_short_send(xconn, fsp, nread,
4311 sizeof(headerbuf), smb_maxcnt);
4314 r = "send_file_readX: sendfile_short_send failed";
4315 DEBUG(0,("%s for file %s (%s).\n",
4316 r, fsp_str_dbg(fsp), strerror(errno)));
4317 exit_server_cleanly(r);
4320 /* No outbuf here means successful sendfile. */
4321 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4322 SMB_PERFCOUNT_END(&req->pcd);
4328 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4329 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4332 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4333 (startpos > fsp->fsp_name->st.st_ex_size) ||
4334 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4336 * We already know that we would do a short
4337 * read, so don't try the sendfile() path.
4339 goto nosendfile_read;
4342 construct_reply_common_req(req, (char *)headerbuf);
4343 setup_readX_header((char *)headerbuf, smb_maxcnt);
4345 /* Send out the header. */
4346 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4348 if (ret != sizeof(headerbuf)) {
4349 saved_errno = errno;
4351 * Try and give an error message saying what
4354 DEBUG(0,("send_file_readX: write_data failed for file "
4355 "%s (%s) for client %s. Terminating\n",
4357 smbXsrv_connection_dbg(xconn),
4358 strerror(saved_errno)));
4359 errno = saved_errno;
4360 exit_server_cleanly("send_file_readX sendfile failed");
4362 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4364 saved_errno = errno;
4365 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4366 "%s (%s) for client %s. Terminating\n",
4368 smbXsrv_connection_dbg(xconn),
4369 strerror(saved_errno)));
4370 errno = saved_errno;
4371 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4378 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4379 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4380 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4382 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4383 startpos, smb_maxcnt);
4384 saved_errno = errno;
4387 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4391 setup_readX_header((char *)req->outbuf, nread);
4393 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4394 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4398 TALLOC_FREE(req->outbuf);
4402 /****************************************************************************
4403 Work out how much space we have for a read return.
4404 ****************************************************************************/
4406 static size_t calc_max_read_pdu(const struct smb_request *req)
4408 struct smbXsrv_connection *xconn = req->xconn;
4410 if (xconn->protocol < PROTOCOL_NT1) {
4411 return xconn->smb1.sessions.max_send;
4414 if (!lp_large_readwrite()) {
4415 return xconn->smb1.sessions.max_send;
4418 if (req_is_in_chain(req)) {
4419 return xconn->smb1.sessions.max_send;
4422 if (req->encrypted) {
4424 * Don't take encrypted traffic up to the
4425 * limit. There are padding considerations
4426 * that make that tricky.
4428 return xconn->smb1.sessions.max_send;
4431 if (srv_is_signing_active(xconn)) {
4435 if (!lp_unix_extensions()) {
4440 * We can do ultra-large POSIX reads.
4445 /****************************************************************************
4446 Calculate how big a read can be. Copes with all clients. It's always
4447 safe to return a short read - Windows does this.
4448 ****************************************************************************/
4450 static size_t calc_read_size(const struct smb_request *req,
4454 struct smbXsrv_connection *xconn = req->xconn;
4455 size_t max_pdu = calc_max_read_pdu(req);
4456 size_t total_size = 0;
4457 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4458 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4461 * Windows explicitly ignores upper size of 0xFFFF.
4462 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4463 * We must do the same as these will never fit even in
4464 * an extended size NetBIOS packet.
4466 if (upper_size == 0xFFFF) {
4470 if (xconn->protocol < PROTOCOL_NT1) {
4474 total_size = ((upper_size<<16) | lower_size);
4477 * LARGE_READX test shows it's always safe to return
4478 * a short read. Windows does so.
4480 return MIN(total_size, max_len);
4483 /****************************************************************************
4484 Reply to a read and X.
4485 ****************************************************************************/
4487 void reply_read_and_X(struct smb_request *req)
4489 connection_struct *conn = req->conn;
4494 bool big_readX = False;
4496 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4499 START_PROFILE(SMBreadX);
4501 if ((req->wct != 10) && (req->wct != 12)) {
4502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4506 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4507 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4508 smb_maxcnt = SVAL(req->vwv+5, 0);
4510 /* If it's an IPC, pass off the pipe handler. */
4512 reply_pipe_read_and_X(req);
4513 END_PROFILE(SMBreadX);
4517 if (!check_fsp(conn, req, fsp)) {
4518 END_PROFILE(SMBreadX);
4522 if (!CHECK_READ(fsp,req)) {
4523 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4524 END_PROFILE(SMBreadX);
4528 upper_size = SVAL(req->vwv+7, 0);
4529 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4530 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4532 * This is a heuristic to avoid keeping large
4533 * outgoing buffers around over long-lived aio
4539 if (req->wct == 12) {
4541 * This is a large offset (64 bit) read.
4543 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4548 NTSTATUS status = schedule_aio_read_and_X(conn,
4553 if (NT_STATUS_IS_OK(status)) {
4554 /* Read scheduled - we're done. */
4557 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4558 /* Real error - report to client. */
4559 END_PROFILE(SMBreadX);
4560 reply_nterror(req, status);
4563 /* NT_STATUS_RETRY - fall back to sync read. */
4566 smbd_lock_socket(req->xconn);
4567 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4568 smbd_unlock_socket(req->xconn);
4571 END_PROFILE(SMBreadX);
4575 /****************************************************************************
4576 Error replies to writebraw must have smb_wct == 1. Fix this up.
4577 ****************************************************************************/
4579 void error_to_writebrawerr(struct smb_request *req)
4581 uint8_t *old_outbuf = req->outbuf;
4583 reply_outbuf(req, 1, 0);
4585 memcpy(req->outbuf, old_outbuf, smb_size);
4586 TALLOC_FREE(old_outbuf);
4589 /****************************************************************************
4590 Read 4 bytes of a smb packet and return the smb length of the packet.
4591 Store the result in the buffer. This version of the function will
4592 never return a session keepalive (length of zero).
4593 Timeout is in milliseconds.
4594 ****************************************************************************/
4596 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4599 uint8_t msgtype = NBSSkeepalive;
4601 while (msgtype == NBSSkeepalive) {
4604 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4606 if (!NT_STATUS_IS_OK(status)) {
4607 char addr[INET6_ADDRSTRLEN];
4608 /* Try and give an error message
4609 * saying what client failed. */
4610 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4611 "client %s read error = %s.\n",
4612 get_peer_addr(fd,addr,sizeof(addr)),
4613 nt_errstr(status)));
4617 msgtype = CVAL(inbuf, 0);
4620 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4621 (unsigned long)len));
4623 return NT_STATUS_OK;
4626 /****************************************************************************
4627 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4628 ****************************************************************************/
4630 void reply_writebraw(struct smb_request *req)
4632 connection_struct *conn = req->conn;
4633 struct smbXsrv_connection *xconn = req->xconn;
4636 ssize_t total_written=0;
4637 size_t numtowrite=0;
4640 const char *data=NULL;
4643 struct lock_struct lock;
4646 START_PROFILE(SMBwritebraw);
4649 * If we ever reply with an error, it must have the SMB command
4650 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4653 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4655 if (srv_is_signing_active(xconn)) {
4656 END_PROFILE(SMBwritebraw);
4657 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4658 "raw reads/writes are disallowed.");
4661 if (req->wct < 12) {
4662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4663 error_to_writebrawerr(req);
4664 END_PROFILE(SMBwritebraw);
4668 if (xconn->smb1.echo_handler.trusted_fde) {
4669 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4670 "'async smb echo handler = yes'\n"));
4671 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4672 error_to_writebrawerr(req);
4673 END_PROFILE(SMBwritebraw);
4677 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4678 if (!check_fsp(conn, req, fsp)) {
4679 error_to_writebrawerr(req);
4680 END_PROFILE(SMBwritebraw);
4684 if (!CHECK_WRITE(fsp)) {
4685 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4686 error_to_writebrawerr(req);
4687 END_PROFILE(SMBwritebraw);
4691 tcount = IVAL(req->vwv+1, 0);
4692 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4693 write_through = BITSETW(req->vwv+7,0);
4695 /* We have to deal with slightly different formats depending
4696 on whether we are using the core+ or lanman1.0 protocol */
4698 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4699 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4700 data = smb_buf_const(req->inbuf);
4702 numtowrite = SVAL(req->vwv+10, 0);
4703 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4706 /* Ensure we don't write bytes past the end of this packet. */
4708 * This already protects us against CVE-2017-12163.
4710 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4712 error_to_writebrawerr(req);
4713 END_PROFILE(SMBwritebraw);
4717 if (!fsp->print_file) {
4718 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4719 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4722 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4723 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4724 error_to_writebrawerr(req);
4725 END_PROFILE(SMBwritebraw);
4731 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4734 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4735 "wrote=%d sync=%d\n",
4736 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4737 (int)nwritten, (int)write_through));
4739 if (nwritten < (ssize_t)numtowrite) {
4740 reply_nterror(req, NT_STATUS_DISK_FULL);
4741 error_to_writebrawerr(req);
4745 total_written = nwritten;
4747 /* Allocate a buffer of 64k + length. */
4748 buf = talloc_array(NULL, char, 65540);
4750 reply_nterror(req, NT_STATUS_NO_MEMORY);
4751 error_to_writebrawerr(req);
4755 /* Return a SMBwritebraw message to the redirector to tell
4756 * it to send more bytes */
4758 memcpy(buf, req->inbuf, smb_size);
4759 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4760 SCVAL(buf,smb_com,SMBwritebraw);
4761 SSVALS(buf,smb_vwv0,0xFFFF);
4763 if (!srv_send_smb(req->xconn,
4765 false, 0, /* no signing */
4766 IS_CONN_ENCRYPTED(conn),
4768 exit_server_cleanly("reply_writebraw: srv_send_smb "
4772 /* Now read the raw data into the buffer and write it */
4773 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4775 if (!NT_STATUS_IS_OK(status)) {
4776 exit_server_cleanly("secondary writebraw failed");
4779 /* Set up outbuf to return the correct size */
4780 reply_outbuf(req, 1, 0);
4782 if (numtowrite != 0) {
4784 if (numtowrite > 0xFFFF) {
4785 DEBUG(0,("reply_writebraw: Oversize secondary write "
4786 "raw requested (%u). Terminating\n",
4787 (unsigned int)numtowrite ));
4788 exit_server_cleanly("secondary writebraw failed");
4791 if (tcount > nwritten+numtowrite) {
4792 DEBUG(3,("reply_writebraw: Client overestimated the "
4794 (int)tcount,(int)nwritten,(int)numtowrite));
4797 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4800 if (!NT_STATUS_IS_OK(status)) {
4801 /* Try and give an error message
4802 * saying what client failed. */
4803 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4804 "raw read failed (%s) for client %s. "
4805 "Terminating\n", nt_errstr(status),
4806 smbXsrv_connection_dbg(xconn)));
4807 exit_server_cleanly("secondary writebraw failed");
4811 * We are not vulnerable to CVE-2017-12163
4812 * here as we are guaranteed to have numtowrite
4813 * bytes available - we just read from the client.
4815 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4816 if (nwritten == -1) {
4818 reply_nterror(req, map_nt_error_from_unix(errno));
4819 error_to_writebrawerr(req);
4823 if (nwritten < (ssize_t)numtowrite) {
4824 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4825 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4829 total_written += nwritten;
4834 SSVAL(req->outbuf,smb_vwv0,total_written);
4836 status = sync_file(conn, fsp, write_through);
4837 if (!NT_STATUS_IS_OK(status)) {
4838 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4839 fsp_str_dbg(fsp), nt_errstr(status)));
4840 reply_nterror(req, status);
4841 error_to_writebrawerr(req);
4845 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4847 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4848 (int)total_written));
4850 /* We won't return a status if write through is not selected - this
4851 * follows what WfWg does */
4852 END_PROFILE(SMBwritebraw);
4854 if (!write_through && total_written==tcount) {
4856 #if RABBIT_PELLET_FIX
4858 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4859 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4862 if (!send_keepalive(xconn->transport.sock)) {
4863 exit_server_cleanly("reply_writebraw: send of "
4864 "keepalive failed");
4867 TALLOC_FREE(req->outbuf);
4872 END_PROFILE(SMBwritebraw);
4877 #define DBGC_CLASS DBGC_LOCKING
4879 /****************************************************************************
4880 Reply to a writeunlock (core+).
4881 ****************************************************************************/
4883 void reply_writeunlock(struct smb_request *req)
4885 connection_struct *conn = req->conn;
4886 ssize_t nwritten = -1;
4891 NTSTATUS status = NT_STATUS_OK;
4893 struct lock_struct lock;
4894 int saved_errno = 0;
4896 START_PROFILE(SMBwriteunlock);
4899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4900 END_PROFILE(SMBwriteunlock);
4904 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4906 if (!check_fsp(conn, req, fsp)) {
4907 END_PROFILE(SMBwriteunlock);
4911 if (!CHECK_WRITE(fsp)) {
4912 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4913 END_PROFILE(SMBwriteunlock);
4917 numtowrite = SVAL(req->vwv+1, 0);
4918 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4919 data = (const char *)req->buf + 3;
4922 * Ensure client isn't asking us to write more than
4923 * they sent. CVE-2017-12163.
4925 remaining = smbreq_bufrem(req, data);
4926 if (numtowrite > remaining) {
4927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4928 END_PROFILE(SMBwriteunlock);
4932 if (!fsp->print_file && numtowrite > 0) {
4933 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4934 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4937 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4938 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4939 END_PROFILE(SMBwriteunlock);
4944 /* The special X/Open SMB protocol handling of
4945 zero length writes is *NOT* done for
4947 if(numtowrite == 0) {
4950 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4951 saved_errno = errno;
4954 status = sync_file(conn, fsp, False /* write through */);
4955 if (!NT_STATUS_IS_OK(status)) {
4956 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4957 fsp_str_dbg(fsp), nt_errstr(status)));
4958 reply_nterror(req, status);
4963 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4967 if((nwritten < numtowrite) && (numtowrite != 0)) {
4968 reply_nterror(req, NT_STATUS_DISK_FULL);
4972 if (numtowrite && !fsp->print_file) {
4973 struct smbd_lock_element l = {
4974 .smblctx = req->smbpid,
4975 .brltype = UNLOCK_LOCK,
4977 .count = numtowrite,
4979 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
4980 if (NT_STATUS_V(status)) {
4981 reply_nterror(req, status);
4986 reply_outbuf(req, 1, 0);
4988 SSVAL(req->outbuf,smb_vwv0,nwritten);
4990 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4991 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4994 END_PROFILE(SMBwriteunlock);
4999 #define DBGC_CLASS DBGC_ALL
5001 /****************************************************************************
5003 ****************************************************************************/
5005 void reply_write(struct smb_request *req)
5007 connection_struct *conn = req->conn;
5010 ssize_t nwritten = -1;
5014 struct lock_struct lock;
5016 int saved_errno = 0;
5018 START_PROFILE(SMBwrite);
5021 END_PROFILE(SMBwrite);
5022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5026 /* If it's an IPC, pass off the pipe handler. */
5028 reply_pipe_write(req);
5029 END_PROFILE(SMBwrite);
5033 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5035 if (!check_fsp(conn, req, fsp)) {
5036 END_PROFILE(SMBwrite);
5040 if (!CHECK_WRITE(fsp)) {
5041 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5042 END_PROFILE(SMBwrite);
5046 numtowrite = SVAL(req->vwv+1, 0);
5047 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5048 data = (const char *)req->buf + 3;
5051 * Ensure client isn't asking us to write more than
5052 * they sent. CVE-2017-12163.
5054 remaining = smbreq_bufrem(req, data);
5055 if (numtowrite > remaining) {
5056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5057 END_PROFILE(SMBwrite);
5061 if (!fsp->print_file) {
5062 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5063 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5066 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5067 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5068 END_PROFILE(SMBwrite);
5074 * X/Open SMB protocol says that if smb_vwv1 is
5075 * zero then the file size should be extended or
5076 * truncated to the size given in smb_vwv[2-3].
5079 if(numtowrite == 0) {
5081 * This is actually an allocate call, and set EOF. JRA.
5083 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5085 reply_nterror(req, NT_STATUS_DISK_FULL);
5088 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5090 reply_nterror(req, NT_STATUS_DISK_FULL);
5093 trigger_write_time_update_immediate(fsp);
5095 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5098 status = sync_file(conn, fsp, False);
5099 if (!NT_STATUS_IS_OK(status)) {
5100 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5101 fsp_str_dbg(fsp), nt_errstr(status)));
5102 reply_nterror(req, status);
5107 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5111 if((nwritten == 0) && (numtowrite != 0)) {
5112 reply_nterror(req, NT_STATUS_DISK_FULL);
5116 reply_outbuf(req, 1, 0);
5118 SSVAL(req->outbuf,smb_vwv0,nwritten);
5120 if (nwritten < (ssize_t)numtowrite) {
5121 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5122 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5125 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5128 END_PROFILE(SMBwrite);
5132 /****************************************************************************
5133 Ensure a buffer is a valid writeX for recvfile purposes.
5134 ****************************************************************************/
5136 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5137 (2*14) + /* word count (including bcc) */ \
5140 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5141 const uint8_t *inbuf)
5144 unsigned int doff = 0;
5145 size_t len = smb_len_large(inbuf);
5147 struct smbXsrv_open *op = NULL;
5148 struct files_struct *fsp = NULL;
5151 if (is_encrypted_packet(inbuf)) {
5152 /* Can't do this on encrypted
5157 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5161 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5162 CVAL(inbuf,smb_wct) != 14) {
5163 DEBUG(10,("is_valid_writeX_buffer: chained or "
5164 "invalid word length.\n"));
5168 fnum = SVAL(inbuf, smb_vwv2);
5169 status = smb1srv_open_lookup(xconn,
5173 if (!NT_STATUS_IS_OK(status)) {
5174 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5179 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5182 if (fsp->conn == NULL) {
5183 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5187 if (IS_IPC(fsp->conn)) {
5188 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5191 if (IS_PRINT(fsp->conn)) {
5192 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5195 if (fsp->base_fsp != NULL) {
5196 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5199 doff = SVAL(inbuf,smb_vwv11);
5201 numtowrite = SVAL(inbuf,smb_vwv10);
5203 if (len > doff && len - doff > 0xFFFF) {
5204 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5207 if (numtowrite == 0) {
5208 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5212 /* Ensure the sizes match up. */
5213 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5214 /* no pad byte...old smbclient :-( */
5215 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5217 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5221 if (len - doff != numtowrite) {
5222 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5223 "len = %u, doff = %u, numtowrite = %u\n",
5226 (unsigned int)numtowrite ));
5230 DEBUG(10,("is_valid_writeX_buffer: true "
5231 "len = %u, doff = %u, numtowrite = %u\n",
5234 (unsigned int)numtowrite ));
5239 /****************************************************************************
5240 Reply to a write and X.
5241 ****************************************************************************/
5243 void reply_write_and_X(struct smb_request *req)
5245 connection_struct *conn = req->conn;
5246 struct smbXsrv_connection *xconn = req->xconn;
5248 struct lock_struct lock;
5253 unsigned int smb_doff;
5254 unsigned int smblen;
5257 int saved_errno = 0;
5259 START_PROFILE(SMBwriteX);
5261 if ((req->wct != 12) && (req->wct != 14)) {
5262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5266 numtowrite = SVAL(req->vwv+10, 0);
5267 smb_doff = SVAL(req->vwv+11, 0);
5268 smblen = smb_len(req->inbuf);
5270 if (req->unread_bytes > 0xFFFF ||
5271 (smblen > smb_doff &&
5272 smblen - smb_doff > 0xFFFF)) {
5273 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5276 if (req->unread_bytes) {
5277 /* Can't do a recvfile write on IPC$ */
5279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5282 if (numtowrite != req->unread_bytes) {
5283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5288 * This already protects us against CVE-2017-12163.
5290 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5291 smb_doff + numtowrite > smblen) {
5292 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5297 /* If it's an IPC, pass off the pipe handler. */
5299 if (req->unread_bytes) {
5300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5303 reply_pipe_write_and_X(req);
5307 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5308 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5309 write_through = BITSETW(req->vwv+7,0);
5311 if (!check_fsp(conn, req, fsp)) {
5315 if (!CHECK_WRITE(fsp)) {
5316 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5320 data = smb_base(req->inbuf) + smb_doff;
5322 if(req->wct == 14) {
5324 * This is a large offset (64 bit) write.
5326 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5330 /* X/Open SMB protocol says that, unlike SMBwrite
5331 if the length is zero then NO truncation is
5332 done, just a write of zero. To truncate a file,
5335 if(numtowrite == 0) {
5338 if (req->unread_bytes == 0) {
5339 status = schedule_aio_write_and_X(conn,
5346 if (NT_STATUS_IS_OK(status)) {
5347 /* write scheduled - we're done. */
5350 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5351 /* Real error - report to client. */
5352 reply_nterror(req, status);
5355 /* NT_STATUS_RETRY - fall through to sync write. */
5358 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5359 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5362 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5363 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5367 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5368 saved_errno = errno;
5372 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5376 if((nwritten == 0) && (numtowrite != 0)) {
5377 reply_nterror(req, NT_STATUS_DISK_FULL);
5381 reply_outbuf(req, 6, 0);
5382 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5383 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5384 SSVAL(req->outbuf,smb_vwv2,nwritten);
5385 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5387 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5388 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5390 status = sync_file(conn, fsp, write_through);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5393 fsp_str_dbg(fsp), nt_errstr(status)));
5394 reply_nterror(req, status);
5398 END_PROFILE(SMBwriteX);
5402 if (req->unread_bytes) {
5403 /* writeX failed. drain socket. */
5404 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5405 req->unread_bytes) {
5406 smb_panic("failed to drain pending bytes");
5408 req->unread_bytes = 0;
5411 END_PROFILE(SMBwriteX);
5415 /****************************************************************************
5417 ****************************************************************************/
5419 void reply_lseek(struct smb_request *req)
5421 connection_struct *conn = req->conn;
5427 START_PROFILE(SMBlseek);
5430 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5431 END_PROFILE(SMBlseek);
5435 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5437 if (!check_fsp(conn, req, fsp)) {
5441 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5443 mode = SVAL(req->vwv+1, 0) & 3;
5444 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5445 startpos = (off_t)IVALS(req->vwv+2, 0);
5454 res = fsp->fh->pos + startpos;
5465 if (umode == SEEK_END) {
5466 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5467 if(errno == EINVAL) {
5468 off_t current_pos = startpos;
5470 if(fsp_stat(fsp) == -1) {
5472 map_nt_error_from_unix(errno));
5473 END_PROFILE(SMBlseek);
5477 current_pos += fsp->fsp_name->st.st_ex_size;
5479 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5484 reply_nterror(req, map_nt_error_from_unix(errno));
5485 END_PROFILE(SMBlseek);
5492 reply_outbuf(req, 2, 0);
5493 SIVAL(req->outbuf,smb_vwv0,res);
5495 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5496 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5498 END_PROFILE(SMBlseek);
5502 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5505 connection_struct *conn = talloc_get_type_abort(
5506 private_data, connection_struct);
5508 if (conn != fsp->conn) {
5511 if (fsp->fh->fd == -1) {
5514 sync_file(conn, fsp, True /* write through */);
5519 /****************************************************************************
5521 ****************************************************************************/
5523 void reply_flush(struct smb_request *req)
5525 connection_struct *conn = req->conn;
5529 START_PROFILE(SMBflush);
5532 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5536 fnum = SVAL(req->vwv+0, 0);
5537 fsp = file_fsp(req, fnum);
5539 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5544 files_forall(req->sconn, file_sync_one_fn, conn);
5546 NTSTATUS status = sync_file(conn, fsp, True);
5547 if (!NT_STATUS_IS_OK(status)) {
5548 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5549 fsp_str_dbg(fsp), nt_errstr(status)));
5550 reply_nterror(req, status);
5551 END_PROFILE(SMBflush);
5556 reply_outbuf(req, 0, 0);
5558 DEBUG(3,("flush\n"));
5559 END_PROFILE(SMBflush);
5563 /****************************************************************************
5565 conn POINTER CAN BE NULL HERE !
5566 ****************************************************************************/
5568 void reply_exit(struct smb_request *req)
5570 START_PROFILE(SMBexit);
5572 file_close_pid(req->sconn, req->smbpid, req->vuid);
5574 reply_outbuf(req, 0, 0);
5576 DEBUG(3,("exit\n"));
5578 END_PROFILE(SMBexit);
5582 struct reply_close_state {
5584 struct smb_request *smbreq;
5587 static void do_smb1_close(struct tevent_req *req);
5589 void reply_close(struct smb_request *req)
5591 connection_struct *conn = req->conn;
5592 NTSTATUS status = NT_STATUS_OK;
5593 files_struct *fsp = NULL;
5594 START_PROFILE(SMBclose);
5597 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5598 END_PROFILE(SMBclose);
5602 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5605 * We can only use check_fsp if we know it's not a directory.
5608 if (!check_fsp_open(conn, req, fsp)) {
5609 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5610 END_PROFILE(SMBclose);
5614 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5615 fsp->is_directory ? "directory" : "file",
5616 fsp->fh->fd, fsp_fnum_dbg(fsp),
5617 conn->num_files_open));
5619 if (!fsp->is_directory) {
5623 * Take care of any time sent in the close.
5626 t = srv_make_unix_date3(req->vwv+1);
5627 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5630 if (fsp->num_aio_requests != 0) {
5632 struct reply_close_state *state;
5634 DEBUG(10, ("closing with aio %u requests pending\n",
5635 fsp->num_aio_requests));
5638 * We depend on the aio_extra destructor to take care of this
5639 * close request once fsp->num_aio_request drops to 0.
5642 fsp->deferred_close = tevent_wait_send(
5643 fsp, fsp->conn->sconn->ev_ctx);
5644 if (fsp->deferred_close == NULL) {
5645 status = NT_STATUS_NO_MEMORY;
5649 state = talloc(fsp, struct reply_close_state);
5650 if (state == NULL) {
5651 TALLOC_FREE(fsp->deferred_close);
5652 status = NT_STATUS_NO_MEMORY;
5656 state->smbreq = talloc_move(fsp, &req);
5657 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5659 END_PROFILE(SMBclose);
5664 * close_file() returns the unix errno if an error was detected on
5665 * close - normally this is due to a disk full error. If not then it
5666 * was probably an I/O error.
5669 status = close_file(req, fsp, NORMAL_CLOSE);
5671 if (!NT_STATUS_IS_OK(status)) {
5672 reply_nterror(req, status);
5673 END_PROFILE(SMBclose);
5677 reply_outbuf(req, 0, 0);
5678 END_PROFILE(SMBclose);
5682 static void do_smb1_close(struct tevent_req *req)
5684 struct reply_close_state *state = tevent_req_callback_data(
5685 req, struct reply_close_state);
5686 struct smb_request *smbreq;
5690 ret = tevent_wait_recv(req);
5693 DEBUG(10, ("tevent_wait_recv returned %s\n",
5696 * Continue anyway, this should never happen
5701 * fsp->smb2_close_request right now is a talloc grandchild of
5702 * fsp. When we close_file(fsp), it would go with it. No chance to
5705 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5707 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5708 if (NT_STATUS_IS_OK(status)) {
5709 reply_outbuf(smbreq, 0, 0);
5711 reply_nterror(smbreq, status);
5713 if (!srv_send_smb(smbreq->xconn,
5714 (char *)smbreq->outbuf,
5717 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5719 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5722 TALLOC_FREE(smbreq);
5725 /****************************************************************************
5726 Reply to a writeclose (Core+ protocol).
5727 ****************************************************************************/
5729 void reply_writeclose(struct smb_request *req)
5731 connection_struct *conn = req->conn;
5734 ssize_t nwritten = -1;
5735 NTSTATUS close_status = NT_STATUS_OK;
5738 struct timespec mtime;
5740 struct lock_struct lock;
5742 START_PROFILE(SMBwriteclose);
5745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5746 END_PROFILE(SMBwriteclose);
5750 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5752 if (!check_fsp(conn, req, fsp)) {
5753 END_PROFILE(SMBwriteclose);
5756 if (!CHECK_WRITE(fsp)) {
5757 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5758 END_PROFILE(SMBwriteclose);
5762 numtowrite = SVAL(req->vwv+1, 0);
5763 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5764 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5765 data = (const char *)req->buf + 1;
5768 * Ensure client isn't asking us to write more than
5769 * they sent. CVE-2017-12163.
5771 remaining = smbreq_bufrem(req, data);
5772 if (numtowrite > remaining) {
5773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5774 END_PROFILE(SMBwriteclose);
5778 if (fsp->print_file == NULL) {
5779 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5780 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5783 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5784 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5785 END_PROFILE(SMBwriteclose);
5790 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5792 set_close_write_time(fsp, mtime);
5795 * More insanity. W2K only closes the file if writelen > 0.
5799 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5800 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5801 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5804 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5805 "file %s\n", fsp_str_dbg(fsp)));
5806 close_status = close_file(req, fsp, NORMAL_CLOSE);
5810 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5811 reply_nterror(req, NT_STATUS_DISK_FULL);
5815 if(!NT_STATUS_IS_OK(close_status)) {
5816 reply_nterror(req, close_status);
5820 reply_outbuf(req, 1, 0);
5822 SSVAL(req->outbuf,smb_vwv0,nwritten);
5826 END_PROFILE(SMBwriteclose);
5831 #define DBGC_CLASS DBGC_LOCKING
5833 /****************************************************************************
5835 ****************************************************************************/
5837 static void reply_lock_done(struct tevent_req *subreq);
5839 void reply_lock(struct smb_request *req)
5841 struct tevent_req *subreq = NULL;
5842 connection_struct *conn = req->conn;
5844 struct smbd_lock_element *lck = NULL;
5846 START_PROFILE(SMBlock);
5849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5850 END_PROFILE(SMBlock);
5854 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5856 if (!check_fsp(conn, req, fsp)) {
5857 END_PROFILE(SMBlock);
5861 lck = talloc(req, struct smbd_lock_element);
5863 reply_nterror(req, NT_STATUS_NO_MEMORY);
5864 END_PROFILE(SMBlock);
5868 *lck = (struct smbd_lock_element) {
5869 .smblctx = req->smbpid,
5870 .brltype = WRITE_LOCK,
5871 .count = IVAL(req->vwv+1, 0),
5872 .offset = IVAL(req->vwv+3, 0),
5875 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5881 subreq = smbd_smb1_do_locks_send(
5887 false, /* large_offset */
5891 if (subreq == NULL) {
5892 reply_nterror(req, NT_STATUS_NO_MEMORY);
5893 END_PROFILE(SMBlock);
5896 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5897 END_PROFILE(SMBlock);
5900 static void reply_lock_done(struct tevent_req *subreq)
5902 struct smb_request *req = NULL;
5906 START_PROFILE(SMBlock);
5908 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5911 status = smbd_smb1_do_locks_recv(subreq);
5912 TALLOC_FREE(subreq);
5914 if (NT_STATUS_IS_OK(status)) {
5915 reply_outbuf(req, 0, 0);
5917 reply_nterror(req, status);
5920 ok = srv_send_smb(req->xconn,
5921 (char *)req->outbuf,
5924 IS_CONN_ENCRYPTED(req->conn),
5927 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
5930 END_PROFILE(SMBlock);
5933 /****************************************************************************
5935 ****************************************************************************/
5937 void reply_unlock(struct smb_request *req)
5939 connection_struct *conn = req->conn;
5942 struct smbd_lock_element lck;
5944 START_PROFILE(SMBunlock);
5947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5948 END_PROFILE(SMBunlock);
5952 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5954 if (!check_fsp(conn, req, fsp)) {
5955 END_PROFILE(SMBunlock);
5959 lck = (struct smbd_lock_element) {
5960 .smblctx = req->smbpid,
5961 .brltype = UNLOCK_LOCK,
5962 .offset = IVAL(req->vwv+3, 0),
5963 .count = IVAL(req->vwv+1, 0),
5966 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
5968 if (!NT_STATUS_IS_OK(status)) {
5969 reply_nterror(req, status);
5970 END_PROFILE(SMBunlock);
5974 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5980 reply_outbuf(req, 0, 0);
5982 END_PROFILE(SMBunlock);
5987 #define DBGC_CLASS DBGC_ALL
5989 /****************************************************************************
5991 conn POINTER CAN BE NULL HERE !
5992 ****************************************************************************/
5994 void reply_tdis(struct smb_request *req)
5997 connection_struct *conn = req->conn;
5998 struct smbXsrv_tcon *tcon;
6000 START_PROFILE(SMBtdis);
6003 DEBUG(4,("Invalid connection in tdis\n"));
6004 reply_force_doserror(req, ERRSRV, ERRinvnid);
6005 END_PROFILE(SMBtdis);
6013 * TODO: cancel all outstanding requests on the tcon
6015 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
6016 if (!NT_STATUS_IS_OK(status)) {
6017 DEBUG(0, ("reply_tdis: "
6018 "smbXsrv_tcon_disconnect() failed: %s\n",
6019 nt_errstr(status)));
6021 * If we hit this case, there is something completely
6022 * wrong, so we better disconnect the transport connection.
6024 END_PROFILE(SMBtdis);
6025 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6031 reply_outbuf(req, 0, 0);
6032 END_PROFILE(SMBtdis);
6036 /****************************************************************************
6038 conn POINTER CAN BE NULL HERE !
6039 ****************************************************************************/
6041 void reply_echo(struct smb_request *req)
6043 connection_struct *conn = req->conn;
6044 struct smb_perfcount_data local_pcd;
6045 struct smb_perfcount_data *cur_pcd;
6049 START_PROFILE(SMBecho);
6051 smb_init_perfcount_data(&local_pcd);
6054 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6055 END_PROFILE(SMBecho);
6059 smb_reverb = SVAL(req->vwv+0, 0);
6061 reply_outbuf(req, 1, req->buflen);
6063 /* copy any incoming data back out */
6064 if (req->buflen > 0) {
6065 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6068 if (smb_reverb > 100) {
6069 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6073 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6075 /* this makes sure we catch the request pcd */
6076 if (seq_num == smb_reverb) {
6077 cur_pcd = &req->pcd;
6079 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6080 cur_pcd = &local_pcd;
6083 SSVAL(req->outbuf,smb_vwv0,seq_num);
6085 show_msg((char *)req->outbuf);
6086 if (!srv_send_smb(req->xconn,
6087 (char *)req->outbuf,
6088 true, req->seqnum+1,
6089 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6091 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6094 DEBUG(3,("echo %d times\n", smb_reverb));
6096 TALLOC_FREE(req->outbuf);
6098 END_PROFILE(SMBecho);
6102 /****************************************************************************
6103 Reply to a printopen.
6104 ****************************************************************************/
6106 void reply_printopen(struct smb_request *req)
6108 connection_struct *conn = req->conn;
6112 START_PROFILE(SMBsplopen);
6115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6116 END_PROFILE(SMBsplopen);
6120 if (!CAN_PRINT(conn)) {
6121 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6122 END_PROFILE(SMBsplopen);
6126 status = file_new(req, conn, &fsp);
6127 if(!NT_STATUS_IS_OK(status)) {
6128 reply_nterror(req, status);
6129 END_PROFILE(SMBsplopen);
6133 /* Open for exclusive use, write only. */
6134 status = print_spool_open(fsp, NULL, req->vuid);
6136 if (!NT_STATUS_IS_OK(status)) {
6137 file_free(req, fsp);
6138 reply_nterror(req, status);
6139 END_PROFILE(SMBsplopen);
6143 reply_outbuf(req, 1, 0);
6144 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6146 DEBUG(3,("openprint fd=%d %s\n",
6147 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6149 END_PROFILE(SMBsplopen);
6153 /****************************************************************************
6154 Reply to a printclose.
6155 ****************************************************************************/
6157 void reply_printclose(struct smb_request *req)
6159 connection_struct *conn = req->conn;
6163 START_PROFILE(SMBsplclose);
6166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6167 END_PROFILE(SMBsplclose);
6171 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6173 if (!check_fsp(conn, req, fsp)) {
6174 END_PROFILE(SMBsplclose);
6178 if (!CAN_PRINT(conn)) {
6179 reply_force_doserror(req, ERRSRV, ERRerror);
6180 END_PROFILE(SMBsplclose);
6184 DEBUG(3,("printclose fd=%d %s\n",
6185 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6187 status = close_file(req, fsp, NORMAL_CLOSE);
6189 if(!NT_STATUS_IS_OK(status)) {
6190 reply_nterror(req, status);
6191 END_PROFILE(SMBsplclose);
6195 reply_outbuf(req, 0, 0);
6197 END_PROFILE(SMBsplclose);
6201 /****************************************************************************
6202 Reply to a printqueue.
6203 ****************************************************************************/
6205 void reply_printqueue(struct smb_request *req)
6207 connection_struct *conn = req->conn;
6211 START_PROFILE(SMBsplretq);
6214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6215 END_PROFILE(SMBsplretq);
6219 max_count = SVAL(req->vwv+0, 0);
6220 start_index = SVAL(req->vwv+1, 0);
6222 /* we used to allow the client to get the cnum wrong, but that
6223 is really quite gross and only worked when there was only
6224 one printer - I think we should now only accept it if they
6225 get it right (tridge) */
6226 if (!CAN_PRINT(conn)) {
6227 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6228 END_PROFILE(SMBsplretq);
6232 reply_outbuf(req, 2, 3);
6233 SSVAL(req->outbuf,smb_vwv0,0);
6234 SSVAL(req->outbuf,smb_vwv1,0);
6235 SCVAL(smb_buf(req->outbuf),0,1);
6236 SSVAL(smb_buf(req->outbuf),1,0);
6238 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6239 start_index, max_count));
6242 TALLOC_CTX *mem_ctx = talloc_tos();
6245 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
6246 struct rpc_pipe_client *cli = NULL;
6247 struct dcerpc_binding_handle *b = NULL;
6248 struct policy_handle handle;
6249 struct spoolss_DevmodeContainer devmode_ctr;
6250 union spoolss_JobInfo *info;
6252 uint32_t num_to_get;
6256 ZERO_STRUCT(handle);
6258 status = rpc_pipe_open_interface(mem_ctx,
6261 conn->sconn->remote_address,
6262 conn->sconn->local_address,
6263 conn->sconn->msg_ctx,
6265 if (!NT_STATUS_IS_OK(status)) {
6266 DEBUG(0, ("reply_printqueue: "
6267 "could not connect to spoolss: %s\n",
6268 nt_errstr(status)));
6269 reply_nterror(req, status);
6272 b = cli->binding_handle;
6274 ZERO_STRUCT(devmode_ctr);
6276 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6279 SEC_FLAG_MAXIMUM_ALLOWED,
6282 if (!NT_STATUS_IS_OK(status)) {
6283 reply_nterror(req, status);
6286 if (!W_ERROR_IS_OK(werr)) {
6287 reply_nterror(req, werror_to_ntstatus(werr));
6291 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6299 if (!W_ERROR_IS_OK(werr)) {
6300 reply_nterror(req, werror_to_ntstatus(werr));
6304 if (max_count > 0) {
6305 first = start_index;
6307 first = start_index + max_count + 1;
6310 if (first >= count) {
6313 num_to_get = first + MIN(ABS(max_count), count - first);
6316 for (i = first; i < num_to_get; i++) {
6319 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6322 uint16_t qrapjobid = pjobid_to_rap(sharename,
6323 info[i].info2.job_id);
6325 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6331 srv_put_dos_date2(p, 0, qtime);
6332 SCVAL(p, 4, qstatus);
6333 SSVAL(p, 5, qrapjobid);
6334 SIVAL(p, 7, info[i].info2.size);
6336 status = srvstr_push(blob, req->flags2, p+12,
6337 info[i].info2.notify_name, 16, STR_ASCII, &len);
6338 if (!NT_STATUS_IS_OK(status)) {
6339 reply_nterror(req, status);
6342 if (message_push_blob(
6345 blob, sizeof(blob))) == -1) {
6346 reply_nterror(req, NT_STATUS_NO_MEMORY);
6352 SSVAL(req->outbuf,smb_vwv0,count);
6353 SSVAL(req->outbuf,smb_vwv1,
6354 (max_count>0?first+count:first-1));
6355 SCVAL(smb_buf(req->outbuf),0,1);
6356 SSVAL(smb_buf(req->outbuf),1,28*count);
6360 DEBUG(3, ("%u entries returned in queue\n",
6364 if (b && is_valid_policy_hnd(&handle)) {
6365 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6370 END_PROFILE(SMBsplretq);
6374 /****************************************************************************
6375 Reply to a printwrite.
6376 ****************************************************************************/
6378 void reply_printwrite(struct smb_request *req)
6380 connection_struct *conn = req->conn;
6385 START_PROFILE(SMBsplwr);
6388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6389 END_PROFILE(SMBsplwr);
6393 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6395 if (!check_fsp(conn, req, fsp)) {
6396 END_PROFILE(SMBsplwr);
6400 if (!fsp->print_file) {
6401 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6402 END_PROFILE(SMBsplwr);
6406 if (!CHECK_WRITE(fsp)) {
6407 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6408 END_PROFILE(SMBsplwr);
6412 numtowrite = SVAL(req->buf, 1);
6415 * This already protects us against CVE-2017-12163.
6417 if (req->buflen < numtowrite + 3) {
6418 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6419 END_PROFILE(SMBsplwr);
6423 data = (const char *)req->buf + 3;
6425 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6426 reply_nterror(req, map_nt_error_from_unix(errno));
6427 END_PROFILE(SMBsplwr);
6431 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6433 END_PROFILE(SMBsplwr);
6437 /****************************************************************************
6439 ****************************************************************************/
6441 void reply_mkdir(struct smb_request *req)
6443 connection_struct *conn = req->conn;
6444 struct smb_filename *smb_dname = NULL;
6445 char *directory = NULL;
6448 TALLOC_CTX *ctx = talloc_tos();
6450 START_PROFILE(SMBmkdir);
6452 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6453 STR_TERMINATE, &status);
6454 if (!NT_STATUS_IS_OK(status)) {
6455 reply_nterror(req, status);
6459 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6460 status = filename_convert(ctx, conn,
6466 if (!NT_STATUS_IS_OK(status)) {
6467 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6468 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6469 ERRSRV, ERRbadpath);
6472 reply_nterror(req, status);
6476 status = create_directory(conn, req, smb_dname);
6478 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6480 if (!NT_STATUS_IS_OK(status)) {
6482 if (!use_nt_status()
6483 && NT_STATUS_EQUAL(status,
6484 NT_STATUS_OBJECT_NAME_COLLISION)) {
6486 * Yes, in the DOS error code case we get a
6487 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6488 * samba4 torture test.
6490 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6493 reply_nterror(req, status);
6497 reply_outbuf(req, 0, 0);
6499 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6501 TALLOC_FREE(smb_dname);
6502 END_PROFILE(SMBmkdir);
6506 /****************************************************************************
6508 ****************************************************************************/
6510 void reply_rmdir(struct smb_request *req)
6512 connection_struct *conn = req->conn;
6513 struct smb_filename *smb_dname = NULL;
6514 char *directory = NULL;
6516 TALLOC_CTX *ctx = talloc_tos();
6517 files_struct *fsp = NULL;
6519 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6521 START_PROFILE(SMBrmdir);
6523 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6524 STR_TERMINATE, &status);
6525 if (!NT_STATUS_IS_OK(status)) {
6526 reply_nterror(req, status);
6530 status = filename_convert(ctx, conn,
6536 if (!NT_STATUS_IS_OK(status)) {
6537 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6538 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6539 ERRSRV, ERRbadpath);
6542 reply_nterror(req, status);
6546 if (is_ntfs_stream_smb_fname(smb_dname)) {
6547 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6551 status = SMB_VFS_CREATE_FILE(
6554 0, /* root_dir_fid */
6555 smb_dname, /* fname */
6556 DELETE_ACCESS, /* access_mask */
6557 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6559 FILE_OPEN, /* create_disposition*/
6560 FILE_DIRECTORY_FILE, /* create_options */
6561 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6562 0, /* oplock_request */
6564 0, /* allocation_size */
6565 0, /* private_flags */
6570 NULL, NULL); /* create context */
6572 if (!NT_STATUS_IS_OK(status)) {
6573 if (open_was_deferred(req->xconn, req->mid)) {
6574 /* We have re-scheduled this call. */
6577 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6578 bool ok = defer_smb1_sharing_violation(req);
6583 reply_nterror(req, status);
6587 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6588 if (!NT_STATUS_IS_OK(status)) {
6589 close_file(req, fsp, ERROR_CLOSE);
6590 reply_nterror(req, status);
6594 if (!set_delete_on_close(fsp, true,
6595 conn->session_info->security_token,
6596 conn->session_info->unix_token)) {
6597 close_file(req, fsp, ERROR_CLOSE);
6598 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6602 status = close_file(req, fsp, NORMAL_CLOSE);
6603 if (!NT_STATUS_IS_OK(status)) {
6604 reply_nterror(req, status);
6606 reply_outbuf(req, 0, 0);
6609 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6611 TALLOC_FREE(smb_dname);
6612 END_PROFILE(SMBrmdir);
6616 /*******************************************************************
6617 Resolve wildcards in a filename rename.
6618 ********************************************************************/
6620 static bool resolve_wildcards(TALLOC_CTX *ctx,
6625 char *name2_copy = NULL;
6630 char *p,*p2, *pname1, *pname2;
6632 name2_copy = talloc_strdup(ctx, name2);
6637 pname1 = strrchr_m(name1,'/');
6638 pname2 = strrchr_m(name2_copy,'/');
6640 if (!pname1 || !pname2) {
6644 /* Truncate the copy of name2 at the last '/' */
6647 /* Now go past the '/' */
6651 root1 = talloc_strdup(ctx, pname1);
6652 root2 = talloc_strdup(ctx, pname2);
6654 if (!root1 || !root2) {
6658 p = strrchr_m(root1,'.');
6661 ext1 = talloc_strdup(ctx, p+1);
6663 ext1 = talloc_strdup(ctx, "");
6665 p = strrchr_m(root2,'.');
6668 ext2 = talloc_strdup(ctx, p+1);
6670 ext2 = talloc_strdup(ctx, "");
6673 if (!ext1 || !ext2) {
6681 /* Hmmm. Should this be mb-aware ? */
6684 } else if (*p2 == '*') {
6686 root2 = talloc_asprintf(ctx, "%s%s",
6705 /* Hmmm. Should this be mb-aware ? */
6708 } else if (*p2 == '*') {
6710 ext2 = talloc_asprintf(ctx, "%s%s",
6726 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6731 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6743 /****************************************************************************
6744 Ensure open files have their names updated. Updated to notify other smbd's
6746 ****************************************************************************/
6748 static void rename_open_files(connection_struct *conn,
6749 struct share_mode_lock *lck,
6751 uint32_t orig_name_hash,
6752 const struct smb_filename *smb_fname_dst)
6755 bool did_rename = False;
6757 uint32_t new_name_hash = 0;
6759 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6760 fsp = file_find_di_next(fsp)) {
6761 /* fsp_name is a relative path under the fsp. To change this for other
6762 sharepaths we need to manipulate relative paths. */
6763 /* TODO - create the absolute path and manipulate the newname
6764 relative to the sharepath. */
6765 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6768 if (fsp->name_hash != orig_name_hash) {
6771 DEBUG(10, ("rename_open_files: renaming file %s "
6772 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6773 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6774 smb_fname_str_dbg(smb_fname_dst)));
6776 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6777 if (NT_STATUS_IS_OK(status)) {
6779 new_name_hash = fsp->name_hash;
6784 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6785 "for %s\n", file_id_string_tos(&id),
6786 smb_fname_str_dbg(smb_fname_dst)));
6789 /* Send messages to all smbd's (not ourself) that the name has changed. */
6790 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6791 orig_name_hash, new_name_hash,
6796 /****************************************************************************
6797 We need to check if the source path is a parent directory of the destination
6798 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6799 refuse the rename with a sharing violation. Under UNIX the above call can
6800 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6801 probably need to check that the client is a Windows one before disallowing
6802 this as a UNIX client (one with UNIX extensions) can know the source is a
6803 symlink and make this decision intelligently. Found by an excellent bug
6804 report from <AndyLiebman@aol.com>.
6805 ****************************************************************************/
6807 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6808 const struct smb_filename *smb_fname_dst)
6810 const char *psrc = smb_fname_src->base_name;
6811 const char *pdst = smb_fname_dst->base_name;
6814 if (psrc[0] == '.' && psrc[1] == '/') {
6817 if (pdst[0] == '.' && pdst[1] == '/') {
6820 if ((slen = strlen(psrc)) > strlen(pdst)) {
6823 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6827 * Do the notify calls from a rename
6830 static void notify_rename(connection_struct *conn, bool is_dir,
6831 const struct smb_filename *smb_fname_src,
6832 const struct smb_filename *smb_fname_dst)
6834 char *parent_dir_src = NULL;
6835 char *parent_dir_dst = NULL;
6838 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6839 : FILE_NOTIFY_CHANGE_FILE_NAME;
6841 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6842 &parent_dir_src, NULL) ||
6843 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6844 &parent_dir_dst, NULL)) {
6848 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6849 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6850 smb_fname_src->base_name);
6851 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6852 smb_fname_dst->base_name);
6855 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6856 smb_fname_src->base_name);
6857 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6858 smb_fname_dst->base_name);
6861 /* this is a strange one. w2k3 gives an additional event for
6862 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6863 files, but not directories */
6865 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6866 FILE_NOTIFY_CHANGE_ATTRIBUTES
6867 |FILE_NOTIFY_CHANGE_CREATION,
6868 smb_fname_dst->base_name);
6871 TALLOC_FREE(parent_dir_src);
6872 TALLOC_FREE(parent_dir_dst);
6875 /****************************************************************************
6876 Returns an error if the parent directory for a filename is open in an
6878 ****************************************************************************/
6880 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6881 const struct smb_filename *smb_fname_dst_in)
6883 char *parent_dir = NULL;
6884 struct smb_filename smb_fname_parent;
6886 files_struct *fsp = NULL;
6889 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6890 &parent_dir, NULL)) {
6891 return NT_STATUS_NO_MEMORY;
6893 ZERO_STRUCT(smb_fname_parent);
6894 smb_fname_parent.base_name = parent_dir;
6896 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6898 return map_nt_error_from_unix(errno);
6902 * We're only checking on this smbd here, mostly good
6903 * enough.. and will pass tests.
6906 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6907 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6908 fsp = file_find_di_next(fsp)) {
6909 if (fsp->access_mask & DELETE_ACCESS) {
6910 return NT_STATUS_SHARING_VIOLATION;
6913 return NT_STATUS_OK;
6916 /****************************************************************************
6917 Rename an open file - given an fsp.
6918 ****************************************************************************/
6920 NTSTATUS rename_internals_fsp(connection_struct *conn,
6922 const struct smb_filename *smb_fname_dst_in,
6924 bool replace_if_exists)
6926 TALLOC_CTX *ctx = talloc_tos();
6927 struct smb_filename *smb_fname_dst = NULL;
6928 NTSTATUS status = NT_STATUS_OK;
6929 struct share_mode_lock *lck = NULL;
6930 uint32_t access_mask = SEC_DIR_ADD_FILE;
6931 bool dst_exists, old_is_stream, new_is_stream;
6934 status = check_name(conn, smb_fname_dst_in);
6935 if (!NT_STATUS_IS_OK(status)) {
6939 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6940 if (!NT_STATUS_IS_OK(status)) {
6944 if (file_has_open_streams(fsp)) {
6945 return NT_STATUS_ACCESS_DENIED;
6948 /* Make a copy of the dst smb_fname structs */
6950 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6951 if (smb_fname_dst == NULL) {
6952 status = NT_STATUS_NO_MEMORY;
6957 * Check for special case with case preserving and not
6958 * case sensitive. If the new last component differs from the original
6959 * last component only by case, then we should allow
6960 * the rename (user is trying to change the case of the
6963 if (!conn->case_sensitive && conn->case_preserve &&
6964 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6965 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6966 char *fname_dst_parent = NULL;
6967 const char *fname_dst_lcomp = NULL;
6968 char *orig_lcomp_path = NULL;
6969 char *orig_lcomp_stream = NULL;
6973 * Split off the last component of the processed
6974 * destination name. We will compare this to
6975 * the split components of smb_fname_dst->original_lcomp.
6977 if (!parent_dirname(ctx,
6978 smb_fname_dst->base_name,
6980 &fname_dst_lcomp)) {
6981 status = NT_STATUS_NO_MEMORY;
6986 * The original_lcomp component contains
6987 * the last_component of the path + stream
6988 * name (if a stream exists).
6990 * Split off the stream name so we
6991 * can check them separately.
6994 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6995 /* POSIX - no stream component. */
6996 orig_lcomp_path = talloc_strdup(ctx,
6997 smb_fname_dst->original_lcomp);
6998 if (orig_lcomp_path == NULL) {
7002 ok = split_stream_filename(ctx,
7003 smb_fname_dst->original_lcomp,
7005 &orig_lcomp_stream);
7009 TALLOC_FREE(fname_dst_parent);
7010 status = NT_STATUS_NO_MEMORY;
7014 /* If the base names only differ by case, use original. */
7015 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7018 * Replace the modified last component with the
7021 if (!ISDOT(fname_dst_parent)) {
7022 tmp = talloc_asprintf(smb_fname_dst,
7027 tmp = talloc_strdup(smb_fname_dst,
7031 status = NT_STATUS_NO_MEMORY;
7032 TALLOC_FREE(fname_dst_parent);
7033 TALLOC_FREE(orig_lcomp_path);
7034 TALLOC_FREE(orig_lcomp_stream);
7037 TALLOC_FREE(smb_fname_dst->base_name);
7038 smb_fname_dst->base_name = tmp;
7041 /* If the stream_names only differ by case, use original. */
7042 if(!strcsequal(smb_fname_dst->stream_name,
7043 orig_lcomp_stream)) {
7044 /* Use the original stream. */
7045 char *tmp = talloc_strdup(smb_fname_dst,
7048 status = NT_STATUS_NO_MEMORY;
7049 TALLOC_FREE(fname_dst_parent);
7050 TALLOC_FREE(orig_lcomp_path);
7051 TALLOC_FREE(orig_lcomp_stream);
7054 TALLOC_FREE(smb_fname_dst->stream_name);
7055 smb_fname_dst->stream_name = tmp;
7057 TALLOC_FREE(fname_dst_parent);
7058 TALLOC_FREE(orig_lcomp_path);
7059 TALLOC_FREE(orig_lcomp_stream);
7063 * If the src and dest names are identical - including case,
7064 * don't do the rename, just return success.
7067 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7068 strcsequal(fsp->fsp_name->stream_name,
7069 smb_fname_dst->stream_name)) {
7070 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7071 "- returning success\n",
7072 smb_fname_str_dbg(smb_fname_dst)));
7073 status = NT_STATUS_OK;
7077 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7078 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7080 /* Return the correct error code if both names aren't streams. */
7081 if (!old_is_stream && new_is_stream) {
7082 status = NT_STATUS_OBJECT_NAME_INVALID;
7086 if (old_is_stream && !new_is_stream) {
7087 status = NT_STATUS_INVALID_PARAMETER;
7091 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7093 if(!replace_if_exists && dst_exists) {
7094 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7095 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7096 smb_fname_str_dbg(smb_fname_dst)));
7097 status = NT_STATUS_OBJECT_NAME_COLLISION;
7102 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7103 &smb_fname_dst->st);
7104 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7106 /* The file can be open when renaming a stream */
7107 if (dst_fsp && !new_is_stream) {
7108 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7109 status = NT_STATUS_ACCESS_DENIED;
7114 /* Ensure we have a valid stat struct for the source. */
7115 status = vfs_stat_fsp(fsp);
7116 if (!NT_STATUS_IS_OK(status)) {
7120 status = can_rename(conn, fsp, attrs);
7122 if (!NT_STATUS_IS_OK(status)) {
7123 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7124 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7125 smb_fname_str_dbg(smb_fname_dst)));
7126 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7127 status = NT_STATUS_ACCESS_DENIED;
7131 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7132 status = NT_STATUS_ACCESS_DENIED;
7136 /* Do we have rights to move into the destination ? */
7137 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7138 /* We're moving a directory. */
7139 access_mask = SEC_DIR_ADD_SUBDIR;
7141 status = check_parent_access(conn,
7144 if (!NT_STATUS_IS_OK(status)) {
7145 DBG_INFO("check_parent_access on "
7146 "dst %s returned %s\n",
7147 smb_fname_str_dbg(smb_fname_dst),
7152 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7155 * We have the file open ourselves, so not being able to get the
7156 * corresponding share mode lock is a fatal error.
7159 SMB_ASSERT(lck != NULL);
7161 ret = SMB_VFS_RENAMEAT(conn,
7167 uint32_t create_options = fsp->fh->private_options;
7169 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7170 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7171 smb_fname_str_dbg(smb_fname_dst)));
7173 if (!fsp->is_directory &&
7174 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7175 (lp_map_archive(SNUM(conn)) ||
7176 lp_store_dos_attributes(SNUM(conn)))) {
7177 /* We must set the archive bit on the newly
7179 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7180 uint32_t old_dosmode = dos_mode(conn,
7182 file_set_dosmode(conn,
7184 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7190 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
7193 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7197 * A rename acts as a new file create w.r.t. allowing an initial delete
7198 * on close, probably because in Windows there is a new handle to the
7199 * new file. If initial delete on close was requested but not
7200 * originally set, we need to set it here. This is probably not 100% correct,
7201 * but will work for the CIFSFS client which in non-posix mode
7202 * depends on these semantics. JRA.
7205 if (create_options & FILE_DELETE_ON_CLOSE) {
7206 status = can_set_delete_on_close(fsp, 0);
7208 if (NT_STATUS_IS_OK(status)) {
7209 /* Note that here we set the *initial* delete on close flag,
7210 * not the regular one. The magic gets handled in close. */
7211 fsp->initial_delete_on_close = True;
7215 status = NT_STATUS_OK;
7221 if (errno == ENOTDIR || errno == EISDIR) {
7222 status = NT_STATUS_OBJECT_NAME_COLLISION;
7224 status = map_nt_error_from_unix(errno);
7227 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7228 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7229 smb_fname_str_dbg(smb_fname_dst)));
7232 TALLOC_FREE(smb_fname_dst);
7237 /****************************************************************************
7238 The guts of the rename command, split out so it may be called by the NT SMB
7240 ****************************************************************************/
7242 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7243 connection_struct *conn,
7244 struct smb_request *req,
7245 struct smb_filename *smb_fname_src,
7246 struct smb_filename *smb_fname_dst,
7248 bool replace_if_exists,
7251 uint32_t access_mask)
7253 char *fname_src_dir = NULL;
7254 struct smb_filename *smb_fname_src_dir = NULL;
7255 char *fname_src_mask = NULL;
7257 NTSTATUS status = NT_STATUS_OK;
7258 struct smb_Dir *dir_hnd = NULL;
7259 const char *dname = NULL;
7260 char *talloced = NULL;
7262 int create_options = 0;
7263 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7267 * Split the old name into directory and last component
7268 * strings. Note that unix_convert may have stripped off a
7269 * leading ./ from both name and newname if the rename is
7270 * at the root of the share. We need to make sure either both
7271 * name and newname contain a / character or neither of them do
7272 * as this is checked in resolve_wildcards().
7275 /* Split up the directory from the filename/mask. */
7276 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7277 &fname_src_dir, &fname_src_mask);
7278 if (!NT_STATUS_IS_OK(status)) {
7279 status = NT_STATUS_NO_MEMORY;
7284 * We should only check the mangled cache
7285 * here if unix_convert failed. This means
7286 * that the path in 'mask' doesn't exist
7287 * on the file system and so we need to look
7288 * for a possible mangle. This patch from
7289 * Tine Smukavec <valentin.smukavec@hermes.si>.
7292 if (!VALID_STAT(smb_fname_src->st) &&
7293 mangle_is_mangled(fname_src_mask, conn->params)) {
7294 char *new_mask = NULL;
7295 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7298 TALLOC_FREE(fname_src_mask);
7299 fname_src_mask = new_mask;
7303 if (!src_has_wild) {
7307 * Only one file needs to be renamed. Append the mask back
7308 * onto the directory.
7310 TALLOC_FREE(smb_fname_src->base_name);
7311 if (ISDOT(fname_src_dir)) {
7312 /* Ensure we use canonical names on open. */
7313 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7317 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7322 if (!smb_fname_src->base_name) {
7323 status = NT_STATUS_NO_MEMORY;
7327 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7328 "case_preserve = %d, short case preserve = %d, "
7329 "directory = %s, newname = %s, "
7330 "last_component_dest = %s\n",
7331 conn->case_sensitive, conn->case_preserve,
7332 conn->short_case_preserve,
7333 smb_fname_str_dbg(smb_fname_src),
7334 smb_fname_str_dbg(smb_fname_dst),
7335 smb_fname_dst->original_lcomp));
7337 /* The dest name still may have wildcards. */
7338 if (dest_has_wild) {
7339 char *fname_dst_mod = NULL;
7340 if (!resolve_wildcards(smb_fname_dst,
7341 smb_fname_src->base_name,
7342 smb_fname_dst->base_name,
7344 DEBUG(6, ("rename_internals: resolve_wildcards "
7346 smb_fname_src->base_name,
7347 smb_fname_dst->base_name));
7348 status = NT_STATUS_NO_MEMORY;
7351 TALLOC_FREE(smb_fname_dst->base_name);
7352 smb_fname_dst->base_name = fname_dst_mod;
7355 ZERO_STRUCT(smb_fname_src->st);
7356 if (posix_pathnames) {
7357 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7359 rc = SMB_VFS_STAT(conn, smb_fname_src);
7362 status = map_nt_error_from_unix_common(errno);
7366 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7367 create_options |= FILE_DIRECTORY_FILE;
7370 status = SMB_VFS_CREATE_FILE(
7373 0, /* root_dir_fid */
7374 smb_fname_src, /* fname */
7375 access_mask, /* access_mask */
7376 (FILE_SHARE_READ | /* share_access */
7378 FILE_OPEN, /* create_disposition*/
7379 create_options, /* create_options */
7380 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7381 0, /* oplock_request */
7383 0, /* allocation_size */
7384 0, /* private_flags */
7389 NULL, NULL); /* create context */
7391 if (!NT_STATUS_IS_OK(status)) {
7392 DEBUG(3, ("Could not open rename source %s: %s\n",
7393 smb_fname_str_dbg(smb_fname_src),
7394 nt_errstr(status)));
7398 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7399 attrs, replace_if_exists);
7401 close_file(req, fsp, NORMAL_CLOSE);
7403 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7404 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7405 smb_fname_str_dbg(smb_fname_dst)));
7411 * Wildcards - process each file that matches.
7413 if (strequal(fname_src_mask, "????????.???")) {
7414 TALLOC_FREE(fname_src_mask);
7415 fname_src_mask = talloc_strdup(ctx, "*");
7416 if (!fname_src_mask) {
7417 status = NT_STATUS_NO_MEMORY;
7422 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7426 smb_fname_src->flags);
7427 if (smb_fname_src_dir == NULL) {
7428 status = NT_STATUS_NO_MEMORY;
7432 status = check_name(conn, smb_fname_src_dir);
7433 if (!NT_STATUS_IS_OK(status)) {
7437 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7439 if (dir_hnd == NULL) {
7440 status = map_nt_error_from_unix(errno);
7444 status = NT_STATUS_NO_SUCH_FILE;
7446 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7447 * - gentest fix. JRA
7450 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7452 files_struct *fsp = NULL;
7453 char *destname = NULL;
7454 bool sysdir_entry = False;
7456 /* Quick check for "." and ".." */
7457 if (ISDOT(dname) || ISDOTDOT(dname)) {
7458 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7459 sysdir_entry = True;
7461 TALLOC_FREE(talloced);
7466 if (!is_visible_file(conn, fname_src_dir, dname,
7467 &smb_fname_src->st, false)) {
7468 TALLOC_FREE(talloced);
7472 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7473 TALLOC_FREE(talloced);
7478 status = NT_STATUS_OBJECT_NAME_INVALID;
7482 TALLOC_FREE(smb_fname_src->base_name);
7483 if (ISDOT(fname_src_dir)) {
7484 /* Ensure we use canonical names on open. */
7485 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7489 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7494 if (!smb_fname_src->base_name) {
7495 status = NT_STATUS_NO_MEMORY;
7499 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7500 smb_fname_dst->base_name,
7502 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7503 smb_fname_src->base_name, destname));
7504 TALLOC_FREE(talloced);
7508 status = NT_STATUS_NO_MEMORY;
7512 TALLOC_FREE(smb_fname_dst->base_name);
7513 smb_fname_dst->base_name = destname;
7515 ZERO_STRUCT(smb_fname_src->st);
7516 if (posix_pathnames) {
7517 SMB_VFS_LSTAT(conn, smb_fname_src);
7519 SMB_VFS_STAT(conn, smb_fname_src);
7524 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7525 create_options |= FILE_DIRECTORY_FILE;
7528 status = SMB_VFS_CREATE_FILE(
7531 0, /* root_dir_fid */
7532 smb_fname_src, /* fname */
7533 access_mask, /* access_mask */
7534 (FILE_SHARE_READ | /* share_access */
7536 FILE_OPEN, /* create_disposition*/
7537 create_options, /* create_options */
7538 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7539 0, /* oplock_request */
7541 0, /* allocation_size */
7542 0, /* private_flags */
7547 NULL, NULL); /* create context */
7549 if (!NT_STATUS_IS_OK(status)) {
7550 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7551 "returned %s rename %s -> %s\n",
7553 smb_fname_str_dbg(smb_fname_src),
7554 smb_fname_str_dbg(smb_fname_dst)));
7558 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7560 if (!smb_fname_dst->original_lcomp) {
7561 status = NT_STATUS_NO_MEMORY;
7565 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7566 attrs, replace_if_exists);
7568 close_file(req, fsp, NORMAL_CLOSE);
7570 if (!NT_STATUS_IS_OK(status)) {
7571 DEBUG(3, ("rename_internals_fsp returned %s for "
7572 "rename %s -> %s\n", nt_errstr(status),
7573 smb_fname_str_dbg(smb_fname_src),
7574 smb_fname_str_dbg(smb_fname_dst)));
7580 DEBUG(3,("rename_internals: doing rename on %s -> "
7581 "%s\n", smb_fname_str_dbg(smb_fname_src),
7582 smb_fname_str_dbg(smb_fname_src)));
7583 TALLOC_FREE(talloced);
7585 TALLOC_FREE(dir_hnd);
7587 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7588 status = map_nt_error_from_unix(errno);
7592 TALLOC_FREE(talloced);
7593 TALLOC_FREE(smb_fname_src_dir);
7594 TALLOC_FREE(fname_src_dir);
7595 TALLOC_FREE(fname_src_mask);
7599 /****************************************************************************
7601 ****************************************************************************/
7603 void reply_mv(struct smb_request *req)
7605 connection_struct *conn = req->conn;
7607 char *newname = NULL;
7611 bool src_has_wcard = False;
7612 bool dest_has_wcard = False;
7613 TALLOC_CTX *ctx = talloc_tos();
7614 struct smb_filename *smb_fname_src = NULL;
7615 struct smb_filename *smb_fname_dst = NULL;
7616 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7617 (req->posix_pathnames ?
7618 UCF_UNIX_NAME_LOOKUP :
7619 UCF_COND_ALLOW_WCARD_LCOMP);
7620 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7622 (req->posix_pathnames ?
7624 UCF_COND_ALLOW_WCARD_LCOMP);
7625 bool stream_rename = false;
7627 START_PROFILE(SMBmv);
7630 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7634 attrs = SVAL(req->vwv+0, 0);
7636 p = (const char *)req->buf + 1;
7637 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7638 &status, &src_has_wcard);
7639 if (!NT_STATUS_IS_OK(status)) {
7640 reply_nterror(req, status);
7644 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7645 &status, &dest_has_wcard);
7646 if (!NT_STATUS_IS_OK(status)) {
7647 reply_nterror(req, status);
7651 if (!req->posix_pathnames) {
7652 /* The newname must begin with a ':' if the
7653 name contains a ':'. */
7654 if (strchr_m(name, ':')) {
7655 if (newname[0] != ':') {
7656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7659 stream_rename = true;
7663 status = filename_convert(ctx,
7671 if (!NT_STATUS_IS_OK(status)) {
7672 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7673 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7674 ERRSRV, ERRbadpath);
7677 reply_nterror(req, status);
7681 status = filename_convert(ctx,
7689 if (!NT_STATUS_IS_OK(status)) {
7690 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7691 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7692 ERRSRV, ERRbadpath);
7695 reply_nterror(req, status);
7699 if (stream_rename) {
7700 /* smb_fname_dst->base_name must be the same as
7701 smb_fname_src->base_name. */
7702 TALLOC_FREE(smb_fname_dst->base_name);
7703 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7704 smb_fname_src->base_name);
7705 if (!smb_fname_dst->base_name) {
7706 reply_nterror(req, NT_STATUS_NO_MEMORY);
7711 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7712 smb_fname_str_dbg(smb_fname_dst)));
7714 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7715 attrs, False, src_has_wcard, dest_has_wcard,
7717 if (!NT_STATUS_IS_OK(status)) {
7718 if (open_was_deferred(req->xconn, req->mid)) {
7719 /* We have re-scheduled this call. */
7722 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7723 bool ok = defer_smb1_sharing_violation(req);
7728 reply_nterror(req, status);
7732 reply_outbuf(req, 0, 0);
7734 TALLOC_FREE(smb_fname_src);
7735 TALLOC_FREE(smb_fname_dst);
7740 /*******************************************************************
7741 Copy a file as part of a reply_copy.
7742 ******************************************************************/
7745 * TODO: check error codes on all callers
7748 NTSTATUS copy_file(TALLOC_CTX *ctx,
7749 connection_struct *conn,
7750 struct smb_filename *smb_fname_src,
7751 struct smb_filename *smb_fname_dst,
7754 bool target_is_directory)
7756 struct smb_filename *smb_fname_dst_tmp = NULL;
7758 files_struct *fsp1,*fsp2;
7760 uint32_t new_create_disposition;
7764 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7765 if (smb_fname_dst_tmp == NULL) {
7766 return NT_STATUS_NO_MEMORY;
7770 * If the target is a directory, extract the last component from the
7771 * src filename and append it to the dst filename
7773 if (target_is_directory) {
7776 /* dest/target can't be a stream if it's a directory. */
7777 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7779 p = strrchr_m(smb_fname_src->base_name,'/');
7783 p = smb_fname_src->base_name;
7785 smb_fname_dst_tmp->base_name =
7786 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7788 if (!smb_fname_dst_tmp->base_name) {
7789 status = NT_STATUS_NO_MEMORY;
7794 status = vfs_file_exist(conn, smb_fname_src);
7795 if (!NT_STATUS_IS_OK(status)) {
7799 if (!target_is_directory && count) {
7800 new_create_disposition = FILE_OPEN;
7802 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7805 &new_create_disposition,
7808 status = NT_STATUS_INVALID_PARAMETER;
7813 /* Open the src file for reading. */
7814 status = SMB_VFS_CREATE_FILE(
7817 0, /* root_dir_fid */
7818 smb_fname_src, /* fname */
7819 FILE_GENERIC_READ, /* access_mask */
7820 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7821 FILE_OPEN, /* create_disposition*/
7822 0, /* create_options */
7823 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7824 INTERNAL_OPEN_ONLY, /* oplock_request */
7826 0, /* allocation_size */
7827 0, /* private_flags */
7832 NULL, NULL); /* create context */
7834 if (!NT_STATUS_IS_OK(status)) {
7838 dosattrs = dos_mode(conn, smb_fname_src);
7840 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7841 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7844 /* Open the dst file for writing. */
7845 status = SMB_VFS_CREATE_FILE(
7848 0, /* root_dir_fid */
7849 smb_fname_dst, /* fname */
7850 FILE_GENERIC_WRITE, /* access_mask */
7851 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7852 new_create_disposition, /* create_disposition*/
7853 0, /* create_options */
7854 dosattrs, /* file_attributes */
7855 INTERNAL_OPEN_ONLY, /* oplock_request */
7857 0, /* allocation_size */
7858 0, /* private_flags */
7863 NULL, NULL); /* create context */
7865 if (!NT_STATUS_IS_OK(status)) {
7866 close_file(NULL, fsp1, ERROR_CLOSE);
7870 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7871 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7873 DEBUG(0, ("error - vfs lseek returned error %s\n",
7875 status = map_nt_error_from_unix(errno);
7876 close_file(NULL, fsp1, ERROR_CLOSE);
7877 close_file(NULL, fsp2, ERROR_CLOSE);
7882 /* Do the actual copy. */
7883 if (smb_fname_src->st.st_ex_size) {
7884 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7889 close_file(NULL, fsp1, NORMAL_CLOSE);
7891 /* Ensure the modtime is set correctly on the destination file. */
7892 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7895 * As we are opening fsp1 read-only we only expect
7896 * an error on close on fsp2 if we are out of space.
7897 * Thus we don't look at the error return from the
7900 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7902 if (!NT_STATUS_IS_OK(status)) {
7906 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7907 status = NT_STATUS_DISK_FULL;
7911 status = NT_STATUS_OK;
7914 TALLOC_FREE(smb_fname_dst_tmp);
7918 /****************************************************************************
7919 Reply to a file copy.
7920 ****************************************************************************/
7922 void reply_copy(struct smb_request *req)
7924 connection_struct *conn = req->conn;
7925 struct smb_filename *smb_fname_src = NULL;
7926 struct smb_filename *smb_fname_src_dir = NULL;
7927 struct smb_filename *smb_fname_dst = NULL;
7928 char *fname_src = NULL;
7929 char *fname_dst = NULL;
7930 char *fname_src_mask = NULL;
7931 char *fname_src_dir = NULL;
7934 int error = ERRnoaccess;
7938 bool target_is_directory=False;
7939 bool source_has_wild = False;
7940 bool dest_has_wild = False;
7942 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7943 ucf_flags_from_smb_request(req);
7944 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7945 ucf_flags_from_smb_request(req);
7946 TALLOC_CTX *ctx = talloc_tos();
7948 START_PROFILE(SMBcopy);
7951 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7955 tid2 = SVAL(req->vwv+0, 0);
7956 ofun = SVAL(req->vwv+1, 0);
7957 flags = SVAL(req->vwv+2, 0);
7959 p = (const char *)req->buf;
7960 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7961 &status, &source_has_wild);
7962 if (!NT_STATUS_IS_OK(status)) {
7963 reply_nterror(req, status);
7966 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7967 &status, &dest_has_wild);
7968 if (!NT_STATUS_IS_OK(status)) {
7969 reply_nterror(req, status);
7973 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7975 if (tid2 != conn->cnum) {
7976 /* can't currently handle inter share copies XXXX */
7977 DEBUG(3,("Rejecting inter-share copy\n"));
7978 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7982 status = filename_convert(ctx, conn,
7988 if (!NT_STATUS_IS_OK(status)) {
7989 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7990 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7991 ERRSRV, ERRbadpath);
7994 reply_nterror(req, status);
7998 status = filename_convert(ctx, conn,
8004 if (!NT_STATUS_IS_OK(status)) {
8005 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8006 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8007 ERRSRV, ERRbadpath);
8010 reply_nterror(req, status);
8014 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8016 if ((flags&1) && target_is_directory) {
8017 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8021 if ((flags&2) && !target_is_directory) {
8022 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8026 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8027 /* wants a tree copy! XXXX */
8028 DEBUG(3,("Rejecting tree copy\n"));
8029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8033 /* Split up the directory from the filename/mask. */
8034 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8035 &fname_src_dir, &fname_src_mask);
8036 if (!NT_STATUS_IS_OK(status)) {
8037 reply_nterror(req, NT_STATUS_NO_MEMORY);
8042 * We should only check the mangled cache
8043 * here if unix_convert failed. This means
8044 * that the path in 'mask' doesn't exist
8045 * on the file system and so we need to look
8046 * for a possible mangle. This patch from
8047 * Tine Smukavec <valentin.smukavec@hermes.si>.
8049 if (!VALID_STAT(smb_fname_src->st) &&
8050 mangle_is_mangled(fname_src_mask, conn->params)) {
8051 char *new_mask = NULL;
8052 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8053 &new_mask, conn->params);
8055 /* Use demangled name if one was successfully found. */
8057 TALLOC_FREE(fname_src_mask);
8058 fname_src_mask = new_mask;
8062 if (!source_has_wild) {
8065 * Only one file needs to be copied. Append the mask back onto
8068 TALLOC_FREE(smb_fname_src->base_name);
8069 if (ISDOT(fname_src_dir)) {
8070 /* Ensure we use canonical names on open. */
8071 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8075 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8080 if (!smb_fname_src->base_name) {
8081 reply_nterror(req, NT_STATUS_NO_MEMORY);
8085 if (dest_has_wild) {
8086 char *fname_dst_mod = NULL;
8087 if (!resolve_wildcards(smb_fname_dst,
8088 smb_fname_src->base_name,
8089 smb_fname_dst->base_name,
8091 reply_nterror(req, NT_STATUS_NO_MEMORY);
8094 TALLOC_FREE(smb_fname_dst->base_name);
8095 smb_fname_dst->base_name = fname_dst_mod;
8098 status = check_name(conn, smb_fname_src);
8099 if (!NT_STATUS_IS_OK(status)) {
8100 reply_nterror(req, status);
8104 status = check_name(conn, smb_fname_dst);
8105 if (!NT_STATUS_IS_OK(status)) {
8106 reply_nterror(req, status);
8110 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8111 ofun, count, target_is_directory);
8113 if(!NT_STATUS_IS_OK(status)) {
8114 reply_nterror(req, status);
8120 struct smb_Dir *dir_hnd = NULL;
8121 const char *dname = NULL;
8122 char *talloced = NULL;
8126 * There is a wildcard that requires us to actually read the
8127 * src dir and copy each file matching the mask to the dst.
8128 * Right now streams won't be copied, but this could
8129 * presumably be added with a nested loop for reach dir entry.
8131 SMB_ASSERT(!smb_fname_src->stream_name);
8132 SMB_ASSERT(!smb_fname_dst->stream_name);
8134 smb_fname_src->stream_name = NULL;
8135 smb_fname_dst->stream_name = NULL;
8137 if (strequal(fname_src_mask,"????????.???")) {
8138 TALLOC_FREE(fname_src_mask);
8139 fname_src_mask = talloc_strdup(ctx, "*");
8140 if (!fname_src_mask) {
8141 reply_nterror(req, NT_STATUS_NO_MEMORY);
8146 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8150 smb_fname_src->flags);
8151 if (smb_fname_src_dir == NULL) {
8152 reply_nterror(req, NT_STATUS_NO_MEMORY);
8156 status = check_name(conn, smb_fname_src_dir);
8157 if (!NT_STATUS_IS_OK(status)) {
8158 reply_nterror(req, status);
8162 dir_hnd = OpenDir(ctx,
8167 if (dir_hnd == NULL) {
8168 status = map_nt_error_from_unix(errno);
8169 reply_nterror(req, status);
8175 /* Iterate over the src dir copying each entry to the dst. */
8176 while ((dname = ReadDirName(dir_hnd, &offset,
8177 &smb_fname_src->st, &talloced))) {
8178 char *destname = NULL;
8180 if (ISDOT(dname) || ISDOTDOT(dname)) {
8181 TALLOC_FREE(talloced);
8185 if (!is_visible_file(conn, fname_src_dir, dname,
8186 &smb_fname_src->st, false)) {
8187 TALLOC_FREE(talloced);
8191 if(!mask_match(dname, fname_src_mask,
8192 conn->case_sensitive)) {
8193 TALLOC_FREE(talloced);
8197 error = ERRnoaccess;
8199 /* Get the src smb_fname struct setup. */
8200 TALLOC_FREE(smb_fname_src->base_name);
8201 if (ISDOT(fname_src_dir)) {
8202 /* Ensure we use canonical names on open. */
8203 smb_fname_src->base_name =
8204 talloc_asprintf(smb_fname_src, "%s",
8207 smb_fname_src->base_name =
8208 talloc_asprintf(smb_fname_src, "%s/%s",
8209 fname_src_dir, dname);
8212 if (!smb_fname_src->base_name) {
8213 TALLOC_FREE(dir_hnd);
8214 TALLOC_FREE(talloced);
8215 reply_nterror(req, NT_STATUS_NO_MEMORY);
8219 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8220 smb_fname_dst->base_name,
8222 TALLOC_FREE(talloced);
8226 TALLOC_FREE(dir_hnd);
8227 TALLOC_FREE(talloced);
8228 reply_nterror(req, NT_STATUS_NO_MEMORY);
8232 TALLOC_FREE(smb_fname_dst->base_name);
8233 smb_fname_dst->base_name = destname;
8235 status = check_name(conn, smb_fname_src);
8236 if (!NT_STATUS_IS_OK(status)) {
8237 TALLOC_FREE(dir_hnd);
8238 TALLOC_FREE(talloced);
8239 reply_nterror(req, status);
8243 status = check_name(conn, smb_fname_dst);
8244 if (!NT_STATUS_IS_OK(status)) {
8245 TALLOC_FREE(dir_hnd);
8246 TALLOC_FREE(talloced);
8247 reply_nterror(req, status);
8251 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8252 smb_fname_src->base_name,
8253 smb_fname_dst->base_name));
8255 status = copy_file(ctx, conn, smb_fname_src,
8256 smb_fname_dst, ofun, count,
8257 target_is_directory);
8258 if (NT_STATUS_IS_OK(status)) {
8262 TALLOC_FREE(talloced);
8264 TALLOC_FREE(dir_hnd);
8268 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8272 reply_outbuf(req, 1, 0);
8273 SSVAL(req->outbuf,smb_vwv0,count);
8275 TALLOC_FREE(smb_fname_src);
8276 TALLOC_FREE(smb_fname_src_dir);
8277 TALLOC_FREE(smb_fname_dst);
8278 TALLOC_FREE(fname_src);
8279 TALLOC_FREE(fname_dst);
8280 TALLOC_FREE(fname_src_mask);
8281 TALLOC_FREE(fname_src_dir);
8283 END_PROFILE(SMBcopy);
8288 #define DBGC_CLASS DBGC_LOCKING
8290 /****************************************************************************
8291 Get a lock pid, dealing with large count requests.
8292 ****************************************************************************/
8294 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8295 bool large_file_format)
8297 if(!large_file_format)
8298 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8300 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8303 /****************************************************************************
8304 Get a lock count, dealing with large count requests.
8305 ****************************************************************************/
8307 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8308 bool large_file_format)
8312 if(!large_file_format) {
8313 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8316 * No BVAL, this is reversed!
8318 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8319 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8325 /****************************************************************************
8326 Get a lock offset, dealing with large offset requests.
8327 ****************************************************************************/
8329 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8330 bool large_file_format)
8332 uint64_t offset = 0;
8334 if(!large_file_format) {
8335 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8338 * No BVAL, this is reversed!
8340 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8341 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8347 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8349 uint16_t num_ulocks,
8350 struct smbd_lock_element *ulocks,
8351 enum brl_flavour lock_flav)
8353 struct share_mode_lock *lck;
8354 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8357 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8359 for(i = 0; i < num_ulocks; i++) {
8360 struct smbd_lock_element *e = &ulocks[i];
8362 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
8363 "pid %"PRIu64", file %s\n",
8369 if (e->brltype != UNLOCK_LOCK) {
8370 /* this can only happen with SMB2 */
8371 status = NT_STATUS_INVALID_PARAMETER;
8382 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8383 nt_errstr(status)));
8385 if (!NT_STATUS_IS_OK(status)) {
8390 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8394 if (NT_STATUS_IS_OK(status) && (lck != NULL)) {
8395 lck->data->modified = true;
8402 /****************************************************************************
8403 Reply to a lockingX request.
8404 ****************************************************************************/
8406 static void reply_lockingx_done(struct tevent_req *subreq);
8408 void reply_lockingX(struct smb_request *req)
8410 connection_struct *conn = req->conn;
8412 unsigned char locktype;
8413 enum brl_type brltype;
8414 unsigned char oplocklevel;
8415 uint16_t num_ulocks;
8417 int32_t lock_timeout;
8419 const uint8_t *data;
8420 bool large_file_format;
8421 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8422 struct smbd_lock_element *locks = NULL;
8423 struct tevent_req *subreq = NULL;
8425 START_PROFILE(SMBlockingX);
8428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8429 END_PROFILE(SMBlockingX);
8433 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8434 locktype = CVAL(req->vwv+3, 0);
8435 oplocklevel = CVAL(req->vwv+3, 1);
8436 num_ulocks = SVAL(req->vwv+6, 0);
8437 num_locks = SVAL(req->vwv+7, 0);
8438 lock_timeout = IVAL(req->vwv+4, 0);
8439 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8441 if (!check_fsp(conn, req, fsp)) {
8442 END_PROFILE(SMBlockingX);
8448 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8449 /* we don't support these - and CANCEL_LOCK makes w2k
8450 and XP reboot so I don't really want to be
8451 compatible! (tridge) */
8452 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8453 END_PROFILE(SMBlockingX);
8457 /* Check if this is an oplock break on a file
8458 we have granted an oplock on.
8460 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8461 /* Client can insist on breaking to none. */
8462 bool break_to_none = (oplocklevel == 0);
8465 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8466 "for %s\n", (unsigned int)oplocklevel,
8467 fsp_fnum_dbg(fsp)));
8470 * Make sure we have granted an exclusive or batch oplock on
8474 if (fsp->oplock_type == 0) {
8476 /* The Samba4 nbench simulator doesn't understand
8477 the difference between break to level2 and break
8478 to none from level2 - it sends oplock break
8479 replies in both cases. Don't keep logging an error
8480 message here - just ignore it. JRA. */
8482 DEBUG(5,("reply_lockingX: Error : oplock break from "
8483 "client for %s (oplock=%d) and no "
8484 "oplock granted on this file (%s).\n",
8485 fsp_fnum_dbg(fsp), fsp->oplock_type,
8488 /* if this is a pure oplock break request then don't
8490 if (num_locks == 0 && num_ulocks == 0) {
8491 END_PROFILE(SMBlockingX);
8495 END_PROFILE(SMBlockingX);
8496 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8500 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8502 result = remove_oplock(fsp);
8504 result = downgrade_oplock(fsp);
8508 DEBUG(0, ("reply_lockingX: error in removing "
8509 "oplock on file %s\n", fsp_str_dbg(fsp)));
8510 /* Hmmm. Is this panic justified? */
8511 smb_panic("internal tdb error");
8514 /* if this is a pure oplock break request then don't send a
8516 if (num_locks == 0 && num_ulocks == 0) {
8517 /* Sanity check - ensure a pure oplock break is not a
8519 if (CVAL(req->vwv+0, 0) != 0xff) {
8520 DEBUG(0,("reply_lockingX: Error : pure oplock "
8521 "break is a chained %d request !\n",
8522 (unsigned int)CVAL(req->vwv+0, 0)));
8524 END_PROFILE(SMBlockingX);
8530 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8532 END_PROFILE(SMBlockingX);
8536 if (num_ulocks != 0) {
8537 struct smbd_lock_element *ulocks = NULL;
8540 ulocks = talloc_array(
8541 req, struct smbd_lock_element, num_ulocks);
8542 if (ulocks == NULL) {
8543 reply_nterror(req, NT_STATUS_NO_MEMORY);
8544 END_PROFILE(SMBlockingX);
8549 * Data now points at the beginning of the list of
8550 * smb_unlkrng structs
8552 for (i = 0; i < num_ulocks; i++) {
8553 ulocks[i].smblctx = get_lock_pid(
8554 data, i, large_file_format);
8555 ulocks[i].count = get_lock_count(
8556 data, i, large_file_format);
8557 ulocks[i].offset = get_lock_offset(
8558 data, i, large_file_format);
8559 ulocks[i].brltype = UNLOCK_LOCK;
8563 * Unlock cancels pending locks
8566 ok = smbd_smb1_brl_finish_by_lock(
8573 reply_outbuf(req, 2, 0);
8574 SSVAL(req->outbuf, smb_vwv0, 0xff);
8575 SSVAL(req->outbuf, smb_vwv1, 0);
8576 END_PROFILE(SMBlockingX);
8580 status = smbd_do_unlocking(
8581 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
8582 TALLOC_FREE(ulocks);
8583 if (!NT_STATUS_IS_OK(status)) {
8584 END_PROFILE(SMBlockingX);
8585 reply_nterror(req, status);
8590 /* Now do any requested locks */
8591 data += ((large_file_format ? 20 : 10)*num_ulocks);
8593 /* Data now points at the beginning of the list
8594 of smb_lkrng structs */
8596 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8597 brltype = READ_LOCK;
8599 brltype = WRITE_LOCK;
8602 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8603 if (locks == NULL) {
8604 reply_nterror(req, NT_STATUS_NO_MEMORY);
8605 END_PROFILE(SMBlockingX);
8609 for (i = 0; i < num_locks; i++) {
8610 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8611 locks[i].count = get_lock_count(data, i, large_file_format);
8612 locks[i].offset = get_lock_offset(data, i, large_file_format);
8613 locks[i].brltype = brltype;
8616 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8620 if (num_locks == 0) {
8621 /* See smbtorture3 lock11 test */
8622 reply_outbuf(req, 2, 0);
8623 /* andx chain ends */
8624 SSVAL(req->outbuf, smb_vwv0, 0xff);
8625 SSVAL(req->outbuf, smb_vwv1, 0);
8626 END_PROFILE(SMBlockingX);
8630 ok = smbd_smb1_brl_finish_by_lock(
8634 locks[0], /* Windows only cancels the first lock */
8635 NT_STATUS_FILE_LOCK_CONFLICT);
8638 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
8639 END_PROFILE(SMBlockingX);
8643 reply_outbuf(req, 2, 0);
8644 SSVAL(req->outbuf, smb_vwv0, 0xff);
8645 SSVAL(req->outbuf, smb_vwv1, 0);
8646 END_PROFILE(SMBlockingX);
8650 subreq = smbd_smb1_do_locks_send(
8660 if (subreq == NULL) {
8661 reply_nterror(req, NT_STATUS_NO_MEMORY);
8662 END_PROFILE(SMBlockingX);
8665 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
8666 END_PROFILE(SMBlockingX);
8669 static void reply_lockingx_done(struct tevent_req *subreq)
8671 struct smb_request *req = NULL;
8675 START_PROFILE(SMBlockingX);
8677 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
8680 status = smbd_smb1_do_locks_recv(subreq);
8681 TALLOC_FREE(subreq);
8683 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
8685 if (NT_STATUS_IS_OK(status)) {
8686 reply_outbuf(req, 2, 0);
8687 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8688 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8690 reply_nterror(req, status);
8693 ok = srv_send_smb(req->xconn,
8694 (char *)req->outbuf,
8697 IS_CONN_ENCRYPTED(req->conn),
8700 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
8703 END_PROFILE(SMBlockingX);
8707 #define DBGC_CLASS DBGC_ALL
8709 /****************************************************************************
8710 Reply to a SMBreadbmpx (read block multiplex) request.
8711 Always reply with an error, if someone has a platform really needs this,
8712 please contact vl@samba.org
8713 ****************************************************************************/
8715 void reply_readbmpx(struct smb_request *req)
8717 START_PROFILE(SMBreadBmpx);
8718 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8719 END_PROFILE(SMBreadBmpx);
8723 /****************************************************************************
8724 Reply to a SMBreadbs (read block multiplex secondary) request.
8725 Always reply with an error, if someone has a platform really needs this,
8726 please contact vl@samba.org
8727 ****************************************************************************/
8729 void reply_readbs(struct smb_request *req)
8731 START_PROFILE(SMBreadBs);
8732 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8733 END_PROFILE(SMBreadBs);
8737 /****************************************************************************
8738 Reply to a SMBsetattrE.
8739 ****************************************************************************/
8741 void reply_setattrE(struct smb_request *req)
8743 connection_struct *conn = req->conn;
8744 struct smb_file_time ft;
8748 START_PROFILE(SMBsetattrE);
8752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8756 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8758 if(!fsp || (fsp->conn != conn)) {
8759 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8764 * Convert the DOS times into unix times.
8767 ft.atime = convert_time_t_to_timespec(
8768 srv_make_unix_date2(req->vwv+3));
8769 ft.mtime = convert_time_t_to_timespec(
8770 srv_make_unix_date2(req->vwv+5));
8771 ft.create_time = convert_time_t_to_timespec(
8772 srv_make_unix_date2(req->vwv+1));
8774 reply_outbuf(req, 0, 0);
8777 * Patch from Ray Frush <frush@engr.colostate.edu>
8778 * Sometimes times are sent as zero - ignore them.
8781 /* Ensure we have a valid stat struct for the source. */
8782 status = vfs_stat_fsp(fsp);
8783 if (!NT_STATUS_IS_OK(status)) {
8784 reply_nterror(req, status);
8788 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8789 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8793 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8794 if (!NT_STATUS_IS_OK(status)) {
8795 reply_nterror(req, status);
8799 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8802 (unsigned int)ft.atime.tv_sec,
8803 (unsigned int)ft.mtime.tv_sec,
8804 (unsigned int)ft.create_time.tv_sec
8807 END_PROFILE(SMBsetattrE);
8812 /* Back from the dead for OS/2..... JRA. */
8814 /****************************************************************************
8815 Reply to a SMBwritebmpx (write block multiplex primary) request.
8816 Always reply with an error, if someone has a platform really needs this,
8817 please contact vl@samba.org
8818 ****************************************************************************/
8820 void reply_writebmpx(struct smb_request *req)
8822 START_PROFILE(SMBwriteBmpx);
8823 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8824 END_PROFILE(SMBwriteBmpx);
8828 /****************************************************************************
8829 Reply to a SMBwritebs (write block multiplex secondary) request.
8830 Always reply with an error, if someone has a platform really needs this,
8831 please contact vl@samba.org
8832 ****************************************************************************/
8834 void reply_writebs(struct smb_request *req)
8836 START_PROFILE(SMBwriteBs);
8837 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8838 END_PROFILE(SMBwriteBs);
8842 /****************************************************************************
8843 Reply to a SMBgetattrE.
8844 ****************************************************************************/
8846 void reply_getattrE(struct smb_request *req)
8848 connection_struct *conn = req->conn;
8851 struct timespec create_ts;
8853 START_PROFILE(SMBgetattrE);
8856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8857 END_PROFILE(SMBgetattrE);
8861 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8863 if(!fsp || (fsp->conn != conn)) {
8864 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8865 END_PROFILE(SMBgetattrE);
8869 /* Do an fstat on this file */
8871 reply_nterror(req, map_nt_error_from_unix(errno));
8872 END_PROFILE(SMBgetattrE);
8876 mode = dos_mode(conn, fsp->fsp_name);
8879 * Convert the times into dos times. Set create
8880 * date to be last modify date as UNIX doesn't save
8884 reply_outbuf(req, 11, 0);
8886 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8887 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8888 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8889 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8890 /* Should we check pending modtime here ? JRA */
8891 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8892 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8894 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8895 SIVAL(req->outbuf, smb_vwv6, 0);
8896 SIVAL(req->outbuf, smb_vwv8, 0);
8898 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8899 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8900 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8902 SSVAL(req->outbuf,smb_vwv10, mode);
8904 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8906 END_PROFILE(SMBgetattrE);