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"
48 /****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
54 ****************************************************************************/
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
59 static NTSTATUS check_path_syntax_internal(char *path,
61 bool *p_last_component_contains_wcard)
65 NTSTATUS ret = NT_STATUS_OK;
66 bool start_of_name_component = True;
67 bool stream_started = false;
69 *p_last_component_contains_wcard = False;
76 return NT_STATUS_OBJECT_NAME_INVALID;
79 return NT_STATUS_OBJECT_NAME_INVALID;
81 if (strchr_m(&s[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID;
88 if ((*s == ':') && !posix_path && !stream_started) {
89 if (*p_last_component_contains_wcard) {
90 return NT_STATUS_OBJECT_NAME_INVALID;
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
98 stream_started = true;
99 start_of_name_component = false;
103 return NT_STATUS_OBJECT_NAME_INVALID;
107 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s,posix_path)) {
116 if ((d != path) && (*s != '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
121 start_of_name_component = True;
123 *p_last_component_contains_wcard = False;
127 if (start_of_name_component) {
128 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
132 * No mb char starts with '.' so we're safe checking the directory separator here.
135 /* If we just added a '/' - delete it */
136 if ((d > path) && (*(d-1) == '/')) {
141 /* Are we at the start ? Can't go back further if so. */
143 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d--; d > path; d--) {
154 s += 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
158 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
170 if (*s <= 0x1f || *s == '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID;
179 *p_last_component_contains_wcard = True;
188 /* Get the size of the next MB character. */
189 next_codepoint(s,&siz);
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
209 return NT_STATUS_INVALID_PARAMETER;
212 start_of_name_component = False;
220 /****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223 ****************************************************************************/
225 NTSTATUS check_path_syntax(char *path)
228 return check_path_syntax_internal(path, False, &ignore);
231 /****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
235 ****************************************************************************/
237 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
239 return check_path_syntax_internal(path, False, p_contains_wcard);
242 /****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246 ****************************************************************************/
248 NTSTATUS check_path_syntax_posix(char *path)
251 return check_path_syntax_internal(path, True, &ignore);
254 /****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 Passes in posix flag.
257 ****************************************************************************/
259 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
260 const char *base_ptr,
266 bool posix_pathnames,
268 bool *contains_wcard)
274 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
278 *err = NT_STATUS_INVALID_PARAMETER;
282 *contains_wcard = False;
284 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
286 * For a DFS path the function parse_dfs_path()
287 * will do the path processing, just make a copy.
293 if (posix_pathnames) {
294 *err = check_path_syntax_posix(*pp_dest);
296 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
302 /****************************************************************************
303 Pull a string and check the path allowing a wilcard - provide for error return.
304 ****************************************************************************/
306 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
307 const char *base_ptr,
314 bool *contains_wcard)
316 return srvstr_get_path_wcard_internal(ctx,
328 /****************************************************************************
329 Pull a string and check the path allowing a wilcard - provide for error return.
330 posix_pathnames version.
331 ****************************************************************************/
333 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
334 const char *base_ptr,
341 bool *contains_wcard)
343 return srvstr_get_path_wcard_internal(ctx,
355 /****************************************************************************
356 Pull a string and check the path - provide for error return.
357 ****************************************************************************/
359 size_t srvstr_get_path(TALLOC_CTX *ctx,
360 const char *base_ptr,
369 return srvstr_get_path_wcard_internal(ctx,
381 /****************************************************************************
382 Pull a string and check the path - provide for error return.
383 posix_pathnames version.
384 ****************************************************************************/
386 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
387 const char *base_ptr,
396 return srvstr_get_path_wcard_internal(ctx,
409 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
410 char **pp_dest, const char *src, int flags,
411 NTSTATUS *err, bool *contains_wcard)
413 ssize_t bufrem = smbreq_bufrem(req, src);
416 *err = NT_STATUS_INVALID_PARAMETER;
420 if (req->posix_pathnames) {
421 return srvstr_get_path_wcard_internal(mem_ctx,
422 (const char *)req->inbuf,
432 return srvstr_get_path_wcard_internal(mem_ctx,
433 (const char *)req->inbuf,
445 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
446 char **pp_dest, const char *src, int flags,
450 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
451 flags, err, &ignore);
455 * pull a string from the smb_buf part of a packet. In this case the
456 * string can either be null terminated or it can be terminated by the
457 * end of the smbbuf area
459 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
460 char **dest, const uint8_t *src, int flags)
462 ssize_t bufrem = smbreq_bufrem(req, src);
468 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
472 /****************************************************************************
473 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
474 ****************************************************************************/
476 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
479 if ((fsp == NULL) || (conn == NULL)) {
480 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
483 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
484 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
490 /****************************************************************************
491 Check if we have a correct fsp pointing to a file.
492 ****************************************************************************/
494 bool check_fsp(connection_struct *conn, struct smb_request *req,
497 if (!check_fsp_open(conn, req, fsp)) {
500 if (fsp->is_directory) {
501 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
504 if (fsp->fh->fd == -1) {
505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
508 fsp->num_smb_operations++;
512 /****************************************************************************
513 Check if we have a correct fsp pointing to a quota fake file. Replacement for
514 the CHECK_NTQUOTA_HANDLE_OK macro.
515 ****************************************************************************/
517 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
520 if (!check_fsp_open(conn, req, fsp)) {
524 if (fsp->is_directory) {
528 if (fsp->fake_file_handle == NULL) {
532 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
536 if (fsp->fake_file_handle->private_data == NULL) {
543 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
544 const char *name, int name_type)
547 char *trim_name_type;
548 const char *retarget_parm;
551 int retarget_type = 0x20;
552 int retarget_port = NBT_SMB_PORT;
553 struct sockaddr_storage retarget_addr;
554 struct sockaddr_in *in_addr;
558 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
562 trim_name = talloc_strdup(talloc_tos(), name);
563 if (trim_name == NULL) {
566 trim_char(trim_name, ' ', ' ');
568 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
570 if (trim_name_type == NULL) {
574 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
575 trim_name_type, NULL);
576 if (retarget_parm == NULL) {
577 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
580 if (retarget_parm == NULL) {
584 retarget = talloc_strdup(trim_name, retarget_parm);
585 if (retarget == NULL) {
589 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
591 p = strchr(retarget, ':');
594 retarget_port = atoi(p);
597 p = strchr_m(retarget, '#');
600 if (sscanf(p, "%x", &retarget_type) != 1) {
605 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
607 DEBUG(10, ("could not resolve %s\n", retarget));
611 if (retarget_addr.ss_family != AF_INET) {
612 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
616 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
618 _smb_setlen(outbuf, 6);
619 SCVAL(outbuf, 0, 0x84);
620 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
621 *(uint16_t *)(outbuf+8) = htons(retarget_port);
623 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
625 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
631 TALLOC_FREE(trim_name);
635 static void reply_called_name_not_present(char *outbuf)
637 smb_setlen(outbuf, 1);
638 SCVAL(outbuf, 0, 0x83);
639 SCVAL(outbuf, 4, 0x82);
642 /****************************************************************************
643 Reply to a (netbios-level) special message.
644 ****************************************************************************/
646 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
648 struct smbd_server_connection *sconn = xconn->client->sconn;
649 int msg_type = CVAL(inbuf,0);
650 int msg_flags = CVAL(inbuf,1);
652 * We only really use 4 bytes of the outbuf, but for the smb_setlen
653 * calculation & friends (srv_send_smb uses that) we need the full smb
656 char outbuf[smb_size];
658 memset(outbuf, '\0', sizeof(outbuf));
660 smb_setlen(outbuf,0);
663 case NBSSrequest: /* session request */
665 /* inbuf_size is guarenteed to be at least 4. */
667 int name_type1, name_type2;
668 int name_len1, name_len2;
672 if (xconn->transport.nbt.got_session) {
673 exit_server_cleanly("multiple session request not permitted");
676 SCVAL(outbuf,0,NBSSpositive);
679 /* inbuf_size is guaranteed to be at least 4. */
680 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
681 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
682 DEBUG(0,("Invalid name length in session request\n"));
683 reply_called_name_not_present(outbuf);
686 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
687 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
688 DEBUG(0,("Invalid name length in session request\n"));
689 reply_called_name_not_present(outbuf);
693 name_type1 = name_extract((unsigned char *)inbuf,
694 inbuf_size,(unsigned int)4,name1);
695 name_type2 = name_extract((unsigned char *)inbuf,
696 inbuf_size,(unsigned int)(4 + name_len1),name2);
698 if (name_type1 == -1 || name_type2 == -1) {
699 DEBUG(0,("Invalid name type in session request\n"));
700 reply_called_name_not_present(outbuf);
704 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
705 name1, name_type1, name2, name_type2));
707 if (netbios_session_retarget(xconn, name1, name_type1)) {
708 exit_server_cleanly("retargeted client");
712 * Windows NT/2k uses "*SMBSERVER" and XP uses
713 * "*SMBSERV" arrggg!!!
715 if (strequal(name1, "*SMBSERVER ")
716 || strequal(name1, "*SMBSERV ")) {
719 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
722 exit_server_cleanly("could not allocate raddr");
725 fstrcpy(name1, raddr);
728 set_local_machine_name(name1, True);
729 set_remote_machine_name(name2, True);
731 if (is_ipaddress(sconn->remote_hostname)) {
732 char *p = discard_const_p(char, sconn->remote_hostname);
736 sconn->remote_hostname = talloc_strdup(sconn,
737 get_remote_machine_name());
738 if (sconn->remote_hostname == NULL) {
739 exit_server_cleanly("could not copy remote name");
741 xconn->remote_hostname = sconn->remote_hostname;
744 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
745 get_local_machine_name(), get_remote_machine_name(),
748 if (name_type2 == 'R') {
749 /* We are being asked for a pathworks session ---
751 reply_called_name_not_present(outbuf);
755 reload_services(sconn, conn_snum_used, true);
758 xconn->transport.nbt.got_session = true;
762 case 0x89: /* session keepalive request
763 (some old clients produce this?) */
764 SCVAL(outbuf,0,NBSSkeepalive);
768 case NBSSpositive: /* positive session response */
769 case NBSSnegative: /* negative session response */
770 case NBSSretarget: /* retarget session response */
771 DEBUG(0,("Unexpected session response\n"));
774 case NBSSkeepalive: /* session keepalive */
779 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
780 msg_type, msg_flags));
782 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
783 exit_server_cleanly("reply_special: srv_send_smb failed.");
786 if (CVAL(outbuf, 0) != 0x82) {
787 exit_server_cleanly("invalid netbios session");
792 /****************************************************************************
794 conn POINTER CAN BE NULL HERE !
795 ****************************************************************************/
797 void reply_tcon(struct smb_request *req)
799 connection_struct *conn = req->conn;
801 char *service_buf = NULL;
802 char *password = NULL;
808 TALLOC_CTX *ctx = talloc_tos();
809 struct smbXsrv_connection *xconn = req->xconn;
810 NTTIME now = timeval_to_nttime(&req->request_time);
812 START_PROFILE(SMBtcon);
814 if (req->buflen < 4) {
815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
816 END_PROFILE(SMBtcon);
821 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
823 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
825 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
828 if (service_buf == NULL || password == NULL || dev == NULL) {
829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
830 END_PROFILE(SMBtcon);
833 p2 = strrchr_m(service_buf,'\\');
837 service = service_buf;
840 conn = make_connection(req, now, service, dev,
841 req->vuid,&nt_status);
845 reply_nterror(req, nt_status);
846 END_PROFILE(SMBtcon);
850 reply_outbuf(req, 2, 0);
851 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
852 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
853 SSVAL(req->outbuf,smb_tid,conn->cnum);
855 DEBUG(3,("tcon service=%s cnum=%d\n",
856 service, conn->cnum));
858 END_PROFILE(SMBtcon);
862 /****************************************************************************
863 Reply to a tcon and X.
864 conn POINTER CAN BE NULL HERE !
865 ****************************************************************************/
867 void reply_tcon_and_X(struct smb_request *req)
869 connection_struct *conn = req->conn;
870 const char *service = NULL;
871 TALLOC_CTX *ctx = talloc_tos();
872 /* what the client thinks the device is */
873 char *client_devicetype = NULL;
874 /* what the server tells the client the share represents */
875 const char *server_devicetype;
882 struct smbXsrv_session *session = NULL;
883 NTTIME now = timeval_to_nttime(&req->request_time);
884 bool session_key_updated = false;
885 uint16_t optional_support = 0;
886 struct smbXsrv_connection *xconn = req->xconn;
888 START_PROFILE(SMBtconX);
891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
892 END_PROFILE(SMBtconX);
896 passlen = SVAL(req->vwv+3, 0);
897 tcon_flags = SVAL(req->vwv+2, 0);
899 /* we might have to close an old one */
900 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
901 struct smbXsrv_tcon *tcon;
909 * TODO: cancel all outstanding requests on the tcon
911 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
912 if (!NT_STATUS_IS_OK(status)) {
913 DEBUG(0, ("reply_tcon_and_X: "
914 "smbXsrv_tcon_disconnect() failed: %s\n",
917 * If we hit this case, there is something completely
918 * wrong, so we better disconnect the transport connection.
920 END_PROFILE(SMBtconX);
921 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
927 * This tree id is gone. Make sure we can't re-use it
933 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
934 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
935 END_PROFILE(SMBtconX);
939 if (xconn->smb1.negprot.encrypted_passwords) {
940 p = req->buf + passlen;
942 p = req->buf + passlen + 1;
945 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
949 END_PROFILE(SMBtconX);
954 * the service name can be either: \\server\share
955 * or share directly like on the DELL PowerVault 705
958 q = strchr_m(path+2,'\\');
960 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
961 END_PROFILE(SMBtconX);
969 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
970 &client_devicetype, p,
971 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
973 if (client_devicetype == NULL) {
974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
975 END_PROFILE(SMBtconX);
979 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
981 nt_status = smb1srv_session_lookup(xconn,
982 req->vuid, now, &session);
983 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
984 reply_force_doserror(req, ERRSRV, ERRbaduid);
985 END_PROFILE(SMBtconX);
988 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
989 reply_nterror(req, nt_status);
990 END_PROFILE(SMBtconX);
993 if (!NT_STATUS_IS_OK(nt_status)) {
994 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
995 END_PROFILE(SMBtconX);
999 if (session->global->auth_session_info == NULL) {
1000 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1001 END_PROFILE(SMBtconX);
1006 * If there is no application key defined yet
1009 * This means we setup the application key on the
1010 * first tcon that happens via the given session.
1012 * Once the application key is defined, it does not
1015 if (session->global->application_key.length == 0 &&
1016 session->global->signing_key.length > 0)
1018 struct smbXsrv_session *x = session;
1019 struct auth_session_info *session_info =
1020 session->global->auth_session_info;
1021 uint8_t session_key[16];
1023 ZERO_STRUCT(session_key);
1024 memcpy(session_key, x->global->signing_key.data,
1025 MIN(x->global->signing_key.length, sizeof(session_key)));
1028 * The application key is truncated/padded to 16 bytes
1030 x->global->application_key = data_blob_talloc(x->global,
1032 sizeof(session_key));
1033 ZERO_STRUCT(session_key);
1034 if (x->global->application_key.data == NULL) {
1035 reply_nterror(req, NT_STATUS_NO_MEMORY);
1036 END_PROFILE(SMBtconX);
1040 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1041 smb_key_derivation(x->global->application_key.data,
1042 x->global->application_key.length,
1043 x->global->application_key.data);
1044 optional_support |= SMB_EXTENDED_SIGNATURES;
1048 * Place the application key into the session_info
1050 data_blob_clear_free(&session_info->session_key);
1051 session_info->session_key = data_blob_dup_talloc(session_info,
1052 x->global->application_key);
1053 if (session_info->session_key.data == NULL) {
1054 data_blob_clear_free(&x->global->application_key);
1055 reply_nterror(req, NT_STATUS_NO_MEMORY);
1056 END_PROFILE(SMBtconX);
1059 session_key_updated = true;
1062 conn = make_connection(req, now, service, client_devicetype,
1063 req->vuid, &nt_status);
1067 if (session_key_updated) {
1068 struct smbXsrv_session *x = session;
1069 struct auth_session_info *session_info =
1070 session->global->auth_session_info;
1071 data_blob_clear_free(&x->global->application_key);
1072 data_blob_clear_free(&session_info->session_key);
1074 reply_nterror(req, nt_status);
1075 END_PROFILE(SMBtconX);
1080 server_devicetype = "IPC";
1081 else if ( IS_PRINT(conn) )
1082 server_devicetype = "LPT1:";
1084 server_devicetype = "A:";
1086 if (get_Protocol() < PROTOCOL_NT1) {
1087 reply_outbuf(req, 2, 0);
1088 if (message_push_string(&req->outbuf, server_devicetype,
1089 STR_TERMINATE|STR_ASCII) == -1) {
1090 reply_nterror(req, NT_STATUS_NO_MEMORY);
1091 END_PROFILE(SMBtconX);
1095 /* NT sets the fstype of IPC$ to the null string */
1096 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1098 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1099 /* Return permissions. */
1103 reply_outbuf(req, 7, 0);
1106 perm1 = FILE_ALL_ACCESS;
1107 perm2 = FILE_ALL_ACCESS;
1109 perm1 = conn->share_access;
1112 SIVAL(req->outbuf, smb_vwv3, perm1);
1113 SIVAL(req->outbuf, smb_vwv5, perm2);
1115 reply_outbuf(req, 3, 0);
1118 if ((message_push_string(&req->outbuf, server_devicetype,
1119 STR_TERMINATE|STR_ASCII) == -1)
1120 || (message_push_string(&req->outbuf, fstype,
1121 STR_TERMINATE) == -1)) {
1122 reply_nterror(req, NT_STATUS_NO_MEMORY);
1123 END_PROFILE(SMBtconX);
1127 /* what does setting this bit do? It is set by NT4 and
1128 may affect the ability to autorun mounted cdroms */
1129 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1131 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1133 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1134 DEBUG(2,("Serving %s as a Dfs root\n",
1135 lp_servicename(ctx, SNUM(conn)) ));
1136 optional_support |= SMB_SHARE_IN_DFS;
1139 SSVAL(req->outbuf, smb_vwv2, optional_support);
1142 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1143 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1145 DEBUG(3,("tconX service=%s \n",
1148 /* set the incoming and outgoing tid to the just created one */
1149 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1150 SSVAL(req->outbuf,smb_tid,conn->cnum);
1152 END_PROFILE(SMBtconX);
1154 req->tid = conn->cnum;
1157 /****************************************************************************
1158 Reply to an unknown type.
1159 ****************************************************************************/
1161 void reply_unknown_new(struct smb_request *req, uint8_t type)
1163 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1164 smb_fn_name(type), type, type));
1165 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1169 /****************************************************************************
1171 conn POINTER CAN BE NULL HERE !
1172 ****************************************************************************/
1174 void reply_ioctl(struct smb_request *req)
1176 connection_struct *conn = req->conn;
1179 uint32_t ioctl_code;
1183 START_PROFILE(SMBioctl);
1186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1187 END_PROFILE(SMBioctl);
1191 device = SVAL(req->vwv+1, 0);
1192 function = SVAL(req->vwv+2, 0);
1193 ioctl_code = (device << 16) + function;
1195 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1197 switch (ioctl_code) {
1198 case IOCTL_QUERY_JOB_INFO:
1202 reply_force_doserror(req, ERRSRV, ERRnosupport);
1203 END_PROFILE(SMBioctl);
1207 reply_outbuf(req, 8, replysize+1);
1208 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1209 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1210 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1211 p = smb_buf(req->outbuf);
1212 memset(p, '\0', replysize+1); /* valgrind-safe. */
1213 p += 1; /* Allow for alignment */
1215 switch (ioctl_code) {
1216 case IOCTL_QUERY_JOB_INFO:
1220 files_struct *fsp = file_fsp(
1221 req, SVAL(req->vwv+0, 0));
1223 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1224 END_PROFILE(SMBioctl);
1228 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1230 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1231 lp_netbios_name(), 15,
1232 STR_TERMINATE|STR_ASCII, &len);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 reply_nterror(req, status);
1235 END_PROFILE(SMBioctl);
1239 status = srvstr_push((char *)req->outbuf, req->flags2,
1241 lp_servicename(talloc_tos(),
1243 13, STR_TERMINATE|STR_ASCII, &len);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 reply_nterror(req, status);
1246 END_PROFILE(SMBioctl);
1250 memset(p+18, 0, 13);
1256 END_PROFILE(SMBioctl);
1260 /****************************************************************************
1261 Strange checkpath NTSTATUS mapping.
1262 ****************************************************************************/
1264 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1266 /* Strange DOS error code semantics only for checkpath... */
1267 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1268 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1269 /* We need to map to ERRbadpath */
1270 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1276 /****************************************************************************
1277 Reply to a checkpath.
1278 ****************************************************************************/
1280 void reply_checkpath(struct smb_request *req)
1282 connection_struct *conn = req->conn;
1283 struct smb_filename *smb_fname = NULL;
1286 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1287 TALLOC_CTX *ctx = talloc_tos();
1289 START_PROFILE(SMBcheckpath);
1291 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1292 STR_TERMINATE, &status);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 status = map_checkpath_error(req->flags2, status);
1296 reply_nterror(req, status);
1297 END_PROFILE(SMBcheckpath);
1301 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1303 status = filename_convert(ctx,
1311 if (!NT_STATUS_IS_OK(status)) {
1312 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1313 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1314 ERRSRV, ERRbadpath);
1315 END_PROFILE(SMBcheckpath);
1321 if (!VALID_STAT(smb_fname->st) &&
1322 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1323 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1324 smb_fname_str_dbg(smb_fname), strerror(errno)));
1325 status = map_nt_error_from_unix(errno);
1329 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1330 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1331 ERRDOS, ERRbadpath);
1335 reply_outbuf(req, 0, 0);
1338 /* We special case this - as when a Windows machine
1339 is parsing a path is steps through the components
1340 one at a time - if a component fails it expects
1341 ERRbadpath, not ERRbadfile.
1343 status = map_checkpath_error(req->flags2, status);
1344 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1346 * Windows returns different error codes if
1347 * the parent directory is valid but not the
1348 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1349 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1350 * if the path is invalid.
1352 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1353 ERRDOS, ERRbadpath);
1357 reply_nterror(req, status);
1360 TALLOC_FREE(smb_fname);
1361 END_PROFILE(SMBcheckpath);
1365 /****************************************************************************
1367 ****************************************************************************/
1369 void reply_getatr(struct smb_request *req)
1371 connection_struct *conn = req->conn;
1372 struct smb_filename *smb_fname = NULL;
1379 TALLOC_CTX *ctx = talloc_tos();
1380 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1382 START_PROFILE(SMBgetatr);
1384 p = (const char *)req->buf + 1;
1385 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1386 if (!NT_STATUS_IS_OK(status)) {
1387 reply_nterror(req, status);
1391 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1392 under WfWg - weird! */
1393 if (*fname == '\0') {
1394 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1395 if (!CAN_WRITE(conn)) {
1396 mode |= FILE_ATTRIBUTE_READONLY;
1401 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1402 status = filename_convert(ctx,
1409 if (!NT_STATUS_IS_OK(status)) {
1410 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1411 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1412 ERRSRV, ERRbadpath);
1415 reply_nterror(req, status);
1418 if (!VALID_STAT(smb_fname->st) &&
1419 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1420 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1421 smb_fname_str_dbg(smb_fname),
1423 reply_nterror(req, map_nt_error_from_unix(errno));
1427 mode = dos_mode(conn, smb_fname);
1428 size = smb_fname->st.st_ex_size;
1430 if (ask_sharemode) {
1431 struct timespec write_time_ts;
1432 struct file_id fileid;
1434 ZERO_STRUCT(write_time_ts);
1435 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1436 get_file_infos(fileid, 0, NULL, &write_time_ts);
1437 if (!null_timespec(write_time_ts)) {
1438 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1442 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1443 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1448 reply_outbuf(req, 10, 0);
1450 SSVAL(req->outbuf,smb_vwv0,mode);
1451 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1452 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1454 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1456 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1458 if (get_Protocol() >= PROTOCOL_NT1) {
1459 SSVAL(req->outbuf, smb_flg2,
1460 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1463 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1464 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1467 TALLOC_FREE(smb_fname);
1469 END_PROFILE(SMBgetatr);
1473 /****************************************************************************
1475 ****************************************************************************/
1477 void reply_setatr(struct smb_request *req)
1479 struct smb_file_time ft;
1480 connection_struct *conn = req->conn;
1481 struct smb_filename *smb_fname = NULL;
1487 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1488 TALLOC_CTX *ctx = talloc_tos();
1490 START_PROFILE(SMBsetatr);
1495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1499 p = (const char *)req->buf + 1;
1500 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1501 if (!NT_STATUS_IS_OK(status)) {
1502 reply_nterror(req, status);
1506 status = filename_convert(ctx,
1513 if (!NT_STATUS_IS_OK(status)) {
1514 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1515 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1516 ERRSRV, ERRbadpath);
1519 reply_nterror(req, status);
1523 if (smb_fname->base_name[0] == '.' &&
1524 smb_fname->base_name[1] == '\0') {
1526 * Not sure here is the right place to catch this
1527 * condition. Might be moved to somewhere else later -- vl
1529 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1533 mode = SVAL(req->vwv+0, 0);
1534 mtime = srv_make_unix_date3(req->vwv+1);
1536 if (mode != FILE_ATTRIBUTE_NORMAL) {
1537 if (VALID_STAT_OF_DIR(smb_fname->st))
1538 mode |= FILE_ATTRIBUTE_DIRECTORY;
1540 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1542 status = check_access(conn, NULL, smb_fname,
1543 FILE_WRITE_ATTRIBUTES);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 reply_nterror(req, status);
1549 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1551 reply_nterror(req, map_nt_error_from_unix(errno));
1556 ft.mtime = convert_time_t_to_timespec(mtime);
1557 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1558 if (!NT_STATUS_IS_OK(status)) {
1559 reply_nterror(req, status);
1563 reply_outbuf(req, 0, 0);
1565 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1568 TALLOC_FREE(smb_fname);
1569 END_PROFILE(SMBsetatr);
1573 /****************************************************************************
1575 ****************************************************************************/
1577 void reply_dskattr(struct smb_request *req)
1579 connection_struct *conn = req->conn;
1581 uint64_t dfree,dsize,bsize;
1582 struct smb_filename smb_fname;
1583 START_PROFILE(SMBdskattr);
1585 ZERO_STRUCT(smb_fname);
1586 smb_fname.base_name = discard_const_p(char, ".");
1588 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1589 reply_nterror(req, map_nt_error_from_unix(errno));
1590 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1591 END_PROFILE(SMBdskattr);
1595 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1596 if (ret == (uint64_t)-1) {
1597 reply_nterror(req, map_nt_error_from_unix(errno));
1598 END_PROFILE(SMBdskattr);
1603 * Force max to fit in 16 bit fields.
1605 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1609 if (bsize > (WORDMAX*512)) {
1610 bsize = (WORDMAX*512);
1611 if (dsize > WORDMAX)
1613 if (dfree > WORDMAX)
1619 reply_outbuf(req, 5, 0);
1621 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1622 double total_space, free_space;
1623 /* we need to scale this to a number that DOS6 can handle. We
1624 use floating point so we can handle large drives on systems
1625 that don't have 64 bit integers
1627 we end up displaying a maximum of 2G to DOS systems
1629 total_space = dsize * (double)bsize;
1630 free_space = dfree * (double)bsize;
1632 dsize = (uint64_t)((total_space+63*512) / (64*512));
1633 dfree = (uint64_t)((free_space+63*512) / (64*512));
1635 if (dsize > 0xFFFF) dsize = 0xFFFF;
1636 if (dfree > 0xFFFF) dfree = 0xFFFF;
1638 SSVAL(req->outbuf,smb_vwv0,dsize);
1639 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1640 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1641 SSVAL(req->outbuf,smb_vwv3,dfree);
1643 SSVAL(req->outbuf,smb_vwv0,dsize);
1644 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1645 SSVAL(req->outbuf,smb_vwv2,512);
1646 SSVAL(req->outbuf,smb_vwv3,dfree);
1649 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1651 END_PROFILE(SMBdskattr);
1656 * Utility function to split the filename from the directory.
1658 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1659 char **fname_dir_out,
1660 char **fname_mask_out)
1662 const char *p = NULL;
1663 char *fname_dir = NULL;
1664 char *fname_mask = NULL;
1666 p = strrchr_m(fname_in, '/');
1668 fname_dir = talloc_strdup(ctx, ".");
1669 fname_mask = talloc_strdup(ctx, fname_in);
1671 fname_dir = talloc_strndup(ctx, fname_in,
1672 PTR_DIFF(p, fname_in));
1673 fname_mask = talloc_strdup(ctx, p+1);
1676 if (!fname_dir || !fname_mask) {
1677 TALLOC_FREE(fname_dir);
1678 TALLOC_FREE(fname_mask);
1679 return NT_STATUS_NO_MEMORY;
1682 *fname_dir_out = fname_dir;
1683 *fname_mask_out = fname_mask;
1684 return NT_STATUS_OK;
1687 /****************************************************************************
1689 ****************************************************************************/
1691 static bool make_dir_struct(TALLOC_CTX *ctx,
1701 char *mask2 = talloc_strdup(ctx, mask);
1707 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1711 memset(buf+1,' ',11);
1712 if ((p = strchr_m(mask2,'.')) != NULL) {
1714 push_ascii(buf+1,mask2,8, 0);
1715 push_ascii(buf+9,p+1,3, 0);
1718 push_ascii(buf+1,mask2,11, 0);
1721 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1723 srv_put_dos_date(buf,22,date);
1724 SSVAL(buf,26,size & 0xFFFF);
1725 SSVAL(buf,28,(size >> 16)&0xFFFF);
1726 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1727 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1728 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1729 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1733 /****************************************************************************
1735 Can be called from SMBsearch, SMBffirst or SMBfunique.
1736 ****************************************************************************/
1738 void reply_search(struct smb_request *req)
1740 connection_struct *conn = req->conn;
1743 char *directory = NULL;
1744 struct smb_filename *smb_fname = NULL;
1748 struct timespec date;
1750 unsigned int numentries = 0;
1751 unsigned int maxentries = 0;
1752 bool finished = False;
1757 bool check_descend = False;
1758 bool expect_close = False;
1760 bool mask_contains_wcard = False;
1761 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1762 TALLOC_CTX *ctx = talloc_tos();
1763 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1764 struct dptr_struct *dirptr = NULL;
1765 struct smbXsrv_connection *xconn = req->xconn;
1766 struct smbd_server_connection *sconn = req->sconn;
1768 START_PROFILE(SMBsearch);
1771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1775 if (req->posix_pathnames) {
1776 reply_unknown_new(req, req->cmd);
1780 /* If we were called as SMBffirst then we must expect close. */
1781 if(req->cmd == SMBffirst) {
1782 expect_close = True;
1785 reply_outbuf(req, 1, 3);
1786 maxentries = SVAL(req->vwv+0, 0);
1787 dirtype = SVAL(req->vwv+1, 0);
1788 p = (const char *)req->buf + 1;
1789 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1790 &nt_status, &mask_contains_wcard);
1791 if (!NT_STATUS_IS_OK(nt_status)) {
1792 reply_nterror(req, nt_status);
1797 status_len = SVAL(p, 0);
1800 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1802 if (status_len == 0) {
1803 struct smb_filename *smb_dname = NULL;
1804 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1805 ucf_flags_from_smb_request(req);
1806 nt_status = filename_convert(ctx, conn,
1810 &mask_contains_wcard,
1812 if (!NT_STATUS_IS_OK(nt_status)) {
1813 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1814 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1815 ERRSRV, ERRbadpath);
1818 reply_nterror(req, nt_status);
1822 directory = smb_fname->base_name;
1824 p = strrchr_m(directory,'/');
1825 if ((p != NULL) && (*directory != '/')) {
1826 mask = talloc_strdup(ctx, p + 1);
1827 directory = talloc_strndup(ctx, directory,
1828 PTR_DIFF(p, directory));
1830 mask = talloc_strdup(ctx, directory);
1831 directory = talloc_strdup(ctx,".");
1835 reply_nterror(req, NT_STATUS_NO_MEMORY);
1839 memset((char *)status,'\0',21);
1840 SCVAL(status,0,(dirtype & 0x1F));
1842 smb_dname = synthetic_smb_fname(talloc_tos(),
1847 if (smb_dname == NULL) {
1848 reply_nterror(req, NT_STATUS_NO_MEMORY);
1852 nt_status = dptr_create(conn,
1860 mask_contains_wcard,
1864 TALLOC_FREE(smb_dname);
1866 if (!NT_STATUS_IS_OK(nt_status)) {
1867 reply_nterror(req, nt_status);
1870 dptr_num = dptr_dnum(dirptr);
1873 const char *dirpath;
1875 memcpy(status,p,21);
1876 status_dirtype = CVAL(status,0) & 0x1F;
1877 if (status_dirtype != (dirtype & 0x1F)) {
1878 dirtype = status_dirtype;
1881 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1885 dirpath = dptr_path(sconn, dptr_num);
1886 directory = talloc_strdup(ctx, dirpath);
1888 reply_nterror(req, NT_STATUS_NO_MEMORY);
1892 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1897 * For a 'continue' search we have no string. So
1898 * check from the initial saved string.
1900 if (!req->posix_pathnames) {
1901 mask_contains_wcard = ms_has_wild(mask);
1903 dirtype = dptr_attr(sconn, dptr_num);
1906 DEBUG(4,("dptr_num is %d\n",dptr_num));
1908 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1909 char buf[DIR_STRUCT_SIZE];
1910 memcpy(buf,status,21);
1911 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1912 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1913 reply_nterror(req, NT_STATUS_NO_MEMORY);
1916 dptr_fill(sconn, buf+12,dptr_num);
1917 if (dptr_zero(buf+12) && (status_len==0)) {
1922 if (message_push_blob(&req->outbuf,
1923 data_blob_const(buf, sizeof(buf)))
1925 reply_nterror(req, NT_STATUS_NO_MEMORY);
1930 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1931 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1933 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1935 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1936 directory,lp_dont_descend(ctx, SNUM(conn))));
1937 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1938 check_descend = True;
1941 for (i=numentries;(i<maxentries) && !finished;i++) {
1942 finished = !get_dir_entry(ctx,
1953 char buf[DIR_STRUCT_SIZE];
1954 memcpy(buf,status,21);
1955 if (!make_dir_struct(ctx,
1961 convert_timespec_to_time_t(date),
1962 !allow_long_path_components)) {
1963 reply_nterror(req, NT_STATUS_NO_MEMORY);
1966 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1969 if (message_push_blob(&req->outbuf,
1970 data_blob_const(buf, sizeof(buf)))
1972 reply_nterror(req, NT_STATUS_NO_MEMORY);
1982 /* If we were called as SMBffirst with smb_search_id == NULL
1983 and no entries were found then return error and close dirptr
1986 if (numentries == 0) {
1987 dptr_close(sconn, &dptr_num);
1988 } else if(expect_close && status_len == 0) {
1989 /* Close the dptr - we know it's gone */
1990 dptr_close(sconn, &dptr_num);
1993 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1994 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1995 dptr_close(sconn, &dptr_num);
1998 if ((numentries == 0) && !mask_contains_wcard) {
1999 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2003 SSVAL(req->outbuf,smb_vwv0,numentries);
2004 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2005 SCVAL(smb_buf(req->outbuf),0,5);
2006 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2008 /* The replies here are never long name. */
2009 SSVAL(req->outbuf, smb_flg2,
2010 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2011 if (!allow_long_path_components) {
2012 SSVAL(req->outbuf, smb_flg2,
2013 SVAL(req->outbuf, smb_flg2)
2014 & (~FLAGS2_LONG_PATH_COMPONENTS));
2017 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2018 SSVAL(req->outbuf, smb_flg2,
2019 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2021 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2022 smb_fn_name(req->cmd),
2029 TALLOC_FREE(directory);
2031 TALLOC_FREE(smb_fname);
2032 END_PROFILE(SMBsearch);
2036 /****************************************************************************
2037 Reply to a fclose (stop directory search).
2038 ****************************************************************************/
2040 void reply_fclose(struct smb_request *req)
2048 bool path_contains_wcard = False;
2049 TALLOC_CTX *ctx = talloc_tos();
2050 struct smbd_server_connection *sconn = req->sconn;
2052 START_PROFILE(SMBfclose);
2054 if (req->posix_pathnames) {
2055 reply_unknown_new(req, req->cmd);
2056 END_PROFILE(SMBfclose);
2060 p = (const char *)req->buf + 1;
2061 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2062 &err, &path_contains_wcard);
2063 if (!NT_STATUS_IS_OK(err)) {
2064 reply_nterror(req, err);
2065 END_PROFILE(SMBfclose);
2069 status_len = SVAL(p,0);
2072 if (status_len == 0) {
2073 reply_force_doserror(req, ERRSRV, ERRsrverror);
2074 END_PROFILE(SMBfclose);
2078 memcpy(status,p,21);
2080 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2081 /* Close the dptr - we know it's gone */
2082 dptr_close(sconn, &dptr_num);
2085 reply_outbuf(req, 1, 0);
2086 SSVAL(req->outbuf,smb_vwv0,0);
2088 DEBUG(3,("search close\n"));
2090 END_PROFILE(SMBfclose);
2094 /****************************************************************************
2096 ****************************************************************************/
2098 void reply_open(struct smb_request *req)
2100 connection_struct *conn = req->conn;
2101 struct smb_filename *smb_fname = NULL;
2111 uint32_t access_mask;
2112 uint32_t share_mode;
2113 uint32_t create_disposition;
2114 uint32_t create_options = 0;
2115 uint32_t private_flags = 0;
2118 TALLOC_CTX *ctx = talloc_tos();
2120 START_PROFILE(SMBopen);
2123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2127 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2128 deny_mode = SVAL(req->vwv+0, 0);
2129 dos_attr = SVAL(req->vwv+1, 0);
2131 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2132 STR_TERMINATE, &status);
2133 if (!NT_STATUS_IS_OK(status)) {
2134 reply_nterror(req, status);
2138 if (!map_open_params_to_ntcreate(fname, deny_mode,
2139 OPENX_FILE_EXISTS_OPEN, &access_mask,
2140 &share_mode, &create_disposition,
2141 &create_options, &private_flags)) {
2142 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2146 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2148 status = filename_convert(ctx,
2155 if (!NT_STATUS_IS_OK(status)) {
2156 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2157 reply_botherror(req,
2158 NT_STATUS_PATH_NOT_COVERED,
2159 ERRSRV, ERRbadpath);
2162 reply_nterror(req, status);
2166 status = SMB_VFS_CREATE_FILE(
2169 0, /* root_dir_fid */
2170 smb_fname, /* fname */
2171 access_mask, /* access_mask */
2172 share_mode, /* share_access */
2173 create_disposition, /* create_disposition*/
2174 create_options, /* create_options */
2175 dos_attr, /* file_attributes */
2176 oplock_request, /* oplock_request */
2178 0, /* allocation_size */
2184 NULL, NULL); /* create context */
2186 if (!NT_STATUS_IS_OK(status)) {
2187 if (open_was_deferred(req->xconn, req->mid)) {
2188 /* We have re-scheduled this call. */
2191 reply_openerror(req, status);
2195 /* Ensure we're pointing at the correct stat struct. */
2196 TALLOC_FREE(smb_fname);
2197 smb_fname = fsp->fsp_name;
2199 size = smb_fname->st.st_ex_size;
2200 fattr = dos_mode(conn, smb_fname);
2202 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2204 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2205 DEBUG(3,("attempt to open a directory %s\n",
2207 close_file(req, fsp, ERROR_CLOSE);
2208 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2209 ERRDOS, ERRnoaccess);
2213 reply_outbuf(req, 7, 0);
2214 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2215 SSVAL(req->outbuf,smb_vwv1,fattr);
2216 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2217 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2219 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2221 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2222 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2224 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2225 SCVAL(req->outbuf,smb_flg,
2226 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2229 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2230 SCVAL(req->outbuf,smb_flg,
2231 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2234 END_PROFILE(SMBopen);
2238 /****************************************************************************
2239 Reply to an open and X.
2240 ****************************************************************************/
2242 void reply_open_and_X(struct smb_request *req)
2244 connection_struct *conn = req->conn;
2245 struct smb_filename *smb_fname = NULL;
2247 uint16_t open_flags;
2250 /* Breakout the oplock request bits so we can set the
2251 reply bits separately. */
2252 int ex_oplock_request;
2253 int core_oplock_request;
2256 int smb_sattr = SVAL(req->vwv+4, 0);
2257 uint32_t smb_time = make_unix_date3(req->vwv+6);
2265 uint64_t allocation_size;
2266 ssize_t retval = -1;
2267 uint32_t access_mask;
2268 uint32_t share_mode;
2269 uint32_t create_disposition;
2270 uint32_t create_options = 0;
2271 uint32_t private_flags = 0;
2273 TALLOC_CTX *ctx = talloc_tos();
2275 START_PROFILE(SMBopenX);
2277 if (req->wct < 15) {
2278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2282 open_flags = SVAL(req->vwv+2, 0);
2283 deny_mode = SVAL(req->vwv+3, 0);
2284 smb_attr = SVAL(req->vwv+5, 0);
2285 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2286 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2287 oplock_request = ex_oplock_request | core_oplock_request;
2288 smb_ofun = SVAL(req->vwv+8, 0);
2289 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2291 /* If it's an IPC, pass off the pipe handler. */
2293 if (lp_nt_pipe_support()) {
2294 reply_open_pipe_and_X(conn, req);
2296 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2301 /* XXXX we need to handle passed times, sattr and flags */
2302 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2303 STR_TERMINATE, &status);
2304 if (!NT_STATUS_IS_OK(status)) {
2305 reply_nterror(req, status);
2309 if (!map_open_params_to_ntcreate(fname, deny_mode,
2311 &access_mask, &share_mode,
2312 &create_disposition,
2315 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2319 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2321 status = filename_convert(ctx,
2328 if (!NT_STATUS_IS_OK(status)) {
2329 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2330 reply_botherror(req,
2331 NT_STATUS_PATH_NOT_COVERED,
2332 ERRSRV, ERRbadpath);
2335 reply_nterror(req, status);
2339 status = SMB_VFS_CREATE_FILE(
2342 0, /* root_dir_fid */
2343 smb_fname, /* fname */
2344 access_mask, /* access_mask */
2345 share_mode, /* share_access */
2346 create_disposition, /* create_disposition*/
2347 create_options, /* create_options */
2348 smb_attr, /* file_attributes */
2349 oplock_request, /* oplock_request */
2351 0, /* allocation_size */
2356 &smb_action, /* pinfo */
2357 NULL, NULL); /* create context */
2359 if (!NT_STATUS_IS_OK(status)) {
2360 if (open_was_deferred(req->xconn, req->mid)) {
2361 /* We have re-scheduled this call. */
2364 reply_openerror(req, status);
2368 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2369 if the file is truncated or created. */
2370 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2371 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2372 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2373 close_file(req, fsp, ERROR_CLOSE);
2374 reply_nterror(req, NT_STATUS_DISK_FULL);
2377 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2379 close_file(req, fsp, ERROR_CLOSE);
2380 reply_nterror(req, NT_STATUS_DISK_FULL);
2383 status = vfs_stat_fsp(fsp);
2384 if (!NT_STATUS_IS_OK(status)) {
2385 close_file(req, fsp, ERROR_CLOSE);
2386 reply_nterror(req, status);
2391 fattr = dos_mode(conn, fsp->fsp_name);
2392 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2393 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2394 close_file(req, fsp, ERROR_CLOSE);
2395 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2399 /* If the caller set the extended oplock request bit
2400 and we granted one (by whatever means) - set the
2401 correct bit for extended oplock reply.
2404 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2405 smb_action |= EXTENDED_OPLOCK_GRANTED;
2408 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2409 smb_action |= EXTENDED_OPLOCK_GRANTED;
2412 /* If the caller set the core oplock request bit
2413 and we granted one (by whatever means) - set the
2414 correct bit for core oplock reply.
2417 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2418 reply_outbuf(req, 19, 0);
2420 reply_outbuf(req, 15, 0);
2423 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2424 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2426 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2427 SCVAL(req->outbuf, smb_flg,
2428 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2431 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2432 SCVAL(req->outbuf, smb_flg,
2433 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2436 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2437 SSVAL(req->outbuf,smb_vwv3,fattr);
2438 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2439 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2441 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2443 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2444 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2445 SSVAL(req->outbuf,smb_vwv11,smb_action);
2447 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2448 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2452 TALLOC_FREE(smb_fname);
2453 END_PROFILE(SMBopenX);
2457 /****************************************************************************
2458 Reply to a SMBulogoffX.
2459 ****************************************************************************/
2461 void reply_ulogoffX(struct smb_request *req)
2463 struct smbd_server_connection *sconn = req->sconn;
2464 struct user_struct *vuser;
2465 struct smbXsrv_session *session = NULL;
2468 START_PROFILE(SMBulogoffX);
2470 vuser = get_valid_user_struct(sconn, req->vuid);
2473 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2474 (unsigned long long)req->vuid));
2476 req->vuid = UID_FIELD_INVALID;
2477 reply_force_doserror(req, ERRSRV, ERRbaduid);
2478 END_PROFILE(SMBulogoffX);
2482 session = vuser->session;
2486 * TODO: cancel all outstanding requests on the session
2488 status = smbXsrv_session_logoff(session);
2489 if (!NT_STATUS_IS_OK(status)) {
2490 DEBUG(0, ("reply_ulogoff: "
2491 "smbXsrv_session_logoff() failed: %s\n",
2492 nt_errstr(status)));
2494 * If we hit this case, there is something completely
2495 * wrong, so we better disconnect the transport connection.
2497 END_PROFILE(SMBulogoffX);
2498 exit_server(__location__ ": smbXsrv_session_logoff failed");
2502 TALLOC_FREE(session);
2504 reply_outbuf(req, 2, 0);
2505 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2506 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2508 DEBUG(3, ("ulogoffX vuid=%llu\n",
2509 (unsigned long long)req->vuid));
2511 END_PROFILE(SMBulogoffX);
2512 req->vuid = UID_FIELD_INVALID;
2515 /****************************************************************************
2516 Reply to a mknew or a create.
2517 ****************************************************************************/
2519 void reply_mknew(struct smb_request *req)
2521 connection_struct *conn = req->conn;
2522 struct smb_filename *smb_fname = NULL;
2525 struct smb_file_time ft;
2527 int oplock_request = 0;
2529 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2530 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2531 uint32_t create_disposition;
2532 uint32_t create_options = 0;
2534 TALLOC_CTX *ctx = talloc_tos();
2536 START_PROFILE(SMBcreate);
2540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2544 fattr = SVAL(req->vwv+0, 0);
2545 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2547 if (req->cmd == SMBmknew) {
2548 /* We should fail if file exists. */
2549 create_disposition = FILE_CREATE;
2551 /* Create if file doesn't exist, truncate if it does. */
2552 create_disposition = FILE_OVERWRITE_IF;
2556 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2558 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2559 STR_TERMINATE, &status);
2560 if (!NT_STATUS_IS_OK(status)) {
2561 reply_nterror(req, status);
2565 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2566 status = filename_convert(ctx,
2573 if (!NT_STATUS_IS_OK(status)) {
2574 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2575 reply_botherror(req,
2576 NT_STATUS_PATH_NOT_COVERED,
2577 ERRSRV, ERRbadpath);
2580 reply_nterror(req, status);
2584 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2585 DEBUG(0,("Attempt to create file (%s) with volid set - "
2586 "please report this\n",
2587 smb_fname_str_dbg(smb_fname)));
2590 status = SMB_VFS_CREATE_FILE(
2593 0, /* root_dir_fid */
2594 smb_fname, /* fname */
2595 access_mask, /* access_mask */
2596 share_mode, /* share_access */
2597 create_disposition, /* create_disposition*/
2598 create_options, /* create_options */
2599 fattr, /* file_attributes */
2600 oplock_request, /* oplock_request */
2602 0, /* allocation_size */
2603 0, /* private_flags */
2608 NULL, NULL); /* create context */
2610 if (!NT_STATUS_IS_OK(status)) {
2611 if (open_was_deferred(req->xconn, req->mid)) {
2612 /* We have re-scheduled this call. */
2615 reply_openerror(req, status);
2619 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2620 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2621 if (!NT_STATUS_IS_OK(status)) {
2622 END_PROFILE(SMBcreate);
2626 reply_outbuf(req, 1, 0);
2627 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2629 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2630 SCVAL(req->outbuf,smb_flg,
2631 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2634 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2635 SCVAL(req->outbuf,smb_flg,
2636 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2639 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2640 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2641 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2642 (unsigned int)fattr));
2645 TALLOC_FREE(smb_fname);
2646 END_PROFILE(SMBcreate);
2650 /****************************************************************************
2651 Reply to a create temporary file.
2652 ****************************************************************************/
2654 void reply_ctemp(struct smb_request *req)
2656 connection_struct *conn = req->conn;
2657 struct smb_filename *smb_fname = NULL;
2658 char *wire_name = NULL;
2667 TALLOC_CTX *ctx = talloc_tos();
2669 START_PROFILE(SMBctemp);
2672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2676 fattr = SVAL(req->vwv+0, 0);
2677 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2679 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2680 STR_TERMINATE, &status);
2681 if (!NT_STATUS_IS_OK(status)) {
2682 reply_nterror(req, status);
2686 for (i = 0; i < 10; i++) {
2688 fname = talloc_asprintf(ctx,
2691 generate_random_str_list(ctx, 5, "0123456789"));
2693 fname = talloc_asprintf(ctx,
2695 generate_random_str_list(ctx, 5, "0123456789"));
2699 reply_nterror(req, NT_STATUS_NO_MEMORY);
2703 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2704 status = filename_convert(ctx, conn,
2710 if (!NT_STATUS_IS_OK(status)) {
2711 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2712 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2713 ERRSRV, ERRbadpath);
2716 reply_nterror(req, status);
2720 /* Create the file. */
2721 status = SMB_VFS_CREATE_FILE(
2724 0, /* root_dir_fid */
2725 smb_fname, /* fname */
2726 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2727 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2728 FILE_CREATE, /* create_disposition*/
2729 0, /* create_options */
2730 fattr, /* file_attributes */
2731 oplock_request, /* oplock_request */
2733 0, /* allocation_size */
2734 0, /* private_flags */
2739 NULL, NULL); /* create context */
2741 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2743 TALLOC_FREE(smb_fname);
2747 if (!NT_STATUS_IS_OK(status)) {
2748 if (open_was_deferred(req->xconn, req->mid)) {
2749 /* We have re-scheduled this call. */
2752 reply_openerror(req, status);
2760 /* Collision after 10 times... */
2761 reply_nterror(req, status);
2765 reply_outbuf(req, 1, 0);
2766 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2768 /* the returned filename is relative to the directory */
2769 s = strrchr_m(fsp->fsp_name->base_name, '/');
2771 s = fsp->fsp_name->base_name;
2777 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2778 thing in the byte section. JRA */
2779 SSVALS(p, 0, -1); /* what is this? not in spec */
2781 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2783 reply_nterror(req, NT_STATUS_NO_MEMORY);
2787 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2788 SCVAL(req->outbuf, smb_flg,
2789 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2792 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2793 SCVAL(req->outbuf, smb_flg,
2794 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2797 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2798 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2799 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2801 TALLOC_FREE(smb_fname);
2802 TALLOC_FREE(wire_name);
2803 END_PROFILE(SMBctemp);
2807 /*******************************************************************
2808 Check if a user is allowed to rename a file.
2809 ********************************************************************/
2811 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2814 if (!CAN_WRITE(conn)) {
2815 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2818 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2819 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2820 /* Only bother to read the DOS attribute if we might deny the
2821 rename on the grounds of attribute mismatch. */
2822 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2823 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2824 return NT_STATUS_NO_SUCH_FILE;
2828 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2829 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2830 return NT_STATUS_OK;
2833 /* If no pathnames are open below this
2834 directory, allow the rename. */
2836 if (lp_strict_rename(SNUM(conn))) {
2838 * Strict rename, check open file db.
2840 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2841 return NT_STATUS_ACCESS_DENIED;
2843 } else if (file_find_subpath(fsp)) {
2845 * No strict rename, just look in local process.
2847 return NT_STATUS_ACCESS_DENIED;
2849 return NT_STATUS_OK;
2852 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2853 return NT_STATUS_OK;
2856 return NT_STATUS_ACCESS_DENIED;
2859 /*******************************************************************
2860 * unlink a file with all relevant access checks
2861 *******************************************************************/
2863 static NTSTATUS do_unlink(connection_struct *conn,
2864 struct smb_request *req,
2865 struct smb_filename *smb_fname,
2870 uint32_t dirtype_orig = dirtype;
2873 bool posix_paths = (req != NULL && req->posix_pathnames);
2875 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2876 smb_fname_str_dbg(smb_fname),
2879 if (!CAN_WRITE(conn)) {
2880 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2884 ret = SMB_VFS_LSTAT(conn, smb_fname);
2886 ret = SMB_VFS_STAT(conn, smb_fname);
2889 return map_nt_error_from_unix(errno);
2892 fattr = dos_mode(conn, smb_fname);
2894 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2895 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2898 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2900 return NT_STATUS_NO_SUCH_FILE;
2903 if (!dir_check_ftype(fattr, dirtype)) {
2904 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2905 return NT_STATUS_FILE_IS_A_DIRECTORY;
2907 return NT_STATUS_NO_SUCH_FILE;
2910 if (dirtype_orig & 0x8000) {
2911 /* These will never be set for POSIX. */
2912 return NT_STATUS_NO_SUCH_FILE;
2916 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2917 return NT_STATUS_FILE_IS_A_DIRECTORY;
2920 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2921 return NT_STATUS_NO_SUCH_FILE;
2924 if (dirtype & 0xFF00) {
2925 /* These will never be set for POSIX. */
2926 return NT_STATUS_NO_SUCH_FILE;
2931 return NT_STATUS_NO_SUCH_FILE;
2934 /* Can't delete a directory. */
2935 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2936 return NT_STATUS_FILE_IS_A_DIRECTORY;
2941 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2942 return NT_STATUS_OBJECT_NAME_INVALID;
2943 #endif /* JRATEST */
2945 /* On open checks the open itself will check the share mode, so
2946 don't do it here as we'll get it wrong. */
2948 status = SMB_VFS_CREATE_FILE
2951 0, /* root_dir_fid */
2952 smb_fname, /* fname */
2953 DELETE_ACCESS, /* access_mask */
2954 FILE_SHARE_NONE, /* share_access */
2955 FILE_OPEN, /* create_disposition*/
2956 FILE_NON_DIRECTORY_FILE, /* create_options */
2957 /* file_attributes */
2958 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2959 FILE_ATTRIBUTE_NORMAL,
2960 0, /* oplock_request */
2962 0, /* allocation_size */
2963 0, /* private_flags */
2968 NULL, NULL); /* create context */
2970 if (!NT_STATUS_IS_OK(status)) {
2971 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2972 nt_errstr(status)));
2976 status = can_set_delete_on_close(fsp, fattr);
2977 if (!NT_STATUS_IS_OK(status)) {
2978 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2980 smb_fname_str_dbg(smb_fname),
2981 nt_errstr(status)));
2982 close_file(req, fsp, NORMAL_CLOSE);
2986 /* The set is across all open files on this dev/inode pair. */
2987 if (!set_delete_on_close(fsp, True,
2988 conn->session_info->security_token,
2989 conn->session_info->unix_token)) {
2990 close_file(req, fsp, NORMAL_CLOSE);
2991 return NT_STATUS_ACCESS_DENIED;
2994 return close_file(req, fsp, NORMAL_CLOSE);
2997 /****************************************************************************
2998 The guts of the unlink command, split out so it may be called by the NT SMB
3000 ****************************************************************************/
3002 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3003 uint32_t dirtype, struct smb_filename *smb_fname,
3006 char *fname_dir = NULL;
3007 char *fname_mask = NULL;
3009 NTSTATUS status = NT_STATUS_OK;
3010 struct smb_filename *smb_fname_dir = NULL;
3011 TALLOC_CTX *ctx = talloc_tos();
3013 /* Split up the directory from the filename/mask. */
3014 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3015 &fname_dir, &fname_mask);
3016 if (!NT_STATUS_IS_OK(status)) {
3021 * We should only check the mangled cache
3022 * here if unix_convert failed. This means
3023 * that the path in 'mask' doesn't exist
3024 * on the file system and so we need to look
3025 * for a possible mangle. This patch from
3026 * Tine Smukavec <valentin.smukavec@hermes.si>.
3029 if (!VALID_STAT(smb_fname->st) &&
3030 mangle_is_mangled(fname_mask, conn->params)) {
3031 char *new_mask = NULL;
3032 mangle_lookup_name_from_8_3(ctx, fname_mask,
3033 &new_mask, conn->params);
3035 TALLOC_FREE(fname_mask);
3036 fname_mask = new_mask;
3043 * Only one file needs to be unlinked. Append the mask back
3044 * onto the directory.
3046 TALLOC_FREE(smb_fname->base_name);
3047 if (ISDOT(fname_dir)) {
3048 /* Ensure we use canonical names on open. */
3049 smb_fname->base_name = talloc_asprintf(smb_fname,
3053 smb_fname->base_name = talloc_asprintf(smb_fname,
3058 if (!smb_fname->base_name) {
3059 status = NT_STATUS_NO_MEMORY;
3063 dirtype = FILE_ATTRIBUTE_NORMAL;
3066 status = check_name(conn, smb_fname);
3067 if (!NT_STATUS_IS_OK(status)) {
3071 status = do_unlink(conn, req, smb_fname, dirtype);
3072 if (!NT_STATUS_IS_OK(status)) {
3078 struct smb_Dir *dir_hnd = NULL;
3080 const char *dname = NULL;
3081 char *talloced = NULL;
3083 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3084 status = NT_STATUS_OBJECT_NAME_INVALID;
3088 dirtype = FILE_ATTRIBUTE_NORMAL;
3091 if (strequal(fname_mask,"????????.???")) {
3092 TALLOC_FREE(fname_mask);
3093 fname_mask = talloc_strdup(ctx, "*");
3095 status = NT_STATUS_NO_MEMORY;
3100 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3105 if (smb_fname_dir == NULL) {
3106 status = NT_STATUS_NO_MEMORY;
3110 status = check_name(conn, smb_fname_dir);
3111 if (!NT_STATUS_IS_OK(status)) {
3115 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3117 if (dir_hnd == NULL) {
3118 status = map_nt_error_from_unix(errno);
3122 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3123 the pattern matches against the long name, otherwise the short name
3124 We don't implement this yet XXXX
3127 status = NT_STATUS_NO_SUCH_FILE;
3129 while ((dname = ReadDirName(dir_hnd, &offset,
3130 &smb_fname->st, &talloced))) {
3131 TALLOC_CTX *frame = talloc_stackframe();
3133 if (!is_visible_file(conn, fname_dir, dname,
3134 &smb_fname->st, true)) {
3136 TALLOC_FREE(talloced);
3140 /* Quick check for "." and ".." */
3141 if (ISDOT(dname) || ISDOTDOT(dname)) {
3143 TALLOC_FREE(talloced);
3147 if(!mask_match(dname, fname_mask,
3148 conn->case_sensitive)) {
3150 TALLOC_FREE(talloced);
3154 TALLOC_FREE(smb_fname->base_name);
3155 if (ISDOT(fname_dir)) {
3156 /* Ensure we use canonical names on open. */
3157 smb_fname->base_name =
3158 talloc_asprintf(smb_fname, "%s",
3161 smb_fname->base_name =
3162 talloc_asprintf(smb_fname, "%s/%s",
3166 if (!smb_fname->base_name) {
3167 TALLOC_FREE(dir_hnd);
3168 status = NT_STATUS_NO_MEMORY;
3170 TALLOC_FREE(talloced);
3174 status = check_name(conn, smb_fname);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 TALLOC_FREE(dir_hnd);
3178 TALLOC_FREE(talloced);
3182 status = do_unlink(conn, req, smb_fname, dirtype);
3183 if (!NT_STATUS_IS_OK(status)) {
3184 TALLOC_FREE(dir_hnd);
3186 TALLOC_FREE(talloced);
3191 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3192 smb_fname->base_name));
3195 TALLOC_FREE(talloced);
3197 TALLOC_FREE(dir_hnd);
3200 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3201 status = map_nt_error_from_unix(errno);
3205 TALLOC_FREE(smb_fname_dir);
3206 TALLOC_FREE(fname_dir);
3207 TALLOC_FREE(fname_mask);
3211 /****************************************************************************
3213 ****************************************************************************/
3215 void reply_unlink(struct smb_request *req)
3217 connection_struct *conn = req->conn;
3219 struct smb_filename *smb_fname = NULL;
3222 bool path_contains_wcard = False;
3223 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3224 ucf_flags_from_smb_request(req);
3225 TALLOC_CTX *ctx = talloc_tos();
3227 START_PROFILE(SMBunlink);
3230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3234 dirtype = SVAL(req->vwv+0, 0);
3236 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3237 STR_TERMINATE, &status,
3238 &path_contains_wcard);
3239 if (!NT_STATUS_IS_OK(status)) {
3240 reply_nterror(req, status);
3244 status = filename_convert(ctx, conn,
3248 &path_contains_wcard,
3250 if (!NT_STATUS_IS_OK(status)) {
3251 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3252 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3253 ERRSRV, ERRbadpath);
3256 reply_nterror(req, status);
3260 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3262 status = unlink_internals(conn, req, dirtype, smb_fname,
3263 path_contains_wcard);
3264 if (!NT_STATUS_IS_OK(status)) {
3265 if (open_was_deferred(req->xconn, req->mid)) {
3266 /* We have re-scheduled this call. */
3269 reply_nterror(req, status);
3273 reply_outbuf(req, 0, 0);
3275 TALLOC_FREE(smb_fname);
3276 END_PROFILE(SMBunlink);
3280 /****************************************************************************
3282 ****************************************************************************/
3284 static void fail_readraw(void)
3286 const char *errstr = talloc_asprintf(talloc_tos(),
3287 "FAIL ! reply_readbraw: socket write fail (%s)",
3292 exit_server_cleanly(errstr);
3295 /****************************************************************************
3296 Fake (read/write) sendfile. Returns -1 on read or write fail.
3297 ****************************************************************************/
3299 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3300 off_t startpos, size_t nread)
3303 size_t tosend = nread;
3310 bufsize = MIN(nread, 65536);
3312 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3316 while (tosend > 0) {
3320 cur_read = MIN(tosend, bufsize);
3321 ret = read_file(fsp,buf,startpos,cur_read);
3327 /* If we had a short read, fill with zeros. */
3328 if (ret < cur_read) {
3329 memset(buf + ret, '\0', cur_read - ret);
3332 ret = write_data(xconn->transport.sock, buf, cur_read);
3333 if (ret != cur_read) {
3334 int saved_errno = errno;
3336 * Try and give an error message saying what
3339 DEBUG(0, ("write_data failed for client %s. "
3341 smbXsrv_connection_dbg(xconn),
3342 strerror(saved_errno)));
3344 errno = saved_errno;
3348 startpos += cur_read;
3352 return (ssize_t)nread;
3355 /****************************************************************************
3356 Deal with the case of sendfile reading less bytes from the file than
3357 requested. Fill with zeros (all we can do). Returns 0 on success
3358 ****************************************************************************/
3360 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3366 #define SHORT_SEND_BUFSIZE 1024
3367 if (nread < headersize) {
3368 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3369 "header for file %s (%s). Terminating\n",
3370 fsp_str_dbg(fsp), strerror(errno)));
3374 nread -= headersize;
3376 if (nread < smb_maxcnt) {
3377 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3379 DEBUG(0,("sendfile_short_send: malloc failed "
3380 "for file %s (%s). Terminating\n",
3381 fsp_str_dbg(fsp), strerror(errno)));
3385 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3386 "with zeros !\n", fsp_str_dbg(fsp)));
3388 while (nread < smb_maxcnt) {
3390 * We asked for the real file size and told sendfile
3391 * to not go beyond the end of the file. But it can
3392 * happen that in between our fstat call and the
3393 * sendfile call the file was truncated. This is very
3394 * bad because we have already announced the larger
3395 * number of bytes to the client.
3397 * The best we can do now is to send 0-bytes, just as
3398 * a read from a hole in a sparse file would do.
3400 * This should happen rarely enough that I don't care
3401 * about efficiency here :-)
3406 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3407 ret = write_data(xconn->transport.sock, buf, to_write);
3408 if (ret != to_write) {
3409 int saved_errno = errno;
3411 * Try and give an error message saying what
3414 DEBUG(0, ("write_data failed for client %s. "
3416 smbXsrv_connection_dbg(xconn),
3417 strerror(saved_errno)));
3418 errno = saved_errno;
3429 /****************************************************************************
3430 Return a readbraw error (4 bytes of zero).
3431 ****************************************************************************/
3433 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3439 smbd_lock_socket(xconn);
3440 if (write_data(xconn->transport.sock,header,4) != 4) {
3441 int saved_errno = errno;
3443 * Try and give an error message saying what
3446 DEBUG(0, ("write_data failed for client %s. "
3448 smbXsrv_connection_dbg(xconn),
3449 strerror(saved_errno)));
3450 errno = saved_errno;
3454 smbd_unlock_socket(xconn);
3457 /****************************************************************************
3458 Use sendfile in readbraw.
3459 ****************************************************************************/
3461 static void send_file_readbraw(connection_struct *conn,
3462 struct smb_request *req,
3468 struct smbXsrv_connection *xconn = req->xconn;
3469 char *outbuf = NULL;
3473 * We can only use sendfile on a non-chained packet
3474 * but we can use on a non-oplocked file. tridge proved this
3475 * on a train in Germany :-). JRA.
3476 * reply_readbraw has already checked the length.
3479 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3480 (fsp->wcp == NULL) &&
3481 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3482 ssize_t sendfile_read = -1;
3484 DATA_BLOB header_blob;
3486 _smb_setlen(header,nread);
3487 header_blob = data_blob_const(header, 4);
3489 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3490 &header_blob, startpos,
3492 if (sendfile_read == -1) {
3493 /* Returning ENOSYS means no data at all was sent.
3494 * Do this as a normal read. */
3495 if (errno == ENOSYS) {
3496 goto normal_readbraw;
3500 * Special hack for broken Linux with no working sendfile. If we
3501 * return EINTR we sent the header but not the rest of the data.
3502 * Fake this up by doing read/write calls.
3504 if (errno == EINTR) {
3505 /* Ensure we don't do this again. */
3506 set_use_sendfile(SNUM(conn), False);
3507 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3509 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3510 DEBUG(0,("send_file_readbraw: "
3511 "fake_sendfile failed for "
3515 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3520 DEBUG(0,("send_file_readbraw: sendfile failed for "
3521 "file %s (%s). Terminating\n",
3522 fsp_str_dbg(fsp), strerror(errno)));
3523 exit_server_cleanly("send_file_readbraw sendfile failed");
3524 } else if (sendfile_read == 0) {
3526 * Some sendfile implementations return 0 to indicate
3527 * that there was a short read, but nothing was
3528 * actually written to the socket. In this case,
3529 * fallback to the normal read path so the header gets
3530 * the correct byte count.
3532 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3533 "bytes falling back to the normal read: "
3534 "%s\n", fsp_str_dbg(fsp)));
3535 goto normal_readbraw;
3538 /* Deal with possible short send. */
3539 if (sendfile_read != 4+nread) {
3540 ret = sendfile_short_send(xconn, fsp,
3541 sendfile_read, 4, nread);
3551 outbuf = talloc_array(NULL, char, nread+4);
3553 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3554 (unsigned)(nread+4)));
3555 reply_readbraw_error(xconn);
3560 ret = read_file(fsp,outbuf+4,startpos,nread);
3561 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3570 _smb_setlen(outbuf,ret);
3571 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3572 int saved_errno = errno;
3574 * Try and give an error message saying what
3577 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3578 smbXsrv_connection_dbg(xconn),
3579 strerror(saved_errno)));
3580 errno = saved_errno;
3585 TALLOC_FREE(outbuf);
3588 /****************************************************************************
3589 Reply to a readbraw (core+ protocol).
3590 ****************************************************************************/
3592 void reply_readbraw(struct smb_request *req)
3594 connection_struct *conn = req->conn;
3595 struct smbXsrv_connection *xconn = req->xconn;
3596 ssize_t maxcount,mincount;
3600 struct lock_struct lock;
3603 START_PROFILE(SMBreadbraw);
3605 if (srv_is_signing_active(xconn) || req->encrypted) {
3606 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3607 "raw reads/writes are disallowed.");
3611 reply_readbraw_error(xconn);
3612 END_PROFILE(SMBreadbraw);
3616 if (xconn->smb1.echo_handler.trusted_fde) {
3617 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3618 "'async smb echo handler = yes'\n"));
3619 reply_readbraw_error(xconn);
3620 END_PROFILE(SMBreadbraw);
3625 * Special check if an oplock break has been issued
3626 * and the readraw request croses on the wire, we must
3627 * return a zero length response here.
3630 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3633 * We have to do a check_fsp by hand here, as
3634 * we must always return 4 zero bytes on error,
3638 if (!fsp || !conn || conn != fsp->conn ||
3639 req->vuid != fsp->vuid ||
3640 fsp->is_directory || fsp->fh->fd == -1) {
3642 * fsp could be NULL here so use the value from the packet. JRA.
3644 DEBUG(3,("reply_readbraw: fnum %d not valid "
3646 (int)SVAL(req->vwv+0, 0)));
3647 reply_readbraw_error(xconn);
3648 END_PROFILE(SMBreadbraw);
3652 /* Do a "by hand" version of CHECK_READ. */
3653 if (!(fsp->can_read ||
3654 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3655 (fsp->access_mask & FILE_EXECUTE)))) {
3656 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3657 (int)SVAL(req->vwv+0, 0)));
3658 reply_readbraw_error(xconn);
3659 END_PROFILE(SMBreadbraw);
3663 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3665 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3666 if(req->wct == 10) {
3668 * This is a large offset (64 bit) read.
3671 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3674 DEBUG(0,("reply_readbraw: negative 64 bit "
3675 "readraw offset (%.0f) !\n",
3676 (double)startpos ));
3677 reply_readbraw_error(xconn);
3678 END_PROFILE(SMBreadbraw);
3683 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3684 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3686 /* ensure we don't overrun the packet size */
3687 maxcount = MIN(65535,maxcount);
3689 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3690 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3693 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3694 reply_readbraw_error(xconn);
3695 END_PROFILE(SMBreadbraw);
3699 if (fsp_stat(fsp) == 0) {
3700 size = fsp->fsp_name->st.st_ex_size;
3703 if (startpos >= size) {
3706 nread = MIN(maxcount,(size - startpos));
3709 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3710 if (nread < mincount)
3714 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3715 "min=%lu nread=%lu\n",
3716 fsp_fnum_dbg(fsp), (double)startpos,
3717 (unsigned long)maxcount,
3718 (unsigned long)mincount,
3719 (unsigned long)nread ) );
3721 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3723 DEBUG(5,("reply_readbraw finished\n"));
3725 END_PROFILE(SMBreadbraw);
3730 #define DBGC_CLASS DBGC_LOCKING
3732 /****************************************************************************
3733 Reply to a lockread (core+ protocol).
3734 ****************************************************************************/
3736 void reply_lockread(struct smb_request *req)
3738 connection_struct *conn = req->conn;
3746 struct byte_range_lock *br_lck = NULL;
3748 struct smbXsrv_connection *xconn = req->xconn;
3750 START_PROFILE(SMBlockread);
3753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3754 END_PROFILE(SMBlockread);
3758 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3760 if (!check_fsp(conn, req, fsp)) {
3761 END_PROFILE(SMBlockread);
3765 if (!CHECK_READ(fsp,req)) {
3766 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3767 END_PROFILE(SMBlockread);
3771 numtoread = SVAL(req->vwv+1, 0);
3772 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3775 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3776 * protocol request that predates the read/write lock concept.
3777 * Thus instead of asking for a read lock here we need to ask
3778 * for a write lock. JRA.
3779 * Note that the requested lock size is unaffected by max_send.
3782 br_lck = do_lock(req->sconn->msg_ctx,
3784 (uint64_t)req->smbpid,
3785 (uint64_t)numtoread,
3789 False, /* Non-blocking lock. */
3792 TALLOC_FREE(br_lck);
3794 if (NT_STATUS_V(status)) {
3795 reply_nterror(req, status);
3796 END_PROFILE(SMBlockread);
3801 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3803 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3805 if (numtoread > maxtoread) {
3806 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3807 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3808 (unsigned int)numtoread, (unsigned int)maxtoread,
3809 (unsigned int)xconn->smb1.sessions.max_send));
3810 numtoread = maxtoread;
3813 reply_outbuf(req, 5, numtoread + 3);
3815 data = smb_buf(req->outbuf) + 3;
3817 nread = read_file(fsp,data,startpos,numtoread);
3820 reply_nterror(req, map_nt_error_from_unix(errno));
3821 END_PROFILE(SMBlockread);
3825 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3827 SSVAL(req->outbuf,smb_vwv0,nread);
3828 SSVAL(req->outbuf,smb_vwv5,nread+3);
3829 p = smb_buf(req->outbuf);
3830 SCVAL(p,0,0); /* pad byte. */
3833 DEBUG(3,("lockread %s num=%d nread=%d\n",
3834 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3836 END_PROFILE(SMBlockread);
3841 #define DBGC_CLASS DBGC_ALL
3843 /****************************************************************************
3845 ****************************************************************************/
3847 void reply_read(struct smb_request *req)
3849 connection_struct *conn = req->conn;
3856 struct lock_struct lock;
3857 struct smbXsrv_connection *xconn = req->xconn;
3859 START_PROFILE(SMBread);
3862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3863 END_PROFILE(SMBread);
3867 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3869 if (!check_fsp(conn, req, fsp)) {
3870 END_PROFILE(SMBread);
3874 if (!CHECK_READ(fsp,req)) {
3875 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3876 END_PROFILE(SMBread);
3880 numtoread = SVAL(req->vwv+1, 0);
3881 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3884 * The requested read size cannot be greater than max_send. JRA.
3886 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3888 if (numtoread > maxtoread) {
3889 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3890 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3891 (unsigned int)numtoread, (unsigned int)maxtoread,
3892 (unsigned int)xconn->smb1.sessions.max_send));
3893 numtoread = maxtoread;
3896 reply_outbuf(req, 5, numtoread+3);
3898 data = smb_buf(req->outbuf) + 3;
3900 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3901 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3904 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3905 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3906 END_PROFILE(SMBread);
3911 nread = read_file(fsp,data,startpos,numtoread);
3914 reply_nterror(req, map_nt_error_from_unix(errno));
3918 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3920 SSVAL(req->outbuf,smb_vwv0,nread);
3921 SSVAL(req->outbuf,smb_vwv5,nread+3);
3922 SCVAL(smb_buf(req->outbuf),0,1);
3923 SSVAL(smb_buf(req->outbuf),1,nread);
3925 DEBUG(3, ("read %s num=%d nread=%d\n",
3926 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3929 END_PROFILE(SMBread);
3933 /****************************************************************************
3935 ****************************************************************************/
3937 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3941 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3944 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3946 SCVAL(outbuf,smb_vwv0,0xFF);
3947 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3948 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3949 SSVAL(outbuf,smb_vwv6,
3950 (smb_wct - 4) /* offset from smb header to wct */
3951 + 1 /* the wct field */
3952 + 12 * sizeof(uint16_t) /* vwv */
3953 + 2 /* the buflen field */
3954 + 1); /* padding byte */
3955 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3956 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3957 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3958 _smb_setlen_large(outbuf,
3959 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3963 /****************************************************************************
3964 Reply to a read and X - possibly using sendfile.
3965 ****************************************************************************/
3967 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3968 files_struct *fsp, off_t startpos,
3971 struct smbXsrv_connection *xconn = req->xconn;
3973 struct lock_struct lock;
3974 int saved_errno = 0;
3976 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3977 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3980 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3981 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3986 * We can only use sendfile on a non-chained packet
3987 * but we can use on a non-oplocked file. tridge proved this
3988 * on a train in Germany :-). JRA.
3991 if (!req_is_in_chain(req) &&
3993 (fsp->base_fsp == NULL) &&
3994 (fsp->wcp == NULL) &&
3995 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3996 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3999 if(fsp_stat(fsp) == -1) {
4000 reply_nterror(req, map_nt_error_from_unix(errno));
4004 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4005 (startpos > fsp->fsp_name->st.st_ex_size) ||
4006 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4008 * We already know that we would do a short read, so don't
4009 * try the sendfile() path.
4011 goto nosendfile_read;
4015 * Set up the packet header before send. We
4016 * assume here the sendfile will work (get the
4017 * correct amount of data).
4020 header = data_blob_const(headerbuf, sizeof(headerbuf));
4022 construct_reply_common_req(req, (char *)headerbuf);
4023 setup_readX_header((char *)headerbuf, smb_maxcnt);
4025 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4026 startpos, smb_maxcnt);
4028 saved_errno = errno;
4030 /* Returning ENOSYS means no data at all was sent.
4031 Do this as a normal read. */
4032 if (errno == ENOSYS) {
4037 * Special hack for broken Linux with no working sendfile. If we
4038 * return EINTR we sent the header but not the rest of the data.
4039 * Fake this up by doing read/write calls.
4042 if (errno == EINTR) {
4043 /* Ensure we don't do this again. */
4044 set_use_sendfile(SNUM(conn), False);
4045 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4046 nread = fake_sendfile(xconn, fsp, startpos,
4049 saved_errno = errno;
4050 DEBUG(0,("send_file_readX: "
4051 "fake_sendfile failed for "
4052 "file %s (%s) for client %s. "
4055 smbXsrv_connection_dbg(xconn),
4056 strerror(saved_errno)));
4057 errno = saved_errno;
4058 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4060 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4061 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4062 /* No outbuf here means successful sendfile. */
4066 DEBUG(0,("send_file_readX: sendfile failed for file "
4067 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4069 exit_server_cleanly("send_file_readX sendfile failed");
4070 } else if (nread == 0) {
4072 * Some sendfile implementations return 0 to indicate
4073 * that there was a short read, but nothing was
4074 * actually written to the socket. In this case,
4075 * fallback to the normal read path so the header gets
4076 * the correct byte count.
4078 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4079 "falling back to the normal read: %s\n",
4084 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4085 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4087 /* Deal with possible short send. */
4088 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4091 ret = sendfile_short_send(xconn, fsp, nread,
4092 sizeof(headerbuf), smb_maxcnt);
4095 r = "send_file_readX: sendfile_short_send failed";
4096 DEBUG(0,("%s for file %s (%s).\n",
4097 r, fsp_str_dbg(fsp), strerror(errno)));
4098 exit_server_cleanly(r);
4101 /* No outbuf here means successful sendfile. */
4102 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4103 SMB_PERFCOUNT_END(&req->pcd);
4109 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4110 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4113 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4114 (startpos > fsp->fsp_name->st.st_ex_size) ||
4115 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4117 * We already know that we would do a short
4118 * read, so don't try the sendfile() path.
4120 goto nosendfile_read;
4123 construct_reply_common_req(req, (char *)headerbuf);
4124 setup_readX_header((char *)headerbuf, smb_maxcnt);
4126 /* Send out the header. */
4127 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4129 if (ret != sizeof(headerbuf)) {
4130 saved_errno = errno;
4132 * Try and give an error message saying what
4135 DEBUG(0,("send_file_readX: write_data failed for file "
4136 "%s (%s) for client %s. Terminating\n",
4138 smbXsrv_connection_dbg(xconn),
4139 strerror(saved_errno)));
4140 errno = saved_errno;
4141 exit_server_cleanly("send_file_readX sendfile failed");
4143 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4145 saved_errno = errno;
4146 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4147 "%s (%s) for client %s. Terminating\n",
4149 smbXsrv_connection_dbg(xconn),
4150 strerror(saved_errno)));
4151 errno = saved_errno;
4152 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4159 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4160 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4161 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4163 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4164 startpos, smb_maxcnt);
4165 saved_errno = errno;
4168 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4172 setup_readX_header((char *)req->outbuf, nread);
4174 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4175 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4179 TALLOC_FREE(req->outbuf);
4183 /****************************************************************************
4184 Work out how much space we have for a read return.
4185 ****************************************************************************/
4187 static size_t calc_max_read_pdu(const struct smb_request *req)
4189 struct smbXsrv_connection *xconn = req->xconn;
4191 if (xconn->protocol < PROTOCOL_NT1) {
4192 return xconn->smb1.sessions.max_send;
4195 if (!lp_large_readwrite()) {
4196 return xconn->smb1.sessions.max_send;
4199 if (req_is_in_chain(req)) {
4200 return xconn->smb1.sessions.max_send;
4203 if (req->encrypted) {
4205 * Don't take encrypted traffic up to the
4206 * limit. There are padding considerations
4207 * that make that tricky.
4209 return xconn->smb1.sessions.max_send;
4212 if (srv_is_signing_active(xconn)) {
4216 if (!lp_unix_extensions()) {
4221 * We can do ultra-large POSIX reads.
4226 /****************************************************************************
4227 Calculate how big a read can be. Copes with all clients. It's always
4228 safe to return a short read - Windows does this.
4229 ****************************************************************************/
4231 static size_t calc_read_size(const struct smb_request *req,
4235 struct smbXsrv_connection *xconn = req->xconn;
4236 size_t max_pdu = calc_max_read_pdu(req);
4237 size_t total_size = 0;
4238 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4239 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4242 * Windows explicitly ignores upper size of 0xFFFF.
4243 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4244 * We must do the same as these will never fit even in
4245 * an extended size NetBIOS packet.
4247 if (upper_size == 0xFFFF) {
4251 if (xconn->protocol < PROTOCOL_NT1) {
4255 total_size = ((upper_size<<16) | lower_size);
4258 * LARGE_READX test shows it's always safe to return
4259 * a short read. Windows does so.
4261 return MIN(total_size, max_len);
4264 /****************************************************************************
4265 Reply to a read and X.
4266 ****************************************************************************/
4268 void reply_read_and_X(struct smb_request *req)
4270 connection_struct *conn = req->conn;
4275 bool big_readX = False;
4277 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4280 START_PROFILE(SMBreadX);
4282 if ((req->wct != 10) && (req->wct != 12)) {
4283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4287 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4288 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4289 smb_maxcnt = SVAL(req->vwv+5, 0);
4291 /* If it's an IPC, pass off the pipe handler. */
4293 reply_pipe_read_and_X(req);
4294 END_PROFILE(SMBreadX);
4298 if (!check_fsp(conn, req, fsp)) {
4299 END_PROFILE(SMBreadX);
4303 if (!CHECK_READ(fsp,req)) {
4304 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4305 END_PROFILE(SMBreadX);
4309 upper_size = SVAL(req->vwv+7, 0);
4310 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4311 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4313 * This is a heuristic to avoid keeping large
4314 * outgoing buffers around over long-lived aio
4320 if (req->wct == 12) {
4322 * This is a large offset (64 bit) read.
4324 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4329 NTSTATUS status = schedule_aio_read_and_X(conn,
4334 if (NT_STATUS_IS_OK(status)) {
4335 /* Read scheduled - we're done. */
4338 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4339 /* Real error - report to client. */
4340 END_PROFILE(SMBreadX);
4341 reply_nterror(req, status);
4344 /* NT_STATUS_RETRY - fall back to sync read. */
4347 smbd_lock_socket(req->xconn);
4348 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4349 smbd_unlock_socket(req->xconn);
4352 END_PROFILE(SMBreadX);
4356 /****************************************************************************
4357 Error replies to writebraw must have smb_wct == 1. Fix this up.
4358 ****************************************************************************/
4360 void error_to_writebrawerr(struct smb_request *req)
4362 uint8_t *old_outbuf = req->outbuf;
4364 reply_outbuf(req, 1, 0);
4366 memcpy(req->outbuf, old_outbuf, smb_size);
4367 TALLOC_FREE(old_outbuf);
4370 /****************************************************************************
4371 Read 4 bytes of a smb packet and return the smb length of the packet.
4372 Store the result in the buffer. This version of the function will
4373 never return a session keepalive (length of zero).
4374 Timeout is in milliseconds.
4375 ****************************************************************************/
4377 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4380 uint8_t msgtype = NBSSkeepalive;
4382 while (msgtype == NBSSkeepalive) {
4385 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4387 if (!NT_STATUS_IS_OK(status)) {
4388 char addr[INET6_ADDRSTRLEN];
4389 /* Try and give an error message
4390 * saying what client failed. */
4391 DEBUG(0, ("read_fd_with_timeout failed for "
4392 "client %s read error = %s.\n",
4393 get_peer_addr(fd,addr,sizeof(addr)),
4394 nt_errstr(status)));
4398 msgtype = CVAL(inbuf, 0);
4401 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4402 (unsigned long)len));
4404 return NT_STATUS_OK;
4407 /****************************************************************************
4408 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4409 ****************************************************************************/
4411 void reply_writebraw(struct smb_request *req)
4413 connection_struct *conn = req->conn;
4414 struct smbXsrv_connection *xconn = req->xconn;
4417 ssize_t total_written=0;
4418 size_t numtowrite=0;
4421 const char *data=NULL;
4424 struct lock_struct lock;
4427 START_PROFILE(SMBwritebraw);
4430 * If we ever reply with an error, it must have the SMB command
4431 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4434 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4436 if (srv_is_signing_active(xconn)) {
4437 END_PROFILE(SMBwritebraw);
4438 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4439 "raw reads/writes are disallowed.");
4442 if (req->wct < 12) {
4443 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4444 error_to_writebrawerr(req);
4445 END_PROFILE(SMBwritebraw);
4449 if (xconn->smb1.echo_handler.trusted_fde) {
4450 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4451 "'async smb echo handler = yes'\n"));
4452 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4453 error_to_writebrawerr(req);
4454 END_PROFILE(SMBwritebraw);
4458 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4459 if (!check_fsp(conn, req, fsp)) {
4460 error_to_writebrawerr(req);
4461 END_PROFILE(SMBwritebraw);
4465 if (!CHECK_WRITE(fsp)) {
4466 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4467 error_to_writebrawerr(req);
4468 END_PROFILE(SMBwritebraw);
4472 tcount = IVAL(req->vwv+1, 0);
4473 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4474 write_through = BITSETW(req->vwv+7,0);
4476 /* We have to deal with slightly different formats depending
4477 on whether we are using the core+ or lanman1.0 protocol */
4479 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4480 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4481 data = smb_buf_const(req->inbuf);
4483 numtowrite = SVAL(req->vwv+10, 0);
4484 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4487 /* Ensure we don't write bytes past the end of this packet. */
4489 * This already protects us against CVE-2017-12163.
4491 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4493 error_to_writebrawerr(req);
4494 END_PROFILE(SMBwritebraw);
4498 if (!fsp->print_file) {
4499 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4500 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4503 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4504 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4505 error_to_writebrawerr(req);
4506 END_PROFILE(SMBwritebraw);
4512 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4515 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4516 "wrote=%d sync=%d\n",
4517 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4518 (int)nwritten, (int)write_through));
4520 if (nwritten < (ssize_t)numtowrite) {
4521 reply_nterror(req, NT_STATUS_DISK_FULL);
4522 error_to_writebrawerr(req);
4526 total_written = nwritten;
4528 /* Allocate a buffer of 64k + length. */
4529 buf = talloc_array(NULL, char, 65540);
4531 reply_nterror(req, NT_STATUS_NO_MEMORY);
4532 error_to_writebrawerr(req);
4536 /* Return a SMBwritebraw message to the redirector to tell
4537 * it to send more bytes */
4539 memcpy(buf, req->inbuf, smb_size);
4540 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4541 SCVAL(buf,smb_com,SMBwritebraw);
4542 SSVALS(buf,smb_vwv0,0xFFFF);
4544 if (!srv_send_smb(req->xconn,
4546 false, 0, /* no signing */
4547 IS_CONN_ENCRYPTED(conn),
4549 exit_server_cleanly("reply_writebraw: srv_send_smb "
4553 /* Now read the raw data into the buffer and write it */
4554 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4556 if (!NT_STATUS_IS_OK(status)) {
4557 exit_server_cleanly("secondary writebraw failed");
4560 /* Set up outbuf to return the correct size */
4561 reply_outbuf(req, 1, 0);
4563 if (numtowrite != 0) {
4565 if (numtowrite > 0xFFFF) {
4566 DEBUG(0,("reply_writebraw: Oversize secondary write "
4567 "raw requested (%u). Terminating\n",
4568 (unsigned int)numtowrite ));
4569 exit_server_cleanly("secondary writebraw failed");
4572 if (tcount > nwritten+numtowrite) {
4573 DEBUG(3,("reply_writebraw: Client overestimated the "
4575 (int)tcount,(int)nwritten,(int)numtowrite));
4578 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4581 if (!NT_STATUS_IS_OK(status)) {
4582 /* Try and give an error message
4583 * saying what client failed. */
4584 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4585 "raw read failed (%s) for client %s. "
4586 "Terminating\n", nt_errstr(status),
4587 smbXsrv_connection_dbg(xconn)));
4588 exit_server_cleanly("secondary writebraw failed");
4592 * We are not vulnerable to CVE-2017-12163
4593 * here as we are guarenteed to have numtowrite
4594 * bytes available - we just read from the client.
4596 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4597 if (nwritten == -1) {
4599 reply_nterror(req, map_nt_error_from_unix(errno));
4600 error_to_writebrawerr(req);
4604 if (nwritten < (ssize_t)numtowrite) {
4605 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4606 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4610 total_written += nwritten;
4615 SSVAL(req->outbuf,smb_vwv0,total_written);
4617 status = sync_file(conn, fsp, write_through);
4618 if (!NT_STATUS_IS_OK(status)) {
4619 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4620 fsp_str_dbg(fsp), nt_errstr(status)));
4621 reply_nterror(req, status);
4622 error_to_writebrawerr(req);
4626 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4628 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4629 (int)total_written));
4631 /* We won't return a status if write through is not selected - this
4632 * follows what WfWg does */
4633 END_PROFILE(SMBwritebraw);
4635 if (!write_through && total_written==tcount) {
4637 #if RABBIT_PELLET_FIX
4639 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4640 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4643 if (!send_keepalive(xconn->transport.sock)) {
4644 exit_server_cleanly("reply_writebraw: send of "
4645 "keepalive failed");
4648 TALLOC_FREE(req->outbuf);
4653 END_PROFILE(SMBwritebraw);
4658 #define DBGC_CLASS DBGC_LOCKING
4660 /****************************************************************************
4661 Reply to a writeunlock (core+).
4662 ****************************************************************************/
4664 void reply_writeunlock(struct smb_request *req)
4666 connection_struct *conn = req->conn;
4667 ssize_t nwritten = -1;
4672 NTSTATUS status = NT_STATUS_OK;
4674 struct lock_struct lock;
4675 int saved_errno = 0;
4677 START_PROFILE(SMBwriteunlock);
4680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4681 END_PROFILE(SMBwriteunlock);
4685 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4687 if (!check_fsp(conn, req, fsp)) {
4688 END_PROFILE(SMBwriteunlock);
4692 if (!CHECK_WRITE(fsp)) {
4693 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4694 END_PROFILE(SMBwriteunlock);
4698 numtowrite = SVAL(req->vwv+1, 0);
4699 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4700 data = (const char *)req->buf + 3;
4703 * Ensure client isn't asking us to write more than
4704 * they sent. CVE-2017-12163.
4706 remaining = smbreq_bufrem(req, data);
4707 if (numtowrite > remaining) {
4708 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4709 END_PROFILE(SMBwriteunlock);
4713 if (!fsp->print_file && numtowrite > 0) {
4714 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4715 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4718 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4719 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4720 END_PROFILE(SMBwriteunlock);
4725 /* The special X/Open SMB protocol handling of
4726 zero length writes is *NOT* done for
4728 if(numtowrite == 0) {
4731 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4732 saved_errno = errno;
4735 status = sync_file(conn, fsp, False /* write through */);
4736 if (!NT_STATUS_IS_OK(status)) {
4737 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4738 fsp_str_dbg(fsp), nt_errstr(status)));
4739 reply_nterror(req, status);
4744 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4748 if((nwritten < numtowrite) && (numtowrite != 0)) {
4749 reply_nterror(req, NT_STATUS_DISK_FULL);
4753 if (numtowrite && !fsp->print_file) {
4754 status = do_unlock(req->sconn->msg_ctx,
4756 (uint64_t)req->smbpid,
4757 (uint64_t)numtowrite,
4761 if (NT_STATUS_V(status)) {
4762 reply_nterror(req, status);
4767 reply_outbuf(req, 1, 0);
4769 SSVAL(req->outbuf,smb_vwv0,nwritten);
4771 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4772 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4775 END_PROFILE(SMBwriteunlock);
4780 #define DBGC_CLASS DBGC_ALL
4782 /****************************************************************************
4784 ****************************************************************************/
4786 void reply_write(struct smb_request *req)
4788 connection_struct *conn = req->conn;
4791 ssize_t nwritten = -1;
4795 struct lock_struct lock;
4797 int saved_errno = 0;
4799 START_PROFILE(SMBwrite);
4802 END_PROFILE(SMBwrite);
4803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4807 /* If it's an IPC, pass off the pipe handler. */
4809 reply_pipe_write(req);
4810 END_PROFILE(SMBwrite);
4814 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4816 if (!check_fsp(conn, req, fsp)) {
4817 END_PROFILE(SMBwrite);
4821 if (!CHECK_WRITE(fsp)) {
4822 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4823 END_PROFILE(SMBwrite);
4827 numtowrite = SVAL(req->vwv+1, 0);
4828 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4829 data = (const char *)req->buf + 3;
4832 * Ensure client isn't asking us to write more than
4833 * they sent. CVE-2017-12163.
4835 remaining = smbreq_bufrem(req, data);
4836 if (numtowrite > remaining) {
4837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4838 END_PROFILE(SMBwrite);
4842 if (!fsp->print_file) {
4843 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4844 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4847 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4848 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4849 END_PROFILE(SMBwrite);
4855 * X/Open SMB protocol says that if smb_vwv1 is
4856 * zero then the file size should be extended or
4857 * truncated to the size given in smb_vwv[2-3].
4860 if(numtowrite == 0) {
4862 * This is actually an allocate call, and set EOF. JRA.
4864 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4866 reply_nterror(req, NT_STATUS_DISK_FULL);
4869 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4871 reply_nterror(req, NT_STATUS_DISK_FULL);
4874 trigger_write_time_update_immediate(fsp);
4876 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4879 status = sync_file(conn, fsp, False);
4880 if (!NT_STATUS_IS_OK(status)) {
4881 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4882 fsp_str_dbg(fsp), nt_errstr(status)));
4883 reply_nterror(req, status);
4888 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4892 if((nwritten == 0) && (numtowrite != 0)) {
4893 reply_nterror(req, NT_STATUS_DISK_FULL);
4897 reply_outbuf(req, 1, 0);
4899 SSVAL(req->outbuf,smb_vwv0,nwritten);
4901 if (nwritten < (ssize_t)numtowrite) {
4902 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4903 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4906 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4909 END_PROFILE(SMBwrite);
4913 /****************************************************************************
4914 Ensure a buffer is a valid writeX for recvfile purposes.
4915 ****************************************************************************/
4917 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4918 (2*14) + /* word count (including bcc) */ \
4921 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4922 const uint8_t *inbuf)
4925 unsigned int doff = 0;
4926 size_t len = smb_len_large(inbuf);
4928 struct smbXsrv_open *op = NULL;
4929 struct files_struct *fsp = NULL;
4932 if (is_encrypted_packet(inbuf)) {
4933 /* Can't do this on encrypted
4938 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4942 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4943 CVAL(inbuf,smb_wct) != 14) {
4944 DEBUG(10,("is_valid_writeX_buffer: chained or "
4945 "invalid word length.\n"));
4949 fnum = SVAL(inbuf, smb_vwv2);
4950 status = smb1srv_open_lookup(xconn,
4954 if (!NT_STATUS_IS_OK(status)) {
4955 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4960 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4963 if (fsp->conn == NULL) {
4964 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4968 if (IS_IPC(fsp->conn)) {
4969 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4972 if (IS_PRINT(fsp->conn)) {
4973 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4976 doff = SVAL(inbuf,smb_vwv11);
4978 numtowrite = SVAL(inbuf,smb_vwv10);
4980 if (len > doff && len - doff > 0xFFFF) {
4981 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4984 if (numtowrite == 0) {
4985 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4989 /* Ensure the sizes match up. */
4990 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4991 /* no pad byte...old smbclient :-( */
4992 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4994 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4998 if (len - doff != numtowrite) {
4999 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5000 "len = %u, doff = %u, numtowrite = %u\n",
5003 (unsigned int)numtowrite ));
5007 DEBUG(10,("is_valid_writeX_buffer: true "
5008 "len = %u, doff = %u, numtowrite = %u\n",
5011 (unsigned int)numtowrite ));
5016 /****************************************************************************
5017 Reply to a write and X.
5018 ****************************************************************************/
5020 void reply_write_and_X(struct smb_request *req)
5022 connection_struct *conn = req->conn;
5023 struct smbXsrv_connection *xconn = req->xconn;
5025 struct lock_struct lock;
5030 unsigned int smb_doff;
5031 unsigned int smblen;
5034 int saved_errno = 0;
5036 START_PROFILE(SMBwriteX);
5038 if ((req->wct != 12) && (req->wct != 14)) {
5039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5043 numtowrite = SVAL(req->vwv+10, 0);
5044 smb_doff = SVAL(req->vwv+11, 0);
5045 smblen = smb_len(req->inbuf);
5047 if (req->unread_bytes > 0xFFFF ||
5048 (smblen > smb_doff &&
5049 smblen - smb_doff > 0xFFFF)) {
5050 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5053 if (req->unread_bytes) {
5054 /* Can't do a recvfile write on IPC$ */
5056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5059 if (numtowrite != req->unread_bytes) {
5060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5065 * This already protects us against CVE-2017-12163.
5067 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5068 smb_doff + numtowrite > smblen) {
5069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5074 /* If it's an IPC, pass off the pipe handler. */
5076 if (req->unread_bytes) {
5077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5080 reply_pipe_write_and_X(req);
5084 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5085 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5086 write_through = BITSETW(req->vwv+7,0);
5088 if (!check_fsp(conn, req, fsp)) {
5092 if (!CHECK_WRITE(fsp)) {
5093 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5097 data = smb_base(req->inbuf) + smb_doff;
5099 if(req->wct == 14) {
5101 * This is a large offset (64 bit) write.
5103 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5107 /* X/Open SMB protocol says that, unlike SMBwrite
5108 if the length is zero then NO truncation is
5109 done, just a write of zero. To truncate a file,
5112 if(numtowrite == 0) {
5115 if (req->unread_bytes == 0) {
5116 status = schedule_aio_write_and_X(conn,
5123 if (NT_STATUS_IS_OK(status)) {
5124 /* write scheduled - we're done. */
5127 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5128 /* Real error - report to client. */
5129 reply_nterror(req, status);
5132 /* NT_STATUS_RETRY - fall through to sync write. */
5135 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5136 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5139 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5140 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5144 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5145 saved_errno = errno;
5149 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5153 if((nwritten == 0) && (numtowrite != 0)) {
5154 reply_nterror(req, NT_STATUS_DISK_FULL);
5158 reply_outbuf(req, 6, 0);
5159 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5160 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5161 SSVAL(req->outbuf,smb_vwv2,nwritten);
5162 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5164 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5165 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5167 status = sync_file(conn, fsp, write_through);
5168 if (!NT_STATUS_IS_OK(status)) {
5169 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5170 fsp_str_dbg(fsp), nt_errstr(status)));
5171 reply_nterror(req, status);
5175 END_PROFILE(SMBwriteX);
5179 if (req->unread_bytes) {
5180 /* writeX failed. drain socket. */
5181 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5182 req->unread_bytes) {
5183 smb_panic("failed to drain pending bytes");
5185 req->unread_bytes = 0;
5188 END_PROFILE(SMBwriteX);
5192 /****************************************************************************
5194 ****************************************************************************/
5196 void reply_lseek(struct smb_request *req)
5198 connection_struct *conn = req->conn;
5204 START_PROFILE(SMBlseek);
5207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5208 END_PROFILE(SMBlseek);
5212 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5214 if (!check_fsp(conn, req, fsp)) {
5218 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5220 mode = SVAL(req->vwv+1, 0) & 3;
5221 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5222 startpos = (off_t)IVALS(req->vwv+2, 0);
5231 res = fsp->fh->pos + startpos;
5242 if (umode == SEEK_END) {
5243 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5244 if(errno == EINVAL) {
5245 off_t current_pos = startpos;
5247 if(fsp_stat(fsp) == -1) {
5249 map_nt_error_from_unix(errno));
5250 END_PROFILE(SMBlseek);
5254 current_pos += fsp->fsp_name->st.st_ex_size;
5256 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5261 reply_nterror(req, map_nt_error_from_unix(errno));
5262 END_PROFILE(SMBlseek);
5269 reply_outbuf(req, 2, 0);
5270 SIVAL(req->outbuf,smb_vwv0,res);
5272 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5273 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5275 END_PROFILE(SMBlseek);
5279 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5282 connection_struct *conn = talloc_get_type_abort(
5283 private_data, connection_struct);
5285 if (conn != fsp->conn) {
5288 if (fsp->fh->fd == -1) {
5291 sync_file(conn, fsp, True /* write through */);
5296 /****************************************************************************
5298 ****************************************************************************/
5300 void reply_flush(struct smb_request *req)
5302 connection_struct *conn = req->conn;
5306 START_PROFILE(SMBflush);
5309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5313 fnum = SVAL(req->vwv+0, 0);
5314 fsp = file_fsp(req, fnum);
5316 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5321 files_forall(req->sconn, file_sync_one_fn, conn);
5323 NTSTATUS status = sync_file(conn, fsp, True);
5324 if (!NT_STATUS_IS_OK(status)) {
5325 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5326 fsp_str_dbg(fsp), nt_errstr(status)));
5327 reply_nterror(req, status);
5328 END_PROFILE(SMBflush);
5333 reply_outbuf(req, 0, 0);
5335 DEBUG(3,("flush\n"));
5336 END_PROFILE(SMBflush);
5340 /****************************************************************************
5342 conn POINTER CAN BE NULL HERE !
5343 ****************************************************************************/
5345 void reply_exit(struct smb_request *req)
5347 START_PROFILE(SMBexit);
5349 file_close_pid(req->sconn, req->smbpid, req->vuid);
5351 reply_outbuf(req, 0, 0);
5353 DEBUG(3,("exit\n"));
5355 END_PROFILE(SMBexit);
5359 struct reply_close_state {
5361 struct smb_request *smbreq;
5364 static void do_smb1_close(struct tevent_req *req);
5366 void reply_close(struct smb_request *req)
5368 connection_struct *conn = req->conn;
5369 NTSTATUS status = NT_STATUS_OK;
5370 files_struct *fsp = NULL;
5371 START_PROFILE(SMBclose);
5374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5375 END_PROFILE(SMBclose);
5379 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5382 * We can only use check_fsp if we know it's not a directory.
5385 if (!check_fsp_open(conn, req, fsp)) {
5386 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5387 END_PROFILE(SMBclose);
5391 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5392 fsp->is_directory ? "directory" : "file",
5393 fsp->fh->fd, fsp_fnum_dbg(fsp),
5394 conn->num_files_open));
5396 if (!fsp->is_directory) {
5400 * Take care of any time sent in the close.
5403 t = srv_make_unix_date3(req->vwv+1);
5404 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5407 if (fsp->num_aio_requests != 0) {
5409 struct reply_close_state *state;
5411 DEBUG(10, ("closing with aio %u requests pending\n",
5412 fsp->num_aio_requests));
5415 * We depend on the aio_extra destructor to take care of this
5416 * close request once fsp->num_aio_request drops to 0.
5419 fsp->deferred_close = tevent_wait_send(
5420 fsp, fsp->conn->sconn->ev_ctx);
5421 if (fsp->deferred_close == NULL) {
5422 status = NT_STATUS_NO_MEMORY;
5426 state = talloc(fsp, struct reply_close_state);
5427 if (state == NULL) {
5428 TALLOC_FREE(fsp->deferred_close);
5429 status = NT_STATUS_NO_MEMORY;
5433 state->smbreq = talloc_move(fsp, &req);
5434 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5436 END_PROFILE(SMBclose);
5441 * close_file() returns the unix errno if an error was detected on
5442 * close - normally this is due to a disk full error. If not then it
5443 * was probably an I/O error.
5446 status = close_file(req, fsp, NORMAL_CLOSE);
5448 if (!NT_STATUS_IS_OK(status)) {
5449 reply_nterror(req, status);
5450 END_PROFILE(SMBclose);
5454 reply_outbuf(req, 0, 0);
5455 END_PROFILE(SMBclose);
5459 static void do_smb1_close(struct tevent_req *req)
5461 struct reply_close_state *state = tevent_req_callback_data(
5462 req, struct reply_close_state);
5463 struct smb_request *smbreq;
5467 ret = tevent_wait_recv(req);
5470 DEBUG(10, ("tevent_wait_recv returned %s\n",
5473 * Continue anyway, this should never happen
5478 * fsp->smb2_close_request right now is a talloc grandchild of
5479 * fsp. When we close_file(fsp), it would go with it. No chance to
5482 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5484 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5485 if (NT_STATUS_IS_OK(status)) {
5486 reply_outbuf(smbreq, 0, 0);
5488 reply_nterror(smbreq, status);
5490 if (!srv_send_smb(smbreq->xconn,
5491 (char *)smbreq->outbuf,
5494 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5496 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5499 TALLOC_FREE(smbreq);
5502 /****************************************************************************
5503 Reply to a writeclose (Core+ protocol).
5504 ****************************************************************************/
5506 void reply_writeclose(struct smb_request *req)
5508 connection_struct *conn = req->conn;
5511 ssize_t nwritten = -1;
5512 NTSTATUS close_status = NT_STATUS_OK;
5515 struct timespec mtime;
5517 struct lock_struct lock;
5519 START_PROFILE(SMBwriteclose);
5522 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5523 END_PROFILE(SMBwriteclose);
5527 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5529 if (!check_fsp(conn, req, fsp)) {
5530 END_PROFILE(SMBwriteclose);
5533 if (!CHECK_WRITE(fsp)) {
5534 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5535 END_PROFILE(SMBwriteclose);
5539 numtowrite = SVAL(req->vwv+1, 0);
5540 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5541 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5542 data = (const char *)req->buf + 1;
5545 * Ensure client isn't asking us to write more than
5546 * they sent. CVE-2017-12163.
5548 remaining = smbreq_bufrem(req, data);
5549 if (numtowrite > remaining) {
5550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5551 END_PROFILE(SMBwriteclose);
5555 if (fsp->print_file == NULL) {
5556 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5557 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5560 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5561 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5562 END_PROFILE(SMBwriteclose);
5567 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5569 set_close_write_time(fsp, mtime);
5572 * More insanity. W2K only closes the file if writelen > 0.
5576 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5577 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5578 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5581 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5582 "file %s\n", fsp_str_dbg(fsp)));
5583 close_status = close_file(req, fsp, NORMAL_CLOSE);
5587 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5588 reply_nterror(req, NT_STATUS_DISK_FULL);
5592 if(!NT_STATUS_IS_OK(close_status)) {
5593 reply_nterror(req, close_status);
5597 reply_outbuf(req, 1, 0);
5599 SSVAL(req->outbuf,smb_vwv0,nwritten);
5603 END_PROFILE(SMBwriteclose);
5608 #define DBGC_CLASS DBGC_LOCKING
5610 /****************************************************************************
5612 ****************************************************************************/
5614 void reply_lock(struct smb_request *req)
5616 connection_struct *conn = req->conn;
5617 uint64_t count,offset;
5620 struct byte_range_lock *br_lck = NULL;
5622 START_PROFILE(SMBlock);
5625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5626 END_PROFILE(SMBlock);
5630 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5632 if (!check_fsp(conn, req, fsp)) {
5633 END_PROFILE(SMBlock);
5637 count = (uint64_t)IVAL(req->vwv+1, 0);
5638 offset = (uint64_t)IVAL(req->vwv+3, 0);
5640 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5641 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5643 br_lck = do_lock(req->sconn->msg_ctx,
5645 (uint64_t)req->smbpid,
5650 False, /* Non-blocking lock. */
5654 TALLOC_FREE(br_lck);
5656 if (NT_STATUS_V(status)) {
5657 reply_nterror(req, status);
5658 END_PROFILE(SMBlock);
5662 reply_outbuf(req, 0, 0);
5664 END_PROFILE(SMBlock);
5668 /****************************************************************************
5670 ****************************************************************************/
5672 void reply_unlock(struct smb_request *req)
5674 connection_struct *conn = req->conn;
5675 uint64_t count,offset;
5679 START_PROFILE(SMBunlock);
5682 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5683 END_PROFILE(SMBunlock);
5687 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5689 if (!check_fsp(conn, req, fsp)) {
5690 END_PROFILE(SMBunlock);
5694 count = (uint64_t)IVAL(req->vwv+1, 0);
5695 offset = (uint64_t)IVAL(req->vwv+3, 0);
5697 status = do_unlock(req->sconn->msg_ctx,
5699 (uint64_t)req->smbpid,
5704 if (NT_STATUS_V(status)) {
5705 reply_nterror(req, status);
5706 END_PROFILE(SMBunlock);
5710 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5711 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5713 reply_outbuf(req, 0, 0);
5715 END_PROFILE(SMBunlock);
5720 #define DBGC_CLASS DBGC_ALL
5722 /****************************************************************************
5724 conn POINTER CAN BE NULL HERE !
5725 ****************************************************************************/
5727 void reply_tdis(struct smb_request *req)
5730 connection_struct *conn = req->conn;
5731 struct smbXsrv_tcon *tcon;
5733 START_PROFILE(SMBtdis);
5736 DEBUG(4,("Invalid connection in tdis\n"));
5737 reply_force_doserror(req, ERRSRV, ERRinvnid);
5738 END_PROFILE(SMBtdis);
5746 * TODO: cancel all outstanding requests on the tcon
5748 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5749 if (!NT_STATUS_IS_OK(status)) {
5750 DEBUG(0, ("reply_tdis: "
5751 "smbXsrv_tcon_disconnect() failed: %s\n",
5752 nt_errstr(status)));
5754 * If we hit this case, there is something completely
5755 * wrong, so we better disconnect the transport connection.
5757 END_PROFILE(SMBtdis);
5758 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5764 reply_outbuf(req, 0, 0);
5765 END_PROFILE(SMBtdis);
5769 /****************************************************************************
5771 conn POINTER CAN BE NULL HERE !
5772 ****************************************************************************/
5774 void reply_echo(struct smb_request *req)
5776 connection_struct *conn = req->conn;
5777 struct smb_perfcount_data local_pcd;
5778 struct smb_perfcount_data *cur_pcd;
5782 START_PROFILE(SMBecho);
5784 smb_init_perfcount_data(&local_pcd);
5787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5788 END_PROFILE(SMBecho);
5792 smb_reverb = SVAL(req->vwv+0, 0);
5794 reply_outbuf(req, 1, req->buflen);
5796 /* copy any incoming data back out */
5797 if (req->buflen > 0) {
5798 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5801 if (smb_reverb > 100) {
5802 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5806 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5808 /* this makes sure we catch the request pcd */
5809 if (seq_num == smb_reverb) {
5810 cur_pcd = &req->pcd;
5812 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5813 cur_pcd = &local_pcd;
5816 SSVAL(req->outbuf,smb_vwv0,seq_num);
5818 show_msg((char *)req->outbuf);
5819 if (!srv_send_smb(req->xconn,
5820 (char *)req->outbuf,
5821 true, req->seqnum+1,
5822 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5824 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5827 DEBUG(3,("echo %d times\n", smb_reverb));
5829 TALLOC_FREE(req->outbuf);
5831 END_PROFILE(SMBecho);
5835 /****************************************************************************
5836 Reply to a printopen.
5837 ****************************************************************************/
5839 void reply_printopen(struct smb_request *req)
5841 connection_struct *conn = req->conn;
5845 START_PROFILE(SMBsplopen);
5848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5849 END_PROFILE(SMBsplopen);
5853 if (!CAN_PRINT(conn)) {
5854 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5855 END_PROFILE(SMBsplopen);
5859 status = file_new(req, conn, &fsp);
5860 if(!NT_STATUS_IS_OK(status)) {
5861 reply_nterror(req, status);
5862 END_PROFILE(SMBsplopen);
5866 /* Open for exclusive use, write only. */
5867 status = print_spool_open(fsp, NULL, req->vuid);
5869 if (!NT_STATUS_IS_OK(status)) {
5870 file_free(req, fsp);
5871 reply_nterror(req, status);
5872 END_PROFILE(SMBsplopen);
5876 reply_outbuf(req, 1, 0);
5877 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5879 DEBUG(3,("openprint fd=%d %s\n",
5880 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5882 END_PROFILE(SMBsplopen);
5886 /****************************************************************************
5887 Reply to a printclose.
5888 ****************************************************************************/
5890 void reply_printclose(struct smb_request *req)
5892 connection_struct *conn = req->conn;
5896 START_PROFILE(SMBsplclose);
5899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5900 END_PROFILE(SMBsplclose);
5904 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5906 if (!check_fsp(conn, req, fsp)) {
5907 END_PROFILE(SMBsplclose);
5911 if (!CAN_PRINT(conn)) {
5912 reply_force_doserror(req, ERRSRV, ERRerror);
5913 END_PROFILE(SMBsplclose);
5917 DEBUG(3,("printclose fd=%d %s\n",
5918 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5920 status = close_file(req, fsp, NORMAL_CLOSE);
5922 if(!NT_STATUS_IS_OK(status)) {
5923 reply_nterror(req, status);
5924 END_PROFILE(SMBsplclose);
5928 reply_outbuf(req, 0, 0);
5930 END_PROFILE(SMBsplclose);
5934 /****************************************************************************
5935 Reply to a printqueue.
5936 ****************************************************************************/
5938 void reply_printqueue(struct smb_request *req)
5940 connection_struct *conn = req->conn;
5944 START_PROFILE(SMBsplretq);
5947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5948 END_PROFILE(SMBsplretq);
5952 max_count = SVAL(req->vwv+0, 0);
5953 start_index = SVAL(req->vwv+1, 0);
5955 /* we used to allow the client to get the cnum wrong, but that
5956 is really quite gross and only worked when there was only
5957 one printer - I think we should now only accept it if they
5958 get it right (tridge) */
5959 if (!CAN_PRINT(conn)) {
5960 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5961 END_PROFILE(SMBsplretq);
5965 reply_outbuf(req, 2, 3);
5966 SSVAL(req->outbuf,smb_vwv0,0);
5967 SSVAL(req->outbuf,smb_vwv1,0);
5968 SCVAL(smb_buf(req->outbuf),0,1);
5969 SSVAL(smb_buf(req->outbuf),1,0);
5971 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5972 start_index, max_count));
5975 TALLOC_CTX *mem_ctx = talloc_tos();
5978 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5979 struct rpc_pipe_client *cli = NULL;
5980 struct dcerpc_binding_handle *b = NULL;
5981 struct policy_handle handle;
5982 struct spoolss_DevmodeContainer devmode_ctr;
5983 union spoolss_JobInfo *info;
5985 uint32_t num_to_get;
5989 ZERO_STRUCT(handle);
5991 status = rpc_pipe_open_interface(mem_ctx,
5994 conn->sconn->remote_address,
5995 conn->sconn->local_address,
5996 conn->sconn->msg_ctx,
5998 if (!NT_STATUS_IS_OK(status)) {
5999 DEBUG(0, ("reply_printqueue: "
6000 "could not connect to spoolss: %s\n",
6001 nt_errstr(status)));
6002 reply_nterror(req, status);
6005 b = cli->binding_handle;
6007 ZERO_STRUCT(devmode_ctr);
6009 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6012 SEC_FLAG_MAXIMUM_ALLOWED,
6015 if (!NT_STATUS_IS_OK(status)) {
6016 reply_nterror(req, status);
6019 if (!W_ERROR_IS_OK(werr)) {
6020 reply_nterror(req, werror_to_ntstatus(werr));
6024 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6032 if (!W_ERROR_IS_OK(werr)) {
6033 reply_nterror(req, werror_to_ntstatus(werr));
6037 if (max_count > 0) {
6038 first = start_index;
6040 first = start_index + max_count + 1;
6043 if (first >= count) {
6046 num_to_get = first + MIN(ABS(max_count), count - first);
6049 for (i = first; i < num_to_get; i++) {
6052 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6055 uint16_t qrapjobid = pjobid_to_rap(sharename,
6056 info[i].info2.job_id);
6058 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6064 srv_put_dos_date2(p, 0, qtime);
6065 SCVAL(p, 4, qstatus);
6066 SSVAL(p, 5, qrapjobid);
6067 SIVAL(p, 7, info[i].info2.size);
6069 status = srvstr_push(blob, req->flags2, p+12,
6070 info[i].info2.notify_name, 16, STR_ASCII, &len);
6071 if (!NT_STATUS_IS_OK(status)) {
6072 reply_nterror(req, status);
6075 if (message_push_blob(
6078 blob, sizeof(blob))) == -1) {
6079 reply_nterror(req, NT_STATUS_NO_MEMORY);
6085 SSVAL(req->outbuf,smb_vwv0,count);
6086 SSVAL(req->outbuf,smb_vwv1,
6087 (max_count>0?first+count:first-1));
6088 SCVAL(smb_buf(req->outbuf),0,1);
6089 SSVAL(smb_buf(req->outbuf),1,28*count);
6093 DEBUG(3, ("%u entries returned in queue\n",
6097 if (b && is_valid_policy_hnd(&handle)) {
6098 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6103 END_PROFILE(SMBsplretq);
6107 /****************************************************************************
6108 Reply to a printwrite.
6109 ****************************************************************************/
6111 void reply_printwrite(struct smb_request *req)
6113 connection_struct *conn = req->conn;
6118 START_PROFILE(SMBsplwr);
6121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6122 END_PROFILE(SMBsplwr);
6126 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6128 if (!check_fsp(conn, req, fsp)) {
6129 END_PROFILE(SMBsplwr);
6133 if (!fsp->print_file) {
6134 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6135 END_PROFILE(SMBsplwr);
6139 if (!CHECK_WRITE(fsp)) {
6140 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6141 END_PROFILE(SMBsplwr);
6145 numtowrite = SVAL(req->buf, 1);
6148 * This already protects us against CVE-2017-12163.
6150 if (req->buflen < numtowrite + 3) {
6151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6152 END_PROFILE(SMBsplwr);
6156 data = (const char *)req->buf + 3;
6158 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6159 reply_nterror(req, map_nt_error_from_unix(errno));
6160 END_PROFILE(SMBsplwr);
6164 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6166 END_PROFILE(SMBsplwr);
6170 /****************************************************************************
6172 ****************************************************************************/
6174 void reply_mkdir(struct smb_request *req)
6176 connection_struct *conn = req->conn;
6177 struct smb_filename *smb_dname = NULL;
6178 char *directory = NULL;
6181 TALLOC_CTX *ctx = talloc_tos();
6183 START_PROFILE(SMBmkdir);
6185 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6186 STR_TERMINATE, &status);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 reply_nterror(req, status);
6192 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6193 status = filename_convert(ctx, conn,
6199 if (!NT_STATUS_IS_OK(status)) {
6200 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6201 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6202 ERRSRV, ERRbadpath);
6205 reply_nterror(req, status);
6209 status = create_directory(conn, req, smb_dname);
6211 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6213 if (!NT_STATUS_IS_OK(status)) {
6215 if (!use_nt_status()
6216 && NT_STATUS_EQUAL(status,
6217 NT_STATUS_OBJECT_NAME_COLLISION)) {
6219 * Yes, in the DOS error code case we get a
6220 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6221 * samba4 torture test.
6223 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6226 reply_nterror(req, status);
6230 reply_outbuf(req, 0, 0);
6232 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6234 TALLOC_FREE(smb_dname);
6235 END_PROFILE(SMBmkdir);
6239 /****************************************************************************
6241 ****************************************************************************/
6243 void reply_rmdir(struct smb_request *req)
6245 connection_struct *conn = req->conn;
6246 struct smb_filename *smb_dname = NULL;
6247 char *directory = NULL;
6249 TALLOC_CTX *ctx = talloc_tos();
6250 files_struct *fsp = NULL;
6252 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6253 struct smbd_server_connection *sconn = req->sconn;
6255 START_PROFILE(SMBrmdir);
6257 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6258 STR_TERMINATE, &status);
6259 if (!NT_STATUS_IS_OK(status)) {
6260 reply_nterror(req, status);
6264 status = filename_convert(ctx, conn,
6270 if (!NT_STATUS_IS_OK(status)) {
6271 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6272 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6273 ERRSRV, ERRbadpath);
6276 reply_nterror(req, status);
6280 if (is_ntfs_stream_smb_fname(smb_dname)) {
6281 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6285 status = SMB_VFS_CREATE_FILE(
6288 0, /* root_dir_fid */
6289 smb_dname, /* fname */
6290 DELETE_ACCESS, /* access_mask */
6291 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6293 FILE_OPEN, /* create_disposition*/
6294 FILE_DIRECTORY_FILE, /* create_options */
6295 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6296 0, /* oplock_request */
6298 0, /* allocation_size */
6299 0, /* private_flags */
6304 NULL, NULL); /* create context */
6306 if (!NT_STATUS_IS_OK(status)) {
6307 if (open_was_deferred(req->xconn, req->mid)) {
6308 /* We have re-scheduled this call. */
6311 reply_nterror(req, status);
6315 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6316 if (!NT_STATUS_IS_OK(status)) {
6317 close_file(req, fsp, ERROR_CLOSE);
6318 reply_nterror(req, status);
6322 if (!set_delete_on_close(fsp, true,
6323 conn->session_info->security_token,
6324 conn->session_info->unix_token)) {
6325 close_file(req, fsp, ERROR_CLOSE);
6326 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6330 status = close_file(req, fsp, NORMAL_CLOSE);
6331 if (!NT_STATUS_IS_OK(status)) {
6332 reply_nterror(req, status);
6334 reply_outbuf(req, 0, 0);
6337 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6339 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6341 TALLOC_FREE(smb_dname);
6342 END_PROFILE(SMBrmdir);
6346 /*******************************************************************
6347 Resolve wildcards in a filename rename.
6348 ********************************************************************/
6350 static bool resolve_wildcards(TALLOC_CTX *ctx,
6355 char *name2_copy = NULL;
6360 char *p,*p2, *pname1, *pname2;
6362 name2_copy = talloc_strdup(ctx, name2);
6367 pname1 = strrchr_m(name1,'/');
6368 pname2 = strrchr_m(name2_copy,'/');
6370 if (!pname1 || !pname2) {
6374 /* Truncate the copy of name2 at the last '/' */
6377 /* Now go past the '/' */
6381 root1 = talloc_strdup(ctx, pname1);
6382 root2 = talloc_strdup(ctx, pname2);
6384 if (!root1 || !root2) {
6388 p = strrchr_m(root1,'.');
6391 ext1 = talloc_strdup(ctx, p+1);
6393 ext1 = talloc_strdup(ctx, "");
6395 p = strrchr_m(root2,'.');
6398 ext2 = talloc_strdup(ctx, p+1);
6400 ext2 = talloc_strdup(ctx, "");
6403 if (!ext1 || !ext2) {
6411 /* Hmmm. Should this be mb-aware ? */
6414 } else if (*p2 == '*') {
6416 root2 = talloc_asprintf(ctx, "%s%s",
6435 /* Hmmm. Should this be mb-aware ? */
6438 } else if (*p2 == '*') {
6440 ext2 = talloc_asprintf(ctx, "%s%s",
6456 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6461 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6473 /****************************************************************************
6474 Ensure open files have their names updated. Updated to notify other smbd's
6476 ****************************************************************************/
6478 static void rename_open_files(connection_struct *conn,
6479 struct share_mode_lock *lck,
6481 uint32_t orig_name_hash,
6482 const struct smb_filename *smb_fname_dst)
6485 bool did_rename = False;
6487 uint32_t new_name_hash = 0;
6489 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6490 fsp = file_find_di_next(fsp)) {
6491 /* fsp_name is a relative path under the fsp. To change this for other
6492 sharepaths we need to manipulate relative paths. */
6493 /* TODO - create the absolute path and manipulate the newname
6494 relative to the sharepath. */
6495 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6498 if (fsp->name_hash != orig_name_hash) {
6501 DEBUG(10, ("rename_open_files: renaming file %s "
6502 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6503 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6504 smb_fname_str_dbg(smb_fname_dst)));
6506 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6507 if (NT_STATUS_IS_OK(status)) {
6509 new_name_hash = fsp->name_hash;
6514 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6515 "for %s\n", file_id_string_tos(&id),
6516 smb_fname_str_dbg(smb_fname_dst)));
6519 /* Send messages to all smbd's (not ourself) that the name has changed. */
6520 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6521 orig_name_hash, new_name_hash,
6526 /****************************************************************************
6527 We need to check if the source path is a parent directory of the destination
6528 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6529 refuse the rename with a sharing violation. Under UNIX the above call can
6530 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6531 probably need to check that the client is a Windows one before disallowing
6532 this as a UNIX client (one with UNIX extensions) can know the source is a
6533 symlink and make this decision intelligently. Found by an excellent bug
6534 report from <AndyLiebman@aol.com>.
6535 ****************************************************************************/
6537 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6538 const struct smb_filename *smb_fname_dst)
6540 const char *psrc = smb_fname_src->base_name;
6541 const char *pdst = smb_fname_dst->base_name;
6544 if (psrc[0] == '.' && psrc[1] == '/') {
6547 if (pdst[0] == '.' && pdst[1] == '/') {
6550 if ((slen = strlen(psrc)) > strlen(pdst)) {
6553 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6557 * Do the notify calls from a rename
6560 static void notify_rename(connection_struct *conn, bool is_dir,
6561 const struct smb_filename *smb_fname_src,
6562 const struct smb_filename *smb_fname_dst)
6564 char *parent_dir_src = NULL;
6565 char *parent_dir_dst = NULL;
6568 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6569 : FILE_NOTIFY_CHANGE_FILE_NAME;
6571 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6572 &parent_dir_src, NULL) ||
6573 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6574 &parent_dir_dst, NULL)) {
6578 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6579 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6580 smb_fname_src->base_name);
6581 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6582 smb_fname_dst->base_name);
6585 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6586 smb_fname_src->base_name);
6587 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6588 smb_fname_dst->base_name);
6591 /* this is a strange one. w2k3 gives an additional event for
6592 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6593 files, but not directories */
6595 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6596 FILE_NOTIFY_CHANGE_ATTRIBUTES
6597 |FILE_NOTIFY_CHANGE_CREATION,
6598 smb_fname_dst->base_name);
6601 TALLOC_FREE(parent_dir_src);
6602 TALLOC_FREE(parent_dir_dst);
6605 /****************************************************************************
6606 Returns an error if the parent directory for a filename is open in an
6608 ****************************************************************************/
6610 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6611 const struct smb_filename *smb_fname_dst_in)
6613 char *parent_dir = NULL;
6614 struct smb_filename smb_fname_parent;
6616 files_struct *fsp = NULL;
6619 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6620 &parent_dir, NULL)) {
6621 return NT_STATUS_NO_MEMORY;
6623 ZERO_STRUCT(smb_fname_parent);
6624 smb_fname_parent.base_name = parent_dir;
6626 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6628 return map_nt_error_from_unix(errno);
6632 * We're only checking on this smbd here, mostly good
6633 * enough.. and will pass tests.
6636 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6637 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6638 fsp = file_find_di_next(fsp)) {
6639 if (fsp->access_mask & DELETE_ACCESS) {
6640 return NT_STATUS_SHARING_VIOLATION;
6643 return NT_STATUS_OK;
6646 /****************************************************************************
6647 Rename an open file - given an fsp.
6648 ****************************************************************************/
6650 NTSTATUS rename_internals_fsp(connection_struct *conn,
6652 const struct smb_filename *smb_fname_dst_in,
6654 bool replace_if_exists)
6656 TALLOC_CTX *ctx = talloc_tos();
6657 struct smb_filename *smb_fname_dst = NULL;
6658 NTSTATUS status = NT_STATUS_OK;
6659 struct share_mode_lock *lck = NULL;
6660 uint32_t access_mask = SEC_DIR_ADD_FILE;
6661 bool dst_exists, old_is_stream, new_is_stream;
6663 status = check_name(conn, smb_fname_dst_in);
6664 if (!NT_STATUS_IS_OK(status)) {
6668 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6669 if (!NT_STATUS_IS_OK(status)) {
6673 if (file_has_open_streams(fsp)) {
6674 return NT_STATUS_ACCESS_DENIED;
6677 /* Make a copy of the dst smb_fname structs */
6679 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6680 if (smb_fname_dst == NULL) {
6681 status = NT_STATUS_NO_MEMORY;
6686 * Check for special case with case preserving and not
6687 * case sensitive. If the new last component differs from the original
6688 * last component only by case, then we should allow
6689 * the rename (user is trying to change the case of the
6692 if (!conn->case_sensitive && conn->case_preserve &&
6693 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6694 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6695 char *fname_dst_parent = NULL;
6696 const char *fname_dst_lcomp = NULL;
6697 char *orig_lcomp_path = NULL;
6698 char *orig_lcomp_stream = NULL;
6702 * Split off the last component of the processed
6703 * destination name. We will compare this to
6704 * the split components of smb_fname_dst->original_lcomp.
6706 if (!parent_dirname(ctx,
6707 smb_fname_dst->base_name,
6709 &fname_dst_lcomp)) {
6710 status = NT_STATUS_NO_MEMORY;
6715 * The original_lcomp component contains
6716 * the last_component of the path + stream
6717 * name (if a stream exists).
6719 * Split off the stream name so we
6720 * can check them separately.
6723 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6724 /* POSIX - no stream component. */
6725 orig_lcomp_path = talloc_strdup(ctx,
6726 smb_fname_dst->original_lcomp);
6727 if (orig_lcomp_path == NULL) {
6731 ok = split_stream_filename(ctx,
6732 smb_fname_dst->original_lcomp,
6734 &orig_lcomp_stream);
6738 TALLOC_FREE(fname_dst_parent);
6739 status = NT_STATUS_NO_MEMORY;
6743 /* If the base names only differ by case, use original. */
6744 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6747 * Replace the modified last component with the
6750 if (!ISDOT(fname_dst_parent)) {
6751 tmp = talloc_asprintf(smb_fname_dst,
6756 tmp = talloc_strdup(smb_fname_dst,
6760 status = NT_STATUS_NO_MEMORY;
6761 TALLOC_FREE(fname_dst_parent);
6762 TALLOC_FREE(orig_lcomp_path);
6763 TALLOC_FREE(orig_lcomp_stream);
6766 TALLOC_FREE(smb_fname_dst->base_name);
6767 smb_fname_dst->base_name = tmp;
6770 /* If the stream_names only differ by case, use original. */
6771 if(!strcsequal(smb_fname_dst->stream_name,
6772 orig_lcomp_stream)) {
6773 /* Use the original stream. */
6774 char *tmp = talloc_strdup(smb_fname_dst,
6777 status = NT_STATUS_NO_MEMORY;
6778 TALLOC_FREE(fname_dst_parent);
6779 TALLOC_FREE(orig_lcomp_path);
6780 TALLOC_FREE(orig_lcomp_stream);
6783 TALLOC_FREE(smb_fname_dst->stream_name);
6784 smb_fname_dst->stream_name = tmp;
6786 TALLOC_FREE(fname_dst_parent);
6787 TALLOC_FREE(orig_lcomp_path);
6788 TALLOC_FREE(orig_lcomp_stream);
6792 * If the src and dest names are identical - including case,
6793 * don't do the rename, just return success.
6796 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6797 strcsequal(fsp->fsp_name->stream_name,
6798 smb_fname_dst->stream_name)) {
6799 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6800 "- returning success\n",
6801 smb_fname_str_dbg(smb_fname_dst)));
6802 status = NT_STATUS_OK;
6806 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6807 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6809 /* Return the correct error code if both names aren't streams. */
6810 if (!old_is_stream && new_is_stream) {
6811 status = NT_STATUS_OBJECT_NAME_INVALID;
6815 if (old_is_stream && !new_is_stream) {
6816 status = NT_STATUS_INVALID_PARAMETER;
6820 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6822 if(!replace_if_exists && dst_exists) {
6823 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6824 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6825 smb_fname_str_dbg(smb_fname_dst)));
6826 status = NT_STATUS_OBJECT_NAME_COLLISION;
6831 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6832 &smb_fname_dst->st);
6833 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6835 /* The file can be open when renaming a stream */
6836 if (dst_fsp && !new_is_stream) {
6837 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6838 status = NT_STATUS_ACCESS_DENIED;
6843 /* Ensure we have a valid stat struct for the source. */
6844 status = vfs_stat_fsp(fsp);
6845 if (!NT_STATUS_IS_OK(status)) {
6849 status = can_rename(conn, fsp, attrs);
6851 if (!NT_STATUS_IS_OK(status)) {
6852 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6853 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6854 smb_fname_str_dbg(smb_fname_dst)));
6855 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6856 status = NT_STATUS_ACCESS_DENIED;
6860 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6861 status = NT_STATUS_ACCESS_DENIED;
6865 /* Do we have rights to move into the destination ? */
6866 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6867 /* We're moving a directory. */
6868 access_mask = SEC_DIR_ADD_SUBDIR;
6870 status = check_parent_access(conn,
6873 if (!NT_STATUS_IS_OK(status)) {
6874 DBG_INFO("check_parent_access on "
6875 "dst %s returned %s\n",
6876 smb_fname_str_dbg(smb_fname_dst),
6881 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6884 * We have the file open ourselves, so not being able to get the
6885 * corresponding share mode lock is a fatal error.
6888 SMB_ASSERT(lck != NULL);
6890 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6891 uint32_t create_options = fsp->fh->private_options;
6893 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6894 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6895 smb_fname_str_dbg(smb_fname_dst)));
6897 if (!fsp->is_directory &&
6898 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6899 (lp_map_archive(SNUM(conn)) ||
6900 lp_store_dos_attributes(SNUM(conn)))) {
6901 /* We must set the archive bit on the newly
6903 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6904 uint32_t old_dosmode = dos_mode(conn,
6906 file_set_dosmode(conn,
6908 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6914 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6917 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6921 * A rename acts as a new file create w.r.t. allowing an initial delete
6922 * on close, probably because in Windows there is a new handle to the
6923 * new file. If initial delete on close was requested but not
6924 * originally set, we need to set it here. This is probably not 100% correct,
6925 * but will work for the CIFSFS client which in non-posix mode
6926 * depends on these semantics. JRA.
6929 if (create_options & FILE_DELETE_ON_CLOSE) {
6930 status = can_set_delete_on_close(fsp, 0);
6932 if (NT_STATUS_IS_OK(status)) {
6933 /* Note that here we set the *initial* delete on close flag,
6934 * not the regular one. The magic gets handled in close. */
6935 fsp->initial_delete_on_close = True;
6939 status = NT_STATUS_OK;
6945 if (errno == ENOTDIR || errno == EISDIR) {
6946 status = NT_STATUS_OBJECT_NAME_COLLISION;
6948 status = map_nt_error_from_unix(errno);
6951 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6952 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6953 smb_fname_str_dbg(smb_fname_dst)));
6956 TALLOC_FREE(smb_fname_dst);
6961 /****************************************************************************
6962 The guts of the rename command, split out so it may be called by the NT SMB
6964 ****************************************************************************/
6966 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6967 connection_struct *conn,
6968 struct smb_request *req,
6969 struct smb_filename *smb_fname_src,
6970 struct smb_filename *smb_fname_dst,
6972 bool replace_if_exists,
6975 uint32_t access_mask)
6977 char *fname_src_dir = NULL;
6978 struct smb_filename *smb_fname_src_dir = NULL;
6979 char *fname_src_mask = NULL;
6981 NTSTATUS status = NT_STATUS_OK;
6982 struct smb_Dir *dir_hnd = NULL;
6983 const char *dname = NULL;
6984 char *talloced = NULL;
6986 int create_options = 0;
6987 bool posix_pathnames = (req != NULL && req->posix_pathnames);
6991 * Split the old name into directory and last component
6992 * strings. Note that unix_convert may have stripped off a
6993 * leading ./ from both name and newname if the rename is
6994 * at the root of the share. We need to make sure either both
6995 * name and newname contain a / character or neither of them do
6996 * as this is checked in resolve_wildcards().
6999 /* Split up the directory from the filename/mask. */
7000 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7001 &fname_src_dir, &fname_src_mask);
7002 if (!NT_STATUS_IS_OK(status)) {
7003 status = NT_STATUS_NO_MEMORY;
7008 * We should only check the mangled cache
7009 * here if unix_convert failed. This means
7010 * that the path in 'mask' doesn't exist
7011 * on the file system and so we need to look
7012 * for a possible mangle. This patch from
7013 * Tine Smukavec <valentin.smukavec@hermes.si>.
7016 if (!VALID_STAT(smb_fname_src->st) &&
7017 mangle_is_mangled(fname_src_mask, conn->params)) {
7018 char *new_mask = NULL;
7019 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7022 TALLOC_FREE(fname_src_mask);
7023 fname_src_mask = new_mask;
7027 if (!src_has_wild) {
7031 * Only one file needs to be renamed. Append the mask back
7032 * onto the directory.
7034 TALLOC_FREE(smb_fname_src->base_name);
7035 if (ISDOT(fname_src_dir)) {
7036 /* Ensure we use canonical names on open. */
7037 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7041 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7046 if (!smb_fname_src->base_name) {
7047 status = NT_STATUS_NO_MEMORY;
7051 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7052 "case_preserve = %d, short case preserve = %d, "
7053 "directory = %s, newname = %s, "
7054 "last_component_dest = %s\n",
7055 conn->case_sensitive, conn->case_preserve,
7056 conn->short_case_preserve,
7057 smb_fname_str_dbg(smb_fname_src),
7058 smb_fname_str_dbg(smb_fname_dst),
7059 smb_fname_dst->original_lcomp));
7061 /* The dest name still may have wildcards. */
7062 if (dest_has_wild) {
7063 char *fname_dst_mod = NULL;
7064 if (!resolve_wildcards(smb_fname_dst,
7065 smb_fname_src->base_name,
7066 smb_fname_dst->base_name,
7068 DEBUG(6, ("rename_internals: resolve_wildcards "
7070 smb_fname_src->base_name,
7071 smb_fname_dst->base_name));
7072 status = NT_STATUS_NO_MEMORY;
7075 TALLOC_FREE(smb_fname_dst->base_name);
7076 smb_fname_dst->base_name = fname_dst_mod;
7079 ZERO_STRUCT(smb_fname_src->st);
7080 if (posix_pathnames) {
7081 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7083 rc = SMB_VFS_STAT(conn, smb_fname_src);
7086 status = map_nt_error_from_unix_common(errno);
7090 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7091 create_options |= FILE_DIRECTORY_FILE;
7094 status = SMB_VFS_CREATE_FILE(
7097 0, /* root_dir_fid */
7098 smb_fname_src, /* fname */
7099 access_mask, /* access_mask */
7100 (FILE_SHARE_READ | /* share_access */
7102 FILE_OPEN, /* create_disposition*/
7103 create_options, /* create_options */
7104 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7105 0, /* oplock_request */
7107 0, /* allocation_size */
7108 0, /* private_flags */
7113 NULL, NULL); /* create context */
7115 if (!NT_STATUS_IS_OK(status)) {
7116 DEBUG(3, ("Could not open rename source %s: %s\n",
7117 smb_fname_str_dbg(smb_fname_src),
7118 nt_errstr(status)));
7122 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7123 attrs, replace_if_exists);
7125 close_file(req, fsp, NORMAL_CLOSE);
7127 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7128 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7129 smb_fname_str_dbg(smb_fname_dst)));
7135 * Wildcards - process each file that matches.
7137 if (strequal(fname_src_mask, "????????.???")) {
7138 TALLOC_FREE(fname_src_mask);
7139 fname_src_mask = talloc_strdup(ctx, "*");
7140 if (!fname_src_mask) {
7141 status = NT_STATUS_NO_MEMORY;
7146 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7150 smb_fname_src->flags);
7151 if (smb_fname_src_dir == NULL) {
7152 status = NT_STATUS_NO_MEMORY;
7156 status = check_name(conn, smb_fname_src_dir);
7157 if (!NT_STATUS_IS_OK(status)) {
7161 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7163 if (dir_hnd == NULL) {
7164 status = map_nt_error_from_unix(errno);
7168 status = NT_STATUS_NO_SUCH_FILE;
7170 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7171 * - gentest fix. JRA
7174 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7176 files_struct *fsp = NULL;
7177 char *destname = NULL;
7178 bool sysdir_entry = False;
7180 /* Quick check for "." and ".." */
7181 if (ISDOT(dname) || ISDOTDOT(dname)) {
7182 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7183 sysdir_entry = True;
7185 TALLOC_FREE(talloced);
7190 if (!is_visible_file(conn, fname_src_dir, dname,
7191 &smb_fname_src->st, false)) {
7192 TALLOC_FREE(talloced);
7196 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7197 TALLOC_FREE(talloced);
7202 status = NT_STATUS_OBJECT_NAME_INVALID;
7206 TALLOC_FREE(smb_fname_src->base_name);
7207 if (ISDOT(fname_src_dir)) {
7208 /* Ensure we use canonical names on open. */
7209 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7213 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7218 if (!smb_fname_src->base_name) {
7219 status = NT_STATUS_NO_MEMORY;
7223 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7224 smb_fname_dst->base_name,
7226 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7227 smb_fname_src->base_name, destname));
7228 TALLOC_FREE(talloced);
7232 status = NT_STATUS_NO_MEMORY;
7236 TALLOC_FREE(smb_fname_dst->base_name);
7237 smb_fname_dst->base_name = destname;
7239 ZERO_STRUCT(smb_fname_src->st);
7240 if (posix_pathnames) {
7241 SMB_VFS_LSTAT(conn, smb_fname_src);
7243 SMB_VFS_STAT(conn, smb_fname_src);
7248 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7249 create_options |= FILE_DIRECTORY_FILE;
7252 status = SMB_VFS_CREATE_FILE(
7255 0, /* root_dir_fid */
7256 smb_fname_src, /* fname */
7257 access_mask, /* access_mask */
7258 (FILE_SHARE_READ | /* share_access */
7260 FILE_OPEN, /* create_disposition*/
7261 create_options, /* create_options */
7262 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7263 0, /* oplock_request */
7265 0, /* allocation_size */
7266 0, /* private_flags */
7271 NULL, NULL); /* create context */
7273 if (!NT_STATUS_IS_OK(status)) {
7274 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7275 "returned %s rename %s -> %s\n",
7277 smb_fname_str_dbg(smb_fname_src),
7278 smb_fname_str_dbg(smb_fname_dst)));
7282 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7284 if (!smb_fname_dst->original_lcomp) {
7285 status = NT_STATUS_NO_MEMORY;
7289 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7290 attrs, replace_if_exists);
7292 close_file(req, fsp, NORMAL_CLOSE);
7294 if (!NT_STATUS_IS_OK(status)) {
7295 DEBUG(3, ("rename_internals_fsp returned %s for "
7296 "rename %s -> %s\n", nt_errstr(status),
7297 smb_fname_str_dbg(smb_fname_src),
7298 smb_fname_str_dbg(smb_fname_dst)));
7304 DEBUG(3,("rename_internals: doing rename on %s -> "
7305 "%s\n", smb_fname_str_dbg(smb_fname_src),
7306 smb_fname_str_dbg(smb_fname_src)));
7307 TALLOC_FREE(talloced);
7309 TALLOC_FREE(dir_hnd);
7311 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7312 status = map_nt_error_from_unix(errno);
7316 TALLOC_FREE(talloced);
7317 TALLOC_FREE(smb_fname_src_dir);
7318 TALLOC_FREE(fname_src_dir);
7319 TALLOC_FREE(fname_src_mask);
7323 /****************************************************************************
7325 ****************************************************************************/
7327 void reply_mv(struct smb_request *req)
7329 connection_struct *conn = req->conn;
7331 char *newname = NULL;
7335 bool src_has_wcard = False;
7336 bool dest_has_wcard = False;
7337 TALLOC_CTX *ctx = talloc_tos();
7338 struct smb_filename *smb_fname_src = NULL;
7339 struct smb_filename *smb_fname_dst = NULL;
7340 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7341 (req->posix_pathnames ?
7342 UCF_UNIX_NAME_LOOKUP :
7343 UCF_COND_ALLOW_WCARD_LCOMP);
7344 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7346 (req->posix_pathnames ?
7348 UCF_COND_ALLOW_WCARD_LCOMP);
7349 bool stream_rename = false;
7351 START_PROFILE(SMBmv);
7354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7358 attrs = SVAL(req->vwv+0, 0);
7360 p = (const char *)req->buf + 1;
7361 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7362 &status, &src_has_wcard);
7363 if (!NT_STATUS_IS_OK(status)) {
7364 reply_nterror(req, status);
7368 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7369 &status, &dest_has_wcard);
7370 if (!NT_STATUS_IS_OK(status)) {
7371 reply_nterror(req, status);
7375 if (!req->posix_pathnames) {
7376 /* The newname must begin with a ':' if the
7377 name contains a ':'. */
7378 if (strchr_m(name, ':')) {
7379 if (newname[0] != ':') {
7380 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7383 stream_rename = true;
7387 status = filename_convert(ctx,
7395 if (!NT_STATUS_IS_OK(status)) {
7396 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7397 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7398 ERRSRV, ERRbadpath);
7401 reply_nterror(req, status);
7405 status = filename_convert(ctx,
7413 if (!NT_STATUS_IS_OK(status)) {
7414 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7415 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7416 ERRSRV, ERRbadpath);
7419 reply_nterror(req, status);
7423 if (stream_rename) {
7424 /* smb_fname_dst->base_name must be the same as
7425 smb_fname_src->base_name. */
7426 TALLOC_FREE(smb_fname_dst->base_name);
7427 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7428 smb_fname_src->base_name);
7429 if (!smb_fname_dst->base_name) {
7430 reply_nterror(req, NT_STATUS_NO_MEMORY);
7435 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7436 smb_fname_str_dbg(smb_fname_dst)));
7438 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7439 attrs, False, src_has_wcard, dest_has_wcard,
7441 if (!NT_STATUS_IS_OK(status)) {
7442 if (open_was_deferred(req->xconn, req->mid)) {
7443 /* We have re-scheduled this call. */
7446 reply_nterror(req, status);
7450 reply_outbuf(req, 0, 0);
7452 TALLOC_FREE(smb_fname_src);
7453 TALLOC_FREE(smb_fname_dst);
7458 /*******************************************************************
7459 Copy a file as part of a reply_copy.
7460 ******************************************************************/
7463 * TODO: check error codes on all callers
7466 NTSTATUS copy_file(TALLOC_CTX *ctx,
7467 connection_struct *conn,
7468 struct smb_filename *smb_fname_src,
7469 struct smb_filename *smb_fname_dst,
7472 bool target_is_directory)
7474 struct smb_filename *smb_fname_dst_tmp = NULL;
7476 files_struct *fsp1,*fsp2;
7478 uint32_t new_create_disposition;
7482 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7483 if (smb_fname_dst_tmp == NULL) {
7484 return NT_STATUS_NO_MEMORY;
7488 * If the target is a directory, extract the last component from the
7489 * src filename and append it to the dst filename
7491 if (target_is_directory) {
7494 /* dest/target can't be a stream if it's a directory. */
7495 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7497 p = strrchr_m(smb_fname_src->base_name,'/');
7501 p = smb_fname_src->base_name;
7503 smb_fname_dst_tmp->base_name =
7504 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7506 if (!smb_fname_dst_tmp->base_name) {
7507 status = NT_STATUS_NO_MEMORY;
7512 status = vfs_file_exist(conn, smb_fname_src);
7513 if (!NT_STATUS_IS_OK(status)) {
7517 if (!target_is_directory && count) {
7518 new_create_disposition = FILE_OPEN;
7520 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7523 &new_create_disposition,
7526 status = NT_STATUS_INVALID_PARAMETER;
7531 /* Open the src file for reading. */
7532 status = SMB_VFS_CREATE_FILE(
7535 0, /* root_dir_fid */
7536 smb_fname_src, /* fname */
7537 FILE_GENERIC_READ, /* access_mask */
7538 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7539 FILE_OPEN, /* create_disposition*/
7540 0, /* create_options */
7541 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7542 INTERNAL_OPEN_ONLY, /* oplock_request */
7544 0, /* allocation_size */
7545 0, /* private_flags */
7550 NULL, NULL); /* create context */
7552 if (!NT_STATUS_IS_OK(status)) {
7556 dosattrs = dos_mode(conn, smb_fname_src);
7558 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7559 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7562 /* Open the dst file for writing. */
7563 status = SMB_VFS_CREATE_FILE(
7566 0, /* root_dir_fid */
7567 smb_fname_dst, /* fname */
7568 FILE_GENERIC_WRITE, /* access_mask */
7569 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7570 new_create_disposition, /* create_disposition*/
7571 0, /* create_options */
7572 dosattrs, /* file_attributes */
7573 INTERNAL_OPEN_ONLY, /* oplock_request */
7575 0, /* allocation_size */
7576 0, /* private_flags */
7581 NULL, NULL); /* create context */
7583 if (!NT_STATUS_IS_OK(status)) {
7584 close_file(NULL, fsp1, ERROR_CLOSE);
7588 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7589 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7591 DEBUG(0, ("error - vfs lseek returned error %s\n",
7593 status = map_nt_error_from_unix(errno);
7594 close_file(NULL, fsp1, ERROR_CLOSE);
7595 close_file(NULL, fsp2, ERROR_CLOSE);
7600 /* Do the actual copy. */
7601 if (smb_fname_src->st.st_ex_size) {
7602 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7607 close_file(NULL, fsp1, NORMAL_CLOSE);
7609 /* Ensure the modtime is set correctly on the destination file. */
7610 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7613 * As we are opening fsp1 read-only we only expect
7614 * an error on close on fsp2 if we are out of space.
7615 * Thus we don't look at the error return from the
7618 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7620 if (!NT_STATUS_IS_OK(status)) {
7624 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7625 status = NT_STATUS_DISK_FULL;
7629 status = NT_STATUS_OK;
7632 TALLOC_FREE(smb_fname_dst_tmp);
7636 /****************************************************************************
7637 Reply to a file copy.
7638 ****************************************************************************/
7640 void reply_copy(struct smb_request *req)
7642 connection_struct *conn = req->conn;
7643 struct smb_filename *smb_fname_src = NULL;
7644 struct smb_filename *smb_fname_src_dir = NULL;
7645 struct smb_filename *smb_fname_dst = NULL;
7646 char *fname_src = NULL;
7647 char *fname_dst = NULL;
7648 char *fname_src_mask = NULL;
7649 char *fname_src_dir = NULL;
7652 int error = ERRnoaccess;
7656 bool target_is_directory=False;
7657 bool source_has_wild = False;
7658 bool dest_has_wild = False;
7660 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7661 ucf_flags_from_smb_request(req);
7662 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7663 ucf_flags_from_smb_request(req);
7664 TALLOC_CTX *ctx = talloc_tos();
7666 START_PROFILE(SMBcopy);
7669 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7673 tid2 = SVAL(req->vwv+0, 0);
7674 ofun = SVAL(req->vwv+1, 0);
7675 flags = SVAL(req->vwv+2, 0);
7677 p = (const char *)req->buf;
7678 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7679 &status, &source_has_wild);
7680 if (!NT_STATUS_IS_OK(status)) {
7681 reply_nterror(req, status);
7684 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7685 &status, &dest_has_wild);
7686 if (!NT_STATUS_IS_OK(status)) {
7687 reply_nterror(req, status);
7691 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7693 if (tid2 != conn->cnum) {
7694 /* can't currently handle inter share copies XXXX */
7695 DEBUG(3,("Rejecting inter-share copy\n"));
7696 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7700 status = filename_convert(ctx, conn,
7706 if (!NT_STATUS_IS_OK(status)) {
7707 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7708 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7709 ERRSRV, ERRbadpath);
7712 reply_nterror(req, status);
7716 status = filename_convert(ctx, conn,
7722 if (!NT_STATUS_IS_OK(status)) {
7723 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7724 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7725 ERRSRV, ERRbadpath);
7728 reply_nterror(req, status);
7732 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7734 if ((flags&1) && target_is_directory) {
7735 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7739 if ((flags&2) && !target_is_directory) {
7740 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7744 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7745 /* wants a tree copy! XXXX */
7746 DEBUG(3,("Rejecting tree copy\n"));
7747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7751 /* Split up the directory from the filename/mask. */
7752 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7753 &fname_src_dir, &fname_src_mask);
7754 if (!NT_STATUS_IS_OK(status)) {
7755 reply_nterror(req, NT_STATUS_NO_MEMORY);
7760 * We should only check the mangled cache
7761 * here if unix_convert failed. This means
7762 * that the path in 'mask' doesn't exist
7763 * on the file system and so we need to look
7764 * for a possible mangle. This patch from
7765 * Tine Smukavec <valentin.smukavec@hermes.si>.
7767 if (!VALID_STAT(smb_fname_src->st) &&
7768 mangle_is_mangled(fname_src_mask, conn->params)) {
7769 char *new_mask = NULL;
7770 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7771 &new_mask, conn->params);
7773 /* Use demangled name if one was successfully found. */
7775 TALLOC_FREE(fname_src_mask);
7776 fname_src_mask = new_mask;
7780 if (!source_has_wild) {
7783 * Only one file needs to be copied. Append the mask back onto
7786 TALLOC_FREE(smb_fname_src->base_name);
7787 if (ISDOT(fname_src_dir)) {
7788 /* Ensure we use canonical names on open. */
7789 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7793 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7798 if (!smb_fname_src->base_name) {
7799 reply_nterror(req, NT_STATUS_NO_MEMORY);
7803 if (dest_has_wild) {
7804 char *fname_dst_mod = NULL;
7805 if (!resolve_wildcards(smb_fname_dst,
7806 smb_fname_src->base_name,
7807 smb_fname_dst->base_name,
7809 reply_nterror(req, NT_STATUS_NO_MEMORY);
7812 TALLOC_FREE(smb_fname_dst->base_name);
7813 smb_fname_dst->base_name = fname_dst_mod;
7816 status = check_name(conn, smb_fname_src);
7817 if (!NT_STATUS_IS_OK(status)) {
7818 reply_nterror(req, status);
7822 status = check_name(conn, smb_fname_dst);
7823 if (!NT_STATUS_IS_OK(status)) {
7824 reply_nterror(req, status);
7828 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7829 ofun, count, target_is_directory);
7831 if(!NT_STATUS_IS_OK(status)) {
7832 reply_nterror(req, status);
7838 struct smb_Dir *dir_hnd = NULL;
7839 const char *dname = NULL;
7840 char *talloced = NULL;
7844 * There is a wildcard that requires us to actually read the
7845 * src dir and copy each file matching the mask to the dst.
7846 * Right now streams won't be copied, but this could
7847 * presumably be added with a nested loop for reach dir entry.
7849 SMB_ASSERT(!smb_fname_src->stream_name);
7850 SMB_ASSERT(!smb_fname_dst->stream_name);
7852 smb_fname_src->stream_name = NULL;
7853 smb_fname_dst->stream_name = NULL;
7855 if (strequal(fname_src_mask,"????????.???")) {
7856 TALLOC_FREE(fname_src_mask);
7857 fname_src_mask = talloc_strdup(ctx, "*");
7858 if (!fname_src_mask) {
7859 reply_nterror(req, NT_STATUS_NO_MEMORY);
7864 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7868 smb_fname_src->flags);
7869 if (smb_fname_src_dir == NULL) {
7870 reply_nterror(req, NT_STATUS_NO_MEMORY);
7874 status = check_name(conn, smb_fname_src_dir);
7875 if (!NT_STATUS_IS_OK(status)) {
7876 reply_nterror(req, status);
7880 dir_hnd = OpenDir(ctx,
7885 if (dir_hnd == NULL) {
7886 status = map_nt_error_from_unix(errno);
7887 reply_nterror(req, status);
7893 /* Iterate over the src dir copying each entry to the dst. */
7894 while ((dname = ReadDirName(dir_hnd, &offset,
7895 &smb_fname_src->st, &talloced))) {
7896 char *destname = NULL;
7898 if (ISDOT(dname) || ISDOTDOT(dname)) {
7899 TALLOC_FREE(talloced);
7903 if (!is_visible_file(conn, fname_src_dir, dname,
7904 &smb_fname_src->st, false)) {
7905 TALLOC_FREE(talloced);
7909 if(!mask_match(dname, fname_src_mask,
7910 conn->case_sensitive)) {
7911 TALLOC_FREE(talloced);
7915 error = ERRnoaccess;
7917 /* Get the src smb_fname struct setup. */
7918 TALLOC_FREE(smb_fname_src->base_name);
7919 if (ISDOT(fname_src_dir)) {
7920 /* Ensure we use canonical names on open. */
7921 smb_fname_src->base_name =
7922 talloc_asprintf(smb_fname_src, "%s",
7925 smb_fname_src->base_name =
7926 talloc_asprintf(smb_fname_src, "%s/%s",
7927 fname_src_dir, dname);
7930 if (!smb_fname_src->base_name) {
7931 TALLOC_FREE(dir_hnd);
7932 TALLOC_FREE(talloced);
7933 reply_nterror(req, NT_STATUS_NO_MEMORY);
7937 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7938 smb_fname_dst->base_name,
7940 TALLOC_FREE(talloced);
7944 TALLOC_FREE(dir_hnd);
7945 TALLOC_FREE(talloced);
7946 reply_nterror(req, NT_STATUS_NO_MEMORY);
7950 TALLOC_FREE(smb_fname_dst->base_name);
7951 smb_fname_dst->base_name = destname;
7953 status = check_name(conn, smb_fname_src);
7954 if (!NT_STATUS_IS_OK(status)) {
7955 TALLOC_FREE(dir_hnd);
7956 TALLOC_FREE(talloced);
7957 reply_nterror(req, status);
7961 status = check_name(conn, smb_fname_dst);
7962 if (!NT_STATUS_IS_OK(status)) {
7963 TALLOC_FREE(dir_hnd);
7964 TALLOC_FREE(talloced);
7965 reply_nterror(req, status);
7969 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7970 smb_fname_src->base_name,
7971 smb_fname_dst->base_name));
7973 status = copy_file(ctx, conn, smb_fname_src,
7974 smb_fname_dst, ofun, count,
7975 target_is_directory);
7976 if (NT_STATUS_IS_OK(status)) {
7980 TALLOC_FREE(talloced);
7982 TALLOC_FREE(dir_hnd);
7986 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7990 reply_outbuf(req, 1, 0);
7991 SSVAL(req->outbuf,smb_vwv0,count);
7993 TALLOC_FREE(smb_fname_src);
7994 TALLOC_FREE(smb_fname_src_dir);
7995 TALLOC_FREE(smb_fname_dst);
7996 TALLOC_FREE(fname_src);
7997 TALLOC_FREE(fname_dst);
7998 TALLOC_FREE(fname_src_mask);
7999 TALLOC_FREE(fname_src_dir);
8001 END_PROFILE(SMBcopy);
8006 #define DBGC_CLASS DBGC_LOCKING
8008 /****************************************************************************
8009 Get a lock pid, dealing with large count requests.
8010 ****************************************************************************/
8012 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8013 bool large_file_format)
8015 if(!large_file_format)
8016 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8018 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8021 /****************************************************************************
8022 Get a lock count, dealing with large count requests.
8023 ****************************************************************************/
8025 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8026 bool large_file_format)
8030 if(!large_file_format) {
8031 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8034 * No BVAL, this is reversed!
8036 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8037 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8043 /****************************************************************************
8044 Get a lock offset, dealing with large offset requests.
8045 ****************************************************************************/
8047 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8048 bool large_file_format)
8050 uint64_t offset = 0;
8052 if(!large_file_format) {
8053 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8056 * No BVAL, this is reversed!
8058 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8059 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8065 NTSTATUS smbd_do_locking(struct smb_request *req,
8070 struct smbd_lock_element *locks,
8073 connection_struct *conn = req->conn;
8075 NTSTATUS status = NT_STATUS_OK;
8079 /* Setup the timeout in seconds. */
8081 if (!lp_blocking_locks(SNUM(conn))) {
8085 for(i = 0; i < (int)num_locks; i++) {
8086 struct smbd_lock_element *e = &locks[i];
8088 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8089 "%llu, file %s timeout = %d\n",
8092 (unsigned long long)e->smblctx,
8096 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8097 struct blocking_lock_record *blr = NULL;
8099 if (num_locks > 1) {
8101 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8102 * if the lock vector contains one entry. When given multiple cancel
8103 * requests in a single PDU we expect the server to return an
8104 * error. Windows servers seem to accept the request but only
8105 * cancel the first lock.
8106 * JRA - Do what Windows does (tm) :-).
8110 /* MS-CIFS (2.2.4.32.1) behavior. */
8111 return NT_STATUS_DOS(ERRDOS,
8112 ERRcancelviolation);
8114 /* Windows behavior. */
8116 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8117 "cancel request\n"));
8123 if (lp_blocking_locks(SNUM(conn))) {
8125 /* Schedule a message to ourselves to
8126 remove the blocking lock record and
8127 return the right error. */
8129 blr = blocking_lock_cancel_smb1(fsp,
8135 NT_STATUS_FILE_LOCK_CONFLICT);
8137 return NT_STATUS_DOS(
8139 ERRcancelviolation);
8142 /* Remove a matching pending lock. */
8143 status = do_lock_cancel(fsp,
8149 bool blocking_lock = timeout ? true : false;
8150 bool defer_lock = false;
8151 struct byte_range_lock *br_lck;
8152 uint64_t block_smblctx;
8154 br_lck = do_lock(req->sconn->msg_ctx,
8165 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8166 /* Windows internal resolution for blocking locks seems
8167 to be about 200ms... Don't wait for less than that. JRA. */
8168 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8169 timeout = lp_lock_spin_time();
8174 /* If a lock sent with timeout of zero would fail, and
8175 * this lock has been requested multiple times,
8176 * according to brl_lock_failed() we convert this
8177 * request to a blocking lock with a timeout of between
8178 * 150 - 300 milliseconds.
8180 * If lp_lock_spin_time() has been set to 0, we skip
8181 * this blocking retry and fail immediately.
8183 * Replacement for do_lock_spin(). JRA. */
8185 if (!req->sconn->using_smb2 &&
8186 br_lck && lp_blocking_locks(SNUM(conn)) &&
8187 lp_lock_spin_time() && !blocking_lock &&
8188 NT_STATUS_EQUAL((status),
8189 NT_STATUS_FILE_LOCK_CONFLICT))
8192 timeout = lp_lock_spin_time();
8195 if (br_lck && defer_lock) {
8197 * A blocking lock was requested. Package up
8198 * this smb into a queued request and push it
8199 * onto the blocking lock queue.
8201 if(push_blocking_lock_request(br_lck,
8212 TALLOC_FREE(br_lck);
8214 return NT_STATUS_OK;
8218 TALLOC_FREE(br_lck);
8221 if (!NT_STATUS_IS_OK(status)) {
8226 /* If any of the above locks failed, then we must unlock
8227 all of the previous locks (X/Open spec). */
8229 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8231 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8232 i = -1; /* we want to skip the for loop */
8236 * Ensure we don't do a remove on the lock that just failed,
8237 * as under POSIX rules, if we have a lock already there, we
8238 * will delete it (and we shouldn't) .....
8240 for(i--; i >= 0; i--) {
8241 struct smbd_lock_element *e = &locks[i];
8243 do_unlock(req->sconn->msg_ctx,
8253 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8254 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8256 return NT_STATUS_OK;
8259 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8261 uint16_t num_ulocks,
8262 struct smbd_lock_element *ulocks)
8266 for(i = 0; i < (int)num_ulocks; i++) {
8267 struct smbd_lock_element *e = &ulocks[i];
8270 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8271 "pid %u, file %s\n", __func__,
8274 (unsigned int)e->smblctx,
8277 if (e->brltype != UNLOCK_LOCK) {
8278 /* this can only happen with SMB2 */
8279 return NT_STATUS_INVALID_PARAMETER;
8282 status = do_unlock(req->sconn->msg_ctx,
8289 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8290 nt_errstr(status)));
8292 if (!NT_STATUS_IS_OK(status)) {
8297 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8300 return NT_STATUS_OK;
8303 /****************************************************************************
8304 Reply to a lockingX request.
8305 ****************************************************************************/
8307 void reply_lockingX(struct smb_request *req)
8309 connection_struct *conn = req->conn;
8311 unsigned char locktype;
8312 unsigned char oplocklevel;
8313 uint16_t num_ulocks;
8315 int32_t lock_timeout;
8317 const uint8_t *data;
8318 bool large_file_format;
8319 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8320 struct smbd_lock_element *ulocks;
8321 struct smbd_lock_element *locks;
8324 START_PROFILE(SMBlockingX);
8327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8328 END_PROFILE(SMBlockingX);
8332 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8333 locktype = CVAL(req->vwv+3, 0);
8334 oplocklevel = CVAL(req->vwv+3, 1);
8335 num_ulocks = SVAL(req->vwv+6, 0);
8336 num_locks = SVAL(req->vwv+7, 0);
8337 lock_timeout = IVAL(req->vwv+4, 0);
8338 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8340 if (!check_fsp(conn, req, fsp)) {
8341 END_PROFILE(SMBlockingX);
8347 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8348 /* we don't support these - and CANCEL_LOCK makes w2k
8349 and XP reboot so I don't really want to be
8350 compatible! (tridge) */
8351 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8352 END_PROFILE(SMBlockingX);
8356 /* Check if this is an oplock break on a file
8357 we have granted an oplock on.
8359 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8360 /* Client can insist on breaking to none. */
8361 bool break_to_none = (oplocklevel == 0);
8364 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8365 "for %s\n", (unsigned int)oplocklevel,
8366 fsp_fnum_dbg(fsp)));
8369 * Make sure we have granted an exclusive or batch oplock on
8373 if (fsp->oplock_type == 0) {
8375 /* The Samba4 nbench simulator doesn't understand
8376 the difference between break to level2 and break
8377 to none from level2 - it sends oplock break
8378 replies in both cases. Don't keep logging an error
8379 message here - just ignore it. JRA. */
8381 DEBUG(5,("reply_lockingX: Error : oplock break from "
8382 "client for %s (oplock=%d) and no "
8383 "oplock granted on this file (%s).\n",
8384 fsp_fnum_dbg(fsp), fsp->oplock_type,
8387 /* if this is a pure oplock break request then don't
8389 if (num_locks == 0 && num_ulocks == 0) {
8390 END_PROFILE(SMBlockingX);
8393 END_PROFILE(SMBlockingX);
8394 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8399 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8401 result = remove_oplock(fsp);
8403 result = downgrade_oplock(fsp);
8407 DEBUG(0, ("reply_lockingX: error in removing "
8408 "oplock on file %s\n", fsp_str_dbg(fsp)));
8409 /* Hmmm. Is this panic justified? */
8410 smb_panic("internal tdb error");
8413 /* if this is a pure oplock break request then don't send a
8415 if (num_locks == 0 && num_ulocks == 0) {
8416 /* Sanity check - ensure a pure oplock break is not a
8418 if (CVAL(req->vwv+0, 0) != 0xff) {
8419 DEBUG(0,("reply_lockingX: Error : pure oplock "
8420 "break is a chained %d request !\n",
8421 (unsigned int)CVAL(req->vwv+0, 0)));
8423 END_PROFILE(SMBlockingX);
8429 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8430 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8431 END_PROFILE(SMBlockingX);
8435 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8436 if (ulocks == NULL) {
8437 reply_nterror(req, NT_STATUS_NO_MEMORY);
8438 END_PROFILE(SMBlockingX);
8442 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8443 if (locks == NULL) {
8444 reply_nterror(req, NT_STATUS_NO_MEMORY);
8445 END_PROFILE(SMBlockingX);
8449 /* Data now points at the beginning of the list
8450 of smb_unlkrng structs */
8451 for(i = 0; i < (int)num_ulocks; i++) {
8452 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8453 ulocks[i].count = get_lock_count(data, i, large_file_format);
8454 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8455 ulocks[i].brltype = UNLOCK_LOCK;
8458 /* Now do any requested locks */
8459 data += ((large_file_format ? 20 : 10)*num_ulocks);
8461 /* Data now points at the beginning of the list
8462 of smb_lkrng structs */
8464 for(i = 0; i < (int)num_locks; i++) {
8465 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8466 locks[i].count = get_lock_count(data, i, large_file_format);
8467 locks[i].offset = get_lock_offset(data, i, large_file_format);
8469 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8470 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8471 locks[i].brltype = PENDING_READ_LOCK;
8473 locks[i].brltype = READ_LOCK;
8476 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8477 locks[i].brltype = PENDING_WRITE_LOCK;
8479 locks[i].brltype = WRITE_LOCK;
8484 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8485 if (!NT_STATUS_IS_OK(status)) {
8486 END_PROFILE(SMBlockingX);
8487 reply_nterror(req, status);
8491 status = smbd_do_locking(req, fsp,
8492 locktype, lock_timeout,
8495 if (!NT_STATUS_IS_OK(status)) {
8496 END_PROFILE(SMBlockingX);
8497 reply_nterror(req, status);
8501 END_PROFILE(SMBlockingX);
8505 reply_outbuf(req, 2, 0);
8506 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8507 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8509 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8510 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8512 END_PROFILE(SMBlockingX);
8516 #define DBGC_CLASS DBGC_ALL
8518 /****************************************************************************
8519 Reply to a SMBreadbmpx (read block multiplex) request.
8520 Always reply with an error, if someone has a platform really needs this,
8521 please contact vl@samba.org
8522 ****************************************************************************/
8524 void reply_readbmpx(struct smb_request *req)
8526 START_PROFILE(SMBreadBmpx);
8527 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8528 END_PROFILE(SMBreadBmpx);
8532 /****************************************************************************
8533 Reply to a SMBreadbs (read block multiplex secondary) request.
8534 Always reply with an error, if someone has a platform really needs this,
8535 please contact vl@samba.org
8536 ****************************************************************************/
8538 void reply_readbs(struct smb_request *req)
8540 START_PROFILE(SMBreadBs);
8541 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8542 END_PROFILE(SMBreadBs);
8546 /****************************************************************************
8547 Reply to a SMBsetattrE.
8548 ****************************************************************************/
8550 void reply_setattrE(struct smb_request *req)
8552 connection_struct *conn = req->conn;
8553 struct smb_file_time ft;
8557 START_PROFILE(SMBsetattrE);
8561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8565 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8567 if(!fsp || (fsp->conn != conn)) {
8568 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8573 * Convert the DOS times into unix times.
8576 ft.atime = convert_time_t_to_timespec(
8577 srv_make_unix_date2(req->vwv+3));
8578 ft.mtime = convert_time_t_to_timespec(
8579 srv_make_unix_date2(req->vwv+5));
8580 ft.create_time = convert_time_t_to_timespec(
8581 srv_make_unix_date2(req->vwv+1));
8583 reply_outbuf(req, 0, 0);
8586 * Patch from Ray Frush <frush@engr.colostate.edu>
8587 * Sometimes times are sent as zero - ignore them.
8590 /* Ensure we have a valid stat struct for the source. */
8591 status = vfs_stat_fsp(fsp);
8592 if (!NT_STATUS_IS_OK(status)) {
8593 reply_nterror(req, status);
8597 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8598 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8602 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8603 if (!NT_STATUS_IS_OK(status)) {
8604 reply_nterror(req, status);
8608 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8611 (unsigned int)ft.atime.tv_sec,
8612 (unsigned int)ft.mtime.tv_sec,
8613 (unsigned int)ft.create_time.tv_sec
8616 END_PROFILE(SMBsetattrE);
8621 /* Back from the dead for OS/2..... JRA. */
8623 /****************************************************************************
8624 Reply to a SMBwritebmpx (write block multiplex primary) request.
8625 Always reply with an error, if someone has a platform really needs this,
8626 please contact vl@samba.org
8627 ****************************************************************************/
8629 void reply_writebmpx(struct smb_request *req)
8631 START_PROFILE(SMBwriteBmpx);
8632 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8633 END_PROFILE(SMBwriteBmpx);
8637 /****************************************************************************
8638 Reply to a SMBwritebs (write block multiplex secondary) request.
8639 Always reply with an error, if someone has a platform really needs this,
8640 please contact vl@samba.org
8641 ****************************************************************************/
8643 void reply_writebs(struct smb_request *req)
8645 START_PROFILE(SMBwriteBs);
8646 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8647 END_PROFILE(SMBwriteBs);
8651 /****************************************************************************
8652 Reply to a SMBgetattrE.
8653 ****************************************************************************/
8655 void reply_getattrE(struct smb_request *req)
8657 connection_struct *conn = req->conn;
8660 struct timespec create_ts;
8662 START_PROFILE(SMBgetattrE);
8665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8666 END_PROFILE(SMBgetattrE);
8670 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8672 if(!fsp || (fsp->conn != conn)) {
8673 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8674 END_PROFILE(SMBgetattrE);
8678 /* Do an fstat on this file */
8680 reply_nterror(req, map_nt_error_from_unix(errno));
8681 END_PROFILE(SMBgetattrE);
8685 mode = dos_mode(conn, fsp->fsp_name);
8688 * Convert the times into dos times. Set create
8689 * date to be last modify date as UNIX doesn't save
8693 reply_outbuf(req, 11, 0);
8695 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8696 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8697 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8698 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8699 /* Should we check pending modtime here ? JRA */
8700 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8701 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8703 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8704 SIVAL(req->outbuf, smb_vwv6, 0);
8705 SIVAL(req->outbuf, smb_vwv8, 0);
8707 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8708 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8709 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8711 SSVAL(req->outbuf,smb_vwv10, mode);
8713 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8715 END_PROFILE(SMBgetattrE);