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,
1310 if (!NT_STATUS_IS_OK(status)) {
1311 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1312 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1313 ERRSRV, ERRbadpath);
1314 END_PROFILE(SMBcheckpath);
1320 if (!VALID_STAT(smb_fname->st) &&
1321 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1322 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1323 smb_fname_str_dbg(smb_fname), strerror(errno)));
1324 status = map_nt_error_from_unix(errno);
1328 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1329 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1330 ERRDOS, ERRbadpath);
1334 reply_outbuf(req, 0, 0);
1337 /* We special case this - as when a Windows machine
1338 is parsing a path is steps through the components
1339 one at a time - if a component fails it expects
1340 ERRbadpath, not ERRbadfile.
1342 status = map_checkpath_error(req->flags2, status);
1343 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1345 * Windows returns different error codes if
1346 * the parent directory is valid but not the
1347 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1348 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1349 * if the path is invalid.
1351 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1352 ERRDOS, ERRbadpath);
1356 reply_nterror(req, status);
1359 TALLOC_FREE(smb_fname);
1360 END_PROFILE(SMBcheckpath);
1364 /****************************************************************************
1366 ****************************************************************************/
1368 void reply_getatr(struct smb_request *req)
1370 connection_struct *conn = req->conn;
1371 struct smb_filename *smb_fname = NULL;
1378 TALLOC_CTX *ctx = talloc_tos();
1379 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1381 START_PROFILE(SMBgetatr);
1383 p = (const char *)req->buf + 1;
1384 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1385 if (!NT_STATUS_IS_OK(status)) {
1386 reply_nterror(req, status);
1390 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1391 under WfWg - weird! */
1392 if (*fname == '\0') {
1393 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1394 if (!CAN_WRITE(conn)) {
1395 mode |= FILE_ATTRIBUTE_READONLY;
1400 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1401 status = filename_convert(ctx,
1407 if (!NT_STATUS_IS_OK(status)) {
1408 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1409 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1410 ERRSRV, ERRbadpath);
1413 reply_nterror(req, status);
1416 if (!VALID_STAT(smb_fname->st) &&
1417 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1418 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1419 smb_fname_str_dbg(smb_fname),
1421 reply_nterror(req, map_nt_error_from_unix(errno));
1425 mode = dos_mode(conn, smb_fname);
1426 size = smb_fname->st.st_ex_size;
1428 if (ask_sharemode) {
1429 struct timespec write_time_ts;
1430 struct file_id fileid;
1432 ZERO_STRUCT(write_time_ts);
1433 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1434 get_file_infos(fileid, 0, NULL, &write_time_ts);
1435 if (!null_timespec(write_time_ts)) {
1436 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1440 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1441 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1446 reply_outbuf(req, 10, 0);
1448 SSVAL(req->outbuf,smb_vwv0,mode);
1449 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1450 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1452 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1454 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1456 if (get_Protocol() >= PROTOCOL_NT1) {
1457 SSVAL(req->outbuf, smb_flg2,
1458 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1461 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1462 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1465 TALLOC_FREE(smb_fname);
1467 END_PROFILE(SMBgetatr);
1471 /****************************************************************************
1473 ****************************************************************************/
1475 void reply_setatr(struct smb_request *req)
1477 struct smb_file_time ft;
1478 connection_struct *conn = req->conn;
1479 struct smb_filename *smb_fname = NULL;
1485 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1486 TALLOC_CTX *ctx = talloc_tos();
1488 START_PROFILE(SMBsetatr);
1493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1497 p = (const char *)req->buf + 1;
1498 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1499 if (!NT_STATUS_IS_OK(status)) {
1500 reply_nterror(req, status);
1504 status = filename_convert(ctx,
1510 if (!NT_STATUS_IS_OK(status)) {
1511 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1512 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1513 ERRSRV, ERRbadpath);
1516 reply_nterror(req, status);
1520 if (smb_fname->base_name[0] == '.' &&
1521 smb_fname->base_name[1] == '\0') {
1523 * Not sure here is the right place to catch this
1524 * condition. Might be moved to somewhere else later -- vl
1526 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1530 mode = SVAL(req->vwv+0, 0);
1531 mtime = srv_make_unix_date3(req->vwv+1);
1533 if (mode != FILE_ATTRIBUTE_NORMAL) {
1534 if (VALID_STAT_OF_DIR(smb_fname->st))
1535 mode |= FILE_ATTRIBUTE_DIRECTORY;
1537 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1539 status = check_access(conn, NULL, smb_fname,
1540 FILE_WRITE_ATTRIBUTES);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 reply_nterror(req, status);
1546 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1548 reply_nterror(req, map_nt_error_from_unix(errno));
1553 ft.mtime = convert_time_t_to_timespec(mtime);
1554 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1555 if (!NT_STATUS_IS_OK(status)) {
1556 reply_nterror(req, status);
1560 reply_outbuf(req, 0, 0);
1562 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1565 TALLOC_FREE(smb_fname);
1566 END_PROFILE(SMBsetatr);
1570 /****************************************************************************
1572 ****************************************************************************/
1574 void reply_dskattr(struct smb_request *req)
1576 connection_struct *conn = req->conn;
1578 uint64_t dfree,dsize,bsize;
1579 struct smb_filename smb_fname;
1580 START_PROFILE(SMBdskattr);
1582 ZERO_STRUCT(smb_fname);
1583 smb_fname.base_name = discard_const_p(char, ".");
1585 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1586 reply_nterror(req, map_nt_error_from_unix(errno));
1587 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1588 END_PROFILE(SMBdskattr);
1592 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1593 if (ret == (uint64_t)-1) {
1594 reply_nterror(req, map_nt_error_from_unix(errno));
1595 END_PROFILE(SMBdskattr);
1600 * Force max to fit in 16 bit fields.
1602 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1606 if (bsize > (WORDMAX*512)) {
1607 bsize = (WORDMAX*512);
1608 if (dsize > WORDMAX)
1610 if (dfree > WORDMAX)
1616 reply_outbuf(req, 5, 0);
1618 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1619 double total_space, free_space;
1620 /* we need to scale this to a number that DOS6 can handle. We
1621 use floating point so we can handle large drives on systems
1622 that don't have 64 bit integers
1624 we end up displaying a maximum of 2G to DOS systems
1626 total_space = dsize * (double)bsize;
1627 free_space = dfree * (double)bsize;
1629 dsize = (uint64_t)((total_space+63*512) / (64*512));
1630 dfree = (uint64_t)((free_space+63*512) / (64*512));
1632 if (dsize > 0xFFFF) dsize = 0xFFFF;
1633 if (dfree > 0xFFFF) dfree = 0xFFFF;
1635 SSVAL(req->outbuf,smb_vwv0,dsize);
1636 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1637 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1638 SSVAL(req->outbuf,smb_vwv3,dfree);
1640 SSVAL(req->outbuf,smb_vwv0,dsize);
1641 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1642 SSVAL(req->outbuf,smb_vwv2,512);
1643 SSVAL(req->outbuf,smb_vwv3,dfree);
1646 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1648 END_PROFILE(SMBdskattr);
1653 * Utility function to split the filename from the directory.
1655 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1656 char **fname_dir_out,
1657 char **fname_mask_out)
1659 const char *p = NULL;
1660 char *fname_dir = NULL;
1661 char *fname_mask = NULL;
1663 p = strrchr_m(fname_in, '/');
1665 fname_dir = talloc_strdup(ctx, ".");
1666 fname_mask = talloc_strdup(ctx, fname_in);
1668 fname_dir = talloc_strndup(ctx, fname_in,
1669 PTR_DIFF(p, fname_in));
1670 fname_mask = talloc_strdup(ctx, p+1);
1673 if (!fname_dir || !fname_mask) {
1674 TALLOC_FREE(fname_dir);
1675 TALLOC_FREE(fname_mask);
1676 return NT_STATUS_NO_MEMORY;
1679 *fname_dir_out = fname_dir;
1680 *fname_mask_out = fname_mask;
1681 return NT_STATUS_OK;
1684 /****************************************************************************
1686 ****************************************************************************/
1688 static bool make_dir_struct(TALLOC_CTX *ctx,
1698 char *mask2 = talloc_strdup(ctx, mask);
1704 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1708 memset(buf+1,' ',11);
1709 if ((p = strchr_m(mask2,'.')) != NULL) {
1711 push_ascii(buf+1,mask2,8, 0);
1712 push_ascii(buf+9,p+1,3, 0);
1715 push_ascii(buf+1,mask2,11, 0);
1718 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1720 srv_put_dos_date(buf,22,date);
1721 SSVAL(buf,26,size & 0xFFFF);
1722 SSVAL(buf,28,(size >> 16)&0xFFFF);
1723 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1724 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1725 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1726 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1730 /****************************************************************************
1732 Can be called from SMBsearch, SMBffirst or SMBfunique.
1733 ****************************************************************************/
1735 void reply_search(struct smb_request *req)
1737 connection_struct *conn = req->conn;
1740 char *directory = NULL;
1741 struct smb_filename *smb_fname = NULL;
1745 struct timespec date;
1747 unsigned int numentries = 0;
1748 unsigned int maxentries = 0;
1749 bool finished = False;
1754 bool check_descend = False;
1755 bool expect_close = False;
1757 bool mask_contains_wcard = False;
1758 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1759 TALLOC_CTX *ctx = talloc_tos();
1760 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1761 struct dptr_struct *dirptr = NULL;
1762 struct smbXsrv_connection *xconn = req->xconn;
1763 struct smbd_server_connection *sconn = req->sconn;
1765 START_PROFILE(SMBsearch);
1768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1772 if (req->posix_pathnames) {
1773 reply_unknown_new(req, req->cmd);
1777 /* If we were called as SMBffirst then we must expect close. */
1778 if(req->cmd == SMBffirst) {
1779 expect_close = True;
1782 reply_outbuf(req, 1, 3);
1783 maxentries = SVAL(req->vwv+0, 0);
1784 dirtype = SVAL(req->vwv+1, 0);
1785 p = (const char *)req->buf + 1;
1786 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1787 &nt_status, &mask_contains_wcard);
1788 if (!NT_STATUS_IS_OK(nt_status)) {
1789 reply_nterror(req, nt_status);
1794 status_len = SVAL(p, 0);
1797 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1799 if (status_len == 0) {
1800 struct smb_filename *smb_dname = NULL;
1801 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1802 ucf_flags_from_smb_request(req);
1803 nt_status = filename_convert(ctx, conn,
1806 &mask_contains_wcard,
1808 if (!NT_STATUS_IS_OK(nt_status)) {
1809 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1810 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1811 ERRSRV, ERRbadpath);
1814 reply_nterror(req, nt_status);
1818 directory = smb_fname->base_name;
1820 p = strrchr_m(directory,'/');
1821 if ((p != NULL) && (*directory != '/')) {
1822 mask = talloc_strdup(ctx, p + 1);
1823 directory = talloc_strndup(ctx, directory,
1824 PTR_DIFF(p, directory));
1826 mask = talloc_strdup(ctx, directory);
1827 directory = talloc_strdup(ctx,".");
1831 reply_nterror(req, NT_STATUS_NO_MEMORY);
1835 memset((char *)status,'\0',21);
1836 SCVAL(status,0,(dirtype & 0x1F));
1838 smb_dname = synthetic_smb_fname(talloc_tos(),
1843 if (smb_dname == NULL) {
1844 reply_nterror(req, NT_STATUS_NO_MEMORY);
1848 nt_status = dptr_create(conn,
1856 mask_contains_wcard,
1860 TALLOC_FREE(smb_dname);
1862 if (!NT_STATUS_IS_OK(nt_status)) {
1863 reply_nterror(req, nt_status);
1866 dptr_num = dptr_dnum(dirptr);
1869 const char *dirpath;
1871 memcpy(status,p,21);
1872 status_dirtype = CVAL(status,0) & 0x1F;
1873 if (status_dirtype != (dirtype & 0x1F)) {
1874 dirtype = status_dirtype;
1877 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1881 dirpath = dptr_path(sconn, dptr_num);
1882 directory = talloc_strdup(ctx, dirpath);
1884 reply_nterror(req, NT_STATUS_NO_MEMORY);
1888 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1893 * For a 'continue' search we have no string. So
1894 * check from the initial saved string.
1896 if (!req->posix_pathnames) {
1897 mask_contains_wcard = ms_has_wild(mask);
1899 dirtype = dptr_attr(sconn, dptr_num);
1902 DEBUG(4,("dptr_num is %d\n",dptr_num));
1904 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1905 char buf[DIR_STRUCT_SIZE];
1906 memcpy(buf,status,21);
1907 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1908 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1909 reply_nterror(req, NT_STATUS_NO_MEMORY);
1912 dptr_fill(sconn, buf+12,dptr_num);
1913 if (dptr_zero(buf+12) && (status_len==0)) {
1918 if (message_push_blob(&req->outbuf,
1919 data_blob_const(buf, sizeof(buf)))
1921 reply_nterror(req, NT_STATUS_NO_MEMORY);
1926 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1927 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1929 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1931 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1932 directory,lp_dont_descend(ctx, SNUM(conn))));
1933 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1934 check_descend = True;
1937 for (i=numentries;(i<maxentries) && !finished;i++) {
1938 finished = !get_dir_entry(ctx,
1949 char buf[DIR_STRUCT_SIZE];
1950 memcpy(buf,status,21);
1951 if (!make_dir_struct(ctx,
1957 convert_timespec_to_time_t(date),
1958 !allow_long_path_components)) {
1959 reply_nterror(req, NT_STATUS_NO_MEMORY);
1962 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1965 if (message_push_blob(&req->outbuf,
1966 data_blob_const(buf, sizeof(buf)))
1968 reply_nterror(req, NT_STATUS_NO_MEMORY);
1978 /* If we were called as SMBffirst with smb_search_id == NULL
1979 and no entries were found then return error and close dirptr
1982 if (numentries == 0) {
1983 dptr_close(sconn, &dptr_num);
1984 } else if(expect_close && status_len == 0) {
1985 /* Close the dptr - we know it's gone */
1986 dptr_close(sconn, &dptr_num);
1989 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1990 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1991 dptr_close(sconn, &dptr_num);
1994 if ((numentries == 0) && !mask_contains_wcard) {
1995 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1999 SSVAL(req->outbuf,smb_vwv0,numentries);
2000 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2001 SCVAL(smb_buf(req->outbuf),0,5);
2002 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2004 /* The replies here are never long name. */
2005 SSVAL(req->outbuf, smb_flg2,
2006 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2007 if (!allow_long_path_components) {
2008 SSVAL(req->outbuf, smb_flg2,
2009 SVAL(req->outbuf, smb_flg2)
2010 & (~FLAGS2_LONG_PATH_COMPONENTS));
2013 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2014 SSVAL(req->outbuf, smb_flg2,
2015 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2017 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2018 smb_fn_name(req->cmd),
2025 TALLOC_FREE(directory);
2027 TALLOC_FREE(smb_fname);
2028 END_PROFILE(SMBsearch);
2032 /****************************************************************************
2033 Reply to a fclose (stop directory search).
2034 ****************************************************************************/
2036 void reply_fclose(struct smb_request *req)
2044 bool path_contains_wcard = False;
2045 TALLOC_CTX *ctx = talloc_tos();
2046 struct smbd_server_connection *sconn = req->sconn;
2048 START_PROFILE(SMBfclose);
2050 if (req->posix_pathnames) {
2051 reply_unknown_new(req, req->cmd);
2052 END_PROFILE(SMBfclose);
2056 p = (const char *)req->buf + 1;
2057 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2058 &err, &path_contains_wcard);
2059 if (!NT_STATUS_IS_OK(err)) {
2060 reply_nterror(req, err);
2061 END_PROFILE(SMBfclose);
2065 status_len = SVAL(p,0);
2068 if (status_len == 0) {
2069 reply_force_doserror(req, ERRSRV, ERRsrverror);
2070 END_PROFILE(SMBfclose);
2074 memcpy(status,p,21);
2076 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2077 /* Close the dptr - we know it's gone */
2078 dptr_close(sconn, &dptr_num);
2081 reply_outbuf(req, 1, 0);
2082 SSVAL(req->outbuf,smb_vwv0,0);
2084 DEBUG(3,("search close\n"));
2086 END_PROFILE(SMBfclose);
2090 /****************************************************************************
2092 ****************************************************************************/
2094 void reply_open(struct smb_request *req)
2096 connection_struct *conn = req->conn;
2097 struct smb_filename *smb_fname = NULL;
2107 uint32_t access_mask;
2108 uint32_t share_mode;
2109 uint32_t create_disposition;
2110 uint32_t create_options = 0;
2111 uint32_t private_flags = 0;
2114 TALLOC_CTX *ctx = talloc_tos();
2116 START_PROFILE(SMBopen);
2119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2123 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2124 deny_mode = SVAL(req->vwv+0, 0);
2125 dos_attr = SVAL(req->vwv+1, 0);
2127 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2128 STR_TERMINATE, &status);
2129 if (!NT_STATUS_IS_OK(status)) {
2130 reply_nterror(req, status);
2134 if (!map_open_params_to_ntcreate(fname, deny_mode,
2135 OPENX_FILE_EXISTS_OPEN, &access_mask,
2136 &share_mode, &create_disposition,
2137 &create_options, &private_flags)) {
2138 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2142 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2144 status = filename_convert(ctx,
2150 if (!NT_STATUS_IS_OK(status)) {
2151 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2152 reply_botherror(req,
2153 NT_STATUS_PATH_NOT_COVERED,
2154 ERRSRV, ERRbadpath);
2157 reply_nterror(req, status);
2161 status = SMB_VFS_CREATE_FILE(
2164 0, /* root_dir_fid */
2165 smb_fname, /* fname */
2166 access_mask, /* access_mask */
2167 share_mode, /* share_access */
2168 create_disposition, /* create_disposition*/
2169 create_options, /* create_options */
2170 dos_attr, /* file_attributes */
2171 oplock_request, /* oplock_request */
2173 0, /* allocation_size */
2179 NULL, NULL); /* create context */
2181 if (!NT_STATUS_IS_OK(status)) {
2182 if (open_was_deferred(req->xconn, req->mid)) {
2183 /* We have re-scheduled this call. */
2186 reply_openerror(req, status);
2190 /* Ensure we're pointing at the correct stat struct. */
2191 TALLOC_FREE(smb_fname);
2192 smb_fname = fsp->fsp_name;
2194 size = smb_fname->st.st_ex_size;
2195 fattr = dos_mode(conn, smb_fname);
2197 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2199 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2200 DEBUG(3,("attempt to open a directory %s\n",
2202 close_file(req, fsp, ERROR_CLOSE);
2203 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2204 ERRDOS, ERRnoaccess);
2208 reply_outbuf(req, 7, 0);
2209 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2210 SSVAL(req->outbuf,smb_vwv1,fattr);
2211 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2212 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2214 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2216 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2217 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2219 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2220 SCVAL(req->outbuf,smb_flg,
2221 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2224 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2225 SCVAL(req->outbuf,smb_flg,
2226 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2229 END_PROFILE(SMBopen);
2233 /****************************************************************************
2234 Reply to an open and X.
2235 ****************************************************************************/
2237 void reply_open_and_X(struct smb_request *req)
2239 connection_struct *conn = req->conn;
2240 struct smb_filename *smb_fname = NULL;
2242 uint16_t open_flags;
2245 /* Breakout the oplock request bits so we can set the
2246 reply bits separately. */
2247 int ex_oplock_request;
2248 int core_oplock_request;
2251 int smb_sattr = SVAL(req->vwv+4, 0);
2252 uint32_t smb_time = make_unix_date3(req->vwv+6);
2260 uint64_t allocation_size;
2261 ssize_t retval = -1;
2262 uint32_t access_mask;
2263 uint32_t share_mode;
2264 uint32_t create_disposition;
2265 uint32_t create_options = 0;
2266 uint32_t private_flags = 0;
2268 TALLOC_CTX *ctx = talloc_tos();
2270 START_PROFILE(SMBopenX);
2272 if (req->wct < 15) {
2273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2277 open_flags = SVAL(req->vwv+2, 0);
2278 deny_mode = SVAL(req->vwv+3, 0);
2279 smb_attr = SVAL(req->vwv+5, 0);
2280 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2281 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2282 oplock_request = ex_oplock_request | core_oplock_request;
2283 smb_ofun = SVAL(req->vwv+8, 0);
2284 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2286 /* If it's an IPC, pass off the pipe handler. */
2288 if (lp_nt_pipe_support()) {
2289 reply_open_pipe_and_X(conn, req);
2291 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2296 /* XXXX we need to handle passed times, sattr and flags */
2297 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2298 STR_TERMINATE, &status);
2299 if (!NT_STATUS_IS_OK(status)) {
2300 reply_nterror(req, status);
2304 if (!map_open_params_to_ntcreate(fname, deny_mode,
2306 &access_mask, &share_mode,
2307 &create_disposition,
2310 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2314 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2316 status = filename_convert(ctx,
2322 if (!NT_STATUS_IS_OK(status)) {
2323 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2324 reply_botherror(req,
2325 NT_STATUS_PATH_NOT_COVERED,
2326 ERRSRV, ERRbadpath);
2329 reply_nterror(req, status);
2333 status = SMB_VFS_CREATE_FILE(
2336 0, /* root_dir_fid */
2337 smb_fname, /* fname */
2338 access_mask, /* access_mask */
2339 share_mode, /* share_access */
2340 create_disposition, /* create_disposition*/
2341 create_options, /* create_options */
2342 smb_attr, /* file_attributes */
2343 oplock_request, /* oplock_request */
2345 0, /* allocation_size */
2350 &smb_action, /* pinfo */
2351 NULL, NULL); /* create context */
2353 if (!NT_STATUS_IS_OK(status)) {
2354 if (open_was_deferred(req->xconn, req->mid)) {
2355 /* We have re-scheduled this call. */
2358 reply_openerror(req, status);
2362 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2363 if the file is truncated or created. */
2364 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2365 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2366 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2367 close_file(req, fsp, ERROR_CLOSE);
2368 reply_nterror(req, NT_STATUS_DISK_FULL);
2371 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2373 close_file(req, fsp, ERROR_CLOSE);
2374 reply_nterror(req, NT_STATUS_DISK_FULL);
2377 status = vfs_stat_fsp(fsp);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 close_file(req, fsp, ERROR_CLOSE);
2380 reply_nterror(req, status);
2385 fattr = dos_mode(conn, fsp->fsp_name);
2386 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2387 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2388 close_file(req, fsp, ERROR_CLOSE);
2389 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2393 /* If the caller set the extended oplock request bit
2394 and we granted one (by whatever means) - set the
2395 correct bit for extended oplock reply.
2398 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2399 smb_action |= EXTENDED_OPLOCK_GRANTED;
2402 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2403 smb_action |= EXTENDED_OPLOCK_GRANTED;
2406 /* If the caller set the core oplock request bit
2407 and we granted one (by whatever means) - set the
2408 correct bit for core oplock reply.
2411 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2412 reply_outbuf(req, 19, 0);
2414 reply_outbuf(req, 15, 0);
2417 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2418 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2420 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2421 SCVAL(req->outbuf, smb_flg,
2422 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2425 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2426 SCVAL(req->outbuf, smb_flg,
2427 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2430 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2431 SSVAL(req->outbuf,smb_vwv3,fattr);
2432 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2433 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2435 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2437 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2438 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2439 SSVAL(req->outbuf,smb_vwv11,smb_action);
2441 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2442 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2446 TALLOC_FREE(smb_fname);
2447 END_PROFILE(SMBopenX);
2451 /****************************************************************************
2452 Reply to a SMBulogoffX.
2453 ****************************************************************************/
2455 void reply_ulogoffX(struct smb_request *req)
2457 struct smbd_server_connection *sconn = req->sconn;
2458 struct user_struct *vuser;
2459 struct smbXsrv_session *session = NULL;
2462 START_PROFILE(SMBulogoffX);
2464 vuser = get_valid_user_struct(sconn, req->vuid);
2467 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2468 (unsigned long long)req->vuid));
2470 req->vuid = UID_FIELD_INVALID;
2471 reply_force_doserror(req, ERRSRV, ERRbaduid);
2472 END_PROFILE(SMBulogoffX);
2476 session = vuser->session;
2480 * TODO: cancel all outstanding requests on the session
2482 status = smbXsrv_session_logoff(session);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 DEBUG(0, ("reply_ulogoff: "
2485 "smbXsrv_session_logoff() failed: %s\n",
2486 nt_errstr(status)));
2488 * If we hit this case, there is something completely
2489 * wrong, so we better disconnect the transport connection.
2491 END_PROFILE(SMBulogoffX);
2492 exit_server(__location__ ": smbXsrv_session_logoff failed");
2496 TALLOC_FREE(session);
2498 reply_outbuf(req, 2, 0);
2499 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2500 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2502 DEBUG(3, ("ulogoffX vuid=%llu\n",
2503 (unsigned long long)req->vuid));
2505 END_PROFILE(SMBulogoffX);
2506 req->vuid = UID_FIELD_INVALID;
2509 /****************************************************************************
2510 Reply to a mknew or a create.
2511 ****************************************************************************/
2513 void reply_mknew(struct smb_request *req)
2515 connection_struct *conn = req->conn;
2516 struct smb_filename *smb_fname = NULL;
2519 struct smb_file_time ft;
2521 int oplock_request = 0;
2523 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2524 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2525 uint32_t create_disposition;
2526 uint32_t create_options = 0;
2528 TALLOC_CTX *ctx = talloc_tos();
2530 START_PROFILE(SMBcreate);
2534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2538 fattr = SVAL(req->vwv+0, 0);
2539 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2541 if (req->cmd == SMBmknew) {
2542 /* We should fail if file exists. */
2543 create_disposition = FILE_CREATE;
2545 /* Create if file doesn't exist, truncate if it does. */
2546 create_disposition = FILE_OVERWRITE_IF;
2550 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2552 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2553 STR_TERMINATE, &status);
2554 if (!NT_STATUS_IS_OK(status)) {
2555 reply_nterror(req, status);
2559 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2560 status = filename_convert(ctx,
2566 if (!NT_STATUS_IS_OK(status)) {
2567 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2568 reply_botherror(req,
2569 NT_STATUS_PATH_NOT_COVERED,
2570 ERRSRV, ERRbadpath);
2573 reply_nterror(req, status);
2577 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2578 DEBUG(0,("Attempt to create file (%s) with volid set - "
2579 "please report this\n",
2580 smb_fname_str_dbg(smb_fname)));
2583 status = SMB_VFS_CREATE_FILE(
2586 0, /* root_dir_fid */
2587 smb_fname, /* fname */
2588 access_mask, /* access_mask */
2589 share_mode, /* share_access */
2590 create_disposition, /* create_disposition*/
2591 create_options, /* create_options */
2592 fattr, /* file_attributes */
2593 oplock_request, /* oplock_request */
2595 0, /* allocation_size */
2596 0, /* private_flags */
2601 NULL, NULL); /* create context */
2603 if (!NT_STATUS_IS_OK(status)) {
2604 if (open_was_deferred(req->xconn, req->mid)) {
2605 /* We have re-scheduled this call. */
2608 reply_openerror(req, status);
2612 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2613 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2614 if (!NT_STATUS_IS_OK(status)) {
2615 END_PROFILE(SMBcreate);
2619 reply_outbuf(req, 1, 0);
2620 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2622 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2623 SCVAL(req->outbuf,smb_flg,
2624 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2627 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2628 SCVAL(req->outbuf,smb_flg,
2629 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2632 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2633 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2634 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2635 (unsigned int)fattr));
2638 TALLOC_FREE(smb_fname);
2639 END_PROFILE(SMBcreate);
2643 /****************************************************************************
2644 Reply to a create temporary file.
2645 ****************************************************************************/
2647 void reply_ctemp(struct smb_request *req)
2649 connection_struct *conn = req->conn;
2650 struct smb_filename *smb_fname = NULL;
2651 char *wire_name = NULL;
2660 TALLOC_CTX *ctx = talloc_tos();
2662 START_PROFILE(SMBctemp);
2665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2669 fattr = SVAL(req->vwv+0, 0);
2670 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2672 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2673 STR_TERMINATE, &status);
2674 if (!NT_STATUS_IS_OK(status)) {
2675 reply_nterror(req, status);
2679 for (i = 0; i < 10; i++) {
2681 fname = talloc_asprintf(ctx,
2684 generate_random_str_list(ctx, 5, "0123456789"));
2686 fname = talloc_asprintf(ctx,
2688 generate_random_str_list(ctx, 5, "0123456789"));
2692 reply_nterror(req, NT_STATUS_NO_MEMORY);
2696 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2697 status = filename_convert(ctx, conn,
2702 if (!NT_STATUS_IS_OK(status)) {
2703 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2704 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2705 ERRSRV, ERRbadpath);
2708 reply_nterror(req, status);
2712 /* Create the file. */
2713 status = SMB_VFS_CREATE_FILE(
2716 0, /* root_dir_fid */
2717 smb_fname, /* fname */
2718 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2719 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2720 FILE_CREATE, /* create_disposition*/
2721 0, /* create_options */
2722 fattr, /* file_attributes */
2723 oplock_request, /* oplock_request */
2725 0, /* allocation_size */
2726 0, /* private_flags */
2731 NULL, NULL); /* create context */
2733 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2735 TALLOC_FREE(smb_fname);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 if (open_was_deferred(req->xconn, req->mid)) {
2741 /* We have re-scheduled this call. */
2744 reply_openerror(req, status);
2752 /* Collision after 10 times... */
2753 reply_nterror(req, status);
2757 reply_outbuf(req, 1, 0);
2758 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2760 /* the returned filename is relative to the directory */
2761 s = strrchr_m(fsp->fsp_name->base_name, '/');
2763 s = fsp->fsp_name->base_name;
2769 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2770 thing in the byte section. JRA */
2771 SSVALS(p, 0, -1); /* what is this? not in spec */
2773 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2775 reply_nterror(req, NT_STATUS_NO_MEMORY);
2779 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2780 SCVAL(req->outbuf, smb_flg,
2781 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2784 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2785 SCVAL(req->outbuf, smb_flg,
2786 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2789 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2790 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2791 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2793 TALLOC_FREE(smb_fname);
2794 TALLOC_FREE(wire_name);
2795 END_PROFILE(SMBctemp);
2799 /*******************************************************************
2800 Check if a user is allowed to rename a file.
2801 ********************************************************************/
2803 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2806 if (!CAN_WRITE(conn)) {
2807 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2810 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2811 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2812 /* Only bother to read the DOS attribute if we might deny the
2813 rename on the grounds of attribute mismatch. */
2814 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2815 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2816 return NT_STATUS_NO_SUCH_FILE;
2820 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2821 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2822 return NT_STATUS_OK;
2825 /* If no pathnames are open below this
2826 directory, allow the rename. */
2828 if (lp_strict_rename(SNUM(conn))) {
2830 * Strict rename, check open file db.
2832 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2833 return NT_STATUS_ACCESS_DENIED;
2835 } else if (file_find_subpath(fsp)) {
2837 * No strict rename, just look in local process.
2839 return NT_STATUS_ACCESS_DENIED;
2841 return NT_STATUS_OK;
2844 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2845 return NT_STATUS_OK;
2848 return NT_STATUS_ACCESS_DENIED;
2851 /*******************************************************************
2852 * unlink a file with all relevant access checks
2853 *******************************************************************/
2855 static NTSTATUS do_unlink(connection_struct *conn,
2856 struct smb_request *req,
2857 struct smb_filename *smb_fname,
2862 uint32_t dirtype_orig = dirtype;
2865 bool posix_paths = (req != NULL && req->posix_pathnames);
2867 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2868 smb_fname_str_dbg(smb_fname),
2871 if (!CAN_WRITE(conn)) {
2872 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2876 ret = SMB_VFS_LSTAT(conn, smb_fname);
2878 ret = SMB_VFS_STAT(conn, smb_fname);
2881 return map_nt_error_from_unix(errno);
2884 fattr = dos_mode(conn, smb_fname);
2886 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2887 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2890 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2892 return NT_STATUS_NO_SUCH_FILE;
2895 if (!dir_check_ftype(fattr, dirtype)) {
2896 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2897 return NT_STATUS_FILE_IS_A_DIRECTORY;
2899 return NT_STATUS_NO_SUCH_FILE;
2902 if (dirtype_orig & 0x8000) {
2903 /* These will never be set for POSIX. */
2904 return NT_STATUS_NO_SUCH_FILE;
2908 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2909 return NT_STATUS_FILE_IS_A_DIRECTORY;
2912 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2913 return NT_STATUS_NO_SUCH_FILE;
2916 if (dirtype & 0xFF00) {
2917 /* These will never be set for POSIX. */
2918 return NT_STATUS_NO_SUCH_FILE;
2923 return NT_STATUS_NO_SUCH_FILE;
2926 /* Can't delete a directory. */
2927 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2928 return NT_STATUS_FILE_IS_A_DIRECTORY;
2933 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2934 return NT_STATUS_OBJECT_NAME_INVALID;
2935 #endif /* JRATEST */
2937 /* On open checks the open itself will check the share mode, so
2938 don't do it here as we'll get it wrong. */
2940 status = SMB_VFS_CREATE_FILE
2943 0, /* root_dir_fid */
2944 smb_fname, /* fname */
2945 DELETE_ACCESS, /* access_mask */
2946 FILE_SHARE_NONE, /* share_access */
2947 FILE_OPEN, /* create_disposition*/
2948 FILE_NON_DIRECTORY_FILE, /* create_options */
2949 /* file_attributes */
2950 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2951 FILE_ATTRIBUTE_NORMAL,
2952 0, /* oplock_request */
2954 0, /* allocation_size */
2955 0, /* private_flags */
2960 NULL, NULL); /* create context */
2962 if (!NT_STATUS_IS_OK(status)) {
2963 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2964 nt_errstr(status)));
2968 status = can_set_delete_on_close(fsp, fattr);
2969 if (!NT_STATUS_IS_OK(status)) {
2970 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2972 smb_fname_str_dbg(smb_fname),
2973 nt_errstr(status)));
2974 close_file(req, fsp, NORMAL_CLOSE);
2978 /* The set is across all open files on this dev/inode pair. */
2979 if (!set_delete_on_close(fsp, True,
2980 conn->session_info->security_token,
2981 conn->session_info->unix_token)) {
2982 close_file(req, fsp, NORMAL_CLOSE);
2983 return NT_STATUS_ACCESS_DENIED;
2986 return close_file(req, fsp, NORMAL_CLOSE);
2989 /****************************************************************************
2990 The guts of the unlink command, split out so it may be called by the NT SMB
2992 ****************************************************************************/
2994 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2995 uint32_t dirtype, struct smb_filename *smb_fname,
2998 char *fname_dir = NULL;
2999 char *fname_mask = NULL;
3001 NTSTATUS status = NT_STATUS_OK;
3002 struct smb_filename *smb_fname_dir = NULL;
3003 TALLOC_CTX *ctx = talloc_tos();
3005 /* Split up the directory from the filename/mask. */
3006 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3007 &fname_dir, &fname_mask);
3008 if (!NT_STATUS_IS_OK(status)) {
3013 * We should only check the mangled cache
3014 * here if unix_convert failed. This means
3015 * that the path in 'mask' doesn't exist
3016 * on the file system and so we need to look
3017 * for a possible mangle. This patch from
3018 * Tine Smukavec <valentin.smukavec@hermes.si>.
3021 if (!VALID_STAT(smb_fname->st) &&
3022 mangle_is_mangled(fname_mask, conn->params)) {
3023 char *new_mask = NULL;
3024 mangle_lookup_name_from_8_3(ctx, fname_mask,
3025 &new_mask, conn->params);
3027 TALLOC_FREE(fname_mask);
3028 fname_mask = new_mask;
3035 * Only one file needs to be unlinked. Append the mask back
3036 * onto the directory.
3038 TALLOC_FREE(smb_fname->base_name);
3039 if (ISDOT(fname_dir)) {
3040 /* Ensure we use canonical names on open. */
3041 smb_fname->base_name = talloc_asprintf(smb_fname,
3045 smb_fname->base_name = talloc_asprintf(smb_fname,
3050 if (!smb_fname->base_name) {
3051 status = NT_STATUS_NO_MEMORY;
3055 dirtype = FILE_ATTRIBUTE_NORMAL;
3058 status = check_name(conn, smb_fname);
3059 if (!NT_STATUS_IS_OK(status)) {
3063 status = do_unlink(conn, req, smb_fname, dirtype);
3064 if (!NT_STATUS_IS_OK(status)) {
3070 struct smb_Dir *dir_hnd = NULL;
3072 const char *dname = NULL;
3073 char *talloced = NULL;
3075 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3076 status = NT_STATUS_OBJECT_NAME_INVALID;
3080 dirtype = FILE_ATTRIBUTE_NORMAL;
3083 if (strequal(fname_mask,"????????.???")) {
3084 TALLOC_FREE(fname_mask);
3085 fname_mask = talloc_strdup(ctx, "*");
3087 status = NT_STATUS_NO_MEMORY;
3092 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3097 if (smb_fname_dir == NULL) {
3098 status = NT_STATUS_NO_MEMORY;
3102 status = check_name(conn, smb_fname_dir);
3103 if (!NT_STATUS_IS_OK(status)) {
3107 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3109 if (dir_hnd == NULL) {
3110 status = map_nt_error_from_unix(errno);
3114 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3115 the pattern matches against the long name, otherwise the short name
3116 We don't implement this yet XXXX
3119 status = NT_STATUS_NO_SUCH_FILE;
3121 while ((dname = ReadDirName(dir_hnd, &offset,
3122 &smb_fname->st, &talloced))) {
3123 TALLOC_CTX *frame = talloc_stackframe();
3125 if (!is_visible_file(conn, fname_dir, dname,
3126 &smb_fname->st, true)) {
3128 TALLOC_FREE(talloced);
3132 /* Quick check for "." and ".." */
3133 if (ISDOT(dname) || ISDOTDOT(dname)) {
3135 TALLOC_FREE(talloced);
3139 if(!mask_match(dname, fname_mask,
3140 conn->case_sensitive)) {
3142 TALLOC_FREE(talloced);
3146 TALLOC_FREE(smb_fname->base_name);
3147 if (ISDOT(fname_dir)) {
3148 /* Ensure we use canonical names on open. */
3149 smb_fname->base_name =
3150 talloc_asprintf(smb_fname, "%s",
3153 smb_fname->base_name =
3154 talloc_asprintf(smb_fname, "%s/%s",
3158 if (!smb_fname->base_name) {
3159 TALLOC_FREE(dir_hnd);
3160 status = NT_STATUS_NO_MEMORY;
3162 TALLOC_FREE(talloced);
3166 status = check_name(conn, smb_fname);
3167 if (!NT_STATUS_IS_OK(status)) {
3168 TALLOC_FREE(dir_hnd);
3170 TALLOC_FREE(talloced);
3174 status = do_unlink(conn, req, smb_fname, dirtype);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 TALLOC_FREE(dir_hnd);
3178 TALLOC_FREE(talloced);
3183 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3184 smb_fname->base_name));
3187 TALLOC_FREE(talloced);
3189 TALLOC_FREE(dir_hnd);
3192 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3193 status = map_nt_error_from_unix(errno);
3197 TALLOC_FREE(smb_fname_dir);
3198 TALLOC_FREE(fname_dir);
3199 TALLOC_FREE(fname_mask);
3203 /****************************************************************************
3205 ****************************************************************************/
3207 void reply_unlink(struct smb_request *req)
3209 connection_struct *conn = req->conn;
3211 struct smb_filename *smb_fname = NULL;
3214 bool path_contains_wcard = False;
3215 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3216 ucf_flags_from_smb_request(req);
3217 TALLOC_CTX *ctx = talloc_tos();
3219 START_PROFILE(SMBunlink);
3222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3226 dirtype = SVAL(req->vwv+0, 0);
3228 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3229 STR_TERMINATE, &status,
3230 &path_contains_wcard);
3231 if (!NT_STATUS_IS_OK(status)) {
3232 reply_nterror(req, status);
3236 status = filename_convert(ctx, conn,
3239 &path_contains_wcard,
3241 if (!NT_STATUS_IS_OK(status)) {
3242 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3243 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3244 ERRSRV, ERRbadpath);
3247 reply_nterror(req, status);
3251 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3253 status = unlink_internals(conn, req, dirtype, smb_fname,
3254 path_contains_wcard);
3255 if (!NT_STATUS_IS_OK(status)) {
3256 if (open_was_deferred(req->xconn, req->mid)) {
3257 /* We have re-scheduled this call. */
3260 reply_nterror(req, status);
3264 reply_outbuf(req, 0, 0);
3266 TALLOC_FREE(smb_fname);
3267 END_PROFILE(SMBunlink);
3271 /****************************************************************************
3273 ****************************************************************************/
3275 static void fail_readraw(void)
3277 const char *errstr = talloc_asprintf(talloc_tos(),
3278 "FAIL ! reply_readbraw: socket write fail (%s)",
3283 exit_server_cleanly(errstr);
3286 /****************************************************************************
3287 Fake (read/write) sendfile. Returns -1 on read or write fail.
3288 ****************************************************************************/
3290 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3291 off_t startpos, size_t nread)
3294 size_t tosend = nread;
3301 bufsize = MIN(nread, 65536);
3303 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3307 while (tosend > 0) {
3311 cur_read = MIN(tosend, bufsize);
3312 ret = read_file(fsp,buf,startpos,cur_read);
3318 /* If we had a short read, fill with zeros. */
3319 if (ret < cur_read) {
3320 memset(buf + ret, '\0', cur_read - ret);
3323 ret = write_data(xconn->transport.sock, buf, cur_read);
3324 if (ret != cur_read) {
3325 int saved_errno = errno;
3327 * Try and give an error message saying what
3330 DEBUG(0, ("write_data failed for client %s. "
3332 smbXsrv_connection_dbg(xconn),
3333 strerror(saved_errno)));
3335 errno = saved_errno;
3339 startpos += cur_read;
3343 return (ssize_t)nread;
3346 /****************************************************************************
3347 Deal with the case of sendfile reading less bytes from the file than
3348 requested. Fill with zeros (all we can do). Returns 0 on success
3349 ****************************************************************************/
3351 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3357 #define SHORT_SEND_BUFSIZE 1024
3358 if (nread < headersize) {
3359 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3360 "header for file %s (%s). Terminating\n",
3361 fsp_str_dbg(fsp), strerror(errno)));
3365 nread -= headersize;
3367 if (nread < smb_maxcnt) {
3368 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3370 DEBUG(0,("sendfile_short_send: malloc failed "
3371 "for file %s (%s). Terminating\n",
3372 fsp_str_dbg(fsp), strerror(errno)));
3376 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3377 "with zeros !\n", fsp_str_dbg(fsp)));
3379 while (nread < smb_maxcnt) {
3381 * We asked for the real file size and told sendfile
3382 * to not go beyond the end of the file. But it can
3383 * happen that in between our fstat call and the
3384 * sendfile call the file was truncated. This is very
3385 * bad because we have already announced the larger
3386 * number of bytes to the client.
3388 * The best we can do now is to send 0-bytes, just as
3389 * a read from a hole in a sparse file would do.
3391 * This should happen rarely enough that I don't care
3392 * about efficiency here :-)
3397 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3398 ret = write_data(xconn->transport.sock, buf, to_write);
3399 if (ret != to_write) {
3400 int saved_errno = errno;
3402 * Try and give an error message saying what
3405 DEBUG(0, ("write_data failed for client %s. "
3407 smbXsrv_connection_dbg(xconn),
3408 strerror(saved_errno)));
3409 errno = saved_errno;
3420 /****************************************************************************
3421 Return a readbraw error (4 bytes of zero).
3422 ****************************************************************************/
3424 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3430 smbd_lock_socket(xconn);
3431 if (write_data(xconn->transport.sock,header,4) != 4) {
3432 int saved_errno = errno;
3434 * Try and give an error message saying what
3437 DEBUG(0, ("write_data failed for client %s. "
3439 smbXsrv_connection_dbg(xconn),
3440 strerror(saved_errno)));
3441 errno = saved_errno;
3445 smbd_unlock_socket(xconn);
3448 /****************************************************************************
3449 Use sendfile in readbraw.
3450 ****************************************************************************/
3452 static void send_file_readbraw(connection_struct *conn,
3453 struct smb_request *req,
3459 struct smbXsrv_connection *xconn = req->xconn;
3460 char *outbuf = NULL;
3464 * We can only use sendfile on a non-chained packet
3465 * but we can use on a non-oplocked file. tridge proved this
3466 * on a train in Germany :-). JRA.
3467 * reply_readbraw has already checked the length.
3470 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3471 (fsp->wcp == NULL) &&
3472 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3473 ssize_t sendfile_read = -1;
3475 DATA_BLOB header_blob;
3477 _smb_setlen(header,nread);
3478 header_blob = data_blob_const(header, 4);
3480 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3481 &header_blob, startpos,
3483 if (sendfile_read == -1) {
3484 /* Returning ENOSYS means no data at all was sent.
3485 * Do this as a normal read. */
3486 if (errno == ENOSYS) {
3487 goto normal_readbraw;
3491 * Special hack for broken Linux with no working sendfile. If we
3492 * return EINTR we sent the header but not the rest of the data.
3493 * Fake this up by doing read/write calls.
3495 if (errno == EINTR) {
3496 /* Ensure we don't do this again. */
3497 set_use_sendfile(SNUM(conn), False);
3498 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3500 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3501 DEBUG(0,("send_file_readbraw: "
3502 "fake_sendfile failed for "
3506 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3511 DEBUG(0,("send_file_readbraw: sendfile failed for "
3512 "file %s (%s). Terminating\n",
3513 fsp_str_dbg(fsp), strerror(errno)));
3514 exit_server_cleanly("send_file_readbraw sendfile failed");
3515 } else if (sendfile_read == 0) {
3517 * Some sendfile implementations return 0 to indicate
3518 * that there was a short read, but nothing was
3519 * actually written to the socket. In this case,
3520 * fallback to the normal read path so the header gets
3521 * the correct byte count.
3523 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3524 "bytes falling back to the normal read: "
3525 "%s\n", fsp_str_dbg(fsp)));
3526 goto normal_readbraw;
3529 /* Deal with possible short send. */
3530 if (sendfile_read != 4+nread) {
3531 ret = sendfile_short_send(xconn, fsp,
3532 sendfile_read, 4, nread);
3542 outbuf = talloc_array(NULL, char, nread+4);
3544 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3545 (unsigned)(nread+4)));
3546 reply_readbraw_error(xconn);
3551 ret = read_file(fsp,outbuf+4,startpos,nread);
3552 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3561 _smb_setlen(outbuf,ret);
3562 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3563 int saved_errno = errno;
3565 * Try and give an error message saying what
3568 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3569 smbXsrv_connection_dbg(xconn),
3570 strerror(saved_errno)));
3571 errno = saved_errno;
3576 TALLOC_FREE(outbuf);
3579 /****************************************************************************
3580 Reply to a readbraw (core+ protocol).
3581 ****************************************************************************/
3583 void reply_readbraw(struct smb_request *req)
3585 connection_struct *conn = req->conn;
3586 struct smbXsrv_connection *xconn = req->xconn;
3587 ssize_t maxcount,mincount;
3591 struct lock_struct lock;
3594 START_PROFILE(SMBreadbraw);
3596 if (srv_is_signing_active(xconn) || req->encrypted) {
3597 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3598 "raw reads/writes are disallowed.");
3602 reply_readbraw_error(xconn);
3603 END_PROFILE(SMBreadbraw);
3607 if (xconn->smb1.echo_handler.trusted_fde) {
3608 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3609 "'async smb echo handler = yes'\n"));
3610 reply_readbraw_error(xconn);
3611 END_PROFILE(SMBreadbraw);
3616 * Special check if an oplock break has been issued
3617 * and the readraw request croses on the wire, we must
3618 * return a zero length response here.
3621 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3624 * We have to do a check_fsp by hand here, as
3625 * we must always return 4 zero bytes on error,
3629 if (!fsp || !conn || conn != fsp->conn ||
3630 req->vuid != fsp->vuid ||
3631 fsp->is_directory || fsp->fh->fd == -1) {
3633 * fsp could be NULL here so use the value from the packet. JRA.
3635 DEBUG(3,("reply_readbraw: fnum %d not valid "
3637 (int)SVAL(req->vwv+0, 0)));
3638 reply_readbraw_error(xconn);
3639 END_PROFILE(SMBreadbraw);
3643 /* Do a "by hand" version of CHECK_READ. */
3644 if (!(fsp->can_read ||
3645 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3646 (fsp->access_mask & FILE_EXECUTE)))) {
3647 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3648 (int)SVAL(req->vwv+0, 0)));
3649 reply_readbraw_error(xconn);
3650 END_PROFILE(SMBreadbraw);
3654 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3656 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3657 if(req->wct == 10) {
3659 * This is a large offset (64 bit) read.
3662 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3665 DEBUG(0,("reply_readbraw: negative 64 bit "
3666 "readraw offset (%.0f) !\n",
3667 (double)startpos ));
3668 reply_readbraw_error(xconn);
3669 END_PROFILE(SMBreadbraw);
3674 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3675 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3677 /* ensure we don't overrun the packet size */
3678 maxcount = MIN(65535,maxcount);
3680 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3681 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3684 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3685 reply_readbraw_error(xconn);
3686 END_PROFILE(SMBreadbraw);
3690 if (fsp_stat(fsp) == 0) {
3691 size = fsp->fsp_name->st.st_ex_size;
3694 if (startpos >= size) {
3697 nread = MIN(maxcount,(size - startpos));
3700 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3701 if (nread < mincount)
3705 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3706 "min=%lu nread=%lu\n",
3707 fsp_fnum_dbg(fsp), (double)startpos,
3708 (unsigned long)maxcount,
3709 (unsigned long)mincount,
3710 (unsigned long)nread ) );
3712 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3714 DEBUG(5,("reply_readbraw finished\n"));
3716 END_PROFILE(SMBreadbraw);
3721 #define DBGC_CLASS DBGC_LOCKING
3723 /****************************************************************************
3724 Reply to a lockread (core+ protocol).
3725 ****************************************************************************/
3727 void reply_lockread(struct smb_request *req)
3729 connection_struct *conn = req->conn;
3737 struct byte_range_lock *br_lck = NULL;
3739 struct smbXsrv_connection *xconn = req->xconn;
3741 START_PROFILE(SMBlockread);
3744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3745 END_PROFILE(SMBlockread);
3749 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3751 if (!check_fsp(conn, req, fsp)) {
3752 END_PROFILE(SMBlockread);
3756 if (!CHECK_READ(fsp,req)) {
3757 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3758 END_PROFILE(SMBlockread);
3762 numtoread = SVAL(req->vwv+1, 0);
3763 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3766 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3767 * protocol request that predates the read/write lock concept.
3768 * Thus instead of asking for a read lock here we need to ask
3769 * for a write lock. JRA.
3770 * Note that the requested lock size is unaffected by max_send.
3773 br_lck = do_lock(req->sconn->msg_ctx,
3775 (uint64_t)req->smbpid,
3776 (uint64_t)numtoread,
3780 False, /* Non-blocking lock. */
3783 TALLOC_FREE(br_lck);
3785 if (NT_STATUS_V(status)) {
3786 reply_nterror(req, status);
3787 END_PROFILE(SMBlockread);
3792 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3794 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3796 if (numtoread > maxtoread) {
3797 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3798 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3799 (unsigned int)numtoread, (unsigned int)maxtoread,
3800 (unsigned int)xconn->smb1.sessions.max_send));
3801 numtoread = maxtoread;
3804 reply_outbuf(req, 5, numtoread + 3);
3806 data = smb_buf(req->outbuf) + 3;
3808 nread = read_file(fsp,data,startpos,numtoread);
3811 reply_nterror(req, map_nt_error_from_unix(errno));
3812 END_PROFILE(SMBlockread);
3816 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3818 SSVAL(req->outbuf,smb_vwv0,nread);
3819 SSVAL(req->outbuf,smb_vwv5,nread+3);
3820 p = smb_buf(req->outbuf);
3821 SCVAL(p,0,0); /* pad byte. */
3824 DEBUG(3,("lockread %s num=%d nread=%d\n",
3825 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3827 END_PROFILE(SMBlockread);
3832 #define DBGC_CLASS DBGC_ALL
3834 /****************************************************************************
3836 ****************************************************************************/
3838 void reply_read(struct smb_request *req)
3840 connection_struct *conn = req->conn;
3847 struct lock_struct lock;
3848 struct smbXsrv_connection *xconn = req->xconn;
3850 START_PROFILE(SMBread);
3853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3854 END_PROFILE(SMBread);
3858 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3860 if (!check_fsp(conn, req, fsp)) {
3861 END_PROFILE(SMBread);
3865 if (!CHECK_READ(fsp,req)) {
3866 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3867 END_PROFILE(SMBread);
3871 numtoread = SVAL(req->vwv+1, 0);
3872 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3875 * The requested read size cannot be greater than max_send. JRA.
3877 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3879 if (numtoread > maxtoread) {
3880 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3881 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3882 (unsigned int)numtoread, (unsigned int)maxtoread,
3883 (unsigned int)xconn->smb1.sessions.max_send));
3884 numtoread = maxtoread;
3887 reply_outbuf(req, 5, numtoread+3);
3889 data = smb_buf(req->outbuf) + 3;
3891 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3892 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3895 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3896 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3897 END_PROFILE(SMBread);
3902 nread = read_file(fsp,data,startpos,numtoread);
3905 reply_nterror(req, map_nt_error_from_unix(errno));
3909 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3911 SSVAL(req->outbuf,smb_vwv0,nread);
3912 SSVAL(req->outbuf,smb_vwv5,nread+3);
3913 SCVAL(smb_buf(req->outbuf),0,1);
3914 SSVAL(smb_buf(req->outbuf),1,nread);
3916 DEBUG(3, ("read %s num=%d nread=%d\n",
3917 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3920 END_PROFILE(SMBread);
3924 /****************************************************************************
3926 ****************************************************************************/
3928 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3932 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3935 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3937 SCVAL(outbuf,smb_vwv0,0xFF);
3938 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3939 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3940 SSVAL(outbuf,smb_vwv6,
3941 (smb_wct - 4) /* offset from smb header to wct */
3942 + 1 /* the wct field */
3943 + 12 * sizeof(uint16_t) /* vwv */
3944 + 2 /* the buflen field */
3945 + 1); /* padding byte */
3946 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3947 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3948 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3949 _smb_setlen_large(outbuf,
3950 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3954 /****************************************************************************
3955 Reply to a read and X - possibly using sendfile.
3956 ****************************************************************************/
3958 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3959 files_struct *fsp, off_t startpos,
3962 struct smbXsrv_connection *xconn = req->xconn;
3964 struct lock_struct lock;
3965 int saved_errno = 0;
3967 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3968 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3971 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3972 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3977 * We can only use sendfile on a non-chained packet
3978 * but we can use on a non-oplocked file. tridge proved this
3979 * on a train in Germany :-). JRA.
3982 if (!req_is_in_chain(req) &&
3984 (fsp->base_fsp == NULL) &&
3985 (fsp->wcp == NULL) &&
3986 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3987 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3990 if(fsp_stat(fsp) == -1) {
3991 reply_nterror(req, map_nt_error_from_unix(errno));
3995 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3996 (startpos > fsp->fsp_name->st.st_ex_size) ||
3997 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3999 * We already know that we would do a short read, so don't
4000 * try the sendfile() path.
4002 goto nosendfile_read;
4006 * Set up the packet header before send. We
4007 * assume here the sendfile will work (get the
4008 * correct amount of data).
4011 header = data_blob_const(headerbuf, sizeof(headerbuf));
4013 construct_reply_common_req(req, (char *)headerbuf);
4014 setup_readX_header((char *)headerbuf, smb_maxcnt);
4016 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4017 startpos, smb_maxcnt);
4019 saved_errno = errno;
4021 /* Returning ENOSYS means no data at all was sent.
4022 Do this as a normal read. */
4023 if (errno == ENOSYS) {
4028 * Special hack for broken Linux with no working sendfile. If we
4029 * return EINTR we sent the header but not the rest of the data.
4030 * Fake this up by doing read/write calls.
4033 if (errno == EINTR) {
4034 /* Ensure we don't do this again. */
4035 set_use_sendfile(SNUM(conn), False);
4036 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4037 nread = fake_sendfile(xconn, fsp, startpos,
4040 saved_errno = errno;
4041 DEBUG(0,("send_file_readX: "
4042 "fake_sendfile failed for "
4043 "file %s (%s) for client %s. "
4046 smbXsrv_connection_dbg(xconn),
4047 strerror(saved_errno)));
4048 errno = saved_errno;
4049 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4051 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4052 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4053 /* No outbuf here means successful sendfile. */
4057 DEBUG(0,("send_file_readX: sendfile failed for file "
4058 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4060 exit_server_cleanly("send_file_readX sendfile failed");
4061 } else if (nread == 0) {
4063 * Some sendfile implementations return 0 to indicate
4064 * that there was a short read, but nothing was
4065 * actually written to the socket. In this case,
4066 * fallback to the normal read path so the header gets
4067 * the correct byte count.
4069 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4070 "falling back to the normal read: %s\n",
4075 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4076 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4078 /* Deal with possible short send. */
4079 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4082 ret = sendfile_short_send(xconn, fsp, nread,
4083 sizeof(headerbuf), smb_maxcnt);
4086 r = "send_file_readX: sendfile_short_send failed";
4087 DEBUG(0,("%s for file %s (%s).\n",
4088 r, fsp_str_dbg(fsp), strerror(errno)));
4089 exit_server_cleanly(r);
4092 /* No outbuf here means successful sendfile. */
4093 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4094 SMB_PERFCOUNT_END(&req->pcd);
4100 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4101 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4104 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4105 (startpos > fsp->fsp_name->st.st_ex_size) ||
4106 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4108 * We already know that we would do a short
4109 * read, so don't try the sendfile() path.
4111 goto nosendfile_read;
4114 construct_reply_common_req(req, (char *)headerbuf);
4115 setup_readX_header((char *)headerbuf, smb_maxcnt);
4117 /* Send out the header. */
4118 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4120 if (ret != sizeof(headerbuf)) {
4121 saved_errno = errno;
4123 * Try and give an error message saying what
4126 DEBUG(0,("send_file_readX: write_data failed for file "
4127 "%s (%s) for client %s. Terminating\n",
4129 smbXsrv_connection_dbg(xconn),
4130 strerror(saved_errno)));
4131 errno = saved_errno;
4132 exit_server_cleanly("send_file_readX sendfile failed");
4134 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4136 saved_errno = errno;
4137 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4138 "%s (%s) for client %s. Terminating\n",
4140 smbXsrv_connection_dbg(xconn),
4141 strerror(saved_errno)));
4142 errno = saved_errno;
4143 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4150 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4151 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4152 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4154 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4155 startpos, smb_maxcnt);
4156 saved_errno = errno;
4159 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4163 setup_readX_header((char *)req->outbuf, nread);
4165 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4166 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4170 TALLOC_FREE(req->outbuf);
4174 /****************************************************************************
4175 Work out how much space we have for a read return.
4176 ****************************************************************************/
4178 static size_t calc_max_read_pdu(const struct smb_request *req)
4180 struct smbXsrv_connection *xconn = req->xconn;
4182 if (xconn->protocol < PROTOCOL_NT1) {
4183 return xconn->smb1.sessions.max_send;
4186 if (!lp_large_readwrite()) {
4187 return xconn->smb1.sessions.max_send;
4190 if (req_is_in_chain(req)) {
4191 return xconn->smb1.sessions.max_send;
4194 if (req->encrypted) {
4196 * Don't take encrypted traffic up to the
4197 * limit. There are padding considerations
4198 * that make that tricky.
4200 return xconn->smb1.sessions.max_send;
4203 if (srv_is_signing_active(xconn)) {
4207 if (!lp_unix_extensions()) {
4212 * We can do ultra-large POSIX reads.
4217 /****************************************************************************
4218 Calculate how big a read can be. Copes with all clients. It's always
4219 safe to return a short read - Windows does this.
4220 ****************************************************************************/
4222 static size_t calc_read_size(const struct smb_request *req,
4226 struct smbXsrv_connection *xconn = req->xconn;
4227 size_t max_pdu = calc_max_read_pdu(req);
4228 size_t total_size = 0;
4229 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4230 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4233 * Windows explicitly ignores upper size of 0xFFFF.
4234 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4235 * We must do the same as these will never fit even in
4236 * an extended size NetBIOS packet.
4238 if (upper_size == 0xFFFF) {
4242 if (xconn->protocol < PROTOCOL_NT1) {
4246 total_size = ((upper_size<<16) | lower_size);
4249 * LARGE_READX test shows it's always safe to return
4250 * a short read. Windows does so.
4252 return MIN(total_size, max_len);
4255 /****************************************************************************
4256 Reply to a read and X.
4257 ****************************************************************************/
4259 void reply_read_and_X(struct smb_request *req)
4261 connection_struct *conn = req->conn;
4266 bool big_readX = False;
4268 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4271 START_PROFILE(SMBreadX);
4273 if ((req->wct != 10) && (req->wct != 12)) {
4274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4278 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4279 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4280 smb_maxcnt = SVAL(req->vwv+5, 0);
4282 /* If it's an IPC, pass off the pipe handler. */
4284 reply_pipe_read_and_X(req);
4285 END_PROFILE(SMBreadX);
4289 if (!check_fsp(conn, req, fsp)) {
4290 END_PROFILE(SMBreadX);
4294 if (!CHECK_READ(fsp,req)) {
4295 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4296 END_PROFILE(SMBreadX);
4300 upper_size = SVAL(req->vwv+7, 0);
4301 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4302 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4304 * This is a heuristic to avoid keeping large
4305 * outgoing buffers around over long-lived aio
4311 if (req->wct == 12) {
4313 * This is a large offset (64 bit) read.
4315 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4320 NTSTATUS status = schedule_aio_read_and_X(conn,
4325 if (NT_STATUS_IS_OK(status)) {
4326 /* Read scheduled - we're done. */
4329 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4330 /* Real error - report to client. */
4331 END_PROFILE(SMBreadX);
4332 reply_nterror(req, status);
4335 /* NT_STATUS_RETRY - fall back to sync read. */
4338 smbd_lock_socket(req->xconn);
4339 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4340 smbd_unlock_socket(req->xconn);
4343 END_PROFILE(SMBreadX);
4347 /****************************************************************************
4348 Error replies to writebraw must have smb_wct == 1. Fix this up.
4349 ****************************************************************************/
4351 void error_to_writebrawerr(struct smb_request *req)
4353 uint8_t *old_outbuf = req->outbuf;
4355 reply_outbuf(req, 1, 0);
4357 memcpy(req->outbuf, old_outbuf, smb_size);
4358 TALLOC_FREE(old_outbuf);
4361 /****************************************************************************
4362 Read 4 bytes of a smb packet and return the smb length of the packet.
4363 Store the result in the buffer. This version of the function will
4364 never return a session keepalive (length of zero).
4365 Timeout is in milliseconds.
4366 ****************************************************************************/
4368 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4371 uint8_t msgtype = NBSSkeepalive;
4373 while (msgtype == NBSSkeepalive) {
4376 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4378 if (!NT_STATUS_IS_OK(status)) {
4379 char addr[INET6_ADDRSTRLEN];
4380 /* Try and give an error message
4381 * saying what client failed. */
4382 DEBUG(0, ("read_fd_with_timeout failed for "
4383 "client %s read error = %s.\n",
4384 get_peer_addr(fd,addr,sizeof(addr)),
4385 nt_errstr(status)));
4389 msgtype = CVAL(inbuf, 0);
4392 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4393 (unsigned long)len));
4395 return NT_STATUS_OK;
4398 /****************************************************************************
4399 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4400 ****************************************************************************/
4402 void reply_writebraw(struct smb_request *req)
4404 connection_struct *conn = req->conn;
4405 struct smbXsrv_connection *xconn = req->xconn;
4408 ssize_t total_written=0;
4409 size_t numtowrite=0;
4412 const char *data=NULL;
4415 struct lock_struct lock;
4418 START_PROFILE(SMBwritebraw);
4421 * If we ever reply with an error, it must have the SMB command
4422 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4425 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4427 if (srv_is_signing_active(xconn)) {
4428 END_PROFILE(SMBwritebraw);
4429 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4430 "raw reads/writes are disallowed.");
4433 if (req->wct < 12) {
4434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4435 error_to_writebrawerr(req);
4436 END_PROFILE(SMBwritebraw);
4440 if (xconn->smb1.echo_handler.trusted_fde) {
4441 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4442 "'async smb echo handler = yes'\n"));
4443 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4444 error_to_writebrawerr(req);
4445 END_PROFILE(SMBwritebraw);
4449 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4450 if (!check_fsp(conn, req, fsp)) {
4451 error_to_writebrawerr(req);
4452 END_PROFILE(SMBwritebraw);
4456 if (!CHECK_WRITE(fsp)) {
4457 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4458 error_to_writebrawerr(req);
4459 END_PROFILE(SMBwritebraw);
4463 tcount = IVAL(req->vwv+1, 0);
4464 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4465 write_through = BITSETW(req->vwv+7,0);
4467 /* We have to deal with slightly different formats depending
4468 on whether we are using the core+ or lanman1.0 protocol */
4470 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4471 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4472 data = smb_buf_const(req->inbuf);
4474 numtowrite = SVAL(req->vwv+10, 0);
4475 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4478 /* Ensure we don't write bytes past the end of this packet. */
4480 * This already protects us against CVE-2017-12163.
4482 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4483 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4484 error_to_writebrawerr(req);
4485 END_PROFILE(SMBwritebraw);
4489 if (!fsp->print_file) {
4490 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4491 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4494 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4495 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4496 error_to_writebrawerr(req);
4497 END_PROFILE(SMBwritebraw);
4503 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4506 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4507 "wrote=%d sync=%d\n",
4508 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4509 (int)nwritten, (int)write_through));
4511 if (nwritten < (ssize_t)numtowrite) {
4512 reply_nterror(req, NT_STATUS_DISK_FULL);
4513 error_to_writebrawerr(req);
4517 total_written = nwritten;
4519 /* Allocate a buffer of 64k + length. */
4520 buf = talloc_array(NULL, char, 65540);
4522 reply_nterror(req, NT_STATUS_NO_MEMORY);
4523 error_to_writebrawerr(req);
4527 /* Return a SMBwritebraw message to the redirector to tell
4528 * it to send more bytes */
4530 memcpy(buf, req->inbuf, smb_size);
4531 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4532 SCVAL(buf,smb_com,SMBwritebraw);
4533 SSVALS(buf,smb_vwv0,0xFFFF);
4535 if (!srv_send_smb(req->xconn,
4537 false, 0, /* no signing */
4538 IS_CONN_ENCRYPTED(conn),
4540 exit_server_cleanly("reply_writebraw: srv_send_smb "
4544 /* Now read the raw data into the buffer and write it */
4545 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4547 if (!NT_STATUS_IS_OK(status)) {
4548 exit_server_cleanly("secondary writebraw failed");
4551 /* Set up outbuf to return the correct size */
4552 reply_outbuf(req, 1, 0);
4554 if (numtowrite != 0) {
4556 if (numtowrite > 0xFFFF) {
4557 DEBUG(0,("reply_writebraw: Oversize secondary write "
4558 "raw requested (%u). Terminating\n",
4559 (unsigned int)numtowrite ));
4560 exit_server_cleanly("secondary writebraw failed");
4563 if (tcount > nwritten+numtowrite) {
4564 DEBUG(3,("reply_writebraw: Client overestimated the "
4566 (int)tcount,(int)nwritten,(int)numtowrite));
4569 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4572 if (!NT_STATUS_IS_OK(status)) {
4573 /* Try and give an error message
4574 * saying what client failed. */
4575 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4576 "raw read failed (%s) for client %s. "
4577 "Terminating\n", nt_errstr(status),
4578 smbXsrv_connection_dbg(xconn)));
4579 exit_server_cleanly("secondary writebraw failed");
4583 * We are not vulnerable to CVE-2017-12163
4584 * here as we are guarenteed to have numtowrite
4585 * bytes available - we just read from the client.
4587 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4588 if (nwritten == -1) {
4590 reply_nterror(req, map_nt_error_from_unix(errno));
4591 error_to_writebrawerr(req);
4595 if (nwritten < (ssize_t)numtowrite) {
4596 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4597 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4601 total_written += nwritten;
4606 SSVAL(req->outbuf,smb_vwv0,total_written);
4608 status = sync_file(conn, fsp, write_through);
4609 if (!NT_STATUS_IS_OK(status)) {
4610 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4611 fsp_str_dbg(fsp), nt_errstr(status)));
4612 reply_nterror(req, status);
4613 error_to_writebrawerr(req);
4617 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4619 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4620 (int)total_written));
4622 /* We won't return a status if write through is not selected - this
4623 * follows what WfWg does */
4624 END_PROFILE(SMBwritebraw);
4626 if (!write_through && total_written==tcount) {
4628 #if RABBIT_PELLET_FIX
4630 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4631 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4634 if (!send_keepalive(xconn->transport.sock)) {
4635 exit_server_cleanly("reply_writebraw: send of "
4636 "keepalive failed");
4639 TALLOC_FREE(req->outbuf);
4644 END_PROFILE(SMBwritebraw);
4649 #define DBGC_CLASS DBGC_LOCKING
4651 /****************************************************************************
4652 Reply to a writeunlock (core+).
4653 ****************************************************************************/
4655 void reply_writeunlock(struct smb_request *req)
4657 connection_struct *conn = req->conn;
4658 ssize_t nwritten = -1;
4663 NTSTATUS status = NT_STATUS_OK;
4665 struct lock_struct lock;
4666 int saved_errno = 0;
4668 START_PROFILE(SMBwriteunlock);
4671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4672 END_PROFILE(SMBwriteunlock);
4676 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4678 if (!check_fsp(conn, req, fsp)) {
4679 END_PROFILE(SMBwriteunlock);
4683 if (!CHECK_WRITE(fsp)) {
4684 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4685 END_PROFILE(SMBwriteunlock);
4689 numtowrite = SVAL(req->vwv+1, 0);
4690 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4691 data = (const char *)req->buf + 3;
4694 * Ensure client isn't asking us to write more than
4695 * they sent. CVE-2017-12163.
4697 remaining = smbreq_bufrem(req, data);
4698 if (numtowrite > remaining) {
4699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4700 END_PROFILE(SMBwriteunlock);
4704 if (!fsp->print_file && numtowrite > 0) {
4705 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4706 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4709 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4710 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4711 END_PROFILE(SMBwriteunlock);
4716 /* The special X/Open SMB protocol handling of
4717 zero length writes is *NOT* done for
4719 if(numtowrite == 0) {
4722 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4723 saved_errno = errno;
4726 status = sync_file(conn, fsp, False /* write through */);
4727 if (!NT_STATUS_IS_OK(status)) {
4728 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4729 fsp_str_dbg(fsp), nt_errstr(status)));
4730 reply_nterror(req, status);
4735 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4739 if((nwritten < numtowrite) && (numtowrite != 0)) {
4740 reply_nterror(req, NT_STATUS_DISK_FULL);
4744 if (numtowrite && !fsp->print_file) {
4745 status = do_unlock(req->sconn->msg_ctx,
4747 (uint64_t)req->smbpid,
4748 (uint64_t)numtowrite,
4752 if (NT_STATUS_V(status)) {
4753 reply_nterror(req, status);
4758 reply_outbuf(req, 1, 0);
4760 SSVAL(req->outbuf,smb_vwv0,nwritten);
4762 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4763 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4766 END_PROFILE(SMBwriteunlock);
4771 #define DBGC_CLASS DBGC_ALL
4773 /****************************************************************************
4775 ****************************************************************************/
4777 void reply_write(struct smb_request *req)
4779 connection_struct *conn = req->conn;
4782 ssize_t nwritten = -1;
4786 struct lock_struct lock;
4788 int saved_errno = 0;
4790 START_PROFILE(SMBwrite);
4793 END_PROFILE(SMBwrite);
4794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4798 /* If it's an IPC, pass off the pipe handler. */
4800 reply_pipe_write(req);
4801 END_PROFILE(SMBwrite);
4805 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4807 if (!check_fsp(conn, req, fsp)) {
4808 END_PROFILE(SMBwrite);
4812 if (!CHECK_WRITE(fsp)) {
4813 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4814 END_PROFILE(SMBwrite);
4818 numtowrite = SVAL(req->vwv+1, 0);
4819 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4820 data = (const char *)req->buf + 3;
4823 * Ensure client isn't asking us to write more than
4824 * they sent. CVE-2017-12163.
4826 remaining = smbreq_bufrem(req, data);
4827 if (numtowrite > remaining) {
4828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4829 END_PROFILE(SMBwrite);
4833 if (!fsp->print_file) {
4834 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4835 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4838 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4839 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4840 END_PROFILE(SMBwrite);
4846 * X/Open SMB protocol says that if smb_vwv1 is
4847 * zero then the file size should be extended or
4848 * truncated to the size given in smb_vwv[2-3].
4851 if(numtowrite == 0) {
4853 * This is actually an allocate call, and set EOF. JRA.
4855 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4857 reply_nterror(req, NT_STATUS_DISK_FULL);
4860 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4862 reply_nterror(req, NT_STATUS_DISK_FULL);
4865 trigger_write_time_update_immediate(fsp);
4867 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4870 status = sync_file(conn, fsp, False);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4873 fsp_str_dbg(fsp), nt_errstr(status)));
4874 reply_nterror(req, status);
4879 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4883 if((nwritten == 0) && (numtowrite != 0)) {
4884 reply_nterror(req, NT_STATUS_DISK_FULL);
4888 reply_outbuf(req, 1, 0);
4890 SSVAL(req->outbuf,smb_vwv0,nwritten);
4892 if (nwritten < (ssize_t)numtowrite) {
4893 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4894 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4897 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4900 END_PROFILE(SMBwrite);
4904 /****************************************************************************
4905 Ensure a buffer is a valid writeX for recvfile purposes.
4906 ****************************************************************************/
4908 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4909 (2*14) + /* word count (including bcc) */ \
4912 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4913 const uint8_t *inbuf)
4916 unsigned int doff = 0;
4917 size_t len = smb_len_large(inbuf);
4919 struct smbXsrv_open *op = NULL;
4920 struct files_struct *fsp = NULL;
4923 if (is_encrypted_packet(inbuf)) {
4924 /* Can't do this on encrypted
4929 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4933 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4934 CVAL(inbuf,smb_wct) != 14) {
4935 DEBUG(10,("is_valid_writeX_buffer: chained or "
4936 "invalid word length.\n"));
4940 fnum = SVAL(inbuf, smb_vwv2);
4941 status = smb1srv_open_lookup(xconn,
4945 if (!NT_STATUS_IS_OK(status)) {
4946 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4951 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4954 if (fsp->conn == NULL) {
4955 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4959 if (IS_IPC(fsp->conn)) {
4960 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4963 if (IS_PRINT(fsp->conn)) {
4964 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4967 doff = SVAL(inbuf,smb_vwv11);
4969 numtowrite = SVAL(inbuf,smb_vwv10);
4971 if (len > doff && len - doff > 0xFFFF) {
4972 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4975 if (numtowrite == 0) {
4976 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4980 /* Ensure the sizes match up. */
4981 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4982 /* no pad byte...old smbclient :-( */
4983 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4985 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4989 if (len - doff != numtowrite) {
4990 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4991 "len = %u, doff = %u, numtowrite = %u\n",
4994 (unsigned int)numtowrite ));
4998 DEBUG(10,("is_valid_writeX_buffer: true "
4999 "len = %u, doff = %u, numtowrite = %u\n",
5002 (unsigned int)numtowrite ));
5007 /****************************************************************************
5008 Reply to a write and X.
5009 ****************************************************************************/
5011 void reply_write_and_X(struct smb_request *req)
5013 connection_struct *conn = req->conn;
5014 struct smbXsrv_connection *xconn = req->xconn;
5016 struct lock_struct lock;
5021 unsigned int smb_doff;
5022 unsigned int smblen;
5025 int saved_errno = 0;
5027 START_PROFILE(SMBwriteX);
5029 if ((req->wct != 12) && (req->wct != 14)) {
5030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5034 numtowrite = SVAL(req->vwv+10, 0);
5035 smb_doff = SVAL(req->vwv+11, 0);
5036 smblen = smb_len(req->inbuf);
5038 if (req->unread_bytes > 0xFFFF ||
5039 (smblen > smb_doff &&
5040 smblen - smb_doff > 0xFFFF)) {
5041 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5044 if (req->unread_bytes) {
5045 /* Can't do a recvfile write on IPC$ */
5047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5050 if (numtowrite != req->unread_bytes) {
5051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5056 * This already protects us against CVE-2017-12163.
5058 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5059 smb_doff + numtowrite > smblen) {
5060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5065 /* If it's an IPC, pass off the pipe handler. */
5067 if (req->unread_bytes) {
5068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5071 reply_pipe_write_and_X(req);
5075 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5076 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5077 write_through = BITSETW(req->vwv+7,0);
5079 if (!check_fsp(conn, req, fsp)) {
5083 if (!CHECK_WRITE(fsp)) {
5084 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5088 data = smb_base(req->inbuf) + smb_doff;
5090 if(req->wct == 14) {
5092 * This is a large offset (64 bit) write.
5094 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5098 /* X/Open SMB protocol says that, unlike SMBwrite
5099 if the length is zero then NO truncation is
5100 done, just a write of zero. To truncate a file,
5103 if(numtowrite == 0) {
5106 if (req->unread_bytes == 0) {
5107 status = schedule_aio_write_and_X(conn,
5114 if (NT_STATUS_IS_OK(status)) {
5115 /* write scheduled - we're done. */
5118 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5119 /* Real error - report to client. */
5120 reply_nterror(req, status);
5123 /* NT_STATUS_RETRY - fall through to sync write. */
5126 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5127 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5130 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5131 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5135 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5136 saved_errno = errno;
5140 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5144 if((nwritten == 0) && (numtowrite != 0)) {
5145 reply_nterror(req, NT_STATUS_DISK_FULL);
5149 reply_outbuf(req, 6, 0);
5150 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5151 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5152 SSVAL(req->outbuf,smb_vwv2,nwritten);
5153 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5155 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5156 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5158 status = sync_file(conn, fsp, write_through);
5159 if (!NT_STATUS_IS_OK(status)) {
5160 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5161 fsp_str_dbg(fsp), nt_errstr(status)));
5162 reply_nterror(req, status);
5166 END_PROFILE(SMBwriteX);
5170 if (req->unread_bytes) {
5171 /* writeX failed. drain socket. */
5172 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5173 req->unread_bytes) {
5174 smb_panic("failed to drain pending bytes");
5176 req->unread_bytes = 0;
5179 END_PROFILE(SMBwriteX);
5183 /****************************************************************************
5185 ****************************************************************************/
5187 void reply_lseek(struct smb_request *req)
5189 connection_struct *conn = req->conn;
5195 START_PROFILE(SMBlseek);
5198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5199 END_PROFILE(SMBlseek);
5203 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5205 if (!check_fsp(conn, req, fsp)) {
5209 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5211 mode = SVAL(req->vwv+1, 0) & 3;
5212 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5213 startpos = (off_t)IVALS(req->vwv+2, 0);
5222 res = fsp->fh->pos + startpos;
5233 if (umode == SEEK_END) {
5234 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5235 if(errno == EINVAL) {
5236 off_t current_pos = startpos;
5238 if(fsp_stat(fsp) == -1) {
5240 map_nt_error_from_unix(errno));
5241 END_PROFILE(SMBlseek);
5245 current_pos += fsp->fsp_name->st.st_ex_size;
5247 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5252 reply_nterror(req, map_nt_error_from_unix(errno));
5253 END_PROFILE(SMBlseek);
5260 reply_outbuf(req, 2, 0);
5261 SIVAL(req->outbuf,smb_vwv0,res);
5263 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5264 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5266 END_PROFILE(SMBlseek);
5270 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5273 connection_struct *conn = talloc_get_type_abort(
5274 private_data, connection_struct);
5276 if (conn != fsp->conn) {
5279 if (fsp->fh->fd == -1) {
5282 sync_file(conn, fsp, True /* write through */);
5287 /****************************************************************************
5289 ****************************************************************************/
5291 void reply_flush(struct smb_request *req)
5293 connection_struct *conn = req->conn;
5297 START_PROFILE(SMBflush);
5300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5304 fnum = SVAL(req->vwv+0, 0);
5305 fsp = file_fsp(req, fnum);
5307 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5312 files_forall(req->sconn, file_sync_one_fn, conn);
5314 NTSTATUS status = sync_file(conn, fsp, True);
5315 if (!NT_STATUS_IS_OK(status)) {
5316 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5317 fsp_str_dbg(fsp), nt_errstr(status)));
5318 reply_nterror(req, status);
5319 END_PROFILE(SMBflush);
5324 reply_outbuf(req, 0, 0);
5326 DEBUG(3,("flush\n"));
5327 END_PROFILE(SMBflush);
5331 /****************************************************************************
5333 conn POINTER CAN BE NULL HERE !
5334 ****************************************************************************/
5336 void reply_exit(struct smb_request *req)
5338 START_PROFILE(SMBexit);
5340 file_close_pid(req->sconn, req->smbpid, req->vuid);
5342 reply_outbuf(req, 0, 0);
5344 DEBUG(3,("exit\n"));
5346 END_PROFILE(SMBexit);
5350 struct reply_close_state {
5352 struct smb_request *smbreq;
5355 static void do_smb1_close(struct tevent_req *req);
5357 void reply_close(struct smb_request *req)
5359 connection_struct *conn = req->conn;
5360 NTSTATUS status = NT_STATUS_OK;
5361 files_struct *fsp = NULL;
5362 START_PROFILE(SMBclose);
5365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5366 END_PROFILE(SMBclose);
5370 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5373 * We can only use check_fsp if we know it's not a directory.
5376 if (!check_fsp_open(conn, req, fsp)) {
5377 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5378 END_PROFILE(SMBclose);
5382 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5383 fsp->is_directory ? "directory" : "file",
5384 fsp->fh->fd, fsp_fnum_dbg(fsp),
5385 conn->num_files_open));
5387 if (!fsp->is_directory) {
5391 * Take care of any time sent in the close.
5394 t = srv_make_unix_date3(req->vwv+1);
5395 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5398 if (fsp->num_aio_requests != 0) {
5400 struct reply_close_state *state;
5402 DEBUG(10, ("closing with aio %u requests pending\n",
5403 fsp->num_aio_requests));
5406 * We depend on the aio_extra destructor to take care of this
5407 * close request once fsp->num_aio_request drops to 0.
5410 fsp->deferred_close = tevent_wait_send(
5412 if (fsp->deferred_close == NULL) {
5413 status = NT_STATUS_NO_MEMORY;
5417 state = talloc(fsp, struct reply_close_state);
5418 if (state == NULL) {
5419 TALLOC_FREE(fsp->deferred_close);
5420 status = NT_STATUS_NO_MEMORY;
5424 state->smbreq = talloc_move(fsp, &req);
5425 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5427 END_PROFILE(SMBclose);
5432 * close_file() returns the unix errno if an error was detected on
5433 * close - normally this is due to a disk full error. If not then it
5434 * was probably an I/O error.
5437 status = close_file(req, fsp, NORMAL_CLOSE);
5439 if (!NT_STATUS_IS_OK(status)) {
5440 reply_nterror(req, status);
5441 END_PROFILE(SMBclose);
5445 reply_outbuf(req, 0, 0);
5446 END_PROFILE(SMBclose);
5450 static void do_smb1_close(struct tevent_req *req)
5452 struct reply_close_state *state = tevent_req_callback_data(
5453 req, struct reply_close_state);
5454 struct smb_request *smbreq;
5458 ret = tevent_wait_recv(req);
5461 DEBUG(10, ("tevent_wait_recv returned %s\n",
5464 * Continue anyway, this should never happen
5469 * fsp->smb2_close_request right now is a talloc grandchild of
5470 * fsp. When we close_file(fsp), it would go with it. No chance to
5473 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5475 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5476 if (NT_STATUS_IS_OK(status)) {
5477 reply_outbuf(smbreq, 0, 0);
5479 reply_nterror(smbreq, status);
5481 if (!srv_send_smb(smbreq->xconn,
5482 (char *)smbreq->outbuf,
5485 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5487 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5490 TALLOC_FREE(smbreq);
5493 /****************************************************************************
5494 Reply to a writeclose (Core+ protocol).
5495 ****************************************************************************/
5497 void reply_writeclose(struct smb_request *req)
5499 connection_struct *conn = req->conn;
5502 ssize_t nwritten = -1;
5503 NTSTATUS close_status = NT_STATUS_OK;
5506 struct timespec mtime;
5508 struct lock_struct lock;
5510 START_PROFILE(SMBwriteclose);
5513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5514 END_PROFILE(SMBwriteclose);
5518 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5520 if (!check_fsp(conn, req, fsp)) {
5521 END_PROFILE(SMBwriteclose);
5524 if (!CHECK_WRITE(fsp)) {
5525 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5526 END_PROFILE(SMBwriteclose);
5530 numtowrite = SVAL(req->vwv+1, 0);
5531 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5532 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5533 data = (const char *)req->buf + 1;
5536 * Ensure client isn't asking us to write more than
5537 * they sent. CVE-2017-12163.
5539 remaining = smbreq_bufrem(req, data);
5540 if (numtowrite > remaining) {
5541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5542 END_PROFILE(SMBwriteclose);
5546 if (fsp->print_file == NULL) {
5547 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5548 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5551 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5552 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5553 END_PROFILE(SMBwriteclose);
5558 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5560 set_close_write_time(fsp, mtime);
5563 * More insanity. W2K only closes the file if writelen > 0.
5567 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5568 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5569 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5572 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5573 "file %s\n", fsp_str_dbg(fsp)));
5574 close_status = close_file(req, fsp, NORMAL_CLOSE);
5578 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5579 reply_nterror(req, NT_STATUS_DISK_FULL);
5583 if(!NT_STATUS_IS_OK(close_status)) {
5584 reply_nterror(req, close_status);
5588 reply_outbuf(req, 1, 0);
5590 SSVAL(req->outbuf,smb_vwv0,nwritten);
5594 END_PROFILE(SMBwriteclose);
5599 #define DBGC_CLASS DBGC_LOCKING
5601 /****************************************************************************
5603 ****************************************************************************/
5605 void reply_lock(struct smb_request *req)
5607 connection_struct *conn = req->conn;
5608 uint64_t count,offset;
5611 struct byte_range_lock *br_lck = NULL;
5613 START_PROFILE(SMBlock);
5616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5617 END_PROFILE(SMBlock);
5621 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5623 if (!check_fsp(conn, req, fsp)) {
5624 END_PROFILE(SMBlock);
5628 count = (uint64_t)IVAL(req->vwv+1, 0);
5629 offset = (uint64_t)IVAL(req->vwv+3, 0);
5631 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5632 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5634 br_lck = do_lock(req->sconn->msg_ctx,
5636 (uint64_t)req->smbpid,
5641 False, /* Non-blocking lock. */
5645 TALLOC_FREE(br_lck);
5647 if (NT_STATUS_V(status)) {
5648 reply_nterror(req, status);
5649 END_PROFILE(SMBlock);
5653 reply_outbuf(req, 0, 0);
5655 END_PROFILE(SMBlock);
5659 /****************************************************************************
5661 ****************************************************************************/
5663 void reply_unlock(struct smb_request *req)
5665 connection_struct *conn = req->conn;
5666 uint64_t count,offset;
5670 START_PROFILE(SMBunlock);
5673 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5674 END_PROFILE(SMBunlock);
5678 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5680 if (!check_fsp(conn, req, fsp)) {
5681 END_PROFILE(SMBunlock);
5685 count = (uint64_t)IVAL(req->vwv+1, 0);
5686 offset = (uint64_t)IVAL(req->vwv+3, 0);
5688 status = do_unlock(req->sconn->msg_ctx,
5690 (uint64_t)req->smbpid,
5695 if (NT_STATUS_V(status)) {
5696 reply_nterror(req, status);
5697 END_PROFILE(SMBunlock);
5701 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5702 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5704 reply_outbuf(req, 0, 0);
5706 END_PROFILE(SMBunlock);
5711 #define DBGC_CLASS DBGC_ALL
5713 /****************************************************************************
5715 conn POINTER CAN BE NULL HERE !
5716 ****************************************************************************/
5718 void reply_tdis(struct smb_request *req)
5721 connection_struct *conn = req->conn;
5722 struct smbXsrv_tcon *tcon;
5724 START_PROFILE(SMBtdis);
5727 DEBUG(4,("Invalid connection in tdis\n"));
5728 reply_force_doserror(req, ERRSRV, ERRinvnid);
5729 END_PROFILE(SMBtdis);
5737 * TODO: cancel all outstanding requests on the tcon
5739 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5740 if (!NT_STATUS_IS_OK(status)) {
5741 DEBUG(0, ("reply_tdis: "
5742 "smbXsrv_tcon_disconnect() failed: %s\n",
5743 nt_errstr(status)));
5745 * If we hit this case, there is something completely
5746 * wrong, so we better disconnect the transport connection.
5748 END_PROFILE(SMBtdis);
5749 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5755 reply_outbuf(req, 0, 0);
5756 END_PROFILE(SMBtdis);
5760 /****************************************************************************
5762 conn POINTER CAN BE NULL HERE !
5763 ****************************************************************************/
5765 void reply_echo(struct smb_request *req)
5767 connection_struct *conn = req->conn;
5768 struct smb_perfcount_data local_pcd;
5769 struct smb_perfcount_data *cur_pcd;
5773 START_PROFILE(SMBecho);
5775 smb_init_perfcount_data(&local_pcd);
5778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5779 END_PROFILE(SMBecho);
5783 smb_reverb = SVAL(req->vwv+0, 0);
5785 reply_outbuf(req, 1, req->buflen);
5787 /* copy any incoming data back out */
5788 if (req->buflen > 0) {
5789 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5792 if (smb_reverb > 100) {
5793 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5797 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5799 /* this makes sure we catch the request pcd */
5800 if (seq_num == smb_reverb) {
5801 cur_pcd = &req->pcd;
5803 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5804 cur_pcd = &local_pcd;
5807 SSVAL(req->outbuf,smb_vwv0,seq_num);
5809 show_msg((char *)req->outbuf);
5810 if (!srv_send_smb(req->xconn,
5811 (char *)req->outbuf,
5812 true, req->seqnum+1,
5813 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5815 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5818 DEBUG(3,("echo %d times\n", smb_reverb));
5820 TALLOC_FREE(req->outbuf);
5822 END_PROFILE(SMBecho);
5826 /****************************************************************************
5827 Reply to a printopen.
5828 ****************************************************************************/
5830 void reply_printopen(struct smb_request *req)
5832 connection_struct *conn = req->conn;
5836 START_PROFILE(SMBsplopen);
5839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5840 END_PROFILE(SMBsplopen);
5844 if (!CAN_PRINT(conn)) {
5845 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5846 END_PROFILE(SMBsplopen);
5850 status = file_new(req, conn, &fsp);
5851 if(!NT_STATUS_IS_OK(status)) {
5852 reply_nterror(req, status);
5853 END_PROFILE(SMBsplopen);
5857 /* Open for exclusive use, write only. */
5858 status = print_spool_open(fsp, NULL, req->vuid);
5860 if (!NT_STATUS_IS_OK(status)) {
5861 file_free(req, fsp);
5862 reply_nterror(req, status);
5863 END_PROFILE(SMBsplopen);
5867 reply_outbuf(req, 1, 0);
5868 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5870 DEBUG(3,("openprint fd=%d %s\n",
5871 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5873 END_PROFILE(SMBsplopen);
5877 /****************************************************************************
5878 Reply to a printclose.
5879 ****************************************************************************/
5881 void reply_printclose(struct smb_request *req)
5883 connection_struct *conn = req->conn;
5887 START_PROFILE(SMBsplclose);
5890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5891 END_PROFILE(SMBsplclose);
5895 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5897 if (!check_fsp(conn, req, fsp)) {
5898 END_PROFILE(SMBsplclose);
5902 if (!CAN_PRINT(conn)) {
5903 reply_force_doserror(req, ERRSRV, ERRerror);
5904 END_PROFILE(SMBsplclose);
5908 DEBUG(3,("printclose fd=%d %s\n",
5909 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5911 status = close_file(req, fsp, NORMAL_CLOSE);
5913 if(!NT_STATUS_IS_OK(status)) {
5914 reply_nterror(req, status);
5915 END_PROFILE(SMBsplclose);
5919 reply_outbuf(req, 0, 0);
5921 END_PROFILE(SMBsplclose);
5925 /****************************************************************************
5926 Reply to a printqueue.
5927 ****************************************************************************/
5929 void reply_printqueue(struct smb_request *req)
5931 connection_struct *conn = req->conn;
5935 START_PROFILE(SMBsplretq);
5938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5939 END_PROFILE(SMBsplretq);
5943 max_count = SVAL(req->vwv+0, 0);
5944 start_index = SVAL(req->vwv+1, 0);
5946 /* we used to allow the client to get the cnum wrong, but that
5947 is really quite gross and only worked when there was only
5948 one printer - I think we should now only accept it if they
5949 get it right (tridge) */
5950 if (!CAN_PRINT(conn)) {
5951 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5952 END_PROFILE(SMBsplretq);
5956 reply_outbuf(req, 2, 3);
5957 SSVAL(req->outbuf,smb_vwv0,0);
5958 SSVAL(req->outbuf,smb_vwv1,0);
5959 SCVAL(smb_buf(req->outbuf),0,1);
5960 SSVAL(smb_buf(req->outbuf),1,0);
5962 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5963 start_index, max_count));
5966 TALLOC_CTX *mem_ctx = talloc_tos();
5969 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5970 struct rpc_pipe_client *cli = NULL;
5971 struct dcerpc_binding_handle *b = NULL;
5972 struct policy_handle handle;
5973 struct spoolss_DevmodeContainer devmode_ctr;
5974 union spoolss_JobInfo *info;
5976 uint32_t num_to_get;
5980 ZERO_STRUCT(handle);
5982 status = rpc_pipe_open_interface(mem_ctx,
5985 conn->sconn->remote_address,
5986 conn->sconn->local_address,
5987 conn->sconn->msg_ctx,
5989 if (!NT_STATUS_IS_OK(status)) {
5990 DEBUG(0, ("reply_printqueue: "
5991 "could not connect to spoolss: %s\n",
5992 nt_errstr(status)));
5993 reply_nterror(req, status);
5996 b = cli->binding_handle;
5998 ZERO_STRUCT(devmode_ctr);
6000 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6003 SEC_FLAG_MAXIMUM_ALLOWED,
6006 if (!NT_STATUS_IS_OK(status)) {
6007 reply_nterror(req, status);
6010 if (!W_ERROR_IS_OK(werr)) {
6011 reply_nterror(req, werror_to_ntstatus(werr));
6015 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6023 if (!W_ERROR_IS_OK(werr)) {
6024 reply_nterror(req, werror_to_ntstatus(werr));
6028 if (max_count > 0) {
6029 first = start_index;
6031 first = start_index + max_count + 1;
6034 if (first >= count) {
6037 num_to_get = first + MIN(ABS(max_count), count - first);
6040 for (i = first; i < num_to_get; i++) {
6043 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6046 uint16_t qrapjobid = pjobid_to_rap(sharename,
6047 info[i].info2.job_id);
6049 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6055 srv_put_dos_date2(p, 0, qtime);
6056 SCVAL(p, 4, qstatus);
6057 SSVAL(p, 5, qrapjobid);
6058 SIVAL(p, 7, info[i].info2.size);
6060 status = srvstr_push(blob, req->flags2, p+12,
6061 info[i].info2.notify_name, 16, STR_ASCII, &len);
6062 if (!NT_STATUS_IS_OK(status)) {
6063 reply_nterror(req, status);
6066 if (message_push_blob(
6069 blob, sizeof(blob))) == -1) {
6070 reply_nterror(req, NT_STATUS_NO_MEMORY);
6076 SSVAL(req->outbuf,smb_vwv0,count);
6077 SSVAL(req->outbuf,smb_vwv1,
6078 (max_count>0?first+count:first-1));
6079 SCVAL(smb_buf(req->outbuf),0,1);
6080 SSVAL(smb_buf(req->outbuf),1,28*count);
6084 DEBUG(3, ("%u entries returned in queue\n",
6088 if (b && is_valid_policy_hnd(&handle)) {
6089 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6094 END_PROFILE(SMBsplretq);
6098 /****************************************************************************
6099 Reply to a printwrite.
6100 ****************************************************************************/
6102 void reply_printwrite(struct smb_request *req)
6104 connection_struct *conn = req->conn;
6109 START_PROFILE(SMBsplwr);
6112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6113 END_PROFILE(SMBsplwr);
6117 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6119 if (!check_fsp(conn, req, fsp)) {
6120 END_PROFILE(SMBsplwr);
6124 if (!fsp->print_file) {
6125 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6126 END_PROFILE(SMBsplwr);
6130 if (!CHECK_WRITE(fsp)) {
6131 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6132 END_PROFILE(SMBsplwr);
6136 numtowrite = SVAL(req->buf, 1);
6139 * This already protects us against CVE-2017-12163.
6141 if (req->buflen < numtowrite + 3) {
6142 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6143 END_PROFILE(SMBsplwr);
6147 data = (const char *)req->buf + 3;
6149 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6150 reply_nterror(req, map_nt_error_from_unix(errno));
6151 END_PROFILE(SMBsplwr);
6155 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6157 END_PROFILE(SMBsplwr);
6161 /****************************************************************************
6163 ****************************************************************************/
6165 void reply_mkdir(struct smb_request *req)
6167 connection_struct *conn = req->conn;
6168 struct smb_filename *smb_dname = NULL;
6169 char *directory = NULL;
6172 TALLOC_CTX *ctx = talloc_tos();
6174 START_PROFILE(SMBmkdir);
6176 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6177 STR_TERMINATE, &status);
6178 if (!NT_STATUS_IS_OK(status)) {
6179 reply_nterror(req, status);
6183 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6184 status = filename_convert(ctx, conn,
6189 if (!NT_STATUS_IS_OK(status)) {
6190 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6191 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6192 ERRSRV, ERRbadpath);
6195 reply_nterror(req, status);
6199 status = create_directory(conn, req, smb_dname);
6201 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6203 if (!NT_STATUS_IS_OK(status)) {
6205 if (!use_nt_status()
6206 && NT_STATUS_EQUAL(status,
6207 NT_STATUS_OBJECT_NAME_COLLISION)) {
6209 * Yes, in the DOS error code case we get a
6210 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6211 * samba4 torture test.
6213 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6216 reply_nterror(req, status);
6220 reply_outbuf(req, 0, 0);
6222 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6224 TALLOC_FREE(smb_dname);
6225 END_PROFILE(SMBmkdir);
6229 /****************************************************************************
6231 ****************************************************************************/
6233 void reply_rmdir(struct smb_request *req)
6235 connection_struct *conn = req->conn;
6236 struct smb_filename *smb_dname = NULL;
6237 char *directory = NULL;
6239 TALLOC_CTX *ctx = talloc_tos();
6240 files_struct *fsp = NULL;
6242 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6243 struct smbd_server_connection *sconn = req->sconn;
6245 START_PROFILE(SMBrmdir);
6247 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6248 STR_TERMINATE, &status);
6249 if (!NT_STATUS_IS_OK(status)) {
6250 reply_nterror(req, status);
6254 status = filename_convert(ctx, conn,
6259 if (!NT_STATUS_IS_OK(status)) {
6260 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6261 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6262 ERRSRV, ERRbadpath);
6265 reply_nterror(req, status);
6269 if (is_ntfs_stream_smb_fname(smb_dname)) {
6270 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6274 status = SMB_VFS_CREATE_FILE(
6277 0, /* root_dir_fid */
6278 smb_dname, /* fname */
6279 DELETE_ACCESS, /* access_mask */
6280 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6282 FILE_OPEN, /* create_disposition*/
6283 FILE_DIRECTORY_FILE, /* create_options */
6284 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6285 0, /* oplock_request */
6287 0, /* allocation_size */
6288 0, /* private_flags */
6293 NULL, NULL); /* create context */
6295 if (!NT_STATUS_IS_OK(status)) {
6296 if (open_was_deferred(req->xconn, req->mid)) {
6297 /* We have re-scheduled this call. */
6300 reply_nterror(req, status);
6304 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6305 if (!NT_STATUS_IS_OK(status)) {
6306 close_file(req, fsp, ERROR_CLOSE);
6307 reply_nterror(req, status);
6311 if (!set_delete_on_close(fsp, true,
6312 conn->session_info->security_token,
6313 conn->session_info->unix_token)) {
6314 close_file(req, fsp, ERROR_CLOSE);
6315 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6319 status = close_file(req, fsp, NORMAL_CLOSE);
6320 if (!NT_STATUS_IS_OK(status)) {
6321 reply_nterror(req, status);
6323 reply_outbuf(req, 0, 0);
6326 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6328 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6330 TALLOC_FREE(smb_dname);
6331 END_PROFILE(SMBrmdir);
6335 /*******************************************************************
6336 Resolve wildcards in a filename rename.
6337 ********************************************************************/
6339 static bool resolve_wildcards(TALLOC_CTX *ctx,
6344 char *name2_copy = NULL;
6349 char *p,*p2, *pname1, *pname2;
6351 name2_copy = talloc_strdup(ctx, name2);
6356 pname1 = strrchr_m(name1,'/');
6357 pname2 = strrchr_m(name2_copy,'/');
6359 if (!pname1 || !pname2) {
6363 /* Truncate the copy of name2 at the last '/' */
6366 /* Now go past the '/' */
6370 root1 = talloc_strdup(ctx, pname1);
6371 root2 = talloc_strdup(ctx, pname2);
6373 if (!root1 || !root2) {
6377 p = strrchr_m(root1,'.');
6380 ext1 = talloc_strdup(ctx, p+1);
6382 ext1 = talloc_strdup(ctx, "");
6384 p = strrchr_m(root2,'.');
6387 ext2 = talloc_strdup(ctx, p+1);
6389 ext2 = talloc_strdup(ctx, "");
6392 if (!ext1 || !ext2) {
6400 /* Hmmm. Should this be mb-aware ? */
6403 } else if (*p2 == '*') {
6405 root2 = talloc_asprintf(ctx, "%s%s",
6424 /* Hmmm. Should this be mb-aware ? */
6427 } else if (*p2 == '*') {
6429 ext2 = talloc_asprintf(ctx, "%s%s",
6445 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6450 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6462 /****************************************************************************
6463 Ensure open files have their names updated. Updated to notify other smbd's
6465 ****************************************************************************/
6467 static void rename_open_files(connection_struct *conn,
6468 struct share_mode_lock *lck,
6470 uint32_t orig_name_hash,
6471 const struct smb_filename *smb_fname_dst)
6474 bool did_rename = False;
6476 uint32_t new_name_hash = 0;
6478 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6479 fsp = file_find_di_next(fsp)) {
6480 /* fsp_name is a relative path under the fsp. To change this for other
6481 sharepaths we need to manipulate relative paths. */
6482 /* TODO - create the absolute path and manipulate the newname
6483 relative to the sharepath. */
6484 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6487 if (fsp->name_hash != orig_name_hash) {
6490 DEBUG(10, ("rename_open_files: renaming file %s "
6491 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6492 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6493 smb_fname_str_dbg(smb_fname_dst)));
6495 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6496 if (NT_STATUS_IS_OK(status)) {
6498 new_name_hash = fsp->name_hash;
6503 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6504 "for %s\n", file_id_string_tos(&id),
6505 smb_fname_str_dbg(smb_fname_dst)));
6508 /* Send messages to all smbd's (not ourself) that the name has changed. */
6509 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6510 orig_name_hash, new_name_hash,
6515 /****************************************************************************
6516 We need to check if the source path is a parent directory of the destination
6517 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6518 refuse the rename with a sharing violation. Under UNIX the above call can
6519 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6520 probably need to check that the client is a Windows one before disallowing
6521 this as a UNIX client (one with UNIX extensions) can know the source is a
6522 symlink and make this decision intelligently. Found by an excellent bug
6523 report from <AndyLiebman@aol.com>.
6524 ****************************************************************************/
6526 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6527 const struct smb_filename *smb_fname_dst)
6529 const char *psrc = smb_fname_src->base_name;
6530 const char *pdst = smb_fname_dst->base_name;
6533 if (psrc[0] == '.' && psrc[1] == '/') {
6536 if (pdst[0] == '.' && pdst[1] == '/') {
6539 if ((slen = strlen(psrc)) > strlen(pdst)) {
6542 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6546 * Do the notify calls from a rename
6549 static void notify_rename(connection_struct *conn, bool is_dir,
6550 const struct smb_filename *smb_fname_src,
6551 const struct smb_filename *smb_fname_dst)
6553 char *parent_dir_src = NULL;
6554 char *parent_dir_dst = NULL;
6557 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6558 : FILE_NOTIFY_CHANGE_FILE_NAME;
6560 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6561 &parent_dir_src, NULL) ||
6562 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6563 &parent_dir_dst, NULL)) {
6567 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6568 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6569 smb_fname_src->base_name);
6570 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6571 smb_fname_dst->base_name);
6574 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6575 smb_fname_src->base_name);
6576 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6577 smb_fname_dst->base_name);
6580 /* this is a strange one. w2k3 gives an additional event for
6581 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6582 files, but not directories */
6584 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6585 FILE_NOTIFY_CHANGE_ATTRIBUTES
6586 |FILE_NOTIFY_CHANGE_CREATION,
6587 smb_fname_dst->base_name);
6590 TALLOC_FREE(parent_dir_src);
6591 TALLOC_FREE(parent_dir_dst);
6594 /****************************************************************************
6595 Returns an error if the parent directory for a filename is open in an
6597 ****************************************************************************/
6599 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6600 const struct smb_filename *smb_fname_dst_in)
6602 char *parent_dir = NULL;
6603 struct smb_filename smb_fname_parent;
6605 files_struct *fsp = NULL;
6608 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6609 &parent_dir, NULL)) {
6610 return NT_STATUS_NO_MEMORY;
6612 ZERO_STRUCT(smb_fname_parent);
6613 smb_fname_parent.base_name = parent_dir;
6615 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6617 return map_nt_error_from_unix(errno);
6621 * We're only checking on this smbd here, mostly good
6622 * enough.. and will pass tests.
6625 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6626 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6627 fsp = file_find_di_next(fsp)) {
6628 if (fsp->access_mask & DELETE_ACCESS) {
6629 return NT_STATUS_SHARING_VIOLATION;
6632 return NT_STATUS_OK;
6635 /****************************************************************************
6636 Rename an open file - given an fsp.
6637 ****************************************************************************/
6639 NTSTATUS rename_internals_fsp(connection_struct *conn,
6641 const struct smb_filename *smb_fname_dst_in,
6643 bool replace_if_exists)
6645 TALLOC_CTX *ctx = talloc_tos();
6646 struct smb_filename *smb_fname_dst = NULL;
6647 NTSTATUS status = NT_STATUS_OK;
6648 struct share_mode_lock *lck = NULL;
6649 uint32_t access_mask = SEC_DIR_ADD_FILE;
6650 bool dst_exists, old_is_stream, new_is_stream;
6652 status = check_name(conn, smb_fname_dst_in);
6653 if (!NT_STATUS_IS_OK(status)) {
6657 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6658 if (!NT_STATUS_IS_OK(status)) {
6662 if (file_has_open_streams(fsp)) {
6663 return NT_STATUS_ACCESS_DENIED;
6666 /* Make a copy of the dst smb_fname structs */
6668 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6669 if (smb_fname_dst == NULL) {
6670 status = NT_STATUS_NO_MEMORY;
6675 * Check for special case with case preserving and not
6676 * case sensitive. If the new last component differs from the original
6677 * last component only by case, then we should allow
6678 * the rename (user is trying to change the case of the
6681 if (!conn->case_sensitive && conn->case_preserve &&
6682 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6683 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6684 char *fname_dst_parent = NULL;
6685 const char *fname_dst_lcomp = NULL;
6686 char *orig_lcomp_path = NULL;
6687 char *orig_lcomp_stream = NULL;
6691 * Split off the last component of the processed
6692 * destination name. We will compare this to
6693 * the split components of smb_fname_dst->original_lcomp.
6695 if (!parent_dirname(ctx,
6696 smb_fname_dst->base_name,
6698 &fname_dst_lcomp)) {
6699 status = NT_STATUS_NO_MEMORY;
6704 * The original_lcomp component contains
6705 * the last_component of the path + stream
6706 * name (if a stream exists).
6708 * Split off the stream name so we
6709 * can check them separately.
6712 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6713 /* POSIX - no stream component. */
6714 orig_lcomp_path = talloc_strdup(ctx,
6715 smb_fname_dst->original_lcomp);
6716 if (orig_lcomp_path == NULL) {
6720 ok = split_stream_filename(ctx,
6721 smb_fname_dst->original_lcomp,
6723 &orig_lcomp_stream);
6727 TALLOC_FREE(fname_dst_parent);
6728 status = NT_STATUS_NO_MEMORY;
6732 /* If the base names only differ by case, use original. */
6733 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6736 * Replace the modified last component with the
6739 if (!ISDOT(fname_dst_parent)) {
6740 tmp = talloc_asprintf(smb_fname_dst,
6745 tmp = talloc_strdup(smb_fname_dst,
6749 status = NT_STATUS_NO_MEMORY;
6750 TALLOC_FREE(fname_dst_parent);
6751 TALLOC_FREE(orig_lcomp_path);
6752 TALLOC_FREE(orig_lcomp_stream);
6755 TALLOC_FREE(smb_fname_dst->base_name);
6756 smb_fname_dst->base_name = tmp;
6759 /* If the stream_names only differ by case, use original. */
6760 if(!strcsequal(smb_fname_dst->stream_name,
6761 orig_lcomp_stream)) {
6762 /* Use the original stream. */
6763 char *tmp = talloc_strdup(smb_fname_dst,
6766 status = NT_STATUS_NO_MEMORY;
6767 TALLOC_FREE(fname_dst_parent);
6768 TALLOC_FREE(orig_lcomp_path);
6769 TALLOC_FREE(orig_lcomp_stream);
6772 TALLOC_FREE(smb_fname_dst->stream_name);
6773 smb_fname_dst->stream_name = tmp;
6775 TALLOC_FREE(fname_dst_parent);
6776 TALLOC_FREE(orig_lcomp_path);
6777 TALLOC_FREE(orig_lcomp_stream);
6781 * If the src and dest names are identical - including case,
6782 * don't do the rename, just return success.
6785 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6786 strcsequal(fsp->fsp_name->stream_name,
6787 smb_fname_dst->stream_name)) {
6788 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6789 "- returning success\n",
6790 smb_fname_str_dbg(smb_fname_dst)));
6791 status = NT_STATUS_OK;
6795 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6796 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6798 /* Return the correct error code if both names aren't streams. */
6799 if (!old_is_stream && new_is_stream) {
6800 status = NT_STATUS_OBJECT_NAME_INVALID;
6804 if (old_is_stream && !new_is_stream) {
6805 status = NT_STATUS_INVALID_PARAMETER;
6809 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6811 if(!replace_if_exists && dst_exists) {
6812 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6813 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6814 smb_fname_str_dbg(smb_fname_dst)));
6815 status = NT_STATUS_OBJECT_NAME_COLLISION;
6820 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6821 &smb_fname_dst->st);
6822 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6824 /* The file can be open when renaming a stream */
6825 if (dst_fsp && !new_is_stream) {
6826 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6827 status = NT_STATUS_ACCESS_DENIED;
6832 /* Ensure we have a valid stat struct for the source. */
6833 status = vfs_stat_fsp(fsp);
6834 if (!NT_STATUS_IS_OK(status)) {
6838 status = can_rename(conn, fsp, attrs);
6840 if (!NT_STATUS_IS_OK(status)) {
6841 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6842 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6843 smb_fname_str_dbg(smb_fname_dst)));
6844 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6845 status = NT_STATUS_ACCESS_DENIED;
6849 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6850 status = NT_STATUS_ACCESS_DENIED;
6854 /* Do we have rights to move into the destination ? */
6855 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6856 /* We're moving a directory. */
6857 access_mask = SEC_DIR_ADD_SUBDIR;
6859 status = check_parent_access(conn,
6862 if (!NT_STATUS_IS_OK(status)) {
6863 DBG_INFO("check_parent_access on "
6864 "dst %s returned %s\n",
6865 smb_fname_str_dbg(smb_fname_dst),
6870 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6873 * We have the file open ourselves, so not being able to get the
6874 * corresponding share mode lock is a fatal error.
6877 SMB_ASSERT(lck != NULL);
6879 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6880 uint32_t create_options = fsp->fh->private_options;
6882 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6883 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6884 smb_fname_str_dbg(smb_fname_dst)));
6886 if (!fsp->is_directory &&
6887 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6888 (lp_map_archive(SNUM(conn)) ||
6889 lp_store_dos_attributes(SNUM(conn)))) {
6890 /* We must set the archive bit on the newly
6892 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6893 uint32_t old_dosmode = dos_mode(conn,
6895 file_set_dosmode(conn,
6897 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6903 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6906 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6910 * A rename acts as a new file create w.r.t. allowing an initial delete
6911 * on close, probably because in Windows there is a new handle to the
6912 * new file. If initial delete on close was requested but not
6913 * originally set, we need to set it here. This is probably not 100% correct,
6914 * but will work for the CIFSFS client which in non-posix mode
6915 * depends on these semantics. JRA.
6918 if (create_options & FILE_DELETE_ON_CLOSE) {
6919 status = can_set_delete_on_close(fsp, 0);
6921 if (NT_STATUS_IS_OK(status)) {
6922 /* Note that here we set the *inital* delete on close flag,
6923 * not the regular one. The magic gets handled in close. */
6924 fsp->initial_delete_on_close = True;
6928 status = NT_STATUS_OK;
6934 if (errno == ENOTDIR || errno == EISDIR) {
6935 status = NT_STATUS_OBJECT_NAME_COLLISION;
6937 status = map_nt_error_from_unix(errno);
6940 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6941 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6942 smb_fname_str_dbg(smb_fname_dst)));
6945 TALLOC_FREE(smb_fname_dst);
6950 /****************************************************************************
6951 The guts of the rename command, split out so it may be called by the NT SMB
6953 ****************************************************************************/
6955 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6956 connection_struct *conn,
6957 struct smb_request *req,
6958 struct smb_filename *smb_fname_src,
6959 struct smb_filename *smb_fname_dst,
6961 bool replace_if_exists,
6964 uint32_t access_mask)
6966 char *fname_src_dir = NULL;
6967 struct smb_filename *smb_fname_src_dir = NULL;
6968 char *fname_src_mask = NULL;
6970 NTSTATUS status = NT_STATUS_OK;
6971 struct smb_Dir *dir_hnd = NULL;
6972 const char *dname = NULL;
6973 char *talloced = NULL;
6975 int create_options = 0;
6976 bool posix_pathnames = (req != NULL && req->posix_pathnames);
6980 * Split the old name into directory and last component
6981 * strings. Note that unix_convert may have stripped off a
6982 * leading ./ from both name and newname if the rename is
6983 * at the root of the share. We need to make sure either both
6984 * name and newname contain a / character or neither of them do
6985 * as this is checked in resolve_wildcards().
6988 /* Split up the directory from the filename/mask. */
6989 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6990 &fname_src_dir, &fname_src_mask);
6991 if (!NT_STATUS_IS_OK(status)) {
6992 status = NT_STATUS_NO_MEMORY;
6997 * We should only check the mangled cache
6998 * here if unix_convert failed. This means
6999 * that the path in 'mask' doesn't exist
7000 * on the file system and so we need to look
7001 * for a possible mangle. This patch from
7002 * Tine Smukavec <valentin.smukavec@hermes.si>.
7005 if (!VALID_STAT(smb_fname_src->st) &&
7006 mangle_is_mangled(fname_src_mask, conn->params)) {
7007 char *new_mask = NULL;
7008 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7011 TALLOC_FREE(fname_src_mask);
7012 fname_src_mask = new_mask;
7016 if (!src_has_wild) {
7020 * Only one file needs to be renamed. Append the mask back
7021 * onto the directory.
7023 TALLOC_FREE(smb_fname_src->base_name);
7024 if (ISDOT(fname_src_dir)) {
7025 /* Ensure we use canonical names on open. */
7026 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7030 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7035 if (!smb_fname_src->base_name) {
7036 status = NT_STATUS_NO_MEMORY;
7040 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7041 "case_preserve = %d, short case preserve = %d, "
7042 "directory = %s, newname = %s, "
7043 "last_component_dest = %s\n",
7044 conn->case_sensitive, conn->case_preserve,
7045 conn->short_case_preserve,
7046 smb_fname_str_dbg(smb_fname_src),
7047 smb_fname_str_dbg(smb_fname_dst),
7048 smb_fname_dst->original_lcomp));
7050 /* The dest name still may have wildcards. */
7051 if (dest_has_wild) {
7052 char *fname_dst_mod = NULL;
7053 if (!resolve_wildcards(smb_fname_dst,
7054 smb_fname_src->base_name,
7055 smb_fname_dst->base_name,
7057 DEBUG(6, ("rename_internals: resolve_wildcards "
7059 smb_fname_src->base_name,
7060 smb_fname_dst->base_name));
7061 status = NT_STATUS_NO_MEMORY;
7064 TALLOC_FREE(smb_fname_dst->base_name);
7065 smb_fname_dst->base_name = fname_dst_mod;
7068 ZERO_STRUCT(smb_fname_src->st);
7069 if (posix_pathnames) {
7070 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7072 rc = SMB_VFS_STAT(conn, smb_fname_src);
7075 status = map_nt_error_from_unix_common(errno);
7079 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7080 create_options |= FILE_DIRECTORY_FILE;
7083 status = SMB_VFS_CREATE_FILE(
7086 0, /* root_dir_fid */
7087 smb_fname_src, /* fname */
7088 access_mask, /* access_mask */
7089 (FILE_SHARE_READ | /* share_access */
7091 FILE_OPEN, /* create_disposition*/
7092 create_options, /* create_options */
7093 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7094 0, /* oplock_request */
7096 0, /* allocation_size */
7097 0, /* private_flags */
7102 NULL, NULL); /* create context */
7104 if (!NT_STATUS_IS_OK(status)) {
7105 DEBUG(3, ("Could not open rename source %s: %s\n",
7106 smb_fname_str_dbg(smb_fname_src),
7107 nt_errstr(status)));
7111 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7112 attrs, replace_if_exists);
7114 close_file(req, fsp, NORMAL_CLOSE);
7116 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7117 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7118 smb_fname_str_dbg(smb_fname_dst)));
7124 * Wildcards - process each file that matches.
7126 if (strequal(fname_src_mask, "????????.???")) {
7127 TALLOC_FREE(fname_src_mask);
7128 fname_src_mask = talloc_strdup(ctx, "*");
7129 if (!fname_src_mask) {
7130 status = NT_STATUS_NO_MEMORY;
7135 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7139 smb_fname_src->flags);
7140 if (smb_fname_src_dir == NULL) {
7141 status = NT_STATUS_NO_MEMORY;
7145 status = check_name(conn, smb_fname_src_dir);
7146 if (!NT_STATUS_IS_OK(status)) {
7150 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7152 if (dir_hnd == NULL) {
7153 status = map_nt_error_from_unix(errno);
7157 status = NT_STATUS_NO_SUCH_FILE;
7159 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7160 * - gentest fix. JRA
7163 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7165 files_struct *fsp = NULL;
7166 char *destname = NULL;
7167 bool sysdir_entry = False;
7169 /* Quick check for "." and ".." */
7170 if (ISDOT(dname) || ISDOTDOT(dname)) {
7171 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7172 sysdir_entry = True;
7174 TALLOC_FREE(talloced);
7179 if (!is_visible_file(conn, fname_src_dir, dname,
7180 &smb_fname_src->st, false)) {
7181 TALLOC_FREE(talloced);
7185 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7186 TALLOC_FREE(talloced);
7191 status = NT_STATUS_OBJECT_NAME_INVALID;
7195 TALLOC_FREE(smb_fname_src->base_name);
7196 if (ISDOT(fname_src_dir)) {
7197 /* Ensure we use canonical names on open. */
7198 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7202 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7207 if (!smb_fname_src->base_name) {
7208 status = NT_STATUS_NO_MEMORY;
7212 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7213 smb_fname_dst->base_name,
7215 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7216 smb_fname_src->base_name, destname));
7217 TALLOC_FREE(talloced);
7221 status = NT_STATUS_NO_MEMORY;
7225 TALLOC_FREE(smb_fname_dst->base_name);
7226 smb_fname_dst->base_name = destname;
7228 ZERO_STRUCT(smb_fname_src->st);
7229 if (posix_pathnames) {
7230 SMB_VFS_LSTAT(conn, smb_fname_src);
7232 SMB_VFS_STAT(conn, smb_fname_src);
7237 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7238 create_options |= FILE_DIRECTORY_FILE;
7241 status = SMB_VFS_CREATE_FILE(
7244 0, /* root_dir_fid */
7245 smb_fname_src, /* fname */
7246 access_mask, /* access_mask */
7247 (FILE_SHARE_READ | /* share_access */
7249 FILE_OPEN, /* create_disposition*/
7250 create_options, /* create_options */
7251 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7252 0, /* oplock_request */
7254 0, /* allocation_size */
7255 0, /* private_flags */
7260 NULL, NULL); /* create context */
7262 if (!NT_STATUS_IS_OK(status)) {
7263 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7264 "returned %s rename %s -> %s\n",
7266 smb_fname_str_dbg(smb_fname_src),
7267 smb_fname_str_dbg(smb_fname_dst)));
7271 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7273 if (!smb_fname_dst->original_lcomp) {
7274 status = NT_STATUS_NO_MEMORY;
7278 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7279 attrs, replace_if_exists);
7281 close_file(req, fsp, NORMAL_CLOSE);
7283 if (!NT_STATUS_IS_OK(status)) {
7284 DEBUG(3, ("rename_internals_fsp returned %s for "
7285 "rename %s -> %s\n", nt_errstr(status),
7286 smb_fname_str_dbg(smb_fname_src),
7287 smb_fname_str_dbg(smb_fname_dst)));
7293 DEBUG(3,("rename_internals: doing rename on %s -> "
7294 "%s\n", smb_fname_str_dbg(smb_fname_src),
7295 smb_fname_str_dbg(smb_fname_src)));
7296 TALLOC_FREE(talloced);
7298 TALLOC_FREE(dir_hnd);
7300 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7301 status = map_nt_error_from_unix(errno);
7305 TALLOC_FREE(talloced);
7306 TALLOC_FREE(smb_fname_src_dir);
7307 TALLOC_FREE(fname_src_dir);
7308 TALLOC_FREE(fname_src_mask);
7312 /****************************************************************************
7314 ****************************************************************************/
7316 void reply_mv(struct smb_request *req)
7318 connection_struct *conn = req->conn;
7320 char *newname = NULL;
7324 bool src_has_wcard = False;
7325 bool dest_has_wcard = False;
7326 TALLOC_CTX *ctx = talloc_tos();
7327 struct smb_filename *smb_fname_src = NULL;
7328 struct smb_filename *smb_fname_dst = NULL;
7329 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7330 (req->posix_pathnames ?
7331 UCF_UNIX_NAME_LOOKUP :
7332 UCF_COND_ALLOW_WCARD_LCOMP);
7333 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7335 (req->posix_pathnames ?
7337 UCF_COND_ALLOW_WCARD_LCOMP);
7338 bool stream_rename = false;
7340 START_PROFILE(SMBmv);
7343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7347 attrs = SVAL(req->vwv+0, 0);
7349 p = (const char *)req->buf + 1;
7350 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7351 &status, &src_has_wcard);
7352 if (!NT_STATUS_IS_OK(status)) {
7353 reply_nterror(req, status);
7357 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7358 &status, &dest_has_wcard);
7359 if (!NT_STATUS_IS_OK(status)) {
7360 reply_nterror(req, status);
7364 if (!req->posix_pathnames) {
7365 /* The newname must begin with a ':' if the
7366 name contains a ':'. */
7367 if (strchr_m(name, ':')) {
7368 if (newname[0] != ':') {
7369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7372 stream_rename = true;
7376 status = filename_convert(ctx,
7383 if (!NT_STATUS_IS_OK(status)) {
7384 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7385 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7386 ERRSRV, ERRbadpath);
7389 reply_nterror(req, status);
7393 status = filename_convert(ctx,
7400 if (!NT_STATUS_IS_OK(status)) {
7401 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7402 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7403 ERRSRV, ERRbadpath);
7406 reply_nterror(req, status);
7410 if (stream_rename) {
7411 /* smb_fname_dst->base_name must be the same as
7412 smb_fname_src->base_name. */
7413 TALLOC_FREE(smb_fname_dst->base_name);
7414 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7415 smb_fname_src->base_name);
7416 if (!smb_fname_dst->base_name) {
7417 reply_nterror(req, NT_STATUS_NO_MEMORY);
7422 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7423 smb_fname_str_dbg(smb_fname_dst)));
7425 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7426 attrs, False, src_has_wcard, dest_has_wcard,
7428 if (!NT_STATUS_IS_OK(status)) {
7429 if (open_was_deferred(req->xconn, req->mid)) {
7430 /* We have re-scheduled this call. */
7433 reply_nterror(req, status);
7437 reply_outbuf(req, 0, 0);
7439 TALLOC_FREE(smb_fname_src);
7440 TALLOC_FREE(smb_fname_dst);
7445 /*******************************************************************
7446 Copy a file as part of a reply_copy.
7447 ******************************************************************/
7450 * TODO: check error codes on all callers
7453 NTSTATUS copy_file(TALLOC_CTX *ctx,
7454 connection_struct *conn,
7455 struct smb_filename *smb_fname_src,
7456 struct smb_filename *smb_fname_dst,
7459 bool target_is_directory)
7461 struct smb_filename *smb_fname_dst_tmp = NULL;
7463 files_struct *fsp1,*fsp2;
7465 uint32_t new_create_disposition;
7469 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7470 if (smb_fname_dst_tmp == NULL) {
7471 return NT_STATUS_NO_MEMORY;
7475 * If the target is a directory, extract the last component from the
7476 * src filename and append it to the dst filename
7478 if (target_is_directory) {
7481 /* dest/target can't be a stream if it's a directory. */
7482 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7484 p = strrchr_m(smb_fname_src->base_name,'/');
7488 p = smb_fname_src->base_name;
7490 smb_fname_dst_tmp->base_name =
7491 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7493 if (!smb_fname_dst_tmp->base_name) {
7494 status = NT_STATUS_NO_MEMORY;
7499 status = vfs_file_exist(conn, smb_fname_src);
7500 if (!NT_STATUS_IS_OK(status)) {
7504 if (!target_is_directory && count) {
7505 new_create_disposition = FILE_OPEN;
7507 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7510 &new_create_disposition,
7513 status = NT_STATUS_INVALID_PARAMETER;
7518 /* Open the src file for reading. */
7519 status = SMB_VFS_CREATE_FILE(
7522 0, /* root_dir_fid */
7523 smb_fname_src, /* fname */
7524 FILE_GENERIC_READ, /* access_mask */
7525 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7526 FILE_OPEN, /* create_disposition*/
7527 0, /* create_options */
7528 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7529 INTERNAL_OPEN_ONLY, /* oplock_request */
7531 0, /* allocation_size */
7532 0, /* private_flags */
7537 NULL, NULL); /* create context */
7539 if (!NT_STATUS_IS_OK(status)) {
7543 dosattrs = dos_mode(conn, smb_fname_src);
7545 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7546 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7549 /* Open the dst file for writing. */
7550 status = SMB_VFS_CREATE_FILE(
7553 0, /* root_dir_fid */
7554 smb_fname_dst, /* fname */
7555 FILE_GENERIC_WRITE, /* access_mask */
7556 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7557 new_create_disposition, /* create_disposition*/
7558 0, /* create_options */
7559 dosattrs, /* file_attributes */
7560 INTERNAL_OPEN_ONLY, /* oplock_request */
7562 0, /* allocation_size */
7563 0, /* private_flags */
7568 NULL, NULL); /* create context */
7570 if (!NT_STATUS_IS_OK(status)) {
7571 close_file(NULL, fsp1, ERROR_CLOSE);
7575 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7576 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7578 DEBUG(0, ("error - vfs lseek returned error %s\n",
7580 status = map_nt_error_from_unix(errno);
7581 close_file(NULL, fsp1, ERROR_CLOSE);
7582 close_file(NULL, fsp2, ERROR_CLOSE);
7587 /* Do the actual copy. */
7588 if (smb_fname_src->st.st_ex_size) {
7589 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7594 close_file(NULL, fsp1, NORMAL_CLOSE);
7596 /* Ensure the modtime is set correctly on the destination file. */
7597 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7600 * As we are opening fsp1 read-only we only expect
7601 * an error on close on fsp2 if we are out of space.
7602 * Thus we don't look at the error return from the
7605 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7607 if (!NT_STATUS_IS_OK(status)) {
7611 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7612 status = NT_STATUS_DISK_FULL;
7616 status = NT_STATUS_OK;
7619 TALLOC_FREE(smb_fname_dst_tmp);
7623 /****************************************************************************
7624 Reply to a file copy.
7625 ****************************************************************************/
7627 void reply_copy(struct smb_request *req)
7629 connection_struct *conn = req->conn;
7630 struct smb_filename *smb_fname_src = NULL;
7631 struct smb_filename *smb_fname_src_dir = NULL;
7632 struct smb_filename *smb_fname_dst = NULL;
7633 char *fname_src = NULL;
7634 char *fname_dst = NULL;
7635 char *fname_src_mask = NULL;
7636 char *fname_src_dir = NULL;
7639 int error = ERRnoaccess;
7643 bool target_is_directory=False;
7644 bool source_has_wild = False;
7645 bool dest_has_wild = False;
7647 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7648 ucf_flags_from_smb_request(req);
7649 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7650 ucf_flags_from_smb_request(req);
7651 TALLOC_CTX *ctx = talloc_tos();
7653 START_PROFILE(SMBcopy);
7656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7660 tid2 = SVAL(req->vwv+0, 0);
7661 ofun = SVAL(req->vwv+1, 0);
7662 flags = SVAL(req->vwv+2, 0);
7664 p = (const char *)req->buf;
7665 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7666 &status, &source_has_wild);
7667 if (!NT_STATUS_IS_OK(status)) {
7668 reply_nterror(req, status);
7671 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7672 &status, &dest_has_wild);
7673 if (!NT_STATUS_IS_OK(status)) {
7674 reply_nterror(req, status);
7678 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7680 if (tid2 != conn->cnum) {
7681 /* can't currently handle inter share copies XXXX */
7682 DEBUG(3,("Rejecting inter-share copy\n"));
7683 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7687 status = filename_convert(ctx, conn,
7692 if (!NT_STATUS_IS_OK(status)) {
7693 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7694 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7695 ERRSRV, ERRbadpath);
7698 reply_nterror(req, status);
7702 status = filename_convert(ctx, conn,
7707 if (!NT_STATUS_IS_OK(status)) {
7708 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7709 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7710 ERRSRV, ERRbadpath);
7713 reply_nterror(req, status);
7717 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7719 if ((flags&1) && target_is_directory) {
7720 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7724 if ((flags&2) && !target_is_directory) {
7725 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7729 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7730 /* wants a tree copy! XXXX */
7731 DEBUG(3,("Rejecting tree copy\n"));
7732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7736 /* Split up the directory from the filename/mask. */
7737 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7738 &fname_src_dir, &fname_src_mask);
7739 if (!NT_STATUS_IS_OK(status)) {
7740 reply_nterror(req, NT_STATUS_NO_MEMORY);
7745 * We should only check the mangled cache
7746 * here if unix_convert failed. This means
7747 * that the path in 'mask' doesn't exist
7748 * on the file system and so we need to look
7749 * for a possible mangle. This patch from
7750 * Tine Smukavec <valentin.smukavec@hermes.si>.
7752 if (!VALID_STAT(smb_fname_src->st) &&
7753 mangle_is_mangled(fname_src_mask, conn->params)) {
7754 char *new_mask = NULL;
7755 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7756 &new_mask, conn->params);
7758 /* Use demangled name if one was successfully found. */
7760 TALLOC_FREE(fname_src_mask);
7761 fname_src_mask = new_mask;
7765 if (!source_has_wild) {
7768 * Only one file needs to be copied. Append the mask back onto
7771 TALLOC_FREE(smb_fname_src->base_name);
7772 if (ISDOT(fname_src_dir)) {
7773 /* Ensure we use canonical names on open. */
7774 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7778 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7783 if (!smb_fname_src->base_name) {
7784 reply_nterror(req, NT_STATUS_NO_MEMORY);
7788 if (dest_has_wild) {
7789 char *fname_dst_mod = NULL;
7790 if (!resolve_wildcards(smb_fname_dst,
7791 smb_fname_src->base_name,
7792 smb_fname_dst->base_name,
7794 reply_nterror(req, NT_STATUS_NO_MEMORY);
7797 TALLOC_FREE(smb_fname_dst->base_name);
7798 smb_fname_dst->base_name = fname_dst_mod;
7801 status = check_name(conn, smb_fname_src);
7802 if (!NT_STATUS_IS_OK(status)) {
7803 reply_nterror(req, status);
7807 status = check_name(conn, smb_fname_dst);
7808 if (!NT_STATUS_IS_OK(status)) {
7809 reply_nterror(req, status);
7813 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7814 ofun, count, target_is_directory);
7816 if(!NT_STATUS_IS_OK(status)) {
7817 reply_nterror(req, status);
7823 struct smb_Dir *dir_hnd = NULL;
7824 const char *dname = NULL;
7825 char *talloced = NULL;
7829 * There is a wildcard that requires us to actually read the
7830 * src dir and copy each file matching the mask to the dst.
7831 * Right now streams won't be copied, but this could
7832 * presumably be added with a nested loop for reach dir entry.
7834 SMB_ASSERT(!smb_fname_src->stream_name);
7835 SMB_ASSERT(!smb_fname_dst->stream_name);
7837 smb_fname_src->stream_name = NULL;
7838 smb_fname_dst->stream_name = NULL;
7840 if (strequal(fname_src_mask,"????????.???")) {
7841 TALLOC_FREE(fname_src_mask);
7842 fname_src_mask = talloc_strdup(ctx, "*");
7843 if (!fname_src_mask) {
7844 reply_nterror(req, NT_STATUS_NO_MEMORY);
7849 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7853 smb_fname_src->flags);
7854 if (smb_fname_src_dir == NULL) {
7855 reply_nterror(req, NT_STATUS_NO_MEMORY);
7859 status = check_name(conn, smb_fname_src_dir);
7860 if (!NT_STATUS_IS_OK(status)) {
7861 reply_nterror(req, status);
7865 dir_hnd = OpenDir(ctx,
7870 if (dir_hnd == NULL) {
7871 status = map_nt_error_from_unix(errno);
7872 reply_nterror(req, status);
7878 /* Iterate over the src dir copying each entry to the dst. */
7879 while ((dname = ReadDirName(dir_hnd, &offset,
7880 &smb_fname_src->st, &talloced))) {
7881 char *destname = NULL;
7883 if (ISDOT(dname) || ISDOTDOT(dname)) {
7884 TALLOC_FREE(talloced);
7888 if (!is_visible_file(conn, fname_src_dir, dname,
7889 &smb_fname_src->st, false)) {
7890 TALLOC_FREE(talloced);
7894 if(!mask_match(dname, fname_src_mask,
7895 conn->case_sensitive)) {
7896 TALLOC_FREE(talloced);
7900 error = ERRnoaccess;
7902 /* Get the src smb_fname struct setup. */
7903 TALLOC_FREE(smb_fname_src->base_name);
7904 if (ISDOT(fname_src_dir)) {
7905 /* Ensure we use canonical names on open. */
7906 smb_fname_src->base_name =
7907 talloc_asprintf(smb_fname_src, "%s",
7910 smb_fname_src->base_name =
7911 talloc_asprintf(smb_fname_src, "%s/%s",
7912 fname_src_dir, dname);
7915 if (!smb_fname_src->base_name) {
7916 TALLOC_FREE(dir_hnd);
7917 TALLOC_FREE(talloced);
7918 reply_nterror(req, NT_STATUS_NO_MEMORY);
7922 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7923 smb_fname_dst->base_name,
7925 TALLOC_FREE(talloced);
7929 TALLOC_FREE(dir_hnd);
7930 TALLOC_FREE(talloced);
7931 reply_nterror(req, NT_STATUS_NO_MEMORY);
7935 TALLOC_FREE(smb_fname_dst->base_name);
7936 smb_fname_dst->base_name = destname;
7938 status = check_name(conn, smb_fname_src);
7939 if (!NT_STATUS_IS_OK(status)) {
7940 TALLOC_FREE(dir_hnd);
7941 TALLOC_FREE(talloced);
7942 reply_nterror(req, status);
7946 status = check_name(conn, smb_fname_dst);
7947 if (!NT_STATUS_IS_OK(status)) {
7948 TALLOC_FREE(dir_hnd);
7949 TALLOC_FREE(talloced);
7950 reply_nterror(req, status);
7954 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7955 smb_fname_src->base_name,
7956 smb_fname_dst->base_name));
7958 status = copy_file(ctx, conn, smb_fname_src,
7959 smb_fname_dst, ofun, count,
7960 target_is_directory);
7961 if (NT_STATUS_IS_OK(status)) {
7965 TALLOC_FREE(talloced);
7967 TALLOC_FREE(dir_hnd);
7971 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7975 reply_outbuf(req, 1, 0);
7976 SSVAL(req->outbuf,smb_vwv0,count);
7978 TALLOC_FREE(smb_fname_src);
7979 TALLOC_FREE(smb_fname_src_dir);
7980 TALLOC_FREE(smb_fname_dst);
7981 TALLOC_FREE(fname_src);
7982 TALLOC_FREE(fname_dst);
7983 TALLOC_FREE(fname_src_mask);
7984 TALLOC_FREE(fname_src_dir);
7986 END_PROFILE(SMBcopy);
7991 #define DBGC_CLASS DBGC_LOCKING
7993 /****************************************************************************
7994 Get a lock pid, dealing with large count requests.
7995 ****************************************************************************/
7997 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7998 bool large_file_format)
8000 if(!large_file_format)
8001 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8003 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8006 /****************************************************************************
8007 Get a lock count, dealing with large count requests.
8008 ****************************************************************************/
8010 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8011 bool large_file_format)
8015 if(!large_file_format) {
8016 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8019 * No BVAL, this is reversed!
8021 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8022 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8028 /****************************************************************************
8029 Get a lock offset, dealing with large offset requests.
8030 ****************************************************************************/
8032 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8033 bool large_file_format)
8035 uint64_t offset = 0;
8037 if(!large_file_format) {
8038 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8041 * No BVAL, this is reversed!
8043 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8044 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8050 NTSTATUS smbd_do_locking(struct smb_request *req,
8055 struct smbd_lock_element *locks,
8058 connection_struct *conn = req->conn;
8060 NTSTATUS status = NT_STATUS_OK;
8064 /* Setup the timeout in seconds. */
8066 if (!lp_blocking_locks(SNUM(conn))) {
8070 for(i = 0; i < (int)num_locks; i++) {
8071 struct smbd_lock_element *e = &locks[i];
8073 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8074 "%llu, file %s timeout = %d\n",
8077 (unsigned long long)e->smblctx,
8081 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8082 struct blocking_lock_record *blr = NULL;
8084 if (num_locks > 1) {
8086 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8087 * if the lock vector contains one entry. When given multiple cancel
8088 * requests in a single PDU we expect the server to return an
8089 * error. Windows servers seem to accept the request but only
8090 * cancel the first lock.
8091 * JRA - Do what Windows does (tm) :-).
8095 /* MS-CIFS (2.2.4.32.1) behavior. */
8096 return NT_STATUS_DOS(ERRDOS,
8097 ERRcancelviolation);
8099 /* Windows behavior. */
8101 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8102 "cancel request\n"));
8108 if (lp_blocking_locks(SNUM(conn))) {
8110 /* Schedule a message to ourselves to
8111 remove the blocking lock record and
8112 return the right error. */
8114 blr = blocking_lock_cancel_smb1(fsp,
8120 NT_STATUS_FILE_LOCK_CONFLICT);
8122 return NT_STATUS_DOS(
8124 ERRcancelviolation);
8127 /* Remove a matching pending lock. */
8128 status = do_lock_cancel(fsp,
8134 bool blocking_lock = timeout ? true : false;
8135 bool defer_lock = false;
8136 struct byte_range_lock *br_lck;
8137 uint64_t block_smblctx;
8139 br_lck = do_lock(req->sconn->msg_ctx,
8150 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8151 /* Windows internal resolution for blocking locks seems
8152 to be about 200ms... Don't wait for less than that. JRA. */
8153 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8154 timeout = lp_lock_spin_time();
8159 /* If a lock sent with timeout of zero would fail, and
8160 * this lock has been requested multiple times,
8161 * according to brl_lock_failed() we convert this
8162 * request to a blocking lock with a timeout of between
8163 * 150 - 300 milliseconds.
8165 * If lp_lock_spin_time() has been set to 0, we skip
8166 * this blocking retry and fail immediately.
8168 * Replacement for do_lock_spin(). JRA. */
8170 if (!req->sconn->using_smb2 &&
8171 br_lck && lp_blocking_locks(SNUM(conn)) &&
8172 lp_lock_spin_time() && !blocking_lock &&
8173 NT_STATUS_EQUAL((status),
8174 NT_STATUS_FILE_LOCK_CONFLICT))
8177 timeout = lp_lock_spin_time();
8180 if (br_lck && defer_lock) {
8182 * A blocking lock was requested. Package up
8183 * this smb into a queued request and push it
8184 * onto the blocking lock queue.
8186 if(push_blocking_lock_request(br_lck,
8197 TALLOC_FREE(br_lck);
8199 return NT_STATUS_OK;
8203 TALLOC_FREE(br_lck);
8206 if (!NT_STATUS_IS_OK(status)) {
8211 /* If any of the above locks failed, then we must unlock
8212 all of the previous locks (X/Open spec). */
8214 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8216 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8217 i = -1; /* we want to skip the for loop */
8221 * Ensure we don't do a remove on the lock that just failed,
8222 * as under POSIX rules, if we have a lock already there, we
8223 * will delete it (and we shouldn't) .....
8225 for(i--; i >= 0; i--) {
8226 struct smbd_lock_element *e = &locks[i];
8228 do_unlock(req->sconn->msg_ctx,
8238 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8239 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8241 return NT_STATUS_OK;
8244 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8246 uint16_t num_ulocks,
8247 struct smbd_lock_element *ulocks)
8251 for(i = 0; i < (int)num_ulocks; i++) {
8252 struct smbd_lock_element *e = &ulocks[i];
8255 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8256 "pid %u, file %s\n", __func__,
8259 (unsigned int)e->smblctx,
8262 if (e->brltype != UNLOCK_LOCK) {
8263 /* this can only happen with SMB2 */
8264 return NT_STATUS_INVALID_PARAMETER;
8267 status = do_unlock(req->sconn->msg_ctx,
8274 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8275 nt_errstr(status)));
8277 if (!NT_STATUS_IS_OK(status)) {
8282 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8285 return NT_STATUS_OK;
8288 /****************************************************************************
8289 Reply to a lockingX request.
8290 ****************************************************************************/
8292 void reply_lockingX(struct smb_request *req)
8294 connection_struct *conn = req->conn;
8296 unsigned char locktype;
8297 unsigned char oplocklevel;
8298 uint16_t num_ulocks;
8300 int32_t lock_timeout;
8302 const uint8_t *data;
8303 bool large_file_format;
8304 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8305 struct smbd_lock_element *ulocks;
8306 struct smbd_lock_element *locks;
8309 START_PROFILE(SMBlockingX);
8312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8313 END_PROFILE(SMBlockingX);
8317 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8318 locktype = CVAL(req->vwv+3, 0);
8319 oplocklevel = CVAL(req->vwv+3, 1);
8320 num_ulocks = SVAL(req->vwv+6, 0);
8321 num_locks = SVAL(req->vwv+7, 0);
8322 lock_timeout = IVAL(req->vwv+4, 0);
8323 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8325 if (!check_fsp(conn, req, fsp)) {
8326 END_PROFILE(SMBlockingX);
8332 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8333 /* we don't support these - and CANCEL_LOCK makes w2k
8334 and XP reboot so I don't really want to be
8335 compatible! (tridge) */
8336 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8337 END_PROFILE(SMBlockingX);
8341 /* Check if this is an oplock break on a file
8342 we have granted an oplock on.
8344 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8345 /* Client can insist on breaking to none. */
8346 bool break_to_none = (oplocklevel == 0);
8349 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8350 "for %s\n", (unsigned int)oplocklevel,
8351 fsp_fnum_dbg(fsp)));
8354 * Make sure we have granted an exclusive or batch oplock on
8358 if (fsp->oplock_type == 0) {
8360 /* The Samba4 nbench simulator doesn't understand
8361 the difference between break to level2 and break
8362 to none from level2 - it sends oplock break
8363 replies in both cases. Don't keep logging an error
8364 message here - just ignore it. JRA. */
8366 DEBUG(5,("reply_lockingX: Error : oplock break from "
8367 "client for %s (oplock=%d) and no "
8368 "oplock granted on this file (%s).\n",
8369 fsp_fnum_dbg(fsp), fsp->oplock_type,
8372 /* if this is a pure oplock break request then don't
8374 if (num_locks == 0 && num_ulocks == 0) {
8375 END_PROFILE(SMBlockingX);
8378 END_PROFILE(SMBlockingX);
8379 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8384 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8386 result = remove_oplock(fsp);
8388 result = downgrade_oplock(fsp);
8392 DEBUG(0, ("reply_lockingX: error in removing "
8393 "oplock on file %s\n", fsp_str_dbg(fsp)));
8394 /* Hmmm. Is this panic justified? */
8395 smb_panic("internal tdb error");
8398 /* if this is a pure oplock break request then don't send a
8400 if (num_locks == 0 && num_ulocks == 0) {
8401 /* Sanity check - ensure a pure oplock break is not a
8403 if (CVAL(req->vwv+0, 0) != 0xff) {
8404 DEBUG(0,("reply_lockingX: Error : pure oplock "
8405 "break is a chained %d request !\n",
8406 (unsigned int)CVAL(req->vwv+0, 0)));
8408 END_PROFILE(SMBlockingX);
8414 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8416 END_PROFILE(SMBlockingX);
8420 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8421 if (ulocks == NULL) {
8422 reply_nterror(req, NT_STATUS_NO_MEMORY);
8423 END_PROFILE(SMBlockingX);
8427 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8428 if (locks == NULL) {
8429 reply_nterror(req, NT_STATUS_NO_MEMORY);
8430 END_PROFILE(SMBlockingX);
8434 /* Data now points at the beginning of the list
8435 of smb_unlkrng structs */
8436 for(i = 0; i < (int)num_ulocks; i++) {
8437 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8438 ulocks[i].count = get_lock_count(data, i, large_file_format);
8439 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8440 ulocks[i].brltype = UNLOCK_LOCK;
8443 /* Now do any requested locks */
8444 data += ((large_file_format ? 20 : 10)*num_ulocks);
8446 /* Data now points at the beginning of the list
8447 of smb_lkrng structs */
8449 for(i = 0; i < (int)num_locks; i++) {
8450 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8451 locks[i].count = get_lock_count(data, i, large_file_format);
8452 locks[i].offset = get_lock_offset(data, i, large_file_format);
8454 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8455 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8456 locks[i].brltype = PENDING_READ_LOCK;
8458 locks[i].brltype = READ_LOCK;
8461 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8462 locks[i].brltype = PENDING_WRITE_LOCK;
8464 locks[i].brltype = WRITE_LOCK;
8469 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8470 if (!NT_STATUS_IS_OK(status)) {
8471 END_PROFILE(SMBlockingX);
8472 reply_nterror(req, status);
8476 status = smbd_do_locking(req, fsp,
8477 locktype, lock_timeout,
8480 if (!NT_STATUS_IS_OK(status)) {
8481 END_PROFILE(SMBlockingX);
8482 reply_nterror(req, status);
8486 END_PROFILE(SMBlockingX);
8490 reply_outbuf(req, 2, 0);
8491 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8492 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8494 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8495 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8497 END_PROFILE(SMBlockingX);
8501 #define DBGC_CLASS DBGC_ALL
8503 /****************************************************************************
8504 Reply to a SMBreadbmpx (read block multiplex) request.
8505 Always reply with an error, if someone has a platform really needs this,
8506 please contact vl@samba.org
8507 ****************************************************************************/
8509 void reply_readbmpx(struct smb_request *req)
8511 START_PROFILE(SMBreadBmpx);
8512 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8513 END_PROFILE(SMBreadBmpx);
8517 /****************************************************************************
8518 Reply to a SMBreadbs (read block multiplex secondary) request.
8519 Always reply with an error, if someone has a platform really needs this,
8520 please contact vl@samba.org
8521 ****************************************************************************/
8523 void reply_readbs(struct smb_request *req)
8525 START_PROFILE(SMBreadBs);
8526 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8527 END_PROFILE(SMBreadBs);
8531 /****************************************************************************
8532 Reply to a SMBsetattrE.
8533 ****************************************************************************/
8535 void reply_setattrE(struct smb_request *req)
8537 connection_struct *conn = req->conn;
8538 struct smb_file_time ft;
8542 START_PROFILE(SMBsetattrE);
8546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8550 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8552 if(!fsp || (fsp->conn != conn)) {
8553 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8558 * Convert the DOS times into unix times.
8561 ft.atime = convert_time_t_to_timespec(
8562 srv_make_unix_date2(req->vwv+3));
8563 ft.mtime = convert_time_t_to_timespec(
8564 srv_make_unix_date2(req->vwv+5));
8565 ft.create_time = convert_time_t_to_timespec(
8566 srv_make_unix_date2(req->vwv+1));
8568 reply_outbuf(req, 0, 0);
8571 * Patch from Ray Frush <frush@engr.colostate.edu>
8572 * Sometimes times are sent as zero - ignore them.
8575 /* Ensure we have a valid stat struct for the source. */
8576 status = vfs_stat_fsp(fsp);
8577 if (!NT_STATUS_IS_OK(status)) {
8578 reply_nterror(req, status);
8582 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8583 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8587 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8588 if (!NT_STATUS_IS_OK(status)) {
8589 reply_nterror(req, status);
8593 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8596 (unsigned int)ft.atime.tv_sec,
8597 (unsigned int)ft.mtime.tv_sec,
8598 (unsigned int)ft.create_time.tv_sec
8601 END_PROFILE(SMBsetattrE);
8606 /* Back from the dead for OS/2..... JRA. */
8608 /****************************************************************************
8609 Reply to a SMBwritebmpx (write block multiplex primary) request.
8610 Always reply with an error, if someone has a platform really needs this,
8611 please contact vl@samba.org
8612 ****************************************************************************/
8614 void reply_writebmpx(struct smb_request *req)
8616 START_PROFILE(SMBwriteBmpx);
8617 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8618 END_PROFILE(SMBwriteBmpx);
8622 /****************************************************************************
8623 Reply to a SMBwritebs (write block multiplex secondary) request.
8624 Always reply with an error, if someone has a platform really needs this,
8625 please contact vl@samba.org
8626 ****************************************************************************/
8628 void reply_writebs(struct smb_request *req)
8630 START_PROFILE(SMBwriteBs);
8631 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8632 END_PROFILE(SMBwriteBs);
8636 /****************************************************************************
8637 Reply to a SMBgetattrE.
8638 ****************************************************************************/
8640 void reply_getattrE(struct smb_request *req)
8642 connection_struct *conn = req->conn;
8645 struct timespec create_ts;
8647 START_PROFILE(SMBgetattrE);
8650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8651 END_PROFILE(SMBgetattrE);
8655 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8657 if(!fsp || (fsp->conn != conn)) {
8658 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8659 END_PROFILE(SMBgetattrE);
8663 /* Do an fstat on this file */
8665 reply_nterror(req, map_nt_error_from_unix(errno));
8666 END_PROFILE(SMBgetattrE);
8670 mode = dos_mode(conn, fsp->fsp_name);
8673 * Convert the times into dos times. Set create
8674 * date to be last modify date as UNIX doesn't save
8678 reply_outbuf(req, 11, 0);
8680 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8681 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8682 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8683 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8684 /* Should we check pending modtime here ? JRA */
8685 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8686 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8688 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8689 SIVAL(req->outbuf, smb_vwv6, 0);
8690 SIVAL(req->outbuf, smb_vwv8, 0);
8692 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8693 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8694 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8696 SSVAL(req->outbuf,smb_vwv10, mode);
8698 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8700 END_PROFILE(SMBgetattrE);