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/util/tevent_ntstatus.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "librpc/gen_ndr/open_files.h"
48 #include "smb1_utils.h"
49 #include "libcli/smb/smb2_posix.h"
50 #include "lib/util/string_wrappers.h"
52 /****************************************************************************
53 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
54 path or anything including wildcards.
55 We're assuming here that '/' is not the second byte in any multibyte char
56 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
58 ****************************************************************************/
60 /* Custom version for processing POSIX paths. */
61 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
63 static NTSTATUS check_path_syntax_internal(char *path,
68 NTSTATUS ret = NT_STATUS_OK;
69 bool start_of_name_component = True;
70 bool stream_started = false;
71 bool last_component_contains_wcard = false;
78 return NT_STATUS_OBJECT_NAME_INVALID;
81 return NT_STATUS_OBJECT_NAME_INVALID;
83 if (strchr_m(&s[1], ':')) {
84 return NT_STATUS_OBJECT_NAME_INVALID;
90 if ((*s == ':') && !posix_path && !stream_started) {
91 if (last_component_contains_wcard) {
92 return NT_STATUS_OBJECT_NAME_INVALID;
94 /* Stream names allow more characters than file names.
95 We're overloading posix_path here to allow a wider
96 range of characters. If stream_started is true this
97 is still a Windows path even if posix_path is true.
100 stream_started = true;
101 start_of_name_component = false;
105 return NT_STATUS_OBJECT_NAME_INVALID;
109 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
111 * Safe to assume is not the second part of a mb char
112 * as this is handled below.
114 /* Eat multiple '/' or '\\' */
115 while (IS_PATH_SEP(*s,posix_path)) {
118 if ((d != path) && (*s != '\0')) {
119 /* We only care about non-leading or trailing '/' or '\\' */
123 start_of_name_component = True;
125 last_component_contains_wcard = false;
129 if (start_of_name_component) {
130 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
131 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
134 * No mb char starts with '.' so we're safe checking the directory separator here.
137 /* If we just added a '/' - delete it */
138 if ((d > path) && (*(d-1) == '/')) {
143 /* Are we at the start ? Can't go back further if so. */
145 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
148 /* Go back one level... */
149 /* We know this is safe as '/' cannot be part of a mb sequence. */
150 /* NOTE - if this assumption is invalid we are not in good shape... */
151 /* Decrement d first as d points to the *next* char to write into. */
152 for (d--; d > path; d--) {
156 s += 2; /* Else go past the .. */
157 /* We're still at the start of a name component, just the previous one. */
160 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
172 if (*s <= 0x1f || *s == '|') {
173 return NT_STATUS_OBJECT_NAME_INVALID;
181 last_component_contains_wcard = true;
190 /* Get the size of the next MB character. */
191 next_codepoint(s,&siz);
209 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
211 return NT_STATUS_INVALID_PARAMETER;
214 start_of_name_component = False;
222 /****************************************************************************
223 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
224 No wildcards allowed.
225 ****************************************************************************/
227 NTSTATUS check_path_syntax(char *path)
229 return check_path_syntax_internal(path, false);
232 /****************************************************************************
233 Check the path for a POSIX client.
234 We're assuming here that '/' is not the second byte in any multibyte char
235 set (a safe assumption).
236 ****************************************************************************/
238 NTSTATUS check_path_syntax_posix(char *path)
240 return check_path_syntax_internal(path, true);
243 /****************************************************************************
244 Pull a string and check the path allowing a wildcard - provide for error return.
245 Passes in posix flag.
246 ****************************************************************************/
248 static size_t srvstr_get_path_internal(TALLOC_CTX *ctx,
249 const char *base_ptr,
255 bool posix_pathnames,
262 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
266 *err = NT_STATUS_INVALID_PARAMETER;
270 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
272 * For a DFS path the function parse_dfs_path()
273 * will do the path processing, just make a copy.
279 if (posix_pathnames) {
280 *err = check_path_syntax_posix(*pp_dest);
282 *err = check_path_syntax(*pp_dest);
288 /****************************************************************************
289 Pull a string and check the path - provide for error return.
290 ****************************************************************************/
292 size_t srvstr_get_path(TALLOC_CTX *ctx,
293 const char *base_ptr,
301 return srvstr_get_path_internal(ctx,
312 /****************************************************************************
313 Pull a string and check the path - provide for error return.
314 posix_pathnames version.
315 ****************************************************************************/
317 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
318 const char *base_ptr,
326 return srvstr_get_path_internal(ctx,
338 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
339 char **pp_dest, const char *src, int flags,
342 ssize_t bufrem = smbreq_bufrem(req, src);
345 *err = NT_STATUS_INVALID_PARAMETER;
349 if (req->posix_pathnames) {
350 return srvstr_get_path_internal(mem_ctx,
351 (const char *)req->inbuf,
360 return srvstr_get_path_internal(mem_ctx,
361 (const char *)req->inbuf,
373 * pull a string from the smb_buf part of a packet. In this case the
374 * string can either be null terminated or it can be terminated by the
375 * end of the smbbuf area
377 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
378 char **dest, const uint8_t *src, int flags)
380 ssize_t bufrem = smbreq_bufrem(req, src);
386 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
390 /****************************************************************************
391 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
392 ****************************************************************************/
394 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
397 if ((fsp == NULL) || (conn == NULL)) {
398 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
401 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
402 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
408 /****************************************************************************
409 Check if we have a correct fsp pointing to a file.
410 ****************************************************************************/
412 bool check_fsp(connection_struct *conn, struct smb_request *req,
415 if (!check_fsp_open(conn, req, fsp)) {
418 if (fsp->fsp_flags.is_directory) {
419 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
422 if (fsp->fh->fd == -1) {
423 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
426 fsp->num_smb_operations++;
430 /****************************************************************************
431 Check if we have a correct fsp pointing to a quota fake file. Replacement for
432 the CHECK_NTQUOTA_HANDLE_OK macro.
433 ****************************************************************************/
435 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
438 if (!check_fsp_open(conn, req, fsp)) {
442 if (fsp->fsp_flags.is_directory) {
446 if (fsp->fake_file_handle == NULL) {
450 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
454 if (fsp->fake_file_handle->private_data == NULL) {
461 /****************************************************************************
462 Return the port number we've bound to on a socket.
463 ****************************************************************************/
465 static int get_socket_port(int fd)
467 struct samba_sockaddr saddr = {
468 .sa_socklen = sizeof(struct sockaddr_storage),
475 if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
476 int level = (errno == ENOTCONN) ? 2 : 0;
477 DEBUG(level, ("getsockname failed. Error was %s\n",
482 #if defined(HAVE_IPV6)
483 if (saddr.u.sa.sa_family == AF_INET6) {
484 return ntohs(saddr.u.in6.sin6_port);
487 if (saddr.u.sa.sa_family == AF_INET) {
488 return ntohs(saddr.u.in.sin_port);
493 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
494 const char *name, int name_type)
497 char *trim_name_type;
498 const char *retarget_parm;
501 int retarget_type = 0x20;
502 int retarget_port = NBT_SMB_PORT;
503 struct sockaddr_storage retarget_addr;
504 struct sockaddr_in *in_addr;
508 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
512 trim_name = talloc_strdup(talloc_tos(), name);
513 if (trim_name == NULL) {
516 trim_char(trim_name, ' ', ' ');
518 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
520 if (trim_name_type == NULL) {
524 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
525 trim_name_type, NULL);
526 if (retarget_parm == NULL) {
527 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
530 if (retarget_parm == NULL) {
534 retarget = talloc_strdup(trim_name, retarget_parm);
535 if (retarget == NULL) {
539 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
541 p = strchr(retarget, ':');
544 retarget_port = atoi(p);
547 p = strchr_m(retarget, '#');
550 if (sscanf(p, "%x", &retarget_type) != 1) {
555 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
557 DEBUG(10, ("could not resolve %s\n", retarget));
561 if (retarget_addr.ss_family != AF_INET) {
562 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
566 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
568 _smb_setlen(outbuf, 6);
569 SCVAL(outbuf, 0, 0x84);
570 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
571 *(uint16_t *)(outbuf+8) = htons(retarget_port);
573 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
575 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
581 TALLOC_FREE(trim_name);
585 static void reply_called_name_not_present(char *outbuf)
587 smb_setlen(outbuf, 1);
588 SCVAL(outbuf, 0, 0x83);
589 SCVAL(outbuf, 4, 0x82);
592 /****************************************************************************
593 Reply to a (netbios-level) special message.
594 ****************************************************************************/
596 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
598 struct smbd_server_connection *sconn = xconn->client->sconn;
599 int msg_type = CVAL(inbuf,0);
600 int msg_flags = CVAL(inbuf,1);
602 * We only really use 4 bytes of the outbuf, but for the smb_setlen
603 * calculation & friends (srv_send_smb uses that) we need the full smb
606 char outbuf[smb_size];
608 memset(outbuf, '\0', sizeof(outbuf));
610 smb_setlen(outbuf,0);
613 case NBSSrequest: /* session request */
615 /* inbuf_size is guarenteed to be at least 4. */
617 int name_type1, name_type2;
618 int name_len1, name_len2;
622 if (xconn->transport.nbt.got_session) {
623 exit_server_cleanly("multiple session request not permitted");
626 SCVAL(outbuf,0,NBSSpositive);
629 /* inbuf_size is guaranteed to be at least 4. */
630 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
631 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
632 DEBUG(0,("Invalid name length in session request\n"));
633 reply_called_name_not_present(outbuf);
636 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
637 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
638 DEBUG(0,("Invalid name length in session request\n"));
639 reply_called_name_not_present(outbuf);
643 name_type1 = name_extract((unsigned char *)inbuf,
644 inbuf_size,(unsigned int)4,name1);
645 name_type2 = name_extract((unsigned char *)inbuf,
646 inbuf_size,(unsigned int)(4 + name_len1),name2);
648 if (name_type1 == -1 || name_type2 == -1) {
649 DEBUG(0,("Invalid name type in session request\n"));
650 reply_called_name_not_present(outbuf);
654 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
655 name1, name_type1, name2, name_type2));
657 if (netbios_session_retarget(xconn, name1, name_type1)) {
658 exit_server_cleanly("retargeted client");
662 * Windows NT/2k uses "*SMBSERVER" and XP uses
663 * "*SMBSERV" arrggg!!!
665 if (strequal(name1, "*SMBSERVER ")
666 || strequal(name1, "*SMBSERV ")) {
669 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
672 exit_server_cleanly("could not allocate raddr");
675 fstrcpy(name1, raddr);
678 set_local_machine_name(name1, True);
679 set_remote_machine_name(name2, True);
681 if (is_ipaddress(sconn->remote_hostname)) {
682 char *p = discard_const_p(char, sconn->remote_hostname);
686 sconn->remote_hostname = talloc_strdup(sconn,
687 get_remote_machine_name());
688 if (sconn->remote_hostname == NULL) {
689 exit_server_cleanly("could not copy remote name");
691 xconn->remote_hostname = sconn->remote_hostname;
694 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
695 get_local_machine_name(), get_remote_machine_name(),
698 if (name_type2 == 'R') {
699 /* We are being asked for a pathworks session ---
701 reply_called_name_not_present(outbuf);
705 reload_services(sconn, conn_snum_used, true);
708 xconn->transport.nbt.got_session = true;
712 case 0x89: /* session keepalive request
713 (some old clients produce this?) */
714 SCVAL(outbuf,0,NBSSkeepalive);
718 case NBSSpositive: /* positive session response */
719 case NBSSnegative: /* negative session response */
720 case NBSSretarget: /* retarget session response */
721 DEBUG(0,("Unexpected session response\n"));
724 case NBSSkeepalive: /* session keepalive */
729 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
730 msg_type, msg_flags));
732 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
733 exit_server_cleanly("reply_special: srv_send_smb failed.");
736 if (CVAL(outbuf, 0) != 0x82) {
737 exit_server_cleanly("invalid netbios session");
742 /****************************************************************************
744 conn POINTER CAN BE NULL HERE !
745 ****************************************************************************/
747 void reply_tcon(struct smb_request *req)
749 connection_struct *conn = req->conn;
751 char *service_buf = NULL;
752 char *password = NULL;
758 TALLOC_CTX *ctx = talloc_tos();
759 struct smbXsrv_connection *xconn = req->xconn;
760 NTTIME now = timeval_to_nttime(&req->request_time);
762 START_PROFILE(SMBtcon);
764 if (req->buflen < 4) {
765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
766 END_PROFILE(SMBtcon);
771 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
773 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
775 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
778 if (service_buf == NULL || password == NULL || dev == NULL) {
779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
780 END_PROFILE(SMBtcon);
783 p2 = strrchr_m(service_buf,'\\');
787 service = service_buf;
790 conn = make_connection(req, now, service, dev,
791 req->vuid,&nt_status);
795 reply_nterror(req, nt_status);
796 END_PROFILE(SMBtcon);
800 reply_outbuf(req, 2, 0);
801 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
802 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
803 SSVAL(req->outbuf,smb_tid,conn->cnum);
805 DEBUG(3,("tcon service=%s cnum=%d\n",
806 service, conn->cnum));
808 END_PROFILE(SMBtcon);
812 /****************************************************************************
813 Reply to a tcon and X.
814 conn POINTER CAN BE NULL HERE !
815 ****************************************************************************/
817 void reply_tcon_and_X(struct smb_request *req)
819 const struct loadparm_substitution *lp_sub =
820 loadparm_s3_global_substitution();
821 connection_struct *conn = req->conn;
822 const char *service = NULL;
823 TALLOC_CTX *ctx = talloc_tos();
824 /* what the client thinks the device is */
825 char *client_devicetype = NULL;
826 /* what the server tells the client the share represents */
827 const char *server_devicetype;
834 struct smbXsrv_session *session = NULL;
835 NTTIME now = timeval_to_nttime(&req->request_time);
836 bool session_key_updated = false;
837 uint16_t optional_support = 0;
838 struct smbXsrv_connection *xconn = req->xconn;
840 START_PROFILE(SMBtconX);
843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
844 END_PROFILE(SMBtconX);
848 passlen = SVAL(req->vwv+3, 0);
849 tcon_flags = SVAL(req->vwv+2, 0);
851 /* we might have to close an old one */
852 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
853 struct smbXsrv_tcon *tcon;
861 * TODO: cancel all outstanding requests on the tcon
863 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
864 if (!NT_STATUS_IS_OK(status)) {
865 DEBUG(0, ("reply_tcon_and_X: "
866 "smbXsrv_tcon_disconnect() failed: %s\n",
869 * If we hit this case, there is something completely
870 * wrong, so we better disconnect the transport connection.
872 END_PROFILE(SMBtconX);
873 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
879 * This tree id is gone. Make sure we can't re-use it
885 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
886 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
887 END_PROFILE(SMBtconX);
891 if (xconn->smb1.negprot.encrypted_passwords) {
892 p = req->buf + passlen;
894 p = req->buf + passlen + 1;
897 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
901 END_PROFILE(SMBtconX);
906 * the service name can be either: \\server\share
907 * or share directly like on the DELL PowerVault 705
910 q = strchr_m(path+2,'\\');
912 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
913 END_PROFILE(SMBtconX);
921 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
922 &client_devicetype, p,
923 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
925 if (client_devicetype == NULL) {
926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
927 END_PROFILE(SMBtconX);
931 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
933 nt_status = smb1srv_session_lookup(xconn,
934 req->vuid, now, &session);
935 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
936 reply_force_doserror(req, ERRSRV, ERRbaduid);
937 END_PROFILE(SMBtconX);
940 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
941 reply_nterror(req, nt_status);
942 END_PROFILE(SMBtconX);
945 if (!NT_STATUS_IS_OK(nt_status)) {
946 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
947 END_PROFILE(SMBtconX);
951 if (session->global->auth_session_info == NULL) {
952 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
953 END_PROFILE(SMBtconX);
958 * If there is no application key defined yet
961 * This means we setup the application key on the
962 * first tcon that happens via the given session.
964 * Once the application key is defined, it does not
967 if (session->global->application_key.length == 0 &&
968 smb2_signing_key_valid(session->global->signing_key))
970 struct smbXsrv_session *x = session;
971 struct auth_session_info *session_info =
972 session->global->auth_session_info;
973 uint8_t session_key[16];
975 ZERO_STRUCT(session_key);
976 memcpy(session_key, x->global->signing_key->blob.data,
977 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
980 * The application key is truncated/padded to 16 bytes
982 x->global->application_key = data_blob_talloc(x->global,
984 sizeof(session_key));
985 ZERO_STRUCT(session_key);
986 if (x->global->application_key.data == NULL) {
987 reply_nterror(req, NT_STATUS_NO_MEMORY);
988 END_PROFILE(SMBtconX);
992 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
995 status = smb_key_derivation(x->global->application_key.data,
996 x->global->application_key.length,
997 x->global->application_key.data);
998 if (!NT_STATUS_IS_OK(status)) {
999 DBG_ERR("smb_key_derivation failed: %s\n",
1001 END_PROFILE(SMBtconX);
1004 optional_support |= SMB_EXTENDED_SIGNATURES;
1008 * Place the application key into the session_info
1010 data_blob_clear_free(&session_info->session_key);
1011 session_info->session_key = data_blob_dup_talloc(session_info,
1012 x->global->application_key);
1013 if (session_info->session_key.data == NULL) {
1014 data_blob_clear_free(&x->global->application_key);
1015 reply_nterror(req, NT_STATUS_NO_MEMORY);
1016 END_PROFILE(SMBtconX);
1019 session_key_updated = true;
1022 conn = make_connection(req, now, service, client_devicetype,
1023 req->vuid, &nt_status);
1027 if (session_key_updated) {
1028 struct smbXsrv_session *x = session;
1029 struct auth_session_info *session_info =
1030 session->global->auth_session_info;
1031 data_blob_clear_free(&x->global->application_key);
1032 data_blob_clear_free(&session_info->session_key);
1034 reply_nterror(req, nt_status);
1035 END_PROFILE(SMBtconX);
1040 server_devicetype = "IPC";
1041 else if ( IS_PRINT(conn) )
1042 server_devicetype = "LPT1:";
1044 server_devicetype = "A:";
1046 if (get_Protocol() < PROTOCOL_NT1) {
1047 reply_outbuf(req, 2, 0);
1048 if (message_push_string(&req->outbuf, server_devicetype,
1049 STR_TERMINATE|STR_ASCII) == -1) {
1050 reply_nterror(req, NT_STATUS_NO_MEMORY);
1051 END_PROFILE(SMBtconX);
1055 /* NT sets the fstype of IPC$ to the null string */
1056 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1058 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1059 /* Return permissions. */
1063 reply_outbuf(req, 7, 0);
1066 perm1 = FILE_ALL_ACCESS;
1067 perm2 = FILE_ALL_ACCESS;
1069 perm1 = conn->share_access;
1072 SIVAL(req->outbuf, smb_vwv3, perm1);
1073 SIVAL(req->outbuf, smb_vwv5, perm2);
1075 reply_outbuf(req, 3, 0);
1078 if ((message_push_string(&req->outbuf, server_devicetype,
1079 STR_TERMINATE|STR_ASCII) == -1)
1080 || (message_push_string(&req->outbuf, fstype,
1081 STR_TERMINATE) == -1)) {
1082 reply_nterror(req, NT_STATUS_NO_MEMORY);
1083 END_PROFILE(SMBtconX);
1087 /* what does setting this bit do? It is set by NT4 and
1088 may affect the ability to autorun mounted cdroms */
1089 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1091 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1093 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1094 DEBUG(2,("Serving %s as a Dfs root\n",
1095 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1096 optional_support |= SMB_SHARE_IN_DFS;
1099 SSVAL(req->outbuf, smb_vwv2, optional_support);
1102 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1103 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1105 DEBUG(3,("tconX service=%s \n",
1108 /* set the incoming and outgoing tid to the just created one */
1109 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1110 SSVAL(req->outbuf,smb_tid,conn->cnum);
1112 END_PROFILE(SMBtconX);
1114 req->tid = conn->cnum;
1117 /****************************************************************************
1118 Reply to an unknown type.
1119 ****************************************************************************/
1121 void reply_unknown_new(struct smb_request *req, uint8_t type)
1123 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1124 smb_fn_name(type), type, type));
1125 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1129 /****************************************************************************
1131 conn POINTER CAN BE NULL HERE !
1132 ****************************************************************************/
1134 void reply_ioctl(struct smb_request *req)
1136 const struct loadparm_substitution *lp_sub =
1137 loadparm_s3_global_substitution();
1138 connection_struct *conn = req->conn;
1141 uint32_t ioctl_code;
1145 START_PROFILE(SMBioctl);
1148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1149 END_PROFILE(SMBioctl);
1153 device = SVAL(req->vwv+1, 0);
1154 function = SVAL(req->vwv+2, 0);
1155 ioctl_code = (device << 16) + function;
1157 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1159 switch (ioctl_code) {
1160 case IOCTL_QUERY_JOB_INFO:
1164 reply_force_doserror(req, ERRSRV, ERRnosupport);
1165 END_PROFILE(SMBioctl);
1169 reply_outbuf(req, 8, replysize+1);
1170 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1171 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1172 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1173 p = smb_buf(req->outbuf);
1174 memset(p, '\0', replysize+1); /* valgrind-safe. */
1175 p += 1; /* Allow for alignment */
1177 switch (ioctl_code) {
1178 case IOCTL_QUERY_JOB_INFO:
1182 files_struct *fsp = file_fsp(
1183 req, SVAL(req->vwv+0, 0));
1185 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1186 END_PROFILE(SMBioctl);
1190 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1192 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1193 lp_netbios_name(), 15,
1194 STR_TERMINATE|STR_ASCII, &len);
1195 if (!NT_STATUS_IS_OK(status)) {
1196 reply_nterror(req, status);
1197 END_PROFILE(SMBioctl);
1201 status = srvstr_push((char *)req->outbuf, req->flags2,
1203 lp_servicename(talloc_tos(),
1206 13, STR_TERMINATE|STR_ASCII, &len);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 reply_nterror(req, status);
1209 END_PROFILE(SMBioctl);
1213 memset(p+18, 0, 13);
1219 END_PROFILE(SMBioctl);
1223 /****************************************************************************
1224 Strange checkpath NTSTATUS mapping.
1225 ****************************************************************************/
1227 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1229 /* Strange DOS error code semantics only for checkpath... */
1230 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1231 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1232 /* We need to map to ERRbadpath */
1233 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1239 /****************************************************************************
1240 Reply to a checkpath.
1241 ****************************************************************************/
1243 void reply_checkpath(struct smb_request *req)
1245 connection_struct *conn = req->conn;
1246 struct smb_filename *smb_fname = NULL;
1249 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1250 TALLOC_CTX *ctx = talloc_tos();
1252 START_PROFILE(SMBcheckpath);
1254 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1255 STR_TERMINATE, &status);
1257 if (!NT_STATUS_IS_OK(status)) {
1258 status = map_checkpath_error(req->flags2, status);
1259 reply_nterror(req, status);
1260 END_PROFILE(SMBcheckpath);
1264 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1266 status = filename_convert(ctx,
1273 if (!NT_STATUS_IS_OK(status)) {
1274 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1275 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1276 ERRSRV, ERRbadpath);
1277 END_PROFILE(SMBcheckpath);
1283 if (!VALID_STAT(smb_fname->st) &&
1284 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1285 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1286 smb_fname_str_dbg(smb_fname), strerror(errno)));
1287 status = map_nt_error_from_unix(errno);
1291 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1292 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1293 ERRDOS, ERRbadpath);
1297 reply_outbuf(req, 0, 0);
1300 /* We special case this - as when a Windows machine
1301 is parsing a path is steps through the components
1302 one at a time - if a component fails it expects
1303 ERRbadpath, not ERRbadfile.
1305 status = map_checkpath_error(req->flags2, status);
1306 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1308 * Windows returns different error codes if
1309 * the parent directory is valid but not the
1310 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1311 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1312 * if the path is invalid.
1314 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1315 ERRDOS, ERRbadpath);
1319 reply_nterror(req, status);
1322 TALLOC_FREE(smb_fname);
1323 END_PROFILE(SMBcheckpath);
1327 /****************************************************************************
1329 ****************************************************************************/
1331 void reply_getatr(struct smb_request *req)
1333 connection_struct *conn = req->conn;
1334 struct smb_filename *smb_fname = NULL;
1341 TALLOC_CTX *ctx = talloc_tos();
1342 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1344 START_PROFILE(SMBgetatr);
1346 p = (const char *)req->buf + 1;
1347 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1348 if (!NT_STATUS_IS_OK(status)) {
1349 reply_nterror(req, status);
1353 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1354 under WfWg - weird! */
1355 if (*fname == '\0') {
1356 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1357 if (!CAN_WRITE(conn)) {
1358 mode |= FILE_ATTRIBUTE_READONLY;
1363 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1364 status = filename_convert(ctx,
1370 if (!NT_STATUS_IS_OK(status)) {
1371 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1372 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1373 ERRSRV, ERRbadpath);
1376 reply_nterror(req, status);
1379 if (!VALID_STAT(smb_fname->st) &&
1380 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1381 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1382 smb_fname_str_dbg(smb_fname),
1384 reply_nterror(req, map_nt_error_from_unix(errno));
1388 mode = dos_mode(conn, smb_fname);
1389 size = smb_fname->st.st_ex_size;
1391 if (ask_sharemode) {
1392 struct timespec write_time_ts;
1393 struct file_id fileid;
1395 ZERO_STRUCT(write_time_ts);
1396 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1397 get_file_infos(fileid, 0, NULL, &write_time_ts);
1398 if (!is_omit_timespec(&write_time_ts)) {
1399 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1403 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1404 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1409 reply_outbuf(req, 10, 0);
1411 SSVAL(req->outbuf,smb_vwv0,mode);
1412 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1413 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1415 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1417 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1419 if (get_Protocol() >= PROTOCOL_NT1) {
1420 SSVAL(req->outbuf, smb_flg2,
1421 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1424 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1425 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1428 TALLOC_FREE(smb_fname);
1430 END_PROFILE(SMBgetatr);
1434 /****************************************************************************
1436 ****************************************************************************/
1438 void reply_setatr(struct smb_request *req)
1440 struct smb_file_time ft;
1441 connection_struct *conn = req->conn;
1442 struct smb_filename *smb_fname = NULL;
1448 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1449 TALLOC_CTX *ctx = talloc_tos();
1451 START_PROFILE(SMBsetatr);
1452 init_smb_file_time(&ft);
1455 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1459 p = (const char *)req->buf + 1;
1460 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1461 if (!NT_STATUS_IS_OK(status)) {
1462 reply_nterror(req, status);
1466 status = filename_convert(ctx,
1472 if (!NT_STATUS_IS_OK(status)) {
1473 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1474 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1475 ERRSRV, ERRbadpath);
1478 reply_nterror(req, status);
1482 if (ISDOT(smb_fname->base_name)) {
1484 * Not sure here is the right place to catch this
1485 * condition. Might be moved to somewhere else later -- vl
1487 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1491 mode = SVAL(req->vwv+0, 0);
1492 mtime = srv_make_unix_date3(req->vwv+1);
1494 if (mode != FILE_ATTRIBUTE_NORMAL) {
1495 if (VALID_STAT_OF_DIR(smb_fname->st))
1496 mode |= FILE_ATTRIBUTE_DIRECTORY;
1498 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1500 status = smbd_check_access_rights(conn,
1504 FILE_WRITE_ATTRIBUTES);
1505 if (!NT_STATUS_IS_OK(status)) {
1506 reply_nterror(req, status);
1510 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1512 reply_nterror(req, map_nt_error_from_unix(errno));
1517 ft.mtime = time_t_to_full_timespec(mtime);
1519 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1520 if (!NT_STATUS_IS_OK(status)) {
1521 reply_nterror(req, status);
1525 reply_outbuf(req, 0, 0);
1527 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1530 TALLOC_FREE(smb_fname);
1531 END_PROFILE(SMBsetatr);
1535 /****************************************************************************
1537 ****************************************************************************/
1539 void reply_dskattr(struct smb_request *req)
1541 connection_struct *conn = req->conn;
1543 uint64_t dfree,dsize,bsize;
1544 struct smb_filename smb_fname;
1545 START_PROFILE(SMBdskattr);
1547 ZERO_STRUCT(smb_fname);
1548 smb_fname.base_name = discard_const_p(char, ".");
1550 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1551 reply_nterror(req, map_nt_error_from_unix(errno));
1552 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1553 END_PROFILE(SMBdskattr);
1557 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1558 if (ret == (uint64_t)-1) {
1559 reply_nterror(req, map_nt_error_from_unix(errno));
1560 END_PROFILE(SMBdskattr);
1565 * Force max to fit in 16 bit fields.
1567 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1571 if (bsize > (WORDMAX*512)) {
1572 bsize = (WORDMAX*512);
1573 if (dsize > WORDMAX)
1575 if (dfree > WORDMAX)
1581 reply_outbuf(req, 5, 0);
1583 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1584 double total_space, free_space;
1585 /* we need to scale this to a number that DOS6 can handle. We
1586 use floating point so we can handle large drives on systems
1587 that don't have 64 bit integers
1589 we end up displaying a maximum of 2G to DOS systems
1591 total_space = dsize * (double)bsize;
1592 free_space = dfree * (double)bsize;
1594 dsize = (uint64_t)((total_space+63*512) / (64*512));
1595 dfree = (uint64_t)((free_space+63*512) / (64*512));
1597 if (dsize > 0xFFFF) dsize = 0xFFFF;
1598 if (dfree > 0xFFFF) dfree = 0xFFFF;
1600 SSVAL(req->outbuf,smb_vwv0,dsize);
1601 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1602 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1603 SSVAL(req->outbuf,smb_vwv3,dfree);
1605 SSVAL(req->outbuf,smb_vwv0,dsize);
1606 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1607 SSVAL(req->outbuf,smb_vwv2,512);
1608 SSVAL(req->outbuf,smb_vwv3,dfree);
1611 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1613 END_PROFILE(SMBdskattr);
1618 * Utility function to split the filename from the directory.
1620 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1621 char **fname_dir_out,
1622 char **fname_mask_out)
1624 const char *p = NULL;
1625 char *fname_dir = NULL;
1626 char *fname_mask = NULL;
1628 p = strrchr_m(fname_in, '/');
1630 fname_dir = talloc_strdup(ctx, ".");
1631 fname_mask = talloc_strdup(ctx, fname_in);
1633 fname_dir = talloc_strndup(ctx, fname_in,
1634 PTR_DIFF(p, fname_in));
1635 fname_mask = talloc_strdup(ctx, p+1);
1638 if (!fname_dir || !fname_mask) {
1639 TALLOC_FREE(fname_dir);
1640 TALLOC_FREE(fname_mask);
1641 return NT_STATUS_NO_MEMORY;
1644 *fname_dir_out = fname_dir;
1645 *fname_mask_out = fname_mask;
1646 return NT_STATUS_OK;
1649 /****************************************************************************
1651 ****************************************************************************/
1653 static bool make_dir_struct(TALLOC_CTX *ctx,
1663 char *mask2 = talloc_strdup(ctx, mask);
1669 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1673 memset(buf+1,' ',11);
1674 if ((p = strchr_m(mask2,'.')) != NULL) {
1676 push_ascii(buf+1,mask2,8, 0);
1677 push_ascii(buf+9,p+1,3, 0);
1680 push_ascii(buf+1,mask2,11, 0);
1683 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1685 srv_put_dos_date(buf,22,date);
1686 SSVAL(buf,26,size & 0xFFFF);
1687 SSVAL(buf,28,(size >> 16)&0xFFFF);
1688 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1689 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1690 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1691 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1695 /****************************************************************************
1697 Can be called from SMBsearch, SMBffirst or SMBfunique.
1698 ****************************************************************************/
1700 void reply_search(struct smb_request *req)
1702 connection_struct *conn = req->conn;
1705 char *directory = NULL;
1706 struct smb_filename *smb_fname = NULL;
1710 struct timespec date;
1712 unsigned int numentries = 0;
1713 unsigned int maxentries = 0;
1714 bool finished = False;
1719 bool check_descend = False;
1720 bool expect_close = False;
1722 bool mask_contains_wcard = False;
1723 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1724 TALLOC_CTX *ctx = talloc_tos();
1725 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1726 struct smbXsrv_connection *xconn = req->xconn;
1727 struct smbd_server_connection *sconn = req->sconn;
1728 files_struct *fsp = NULL;
1729 const struct loadparm_substitution *lp_sub =
1730 loadparm_s3_global_substitution();
1732 START_PROFILE(SMBsearch);
1735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1739 if (req->posix_pathnames) {
1740 reply_unknown_new(req, req->cmd);
1744 /* If we were called as SMBffirst then we must expect close. */
1745 if(req->cmd == SMBffirst) {
1746 expect_close = True;
1749 reply_outbuf(req, 1, 3);
1750 maxentries = SVAL(req->vwv+0, 0);
1751 dirtype = SVAL(req->vwv+1, 0);
1752 p = (const char *)req->buf + 1;
1753 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1755 if (!NT_STATUS_IS_OK(nt_status)) {
1756 reply_nterror(req, nt_status);
1760 if (smbreq_bufrem(req, p) < 3) {
1761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1766 status_len = SVAL(p, 0);
1769 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1771 if (status_len == 0) {
1773 struct smb_filename *smb_dname = NULL;
1774 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1775 ucf_flags_from_smb_request(req);
1776 nt_status = filename_convert(ctx, conn,
1781 if (!NT_STATUS_IS_OK(nt_status)) {
1782 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1783 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1784 ERRSRV, ERRbadpath);
1787 reply_nterror(req, nt_status);
1791 directory = smb_fname->base_name;
1793 p = strrchr_m(directory,'/');
1794 if ((p != NULL) && (*directory != '/')) {
1795 mask = talloc_strdup(ctx, p + 1);
1796 directory = talloc_strndup(ctx, directory,
1797 PTR_DIFF(p, directory));
1799 mask = talloc_strdup(ctx, directory);
1800 directory = talloc_strdup(ctx,".");
1804 reply_nterror(req, NT_STATUS_NO_MEMORY);
1808 memset((char *)status,'\0',21);
1809 SCVAL(status,0,(dirtype & 0x1F));
1811 smb_dname = synthetic_smb_fname(talloc_tos(),
1817 if (smb_dname == NULL) {
1818 reply_nterror(req, NT_STATUS_NO_MEMORY);
1823 * As we've cut off the last component from
1824 * smb_fname we need to re-stat smb_dname
1825 * so FILE_OPEN disposition knows the directory
1828 if (req->posix_pathnames) {
1829 ret = SMB_VFS_LSTAT(conn, smb_dname);
1831 ret = SMB_VFS_STAT(conn, smb_dname);
1834 nt_status = map_nt_error_from_unix(errno);
1835 reply_nterror(req, nt_status);
1840 * Open an fsp on this directory for the dptr.
1842 nt_status = SMB_VFS_CREATE_FILE(
1845 smb_dname, /* dname */
1846 FILE_LIST_DIRECTORY, /* access_mask */
1848 FILE_SHARE_WRITE, /* share_access */
1849 FILE_OPEN, /* create_disposition*/
1850 FILE_DIRECTORY_FILE, /* create_options */
1851 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1852 NO_OPLOCK, /* oplock_request */
1854 0, /* allocation_size */
1855 0, /* private_flags */
1860 NULL, /* in_context */
1861 NULL);/* out_context */
1863 if (!NT_STATUS_IS_OK(nt_status)) {
1864 DBG_ERR("failed to open directory %s\n",
1865 smb_fname_str_dbg(smb_dname));
1866 reply_nterror(req, nt_status);
1870 nt_status = dptr_create(conn,
1880 TALLOC_FREE(smb_dname);
1882 if (!NT_STATUS_IS_OK(nt_status)) {
1884 * Use NULL here for the first parameter (req)
1885 * as this is not a client visible handle so
1886 * can'tbe part of an SMB1 chain.
1888 close_file(NULL, fsp, NORMAL_CLOSE);
1890 reply_nterror(req, nt_status);
1894 dptr_num = dptr_dnum(fsp->dptr);
1898 const char *dirpath;
1900 if (smbreq_bufrem(req, p) < 21) {
1901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1905 memcpy(status,p,21);
1906 status_dirtype = CVAL(status,0) & 0x1F;
1907 if (status_dirtype != (dirtype & 0x1F)) {
1908 dirtype = status_dirtype;
1911 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1915 dirpath = dptr_path(sconn, dptr_num);
1916 directory = talloc_strdup(ctx, dirpath);
1918 reply_nterror(req, NT_STATUS_NO_MEMORY);
1922 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1926 dirtype = dptr_attr(sconn, dptr_num);
1929 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1931 DEBUG(4,("dptr_num is %d\n",dptr_num));
1933 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1934 char buf[DIR_STRUCT_SIZE];
1935 memcpy(buf,status,21);
1936 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1937 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1938 reply_nterror(req, NT_STATUS_NO_MEMORY);
1941 dptr_fill(sconn, buf+12,dptr_num);
1942 if (dptr_zero(buf+12) && (status_len==0)) {
1947 if (message_push_blob(&req->outbuf,
1948 data_blob_const(buf, sizeof(buf)))
1950 reply_nterror(req, NT_STATUS_NO_MEMORY);
1955 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1956 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1958 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1960 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1961 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1962 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1963 check_descend = True;
1966 for (i=numentries;(i<maxentries) && !finished;i++) {
1967 finished = !get_dir_entry(ctx,
1978 char buf[DIR_STRUCT_SIZE];
1979 memcpy(buf,status,21);
1980 if (!make_dir_struct(ctx,
1986 convert_timespec_to_time_t(date),
1987 !allow_long_path_components)) {
1988 reply_nterror(req, NT_STATUS_NO_MEMORY);
1991 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1994 if (message_push_blob(&req->outbuf,
1995 data_blob_const(buf, sizeof(buf)))
1997 reply_nterror(req, NT_STATUS_NO_MEMORY);
2007 /* If we were called as SMBffirst with smb_search_id == NULL
2008 and no entries were found then return error and close fsp->dptr
2011 if (numentries == 0) {
2014 close_file(NULL, fsp, NORMAL_CLOSE);
2017 } else if(expect_close && status_len == 0) {
2018 /* Close the dptr - we know it's gone */
2021 close_file(NULL, fsp, NORMAL_CLOSE);
2026 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2027 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2029 /* fsp may have been closed above. */
2031 close_file(NULL, fsp, NORMAL_CLOSE);
2036 if ((numentries == 0) && !mask_contains_wcard) {
2037 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2041 SSVAL(req->outbuf,smb_vwv0,numentries);
2042 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2043 SCVAL(smb_buf(req->outbuf),0,5);
2044 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2046 /* The replies here are never long name. */
2047 SSVAL(req->outbuf, smb_flg2,
2048 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2049 if (!allow_long_path_components) {
2050 SSVAL(req->outbuf, smb_flg2,
2051 SVAL(req->outbuf, smb_flg2)
2052 & (~FLAGS2_LONG_PATH_COMPONENTS));
2055 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2056 SSVAL(req->outbuf, smb_flg2,
2057 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2059 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2060 smb_fn_name(req->cmd),
2067 TALLOC_FREE(directory);
2069 TALLOC_FREE(smb_fname);
2070 END_PROFILE(SMBsearch);
2074 /****************************************************************************
2075 Reply to a fclose (stop directory search).
2076 ****************************************************************************/
2078 void reply_fclose(struct smb_request *req)
2086 TALLOC_CTX *ctx = talloc_tos();
2087 struct smbd_server_connection *sconn = req->sconn;
2088 files_struct *fsp = NULL;
2090 START_PROFILE(SMBfclose);
2092 if (req->posix_pathnames) {
2093 reply_unknown_new(req, req->cmd);
2094 END_PROFILE(SMBfclose);
2098 p = (const char *)req->buf + 1;
2099 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
2101 if (!NT_STATUS_IS_OK(err)) {
2102 reply_nterror(req, err);
2103 END_PROFILE(SMBfclose);
2107 if (smbreq_bufrem(req, p) < 3) {
2108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2109 END_PROFILE(SMBfclose);
2114 status_len = SVAL(p,0);
2117 if (status_len == 0) {
2118 reply_force_doserror(req, ERRSRV, ERRsrverror);
2119 END_PROFILE(SMBfclose);
2123 if (smbreq_bufrem(req, p) < 21) {
2124 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2125 END_PROFILE(SMBfclose);
2129 memcpy(status,p,21);
2131 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2133 /* Close the file - we know it's gone */
2134 close_file(NULL, fsp, NORMAL_CLOSE);
2139 reply_outbuf(req, 1, 0);
2140 SSVAL(req->outbuf,smb_vwv0,0);
2142 DEBUG(3,("search close\n"));
2144 END_PROFILE(SMBfclose);
2148 /****************************************************************************
2150 ****************************************************************************/
2152 void reply_open(struct smb_request *req)
2154 connection_struct *conn = req->conn;
2155 struct smb_filename *smb_fname = NULL;
2165 uint32_t access_mask;
2166 uint32_t share_mode;
2167 uint32_t create_disposition;
2168 uint32_t create_options = 0;
2169 uint32_t private_flags = 0;
2172 TALLOC_CTX *ctx = talloc_tos();
2174 START_PROFILE(SMBopen);
2177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2181 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2182 deny_mode = SVAL(req->vwv+0, 0);
2183 dos_attr = SVAL(req->vwv+1, 0);
2185 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2186 STR_TERMINATE, &status);
2187 if (!NT_STATUS_IS_OK(status)) {
2188 reply_nterror(req, status);
2192 if (!map_open_params_to_ntcreate(fname, deny_mode,
2193 OPENX_FILE_EXISTS_OPEN, &access_mask,
2194 &share_mode, &create_disposition,
2195 &create_options, &private_flags)) {
2196 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2200 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2202 status = filename_convert(ctx,
2208 if (!NT_STATUS_IS_OK(status)) {
2209 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2210 reply_botherror(req,
2211 NT_STATUS_PATH_NOT_COVERED,
2212 ERRSRV, ERRbadpath);
2215 reply_nterror(req, status);
2219 status = SMB_VFS_CREATE_FILE(
2222 smb_fname, /* fname */
2223 access_mask, /* access_mask */
2224 share_mode, /* share_access */
2225 create_disposition, /* create_disposition*/
2226 create_options, /* create_options */
2227 dos_attr, /* file_attributes */
2228 oplock_request, /* oplock_request */
2230 0, /* allocation_size */
2236 NULL, NULL); /* create context */
2238 if (!NT_STATUS_IS_OK(status)) {
2239 if (open_was_deferred(req->xconn, req->mid)) {
2240 /* We have re-scheduled this call. */
2244 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2245 reply_openerror(req, status);
2249 fsp = fcb_or_dos_open(
2256 bool ok = defer_smb1_sharing_violation(req);
2260 reply_openerror(req, status);
2265 /* Ensure we're pointing at the correct stat struct. */
2266 TALLOC_FREE(smb_fname);
2267 smb_fname = fsp->fsp_name;
2269 size = smb_fname->st.st_ex_size;
2270 fattr = dos_mode(conn, smb_fname);
2272 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2274 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2275 DEBUG(3,("attempt to open a directory %s\n",
2277 close_file(req, fsp, ERROR_CLOSE);
2278 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2279 ERRDOS, ERRnoaccess);
2283 reply_outbuf(req, 7, 0);
2284 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2285 SSVAL(req->outbuf,smb_vwv1,fattr);
2286 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2287 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2289 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2291 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2292 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2294 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2295 SCVAL(req->outbuf,smb_flg,
2296 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2299 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2300 SCVAL(req->outbuf,smb_flg,
2301 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2304 END_PROFILE(SMBopen);
2308 /****************************************************************************
2309 Reply to an open and X.
2310 ****************************************************************************/
2312 void reply_open_and_X(struct smb_request *req)
2314 connection_struct *conn = req->conn;
2315 struct smb_filename *smb_fname = NULL;
2317 uint16_t open_flags;
2320 /* Breakout the oplock request bits so we can set the
2321 reply bits separately. */
2322 int ex_oplock_request;
2323 int core_oplock_request;
2326 int smb_sattr = SVAL(req->vwv+4, 0);
2327 uint32_t smb_time = make_unix_date3(req->vwv+6);
2335 uint64_t allocation_size;
2336 ssize_t retval = -1;
2337 uint32_t access_mask;
2338 uint32_t share_mode;
2339 uint32_t create_disposition;
2340 uint32_t create_options = 0;
2341 uint32_t private_flags = 0;
2343 TALLOC_CTX *ctx = talloc_tos();
2345 START_PROFILE(SMBopenX);
2347 if (req->wct < 15) {
2348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2352 open_flags = SVAL(req->vwv+2, 0);
2353 deny_mode = SVAL(req->vwv+3, 0);
2354 smb_attr = SVAL(req->vwv+5, 0);
2355 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2356 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2357 oplock_request = ex_oplock_request | core_oplock_request;
2358 smb_ofun = SVAL(req->vwv+8, 0);
2359 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2361 /* If it's an IPC, pass off the pipe handler. */
2363 if (lp_nt_pipe_support()) {
2364 reply_open_pipe_and_X(conn, req);
2366 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2371 /* XXXX we need to handle passed times, sattr and flags */
2372 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2373 STR_TERMINATE, &status);
2374 if (!NT_STATUS_IS_OK(status)) {
2375 reply_nterror(req, status);
2379 if (!map_open_params_to_ntcreate(fname, deny_mode,
2381 &access_mask, &share_mode,
2382 &create_disposition,
2385 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2389 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2391 status = filename_convert(ctx,
2397 if (!NT_STATUS_IS_OK(status)) {
2398 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2399 reply_botherror(req,
2400 NT_STATUS_PATH_NOT_COVERED,
2401 ERRSRV, ERRbadpath);
2404 reply_nterror(req, status);
2408 status = SMB_VFS_CREATE_FILE(
2411 smb_fname, /* fname */
2412 access_mask, /* access_mask */
2413 share_mode, /* share_access */
2414 create_disposition, /* create_disposition*/
2415 create_options, /* create_options */
2416 smb_attr, /* file_attributes */
2417 oplock_request, /* oplock_request */
2419 0, /* allocation_size */
2424 &smb_action, /* pinfo */
2425 NULL, NULL); /* create context */
2427 if (!NT_STATUS_IS_OK(status)) {
2428 if (open_was_deferred(req->xconn, req->mid)) {
2429 /* We have re-scheduled this call. */
2433 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2434 reply_openerror(req, status);
2438 fsp = fcb_or_dos_open(
2445 bool ok = defer_smb1_sharing_violation(req);
2449 reply_openerror(req, status);
2454 smb_action = FILE_WAS_OPENED;
2457 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2458 if the file is truncated or created. */
2459 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2460 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2461 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2462 close_file(req, fsp, ERROR_CLOSE);
2463 reply_nterror(req, NT_STATUS_DISK_FULL);
2466 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2468 close_file(req, fsp, ERROR_CLOSE);
2469 reply_nterror(req, NT_STATUS_DISK_FULL);
2472 status = vfs_stat_fsp(fsp);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 close_file(req, fsp, ERROR_CLOSE);
2475 reply_nterror(req, status);
2480 fattr = dos_mode(conn, fsp->fsp_name);
2481 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2482 close_file(req, fsp, ERROR_CLOSE);
2483 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2486 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2488 /* If the caller set the extended oplock request bit
2489 and we granted one (by whatever means) - set the
2490 correct bit for extended oplock reply.
2493 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2494 smb_action |= EXTENDED_OPLOCK_GRANTED;
2497 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2498 smb_action |= EXTENDED_OPLOCK_GRANTED;
2501 /* If the caller set the core oplock request bit
2502 and we granted one (by whatever means) - set the
2503 correct bit for core oplock reply.
2506 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2507 reply_outbuf(req, 19, 0);
2509 reply_outbuf(req, 15, 0);
2512 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2513 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2515 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2516 SCVAL(req->outbuf, smb_flg,
2517 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2520 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2521 SCVAL(req->outbuf, smb_flg,
2522 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2525 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2526 SSVAL(req->outbuf,smb_vwv3,fattr);
2527 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2528 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2530 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2532 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2533 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2534 SSVAL(req->outbuf,smb_vwv11,smb_action);
2536 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2537 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2541 TALLOC_FREE(smb_fname);
2542 END_PROFILE(SMBopenX);
2546 /****************************************************************************
2547 Reply to a SMBulogoffX.
2548 ****************************************************************************/
2550 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2551 struct smbXsrv_session *session);
2552 static void reply_ulogoffX_done(struct tevent_req *req);
2554 void reply_ulogoffX(struct smb_request *smb1req)
2556 struct timeval now = timeval_current();
2557 struct smbXsrv_session *session = NULL;
2558 struct tevent_req *req;
2562 * Don't setup the profile charge here, take
2563 * it in reply_ulogoffX_done(). Not strictly correct
2564 * but better than the other SMB1 async
2565 * code that double-charges at the moment.
2568 status = smb1srv_session_lookup(smb1req->xconn,
2570 timeval_to_nttime(&now),
2572 if (!NT_STATUS_IS_OK(status)) {
2573 /* Not going async, profile here. */
2574 START_PROFILE(SMBulogoffX);
2575 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2576 (unsigned long long)smb1req->vuid);
2578 smb1req->vuid = UID_FIELD_INVALID;
2579 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2580 END_PROFILE(SMBulogoffX);
2584 req = reply_ulogoffX_send(smb1req, session);
2586 /* Not going async, profile here. */
2587 START_PROFILE(SMBulogoffX);
2588 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2589 END_PROFILE(SMBulogoffX);
2593 /* We're async. This will complete later. */
2594 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2598 struct reply_ulogoffX_state {
2599 struct tevent_queue *wait_queue;
2600 struct smbXsrv_session *session;
2603 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2605 /****************************************************************************
2606 Async SMB1 ulogoffX.
2607 Note, on failure here we deallocate and return NULL to allow the caller to
2608 SMB1 return an error of ERRnomem immediately.
2609 ****************************************************************************/
2611 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2612 struct smbXsrv_session *session)
2614 struct tevent_req *req;
2615 struct reply_ulogoffX_state *state;
2616 struct tevent_req *subreq;
2618 struct smbd_server_connection *sconn = session->client->sconn;
2619 uint64_t vuid = session->global->session_wire_id;
2621 req = tevent_req_create(smb1req, &state,
2622 struct reply_ulogoffX_state);
2626 state->wait_queue = tevent_queue_create(state,
2627 "reply_ulogoffX_wait_queue");
2628 if (tevent_req_nomem(state->wait_queue, req)) {
2632 state->session = session;
2635 * Make sure that no new request will be able to use this session.
2636 * This ensures that once all outstanding fsp->aio_requests
2637 * on this session are done, we are safe to close it.
2639 session->status = NT_STATUS_USER_SESSION_DELETED;
2641 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2642 if (fsp->vuid != vuid) {
2646 * Flag the file as close in progress.
2647 * This will prevent any more IO being
2650 fsp->fsp_flags.closing = true;
2652 if (fsp->num_aio_requests > 0) {
2654 * Now wait until all aio requests on this fsp are
2657 * We don't set a callback, as we just want to block the
2658 * wait queue and the talloc_free() of fsp->aio_request
2659 * will remove the item from the wait queue.
2661 subreq = tevent_queue_wait_send(fsp->aio_requests,
2664 if (tevent_req_nomem(subreq, req)) {
2672 * Now we add our own waiter to the end of the queue,
2673 * this way we get notified when all pending requests are finished
2674 * and reply to the outstanding SMB1 request.
2676 subreq = tevent_queue_wait_send(state,
2679 if (tevent_req_nomem(subreq, req)) {
2685 * We're really going async - move the SMB1 request from
2686 * a talloc stackframe above us to the sconn talloc-context.
2687 * We need this to stick around until the wait_done
2688 * callback is invoked.
2690 smb1req = talloc_move(sconn, &smb1req);
2692 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2697 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2699 struct tevent_req *req = tevent_req_callback_data(
2700 subreq, struct tevent_req);
2702 tevent_queue_wait_recv(subreq);
2703 TALLOC_FREE(subreq);
2704 tevent_req_done(req);
2707 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2709 return tevent_req_simple_recv_ntstatus(req);
2712 static void reply_ulogoffX_done(struct tevent_req *req)
2714 struct smb_request *smb1req = tevent_req_callback_data(
2715 req, struct smb_request);
2716 struct reply_ulogoffX_state *state = tevent_req_data(req,
2717 struct reply_ulogoffX_state);
2718 struct smbXsrv_session *session = state->session;
2722 * Take the profile charge here. Not strictly
2723 * correct but better than the other SMB1 async
2724 * code that double-charges at the moment.
2726 START_PROFILE(SMBulogoffX);
2728 status = reply_ulogoffX_recv(req);
2730 if (!NT_STATUS_IS_OK(status)) {
2731 TALLOC_FREE(smb1req);
2732 END_PROFILE(SMBulogoffX);
2733 exit_server(__location__ ": reply_ulogoffX_recv failed");
2737 status = smbXsrv_session_logoff(session);
2738 if (!NT_STATUS_IS_OK(status)) {
2739 TALLOC_FREE(smb1req);
2740 END_PROFILE(SMBulogoffX);
2741 exit_server(__location__ ": smbXsrv_session_logoff failed");
2745 TALLOC_FREE(session);
2747 reply_outbuf(smb1req, 2, 0);
2748 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2749 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2751 DBG_NOTICE("ulogoffX vuid=%llu\n",
2752 (unsigned long long)smb1req->vuid);
2754 smb1req->vuid = UID_FIELD_INVALID;
2756 * The following call is needed to push the
2757 * reply data back out the socket after async
2758 * return. Plus it frees smb1req.
2760 smb_request_done(smb1req);
2761 END_PROFILE(SMBulogoffX);
2764 /****************************************************************************
2765 Reply to a mknew or a create.
2766 ****************************************************************************/
2768 void reply_mknew(struct smb_request *req)
2770 connection_struct *conn = req->conn;
2771 struct smb_filename *smb_fname = NULL;
2774 struct smb_file_time ft;
2776 int oplock_request = 0;
2778 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2779 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2780 uint32_t create_disposition;
2781 uint32_t create_options = 0;
2783 TALLOC_CTX *ctx = talloc_tos();
2785 START_PROFILE(SMBcreate);
2786 init_smb_file_time(&ft);
2789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2793 fattr = SVAL(req->vwv+0, 0);
2794 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2796 if (req->cmd == SMBmknew) {
2797 /* We should fail if file exists. */
2798 create_disposition = FILE_CREATE;
2800 /* Create if file doesn't exist, truncate if it does. */
2801 create_disposition = FILE_OVERWRITE_IF;
2805 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2807 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2808 STR_TERMINATE, &status);
2809 if (!NT_STATUS_IS_OK(status)) {
2810 reply_nterror(req, status);
2814 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2815 status = filename_convert(ctx,
2821 if (!NT_STATUS_IS_OK(status)) {
2822 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2823 reply_botherror(req,
2824 NT_STATUS_PATH_NOT_COVERED,
2825 ERRSRV, ERRbadpath);
2828 reply_nterror(req, status);
2832 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2833 DEBUG(0,("Attempt to create file (%s) with volid set - "
2834 "please report this\n",
2835 smb_fname_str_dbg(smb_fname)));
2838 status = SMB_VFS_CREATE_FILE(
2841 smb_fname, /* fname */
2842 access_mask, /* access_mask */
2843 share_mode, /* share_access */
2844 create_disposition, /* create_disposition*/
2845 create_options, /* create_options */
2846 fattr, /* file_attributes */
2847 oplock_request, /* oplock_request */
2849 0, /* allocation_size */
2850 0, /* private_flags */
2855 NULL, NULL); /* create context */
2857 if (!NT_STATUS_IS_OK(status)) {
2858 if (open_was_deferred(req->xconn, req->mid)) {
2859 /* We have re-scheduled this call. */
2862 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2863 bool ok = defer_smb1_sharing_violation(req);
2868 reply_openerror(req, status);
2872 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2873 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2874 if (!NT_STATUS_IS_OK(status)) {
2875 END_PROFILE(SMBcreate);
2879 reply_outbuf(req, 1, 0);
2880 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2882 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2883 SCVAL(req->outbuf,smb_flg,
2884 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2887 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2888 SCVAL(req->outbuf,smb_flg,
2889 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2892 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2893 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2894 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2895 (unsigned int)fattr));
2898 TALLOC_FREE(smb_fname);
2899 END_PROFILE(SMBcreate);
2903 /****************************************************************************
2904 Reply to a create temporary file.
2905 ****************************************************************************/
2907 void reply_ctemp(struct smb_request *req)
2909 connection_struct *conn = req->conn;
2910 struct smb_filename *smb_fname = NULL;
2911 char *wire_name = NULL;
2920 TALLOC_CTX *ctx = talloc_tos();
2922 START_PROFILE(SMBctemp);
2925 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2929 fattr = SVAL(req->vwv+0, 0);
2930 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2932 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2933 STR_TERMINATE, &status);
2934 if (!NT_STATUS_IS_OK(status)) {
2935 reply_nterror(req, status);
2939 for (i = 0; i < 10; i++) {
2941 fname = talloc_asprintf(ctx,
2944 generate_random_str_list(ctx, 5, "0123456789"));
2946 fname = talloc_asprintf(ctx,
2948 generate_random_str_list(ctx, 5, "0123456789"));
2952 reply_nterror(req, NT_STATUS_NO_MEMORY);
2956 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2957 status = filename_convert(ctx, conn,
2962 if (!NT_STATUS_IS_OK(status)) {
2963 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2964 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2965 ERRSRV, ERRbadpath);
2968 reply_nterror(req, status);
2972 /* Create the file. */
2973 status = SMB_VFS_CREATE_FILE(
2976 smb_fname, /* fname */
2977 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2978 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2979 FILE_CREATE, /* create_disposition*/
2980 0, /* create_options */
2981 fattr, /* file_attributes */
2982 oplock_request, /* oplock_request */
2984 0, /* allocation_size */
2985 0, /* private_flags */
2990 NULL, NULL); /* create context */
2992 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2994 TALLOC_FREE(smb_fname);
2998 if (!NT_STATUS_IS_OK(status)) {
2999 if (open_was_deferred(req->xconn, req->mid)) {
3000 /* We have re-scheduled this call. */
3003 if (NT_STATUS_EQUAL(
3004 status, NT_STATUS_SHARING_VIOLATION)) {
3005 bool ok = defer_smb1_sharing_violation(req);
3010 reply_openerror(req, status);
3018 /* Collision after 10 times... */
3019 reply_nterror(req, status);
3023 reply_outbuf(req, 1, 0);
3024 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3026 /* the returned filename is relative to the directory */
3027 s = strrchr_m(fsp->fsp_name->base_name, '/');
3029 s = fsp->fsp_name->base_name;
3035 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3036 thing in the byte section. JRA */
3037 SSVALS(p, 0, -1); /* what is this? not in spec */
3039 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3041 reply_nterror(req, NT_STATUS_NO_MEMORY);
3045 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3046 SCVAL(req->outbuf, smb_flg,
3047 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3050 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3051 SCVAL(req->outbuf, smb_flg,
3052 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3055 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3056 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3057 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
3059 TALLOC_FREE(smb_fname);
3060 TALLOC_FREE(wire_name);
3061 END_PROFILE(SMBctemp);
3065 /*******************************************************************
3066 Check if a user is allowed to rename a file.
3067 ********************************************************************/
3069 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3072 if (!CAN_WRITE(conn)) {
3073 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3076 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3077 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3078 /* Only bother to read the DOS attribute if we might deny the
3079 rename on the grounds of attribute mismatch. */
3080 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3081 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3082 return NT_STATUS_NO_SUCH_FILE;
3086 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3087 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3088 return NT_STATUS_OK;
3091 /* If no pathnames are open below this
3092 directory, allow the rename. */
3094 if (lp_strict_rename(SNUM(conn))) {
3096 * Strict rename, check open file db.
3098 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3099 return NT_STATUS_ACCESS_DENIED;
3101 } else if (file_find_subpath(fsp)) {
3103 * No strict rename, just look in local process.
3105 return NT_STATUS_ACCESS_DENIED;
3107 return NT_STATUS_OK;
3110 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3111 return NT_STATUS_OK;
3114 return NT_STATUS_ACCESS_DENIED;
3117 /*******************************************************************
3118 * unlink a file with all relevant access checks
3119 *******************************************************************/
3121 static NTSTATUS do_unlink(connection_struct *conn,
3122 struct smb_request *req,
3123 struct smb_filename *smb_fname,
3128 uint32_t dirtype_orig = dirtype;
3131 bool posix_paths = (req != NULL && req->posix_pathnames);
3132 struct smb2_create_blobs *posx = NULL;
3134 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3135 smb_fname_str_dbg(smb_fname),
3138 if (!CAN_WRITE(conn)) {
3139 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3143 ret = SMB_VFS_LSTAT(conn, smb_fname);
3145 ret = SMB_VFS_STAT(conn, smb_fname);
3148 return map_nt_error_from_unix(errno);
3151 fattr = dos_mode(conn, smb_fname);
3153 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3154 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3157 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3159 return NT_STATUS_NO_SUCH_FILE;
3162 if (!dir_check_ftype(fattr, dirtype)) {
3163 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3164 return NT_STATUS_FILE_IS_A_DIRECTORY;
3166 return NT_STATUS_NO_SUCH_FILE;
3169 if (dirtype_orig & 0x8000) {
3170 /* These will never be set for POSIX. */
3171 return NT_STATUS_NO_SUCH_FILE;
3175 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3176 return NT_STATUS_FILE_IS_A_DIRECTORY;
3179 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3180 return NT_STATUS_NO_SUCH_FILE;
3183 if (dirtype & 0xFF00) {
3184 /* These will never be set for POSIX. */
3185 return NT_STATUS_NO_SUCH_FILE;
3190 return NT_STATUS_NO_SUCH_FILE;
3193 /* Can't delete a directory. */
3194 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3195 return NT_STATUS_FILE_IS_A_DIRECTORY;
3200 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3201 return NT_STATUS_OBJECT_NAME_INVALID;
3202 #endif /* JRATEST */
3205 status = make_smb2_posix_create_ctx(
3206 talloc_tos(), &posx, 0777);
3207 if (!NT_STATUS_IS_OK(status)) {
3208 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3214 /* On open checks the open itself will check the share mode, so
3215 don't do it here as we'll get it wrong. */
3217 status = SMB_VFS_CREATE_FILE
3220 smb_fname, /* fname */
3221 DELETE_ACCESS, /* access_mask */
3222 FILE_SHARE_NONE, /* share_access */
3223 FILE_OPEN, /* create_disposition*/
3224 FILE_NON_DIRECTORY_FILE, /* create_options */
3225 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3226 0, /* oplock_request */
3228 0, /* allocation_size */
3229 0, /* private_flags */
3234 posx, /* in_context_blobs */
3235 NULL); /* out_context_blobs */
3239 if (!NT_STATUS_IS_OK(status)) {
3240 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3241 nt_errstr(status)));
3245 status = can_set_delete_on_close(fsp, fattr);
3246 if (!NT_STATUS_IS_OK(status)) {
3247 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3249 smb_fname_str_dbg(smb_fname),
3250 nt_errstr(status)));
3251 close_file(req, fsp, NORMAL_CLOSE);
3255 /* The set is across all open files on this dev/inode pair. */
3256 if (!set_delete_on_close(fsp, True,
3257 conn->session_info->security_token,
3258 conn->session_info->unix_token)) {
3259 close_file(req, fsp, NORMAL_CLOSE);
3260 return NT_STATUS_ACCESS_DENIED;
3263 return close_file(req, fsp, NORMAL_CLOSE);
3266 /****************************************************************************
3267 The guts of the unlink command, split out so it may be called by the NT SMB
3269 ****************************************************************************/
3271 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3272 uint32_t dirtype, struct smb_filename *smb_fname)
3274 char *fname_dir = NULL;
3275 char *fname_mask = NULL;
3277 NTSTATUS status = NT_STATUS_OK;
3278 struct smb_filename *smb_fname_dir = NULL;
3279 bool has_wild = false;
3280 TALLOC_CTX *ctx = talloc_tos();
3282 /* Split up the directory from the filename/mask. */
3283 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3284 &fname_dir, &fname_mask);
3285 if (!NT_STATUS_IS_OK(status)) {
3289 if (req != NULL && !req->posix_pathnames) {
3291 * Check the wildcard mask *before*
3292 * unmangling. As mangling is done
3293 * for names that can't be returned
3294 * to Windows the unmangled name may
3295 * contain Windows wildcard characters.
3297 has_wild = ms_has_wild(fname_mask);
3301 * We should only check the mangled cache
3302 * here if unix_convert failed. This means
3303 * that the path in 'mask' doesn't exist
3304 * on the file system and so we need to look
3305 * for a possible mangle. This patch from
3306 * Tine Smukavec <valentin.smukavec@hermes.si>.
3309 if (!VALID_STAT(smb_fname->st) &&
3310 mangle_is_mangled(fname_mask, conn->params)) {
3311 char *new_mask = NULL;
3312 mangle_lookup_name_from_8_3(ctx, fname_mask,
3313 &new_mask, conn->params);
3315 TALLOC_FREE(fname_mask);
3316 fname_mask = new_mask;
3323 * Only one file needs to be unlinked. Append the mask back
3324 * onto the directory.
3326 TALLOC_FREE(smb_fname->base_name);
3327 if (ISDOT(fname_dir)) {
3328 /* Ensure we use canonical names on open. */
3329 smb_fname->base_name = talloc_asprintf(smb_fname,
3333 smb_fname->base_name = talloc_asprintf(smb_fname,
3338 if (!smb_fname->base_name) {
3339 status = NT_STATUS_NO_MEMORY;
3343 dirtype = FILE_ATTRIBUTE_NORMAL;
3346 status = check_name(conn, smb_fname);
3347 if (!NT_STATUS_IS_OK(status)) {
3351 status = do_unlink(conn, req, smb_fname, dirtype);
3352 if (!NT_STATUS_IS_OK(status)) {
3358 struct smb_Dir *dir_hnd = NULL;
3360 const char *dname = NULL;
3361 char *talloced = NULL;
3363 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3364 status = NT_STATUS_OBJECT_NAME_INVALID;
3368 dirtype = FILE_ATTRIBUTE_NORMAL;
3371 if (strequal(fname_mask,"????????.???")) {
3372 TALLOC_FREE(fname_mask);
3373 fname_mask = talloc_strdup(ctx, "*");
3375 status = NT_STATUS_NO_MEMORY;
3380 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3386 if (smb_fname_dir == NULL) {
3387 status = NT_STATUS_NO_MEMORY;
3391 status = check_name(conn, smb_fname_dir);
3392 if (!NT_STATUS_IS_OK(status)) {
3396 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3398 if (dir_hnd == NULL) {
3399 status = map_nt_error_from_unix(errno);
3403 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3404 the pattern matches against the long name, otherwise the short name
3405 We don't implement this yet XXXX
3408 status = NT_STATUS_NO_SUCH_FILE;
3410 while ((dname = ReadDirName(dir_hnd, &offset,
3411 &smb_fname->st, &talloced))) {
3412 TALLOC_CTX *frame = talloc_stackframe();
3414 struct smb_filename *f = NULL;
3416 if (!is_visible_file(conn,
3422 TALLOC_FREE(talloced);
3426 /* Quick check for "." and ".." */
3427 if (ISDOT(dname) || ISDOTDOT(dname)) {
3429 TALLOC_FREE(talloced);
3433 if(!mask_match(dname, fname_mask,
3434 conn->case_sensitive)) {
3436 TALLOC_FREE(talloced);
3440 if (ISDOT(fname_dir)) {
3441 /* Ensure we use canonical names on open. */
3442 p = talloc_asprintf(smb_fname, "%s", dname);
3444 p = talloc_asprintf(smb_fname, "%s/%s",
3448 TALLOC_FREE(dir_hnd);
3449 status = NT_STATUS_NO_MEMORY;
3451 TALLOC_FREE(talloced);
3454 f = synthetic_smb_fname(frame,
3461 TALLOC_FREE(dir_hnd);
3462 status = NT_STATUS_NO_MEMORY;
3464 TALLOC_FREE(talloced);
3468 status = check_name(conn, f);
3469 if (!NT_STATUS_IS_OK(status)) {
3470 TALLOC_FREE(dir_hnd);
3472 TALLOC_FREE(talloced);
3476 status = do_unlink(conn, req, f, dirtype);
3477 if (!NT_STATUS_IS_OK(status)) {
3478 TALLOC_FREE(dir_hnd);
3480 TALLOC_FREE(talloced);
3485 DBG_DEBUG("successful unlink [%s]\n",
3486 smb_fname_str_dbg(f));
3489 TALLOC_FREE(talloced);
3491 TALLOC_FREE(dir_hnd);
3494 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3495 status = map_nt_error_from_unix(errno);
3499 TALLOC_FREE(smb_fname_dir);
3500 TALLOC_FREE(fname_dir);
3501 TALLOC_FREE(fname_mask);
3505 /****************************************************************************
3507 ****************************************************************************/
3509 void reply_unlink(struct smb_request *req)
3511 connection_struct *conn = req->conn;
3513 struct smb_filename *smb_fname = NULL;
3516 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3517 ucf_flags_from_smb_request(req);
3518 TALLOC_CTX *ctx = talloc_tos();
3520 START_PROFILE(SMBunlink);
3523 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3527 dirtype = SVAL(req->vwv+0, 0);
3529 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
3530 STR_TERMINATE, &status);
3531 if (!NT_STATUS_IS_OK(status)) {
3532 reply_nterror(req, status);
3536 status = filename_convert(ctx, conn,
3541 if (!NT_STATUS_IS_OK(status)) {
3542 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3543 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3544 ERRSRV, ERRbadpath);
3547 reply_nterror(req, status);
3551 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3553 status = unlink_internals(conn, req, dirtype, smb_fname);
3554 if (!NT_STATUS_IS_OK(status)) {
3555 if (open_was_deferred(req->xconn, req->mid)) {
3556 /* We have re-scheduled this call. */
3559 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3560 bool ok = defer_smb1_sharing_violation(req);
3565 reply_nterror(req, status);
3569 reply_outbuf(req, 0, 0);
3571 TALLOC_FREE(smb_fname);
3572 END_PROFILE(SMBunlink);
3576 /****************************************************************************
3578 ****************************************************************************/
3580 static void fail_readraw(void)
3582 const char *errstr = talloc_asprintf(talloc_tos(),
3583 "FAIL ! reply_readbraw: socket write fail (%s)",
3588 exit_server_cleanly(errstr);
3591 /****************************************************************************
3592 Fake (read/write) sendfile. Returns -1 on read or write fail.
3593 ****************************************************************************/
3595 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3596 off_t startpos, size_t nread)
3599 size_t tosend = nread;
3606 bufsize = MIN(nread, 65536);
3608 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3612 while (tosend > 0) {
3616 cur_read = MIN(tosend, bufsize);
3617 ret = read_file(fsp,buf,startpos,cur_read);
3623 /* If we had a short read, fill with zeros. */
3624 if (ret < cur_read) {
3625 memset(buf + ret, '\0', cur_read - ret);
3628 ret = write_data(xconn->transport.sock, buf, cur_read);
3629 if (ret != cur_read) {
3630 int saved_errno = errno;
3632 * Try and give an error message saying what
3635 DEBUG(0, ("write_data failed for client %s. "
3637 smbXsrv_connection_dbg(xconn),
3638 strerror(saved_errno)));
3640 errno = saved_errno;
3644 startpos += cur_read;
3648 return (ssize_t)nread;
3651 /****************************************************************************
3652 Deal with the case of sendfile reading less bytes from the file than
3653 requested. Fill with zeros (all we can do). Returns 0 on success
3654 ****************************************************************************/
3656 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3662 #define SHORT_SEND_BUFSIZE 1024
3663 if (nread < headersize) {
3664 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3665 "header for file %s (%s). Terminating\n",
3666 fsp_str_dbg(fsp), strerror(errno)));
3670 nread -= headersize;
3672 if (nread < smb_maxcnt) {
3673 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3675 DEBUG(0,("sendfile_short_send: malloc failed "
3676 "for file %s (%s). Terminating\n",
3677 fsp_str_dbg(fsp), strerror(errno)));
3681 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3682 "with zeros !\n", fsp_str_dbg(fsp)));
3684 while (nread < smb_maxcnt) {
3686 * We asked for the real file size and told sendfile
3687 * to not go beyond the end of the file. But it can
3688 * happen that in between our fstat call and the
3689 * sendfile call the file was truncated. This is very
3690 * bad because we have already announced the larger
3691 * number of bytes to the client.
3693 * The best we can do now is to send 0-bytes, just as
3694 * a read from a hole in a sparse file would do.
3696 * This should happen rarely enough that I don't care
3697 * about efficiency here :-)
3702 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3703 ret = write_data(xconn->transport.sock, buf, to_write);
3704 if (ret != to_write) {
3705 int saved_errno = errno;
3707 * Try and give an error message saying what
3710 DEBUG(0, ("write_data failed for client %s. "
3712 smbXsrv_connection_dbg(xconn),
3713 strerror(saved_errno)));
3714 errno = saved_errno;
3725 /****************************************************************************
3726 Return a readbraw error (4 bytes of zero).
3727 ****************************************************************************/
3729 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3735 smbd_lock_socket(xconn);
3736 if (write_data(xconn->transport.sock,header,4) != 4) {
3737 int saved_errno = errno;
3739 * Try and give an error message saying what
3742 DEBUG(0, ("write_data failed for client %s. "
3744 smbXsrv_connection_dbg(xconn),
3745 strerror(saved_errno)));
3746 errno = saved_errno;
3750 smbd_unlock_socket(xconn);
3753 /*******************************************************************
3754 Ensure we don't use sendfile if server smb signing is active.
3755 ********************************************************************/
3757 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3759 bool sign_active = false;
3761 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3762 if (get_Protocol() < PROTOCOL_NT1) {
3765 if (signing_state) {
3766 sign_active = smb_signing_is_active(signing_state);
3768 return (lp__use_sendfile(snum) &&
3769 (get_remote_arch() != RA_WIN95) &&
3772 /****************************************************************************
3773 Use sendfile in readbraw.
3774 ****************************************************************************/
3776 static void send_file_readbraw(connection_struct *conn,
3777 struct smb_request *req,
3783 struct smbXsrv_connection *xconn = req->xconn;
3784 char *outbuf = NULL;
3788 * We can only use sendfile on a non-chained packet
3789 * but we can use on a non-oplocked file. tridge proved this
3790 * on a train in Germany :-). JRA.
3791 * reply_readbraw has already checked the length.
3794 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3795 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3796 ssize_t sendfile_read = -1;
3798 DATA_BLOB header_blob;
3800 _smb_setlen(header,nread);
3801 header_blob = data_blob_const(header, 4);
3803 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3804 &header_blob, startpos,
3806 if (sendfile_read == -1) {
3807 /* Returning ENOSYS means no data at all was sent.
3808 * Do this as a normal read. */
3809 if (errno == ENOSYS) {
3810 goto normal_readbraw;
3814 * Special hack for broken Linux with no working sendfile. If we
3815 * return EINTR we sent the header but not the rest of the data.
3816 * Fake this up by doing read/write calls.
3818 if (errno == EINTR) {
3819 /* Ensure we don't do this again. */
3820 set_use_sendfile(SNUM(conn), False);
3821 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3823 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3824 DEBUG(0,("send_file_readbraw: "
3825 "fake_sendfile failed for "
3829 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3834 DEBUG(0,("send_file_readbraw: sendfile failed for "
3835 "file %s (%s). Terminating\n",
3836 fsp_str_dbg(fsp), strerror(errno)));
3837 exit_server_cleanly("send_file_readbraw sendfile failed");
3838 } else if (sendfile_read == 0) {
3840 * Some sendfile implementations return 0 to indicate
3841 * that there was a short read, but nothing was
3842 * actually written to the socket. In this case,
3843 * fallback to the normal read path so the header gets
3844 * the correct byte count.
3846 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3847 "bytes falling back to the normal read: "
3848 "%s\n", fsp_str_dbg(fsp)));
3849 goto normal_readbraw;
3852 /* Deal with possible short send. */
3853 if (sendfile_read != 4+nread) {
3854 ret = sendfile_short_send(xconn, fsp,
3855 sendfile_read, 4, nread);
3865 outbuf = talloc_array(NULL, char, nread+4);
3867 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3868 (unsigned)(nread+4)));
3869 reply_readbraw_error(xconn);
3874 ret = read_file(fsp,outbuf+4,startpos,nread);
3875 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3884 _smb_setlen(outbuf,ret);
3885 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3886 int saved_errno = errno;
3888 * Try and give an error message saying what
3891 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3892 smbXsrv_connection_dbg(xconn),
3893 strerror(saved_errno)));
3894 errno = saved_errno;
3899 TALLOC_FREE(outbuf);
3902 /****************************************************************************
3903 Reply to a readbraw (core+ protocol).
3904 ****************************************************************************/
3906 void reply_readbraw(struct smb_request *req)
3908 connection_struct *conn = req->conn;
3909 struct smbXsrv_connection *xconn = req->xconn;
3910 ssize_t maxcount,mincount;
3914 struct lock_struct lock;
3918 START_PROFILE(SMBreadbraw);
3920 if (srv_is_signing_active(xconn) || req->encrypted) {
3921 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3922 "raw reads/writes are disallowed.");
3926 reply_readbraw_error(xconn);
3927 END_PROFILE(SMBreadbraw);
3931 if (xconn->smb1.echo_handler.trusted_fde) {
3932 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3933 "'async smb echo handler = yes'\n"));
3934 reply_readbraw_error(xconn);
3935 END_PROFILE(SMBreadbraw);
3940 * Special check if an oplock break has been issued
3941 * and the readraw request croses on the wire, we must
3942 * return a zero length response here.
3945 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3948 * We have to do a check_fsp by hand here, as
3949 * we must always return 4 zero bytes on error,
3955 conn != fsp->conn ||
3956 req->vuid != fsp->vuid ||
3957 fsp->fsp_flags.is_directory ||
3961 * fsp could be NULL here so use the value from the packet. JRA.
3963 DEBUG(3,("reply_readbraw: fnum %d not valid "
3965 (int)SVAL(req->vwv+0, 0)));
3966 reply_readbraw_error(xconn);
3967 END_PROFILE(SMBreadbraw);
3971 /* Do a "by hand" version of CHECK_READ. */
3972 if (!(fsp->fsp_flags.can_read ||
3973 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3974 (fsp->access_mask & FILE_EXECUTE)))) {
3975 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3976 (int)SVAL(req->vwv+0, 0)));
3977 reply_readbraw_error(xconn);
3978 END_PROFILE(SMBreadbraw);
3982 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3983 if(req->wct == 10) {
3985 * This is a large offset (64 bit) read.
3988 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3991 DEBUG(0,("reply_readbraw: negative 64 bit "
3992 "readraw offset (%.0f) !\n",
3993 (double)startpos ));
3994 reply_readbraw_error(xconn);
3995 END_PROFILE(SMBreadbraw);
4000 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4001 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4003 /* ensure we don't overrun the packet size */
4004 maxcount = MIN(65535,maxcount);
4006 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4007 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4010 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4011 reply_readbraw_error(xconn);
4012 END_PROFILE(SMBreadbraw);
4016 status = vfs_stat_fsp(fsp);
4017 if (NT_STATUS_IS_OK(status)) {
4018 size = fsp->fsp_name->st.st_ex_size;
4021 if (startpos >= size) {
4024 nread = MIN(maxcount,(size - startpos));
4027 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4028 if (nread < mincount)
4032 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4033 "min=%lu nread=%lu\n",
4034 fsp_fnum_dbg(fsp), (double)startpos,
4035 (unsigned long)maxcount,
4036 (unsigned long)mincount,
4037 (unsigned long)nread ) );
4039 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4041 DEBUG(5,("reply_readbraw finished\n"));
4043 END_PROFILE(SMBreadbraw);
4048 #define DBGC_CLASS DBGC_LOCKING
4050 /****************************************************************************
4051 Reply to a lockread (core+ protocol).
4052 ****************************************************************************/
4054 static void reply_lockread_locked(struct tevent_req *subreq);
4056 void reply_lockread(struct smb_request *req)
4058 struct tevent_req *subreq = NULL;
4059 connection_struct *conn = req->conn;
4061 struct smbd_lock_element *lck = NULL;
4063 START_PROFILE(SMBlockread);
4066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4067 END_PROFILE(SMBlockread);
4071 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4073 if (!check_fsp(conn, req, fsp)) {
4074 END_PROFILE(SMBlockread);
4078 if (!CHECK_READ(fsp,req)) {
4079 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4080 END_PROFILE(SMBlockread);
4084 lck = talloc(req, struct smbd_lock_element);
4086 reply_nterror(req, NT_STATUS_NO_MEMORY);
4087 END_PROFILE(SMBlockread);
4092 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4093 * protocol request that predates the read/write lock concept.
4094 * Thus instead of asking for a read lock here we need to ask
4095 * for a write lock. JRA.
4096 * Note that the requested lock size is unaffected by max_send.
4099 *lck = (struct smbd_lock_element) {
4100 .req_guid = smbd_request_guid(req, 0),
4101 .smblctx = req->smbpid,
4102 .brltype = WRITE_LOCK,
4103 .count = SVAL(req->vwv+1, 0),
4104 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4107 subreq = smbd_smb1_do_locks_send(
4113 false, /* large_offset */
4117 if (subreq == NULL) {
4118 reply_nterror(req, NT_STATUS_NO_MEMORY);
4119 END_PROFILE(SMBlockread);
4122 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4123 END_PROFILE(SMBlockread);
4126 static void reply_lockread_locked(struct tevent_req *subreq)
4128 struct smb_request *req = NULL;
4134 size_t numtoread, maxtoread;
4135 struct files_struct *fsp = NULL;
4138 START_PROFILE(SMBlockread);
4140 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4143 status = smbd_smb1_do_locks_recv(subreq);
4144 TALLOC_FREE(subreq);
4146 if (!NT_STATUS_IS_OK(status)) {
4147 reply_nterror(req, status);
4151 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4153 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4157 numtoread = SVAL(req->vwv+1, 0);
4158 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4161 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4163 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4165 if (numtoread > maxtoread) {
4166 DBG_WARNING("requested read size (%zu) is greater than "
4167 "maximum allowed (%zu/%d). "
4168 "Returning short read of maximum allowed for "
4169 "compatibility with Windows 2000.\n",
4172 req->xconn->smb1.sessions.max_send);
4173 numtoread = maxtoread;
4176 reply_outbuf(req, 5, numtoread + 3);
4178 data = smb_buf(req->outbuf) + 3;
4180 nread = read_file(fsp,data,startpos,numtoread);
4183 reply_nterror(req, map_nt_error_from_unix(errno));
4187 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4189 SSVAL(req->outbuf,smb_vwv0,nread);
4190 SSVAL(req->outbuf,smb_vwv5,nread+3);
4191 p = smb_buf(req->outbuf);
4192 SCVAL(p,0,0); /* pad byte. */
4195 DEBUG(3,("lockread %s num=%d nread=%d\n",
4196 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4199 ok = srv_send_smb(req->xconn,
4200 (char *)req->outbuf,
4203 IS_CONN_ENCRYPTED(req->conn),
4206 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4209 END_PROFILE(SMBlockread);
4214 #define DBGC_CLASS DBGC_ALL
4216 /****************************************************************************
4218 ****************************************************************************/
4220 void reply_read(struct smb_request *req)
4222 connection_struct *conn = req->conn;
4229 struct lock_struct lock;
4230 struct smbXsrv_connection *xconn = req->xconn;
4232 START_PROFILE(SMBread);
4235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4236 END_PROFILE(SMBread);
4240 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4242 if (!check_fsp(conn, req, fsp)) {
4243 END_PROFILE(SMBread);
4247 if (!CHECK_READ(fsp,req)) {
4248 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4249 END_PROFILE(SMBread);
4253 numtoread = SVAL(req->vwv+1, 0);
4254 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4257 * The requested read size cannot be greater than max_send. JRA.
4259 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4261 if (numtoread > maxtoread) {
4262 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4263 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4264 (unsigned int)numtoread, (unsigned int)maxtoread,
4265 (unsigned int)xconn->smb1.sessions.max_send));
4266 numtoread = maxtoread;
4269 reply_outbuf(req, 5, numtoread+3);
4271 data = smb_buf(req->outbuf) + 3;
4273 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4274 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4277 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4278 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4279 END_PROFILE(SMBread);
4284 nread = read_file(fsp,data,startpos,numtoread);
4287 reply_nterror(req, map_nt_error_from_unix(errno));
4291 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4293 SSVAL(req->outbuf,smb_vwv0,nread);
4294 SSVAL(req->outbuf,smb_vwv5,nread+3);
4295 SCVAL(smb_buf(req->outbuf),0,1);
4296 SSVAL(smb_buf(req->outbuf),1,nread);
4298 DEBUG(3, ("read %s num=%d nread=%d\n",
4299 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4302 END_PROFILE(SMBread);
4306 /****************************************************************************
4308 ****************************************************************************/
4310 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4314 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4317 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4319 SCVAL(outbuf,smb_vwv0,0xFF);
4320 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4321 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4322 SSVAL(outbuf,smb_vwv6,
4323 (smb_wct - 4) /* offset from smb header to wct */
4324 + 1 /* the wct field */
4325 + 12 * sizeof(uint16_t) /* vwv */
4326 + 2 /* the buflen field */
4327 + 1); /* padding byte */
4328 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4329 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4330 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4331 _smb_setlen_large(outbuf,
4332 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4336 /****************************************************************************
4337 Reply to a read and X - possibly using sendfile.
4338 ****************************************************************************/
4340 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4341 files_struct *fsp, off_t startpos,
4344 struct smbXsrv_connection *xconn = req->xconn;
4346 struct lock_struct lock;
4347 int saved_errno = 0;
4350 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4351 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4354 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4355 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4360 * We can only use sendfile on a non-chained packet
4361 * but we can use on a non-oplocked file. tridge proved this
4362 * on a train in Germany :-). JRA.
4365 if (!req_is_in_chain(req) &&
4367 (fsp->base_fsp == NULL) &&
4368 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4369 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4372 status = vfs_stat_fsp(fsp);
4373 if (!NT_STATUS_IS_OK(status)) {
4374 reply_nterror(req, status);
4378 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4379 (startpos > fsp->fsp_name->st.st_ex_size) ||
4380 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4382 * We already know that we would do a short read, so don't
4383 * try the sendfile() path.
4385 goto nosendfile_read;
4389 * Set up the packet header before send. We
4390 * assume here the sendfile will work (get the
4391 * correct amount of data).
4394 header = data_blob_const(headerbuf, sizeof(headerbuf));
4396 construct_reply_common_req(req, (char *)headerbuf);
4397 setup_readX_header((char *)headerbuf, smb_maxcnt);
4399 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4400 startpos, smb_maxcnt);
4402 saved_errno = errno;
4404 /* Returning ENOSYS means no data at all was sent.
4405 Do this as a normal read. */
4406 if (errno == ENOSYS) {
4411 * Special hack for broken Linux with no working sendfile. If we
4412 * return EINTR we sent the header but not the rest of the data.
4413 * Fake this up by doing read/write calls.
4416 if (errno == EINTR) {
4417 /* Ensure we don't do this again. */
4418 set_use_sendfile(SNUM(conn), False);
4419 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4420 nread = fake_sendfile(xconn, fsp, startpos,
4423 saved_errno = errno;
4424 DEBUG(0,("send_file_readX: "
4425 "fake_sendfile failed for "
4426 "file %s (%s) for client %s. "
4429 smbXsrv_connection_dbg(xconn),
4430 strerror(saved_errno)));
4431 errno = saved_errno;
4432 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4434 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4435 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4436 /* No outbuf here means successful sendfile. */
4440 DEBUG(0,("send_file_readX: sendfile failed for file "
4441 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4443 exit_server_cleanly("send_file_readX sendfile failed");
4444 } else if (nread == 0) {
4446 * Some sendfile implementations return 0 to indicate
4447 * that there was a short read, but nothing was
4448 * actually written to the socket. In this case,
4449 * fallback to the normal read path so the header gets
4450 * the correct byte count.
4452 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4453 "falling back to the normal read: %s\n",
4458 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4459 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4461 /* Deal with possible short send. */
4462 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4465 ret = sendfile_short_send(xconn, fsp, nread,
4466 sizeof(headerbuf), smb_maxcnt);
4469 r = "send_file_readX: sendfile_short_send failed";
4470 DEBUG(0,("%s for file %s (%s).\n",
4471 r, fsp_str_dbg(fsp), strerror(errno)));
4472 exit_server_cleanly(r);
4475 /* No outbuf here means successful sendfile. */
4476 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4477 SMB_PERFCOUNT_END(&req->pcd);
4483 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4484 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4487 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4488 (startpos > fsp->fsp_name->st.st_ex_size) ||
4489 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4491 * We already know that we would do a short
4492 * read, so don't try the sendfile() path.
4494 goto nosendfile_read;
4497 construct_reply_common_req(req, (char *)headerbuf);
4498 setup_readX_header((char *)headerbuf, smb_maxcnt);
4500 /* Send out the header. */
4501 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4503 if (ret != sizeof(headerbuf)) {
4504 saved_errno = errno;
4506 * Try and give an error message saying what
4509 DEBUG(0,("send_file_readX: write_data failed for file "
4510 "%s (%s) for client %s. Terminating\n",
4512 smbXsrv_connection_dbg(xconn),
4513 strerror(saved_errno)));
4514 errno = saved_errno;
4515 exit_server_cleanly("send_file_readX sendfile failed");
4517 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4519 saved_errno = errno;
4520 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4521 "%s (%s) for client %s. Terminating\n",
4523 smbXsrv_connection_dbg(xconn),
4524 strerror(saved_errno)));
4525 errno = saved_errno;
4526 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4533 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4534 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4535 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4537 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4538 startpos, smb_maxcnt);
4539 saved_errno = errno;
4542 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4546 setup_readX_header((char *)req->outbuf, nread);
4548 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4549 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4553 TALLOC_FREE(req->outbuf);
4557 /****************************************************************************
4558 Work out how much space we have for a read return.
4559 ****************************************************************************/
4561 static size_t calc_max_read_pdu(const struct smb_request *req)
4563 struct smbXsrv_connection *xconn = req->xconn;
4565 if (xconn->protocol < PROTOCOL_NT1) {
4566 return xconn->smb1.sessions.max_send;
4569 if (!lp_large_readwrite()) {
4570 return xconn->smb1.sessions.max_send;
4573 if (req_is_in_chain(req)) {
4574 return xconn->smb1.sessions.max_send;
4577 if (req->encrypted) {
4579 * Don't take encrypted traffic up to the
4580 * limit. There are padding considerations
4581 * that make that tricky.
4583 return xconn->smb1.sessions.max_send;
4586 if (srv_is_signing_active(xconn)) {
4590 if (!lp_unix_extensions()) {
4595 * We can do ultra-large POSIX reads.
4600 /****************************************************************************
4601 Calculate how big a read can be. Copes with all clients. It's always
4602 safe to return a short read - Windows does this.
4603 ****************************************************************************/
4605 static size_t calc_read_size(const struct smb_request *req,
4609 struct smbXsrv_connection *xconn = req->xconn;
4610 size_t max_pdu = calc_max_read_pdu(req);
4611 size_t total_size = 0;
4612 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4613 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4616 * Windows explicitly ignores upper size of 0xFFFF.
4617 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4618 * We must do the same as these will never fit even in
4619 * an extended size NetBIOS packet.
4621 if (upper_size == 0xFFFF) {
4625 if (xconn->protocol < PROTOCOL_NT1) {
4629 total_size = ((upper_size<<16) | lower_size);
4632 * LARGE_READX test shows it's always safe to return
4633 * a short read. Windows does so.
4635 return MIN(total_size, max_len);
4638 /****************************************************************************
4639 Reply to a read and X.
4640 ****************************************************************************/
4642 void reply_read_and_X(struct smb_request *req)
4644 connection_struct *conn = req->conn;
4649 bool big_readX = False;
4651 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4654 START_PROFILE(SMBreadX);
4656 if ((req->wct != 10) && (req->wct != 12)) {
4657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4661 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4662 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4663 smb_maxcnt = SVAL(req->vwv+5, 0);
4665 /* If it's an IPC, pass off the pipe handler. */
4667 reply_pipe_read_and_X(req);
4668 END_PROFILE(SMBreadX);
4672 if (!check_fsp(conn, req, fsp)) {
4673 END_PROFILE(SMBreadX);
4677 if (!CHECK_READ(fsp,req)) {
4678 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4679 END_PROFILE(SMBreadX);
4683 upper_size = SVAL(req->vwv+7, 0);
4684 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4685 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4687 * This is a heuristic to avoid keeping large
4688 * outgoing buffers around over long-lived aio
4694 if (req->wct == 12) {
4696 * This is a large offset (64 bit) read.
4698 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4703 NTSTATUS status = schedule_aio_read_and_X(conn,
4708 if (NT_STATUS_IS_OK(status)) {
4709 /* Read scheduled - we're done. */
4712 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4713 /* Real error - report to client. */
4714 END_PROFILE(SMBreadX);
4715 reply_nterror(req, status);
4718 /* NT_STATUS_RETRY - fall back to sync read. */
4721 smbd_lock_socket(req->xconn);
4722 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4723 smbd_unlock_socket(req->xconn);
4726 END_PROFILE(SMBreadX);
4730 /****************************************************************************
4731 Error replies to writebraw must have smb_wct == 1. Fix this up.
4732 ****************************************************************************/
4734 void error_to_writebrawerr(struct smb_request *req)
4736 uint8_t *old_outbuf = req->outbuf;
4738 reply_outbuf(req, 1, 0);
4740 memcpy(req->outbuf, old_outbuf, smb_size);
4741 TALLOC_FREE(old_outbuf);
4744 /****************************************************************************
4745 Read 4 bytes of a smb packet and return the smb length of the packet.
4746 Store the result in the buffer. This version of the function will
4747 never return a session keepalive (length of zero).
4748 Timeout is in milliseconds.
4749 ****************************************************************************/
4751 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4754 uint8_t msgtype = NBSSkeepalive;
4756 while (msgtype == NBSSkeepalive) {
4759 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4761 if (!NT_STATUS_IS_OK(status)) {
4762 char addr[INET6_ADDRSTRLEN];
4763 /* Try and give an error message
4764 * saying what client failed. */
4765 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4766 "client %s read error = %s.\n",
4767 get_peer_addr(fd,addr,sizeof(addr)),
4768 nt_errstr(status)));
4772 msgtype = CVAL(inbuf, 0);
4775 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4776 (unsigned long)len));
4778 return NT_STATUS_OK;
4781 /****************************************************************************
4782 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4783 ****************************************************************************/
4785 void reply_writebraw(struct smb_request *req)
4787 connection_struct *conn = req->conn;
4788 struct smbXsrv_connection *xconn = req->xconn;
4791 ssize_t total_written=0;
4792 size_t numtowrite=0;
4795 const char *data=NULL;
4798 struct lock_struct lock;
4801 START_PROFILE(SMBwritebraw);
4804 * If we ever reply with an error, it must have the SMB command
4805 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4808 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4810 if (srv_is_signing_active(xconn)) {
4811 END_PROFILE(SMBwritebraw);
4812 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4813 "raw reads/writes are disallowed.");
4816 if (req->wct < 12) {
4817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4818 error_to_writebrawerr(req);
4819 END_PROFILE(SMBwritebraw);
4823 if (xconn->smb1.echo_handler.trusted_fde) {
4824 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4825 "'async smb echo handler = yes'\n"));
4826 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4827 error_to_writebrawerr(req);
4828 END_PROFILE(SMBwritebraw);
4832 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4833 if (!check_fsp(conn, req, fsp)) {
4834 error_to_writebrawerr(req);
4835 END_PROFILE(SMBwritebraw);
4839 if (!CHECK_WRITE(fsp)) {
4840 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4841 error_to_writebrawerr(req);
4842 END_PROFILE(SMBwritebraw);
4846 tcount = IVAL(req->vwv+1, 0);
4847 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4848 write_through = BITSETW(req->vwv+7,0);
4850 /* We have to deal with slightly different formats depending
4851 on whether we are using the core+ or lanman1.0 protocol */
4853 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4854 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4855 data = smb_buf_const(req->inbuf);
4857 numtowrite = SVAL(req->vwv+10, 0);
4858 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4861 /* Ensure we don't write bytes past the end of this packet. */
4863 * This already protects us against CVE-2017-12163.
4865 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4866 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4867 error_to_writebrawerr(req);
4868 END_PROFILE(SMBwritebraw);
4872 if (!fsp->print_file) {
4873 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4874 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4877 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4878 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4879 error_to_writebrawerr(req);
4880 END_PROFILE(SMBwritebraw);
4886 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4889 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4890 "wrote=%d sync=%d\n",
4891 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4892 (int)nwritten, (int)write_through));
4894 if (nwritten < (ssize_t)numtowrite) {
4895 reply_nterror(req, NT_STATUS_DISK_FULL);
4896 error_to_writebrawerr(req);
4900 total_written = nwritten;
4902 /* Allocate a buffer of 64k + length. */
4903 buf = talloc_array(NULL, char, 65540);
4905 reply_nterror(req, NT_STATUS_NO_MEMORY);
4906 error_to_writebrawerr(req);
4910 /* Return a SMBwritebraw message to the redirector to tell
4911 * it to send more bytes */
4913 memcpy(buf, req->inbuf, smb_size);
4914 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4915 SCVAL(buf,smb_com,SMBwritebraw);
4916 SSVALS(buf,smb_vwv0,0xFFFF);
4918 if (!srv_send_smb(req->xconn,
4920 false, 0, /* no signing */
4921 IS_CONN_ENCRYPTED(conn),
4923 exit_server_cleanly("reply_writebraw: srv_send_smb "
4927 /* Now read the raw data into the buffer and write it */
4928 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4930 if (!NT_STATUS_IS_OK(status)) {
4931 exit_server_cleanly("secondary writebraw failed");
4934 /* Set up outbuf to return the correct size */
4935 reply_outbuf(req, 1, 0);
4937 if (numtowrite != 0) {
4939 if (numtowrite > 0xFFFF) {
4940 DEBUG(0,("reply_writebraw: Oversize secondary write "
4941 "raw requested (%u). Terminating\n",
4942 (unsigned int)numtowrite ));
4943 exit_server_cleanly("secondary writebraw failed");
4946 if (tcount > nwritten+numtowrite) {
4947 DEBUG(3,("reply_writebraw: Client overestimated the "
4949 (int)tcount,(int)nwritten,(int)numtowrite));
4952 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4955 if (!NT_STATUS_IS_OK(status)) {
4956 /* Try and give an error message
4957 * saying what client failed. */
4958 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4959 "raw read failed (%s) for client %s. "
4960 "Terminating\n", nt_errstr(status),
4961 smbXsrv_connection_dbg(xconn)));
4962 exit_server_cleanly("secondary writebraw failed");
4966 * We are not vulnerable to CVE-2017-12163
4967 * here as we are guaranteed to have numtowrite
4968 * bytes available - we just read from the client.
4970 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4971 if (nwritten == -1) {
4973 reply_nterror(req, map_nt_error_from_unix(errno));
4974 error_to_writebrawerr(req);
4978 if (nwritten < (ssize_t)numtowrite) {
4979 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4980 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4984 total_written += nwritten;
4989 SSVAL(req->outbuf,smb_vwv0,total_written);
4991 status = sync_file(conn, fsp, write_through);
4992 if (!NT_STATUS_IS_OK(status)) {
4993 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4994 fsp_str_dbg(fsp), nt_errstr(status)));
4995 reply_nterror(req, status);
4996 error_to_writebrawerr(req);
5000 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5002 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5003 (int)total_written));
5005 /* We won't return a status if write through is not selected - this
5006 * follows what WfWg does */
5007 END_PROFILE(SMBwritebraw);
5009 if (!write_through && total_written==tcount) {
5011 #if RABBIT_PELLET_FIX
5013 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5014 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5017 if (!send_keepalive(xconn->transport.sock)) {
5018 exit_server_cleanly("reply_writebraw: send of "
5019 "keepalive failed");
5022 TALLOC_FREE(req->outbuf);
5027 END_PROFILE(SMBwritebraw);
5032 #define DBGC_CLASS DBGC_LOCKING
5034 /****************************************************************************
5035 Reply to a writeunlock (core+).
5036 ****************************************************************************/
5038 void reply_writeunlock(struct smb_request *req)
5040 connection_struct *conn = req->conn;
5041 ssize_t nwritten = -1;
5046 NTSTATUS status = NT_STATUS_OK;
5048 struct lock_struct lock;
5049 int saved_errno = 0;
5051 START_PROFILE(SMBwriteunlock);
5054 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5055 END_PROFILE(SMBwriteunlock);
5059 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5061 if (!check_fsp(conn, req, fsp)) {
5062 END_PROFILE(SMBwriteunlock);
5066 if (!CHECK_WRITE(fsp)) {
5067 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5068 END_PROFILE(SMBwriteunlock);
5072 numtowrite = SVAL(req->vwv+1, 0);
5073 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5074 data = (const char *)req->buf + 3;
5077 * Ensure client isn't asking us to write more than
5078 * they sent. CVE-2017-12163.
5080 remaining = smbreq_bufrem(req, data);
5081 if (numtowrite > remaining) {
5082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5083 END_PROFILE(SMBwriteunlock);
5087 if (!fsp->print_file && numtowrite > 0) {
5088 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5089 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5092 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5093 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5094 END_PROFILE(SMBwriteunlock);
5099 /* The special X/Open SMB protocol handling of
5100 zero length writes is *NOT* done for
5102 if(numtowrite == 0) {
5105 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5106 saved_errno = errno;
5109 status = sync_file(conn, fsp, False /* write through */);
5110 if (!NT_STATUS_IS_OK(status)) {
5111 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5112 fsp_str_dbg(fsp), nt_errstr(status)));
5113 reply_nterror(req, status);
5118 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5122 if((nwritten < numtowrite) && (numtowrite != 0)) {
5123 reply_nterror(req, NT_STATUS_DISK_FULL);
5127 if (numtowrite && !fsp->print_file) {
5128 struct smbd_lock_element l = {
5129 .req_guid = smbd_request_guid(req, 0),
5130 .smblctx = req->smbpid,
5131 .brltype = UNLOCK_LOCK,
5133 .count = numtowrite,
5135 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5136 if (NT_STATUS_V(status)) {
5137 reply_nterror(req, status);
5142 reply_outbuf(req, 1, 0);
5144 SSVAL(req->outbuf,smb_vwv0,nwritten);
5146 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5147 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5150 END_PROFILE(SMBwriteunlock);
5155 #define DBGC_CLASS DBGC_ALL
5157 /****************************************************************************
5159 ****************************************************************************/
5161 void reply_write(struct smb_request *req)
5163 connection_struct *conn = req->conn;
5166 ssize_t nwritten = -1;
5170 struct lock_struct lock;
5172 int saved_errno = 0;
5174 START_PROFILE(SMBwrite);
5177 END_PROFILE(SMBwrite);
5178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5182 /* If it's an IPC, pass off the pipe handler. */
5184 reply_pipe_write(req);
5185 END_PROFILE(SMBwrite);
5189 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5191 if (!check_fsp(conn, req, fsp)) {
5192 END_PROFILE(SMBwrite);
5196 if (!CHECK_WRITE(fsp)) {
5197 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5198 END_PROFILE(SMBwrite);
5202 numtowrite = SVAL(req->vwv+1, 0);
5203 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5204 data = (const char *)req->buf + 3;
5207 * Ensure client isn't asking us to write more than
5208 * they sent. CVE-2017-12163.
5210 remaining = smbreq_bufrem(req, data);
5211 if (numtowrite > remaining) {
5212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5213 END_PROFILE(SMBwrite);
5217 if (!fsp->print_file) {
5218 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5219 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5222 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5223 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5224 END_PROFILE(SMBwrite);
5230 * X/Open SMB protocol says that if smb_vwv1 is
5231 * zero then the file size should be extended or
5232 * truncated to the size given in smb_vwv[2-3].
5235 if(numtowrite == 0) {
5237 * This is actually an allocate call, and set EOF. JRA.
5239 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5241 reply_nterror(req, NT_STATUS_DISK_FULL);
5244 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5246 reply_nterror(req, NT_STATUS_DISK_FULL);
5249 trigger_write_time_update_immediate(fsp);
5251 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5254 status = sync_file(conn, fsp, False);
5255 if (!NT_STATUS_IS_OK(status)) {
5256 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5257 fsp_str_dbg(fsp), nt_errstr(status)));
5258 reply_nterror(req, status);
5263 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5267 if((nwritten == 0) && (numtowrite != 0)) {
5268 reply_nterror(req, NT_STATUS_DISK_FULL);
5272 reply_outbuf(req, 1, 0);
5274 SSVAL(req->outbuf,smb_vwv0,nwritten);
5276 if (nwritten < (ssize_t)numtowrite) {
5277 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5278 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5281 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5284 END_PROFILE(SMBwrite);
5288 /****************************************************************************
5289 Ensure a buffer is a valid writeX for recvfile purposes.
5290 ****************************************************************************/
5292 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5293 (2*14) + /* word count (including bcc) */ \
5296 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5297 const uint8_t *inbuf)
5300 unsigned int doff = 0;
5301 size_t len = smb_len_large(inbuf);
5303 struct smbXsrv_open *op = NULL;
5304 struct files_struct *fsp = NULL;
5307 if (is_encrypted_packet(inbuf)) {
5308 /* Can't do this on encrypted
5313 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5317 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5318 CVAL(inbuf,smb_wct) != 14) {
5319 DEBUG(10,("is_valid_writeX_buffer: chained or "
5320 "invalid word length.\n"));
5324 fnum = SVAL(inbuf, smb_vwv2);
5325 status = smb1srv_open_lookup(xconn,
5329 if (!NT_STATUS_IS_OK(status)) {
5330 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5335 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5338 if (fsp->conn == NULL) {
5339 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5343 if (IS_IPC(fsp->conn)) {
5344 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5347 if (IS_PRINT(fsp->conn)) {
5348 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5351 if (fsp->base_fsp != NULL) {
5352 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5355 doff = SVAL(inbuf,smb_vwv11);
5357 numtowrite = SVAL(inbuf,smb_vwv10);
5359 if (len > doff && len - doff > 0xFFFF) {
5360 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5363 if (numtowrite == 0) {
5364 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5368 /* Ensure the sizes match up. */
5369 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5370 /* no pad byte...old smbclient :-( */
5371 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5373 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5377 if (len - doff != numtowrite) {
5378 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5379 "len = %u, doff = %u, numtowrite = %u\n",
5382 (unsigned int)numtowrite ));
5386 DEBUG(10,("is_valid_writeX_buffer: true "
5387 "len = %u, doff = %u, numtowrite = %u\n",
5390 (unsigned int)numtowrite ));
5395 /****************************************************************************
5396 Reply to a write and X.
5397 ****************************************************************************/
5399 void reply_write_and_X(struct smb_request *req)
5401 connection_struct *conn = req->conn;
5402 struct smbXsrv_connection *xconn = req->xconn;
5404 struct lock_struct lock;
5409 unsigned int smb_doff;
5410 unsigned int smblen;
5413 int saved_errno = 0;
5415 START_PROFILE(SMBwriteX);
5417 if ((req->wct != 12) && (req->wct != 14)) {
5418 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5422 numtowrite = SVAL(req->vwv+10, 0);
5423 smb_doff = SVAL(req->vwv+11, 0);
5424 smblen = smb_len(req->inbuf);
5426 if (req->unread_bytes > 0xFFFF ||
5427 (smblen > smb_doff &&
5428 smblen - smb_doff > 0xFFFF)) {
5429 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5432 if (req->unread_bytes) {
5433 /* Can't do a recvfile write on IPC$ */
5435 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5438 if (numtowrite != req->unread_bytes) {
5439 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5444 * This already protects us against CVE-2017-12163.
5446 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5447 smb_doff + numtowrite > smblen) {
5448 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5453 /* If it's an IPC, pass off the pipe handler. */
5455 if (req->unread_bytes) {
5456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5459 reply_pipe_write_and_X(req);
5463 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5464 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5465 write_through = BITSETW(req->vwv+7,0);
5467 if (!check_fsp(conn, req, fsp)) {
5471 if (!CHECK_WRITE(fsp)) {
5472 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5476 data = smb_base(req->inbuf) + smb_doff;
5478 if(req->wct == 14) {
5480 * This is a large offset (64 bit) write.
5482 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5486 /* X/Open SMB protocol says that, unlike SMBwrite
5487 if the length is zero then NO truncation is
5488 done, just a write of zero. To truncate a file,
5491 if(numtowrite == 0) {
5494 if (req->unread_bytes == 0) {
5495 status = schedule_aio_write_and_X(conn,
5502 if (NT_STATUS_IS_OK(status)) {
5503 /* write scheduled - we're done. */
5506 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5507 /* Real error - report to client. */
5508 reply_nterror(req, status);
5511 /* NT_STATUS_RETRY - fall through to sync write. */
5514 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5515 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5518 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5519 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5523 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5524 saved_errno = errno;
5528 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5532 if((nwritten == 0) && (numtowrite != 0)) {
5533 reply_nterror(req, NT_STATUS_DISK_FULL);
5537 reply_outbuf(req, 6, 0);
5538 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5539 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5540 SSVAL(req->outbuf,smb_vwv2,nwritten);
5541 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5543 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5544 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5546 status = sync_file(conn, fsp, write_through);
5547 if (!NT_STATUS_IS_OK(status)) {
5548 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5549 fsp_str_dbg(fsp), nt_errstr(status)));
5550 reply_nterror(req, status);
5554 END_PROFILE(SMBwriteX);
5558 if (req->unread_bytes) {
5559 /* writeX failed. drain socket. */
5560 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5561 req->unread_bytes) {
5562 smb_panic("failed to drain pending bytes");
5564 req->unread_bytes = 0;
5567 END_PROFILE(SMBwriteX);
5571 /****************************************************************************
5573 ****************************************************************************/
5575 void reply_lseek(struct smb_request *req)
5577 connection_struct *conn = req->conn;
5584 START_PROFILE(SMBlseek);
5587 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5588 END_PROFILE(SMBlseek);
5592 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5594 if (!check_fsp(conn, req, fsp)) {
5598 mode = SVAL(req->vwv+1, 0) & 3;
5599 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5600 startpos = (off_t)IVALS(req->vwv+2, 0);
5609 res = fsp->fh->pos + startpos;
5620 if (umode == SEEK_END) {
5621 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5622 if(errno == EINVAL) {
5623 off_t current_pos = startpos;
5625 status = vfs_stat_fsp(fsp);
5626 if (!NT_STATUS_IS_OK(status)) {
5627 reply_nterror(req, status);
5628 END_PROFILE(SMBlseek);
5632 current_pos += fsp->fsp_name->st.st_ex_size;
5634 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5639 reply_nterror(req, map_nt_error_from_unix(errno));
5640 END_PROFILE(SMBlseek);
5647 reply_outbuf(req, 2, 0);
5648 SIVAL(req->outbuf,smb_vwv0,res);
5650 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5651 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5653 END_PROFILE(SMBlseek);
5657 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5660 connection_struct *conn = talloc_get_type_abort(
5661 private_data, connection_struct);
5663 if (conn != fsp->conn) {
5666 if (fsp->fh->fd == -1) {
5669 sync_file(conn, fsp, True /* write through */);
5671 if (fsp->fsp_flags.modified) {
5672 trigger_write_time_update_immediate(fsp);
5678 /****************************************************************************
5680 ****************************************************************************/
5682 void reply_flush(struct smb_request *req)
5684 connection_struct *conn = req->conn;
5688 START_PROFILE(SMBflush);
5691 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5695 fnum = SVAL(req->vwv+0, 0);
5696 fsp = file_fsp(req, fnum);
5698 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5703 files_forall(req->sconn, file_sync_one_fn, conn);
5705 NTSTATUS status = sync_file(conn, fsp, True);
5706 if (!NT_STATUS_IS_OK(status)) {
5707 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5708 fsp_str_dbg(fsp), nt_errstr(status)));
5709 reply_nterror(req, status);
5710 END_PROFILE(SMBflush);
5713 if (fsp->fsp_flags.modified) {
5714 trigger_write_time_update_immediate(fsp);
5718 reply_outbuf(req, 0, 0);
5720 DEBUG(3,("flush\n"));
5721 END_PROFILE(SMBflush);
5725 /****************************************************************************
5727 conn POINTER CAN BE NULL HERE !
5728 ****************************************************************************/
5730 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5731 static void reply_exit_done(struct tevent_req *req);
5733 void reply_exit(struct smb_request *smb1req)
5735 struct tevent_req *req;
5738 * Don't setup the profile charge here, take
5739 * it in reply_exit_done(). Not strictly correct
5740 * but better than the other SMB1 async
5741 * code that double-charges at the moment.
5743 req = reply_exit_send(smb1req);
5745 /* Not going async, profile here. */
5746 START_PROFILE(SMBexit);
5747 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5748 END_PROFILE(SMBexit);
5752 /* We're async. This will complete later. */
5753 tevent_req_set_callback(req, reply_exit_done, smb1req);
5757 struct reply_exit_state {
5758 struct tevent_queue *wait_queue;
5761 static void reply_exit_wait_done(struct tevent_req *subreq);
5763 /****************************************************************************
5765 Note, on failure here we deallocate and return NULL to allow the caller to
5766 SMB1 return an error of ERRnomem immediately.
5767 ****************************************************************************/
5769 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5771 struct tevent_req *req;
5772 struct reply_exit_state *state;
5773 struct tevent_req *subreq;
5775 struct smbd_server_connection *sconn = smb1req->sconn;
5777 req = tevent_req_create(smb1req, &state,
5778 struct reply_exit_state);
5782 state->wait_queue = tevent_queue_create(state,
5783 "reply_exit_wait_queue");
5784 if (tevent_req_nomem(state->wait_queue, req)) {
5789 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5790 if (fsp->file_pid != smb1req->smbpid) {
5793 if (fsp->vuid != smb1req->vuid) {
5797 * Flag the file as close in progress.
5798 * This will prevent any more IO being
5801 fsp->fsp_flags.closing = true;
5803 if (fsp->num_aio_requests > 0) {
5805 * Now wait until all aio requests on this fsp are
5808 * We don't set a callback, as we just want to block the
5809 * wait queue and the talloc_free() of fsp->aio_request
5810 * will remove the item from the wait queue.
5812 subreq = tevent_queue_wait_send(fsp->aio_requests,
5815 if (tevent_req_nomem(subreq, req)) {
5823 * Now we add our own waiter to the end of the queue,
5824 * this way we get notified when all pending requests are finished
5825 * and reply to the outstanding SMB1 request.
5827 subreq = tevent_queue_wait_send(state,
5830 if (tevent_req_nomem(subreq, req)) {
5836 * We're really going async - move the SMB1 request from
5837 * a talloc stackframe above us to the conn talloc-context.
5838 * We need this to stick around until the wait_done
5839 * callback is invoked.
5841 smb1req = talloc_move(sconn, &smb1req);
5843 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5848 static void reply_exit_wait_done(struct tevent_req *subreq)
5850 struct tevent_req *req = tevent_req_callback_data(
5851 subreq, struct tevent_req);
5853 tevent_queue_wait_recv(subreq);
5854 TALLOC_FREE(subreq);
5855 tevent_req_done(req);
5858 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5860 return tevent_req_simple_recv_ntstatus(req);
5863 static void reply_exit_done(struct tevent_req *req)
5865 struct smb_request *smb1req = tevent_req_callback_data(
5866 req, struct smb_request);
5867 struct smbd_server_connection *sconn = smb1req->sconn;
5868 struct smbXsrv_connection *xconn = smb1req->xconn;
5869 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5870 struct smbXsrv_session *session = NULL;
5871 files_struct *fsp, *next;
5875 * Take the profile charge here. Not strictly
5876 * correct but better than the other SMB1 async
5877 * code that double-charges at the moment.
5879 START_PROFILE(SMBexit);
5881 status = reply_exit_recv(req);
5883 if (!NT_STATUS_IS_OK(status)) {
5884 TALLOC_FREE(smb1req);
5885 END_PROFILE(SMBexit);
5886 exit_server(__location__ ": reply_exit_recv failed");
5891 * Ensure the session is still valid.
5893 status = smb1srv_session_lookup(xconn,
5897 if (!NT_STATUS_IS_OK(status)) {
5898 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5899 smb_request_done(smb1req);
5900 END_PROFILE(SMBexit);
5904 * Ensure the vuid is still valid - no one
5905 * called reply_ulogoffX() in the meantime.
5906 * reply_exit() doesn't have AS_USER set, so
5907 * use set_current_user_info() directly.
5908 * This is the same logic as in switch_message().
5910 if (session->global->auth_session_info != NULL) {
5911 set_current_user_info(
5912 session->global->auth_session_info->unix_info->sanitized_username,
5913 session->global->auth_session_info->unix_info->unix_name,
5914 session->global->auth_session_info->info->domain_name);
5917 /* No more aio - do the actual closes. */
5918 for (fsp = sconn->files; fsp; fsp = next) {
5922 if (fsp->file_pid != smb1req->smbpid) {
5925 if (fsp->vuid != smb1req->vuid) {
5928 if (!fsp->fsp_flags.closing) {
5933 * reply_exit() has the DO_CHDIR flag set.
5935 ok = chdir_current_service(fsp->conn);
5937 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5938 smb_request_done(smb1req);
5939 END_PROFILE(SMBexit);
5941 close_file(NULL, fsp, SHUTDOWN_CLOSE);
5944 reply_outbuf(smb1req, 0, 0);
5946 * The following call is needed to push the
5947 * reply data back out the socket after async
5948 * return. Plus it frees smb1req.
5950 smb_request_done(smb1req);
5951 DBG_INFO("reply_exit complete\n");
5952 END_PROFILE(SMBexit);
5956 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5958 static void reply_close_done(struct tevent_req *req);
5960 void reply_close(struct smb_request *smb1req)
5962 connection_struct *conn = smb1req->conn;
5963 NTSTATUS status = NT_STATUS_OK;
5964 files_struct *fsp = NULL;
5965 START_PROFILE(SMBclose);
5967 if (smb1req->wct < 3) {
5968 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5969 END_PROFILE(SMBclose);
5973 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5976 * We can only use check_fsp if we know it's not a directory.
5979 if (!check_fsp_open(conn, smb1req, fsp)) {
5980 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
5981 END_PROFILE(SMBclose);
5985 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5986 fsp->fsp_flags.is_directory ?
5987 "directory" : "file",
5988 fsp->fh->fd, fsp_fnum_dbg(fsp),
5989 conn->num_files_open);
5991 if (!fsp->fsp_flags.is_directory) {
5995 * Take care of any time sent in the close.
5998 t = srv_make_unix_date3(smb1req->vwv+1);
5999 set_close_write_time(fsp, time_t_to_full_timespec(t));
6002 if (fsp->num_aio_requests != 0) {
6003 struct tevent_req *req;
6005 req = reply_close_send(smb1req, fsp);
6007 status = NT_STATUS_NO_MEMORY;
6010 /* We're async. This will complete later. */
6011 tevent_req_set_callback(req, reply_close_done, smb1req);
6012 END_PROFILE(SMBclose);
6017 * close_file() returns the unix errno if an error was detected on
6018 * close - normally this is due to a disk full error. If not then it
6019 * was probably an I/O error.
6022 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6024 if (!NT_STATUS_IS_OK(status)) {
6025 reply_nterror(smb1req, status);
6026 END_PROFILE(SMBclose);
6030 reply_outbuf(smb1req, 0, 0);
6031 END_PROFILE(SMBclose);
6035 struct reply_close_state {
6037 struct tevent_queue *wait_queue;
6040 static void reply_close_wait_done(struct tevent_req *subreq);
6042 /****************************************************************************
6044 Note, on failure here we deallocate and return NULL to allow the caller to
6045 SMB1 return an error of ERRnomem immediately.
6046 ****************************************************************************/
6048 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6051 struct tevent_req *req;
6052 struct reply_close_state *state;
6053 struct tevent_req *subreq;
6054 struct smbd_server_connection *sconn = smb1req->sconn;
6056 req = tevent_req_create(smb1req, &state,
6057 struct reply_close_state);
6061 state->wait_queue = tevent_queue_create(state,
6062 "reply_close_wait_queue");
6063 if (tevent_req_nomem(state->wait_queue, req)) {
6069 * Flag the file as close in progress.
6070 * This will prevent any more IO being
6073 fsp->fsp_flags.closing = true;
6076 * Now wait until all aio requests on this fsp are
6079 * We don't set a callback, as we just want to block the
6080 * wait queue and the talloc_free() of fsp->aio_request
6081 * will remove the item from the wait queue.
6083 subreq = tevent_queue_wait_send(fsp->aio_requests,
6086 if (tevent_req_nomem(subreq, req)) {
6092 * Now we add our own waiter to the end of the queue,
6093 * this way we get notified when all pending requests are finished
6094 * and reply to the outstanding SMB1 request.
6096 subreq = tevent_queue_wait_send(state,
6099 if (tevent_req_nomem(subreq, req)) {
6105 * We're really going async - move the SMB1 request from
6106 * a talloc stackframe above us to the conn talloc-context.
6107 * We need this to stick around until the wait_done
6108 * callback is invoked.
6110 smb1req = talloc_move(sconn, &smb1req);
6112 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6117 static void reply_close_wait_done(struct tevent_req *subreq)
6119 struct tevent_req *req = tevent_req_callback_data(
6120 subreq, struct tevent_req);
6122 tevent_queue_wait_recv(subreq);
6123 TALLOC_FREE(subreq);
6124 tevent_req_done(req);
6127 static NTSTATUS reply_close_recv(struct tevent_req *req)
6129 return tevent_req_simple_recv_ntstatus(req);
6132 static void reply_close_done(struct tevent_req *req)
6134 struct smb_request *smb1req = tevent_req_callback_data(
6135 req, struct smb_request);
6136 struct reply_close_state *state = tevent_req_data(req,
6137 struct reply_close_state);
6140 status = reply_close_recv(req);
6142 if (!NT_STATUS_IS_OK(status)) {
6143 TALLOC_FREE(smb1req);
6144 exit_server(__location__ ": reply_close_recv failed");
6148 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6149 if (NT_STATUS_IS_OK(status)) {
6150 reply_outbuf(smb1req, 0, 0);
6152 reply_nterror(smb1req, status);
6155 * The following call is needed to push the
6156 * reply data back out the socket after async
6157 * return. Plus it frees smb1req.
6159 smb_request_done(smb1req);
6162 /****************************************************************************
6163 Reply to a writeclose (Core+ protocol).
6164 ****************************************************************************/
6166 void reply_writeclose(struct smb_request *req)
6168 connection_struct *conn = req->conn;
6171 ssize_t nwritten = -1;
6172 NTSTATUS close_status = NT_STATUS_OK;
6175 struct timespec mtime;
6177 struct lock_struct lock;
6179 START_PROFILE(SMBwriteclose);
6182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6183 END_PROFILE(SMBwriteclose);
6187 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6189 if (!check_fsp(conn, req, fsp)) {
6190 END_PROFILE(SMBwriteclose);
6193 if (!CHECK_WRITE(fsp)) {
6194 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6195 END_PROFILE(SMBwriteclose);
6199 numtowrite = SVAL(req->vwv+1, 0);
6200 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6201 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6202 data = (const char *)req->buf + 1;
6205 * Ensure client isn't asking us to write more than
6206 * they sent. CVE-2017-12163.
6208 remaining = smbreq_bufrem(req, data);
6209 if (numtowrite > remaining) {
6210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6211 END_PROFILE(SMBwriteclose);
6215 if (fsp->print_file == NULL) {
6216 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6217 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6220 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6221 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6222 END_PROFILE(SMBwriteclose);
6227 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6229 set_close_write_time(fsp, mtime);
6232 * More insanity. W2K only closes the file if writelen > 0.
6236 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6237 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6238 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6241 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6242 "file %s\n", fsp_str_dbg(fsp)));
6243 close_status = close_file(req, fsp, NORMAL_CLOSE);
6247 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6248 reply_nterror(req, NT_STATUS_DISK_FULL);
6252 if(!NT_STATUS_IS_OK(close_status)) {
6253 reply_nterror(req, close_status);
6257 reply_outbuf(req, 1, 0);
6259 SSVAL(req->outbuf,smb_vwv0,nwritten);
6263 END_PROFILE(SMBwriteclose);
6268 #define DBGC_CLASS DBGC_LOCKING
6270 /****************************************************************************
6272 ****************************************************************************/
6274 static void reply_lock_done(struct tevent_req *subreq);
6276 void reply_lock(struct smb_request *req)
6278 struct tevent_req *subreq = NULL;
6279 connection_struct *conn = req->conn;
6281 struct smbd_lock_element *lck = NULL;
6283 START_PROFILE(SMBlock);
6286 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6287 END_PROFILE(SMBlock);
6291 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6293 if (!check_fsp(conn, req, fsp)) {
6294 END_PROFILE(SMBlock);
6298 lck = talloc(req, struct smbd_lock_element);
6300 reply_nterror(req, NT_STATUS_NO_MEMORY);
6301 END_PROFILE(SMBlock);
6305 *lck = (struct smbd_lock_element) {
6306 .req_guid = smbd_request_guid(req, 0),
6307 .smblctx = req->smbpid,
6308 .brltype = WRITE_LOCK,
6309 .count = IVAL(req->vwv+1, 0),
6310 .offset = IVAL(req->vwv+3, 0),
6313 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6319 subreq = smbd_smb1_do_locks_send(
6325 false, /* large_offset */
6329 if (subreq == NULL) {
6330 reply_nterror(req, NT_STATUS_NO_MEMORY);
6331 END_PROFILE(SMBlock);
6334 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6335 END_PROFILE(SMBlock);
6338 static void reply_lock_done(struct tevent_req *subreq)
6340 struct smb_request *req = NULL;
6344 START_PROFILE(SMBlock);
6346 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6349 status = smbd_smb1_do_locks_recv(subreq);
6350 TALLOC_FREE(subreq);
6352 if (NT_STATUS_IS_OK(status)) {
6353 reply_outbuf(req, 0, 0);
6355 reply_nterror(req, status);
6358 ok = srv_send_smb(req->xconn,
6359 (char *)req->outbuf,
6362 IS_CONN_ENCRYPTED(req->conn),
6365 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6368 END_PROFILE(SMBlock);
6371 /****************************************************************************
6373 ****************************************************************************/
6375 void reply_unlock(struct smb_request *req)
6377 connection_struct *conn = req->conn;
6380 struct smbd_lock_element lck;
6382 START_PROFILE(SMBunlock);
6385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6386 END_PROFILE(SMBunlock);
6390 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6392 if (!check_fsp(conn, req, fsp)) {
6393 END_PROFILE(SMBunlock);
6397 lck = (struct smbd_lock_element) {
6398 .req_guid = smbd_request_guid(req, 0),
6399 .smblctx = req->smbpid,
6400 .brltype = UNLOCK_LOCK,
6401 .offset = IVAL(req->vwv+3, 0),
6402 .count = IVAL(req->vwv+1, 0),
6405 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6407 if (!NT_STATUS_IS_OK(status)) {
6408 reply_nterror(req, status);
6409 END_PROFILE(SMBunlock);
6413 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6419 reply_outbuf(req, 0, 0);
6421 END_PROFILE(SMBunlock);
6426 #define DBGC_CLASS DBGC_ALL
6428 /****************************************************************************
6430 conn POINTER CAN BE NULL HERE !
6431 ****************************************************************************/
6433 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6434 static void reply_tdis_done(struct tevent_req *req);
6436 void reply_tdis(struct smb_request *smb1req)
6438 connection_struct *conn = smb1req->conn;
6439 struct tevent_req *req;
6442 * Don't setup the profile charge here, take
6443 * it in reply_tdis_done(). Not strictly correct
6444 * but better than the other SMB1 async
6445 * code that double-charges at the moment.
6449 /* Not going async, profile here. */
6450 START_PROFILE(SMBtdis);
6451 DBG_INFO("Invalid connection in tdis\n");
6452 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6453 END_PROFILE(SMBtdis);
6457 req = reply_tdis_send(smb1req);
6459 /* Not going async, profile here. */
6460 START_PROFILE(SMBtdis);
6461 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6462 END_PROFILE(SMBtdis);
6465 /* We're async. This will complete later. */
6466 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6470 struct reply_tdis_state {
6471 struct tevent_queue *wait_queue;
6474 static void reply_tdis_wait_done(struct tevent_req *subreq);
6476 /****************************************************************************
6478 Note, on failure here we deallocate and return NULL to allow the caller to
6479 SMB1 return an error of ERRnomem immediately.
6480 ****************************************************************************/
6482 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6484 struct tevent_req *req;
6485 struct reply_tdis_state *state;
6486 struct tevent_req *subreq;
6487 connection_struct *conn = smb1req->conn;
6490 req = tevent_req_create(smb1req, &state,
6491 struct reply_tdis_state);
6495 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6496 if (tevent_req_nomem(state->wait_queue, req)) {
6502 * Make sure that no new request will be able to use this tcon.
6503 * This ensures that once all outstanding fsp->aio_requests
6504 * on this tcon are done, we are safe to close it.
6506 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6508 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6509 if (fsp->conn != conn) {
6513 * Flag the file as close in progress.
6514 * This will prevent any more IO being
6515 * done on it. Not strictly needed, but
6516 * doesn't hurt to flag it as closing.
6518 fsp->fsp_flags.closing = true;
6520 if (fsp->num_aio_requests > 0) {
6522 * Now wait until all aio requests on this fsp are
6525 * We don't set a callback, as we just want to block the
6526 * wait queue and the talloc_free() of fsp->aio_request
6527 * will remove the item from the wait queue.
6529 subreq = tevent_queue_wait_send(fsp->aio_requests,
6530 conn->sconn->ev_ctx,
6532 if (tevent_req_nomem(subreq, req)) {
6540 * Now we add our own waiter to the end of the queue,
6541 * this way we get notified when all pending requests are finished
6542 * and reply to the outstanding SMB1 request.
6544 subreq = tevent_queue_wait_send(state,
6545 conn->sconn->ev_ctx,
6547 if (tevent_req_nomem(subreq, req)) {
6553 * We're really going async - move the SMB1 request from
6554 * a talloc stackframe above us to the sconn talloc-context.
6555 * We need this to stick around until the wait_done
6556 * callback is invoked.
6558 smb1req = talloc_move(smb1req->sconn, &smb1req);
6560 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6565 static void reply_tdis_wait_done(struct tevent_req *subreq)
6567 struct tevent_req *req = tevent_req_callback_data(
6568 subreq, struct tevent_req);
6570 tevent_queue_wait_recv(subreq);
6571 TALLOC_FREE(subreq);
6572 tevent_req_done(req);
6575 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6577 return tevent_req_simple_recv_ntstatus(req);
6580 static void reply_tdis_done(struct tevent_req *req)
6582 struct smb_request *smb1req = tevent_req_callback_data(
6583 req, struct smb_request);
6585 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6589 * Take the profile charge here. Not strictly
6590 * correct but better than the other SMB1 async
6591 * code that double-charges at the moment.
6593 START_PROFILE(SMBtdis);
6595 status = reply_tdis_recv(req);
6597 if (!NT_STATUS_IS_OK(status)) {
6598 TALLOC_FREE(smb1req);
6599 END_PROFILE(SMBtdis);
6600 exit_server(__location__ ": reply_tdis_recv failed");
6605 * As we've been awoken, we may have changed
6606 * directory in the meantime.
6607 * reply_tdis() has the DO_CHDIR flag set.
6609 ok = chdir_current_service(smb1req->conn);
6611 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6612 smb_request_done(smb1req);
6613 END_PROFILE(SMBtdis);
6616 status = smbXsrv_tcon_disconnect(tcon,
6618 if (!NT_STATUS_IS_OK(status)) {
6619 TALLOC_FREE(smb1req);
6620 END_PROFILE(SMBtdis);
6621 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6625 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6626 smb1req->conn = NULL;
6630 reply_outbuf(smb1req, 0, 0);
6632 * The following call is needed to push the
6633 * reply data back out the socket after async
6634 * return. Plus it frees smb1req.
6636 smb_request_done(smb1req);
6637 END_PROFILE(SMBtdis);
6640 /****************************************************************************
6642 conn POINTER CAN BE NULL HERE !
6643 ****************************************************************************/
6645 void reply_echo(struct smb_request *req)
6647 connection_struct *conn = req->conn;
6648 struct smb_perfcount_data local_pcd;
6649 struct smb_perfcount_data *cur_pcd;
6653 START_PROFILE(SMBecho);
6655 smb_init_perfcount_data(&local_pcd);
6658 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6659 END_PROFILE(SMBecho);
6663 smb_reverb = SVAL(req->vwv+0, 0);
6665 reply_outbuf(req, 1, req->buflen);
6667 /* copy any incoming data back out */
6668 if (req->buflen > 0) {
6669 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6672 if (smb_reverb > 100) {
6673 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6677 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6679 /* this makes sure we catch the request pcd */
6680 if (seq_num == smb_reverb) {
6681 cur_pcd = &req->pcd;
6683 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6684 cur_pcd = &local_pcd;
6687 SSVAL(req->outbuf,smb_vwv0,seq_num);
6689 show_msg((char *)req->outbuf);
6690 if (!srv_send_smb(req->xconn,
6691 (char *)req->outbuf,
6692 true, req->seqnum+1,
6693 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6695 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6698 DEBUG(3,("echo %d times\n", smb_reverb));
6700 TALLOC_FREE(req->outbuf);
6702 END_PROFILE(SMBecho);
6706 /****************************************************************************
6707 Reply to a printopen.
6708 ****************************************************************************/
6710 void reply_printopen(struct smb_request *req)
6712 connection_struct *conn = req->conn;
6716 START_PROFILE(SMBsplopen);
6719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6720 END_PROFILE(SMBsplopen);
6724 if (!CAN_PRINT(conn)) {
6725 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6726 END_PROFILE(SMBsplopen);
6730 status = file_new(req, conn, &fsp);
6731 if(!NT_STATUS_IS_OK(status)) {
6732 reply_nterror(req, status);
6733 END_PROFILE(SMBsplopen);
6737 /* Open for exclusive use, write only. */
6738 status = print_spool_open(fsp, NULL, req->vuid);
6740 if (!NT_STATUS_IS_OK(status)) {
6741 file_free(req, fsp);
6742 reply_nterror(req, status);
6743 END_PROFILE(SMBsplopen);
6747 reply_outbuf(req, 1, 0);
6748 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6750 DEBUG(3,("openprint fd=%d %s\n",
6751 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6753 END_PROFILE(SMBsplopen);
6757 /****************************************************************************
6758 Reply to a printclose.
6759 ****************************************************************************/
6761 void reply_printclose(struct smb_request *req)
6763 connection_struct *conn = req->conn;
6767 START_PROFILE(SMBsplclose);
6770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6771 END_PROFILE(SMBsplclose);
6775 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6777 if (!check_fsp(conn, req, fsp)) {
6778 END_PROFILE(SMBsplclose);
6782 if (!CAN_PRINT(conn)) {
6783 reply_force_doserror(req, ERRSRV, ERRerror);
6784 END_PROFILE(SMBsplclose);
6788 DEBUG(3,("printclose fd=%d %s\n",
6789 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6791 status = close_file(req, fsp, NORMAL_CLOSE);
6793 if(!NT_STATUS_IS_OK(status)) {
6794 reply_nterror(req, status);
6795 END_PROFILE(SMBsplclose);
6799 reply_outbuf(req, 0, 0);
6801 END_PROFILE(SMBsplclose);
6805 /****************************************************************************
6806 Reply to a printqueue.
6807 ****************************************************************************/
6809 void reply_printqueue(struct smb_request *req)
6811 const struct loadparm_substitution *lp_sub =
6812 loadparm_s3_global_substitution();
6813 connection_struct *conn = req->conn;
6817 START_PROFILE(SMBsplretq);
6820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6821 END_PROFILE(SMBsplretq);
6825 max_count = SVAL(req->vwv+0, 0);
6826 start_index = SVAL(req->vwv+1, 0);
6828 /* we used to allow the client to get the cnum wrong, but that
6829 is really quite gross and only worked when there was only
6830 one printer - I think we should now only accept it if they
6831 get it right (tridge) */
6832 if (!CAN_PRINT(conn)) {
6833 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6834 END_PROFILE(SMBsplretq);
6838 reply_outbuf(req, 2, 3);
6839 SSVAL(req->outbuf,smb_vwv0,0);
6840 SSVAL(req->outbuf,smb_vwv1,0);
6841 SCVAL(smb_buf(req->outbuf),0,1);
6842 SSVAL(smb_buf(req->outbuf),1,0);
6844 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6845 start_index, max_count));
6848 TALLOC_CTX *mem_ctx = talloc_tos();
6851 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6852 struct rpc_pipe_client *cli = NULL;
6853 struct dcerpc_binding_handle *b = NULL;
6854 struct policy_handle handle;
6855 struct spoolss_DevmodeContainer devmode_ctr;
6856 union spoolss_JobInfo *info;
6858 uint32_t num_to_get;
6862 ZERO_STRUCT(handle);
6864 status = rpc_pipe_open_interface(mem_ctx,
6867 conn->sconn->remote_address,
6868 conn->sconn->local_address,
6869 conn->sconn->msg_ctx,
6871 if (!NT_STATUS_IS_OK(status)) {
6872 DEBUG(0, ("reply_printqueue: "
6873 "could not connect to spoolss: %s\n",
6874 nt_errstr(status)));
6875 reply_nterror(req, status);
6878 b = cli->binding_handle;
6880 ZERO_STRUCT(devmode_ctr);
6882 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6885 SEC_FLAG_MAXIMUM_ALLOWED,
6888 if (!NT_STATUS_IS_OK(status)) {
6889 reply_nterror(req, status);
6892 if (!W_ERROR_IS_OK(werr)) {
6893 reply_nterror(req, werror_to_ntstatus(werr));
6897 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6905 if (!W_ERROR_IS_OK(werr)) {
6906 reply_nterror(req, werror_to_ntstatus(werr));
6910 if (max_count > 0) {
6911 first = start_index;
6913 first = start_index + max_count + 1;
6916 if (first >= count) {
6919 num_to_get = first + MIN(ABS(max_count), count - first);
6922 for (i = first; i < num_to_get; i++) {
6925 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6928 uint16_t qrapjobid = pjobid_to_rap(sharename,
6929 info[i].info2.job_id);
6931 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6937 srv_put_dos_date2(p, 0, qtime);
6938 SCVAL(p, 4, qstatus);
6939 SSVAL(p, 5, qrapjobid);
6940 SIVAL(p, 7, info[i].info2.size);
6942 status = srvstr_push(blob, req->flags2, p+12,
6943 info[i].info2.notify_name, 16, STR_ASCII, &len);
6944 if (!NT_STATUS_IS_OK(status)) {
6945 reply_nterror(req, status);
6948 if (message_push_blob(
6951 blob, sizeof(blob))) == -1) {
6952 reply_nterror(req, NT_STATUS_NO_MEMORY);
6958 SSVAL(req->outbuf,smb_vwv0,count);
6959 SSVAL(req->outbuf,smb_vwv1,
6960 (max_count>0?first+count:first-1));
6961 SCVAL(smb_buf(req->outbuf),0,1);
6962 SSVAL(smb_buf(req->outbuf),1,28*count);
6966 DEBUG(3, ("%u entries returned in queue\n",
6970 if (b && is_valid_policy_hnd(&handle)) {
6971 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6976 END_PROFILE(SMBsplretq);
6980 /****************************************************************************
6981 Reply to a printwrite.
6982 ****************************************************************************/
6984 void reply_printwrite(struct smb_request *req)
6986 connection_struct *conn = req->conn;
6991 START_PROFILE(SMBsplwr);
6994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6995 END_PROFILE(SMBsplwr);
6999 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7001 if (!check_fsp(conn, req, fsp)) {
7002 END_PROFILE(SMBsplwr);
7006 if (!fsp->print_file) {
7007 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7008 END_PROFILE(SMBsplwr);
7012 if (!CHECK_WRITE(fsp)) {
7013 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7014 END_PROFILE(SMBsplwr);
7018 numtowrite = SVAL(req->buf, 1);
7021 * This already protects us against CVE-2017-12163.
7023 if (req->buflen < numtowrite + 3) {
7024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7025 END_PROFILE(SMBsplwr);
7029 data = (const char *)req->buf + 3;
7031 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7032 reply_nterror(req, map_nt_error_from_unix(errno));
7033 END_PROFILE(SMBsplwr);
7037 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7039 END_PROFILE(SMBsplwr);
7043 /****************************************************************************
7045 ****************************************************************************/
7047 void reply_mkdir(struct smb_request *req)
7049 connection_struct *conn = req->conn;
7050 struct smb_filename *smb_dname = NULL;
7051 char *directory = NULL;
7054 TALLOC_CTX *ctx = talloc_tos();
7056 START_PROFILE(SMBmkdir);
7058 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7059 STR_TERMINATE, &status);
7060 if (!NT_STATUS_IS_OK(status)) {
7061 reply_nterror(req, status);
7065 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7066 status = filename_convert(ctx, conn,
7071 if (!NT_STATUS_IS_OK(status)) {
7072 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7073 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7074 ERRSRV, ERRbadpath);
7077 reply_nterror(req, status);
7081 status = create_directory(conn, req, smb_dname);
7083 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7085 if (!NT_STATUS_IS_OK(status)) {
7087 if (!use_nt_status()
7088 && NT_STATUS_EQUAL(status,
7089 NT_STATUS_OBJECT_NAME_COLLISION)) {
7091 * Yes, in the DOS error code case we get a
7092 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7093 * samba4 torture test.
7095 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7098 reply_nterror(req, status);
7102 reply_outbuf(req, 0, 0);
7104 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7106 TALLOC_FREE(smb_dname);
7107 END_PROFILE(SMBmkdir);
7111 /****************************************************************************
7113 ****************************************************************************/
7115 void reply_rmdir(struct smb_request *req)
7117 connection_struct *conn = req->conn;
7118 struct smb_filename *smb_dname = NULL;
7119 char *directory = NULL;
7121 TALLOC_CTX *ctx = talloc_tos();
7122 files_struct *fsp = NULL;
7124 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7126 START_PROFILE(SMBrmdir);
7128 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7129 STR_TERMINATE, &status);
7130 if (!NT_STATUS_IS_OK(status)) {
7131 reply_nterror(req, status);
7135 status = filename_convert(ctx, conn,
7140 if (!NT_STATUS_IS_OK(status)) {
7141 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7142 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7143 ERRSRV, ERRbadpath);
7146 reply_nterror(req, status);
7150 if (is_ntfs_stream_smb_fname(smb_dname)) {
7151 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7155 status = SMB_VFS_CREATE_FILE(
7158 smb_dname, /* fname */
7159 DELETE_ACCESS, /* access_mask */
7160 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7162 FILE_OPEN, /* create_disposition*/
7163 FILE_DIRECTORY_FILE, /* create_options */
7164 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7165 0, /* oplock_request */
7167 0, /* allocation_size */
7168 0, /* private_flags */
7173 NULL, NULL); /* create context */
7175 if (!NT_STATUS_IS_OK(status)) {
7176 if (open_was_deferred(req->xconn, req->mid)) {
7177 /* We have re-scheduled this call. */
7180 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7181 bool ok = defer_smb1_sharing_violation(req);
7186 reply_nterror(req, status);
7190 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7191 if (!NT_STATUS_IS_OK(status)) {
7192 close_file(req, fsp, ERROR_CLOSE);
7193 reply_nterror(req, status);
7197 if (!set_delete_on_close(fsp, true,
7198 conn->session_info->security_token,
7199 conn->session_info->unix_token)) {
7200 close_file(req, fsp, ERROR_CLOSE);
7201 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7205 status = close_file(req, fsp, NORMAL_CLOSE);
7206 if (!NT_STATUS_IS_OK(status)) {
7207 reply_nterror(req, status);
7209 reply_outbuf(req, 0, 0);
7212 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7214 TALLOC_FREE(smb_dname);
7215 END_PROFILE(SMBrmdir);
7219 /*******************************************************************
7220 Resolve wildcards in a filename rename.
7221 ********************************************************************/
7223 static bool resolve_wildcards(TALLOC_CTX *ctx,
7228 char *name2_copy = NULL;
7233 char *p,*p2, *pname1, *pname2;
7235 name2_copy = talloc_strdup(ctx, name2);
7240 pname1 = strrchr_m(name1,'/');
7241 pname2 = strrchr_m(name2_copy,'/');
7243 if (!pname1 || !pname2) {
7247 /* Truncate the copy of name2 at the last '/' */
7250 /* Now go past the '/' */
7254 root1 = talloc_strdup(ctx, pname1);
7255 root2 = talloc_strdup(ctx, pname2);
7257 if (!root1 || !root2) {
7261 p = strrchr_m(root1,'.');
7264 ext1 = talloc_strdup(ctx, p+1);
7266 ext1 = talloc_strdup(ctx, "");
7268 p = strrchr_m(root2,'.');
7271 ext2 = talloc_strdup(ctx, p+1);
7273 ext2 = talloc_strdup(ctx, "");
7276 if (!ext1 || !ext2) {
7284 /* Hmmm. Should this be mb-aware ? */
7287 } else if (*p2 == '*') {
7289 root2 = talloc_asprintf(ctx, "%s%s",
7308 /* Hmmm. Should this be mb-aware ? */
7311 } else if (*p2 == '*') {
7313 ext2 = talloc_asprintf(ctx, "%s%s",
7329 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7334 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7346 /****************************************************************************
7347 Ensure open files have their names updated. Updated to notify other smbd's
7349 ****************************************************************************/
7351 static void rename_open_files(connection_struct *conn,
7352 struct share_mode_lock *lck,
7354 uint32_t orig_name_hash,
7355 const struct smb_filename *smb_fname_dst)
7358 bool did_rename = False;
7360 uint32_t new_name_hash = 0;
7362 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7363 fsp = file_find_di_next(fsp)) {
7364 struct file_id_buf idbuf;
7365 /* fsp_name is a relative path under the fsp. To change this for other
7366 sharepaths we need to manipulate relative paths. */
7367 /* TODO - create the absolute path and manipulate the newname
7368 relative to the sharepath. */
7369 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7372 if (fsp->name_hash != orig_name_hash) {
7375 DBG_DEBUG("renaming file %s "
7376 "(file_id %s) from %s -> %s\n",
7378 file_id_str_buf(fsp->file_id, &idbuf),
7380 smb_fname_str_dbg(smb_fname_dst));
7382 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7383 if (NT_STATUS_IS_OK(status)) {
7385 new_name_hash = fsp->name_hash;
7390 struct file_id_buf idbuf;
7391 DBG_DEBUG("no open files on file_id %s "
7393 file_id_str_buf(id, &idbuf),
7394 smb_fname_str_dbg(smb_fname_dst));
7397 /* Send messages to all smbd's (not ourself) that the name has changed. */
7398 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7399 orig_name_hash, new_name_hash,
7404 /****************************************************************************
7405 We need to check if the source path is a parent directory of the destination
7406 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7407 refuse the rename with a sharing violation. Under UNIX the above call can
7408 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7409 probably need to check that the client is a Windows one before disallowing
7410 this as a UNIX client (one with UNIX extensions) can know the source is a
7411 symlink and make this decision intelligently. Found by an excellent bug
7412 report from <AndyLiebman@aol.com>.
7413 ****************************************************************************/
7415 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7416 const struct smb_filename *smb_fname_dst)
7418 const char *psrc = smb_fname_src->base_name;
7419 const char *pdst = smb_fname_dst->base_name;
7422 if (psrc[0] == '.' && psrc[1] == '/') {
7425 if (pdst[0] == '.' && pdst[1] == '/') {
7428 if ((slen = strlen(psrc)) > strlen(pdst)) {
7431 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7435 * Do the notify calls from a rename
7438 static void notify_rename(connection_struct *conn, bool is_dir,
7439 const struct smb_filename *smb_fname_src,
7440 const struct smb_filename *smb_fname_dst)
7442 char *parent_dir_src = NULL;
7443 char *parent_dir_dst = NULL;
7446 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7447 : FILE_NOTIFY_CHANGE_FILE_NAME;
7449 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7450 &parent_dir_src, NULL) ||
7451 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7452 &parent_dir_dst, NULL)) {
7456 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7457 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7458 smb_fname_src->base_name);
7459 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7460 smb_fname_dst->base_name);
7463 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7464 smb_fname_src->base_name);
7465 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7466 smb_fname_dst->base_name);
7469 /* this is a strange one. w2k3 gives an additional event for
7470 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7471 files, but not directories */
7473 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7474 FILE_NOTIFY_CHANGE_ATTRIBUTES
7475 |FILE_NOTIFY_CHANGE_CREATION,
7476 smb_fname_dst->base_name);
7479 TALLOC_FREE(parent_dir_src);
7480 TALLOC_FREE(parent_dir_dst);
7483 /****************************************************************************
7484 Returns an error if the parent directory for a filename is open in an
7486 ****************************************************************************/
7488 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7489 const struct smb_filename *smb_fname_dst_in)
7491 struct smb_filename *smb_fname_parent = NULL;
7493 files_struct *fsp = NULL;
7497 ok = parent_smb_fname(talloc_tos(),
7502 return NT_STATUS_NO_MEMORY;
7505 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7507 return map_nt_error_from_unix(errno);
7511 * We're only checking on this smbd here, mostly good
7512 * enough.. and will pass tests.
7515 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7516 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7517 fsp = file_find_di_next(fsp)) {
7518 if (fsp->access_mask & DELETE_ACCESS) {
7519 return NT_STATUS_SHARING_VIOLATION;
7522 return NT_STATUS_OK;
7525 /****************************************************************************
7526 Rename an open file - given an fsp.
7527 ****************************************************************************/
7529 NTSTATUS rename_internals_fsp(connection_struct *conn,
7531 const struct smb_filename *smb_fname_dst_in,
7532 const char *dst_original_lcomp,
7534 bool replace_if_exists)
7536 TALLOC_CTX *ctx = talloc_tos();
7537 struct smb_filename *smb_fname_dst = NULL;
7538 NTSTATUS status = NT_STATUS_OK;
7539 struct share_mode_lock *lck = NULL;
7540 uint32_t access_mask = SEC_DIR_ADD_FILE;
7541 bool dst_exists, old_is_stream, new_is_stream;
7544 status = check_name(conn, smb_fname_dst_in);
7545 if (!NT_STATUS_IS_OK(status)) {
7549 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7550 if (!NT_STATUS_IS_OK(status)) {
7554 if (file_has_open_streams(fsp)) {
7555 return NT_STATUS_ACCESS_DENIED;
7558 /* Make a copy of the dst smb_fname structs */
7560 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7561 if (smb_fname_dst == NULL) {
7562 status = NT_STATUS_NO_MEMORY;
7567 * Check for special case with case preserving and not
7568 * case sensitive. If the new last component differs from the original
7569 * last component only by case, then we should allow
7570 * the rename (user is trying to change the case of the
7573 if (!conn->case_sensitive && conn->case_preserve &&
7574 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7575 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7576 char *fname_dst_parent = NULL;
7577 const char *fname_dst_lcomp = NULL;
7578 char *orig_lcomp_path = NULL;
7579 char *orig_lcomp_stream = NULL;
7583 * Split off the last component of the processed
7584 * destination name. We will compare this to
7585 * the split components of dst_original_lcomp.
7587 if (!parent_dirname(ctx,
7588 smb_fname_dst->base_name,
7590 &fname_dst_lcomp)) {
7591 status = NT_STATUS_NO_MEMORY;
7596 * The dst_original_lcomp component contains
7597 * the last_component of the path + stream
7598 * name (if a stream exists).
7600 * Split off the stream name so we
7601 * can check them separately.
7604 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7605 /* POSIX - no stream component. */
7606 orig_lcomp_path = talloc_strdup(ctx,
7607 dst_original_lcomp);
7608 if (orig_lcomp_path == NULL) {
7612 ok = split_stream_filename(ctx,
7615 &orig_lcomp_stream);
7619 TALLOC_FREE(fname_dst_parent);
7620 status = NT_STATUS_NO_MEMORY;
7624 /* If the base names only differ by case, use original. */
7625 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7628 * Replace the modified last component with the
7631 if (!ISDOT(fname_dst_parent)) {
7632 tmp = talloc_asprintf(smb_fname_dst,
7637 tmp = talloc_strdup(smb_fname_dst,
7641 status = NT_STATUS_NO_MEMORY;
7642 TALLOC_FREE(fname_dst_parent);
7643 TALLOC_FREE(orig_lcomp_path);
7644 TALLOC_FREE(orig_lcomp_stream);
7647 TALLOC_FREE(smb_fname_dst->base_name);
7648 smb_fname_dst->base_name = tmp;
7651 /* If the stream_names only differ by case, use original. */
7652 if(!strcsequal(smb_fname_dst->stream_name,
7653 orig_lcomp_stream)) {
7654 /* Use the original stream. */
7655 char *tmp = talloc_strdup(smb_fname_dst,
7658 status = NT_STATUS_NO_MEMORY;
7659 TALLOC_FREE(fname_dst_parent);
7660 TALLOC_FREE(orig_lcomp_path);
7661 TALLOC_FREE(orig_lcomp_stream);
7664 TALLOC_FREE(smb_fname_dst->stream_name);
7665 smb_fname_dst->stream_name = tmp;
7667 TALLOC_FREE(fname_dst_parent);
7668 TALLOC_FREE(orig_lcomp_path);
7669 TALLOC_FREE(orig_lcomp_stream);
7673 * If the src and dest names are identical - including case,
7674 * don't do the rename, just return success.
7677 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7678 strcsequal(fsp->fsp_name->stream_name,
7679 smb_fname_dst->stream_name)) {
7680 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7681 "- returning success\n",
7682 smb_fname_str_dbg(smb_fname_dst)));
7683 status = NT_STATUS_OK;
7687 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7688 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7690 /* Return the correct error code if both names aren't streams. */
7691 if (!old_is_stream && new_is_stream) {
7692 status = NT_STATUS_OBJECT_NAME_INVALID;
7696 if (old_is_stream && !new_is_stream) {
7697 status = NT_STATUS_INVALID_PARAMETER;
7701 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7703 if(!replace_if_exists && dst_exists) {
7704 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7705 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7706 smb_fname_str_dbg(smb_fname_dst)));
7707 status = NT_STATUS_OBJECT_NAME_COLLISION;
7712 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7713 &smb_fname_dst->st);
7714 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7716 /* The file can be open when renaming a stream */
7717 if (dst_fsp && !new_is_stream) {
7718 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7719 status = NT_STATUS_ACCESS_DENIED;
7724 /* Ensure we have a valid stat struct for the source. */
7725 status = vfs_stat_fsp(fsp);
7726 if (!NT_STATUS_IS_OK(status)) {
7730 status = can_rename(conn, fsp, attrs);
7732 if (!NT_STATUS_IS_OK(status)) {
7733 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7734 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7735 smb_fname_str_dbg(smb_fname_dst)));
7736 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7737 status = NT_STATUS_ACCESS_DENIED;
7741 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7742 status = NT_STATUS_ACCESS_DENIED;
7746 /* Do we have rights to move into the destination ? */
7747 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7748 /* We're moving a directory. */
7749 access_mask = SEC_DIR_ADD_SUBDIR;
7751 status = check_parent_access(conn,
7755 if (!NT_STATUS_IS_OK(status)) {
7756 DBG_INFO("check_parent_access on "
7757 "dst %s returned %s\n",
7758 smb_fname_str_dbg(smb_fname_dst),
7763 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7766 * We have the file open ourselves, so not being able to get the
7767 * corresponding share mode lock is a fatal error.
7770 SMB_ASSERT(lck != NULL);
7772 ret = SMB_VFS_RENAMEAT(conn,
7778 uint32_t create_options = fsp->fh->private_options;
7780 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7781 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7782 smb_fname_str_dbg(smb_fname_dst)));
7784 if (!fsp->fsp_flags.is_directory &&
7785 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7786 (lp_map_archive(SNUM(conn)) ||
7787 lp_store_dos_attributes(SNUM(conn)))) {
7788 /* We must set the archive bit on the newly
7790 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7791 uint32_t old_dosmode = dos_mode(conn,
7793 file_set_dosmode(conn,
7795 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7802 fsp->fsp_flags.is_directory,
7806 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7810 * A rename acts as a new file create w.r.t. allowing an initial delete
7811 * on close, probably because in Windows there is a new handle to the
7812 * new file. If initial delete on close was requested but not
7813 * originally set, we need to set it here. This is probably not 100% correct,
7814 * but will work for the CIFSFS client which in non-posix mode
7815 * depends on these semantics. JRA.
7818 if (create_options & FILE_DELETE_ON_CLOSE) {
7819 status = can_set_delete_on_close(fsp, 0);
7821 if (NT_STATUS_IS_OK(status)) {
7822 /* Note that here we set the *initial* delete on close flag,
7823 * not the regular one. The magic gets handled in close. */
7824 fsp->fsp_flags.initial_delete_on_close = true;
7828 status = NT_STATUS_OK;
7834 if (errno == ENOTDIR || errno == EISDIR) {
7835 status = NT_STATUS_OBJECT_NAME_COLLISION;
7837 status = map_nt_error_from_unix(errno);
7840 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7841 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7842 smb_fname_str_dbg(smb_fname_dst)));
7845 TALLOC_FREE(smb_fname_dst);
7850 /****************************************************************************
7851 The guts of the rename command, split out so it may be called by the NT SMB
7853 ****************************************************************************/
7855 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7856 connection_struct *conn,
7857 struct smb_request *req,
7858 struct smb_filename *smb_fname_src,
7859 struct smb_filename *smb_fname_dst,
7860 const char *dst_original_lcomp,
7862 bool replace_if_exists,
7863 uint32_t access_mask)
7865 char *fname_src_dir = NULL;
7866 struct smb_filename *smb_fname_src_dir = NULL;
7867 char *fname_src_mask = NULL;
7869 NTSTATUS status = NT_STATUS_OK;
7870 struct smb_Dir *dir_hnd = NULL;
7871 const char *dname = NULL;
7872 char *talloced = NULL;
7874 int create_options = 0;
7875 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7876 struct smb2_create_blobs *posx = NULL;
7878 bool src_has_wild = false;
7879 bool dest_has_wild = false;
7882 * Split the old name into directory and last component
7883 * strings. Note that unix_convert may have stripped off a
7884 * leading ./ from both name and newname if the rename is
7885 * at the root of the share. We need to make sure either both
7886 * name and newname contain a / character or neither of them do
7887 * as this is checked in resolve_wildcards().
7890 /* Split up the directory from the filename/mask. */
7891 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7892 &fname_src_dir, &fname_src_mask);
7893 if (!NT_STATUS_IS_OK(status)) {
7894 status = NT_STATUS_NO_MEMORY;
7898 if (req != NULL && !req->posix_pathnames) {
7900 * Check the wildcard mask *before*
7901 * unmangling. As mangling is done
7902 * for names that can't be returned
7903 * to Windows the unmangled name may
7904 * contain Windows wildcard characters.
7906 src_has_wild = ms_has_wild(fname_src_mask);
7907 dest_has_wild = ms_has_wild(dst_original_lcomp);
7911 * We should only check the mangled cache
7912 * here if unix_convert failed. This means
7913 * that the path in 'mask' doesn't exist
7914 * on the file system and so we need to look
7915 * for a possible mangle. This patch from
7916 * Tine Smukavec <valentin.smukavec@hermes.si>.
7919 if (!VALID_STAT(smb_fname_src->st) &&
7920 mangle_is_mangled(fname_src_mask, conn->params)) {
7921 char *new_mask = NULL;
7922 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7925 TALLOC_FREE(fname_src_mask);
7926 fname_src_mask = new_mask;
7930 if (posix_pathnames) {
7931 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7932 if (!NT_STATUS_IS_OK(status)) {
7933 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7939 if (!src_has_wild) {
7943 * Only one file needs to be renamed. Append the mask back
7944 * onto the directory.
7946 TALLOC_FREE(smb_fname_src->base_name);
7947 if (ISDOT(fname_src_dir)) {
7948 /* Ensure we use canonical names on open. */
7949 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7953 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7958 if (!smb_fname_src->base_name) {
7959 status = NT_STATUS_NO_MEMORY;
7963 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7964 "case_preserve = %d, short case preserve = %d, "
7965 "directory = %s, newname = %s, "
7966 "last_component_dest = %s\n",
7967 conn->case_sensitive, conn->case_preserve,
7968 conn->short_case_preserve,
7969 smb_fname_str_dbg(smb_fname_src),
7970 smb_fname_str_dbg(smb_fname_dst),
7971 dst_original_lcomp));
7973 /* The dest name still may have wildcards. */
7974 if (dest_has_wild) {
7975 char *fname_dst_mod = NULL;
7976 if (!resolve_wildcards(smb_fname_dst,
7977 smb_fname_src->base_name,
7978 smb_fname_dst->base_name,
7980 DEBUG(6, ("rename_internals: resolve_wildcards "
7982 smb_fname_src->base_name,
7983 smb_fname_dst->base_name));
7984 status = NT_STATUS_NO_MEMORY;
7987 TALLOC_FREE(smb_fname_dst->base_name);
7988 smb_fname_dst->base_name = fname_dst_mod;
7991 ZERO_STRUCT(smb_fname_src->st);
7992 if (posix_pathnames) {
7993 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7995 rc = SMB_VFS_STAT(conn, smb_fname_src);
7998 status = map_nt_error_from_unix_common(errno);
8002 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8003 create_options |= FILE_DIRECTORY_FILE;
8006 status = SMB_VFS_CREATE_FILE(
8009 smb_fname_src, /* fname */
8010 access_mask, /* access_mask */
8011 (FILE_SHARE_READ | /* share_access */
8013 FILE_OPEN, /* create_disposition*/
8014 create_options, /* create_options */
8015 0, /* file_attributes */
8016 0, /* oplock_request */
8018 0, /* allocation_size */
8019 0, /* private_flags */
8024 posx, /* in_context_blobs */
8025 NULL); /* out_context_blobs */
8027 if (!NT_STATUS_IS_OK(status)) {
8028 DEBUG(3, ("Could not open rename source %s: %s\n",
8029 smb_fname_str_dbg(smb_fname_src),
8030 nt_errstr(status)));
8034 status = rename_internals_fsp(conn,
8041 close_file(req, fsp, NORMAL_CLOSE);
8043 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8044 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8045 smb_fname_str_dbg(smb_fname_dst)));
8051 * Wildcards - process each file that matches.
8053 if (strequal(fname_src_mask, "????????.???")) {
8054 TALLOC_FREE(fname_src_mask);
8055 fname_src_mask = talloc_strdup(ctx, "*");
8056 if (!fname_src_mask) {
8057 status = NT_STATUS_NO_MEMORY;
8062 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8066 smb_fname_src->twrp,
8067 smb_fname_src->flags);
8068 if (smb_fname_src_dir == NULL) {
8069 status = NT_STATUS_NO_MEMORY;
8073 status = check_name(conn, smb_fname_src_dir);
8074 if (!NT_STATUS_IS_OK(status)) {
8078 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8080 if (dir_hnd == NULL) {
8081 status = map_nt_error_from_unix(errno);
8085 status = NT_STATUS_NO_SUCH_FILE;
8087 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8088 * - gentest fix. JRA
8091 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8093 files_struct *fsp = NULL;
8094 char *destname = NULL;
8095 bool sysdir_entry = False;
8097 /* Quick check for "." and ".." */
8098 if (ISDOT(dname) || ISDOTDOT(dname)) {
8099 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8100 sysdir_entry = True;
8102 TALLOC_FREE(talloced);
8107 if (!is_visible_file(conn,
8112 TALLOC_FREE(talloced);
8116 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8117 TALLOC_FREE(talloced);
8122 status = NT_STATUS_OBJECT_NAME_INVALID;
8126 TALLOC_FREE(smb_fname_src->base_name);
8127 if (ISDOT(fname_src_dir)) {
8128 /* Ensure we use canonical names on open. */
8129 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8133 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8138 if (!smb_fname_src->base_name) {
8139 status = NT_STATUS_NO_MEMORY;
8143 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8144 smb_fname_dst->base_name,
8146 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8147 smb_fname_src->base_name, destname));
8148 TALLOC_FREE(talloced);
8152 status = NT_STATUS_NO_MEMORY;
8156 TALLOC_FREE(smb_fname_dst->base_name);
8157 smb_fname_dst->base_name = destname;
8159 ZERO_STRUCT(smb_fname_src->st);
8160 if (posix_pathnames) {
8161 SMB_VFS_LSTAT(conn, smb_fname_src);
8163 SMB_VFS_STAT(conn, smb_fname_src);
8168 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8169 create_options |= FILE_DIRECTORY_FILE;
8172 status = SMB_VFS_CREATE_FILE(
8175 smb_fname_src, /* fname */
8176 access_mask, /* access_mask */
8177 (FILE_SHARE_READ | /* share_access */
8179 FILE_OPEN, /* create_disposition*/
8180 create_options, /* create_options */
8181 0, /* file_attributes */
8182 0, /* oplock_request */
8184 0, /* allocation_size */
8185 0, /* private_flags */
8190 posx, /* in_context_blobs */
8191 NULL); /* out_context_blobs */
8193 if (!NT_STATUS_IS_OK(status)) {
8194 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8195 "returned %s rename %s -> %s\n",
8197 smb_fname_str_dbg(smb_fname_src),
8198 smb_fname_str_dbg(smb_fname_dst)));
8202 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8203 if (dst_original_lcomp == NULL) {
8204 status = NT_STATUS_NO_MEMORY;
8208 status = rename_internals_fsp(conn,
8215 close_file(req, fsp, NORMAL_CLOSE);
8217 if (!NT_STATUS_IS_OK(status)) {
8218 DEBUG(3, ("rename_internals_fsp returned %s for "
8219 "rename %s -> %s\n", nt_errstr(status),
8220 smb_fname_str_dbg(smb_fname_src),
8221 smb_fname_str_dbg(smb_fname_dst)));
8227 DEBUG(3,("rename_internals: doing rename on %s -> "
8228 "%s\n", smb_fname_str_dbg(smb_fname_src),
8229 smb_fname_str_dbg(smb_fname_src)));
8230 TALLOC_FREE(talloced);
8232 TALLOC_FREE(dir_hnd);
8234 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8235 status = map_nt_error_from_unix(errno);
8240 TALLOC_FREE(talloced);
8241 TALLOC_FREE(smb_fname_src_dir);
8242 TALLOC_FREE(fname_src_dir);
8243 TALLOC_FREE(fname_src_mask);
8247 /****************************************************************************
8249 ****************************************************************************/
8251 void reply_mv(struct smb_request *req)
8253 connection_struct *conn = req->conn;
8255 char *newname = NULL;
8259 TALLOC_CTX *ctx = talloc_tos();
8260 struct smb_filename *smb_fname_src = NULL;
8261 struct smb_filename *smb_fname_dst = NULL;
8262 const char *dst_original_lcomp = NULL;
8263 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8264 (req->posix_pathnames ?
8265 UCF_UNIX_NAME_LOOKUP :
8266 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8267 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8268 (req->posix_pathnames ?
8270 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8271 bool stream_rename = false;
8273 START_PROFILE(SMBmv);
8276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8280 attrs = SVAL(req->vwv+0, 0);
8282 p = (const char *)req->buf + 1;
8283 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
8285 if (!NT_STATUS_IS_OK(status)) {
8286 reply_nterror(req, status);
8290 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
8292 if (!NT_STATUS_IS_OK(status)) {
8293 reply_nterror(req, status);
8297 if (!req->posix_pathnames) {
8298 /* The newname must begin with a ':' if the
8299 name contains a ':'. */
8300 if (strchr_m(name, ':')) {
8301 if (newname[0] != ':') {
8302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8305 stream_rename = true;
8309 status = filename_convert(ctx,
8316 if (!NT_STATUS_IS_OK(status)) {
8317 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8318 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8319 ERRSRV, ERRbadpath);
8322 reply_nterror(req, status);
8326 status = filename_convert(ctx,
8333 if (!NT_STATUS_IS_OK(status)) {
8334 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8335 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8336 ERRSRV, ERRbadpath);
8339 reply_nterror(req, status);
8343 /* Get the last component of the destination for rename_internals(). */
8344 dst_original_lcomp = get_original_lcomp(ctx,
8348 if (dst_original_lcomp == NULL) {
8349 reply_nterror(req, NT_STATUS_NO_MEMORY);
8353 if (stream_rename) {
8354 /* smb_fname_dst->base_name must be the same as
8355 smb_fname_src->base_name. */
8356 TALLOC_FREE(smb_fname_dst->base_name);
8357 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8358 smb_fname_src->base_name);
8359 if (!smb_fname_dst->base_name) {
8360 reply_nterror(req, NT_STATUS_NO_MEMORY);
8365 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8366 smb_fname_str_dbg(smb_fname_dst)));
8368 status = rename_internals(ctx,
8377 if (!NT_STATUS_IS_OK(status)) {
8378 if (open_was_deferred(req->xconn, req->mid)) {
8379 /* We have re-scheduled this call. */
8382 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8383 bool ok = defer_smb1_sharing_violation(req);
8388 reply_nterror(req, status);
8392 reply_outbuf(req, 0, 0);
8394 TALLOC_FREE(smb_fname_src);
8395 TALLOC_FREE(smb_fname_dst);
8400 /*******************************************************************
8401 Copy a file as part of a reply_copy.
8402 ******************************************************************/
8405 * TODO: check error codes on all callers
8408 NTSTATUS copy_file(TALLOC_CTX *ctx,
8409 connection_struct *conn,
8410 struct smb_filename *smb_fname_src,
8411 struct smb_filename *smb_fname_dst,
8414 bool target_is_directory)
8416 struct smb_filename *smb_fname_dst_tmp = NULL;
8418 files_struct *fsp1,*fsp2;
8420 uint32_t new_create_disposition;
8424 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8425 if (smb_fname_dst_tmp == NULL) {
8426 return NT_STATUS_NO_MEMORY;
8430 * If the target is a directory, extract the last component from the
8431 * src filename and append it to the dst filename
8433 if (target_is_directory) {
8436 /* dest/target can't be a stream if it's a directory. */
8437 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8439 p = strrchr_m(smb_fname_src->base_name,'/');
8443 p = smb_fname_src->base_name;
8445 smb_fname_dst_tmp->base_name =
8446 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8448 if (!smb_fname_dst_tmp->base_name) {
8449 status = NT_STATUS_NO_MEMORY;
8454 status = vfs_file_exist(conn, smb_fname_src);
8455 if (!NT_STATUS_IS_OK(status)) {
8459 if (!target_is_directory && count) {
8460 new_create_disposition = FILE_OPEN;
8462 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8465 &new_create_disposition,
8468 status = NT_STATUS_INVALID_PARAMETER;
8473 /* Open the src file for reading. */
8474 status = SMB_VFS_CREATE_FILE(
8477 smb_fname_src, /* fname */
8478 FILE_GENERIC_READ, /* access_mask */
8479 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8480 FILE_OPEN, /* create_disposition*/
8481 0, /* create_options */
8482 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8483 INTERNAL_OPEN_ONLY, /* oplock_request */
8485 0, /* allocation_size */
8486 0, /* private_flags */
8491 NULL, NULL); /* create context */
8493 if (!NT_STATUS_IS_OK(status)) {
8497 dosattrs = dos_mode(conn, smb_fname_src);
8499 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8500 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8503 /* Open the dst file for writing. */
8504 status = SMB_VFS_CREATE_FILE(
8507 smb_fname_dst, /* fname */
8508 FILE_GENERIC_WRITE, /* access_mask */
8509 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8510 new_create_disposition, /* create_disposition*/
8511 0, /* create_options */
8512 dosattrs, /* file_attributes */
8513 INTERNAL_OPEN_ONLY, /* oplock_request */
8515 0, /* allocation_size */
8516 0, /* private_flags */
8521 NULL, NULL); /* create context */
8523 if (!NT_STATUS_IS_OK(status)) {
8524 close_file(NULL, fsp1, ERROR_CLOSE);
8528 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8529 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8531 DEBUG(0, ("error - vfs lseek returned error %s\n",
8533 status = map_nt_error_from_unix(errno);
8534 close_file(NULL, fsp1, ERROR_CLOSE);
8535 close_file(NULL, fsp2, ERROR_CLOSE);
8540 /* Do the actual copy. */
8541 if (smb_fname_src->st.st_ex_size) {
8542 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8547 close_file(NULL, fsp1, NORMAL_CLOSE);
8549 /* Ensure the modtime is set correctly on the destination file. */
8550 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8553 * As we are opening fsp1 read-only we only expect
8554 * an error on close on fsp2 if we are out of space.
8555 * Thus we don't look at the error return from the
8558 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8560 if (!NT_STATUS_IS_OK(status)) {
8564 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8565 status = NT_STATUS_DISK_FULL;
8569 status = NT_STATUS_OK;
8572 TALLOC_FREE(smb_fname_dst_tmp);
8576 /****************************************************************************
8577 Reply to a file copy.
8578 ****************************************************************************/
8580 void reply_copy(struct smb_request *req)
8582 connection_struct *conn = req->conn;
8583 struct smb_filename *smb_fname_src = NULL;
8584 struct smb_filename *smb_fname_src_dir = NULL;
8585 struct smb_filename *smb_fname_dst = NULL;
8586 char *fname_src = NULL;
8587 char *fname_dst = NULL;
8588 char *fname_src_mask = NULL;
8589 char *fname_src_dir = NULL;
8592 int error = ERRnoaccess;
8596 bool target_is_directory=False;
8597 bool source_has_wild = False;
8598 bool dest_has_wild = False;
8600 uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8601 ucf_flags_from_smb_request(req);
8602 uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8603 ucf_flags_from_smb_request(req);
8604 TALLOC_CTX *ctx = talloc_tos();
8606 START_PROFILE(SMBcopy);
8609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8613 tid2 = SVAL(req->vwv+0, 0);
8614 ofun = SVAL(req->vwv+1, 0);
8615 flags = SVAL(req->vwv+2, 0);
8617 p = (const char *)req->buf;
8618 p += srvstr_get_path_req(ctx, req, &fname_src, p, STR_TERMINATE,
8620 if (!NT_STATUS_IS_OK(status)) {
8621 reply_nterror(req, status);
8624 p += srvstr_get_path_req(ctx, req, &fname_dst, p, STR_TERMINATE,
8626 if (!NT_STATUS_IS_OK(status)) {
8627 reply_nterror(req, status);
8631 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8633 if (tid2 != conn->cnum) {
8634 /* can't currently handle inter share copies XXXX */
8635 DEBUG(3,("Rejecting inter-share copy\n"));
8636 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8640 status = filename_convert(ctx, conn,
8645 if (!NT_STATUS_IS_OK(status)) {
8646 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8647 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8648 ERRSRV, ERRbadpath);
8651 reply_nterror(req, status);
8655 status = filename_convert(ctx, conn,
8660 if (!NT_STATUS_IS_OK(status)) {
8661 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8662 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8663 ERRSRV, ERRbadpath);
8666 reply_nterror(req, status);
8670 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8672 if ((flags&1) && target_is_directory) {
8673 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8677 if ((flags&2) && !target_is_directory) {
8678 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8682 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8683 /* wants a tree copy! XXXX */
8684 DEBUG(3,("Rejecting tree copy\n"));
8685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8689 /* Split up the directory from the filename/mask. */
8690 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8691 &fname_src_dir, &fname_src_mask);
8692 if (!NT_STATUS_IS_OK(status)) {
8693 reply_nterror(req, NT_STATUS_NO_MEMORY);
8697 if (!req->posix_pathnames) {
8699 * Check the wildcard mask *before*
8700 * unmangling. As mangling is done
8701 * for names that can't be returned
8702 * to Windows the unmangled name may
8703 * contain Windows wildcard characters.
8705 source_has_wild = ms_has_wild(fname_src_mask);
8706 dest_has_wild = ms_has_wild(smb_fname_dst->base_name);
8710 * We should only check the mangled cache
8711 * here if unix_convert failed. This means
8712 * that the path in 'mask' doesn't exist
8713 * on the file system and so we need to look
8714 * for a possible mangle. This patch from
8715 * Tine Smukavec <valentin.smukavec@hermes.si>.
8717 if (!VALID_STAT(smb_fname_src->st) &&
8718 mangle_is_mangled(fname_src_mask, conn->params)) {
8719 char *new_mask = NULL;
8720 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8721 &new_mask, conn->params);
8723 /* Use demangled name if one was successfully found. */
8725 TALLOC_FREE(fname_src_mask);
8726 fname_src_mask = new_mask;
8730 if (!source_has_wild) {
8733 * Only one file needs to be copied. Append the mask back onto
8736 TALLOC_FREE(smb_fname_src->base_name);
8737 if (ISDOT(fname_src_dir)) {
8738 /* Ensure we use canonical names on open. */
8739 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8743 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8748 if (!smb_fname_src->base_name) {
8749 reply_nterror(req, NT_STATUS_NO_MEMORY);
8753 if (dest_has_wild) {
8754 char *fname_dst_mod = NULL;
8755 if (!resolve_wildcards(smb_fname_dst,
8756 smb_fname_src->base_name,
8757 smb_fname_dst->base_name,
8759 reply_nterror(req, NT_STATUS_NO_MEMORY);
8762 TALLOC_FREE(smb_fname_dst->base_name);
8763 smb_fname_dst->base_name = fname_dst_mod;
8766 status = check_name(conn, smb_fname_src);
8767 if (!NT_STATUS_IS_OK(status)) {
8768 reply_nterror(req, status);
8772 status = check_name(conn, smb_fname_dst);
8773 if (!NT_STATUS_IS_OK(status)) {
8774 reply_nterror(req, status);
8778 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8779 ofun, count, target_is_directory);
8781 if(!NT_STATUS_IS_OK(status)) {
8782 reply_nterror(req, status);
8788 struct smb_Dir *dir_hnd = NULL;
8789 const char *dname = NULL;
8790 char *talloced = NULL;
8794 * There is a wildcard that requires us to actually read the
8795 * src dir and copy each file matching the mask to the dst.
8796 * Right now streams won't be copied, but this could
8797 * presumably be added with a nested loop for reach dir entry.
8799 SMB_ASSERT(!smb_fname_src->stream_name);
8800 SMB_ASSERT(!smb_fname_dst->stream_name);
8802 smb_fname_src->stream_name = NULL;
8803 smb_fname_dst->stream_name = NULL;
8805 if (strequal(fname_src_mask,"????????.???")) {
8806 TALLOC_FREE(fname_src_mask);
8807 fname_src_mask = talloc_strdup(ctx, "*");
8808 if (!fname_src_mask) {
8809 reply_nterror(req, NT_STATUS_NO_MEMORY);
8814 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8818 smb_fname_src->twrp,
8819 smb_fname_src->flags);
8820 if (smb_fname_src_dir == NULL) {
8821 reply_nterror(req, NT_STATUS_NO_MEMORY);
8825 status = check_name(conn, smb_fname_src_dir);
8826 if (!NT_STATUS_IS_OK(status)) {
8827 reply_nterror(req, status);
8831 dir_hnd = OpenDir(ctx,
8836 if (dir_hnd == NULL) {
8837 status = map_nt_error_from_unix(errno);
8838 reply_nterror(req, status);
8844 /* Iterate over the src dir copying each entry to the dst. */
8845 while ((dname = ReadDirName(dir_hnd, &offset,
8846 &smb_fname_src->st, &talloced))) {
8847 char *destname = NULL;
8849 if (ISDOT(dname) || ISDOTDOT(dname)) {
8850 TALLOC_FREE(talloced);
8854 if (!is_visible_file(conn,
8859 TALLOC_FREE(talloced);
8863 if(!mask_match(dname, fname_src_mask,
8864 conn->case_sensitive)) {
8865 TALLOC_FREE(talloced);
8869 error = ERRnoaccess;
8871 /* Get the src smb_fname struct setup. */
8872 TALLOC_FREE(smb_fname_src->base_name);
8873 if (ISDOT(fname_src_dir)) {
8874 /* Ensure we use canonical names on open. */
8875 smb_fname_src->base_name =
8876 talloc_asprintf(smb_fname_src, "%s",
8879 smb_fname_src->base_name =
8880 talloc_asprintf(smb_fname_src, "%s/%s",
8881 fname_src_dir, dname);
8884 if (!smb_fname_src->base_name) {
8885 TALLOC_FREE(dir_hnd);
8886 TALLOC_FREE(talloced);
8887 reply_nterror(req, NT_STATUS_NO_MEMORY);
8891 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8892 smb_fname_dst->base_name,
8894 TALLOC_FREE(talloced);
8898 TALLOC_FREE(dir_hnd);
8899 TALLOC_FREE(talloced);
8900 reply_nterror(req, NT_STATUS_NO_MEMORY);
8904 TALLOC_FREE(smb_fname_dst->base_name);
8905 smb_fname_dst->base_name = destname;
8907 status = check_name(conn, smb_fname_src);
8908 if (!NT_STATUS_IS_OK(status)) {
8909 TALLOC_FREE(dir_hnd);
8910 TALLOC_FREE(talloced);
8911 reply_nterror(req, status);
8915 status = check_name(conn, smb_fname_dst);
8916 if (!NT_STATUS_IS_OK(status)) {
8917 TALLOC_FREE(dir_hnd);
8918 TALLOC_FREE(talloced);
8919 reply_nterror(req, status);
8923 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8924 smb_fname_src->base_name,
8925 smb_fname_dst->base_name));
8927 status = copy_file(ctx, conn, smb_fname_src,
8928 smb_fname_dst, ofun, count,
8929 target_is_directory);
8930 if (NT_STATUS_IS_OK(status)) {
8934 TALLOC_FREE(talloced);
8936 TALLOC_FREE(dir_hnd);
8940 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8944 reply_outbuf(req, 1, 0);
8945 SSVAL(req->outbuf,smb_vwv0,count);
8947 TALLOC_FREE(smb_fname_src);
8948 TALLOC_FREE(smb_fname_src_dir);
8949 TALLOC_FREE(smb_fname_dst);
8950 TALLOC_FREE(fname_src);
8951 TALLOC_FREE(fname_dst);
8952 TALLOC_FREE(fname_src_mask);
8953 TALLOC_FREE(fname_src_dir);
8955 END_PROFILE(SMBcopy);
8960 #define DBGC_CLASS DBGC_LOCKING
8962 /****************************************************************************
8963 Get a lock pid, dealing with large count requests.
8964 ****************************************************************************/
8966 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8967 bool large_file_format)
8969 if(!large_file_format)
8970 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8972 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8975 /****************************************************************************
8976 Get a lock count, dealing with large count requests.
8977 ****************************************************************************/
8979 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8980 bool large_file_format)
8984 if(!large_file_format) {
8985 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8988 * No BVAL, this is reversed!
8990 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8991 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8997 /****************************************************************************
8998 Get a lock offset, dealing with large offset requests.
8999 ****************************************************************************/
9001 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9002 bool large_file_format)
9004 uint64_t offset = 0;
9006 if(!large_file_format) {
9007 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9010 * No BVAL, this is reversed!
9012 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9013 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9019 struct smbd_do_unlocking_state {
9020 struct files_struct *fsp;
9021 uint16_t num_ulocks;
9022 struct smbd_lock_element *ulocks;
9023 enum brl_flavour lock_flav;
9027 static void smbd_do_unlocking_fn(
9030 bool *pmodified_dependent,
9033 struct smbd_do_unlocking_state *state = private_data;
9034 struct files_struct *fsp = state->fsp;
9035 enum brl_flavour lock_flav = state->lock_flav;
9038 for (i = 0; i < state->num_ulocks; i++) {
9039 struct smbd_lock_element *e = &state->ulocks[i];
9041 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9042 "pid %"PRIu64", file %s\n",
9048 if (e->brltype != UNLOCK_LOCK) {
9049 /* this can only happen with SMB2 */
9050 state->status = NT_STATUS_INVALID_PARAMETER;
9054 state->status = do_unlock(
9055 fsp, e->smblctx, e->count, e->offset, lock_flav);
9057 DBG_DEBUG("do_unlock returned %s\n",
9058 nt_errstr(state->status));
9060 if (!NT_STATUS_IS_OK(state->status)) {
9065 *pmodified_dependent = true;
9068 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9070 uint16_t num_ulocks,
9071 struct smbd_lock_element *ulocks,
9072 enum brl_flavour lock_flav)
9074 struct smbd_do_unlocking_state state = {
9076 .num_ulocks = num_ulocks,
9078 .lock_flav = lock_flav,
9082 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9084 status = share_mode_do_locked(
9085 fsp->file_id, smbd_do_unlocking_fn, &state);
9087 if (!NT_STATUS_IS_OK(status)) {
9088 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9092 if (!NT_STATUS_IS_OK(state.status)) {
9093 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9095 return state.status;
9098 return NT_STATUS_OK;
9101 /****************************************************************************
9102 Reply to a lockingX request.
9103 ****************************************************************************/
9105 static void reply_lockingx_done(struct tevent_req *subreq);
9107 void reply_lockingX(struct smb_request *req)
9109 connection_struct *conn = req->conn;
9111 unsigned char locktype;
9112 enum brl_type brltype;
9113 unsigned char oplocklevel;
9114 uint16_t num_ulocks;
9116 int32_t lock_timeout;
9118 const uint8_t *data;
9119 bool large_file_format;
9120 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9121 struct smbd_lock_element *locks = NULL;
9122 struct tevent_req *subreq = NULL;
9124 START_PROFILE(SMBlockingX);
9127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9128 END_PROFILE(SMBlockingX);
9132 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9133 locktype = CVAL(req->vwv+3, 0);
9134 oplocklevel = CVAL(req->vwv+3, 1);
9135 num_ulocks = SVAL(req->vwv+6, 0);
9136 num_locks = SVAL(req->vwv+7, 0);
9137 lock_timeout = IVAL(req->vwv+4, 0);
9138 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9140 if (!check_fsp(conn, req, fsp)) {
9141 END_PROFILE(SMBlockingX);
9147 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9148 /* we don't support these - and CANCEL_LOCK makes w2k
9149 and XP reboot so I don't really want to be
9150 compatible! (tridge) */
9151 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9152 END_PROFILE(SMBlockingX);
9156 /* Check if this is an oplock break on a file
9157 we have granted an oplock on.
9159 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9160 /* Client can insist on breaking to none. */
9161 bool break_to_none = (oplocklevel == 0);
9164 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9165 "for %s\n", (unsigned int)oplocklevel,
9166 fsp_fnum_dbg(fsp)));
9169 * Make sure we have granted an exclusive or batch oplock on
9173 if (fsp->oplock_type == 0) {
9175 /* The Samba4 nbench simulator doesn't understand
9176 the difference between break to level2 and break
9177 to none from level2 - it sends oplock break
9178 replies in both cases. Don't keep logging an error
9179 message here - just ignore it. JRA. */
9181 DEBUG(5,("reply_lockingX: Error : oplock break from "
9182 "client for %s (oplock=%d) and no "
9183 "oplock granted on this file (%s).\n",
9184 fsp_fnum_dbg(fsp), fsp->oplock_type,
9187 /* if this is a pure oplock break request then don't
9189 if (num_locks == 0 && num_ulocks == 0) {
9190 END_PROFILE(SMBlockingX);
9194 END_PROFILE(SMBlockingX);
9195 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9199 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9201 result = remove_oplock(fsp);
9203 result = downgrade_oplock(fsp);
9207 DEBUG(0, ("reply_lockingX: error in removing "
9208 "oplock on file %s\n", fsp_str_dbg(fsp)));
9209 /* Hmmm. Is this panic justified? */
9210 smb_panic("internal tdb error");
9213 /* if this is a pure oplock break request then don't send a
9215 if (num_locks == 0 && num_ulocks == 0) {
9216 /* Sanity check - ensure a pure oplock break is not a
9218 if (CVAL(req->vwv+0, 0) != 0xff) {
9219 DEBUG(0,("reply_lockingX: Error : pure oplock "
9220 "break is a chained %d request !\n",
9221 (unsigned int)CVAL(req->vwv+0, 0)));
9223 END_PROFILE(SMBlockingX);
9229 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9231 END_PROFILE(SMBlockingX);
9235 if (num_ulocks != 0) {
9236 struct smbd_lock_element *ulocks = NULL;
9239 ulocks = talloc_array(
9240 req, struct smbd_lock_element, num_ulocks);
9241 if (ulocks == NULL) {
9242 reply_nterror(req, NT_STATUS_NO_MEMORY);
9243 END_PROFILE(SMBlockingX);
9248 * Data now points at the beginning of the list of
9249 * smb_unlkrng structs
9251 for (i = 0; i < num_ulocks; i++) {
9252 ulocks[i].req_guid = smbd_request_guid(req,
9254 ulocks[i].smblctx = get_lock_pid(
9255 data, i, large_file_format);
9256 ulocks[i].count = get_lock_count(
9257 data, i, large_file_format);
9258 ulocks[i].offset = get_lock_offset(
9259 data, i, large_file_format);
9260 ulocks[i].brltype = UNLOCK_LOCK;
9264 * Unlock cancels pending locks
9267 ok = smbd_smb1_brl_finish_by_lock(
9274 reply_outbuf(req, 2, 0);
9275 SSVAL(req->outbuf, smb_vwv0, 0xff);
9276 SSVAL(req->outbuf, smb_vwv1, 0);
9277 END_PROFILE(SMBlockingX);
9281 status = smbd_do_unlocking(
9282 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9283 TALLOC_FREE(ulocks);
9284 if (!NT_STATUS_IS_OK(status)) {
9285 END_PROFILE(SMBlockingX);
9286 reply_nterror(req, status);
9291 /* Now do any requested locks */
9292 data += ((large_file_format ? 20 : 10)*num_ulocks);
9294 /* Data now points at the beginning of the list
9295 of smb_lkrng structs */
9297 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9298 brltype = READ_LOCK;
9300 brltype = WRITE_LOCK;
9303 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9304 if (locks == NULL) {
9305 reply_nterror(req, NT_STATUS_NO_MEMORY);
9306 END_PROFILE(SMBlockingX);
9310 for (i = 0; i < num_locks; i++) {
9311 locks[i].req_guid = smbd_request_guid(req, i),
9312 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9313 locks[i].count = get_lock_count(data, i, large_file_format);
9314 locks[i].offset = get_lock_offset(data, i, large_file_format);
9315 locks[i].brltype = brltype;
9318 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9322 if (num_locks == 0) {
9323 /* See smbtorture3 lock11 test */
9324 reply_outbuf(req, 2, 0);
9325 /* andx chain ends */
9326 SSVAL(req->outbuf, smb_vwv0, 0xff);
9327 SSVAL(req->outbuf, smb_vwv1, 0);
9328 END_PROFILE(SMBlockingX);
9332 ok = smbd_smb1_brl_finish_by_lock(
9336 locks[0], /* Windows only cancels the first lock */
9337 NT_STATUS_FILE_LOCK_CONFLICT);
9340 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9341 END_PROFILE(SMBlockingX);
9345 reply_outbuf(req, 2, 0);
9346 SSVAL(req->outbuf, smb_vwv0, 0xff);
9347 SSVAL(req->outbuf, smb_vwv1, 0);
9348 END_PROFILE(SMBlockingX);
9352 subreq = smbd_smb1_do_locks_send(
9362 if (subreq == NULL) {
9363 reply_nterror(req, NT_STATUS_NO_MEMORY);
9364 END_PROFILE(SMBlockingX);
9367 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9368 END_PROFILE(SMBlockingX);
9371 static void reply_lockingx_done(struct tevent_req *subreq)
9373 struct smb_request *req = NULL;
9377 START_PROFILE(SMBlockingX);
9379 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9382 status = smbd_smb1_do_locks_recv(subreq);
9383 TALLOC_FREE(subreq);
9385 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9387 if (NT_STATUS_IS_OK(status)) {
9388 reply_outbuf(req, 2, 0);
9389 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9390 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9392 reply_nterror(req, status);
9395 ok = srv_send_smb(req->xconn,
9396 (char *)req->outbuf,
9399 IS_CONN_ENCRYPTED(req->conn),
9402 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9405 END_PROFILE(SMBlockingX);
9409 #define DBGC_CLASS DBGC_ALL
9411 /****************************************************************************
9412 Reply to a SMBreadbmpx (read block multiplex) request.
9413 Always reply with an error, if someone has a platform really needs this,
9414 please contact vl@samba.org
9415 ****************************************************************************/
9417 void reply_readbmpx(struct smb_request *req)
9419 START_PROFILE(SMBreadBmpx);
9420 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9421 END_PROFILE(SMBreadBmpx);
9425 /****************************************************************************
9426 Reply to a SMBreadbs (read block multiplex secondary) request.
9427 Always reply with an error, if someone has a platform really needs this,
9428 please contact vl@samba.org
9429 ****************************************************************************/
9431 void reply_readbs(struct smb_request *req)
9433 START_PROFILE(SMBreadBs);
9434 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9435 END_PROFILE(SMBreadBs);
9439 /****************************************************************************
9440 Reply to a SMBsetattrE.
9441 ****************************************************************************/
9443 void reply_setattrE(struct smb_request *req)
9445 connection_struct *conn = req->conn;
9446 struct smb_file_time ft;
9450 START_PROFILE(SMBsetattrE);
9451 init_smb_file_time(&ft);
9454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9458 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9460 if(!fsp || (fsp->conn != conn)) {
9461 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9466 * Convert the DOS times into unix times.
9469 ft.atime = time_t_to_full_timespec(
9470 srv_make_unix_date2(req->vwv+3));
9471 ft.mtime = time_t_to_full_timespec(
9472 srv_make_unix_date2(req->vwv+5));
9473 ft.create_time = time_t_to_full_timespec(
9474 srv_make_unix_date2(req->vwv+1));
9476 reply_outbuf(req, 0, 0);
9479 * Patch from Ray Frush <frush@engr.colostate.edu>
9480 * Sometimes times are sent as zero - ignore them.
9483 /* Ensure we have a valid stat struct for the source. */
9484 status = vfs_stat_fsp(fsp);
9485 if (!NT_STATUS_IS_OK(status)) {
9486 reply_nterror(req, status);
9490 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9491 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9495 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9496 if (!NT_STATUS_IS_OK(status)) {
9497 reply_nterror(req, status);
9501 if (fsp->fsp_flags.modified) {
9502 trigger_write_time_update_immediate(fsp);
9505 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9508 (unsigned int)ft.atime.tv_sec,
9509 (unsigned int)ft.mtime.tv_sec,
9510 (unsigned int)ft.create_time.tv_sec
9513 END_PROFILE(SMBsetattrE);
9518 /* Back from the dead for OS/2..... JRA. */
9520 /****************************************************************************
9521 Reply to a SMBwritebmpx (write block multiplex primary) request.
9522 Always reply with an error, if someone has a platform really needs this,
9523 please contact vl@samba.org
9524 ****************************************************************************/
9526 void reply_writebmpx(struct smb_request *req)
9528 START_PROFILE(SMBwriteBmpx);
9529 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9530 END_PROFILE(SMBwriteBmpx);
9534 /****************************************************************************
9535 Reply to a SMBwritebs (write block multiplex secondary) request.
9536 Always reply with an error, if someone has a platform really needs this,
9537 please contact vl@samba.org
9538 ****************************************************************************/
9540 void reply_writebs(struct smb_request *req)
9542 START_PROFILE(SMBwriteBs);
9543 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9544 END_PROFILE(SMBwriteBs);
9548 /****************************************************************************
9549 Reply to a SMBgetattrE.
9550 ****************************************************************************/
9552 void reply_getattrE(struct smb_request *req)
9554 connection_struct *conn = req->conn;
9557 struct timespec create_ts;
9560 START_PROFILE(SMBgetattrE);
9563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9564 END_PROFILE(SMBgetattrE);
9568 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9570 if(!fsp || (fsp->conn != conn)) {
9571 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9572 END_PROFILE(SMBgetattrE);
9576 /* Do an fstat on this file */
9577 status = vfs_stat_fsp(fsp);
9578 if (!NT_STATUS_IS_OK(status)) {
9579 reply_nterror(req, status);
9580 END_PROFILE(SMBgetattrE);
9584 mode = dos_mode(conn, fsp->fsp_name);
9587 * Convert the times into dos times. Set create
9588 * date to be last modify date as UNIX doesn't save
9592 reply_outbuf(req, 11, 0);
9594 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9595 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9596 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9597 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9598 /* Should we check pending modtime here ? JRA */
9599 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9600 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9602 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9603 SIVAL(req->outbuf, smb_vwv6, 0);
9604 SIVAL(req->outbuf, smb_vwv8, 0);
9606 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9607 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9608 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9610 SSVAL(req->outbuf,smb_vwv10, mode);
9612 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9614 END_PROFILE(SMBgetattrE);