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,
3272 struct smb_request *req,
3274 struct smb_filename *smb_fname,
3277 char *fname_dir = NULL;
3278 char *fname_mask = NULL;
3280 NTSTATUS status = NT_STATUS_OK;
3281 struct smb_filename *smb_fname_dir = NULL;
3282 TALLOC_CTX *ctx = talloc_tos();
3284 /* Split up the directory from the filename/mask. */
3285 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3286 &fname_dir, &fname_mask);
3287 if (!NT_STATUS_IS_OK(status)) {
3292 * We should only check the mangled cache
3293 * here if unix_convert failed. This means
3294 * that the path in 'mask' doesn't exist
3295 * on the file system and so we need to look
3296 * for a possible mangle. This patch from
3297 * Tine Smukavec <valentin.smukavec@hermes.si>.
3300 if (!VALID_STAT(smb_fname->st) &&
3301 mangle_is_mangled(fname_mask, conn->params)) {
3302 char *new_mask = NULL;
3303 mangle_lookup_name_from_8_3(ctx, fname_mask,
3304 &new_mask, conn->params);
3306 TALLOC_FREE(fname_mask);
3307 fname_mask = new_mask;
3314 * Only one file needs to be unlinked. Append the mask back
3315 * onto the directory.
3317 TALLOC_FREE(smb_fname->base_name);
3318 if (ISDOT(fname_dir)) {
3319 /* Ensure we use canonical names on open. */
3320 smb_fname->base_name = talloc_asprintf(smb_fname,
3324 smb_fname->base_name = talloc_asprintf(smb_fname,
3329 if (!smb_fname->base_name) {
3330 status = NT_STATUS_NO_MEMORY;
3334 dirtype = FILE_ATTRIBUTE_NORMAL;
3337 status = check_name(conn, smb_fname);
3338 if (!NT_STATUS_IS_OK(status)) {
3342 status = do_unlink(conn, req, smb_fname, dirtype);
3343 if (!NT_STATUS_IS_OK(status)) {
3349 struct smb_Dir *dir_hnd = NULL;
3351 const char *dname = NULL;
3352 char *talloced = NULL;
3354 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3355 status = NT_STATUS_OBJECT_NAME_INVALID;
3359 dirtype = FILE_ATTRIBUTE_NORMAL;
3362 if (strequal(fname_mask,"????????.???")) {
3363 TALLOC_FREE(fname_mask);
3364 fname_mask = talloc_strdup(ctx, "*");
3366 status = NT_STATUS_NO_MEMORY;
3371 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3377 if (smb_fname_dir == NULL) {
3378 status = NT_STATUS_NO_MEMORY;
3382 status = check_name(conn, smb_fname_dir);
3383 if (!NT_STATUS_IS_OK(status)) {
3387 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3389 if (dir_hnd == NULL) {
3390 status = map_nt_error_from_unix(errno);
3394 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3395 the pattern matches against the long name, otherwise the short name
3396 We don't implement this yet XXXX
3399 status = NT_STATUS_NO_SUCH_FILE;
3401 while ((dname = ReadDirName(dir_hnd, &offset,
3402 &smb_fname->st, &talloced))) {
3403 TALLOC_CTX *frame = talloc_stackframe();
3405 struct smb_filename *f = NULL;
3407 if (!is_visible_file(conn,
3413 TALLOC_FREE(talloced);
3417 /* Quick check for "." and ".." */
3418 if (ISDOT(dname) || ISDOTDOT(dname)) {
3420 TALLOC_FREE(talloced);
3424 if(!mask_match(dname, fname_mask,
3425 conn->case_sensitive)) {
3427 TALLOC_FREE(talloced);
3431 if (ISDOT(fname_dir)) {
3432 /* Ensure we use canonical names on open. */
3433 p = talloc_asprintf(smb_fname, "%s", dname);
3435 p = talloc_asprintf(smb_fname, "%s/%s",
3439 TALLOC_FREE(dir_hnd);
3440 status = NT_STATUS_NO_MEMORY;
3442 TALLOC_FREE(talloced);
3445 f = synthetic_smb_fname(frame,
3452 TALLOC_FREE(dir_hnd);
3453 status = NT_STATUS_NO_MEMORY;
3455 TALLOC_FREE(talloced);
3459 status = check_name(conn, f);
3460 if (!NT_STATUS_IS_OK(status)) {
3461 TALLOC_FREE(dir_hnd);
3463 TALLOC_FREE(talloced);
3467 status = do_unlink(conn, req, f, dirtype);
3468 if (!NT_STATUS_IS_OK(status)) {
3469 TALLOC_FREE(dir_hnd);
3471 TALLOC_FREE(talloced);
3476 DBG_DEBUG("successful unlink [%s]\n",
3477 smb_fname_str_dbg(f));
3480 TALLOC_FREE(talloced);
3482 TALLOC_FREE(dir_hnd);
3485 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3486 status = map_nt_error_from_unix(errno);
3490 TALLOC_FREE(smb_fname_dir);
3491 TALLOC_FREE(fname_dir);
3492 TALLOC_FREE(fname_mask);
3496 /****************************************************************************
3498 ****************************************************************************/
3500 void reply_unlink(struct smb_request *req)
3502 connection_struct *conn = req->conn;
3504 struct smb_filename *smb_fname = NULL;
3507 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3508 ucf_flags_from_smb_request(req);
3509 TALLOC_CTX *ctx = talloc_tos();
3510 bool has_wild = false;
3512 START_PROFILE(SMBunlink);
3515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3519 dirtype = SVAL(req->vwv+0, 0);
3521 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
3522 STR_TERMINATE, &status);
3523 if (!NT_STATUS_IS_OK(status)) {
3524 reply_nterror(req, status);
3528 status = filename_convert(ctx, conn,
3533 if (!NT_STATUS_IS_OK(status)) {
3534 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3535 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3536 ERRSRV, ERRbadpath);
3539 reply_nterror(req, status);
3543 if (req != NULL && !req->posix_pathnames) {
3544 char *lcomp = get_original_lcomp(ctx,
3548 if (lcomp == NULL) {
3549 reply_nterror(req, NT_STATUS_NO_MEMORY);
3552 has_wild = ms_has_wild(lcomp);
3556 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3558 status = unlink_internals(conn, req, dirtype, smb_fname, has_wild);
3559 if (!NT_STATUS_IS_OK(status)) {
3560 if (open_was_deferred(req->xconn, req->mid)) {
3561 /* We have re-scheduled this call. */
3564 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3565 bool ok = defer_smb1_sharing_violation(req);
3570 reply_nterror(req, status);
3574 reply_outbuf(req, 0, 0);
3576 TALLOC_FREE(smb_fname);
3577 END_PROFILE(SMBunlink);
3581 /****************************************************************************
3583 ****************************************************************************/
3585 static void fail_readraw(void)
3587 const char *errstr = talloc_asprintf(talloc_tos(),
3588 "FAIL ! reply_readbraw: socket write fail (%s)",
3593 exit_server_cleanly(errstr);
3596 /****************************************************************************
3597 Fake (read/write) sendfile. Returns -1 on read or write fail.
3598 ****************************************************************************/
3600 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3601 off_t startpos, size_t nread)
3604 size_t tosend = nread;
3611 bufsize = MIN(nread, 65536);
3613 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3617 while (tosend > 0) {
3621 cur_read = MIN(tosend, bufsize);
3622 ret = read_file(fsp,buf,startpos,cur_read);
3628 /* If we had a short read, fill with zeros. */
3629 if (ret < cur_read) {
3630 memset(buf + ret, '\0', cur_read - ret);
3633 ret = write_data(xconn->transport.sock, buf, cur_read);
3634 if (ret != cur_read) {
3635 int saved_errno = errno;
3637 * Try and give an error message saying what
3640 DEBUG(0, ("write_data failed for client %s. "
3642 smbXsrv_connection_dbg(xconn),
3643 strerror(saved_errno)));
3645 errno = saved_errno;
3649 startpos += cur_read;
3653 return (ssize_t)nread;
3656 /****************************************************************************
3657 Deal with the case of sendfile reading less bytes from the file than
3658 requested. Fill with zeros (all we can do). Returns 0 on success
3659 ****************************************************************************/
3661 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3667 #define SHORT_SEND_BUFSIZE 1024
3668 if (nread < headersize) {
3669 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3670 "header for file %s (%s). Terminating\n",
3671 fsp_str_dbg(fsp), strerror(errno)));
3675 nread -= headersize;
3677 if (nread < smb_maxcnt) {
3678 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3680 DEBUG(0,("sendfile_short_send: malloc failed "
3681 "for file %s (%s). Terminating\n",
3682 fsp_str_dbg(fsp), strerror(errno)));
3686 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3687 "with zeros !\n", fsp_str_dbg(fsp)));
3689 while (nread < smb_maxcnt) {
3691 * We asked for the real file size and told sendfile
3692 * to not go beyond the end of the file. But it can
3693 * happen that in between our fstat call and the
3694 * sendfile call the file was truncated. This is very
3695 * bad because we have already announced the larger
3696 * number of bytes to the client.
3698 * The best we can do now is to send 0-bytes, just as
3699 * a read from a hole in a sparse file would do.
3701 * This should happen rarely enough that I don't care
3702 * about efficiency here :-)
3707 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3708 ret = write_data(xconn->transport.sock, buf, to_write);
3709 if (ret != to_write) {
3710 int saved_errno = errno;
3712 * Try and give an error message saying what
3715 DEBUG(0, ("write_data failed for client %s. "
3717 smbXsrv_connection_dbg(xconn),
3718 strerror(saved_errno)));
3719 errno = saved_errno;
3730 /****************************************************************************
3731 Return a readbraw error (4 bytes of zero).
3732 ****************************************************************************/
3734 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3740 smbd_lock_socket(xconn);
3741 if (write_data(xconn->transport.sock,header,4) != 4) {
3742 int saved_errno = errno;
3744 * Try and give an error message saying what
3747 DEBUG(0, ("write_data failed for client %s. "
3749 smbXsrv_connection_dbg(xconn),
3750 strerror(saved_errno)));
3751 errno = saved_errno;
3755 smbd_unlock_socket(xconn);
3758 /*******************************************************************
3759 Ensure we don't use sendfile if server smb signing is active.
3760 ********************************************************************/
3762 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3764 bool sign_active = false;
3766 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3767 if (get_Protocol() < PROTOCOL_NT1) {
3770 if (signing_state) {
3771 sign_active = smb_signing_is_active(signing_state);
3773 return (lp__use_sendfile(snum) &&
3774 (get_remote_arch() != RA_WIN95) &&
3777 /****************************************************************************
3778 Use sendfile in readbraw.
3779 ****************************************************************************/
3781 static void send_file_readbraw(connection_struct *conn,
3782 struct smb_request *req,
3788 struct smbXsrv_connection *xconn = req->xconn;
3789 char *outbuf = NULL;
3793 * We can only use sendfile on a non-chained packet
3794 * but we can use on a non-oplocked file. tridge proved this
3795 * on a train in Germany :-). JRA.
3796 * reply_readbraw has already checked the length.
3799 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3800 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3801 ssize_t sendfile_read = -1;
3803 DATA_BLOB header_blob;
3805 _smb_setlen(header,nread);
3806 header_blob = data_blob_const(header, 4);
3808 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3809 &header_blob, startpos,
3811 if (sendfile_read == -1) {
3812 /* Returning ENOSYS means no data at all was sent.
3813 * Do this as a normal read. */
3814 if (errno == ENOSYS) {
3815 goto normal_readbraw;
3819 * Special hack for broken Linux with no working sendfile. If we
3820 * return EINTR we sent the header but not the rest of the data.
3821 * Fake this up by doing read/write calls.
3823 if (errno == EINTR) {
3824 /* Ensure we don't do this again. */
3825 set_use_sendfile(SNUM(conn), False);
3826 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3828 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3829 DEBUG(0,("send_file_readbraw: "
3830 "fake_sendfile failed for "
3834 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3839 DEBUG(0,("send_file_readbraw: sendfile failed for "
3840 "file %s (%s). Terminating\n",
3841 fsp_str_dbg(fsp), strerror(errno)));
3842 exit_server_cleanly("send_file_readbraw sendfile failed");
3843 } else if (sendfile_read == 0) {
3845 * Some sendfile implementations return 0 to indicate
3846 * that there was a short read, but nothing was
3847 * actually written to the socket. In this case,
3848 * fallback to the normal read path so the header gets
3849 * the correct byte count.
3851 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3852 "bytes falling back to the normal read: "
3853 "%s\n", fsp_str_dbg(fsp)));
3854 goto normal_readbraw;
3857 /* Deal with possible short send. */
3858 if (sendfile_read != 4+nread) {
3859 ret = sendfile_short_send(xconn, fsp,
3860 sendfile_read, 4, nread);
3870 outbuf = talloc_array(NULL, char, nread+4);
3872 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3873 (unsigned)(nread+4)));
3874 reply_readbraw_error(xconn);
3879 ret = read_file(fsp,outbuf+4,startpos,nread);
3880 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3889 _smb_setlen(outbuf,ret);
3890 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3891 int saved_errno = errno;
3893 * Try and give an error message saying what
3896 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3897 smbXsrv_connection_dbg(xconn),
3898 strerror(saved_errno)));
3899 errno = saved_errno;
3904 TALLOC_FREE(outbuf);
3907 /****************************************************************************
3908 Reply to a readbraw (core+ protocol).
3909 ****************************************************************************/
3911 void reply_readbraw(struct smb_request *req)
3913 connection_struct *conn = req->conn;
3914 struct smbXsrv_connection *xconn = req->xconn;
3915 ssize_t maxcount,mincount;
3919 struct lock_struct lock;
3923 START_PROFILE(SMBreadbraw);
3925 if (srv_is_signing_active(xconn) || req->encrypted) {
3926 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3927 "raw reads/writes are disallowed.");
3931 reply_readbraw_error(xconn);
3932 END_PROFILE(SMBreadbraw);
3936 if (xconn->smb1.echo_handler.trusted_fde) {
3937 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3938 "'async smb echo handler = yes'\n"));
3939 reply_readbraw_error(xconn);
3940 END_PROFILE(SMBreadbraw);
3945 * Special check if an oplock break has been issued
3946 * and the readraw request croses on the wire, we must
3947 * return a zero length response here.
3950 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3953 * We have to do a check_fsp by hand here, as
3954 * we must always return 4 zero bytes on error,
3960 conn != fsp->conn ||
3961 req->vuid != fsp->vuid ||
3962 fsp->fsp_flags.is_directory ||
3966 * fsp could be NULL here so use the value from the packet. JRA.
3968 DEBUG(3,("reply_readbraw: fnum %d not valid "
3970 (int)SVAL(req->vwv+0, 0)));
3971 reply_readbraw_error(xconn);
3972 END_PROFILE(SMBreadbraw);
3976 /* Do a "by hand" version of CHECK_READ. */
3977 if (!(fsp->fsp_flags.can_read ||
3978 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3979 (fsp->access_mask & FILE_EXECUTE)))) {
3980 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3981 (int)SVAL(req->vwv+0, 0)));
3982 reply_readbraw_error(xconn);
3983 END_PROFILE(SMBreadbraw);
3987 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3988 if(req->wct == 10) {
3990 * This is a large offset (64 bit) read.
3993 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3996 DEBUG(0,("reply_readbraw: negative 64 bit "
3997 "readraw offset (%.0f) !\n",
3998 (double)startpos ));
3999 reply_readbraw_error(xconn);
4000 END_PROFILE(SMBreadbraw);
4005 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4006 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4008 /* ensure we don't overrun the packet size */
4009 maxcount = MIN(65535,maxcount);
4011 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4012 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4015 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4016 reply_readbraw_error(xconn);
4017 END_PROFILE(SMBreadbraw);
4021 status = vfs_stat_fsp(fsp);
4022 if (NT_STATUS_IS_OK(status)) {
4023 size = fsp->fsp_name->st.st_ex_size;
4026 if (startpos >= size) {
4029 nread = MIN(maxcount,(size - startpos));
4032 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4033 if (nread < mincount)
4037 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4038 "min=%lu nread=%lu\n",
4039 fsp_fnum_dbg(fsp), (double)startpos,
4040 (unsigned long)maxcount,
4041 (unsigned long)mincount,
4042 (unsigned long)nread ) );
4044 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4046 DEBUG(5,("reply_readbraw finished\n"));
4048 END_PROFILE(SMBreadbraw);
4053 #define DBGC_CLASS DBGC_LOCKING
4055 /****************************************************************************
4056 Reply to a lockread (core+ protocol).
4057 ****************************************************************************/
4059 static void reply_lockread_locked(struct tevent_req *subreq);
4061 void reply_lockread(struct smb_request *req)
4063 struct tevent_req *subreq = NULL;
4064 connection_struct *conn = req->conn;
4066 struct smbd_lock_element *lck = NULL;
4068 START_PROFILE(SMBlockread);
4071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4072 END_PROFILE(SMBlockread);
4076 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4078 if (!check_fsp(conn, req, fsp)) {
4079 END_PROFILE(SMBlockread);
4083 if (!CHECK_READ(fsp,req)) {
4084 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4085 END_PROFILE(SMBlockread);
4089 lck = talloc(req, struct smbd_lock_element);
4091 reply_nterror(req, NT_STATUS_NO_MEMORY);
4092 END_PROFILE(SMBlockread);
4097 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4098 * protocol request that predates the read/write lock concept.
4099 * Thus instead of asking for a read lock here we need to ask
4100 * for a write lock. JRA.
4101 * Note that the requested lock size is unaffected by max_send.
4104 *lck = (struct smbd_lock_element) {
4105 .req_guid = smbd_request_guid(req, 0),
4106 .smblctx = req->smbpid,
4107 .brltype = WRITE_LOCK,
4108 .count = SVAL(req->vwv+1, 0),
4109 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4112 subreq = smbd_smb1_do_locks_send(
4118 false, /* large_offset */
4122 if (subreq == NULL) {
4123 reply_nterror(req, NT_STATUS_NO_MEMORY);
4124 END_PROFILE(SMBlockread);
4127 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4128 END_PROFILE(SMBlockread);
4131 static void reply_lockread_locked(struct tevent_req *subreq)
4133 struct smb_request *req = NULL;
4139 size_t numtoread, maxtoread;
4140 struct files_struct *fsp = NULL;
4143 START_PROFILE(SMBlockread);
4145 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4148 status = smbd_smb1_do_locks_recv(subreq);
4149 TALLOC_FREE(subreq);
4151 if (!NT_STATUS_IS_OK(status)) {
4152 reply_nterror(req, status);
4156 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4158 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4162 numtoread = SVAL(req->vwv+1, 0);
4163 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4166 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4168 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4170 if (numtoread > maxtoread) {
4171 DBG_WARNING("requested read size (%zu) is greater than "
4172 "maximum allowed (%zu/%d). "
4173 "Returning short read of maximum allowed for "
4174 "compatibility with Windows 2000.\n",
4177 req->xconn->smb1.sessions.max_send);
4178 numtoread = maxtoread;
4181 reply_outbuf(req, 5, numtoread + 3);
4183 data = smb_buf(req->outbuf) + 3;
4185 nread = read_file(fsp,data,startpos,numtoread);
4188 reply_nterror(req, map_nt_error_from_unix(errno));
4192 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4194 SSVAL(req->outbuf,smb_vwv0,nread);
4195 SSVAL(req->outbuf,smb_vwv5,nread+3);
4196 p = smb_buf(req->outbuf);
4197 SCVAL(p,0,0); /* pad byte. */
4200 DEBUG(3,("lockread %s num=%d nread=%d\n",
4201 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4204 ok = srv_send_smb(req->xconn,
4205 (char *)req->outbuf,
4208 IS_CONN_ENCRYPTED(req->conn),
4211 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4214 END_PROFILE(SMBlockread);
4219 #define DBGC_CLASS DBGC_ALL
4221 /****************************************************************************
4223 ****************************************************************************/
4225 void reply_read(struct smb_request *req)
4227 connection_struct *conn = req->conn;
4234 struct lock_struct lock;
4235 struct smbXsrv_connection *xconn = req->xconn;
4237 START_PROFILE(SMBread);
4240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4241 END_PROFILE(SMBread);
4245 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4247 if (!check_fsp(conn, req, fsp)) {
4248 END_PROFILE(SMBread);
4252 if (!CHECK_READ(fsp,req)) {
4253 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4254 END_PROFILE(SMBread);
4258 numtoread = SVAL(req->vwv+1, 0);
4259 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4262 * The requested read size cannot be greater than max_send. JRA.
4264 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4266 if (numtoread > maxtoread) {
4267 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4268 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4269 (unsigned int)numtoread, (unsigned int)maxtoread,
4270 (unsigned int)xconn->smb1.sessions.max_send));
4271 numtoread = maxtoread;
4274 reply_outbuf(req, 5, numtoread+3);
4276 data = smb_buf(req->outbuf) + 3;
4278 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4279 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4282 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4283 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4284 END_PROFILE(SMBread);
4289 nread = read_file(fsp,data,startpos,numtoread);
4292 reply_nterror(req, map_nt_error_from_unix(errno));
4296 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4298 SSVAL(req->outbuf,smb_vwv0,nread);
4299 SSVAL(req->outbuf,smb_vwv5,nread+3);
4300 SCVAL(smb_buf(req->outbuf),0,1);
4301 SSVAL(smb_buf(req->outbuf),1,nread);
4303 DEBUG(3, ("read %s num=%d nread=%d\n",
4304 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4307 END_PROFILE(SMBread);
4311 /****************************************************************************
4313 ****************************************************************************/
4315 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4319 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4322 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4324 SCVAL(outbuf,smb_vwv0,0xFF);
4325 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4326 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4327 SSVAL(outbuf,smb_vwv6,
4328 (smb_wct - 4) /* offset from smb header to wct */
4329 + 1 /* the wct field */
4330 + 12 * sizeof(uint16_t) /* vwv */
4331 + 2 /* the buflen field */
4332 + 1); /* padding byte */
4333 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4334 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4335 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4336 _smb_setlen_large(outbuf,
4337 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4341 /****************************************************************************
4342 Reply to a read and X - possibly using sendfile.
4343 ****************************************************************************/
4345 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4346 files_struct *fsp, off_t startpos,
4349 struct smbXsrv_connection *xconn = req->xconn;
4351 struct lock_struct lock;
4352 int saved_errno = 0;
4355 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4356 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4359 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4360 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4365 * We can only use sendfile on a non-chained packet
4366 * but we can use on a non-oplocked file. tridge proved this
4367 * on a train in Germany :-). JRA.
4370 if (!req_is_in_chain(req) &&
4372 (fsp->base_fsp == NULL) &&
4373 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4374 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4377 status = vfs_stat_fsp(fsp);
4378 if (!NT_STATUS_IS_OK(status)) {
4379 reply_nterror(req, status);
4383 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4384 (startpos > fsp->fsp_name->st.st_ex_size) ||
4385 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4387 * We already know that we would do a short read, so don't
4388 * try the sendfile() path.
4390 goto nosendfile_read;
4394 * Set up the packet header before send. We
4395 * assume here the sendfile will work (get the
4396 * correct amount of data).
4399 header = data_blob_const(headerbuf, sizeof(headerbuf));
4401 construct_reply_common_req(req, (char *)headerbuf);
4402 setup_readX_header((char *)headerbuf, smb_maxcnt);
4404 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4405 startpos, smb_maxcnt);
4407 saved_errno = errno;
4409 /* Returning ENOSYS means no data at all was sent.
4410 Do this as a normal read. */
4411 if (errno == ENOSYS) {
4416 * Special hack for broken Linux with no working sendfile. If we
4417 * return EINTR we sent the header but not the rest of the data.
4418 * Fake this up by doing read/write calls.
4421 if (errno == EINTR) {
4422 /* Ensure we don't do this again. */
4423 set_use_sendfile(SNUM(conn), False);
4424 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4425 nread = fake_sendfile(xconn, fsp, startpos,
4428 saved_errno = errno;
4429 DEBUG(0,("send_file_readX: "
4430 "fake_sendfile failed for "
4431 "file %s (%s) for client %s. "
4434 smbXsrv_connection_dbg(xconn),
4435 strerror(saved_errno)));
4436 errno = saved_errno;
4437 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4439 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4440 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4441 /* No outbuf here means successful sendfile. */
4445 DEBUG(0,("send_file_readX: sendfile failed for file "
4446 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4448 exit_server_cleanly("send_file_readX sendfile failed");
4449 } else if (nread == 0) {
4451 * Some sendfile implementations return 0 to indicate
4452 * that there was a short read, but nothing was
4453 * actually written to the socket. In this case,
4454 * fallback to the normal read path so the header gets
4455 * the correct byte count.
4457 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4458 "falling back to the normal read: %s\n",
4463 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4464 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4466 /* Deal with possible short send. */
4467 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4470 ret = sendfile_short_send(xconn, fsp, nread,
4471 sizeof(headerbuf), smb_maxcnt);
4474 r = "send_file_readX: sendfile_short_send failed";
4475 DEBUG(0,("%s for file %s (%s).\n",
4476 r, fsp_str_dbg(fsp), strerror(errno)));
4477 exit_server_cleanly(r);
4480 /* No outbuf here means successful sendfile. */
4481 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4482 SMB_PERFCOUNT_END(&req->pcd);
4488 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4489 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4492 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4493 (startpos > fsp->fsp_name->st.st_ex_size) ||
4494 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4496 * We already know that we would do a short
4497 * read, so don't try the sendfile() path.
4499 goto nosendfile_read;
4502 construct_reply_common_req(req, (char *)headerbuf);
4503 setup_readX_header((char *)headerbuf, smb_maxcnt);
4505 /* Send out the header. */
4506 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4508 if (ret != sizeof(headerbuf)) {
4509 saved_errno = errno;
4511 * Try and give an error message saying what
4514 DEBUG(0,("send_file_readX: write_data failed for file "
4515 "%s (%s) for client %s. Terminating\n",
4517 smbXsrv_connection_dbg(xconn),
4518 strerror(saved_errno)));
4519 errno = saved_errno;
4520 exit_server_cleanly("send_file_readX sendfile failed");
4522 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4524 saved_errno = errno;
4525 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4526 "%s (%s) for client %s. Terminating\n",
4528 smbXsrv_connection_dbg(xconn),
4529 strerror(saved_errno)));
4530 errno = saved_errno;
4531 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4538 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4539 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4540 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4542 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4543 startpos, smb_maxcnt);
4544 saved_errno = errno;
4547 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4551 setup_readX_header((char *)req->outbuf, nread);
4553 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4554 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4558 TALLOC_FREE(req->outbuf);
4562 /****************************************************************************
4563 Work out how much space we have for a read return.
4564 ****************************************************************************/
4566 static size_t calc_max_read_pdu(const struct smb_request *req)
4568 struct smbXsrv_connection *xconn = req->xconn;
4570 if (xconn->protocol < PROTOCOL_NT1) {
4571 return xconn->smb1.sessions.max_send;
4574 if (!lp_large_readwrite()) {
4575 return xconn->smb1.sessions.max_send;
4578 if (req_is_in_chain(req)) {
4579 return xconn->smb1.sessions.max_send;
4582 if (req->encrypted) {
4584 * Don't take encrypted traffic up to the
4585 * limit. There are padding considerations
4586 * that make that tricky.
4588 return xconn->smb1.sessions.max_send;
4591 if (srv_is_signing_active(xconn)) {
4595 if (!lp_unix_extensions()) {
4600 * We can do ultra-large POSIX reads.
4605 /****************************************************************************
4606 Calculate how big a read can be. Copes with all clients. It's always
4607 safe to return a short read - Windows does this.
4608 ****************************************************************************/
4610 static size_t calc_read_size(const struct smb_request *req,
4614 struct smbXsrv_connection *xconn = req->xconn;
4615 size_t max_pdu = calc_max_read_pdu(req);
4616 size_t total_size = 0;
4617 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4618 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4621 * Windows explicitly ignores upper size of 0xFFFF.
4622 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4623 * We must do the same as these will never fit even in
4624 * an extended size NetBIOS packet.
4626 if (upper_size == 0xFFFF) {
4630 if (xconn->protocol < PROTOCOL_NT1) {
4634 total_size = ((upper_size<<16) | lower_size);
4637 * LARGE_READX test shows it's always safe to return
4638 * a short read. Windows does so.
4640 return MIN(total_size, max_len);
4643 /****************************************************************************
4644 Reply to a read and X.
4645 ****************************************************************************/
4647 void reply_read_and_X(struct smb_request *req)
4649 connection_struct *conn = req->conn;
4654 bool big_readX = False;
4656 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4659 START_PROFILE(SMBreadX);
4661 if ((req->wct != 10) && (req->wct != 12)) {
4662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4666 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4667 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4668 smb_maxcnt = SVAL(req->vwv+5, 0);
4670 /* If it's an IPC, pass off the pipe handler. */
4672 reply_pipe_read_and_X(req);
4673 END_PROFILE(SMBreadX);
4677 if (!check_fsp(conn, req, fsp)) {
4678 END_PROFILE(SMBreadX);
4682 if (!CHECK_READ(fsp,req)) {
4683 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4684 END_PROFILE(SMBreadX);
4688 upper_size = SVAL(req->vwv+7, 0);
4689 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4690 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4692 * This is a heuristic to avoid keeping large
4693 * outgoing buffers around over long-lived aio
4699 if (req->wct == 12) {
4701 * This is a large offset (64 bit) read.
4703 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4708 NTSTATUS status = schedule_aio_read_and_X(conn,
4713 if (NT_STATUS_IS_OK(status)) {
4714 /* Read scheduled - we're done. */
4717 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4718 /* Real error - report to client. */
4719 END_PROFILE(SMBreadX);
4720 reply_nterror(req, status);
4723 /* NT_STATUS_RETRY - fall back to sync read. */
4726 smbd_lock_socket(req->xconn);
4727 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4728 smbd_unlock_socket(req->xconn);
4731 END_PROFILE(SMBreadX);
4735 /****************************************************************************
4736 Error replies to writebraw must have smb_wct == 1. Fix this up.
4737 ****************************************************************************/
4739 void error_to_writebrawerr(struct smb_request *req)
4741 uint8_t *old_outbuf = req->outbuf;
4743 reply_outbuf(req, 1, 0);
4745 memcpy(req->outbuf, old_outbuf, smb_size);
4746 TALLOC_FREE(old_outbuf);
4749 /****************************************************************************
4750 Read 4 bytes of a smb packet and return the smb length of the packet.
4751 Store the result in the buffer. This version of the function will
4752 never return a session keepalive (length of zero).
4753 Timeout is in milliseconds.
4754 ****************************************************************************/
4756 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4759 uint8_t msgtype = NBSSkeepalive;
4761 while (msgtype == NBSSkeepalive) {
4764 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4766 if (!NT_STATUS_IS_OK(status)) {
4767 char addr[INET6_ADDRSTRLEN];
4768 /* Try and give an error message
4769 * saying what client failed. */
4770 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4771 "client %s read error = %s.\n",
4772 get_peer_addr(fd,addr,sizeof(addr)),
4773 nt_errstr(status)));
4777 msgtype = CVAL(inbuf, 0);
4780 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4781 (unsigned long)len));
4783 return NT_STATUS_OK;
4786 /****************************************************************************
4787 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4788 ****************************************************************************/
4790 void reply_writebraw(struct smb_request *req)
4792 connection_struct *conn = req->conn;
4793 struct smbXsrv_connection *xconn = req->xconn;
4796 ssize_t total_written=0;
4797 size_t numtowrite=0;
4800 const char *data=NULL;
4803 struct lock_struct lock;
4806 START_PROFILE(SMBwritebraw);
4809 * If we ever reply with an error, it must have the SMB command
4810 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4813 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4815 if (srv_is_signing_active(xconn)) {
4816 END_PROFILE(SMBwritebraw);
4817 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4818 "raw reads/writes are disallowed.");
4821 if (req->wct < 12) {
4822 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4823 error_to_writebrawerr(req);
4824 END_PROFILE(SMBwritebraw);
4828 if (xconn->smb1.echo_handler.trusted_fde) {
4829 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4830 "'async smb echo handler = yes'\n"));
4831 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4832 error_to_writebrawerr(req);
4833 END_PROFILE(SMBwritebraw);
4837 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4838 if (!check_fsp(conn, req, fsp)) {
4839 error_to_writebrawerr(req);
4840 END_PROFILE(SMBwritebraw);
4844 if (!CHECK_WRITE(fsp)) {
4845 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4846 error_to_writebrawerr(req);
4847 END_PROFILE(SMBwritebraw);
4851 tcount = IVAL(req->vwv+1, 0);
4852 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4853 write_through = BITSETW(req->vwv+7,0);
4855 /* We have to deal with slightly different formats depending
4856 on whether we are using the core+ or lanman1.0 protocol */
4858 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4859 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4860 data = smb_buf_const(req->inbuf);
4862 numtowrite = SVAL(req->vwv+10, 0);
4863 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4866 /* Ensure we don't write bytes past the end of this packet. */
4868 * This already protects us against CVE-2017-12163.
4870 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4872 error_to_writebrawerr(req);
4873 END_PROFILE(SMBwritebraw);
4877 if (!fsp->print_file) {
4878 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4879 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4882 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4883 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4884 error_to_writebrawerr(req);
4885 END_PROFILE(SMBwritebraw);
4891 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4894 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4895 "wrote=%d sync=%d\n",
4896 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4897 (int)nwritten, (int)write_through));
4899 if (nwritten < (ssize_t)numtowrite) {
4900 reply_nterror(req, NT_STATUS_DISK_FULL);
4901 error_to_writebrawerr(req);
4905 total_written = nwritten;
4907 /* Allocate a buffer of 64k + length. */
4908 buf = talloc_array(NULL, char, 65540);
4910 reply_nterror(req, NT_STATUS_NO_MEMORY);
4911 error_to_writebrawerr(req);
4915 /* Return a SMBwritebraw message to the redirector to tell
4916 * it to send more bytes */
4918 memcpy(buf, req->inbuf, smb_size);
4919 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4920 SCVAL(buf,smb_com,SMBwritebraw);
4921 SSVALS(buf,smb_vwv0,0xFFFF);
4923 if (!srv_send_smb(req->xconn,
4925 false, 0, /* no signing */
4926 IS_CONN_ENCRYPTED(conn),
4928 exit_server_cleanly("reply_writebraw: srv_send_smb "
4932 /* Now read the raw data into the buffer and write it */
4933 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4935 if (!NT_STATUS_IS_OK(status)) {
4936 exit_server_cleanly("secondary writebraw failed");
4939 /* Set up outbuf to return the correct size */
4940 reply_outbuf(req, 1, 0);
4942 if (numtowrite != 0) {
4944 if (numtowrite > 0xFFFF) {
4945 DEBUG(0,("reply_writebraw: Oversize secondary write "
4946 "raw requested (%u). Terminating\n",
4947 (unsigned int)numtowrite ));
4948 exit_server_cleanly("secondary writebraw failed");
4951 if (tcount > nwritten+numtowrite) {
4952 DEBUG(3,("reply_writebraw: Client overestimated the "
4954 (int)tcount,(int)nwritten,(int)numtowrite));
4957 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4960 if (!NT_STATUS_IS_OK(status)) {
4961 /* Try and give an error message
4962 * saying what client failed. */
4963 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4964 "raw read failed (%s) for client %s. "
4965 "Terminating\n", nt_errstr(status),
4966 smbXsrv_connection_dbg(xconn)));
4967 exit_server_cleanly("secondary writebraw failed");
4971 * We are not vulnerable to CVE-2017-12163
4972 * here as we are guaranteed to have numtowrite
4973 * bytes available - we just read from the client.
4975 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4976 if (nwritten == -1) {
4978 reply_nterror(req, map_nt_error_from_unix(errno));
4979 error_to_writebrawerr(req);
4983 if (nwritten < (ssize_t)numtowrite) {
4984 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4985 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4989 total_written += nwritten;
4994 SSVAL(req->outbuf,smb_vwv0,total_written);
4996 status = sync_file(conn, fsp, write_through);
4997 if (!NT_STATUS_IS_OK(status)) {
4998 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4999 fsp_str_dbg(fsp), nt_errstr(status)));
5000 reply_nterror(req, status);
5001 error_to_writebrawerr(req);
5005 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5007 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5008 (int)total_written));
5010 /* We won't return a status if write through is not selected - this
5011 * follows what WfWg does */
5012 END_PROFILE(SMBwritebraw);
5014 if (!write_through && total_written==tcount) {
5016 #if RABBIT_PELLET_FIX
5018 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5019 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5022 if (!send_keepalive(xconn->transport.sock)) {
5023 exit_server_cleanly("reply_writebraw: send of "
5024 "keepalive failed");
5027 TALLOC_FREE(req->outbuf);
5032 END_PROFILE(SMBwritebraw);
5037 #define DBGC_CLASS DBGC_LOCKING
5039 /****************************************************************************
5040 Reply to a writeunlock (core+).
5041 ****************************************************************************/
5043 void reply_writeunlock(struct smb_request *req)
5045 connection_struct *conn = req->conn;
5046 ssize_t nwritten = -1;
5051 NTSTATUS status = NT_STATUS_OK;
5053 struct lock_struct lock;
5054 int saved_errno = 0;
5056 START_PROFILE(SMBwriteunlock);
5059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5060 END_PROFILE(SMBwriteunlock);
5064 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5066 if (!check_fsp(conn, req, fsp)) {
5067 END_PROFILE(SMBwriteunlock);
5071 if (!CHECK_WRITE(fsp)) {
5072 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5073 END_PROFILE(SMBwriteunlock);
5077 numtowrite = SVAL(req->vwv+1, 0);
5078 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5079 data = (const char *)req->buf + 3;
5082 * Ensure client isn't asking us to write more than
5083 * they sent. CVE-2017-12163.
5085 remaining = smbreq_bufrem(req, data);
5086 if (numtowrite > remaining) {
5087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5088 END_PROFILE(SMBwriteunlock);
5092 if (!fsp->print_file && numtowrite > 0) {
5093 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5094 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5097 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5098 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5099 END_PROFILE(SMBwriteunlock);
5104 /* The special X/Open SMB protocol handling of
5105 zero length writes is *NOT* done for
5107 if(numtowrite == 0) {
5110 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5111 saved_errno = errno;
5114 status = sync_file(conn, fsp, False /* write through */);
5115 if (!NT_STATUS_IS_OK(status)) {
5116 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5117 fsp_str_dbg(fsp), nt_errstr(status)));
5118 reply_nterror(req, status);
5123 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5127 if((nwritten < numtowrite) && (numtowrite != 0)) {
5128 reply_nterror(req, NT_STATUS_DISK_FULL);
5132 if (numtowrite && !fsp->print_file) {
5133 struct smbd_lock_element l = {
5134 .req_guid = smbd_request_guid(req, 0),
5135 .smblctx = req->smbpid,
5136 .brltype = UNLOCK_LOCK,
5138 .count = numtowrite,
5140 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5141 if (NT_STATUS_V(status)) {
5142 reply_nterror(req, status);
5147 reply_outbuf(req, 1, 0);
5149 SSVAL(req->outbuf,smb_vwv0,nwritten);
5151 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5152 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5155 END_PROFILE(SMBwriteunlock);
5160 #define DBGC_CLASS DBGC_ALL
5162 /****************************************************************************
5164 ****************************************************************************/
5166 void reply_write(struct smb_request *req)
5168 connection_struct *conn = req->conn;
5171 ssize_t nwritten = -1;
5175 struct lock_struct lock;
5177 int saved_errno = 0;
5179 START_PROFILE(SMBwrite);
5182 END_PROFILE(SMBwrite);
5183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5187 /* If it's an IPC, pass off the pipe handler. */
5189 reply_pipe_write(req);
5190 END_PROFILE(SMBwrite);
5194 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5196 if (!check_fsp(conn, req, fsp)) {
5197 END_PROFILE(SMBwrite);
5201 if (!CHECK_WRITE(fsp)) {
5202 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5203 END_PROFILE(SMBwrite);
5207 numtowrite = SVAL(req->vwv+1, 0);
5208 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5209 data = (const char *)req->buf + 3;
5212 * Ensure client isn't asking us to write more than
5213 * they sent. CVE-2017-12163.
5215 remaining = smbreq_bufrem(req, data);
5216 if (numtowrite > remaining) {
5217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5218 END_PROFILE(SMBwrite);
5222 if (!fsp->print_file) {
5223 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5224 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5227 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5228 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5229 END_PROFILE(SMBwrite);
5235 * X/Open SMB protocol says that if smb_vwv1 is
5236 * zero then the file size should be extended or
5237 * truncated to the size given in smb_vwv[2-3].
5240 if(numtowrite == 0) {
5242 * This is actually an allocate call, and set EOF. JRA.
5244 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5246 reply_nterror(req, NT_STATUS_DISK_FULL);
5249 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5251 reply_nterror(req, NT_STATUS_DISK_FULL);
5254 trigger_write_time_update_immediate(fsp);
5256 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5259 status = sync_file(conn, fsp, False);
5260 if (!NT_STATUS_IS_OK(status)) {
5261 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5262 fsp_str_dbg(fsp), nt_errstr(status)));
5263 reply_nterror(req, status);
5268 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5272 if((nwritten == 0) && (numtowrite != 0)) {
5273 reply_nterror(req, NT_STATUS_DISK_FULL);
5277 reply_outbuf(req, 1, 0);
5279 SSVAL(req->outbuf,smb_vwv0,nwritten);
5281 if (nwritten < (ssize_t)numtowrite) {
5282 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5283 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5286 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5289 END_PROFILE(SMBwrite);
5293 /****************************************************************************
5294 Ensure a buffer is a valid writeX for recvfile purposes.
5295 ****************************************************************************/
5297 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5298 (2*14) + /* word count (including bcc) */ \
5301 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5302 const uint8_t *inbuf)
5305 unsigned int doff = 0;
5306 size_t len = smb_len_large(inbuf);
5308 struct smbXsrv_open *op = NULL;
5309 struct files_struct *fsp = NULL;
5312 if (is_encrypted_packet(inbuf)) {
5313 /* Can't do this on encrypted
5318 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5322 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5323 CVAL(inbuf,smb_wct) != 14) {
5324 DEBUG(10,("is_valid_writeX_buffer: chained or "
5325 "invalid word length.\n"));
5329 fnum = SVAL(inbuf, smb_vwv2);
5330 status = smb1srv_open_lookup(xconn,
5334 if (!NT_STATUS_IS_OK(status)) {
5335 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5340 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5343 if (fsp->conn == NULL) {
5344 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5348 if (IS_IPC(fsp->conn)) {
5349 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5352 if (IS_PRINT(fsp->conn)) {
5353 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5356 if (fsp->base_fsp != NULL) {
5357 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5360 doff = SVAL(inbuf,smb_vwv11);
5362 numtowrite = SVAL(inbuf,smb_vwv10);
5364 if (len > doff && len - doff > 0xFFFF) {
5365 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5368 if (numtowrite == 0) {
5369 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5373 /* Ensure the sizes match up. */
5374 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5375 /* no pad byte...old smbclient :-( */
5376 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5378 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5382 if (len - doff != numtowrite) {
5383 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5384 "len = %u, doff = %u, numtowrite = %u\n",
5387 (unsigned int)numtowrite ));
5391 DEBUG(10,("is_valid_writeX_buffer: true "
5392 "len = %u, doff = %u, numtowrite = %u\n",
5395 (unsigned int)numtowrite ));
5400 /****************************************************************************
5401 Reply to a write and X.
5402 ****************************************************************************/
5404 void reply_write_and_X(struct smb_request *req)
5406 connection_struct *conn = req->conn;
5407 struct smbXsrv_connection *xconn = req->xconn;
5409 struct lock_struct lock;
5414 unsigned int smb_doff;
5415 unsigned int smblen;
5418 int saved_errno = 0;
5420 START_PROFILE(SMBwriteX);
5422 if ((req->wct != 12) && (req->wct != 14)) {
5423 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5427 numtowrite = SVAL(req->vwv+10, 0);
5428 smb_doff = SVAL(req->vwv+11, 0);
5429 smblen = smb_len(req->inbuf);
5431 if (req->unread_bytes > 0xFFFF ||
5432 (smblen > smb_doff &&
5433 smblen - smb_doff > 0xFFFF)) {
5434 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5437 if (req->unread_bytes) {
5438 /* Can't do a recvfile write on IPC$ */
5440 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5443 if (numtowrite != req->unread_bytes) {
5444 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5449 * This already protects us against CVE-2017-12163.
5451 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5452 smb_doff + numtowrite > smblen) {
5453 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5458 /* If it's an IPC, pass off the pipe handler. */
5460 if (req->unread_bytes) {
5461 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5464 reply_pipe_write_and_X(req);
5468 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5469 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5470 write_through = BITSETW(req->vwv+7,0);
5472 if (!check_fsp(conn, req, fsp)) {
5476 if (!CHECK_WRITE(fsp)) {
5477 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5481 data = smb_base(req->inbuf) + smb_doff;
5483 if(req->wct == 14) {
5485 * This is a large offset (64 bit) write.
5487 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5491 /* X/Open SMB protocol says that, unlike SMBwrite
5492 if the length is zero then NO truncation is
5493 done, just a write of zero. To truncate a file,
5496 if(numtowrite == 0) {
5499 if (req->unread_bytes == 0) {
5500 status = schedule_aio_write_and_X(conn,
5507 if (NT_STATUS_IS_OK(status)) {
5508 /* write scheduled - we're done. */
5511 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5512 /* Real error - report to client. */
5513 reply_nterror(req, status);
5516 /* NT_STATUS_RETRY - fall through to sync write. */
5519 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5520 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5523 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5524 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5528 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5529 saved_errno = errno;
5533 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5537 if((nwritten == 0) && (numtowrite != 0)) {
5538 reply_nterror(req, NT_STATUS_DISK_FULL);
5542 reply_outbuf(req, 6, 0);
5543 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5544 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5545 SSVAL(req->outbuf,smb_vwv2,nwritten);
5546 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5548 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5549 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5551 status = sync_file(conn, fsp, write_through);
5552 if (!NT_STATUS_IS_OK(status)) {
5553 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5554 fsp_str_dbg(fsp), nt_errstr(status)));
5555 reply_nterror(req, status);
5559 END_PROFILE(SMBwriteX);
5563 if (req->unread_bytes) {
5564 /* writeX failed. drain socket. */
5565 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5566 req->unread_bytes) {
5567 smb_panic("failed to drain pending bytes");
5569 req->unread_bytes = 0;
5572 END_PROFILE(SMBwriteX);
5576 /****************************************************************************
5578 ****************************************************************************/
5580 void reply_lseek(struct smb_request *req)
5582 connection_struct *conn = req->conn;
5589 START_PROFILE(SMBlseek);
5592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5593 END_PROFILE(SMBlseek);
5597 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5599 if (!check_fsp(conn, req, fsp)) {
5603 mode = SVAL(req->vwv+1, 0) & 3;
5604 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5605 startpos = (off_t)IVALS(req->vwv+2, 0);
5614 res = fsp->fh->pos + startpos;
5625 if (umode == SEEK_END) {
5626 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5627 if(errno == EINVAL) {
5628 off_t current_pos = startpos;
5630 status = vfs_stat_fsp(fsp);
5631 if (!NT_STATUS_IS_OK(status)) {
5632 reply_nterror(req, status);
5633 END_PROFILE(SMBlseek);
5637 current_pos += fsp->fsp_name->st.st_ex_size;
5639 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5644 reply_nterror(req, map_nt_error_from_unix(errno));
5645 END_PROFILE(SMBlseek);
5652 reply_outbuf(req, 2, 0);
5653 SIVAL(req->outbuf,smb_vwv0,res);
5655 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5656 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5658 END_PROFILE(SMBlseek);
5662 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5665 connection_struct *conn = talloc_get_type_abort(
5666 private_data, connection_struct);
5668 if (conn != fsp->conn) {
5671 if (fsp->fh->fd == -1) {
5674 sync_file(conn, fsp, True /* write through */);
5676 if (fsp->fsp_flags.modified) {
5677 trigger_write_time_update_immediate(fsp);
5683 /****************************************************************************
5685 ****************************************************************************/
5687 void reply_flush(struct smb_request *req)
5689 connection_struct *conn = req->conn;
5693 START_PROFILE(SMBflush);
5696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5700 fnum = SVAL(req->vwv+0, 0);
5701 fsp = file_fsp(req, fnum);
5703 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5708 files_forall(req->sconn, file_sync_one_fn, conn);
5710 NTSTATUS status = sync_file(conn, fsp, True);
5711 if (!NT_STATUS_IS_OK(status)) {
5712 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5713 fsp_str_dbg(fsp), nt_errstr(status)));
5714 reply_nterror(req, status);
5715 END_PROFILE(SMBflush);
5718 if (fsp->fsp_flags.modified) {
5719 trigger_write_time_update_immediate(fsp);
5723 reply_outbuf(req, 0, 0);
5725 DEBUG(3,("flush\n"));
5726 END_PROFILE(SMBflush);
5730 /****************************************************************************
5732 conn POINTER CAN BE NULL HERE !
5733 ****************************************************************************/
5735 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5736 static void reply_exit_done(struct tevent_req *req);
5738 void reply_exit(struct smb_request *smb1req)
5740 struct tevent_req *req;
5743 * Don't setup the profile charge here, take
5744 * it in reply_exit_done(). Not strictly correct
5745 * but better than the other SMB1 async
5746 * code that double-charges at the moment.
5748 req = reply_exit_send(smb1req);
5750 /* Not going async, profile here. */
5751 START_PROFILE(SMBexit);
5752 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5753 END_PROFILE(SMBexit);
5757 /* We're async. This will complete later. */
5758 tevent_req_set_callback(req, reply_exit_done, smb1req);
5762 struct reply_exit_state {
5763 struct tevent_queue *wait_queue;
5766 static void reply_exit_wait_done(struct tevent_req *subreq);
5768 /****************************************************************************
5770 Note, on failure here we deallocate and return NULL to allow the caller to
5771 SMB1 return an error of ERRnomem immediately.
5772 ****************************************************************************/
5774 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5776 struct tevent_req *req;
5777 struct reply_exit_state *state;
5778 struct tevent_req *subreq;
5780 struct smbd_server_connection *sconn = smb1req->sconn;
5782 req = tevent_req_create(smb1req, &state,
5783 struct reply_exit_state);
5787 state->wait_queue = tevent_queue_create(state,
5788 "reply_exit_wait_queue");
5789 if (tevent_req_nomem(state->wait_queue, req)) {
5794 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5795 if (fsp->file_pid != smb1req->smbpid) {
5798 if (fsp->vuid != smb1req->vuid) {
5802 * Flag the file as close in progress.
5803 * This will prevent any more IO being
5806 fsp->fsp_flags.closing = true;
5808 if (fsp->num_aio_requests > 0) {
5810 * Now wait until all aio requests on this fsp are
5813 * We don't set a callback, as we just want to block the
5814 * wait queue and the talloc_free() of fsp->aio_request
5815 * will remove the item from the wait queue.
5817 subreq = tevent_queue_wait_send(fsp->aio_requests,
5820 if (tevent_req_nomem(subreq, req)) {
5828 * Now we add our own waiter to the end of the queue,
5829 * this way we get notified when all pending requests are finished
5830 * and reply to the outstanding SMB1 request.
5832 subreq = tevent_queue_wait_send(state,
5835 if (tevent_req_nomem(subreq, req)) {
5841 * We're really going async - move the SMB1 request from
5842 * a talloc stackframe above us to the conn talloc-context.
5843 * We need this to stick around until the wait_done
5844 * callback is invoked.
5846 smb1req = talloc_move(sconn, &smb1req);
5848 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5853 static void reply_exit_wait_done(struct tevent_req *subreq)
5855 struct tevent_req *req = tevent_req_callback_data(
5856 subreq, struct tevent_req);
5858 tevent_queue_wait_recv(subreq);
5859 TALLOC_FREE(subreq);
5860 tevent_req_done(req);
5863 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5865 return tevent_req_simple_recv_ntstatus(req);
5868 static void reply_exit_done(struct tevent_req *req)
5870 struct smb_request *smb1req = tevent_req_callback_data(
5871 req, struct smb_request);
5872 struct smbd_server_connection *sconn = smb1req->sconn;
5873 struct smbXsrv_connection *xconn = smb1req->xconn;
5874 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5875 struct smbXsrv_session *session = NULL;
5876 files_struct *fsp, *next;
5880 * Take the profile charge here. Not strictly
5881 * correct but better than the other SMB1 async
5882 * code that double-charges at the moment.
5884 START_PROFILE(SMBexit);
5886 status = reply_exit_recv(req);
5888 if (!NT_STATUS_IS_OK(status)) {
5889 TALLOC_FREE(smb1req);
5890 END_PROFILE(SMBexit);
5891 exit_server(__location__ ": reply_exit_recv failed");
5896 * Ensure the session is still valid.
5898 status = smb1srv_session_lookup(xconn,
5902 if (!NT_STATUS_IS_OK(status)) {
5903 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5904 smb_request_done(smb1req);
5905 END_PROFILE(SMBexit);
5909 * Ensure the vuid is still valid - no one
5910 * called reply_ulogoffX() in the meantime.
5911 * reply_exit() doesn't have AS_USER set, so
5912 * use set_current_user_info() directly.
5913 * This is the same logic as in switch_message().
5915 if (session->global->auth_session_info != NULL) {
5916 set_current_user_info(
5917 session->global->auth_session_info->unix_info->sanitized_username,
5918 session->global->auth_session_info->unix_info->unix_name,
5919 session->global->auth_session_info->info->domain_name);
5922 /* No more aio - do the actual closes. */
5923 for (fsp = sconn->files; fsp; fsp = next) {
5927 if (fsp->file_pid != smb1req->smbpid) {
5930 if (fsp->vuid != smb1req->vuid) {
5933 if (!fsp->fsp_flags.closing) {
5938 * reply_exit() has the DO_CHDIR flag set.
5940 ok = chdir_current_service(fsp->conn);
5942 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5943 smb_request_done(smb1req);
5944 END_PROFILE(SMBexit);
5946 close_file(NULL, fsp, SHUTDOWN_CLOSE);
5949 reply_outbuf(smb1req, 0, 0);
5951 * The following call is needed to push the
5952 * reply data back out the socket after async
5953 * return. Plus it frees smb1req.
5955 smb_request_done(smb1req);
5956 DBG_INFO("reply_exit complete\n");
5957 END_PROFILE(SMBexit);
5961 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5963 static void reply_close_done(struct tevent_req *req);
5965 void reply_close(struct smb_request *smb1req)
5967 connection_struct *conn = smb1req->conn;
5968 NTSTATUS status = NT_STATUS_OK;
5969 files_struct *fsp = NULL;
5970 START_PROFILE(SMBclose);
5972 if (smb1req->wct < 3) {
5973 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5974 END_PROFILE(SMBclose);
5978 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5981 * We can only use check_fsp if we know it's not a directory.
5984 if (!check_fsp_open(conn, smb1req, fsp)) {
5985 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
5986 END_PROFILE(SMBclose);
5990 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5991 fsp->fsp_flags.is_directory ?
5992 "directory" : "file",
5993 fsp->fh->fd, fsp_fnum_dbg(fsp),
5994 conn->num_files_open);
5996 if (!fsp->fsp_flags.is_directory) {
6000 * Take care of any time sent in the close.
6003 t = srv_make_unix_date3(smb1req->vwv+1);
6004 set_close_write_time(fsp, time_t_to_full_timespec(t));
6007 if (fsp->num_aio_requests != 0) {
6008 struct tevent_req *req;
6010 req = reply_close_send(smb1req, fsp);
6012 status = NT_STATUS_NO_MEMORY;
6015 /* We're async. This will complete later. */
6016 tevent_req_set_callback(req, reply_close_done, smb1req);
6017 END_PROFILE(SMBclose);
6022 * close_file() returns the unix errno if an error was detected on
6023 * close - normally this is due to a disk full error. If not then it
6024 * was probably an I/O error.
6027 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6029 if (!NT_STATUS_IS_OK(status)) {
6030 reply_nterror(smb1req, status);
6031 END_PROFILE(SMBclose);
6035 reply_outbuf(smb1req, 0, 0);
6036 END_PROFILE(SMBclose);
6040 struct reply_close_state {
6042 struct tevent_queue *wait_queue;
6045 static void reply_close_wait_done(struct tevent_req *subreq);
6047 /****************************************************************************
6049 Note, on failure here we deallocate and return NULL to allow the caller to
6050 SMB1 return an error of ERRnomem immediately.
6051 ****************************************************************************/
6053 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6056 struct tevent_req *req;
6057 struct reply_close_state *state;
6058 struct tevent_req *subreq;
6059 struct smbd_server_connection *sconn = smb1req->sconn;
6061 req = tevent_req_create(smb1req, &state,
6062 struct reply_close_state);
6066 state->wait_queue = tevent_queue_create(state,
6067 "reply_close_wait_queue");
6068 if (tevent_req_nomem(state->wait_queue, req)) {
6074 * Flag the file as close in progress.
6075 * This will prevent any more IO being
6078 fsp->fsp_flags.closing = true;
6081 * Now wait until all aio requests on this fsp are
6084 * We don't set a callback, as we just want to block the
6085 * wait queue and the talloc_free() of fsp->aio_request
6086 * will remove the item from the wait queue.
6088 subreq = tevent_queue_wait_send(fsp->aio_requests,
6091 if (tevent_req_nomem(subreq, req)) {
6097 * Now we add our own waiter to the end of the queue,
6098 * this way we get notified when all pending requests are finished
6099 * and reply to the outstanding SMB1 request.
6101 subreq = tevent_queue_wait_send(state,
6104 if (tevent_req_nomem(subreq, req)) {
6110 * We're really going async - move the SMB1 request from
6111 * a talloc stackframe above us to the conn talloc-context.
6112 * We need this to stick around until the wait_done
6113 * callback is invoked.
6115 smb1req = talloc_move(sconn, &smb1req);
6117 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6122 static void reply_close_wait_done(struct tevent_req *subreq)
6124 struct tevent_req *req = tevent_req_callback_data(
6125 subreq, struct tevent_req);
6127 tevent_queue_wait_recv(subreq);
6128 TALLOC_FREE(subreq);
6129 tevent_req_done(req);
6132 static NTSTATUS reply_close_recv(struct tevent_req *req)
6134 return tevent_req_simple_recv_ntstatus(req);
6137 static void reply_close_done(struct tevent_req *req)
6139 struct smb_request *smb1req = tevent_req_callback_data(
6140 req, struct smb_request);
6141 struct reply_close_state *state = tevent_req_data(req,
6142 struct reply_close_state);
6145 status = reply_close_recv(req);
6147 if (!NT_STATUS_IS_OK(status)) {
6148 TALLOC_FREE(smb1req);
6149 exit_server(__location__ ": reply_close_recv failed");
6153 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6154 if (NT_STATUS_IS_OK(status)) {
6155 reply_outbuf(smb1req, 0, 0);
6157 reply_nterror(smb1req, status);
6160 * The following call is needed to push the
6161 * reply data back out the socket after async
6162 * return. Plus it frees smb1req.
6164 smb_request_done(smb1req);
6167 /****************************************************************************
6168 Reply to a writeclose (Core+ protocol).
6169 ****************************************************************************/
6171 void reply_writeclose(struct smb_request *req)
6173 connection_struct *conn = req->conn;
6176 ssize_t nwritten = -1;
6177 NTSTATUS close_status = NT_STATUS_OK;
6180 struct timespec mtime;
6182 struct lock_struct lock;
6184 START_PROFILE(SMBwriteclose);
6187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6188 END_PROFILE(SMBwriteclose);
6192 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6194 if (!check_fsp(conn, req, fsp)) {
6195 END_PROFILE(SMBwriteclose);
6198 if (!CHECK_WRITE(fsp)) {
6199 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6200 END_PROFILE(SMBwriteclose);
6204 numtowrite = SVAL(req->vwv+1, 0);
6205 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6206 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6207 data = (const char *)req->buf + 1;
6210 * Ensure client isn't asking us to write more than
6211 * they sent. CVE-2017-12163.
6213 remaining = smbreq_bufrem(req, data);
6214 if (numtowrite > remaining) {
6215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6216 END_PROFILE(SMBwriteclose);
6220 if (fsp->print_file == NULL) {
6221 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6222 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6225 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6226 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6227 END_PROFILE(SMBwriteclose);
6232 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6234 set_close_write_time(fsp, mtime);
6237 * More insanity. W2K only closes the file if writelen > 0.
6241 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6242 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6243 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6246 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6247 "file %s\n", fsp_str_dbg(fsp)));
6248 close_status = close_file(req, fsp, NORMAL_CLOSE);
6252 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6253 reply_nterror(req, NT_STATUS_DISK_FULL);
6257 if(!NT_STATUS_IS_OK(close_status)) {
6258 reply_nterror(req, close_status);
6262 reply_outbuf(req, 1, 0);
6264 SSVAL(req->outbuf,smb_vwv0,nwritten);
6268 END_PROFILE(SMBwriteclose);
6273 #define DBGC_CLASS DBGC_LOCKING
6275 /****************************************************************************
6277 ****************************************************************************/
6279 static void reply_lock_done(struct tevent_req *subreq);
6281 void reply_lock(struct smb_request *req)
6283 struct tevent_req *subreq = NULL;
6284 connection_struct *conn = req->conn;
6286 struct smbd_lock_element *lck = NULL;
6288 START_PROFILE(SMBlock);
6291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6292 END_PROFILE(SMBlock);
6296 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6298 if (!check_fsp(conn, req, fsp)) {
6299 END_PROFILE(SMBlock);
6303 lck = talloc(req, struct smbd_lock_element);
6305 reply_nterror(req, NT_STATUS_NO_MEMORY);
6306 END_PROFILE(SMBlock);
6310 *lck = (struct smbd_lock_element) {
6311 .req_guid = smbd_request_guid(req, 0),
6312 .smblctx = req->smbpid,
6313 .brltype = WRITE_LOCK,
6314 .count = IVAL(req->vwv+1, 0),
6315 .offset = IVAL(req->vwv+3, 0),
6318 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6324 subreq = smbd_smb1_do_locks_send(
6330 false, /* large_offset */
6334 if (subreq == NULL) {
6335 reply_nterror(req, NT_STATUS_NO_MEMORY);
6336 END_PROFILE(SMBlock);
6339 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6340 END_PROFILE(SMBlock);
6343 static void reply_lock_done(struct tevent_req *subreq)
6345 struct smb_request *req = NULL;
6349 START_PROFILE(SMBlock);
6351 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6354 status = smbd_smb1_do_locks_recv(subreq);
6355 TALLOC_FREE(subreq);
6357 if (NT_STATUS_IS_OK(status)) {
6358 reply_outbuf(req, 0, 0);
6360 reply_nterror(req, status);
6363 ok = srv_send_smb(req->xconn,
6364 (char *)req->outbuf,
6367 IS_CONN_ENCRYPTED(req->conn),
6370 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6373 END_PROFILE(SMBlock);
6376 /****************************************************************************
6378 ****************************************************************************/
6380 void reply_unlock(struct smb_request *req)
6382 connection_struct *conn = req->conn;
6385 struct smbd_lock_element lck;
6387 START_PROFILE(SMBunlock);
6390 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6391 END_PROFILE(SMBunlock);
6395 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6397 if (!check_fsp(conn, req, fsp)) {
6398 END_PROFILE(SMBunlock);
6402 lck = (struct smbd_lock_element) {
6403 .req_guid = smbd_request_guid(req, 0),
6404 .smblctx = req->smbpid,
6405 .brltype = UNLOCK_LOCK,
6406 .offset = IVAL(req->vwv+3, 0),
6407 .count = IVAL(req->vwv+1, 0),
6410 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6412 if (!NT_STATUS_IS_OK(status)) {
6413 reply_nterror(req, status);
6414 END_PROFILE(SMBunlock);
6418 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6424 reply_outbuf(req, 0, 0);
6426 END_PROFILE(SMBunlock);
6431 #define DBGC_CLASS DBGC_ALL
6433 /****************************************************************************
6435 conn POINTER CAN BE NULL HERE !
6436 ****************************************************************************/
6438 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6439 static void reply_tdis_done(struct tevent_req *req);
6441 void reply_tdis(struct smb_request *smb1req)
6443 connection_struct *conn = smb1req->conn;
6444 struct tevent_req *req;
6447 * Don't setup the profile charge here, take
6448 * it in reply_tdis_done(). Not strictly correct
6449 * but better than the other SMB1 async
6450 * code that double-charges at the moment.
6454 /* Not going async, profile here. */
6455 START_PROFILE(SMBtdis);
6456 DBG_INFO("Invalid connection in tdis\n");
6457 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6458 END_PROFILE(SMBtdis);
6462 req = reply_tdis_send(smb1req);
6464 /* Not going async, profile here. */
6465 START_PROFILE(SMBtdis);
6466 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6467 END_PROFILE(SMBtdis);
6470 /* We're async. This will complete later. */
6471 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6475 struct reply_tdis_state {
6476 struct tevent_queue *wait_queue;
6479 static void reply_tdis_wait_done(struct tevent_req *subreq);
6481 /****************************************************************************
6483 Note, on failure here we deallocate and return NULL to allow the caller to
6484 SMB1 return an error of ERRnomem immediately.
6485 ****************************************************************************/
6487 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6489 struct tevent_req *req;
6490 struct reply_tdis_state *state;
6491 struct tevent_req *subreq;
6492 connection_struct *conn = smb1req->conn;
6495 req = tevent_req_create(smb1req, &state,
6496 struct reply_tdis_state);
6500 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6501 if (tevent_req_nomem(state->wait_queue, req)) {
6507 * Make sure that no new request will be able to use this tcon.
6508 * This ensures that once all outstanding fsp->aio_requests
6509 * on this tcon are done, we are safe to close it.
6511 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6513 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6514 if (fsp->conn != conn) {
6518 * Flag the file as close in progress.
6519 * This will prevent any more IO being
6520 * done on it. Not strictly needed, but
6521 * doesn't hurt to flag it as closing.
6523 fsp->fsp_flags.closing = true;
6525 if (fsp->num_aio_requests > 0) {
6527 * Now wait until all aio requests on this fsp are
6530 * We don't set a callback, as we just want to block the
6531 * wait queue and the talloc_free() of fsp->aio_request
6532 * will remove the item from the wait queue.
6534 subreq = tevent_queue_wait_send(fsp->aio_requests,
6535 conn->sconn->ev_ctx,
6537 if (tevent_req_nomem(subreq, req)) {
6545 * Now we add our own waiter to the end of the queue,
6546 * this way we get notified when all pending requests are finished
6547 * and reply to the outstanding SMB1 request.
6549 subreq = tevent_queue_wait_send(state,
6550 conn->sconn->ev_ctx,
6552 if (tevent_req_nomem(subreq, req)) {
6558 * We're really going async - move the SMB1 request from
6559 * a talloc stackframe above us to the sconn talloc-context.
6560 * We need this to stick around until the wait_done
6561 * callback is invoked.
6563 smb1req = talloc_move(smb1req->sconn, &smb1req);
6565 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6570 static void reply_tdis_wait_done(struct tevent_req *subreq)
6572 struct tevent_req *req = tevent_req_callback_data(
6573 subreq, struct tevent_req);
6575 tevent_queue_wait_recv(subreq);
6576 TALLOC_FREE(subreq);
6577 tevent_req_done(req);
6580 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6582 return tevent_req_simple_recv_ntstatus(req);
6585 static void reply_tdis_done(struct tevent_req *req)
6587 struct smb_request *smb1req = tevent_req_callback_data(
6588 req, struct smb_request);
6590 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6594 * Take the profile charge here. Not strictly
6595 * correct but better than the other SMB1 async
6596 * code that double-charges at the moment.
6598 START_PROFILE(SMBtdis);
6600 status = reply_tdis_recv(req);
6602 if (!NT_STATUS_IS_OK(status)) {
6603 TALLOC_FREE(smb1req);
6604 END_PROFILE(SMBtdis);
6605 exit_server(__location__ ": reply_tdis_recv failed");
6610 * As we've been awoken, we may have changed
6611 * directory in the meantime.
6612 * reply_tdis() has the DO_CHDIR flag set.
6614 ok = chdir_current_service(smb1req->conn);
6616 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6617 smb_request_done(smb1req);
6618 END_PROFILE(SMBtdis);
6621 status = smbXsrv_tcon_disconnect(tcon,
6623 if (!NT_STATUS_IS_OK(status)) {
6624 TALLOC_FREE(smb1req);
6625 END_PROFILE(SMBtdis);
6626 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6630 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6631 smb1req->conn = NULL;
6635 reply_outbuf(smb1req, 0, 0);
6637 * The following call is needed to push the
6638 * reply data back out the socket after async
6639 * return. Plus it frees smb1req.
6641 smb_request_done(smb1req);
6642 END_PROFILE(SMBtdis);
6645 /****************************************************************************
6647 conn POINTER CAN BE NULL HERE !
6648 ****************************************************************************/
6650 void reply_echo(struct smb_request *req)
6652 connection_struct *conn = req->conn;
6653 struct smb_perfcount_data local_pcd;
6654 struct smb_perfcount_data *cur_pcd;
6658 START_PROFILE(SMBecho);
6660 smb_init_perfcount_data(&local_pcd);
6663 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6664 END_PROFILE(SMBecho);
6668 smb_reverb = SVAL(req->vwv+0, 0);
6670 reply_outbuf(req, 1, req->buflen);
6672 /* copy any incoming data back out */
6673 if (req->buflen > 0) {
6674 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6677 if (smb_reverb > 100) {
6678 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6682 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6684 /* this makes sure we catch the request pcd */
6685 if (seq_num == smb_reverb) {
6686 cur_pcd = &req->pcd;
6688 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6689 cur_pcd = &local_pcd;
6692 SSVAL(req->outbuf,smb_vwv0,seq_num);
6694 show_msg((char *)req->outbuf);
6695 if (!srv_send_smb(req->xconn,
6696 (char *)req->outbuf,
6697 true, req->seqnum+1,
6698 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6700 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6703 DEBUG(3,("echo %d times\n", smb_reverb));
6705 TALLOC_FREE(req->outbuf);
6707 END_PROFILE(SMBecho);
6711 /****************************************************************************
6712 Reply to a printopen.
6713 ****************************************************************************/
6715 void reply_printopen(struct smb_request *req)
6717 connection_struct *conn = req->conn;
6721 START_PROFILE(SMBsplopen);
6724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6725 END_PROFILE(SMBsplopen);
6729 if (!CAN_PRINT(conn)) {
6730 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6731 END_PROFILE(SMBsplopen);
6735 status = file_new(req, conn, &fsp);
6736 if(!NT_STATUS_IS_OK(status)) {
6737 reply_nterror(req, status);
6738 END_PROFILE(SMBsplopen);
6742 /* Open for exclusive use, write only. */
6743 status = print_spool_open(fsp, NULL, req->vuid);
6745 if (!NT_STATUS_IS_OK(status)) {
6746 file_free(req, fsp);
6747 reply_nterror(req, status);
6748 END_PROFILE(SMBsplopen);
6752 reply_outbuf(req, 1, 0);
6753 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6755 DEBUG(3,("openprint fd=%d %s\n",
6756 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6758 END_PROFILE(SMBsplopen);
6762 /****************************************************************************
6763 Reply to a printclose.
6764 ****************************************************************************/
6766 void reply_printclose(struct smb_request *req)
6768 connection_struct *conn = req->conn;
6772 START_PROFILE(SMBsplclose);
6775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6776 END_PROFILE(SMBsplclose);
6780 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6782 if (!check_fsp(conn, req, fsp)) {
6783 END_PROFILE(SMBsplclose);
6787 if (!CAN_PRINT(conn)) {
6788 reply_force_doserror(req, ERRSRV, ERRerror);
6789 END_PROFILE(SMBsplclose);
6793 DEBUG(3,("printclose fd=%d %s\n",
6794 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6796 status = close_file(req, fsp, NORMAL_CLOSE);
6798 if(!NT_STATUS_IS_OK(status)) {
6799 reply_nterror(req, status);
6800 END_PROFILE(SMBsplclose);
6804 reply_outbuf(req, 0, 0);
6806 END_PROFILE(SMBsplclose);
6810 /****************************************************************************
6811 Reply to a printqueue.
6812 ****************************************************************************/
6814 void reply_printqueue(struct smb_request *req)
6816 const struct loadparm_substitution *lp_sub =
6817 loadparm_s3_global_substitution();
6818 connection_struct *conn = req->conn;
6822 START_PROFILE(SMBsplretq);
6825 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6826 END_PROFILE(SMBsplretq);
6830 max_count = SVAL(req->vwv+0, 0);
6831 start_index = SVAL(req->vwv+1, 0);
6833 /* we used to allow the client to get the cnum wrong, but that
6834 is really quite gross and only worked when there was only
6835 one printer - I think we should now only accept it if they
6836 get it right (tridge) */
6837 if (!CAN_PRINT(conn)) {
6838 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6839 END_PROFILE(SMBsplretq);
6843 reply_outbuf(req, 2, 3);
6844 SSVAL(req->outbuf,smb_vwv0,0);
6845 SSVAL(req->outbuf,smb_vwv1,0);
6846 SCVAL(smb_buf(req->outbuf),0,1);
6847 SSVAL(smb_buf(req->outbuf),1,0);
6849 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6850 start_index, max_count));
6853 TALLOC_CTX *mem_ctx = talloc_tos();
6856 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6857 struct rpc_pipe_client *cli = NULL;
6858 struct dcerpc_binding_handle *b = NULL;
6859 struct policy_handle handle;
6860 struct spoolss_DevmodeContainer devmode_ctr;
6861 union spoolss_JobInfo *info;
6863 uint32_t num_to_get;
6867 ZERO_STRUCT(handle);
6869 status = rpc_pipe_open_interface(mem_ctx,
6872 conn->sconn->remote_address,
6873 conn->sconn->local_address,
6874 conn->sconn->msg_ctx,
6876 if (!NT_STATUS_IS_OK(status)) {
6877 DEBUG(0, ("reply_printqueue: "
6878 "could not connect to spoolss: %s\n",
6879 nt_errstr(status)));
6880 reply_nterror(req, status);
6883 b = cli->binding_handle;
6885 ZERO_STRUCT(devmode_ctr);
6887 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6890 SEC_FLAG_MAXIMUM_ALLOWED,
6893 if (!NT_STATUS_IS_OK(status)) {
6894 reply_nterror(req, status);
6897 if (!W_ERROR_IS_OK(werr)) {
6898 reply_nterror(req, werror_to_ntstatus(werr));
6902 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6910 if (!W_ERROR_IS_OK(werr)) {
6911 reply_nterror(req, werror_to_ntstatus(werr));
6915 if (max_count > 0) {
6916 first = start_index;
6918 first = start_index + max_count + 1;
6921 if (first >= count) {
6924 num_to_get = first + MIN(ABS(max_count), count - first);
6927 for (i = first; i < num_to_get; i++) {
6930 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6933 uint16_t qrapjobid = pjobid_to_rap(sharename,
6934 info[i].info2.job_id);
6936 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6942 srv_put_dos_date2(p, 0, qtime);
6943 SCVAL(p, 4, qstatus);
6944 SSVAL(p, 5, qrapjobid);
6945 SIVAL(p, 7, info[i].info2.size);
6947 status = srvstr_push(blob, req->flags2, p+12,
6948 info[i].info2.notify_name, 16, STR_ASCII, &len);
6949 if (!NT_STATUS_IS_OK(status)) {
6950 reply_nterror(req, status);
6953 if (message_push_blob(
6956 blob, sizeof(blob))) == -1) {
6957 reply_nterror(req, NT_STATUS_NO_MEMORY);
6963 SSVAL(req->outbuf,smb_vwv0,count);
6964 SSVAL(req->outbuf,smb_vwv1,
6965 (max_count>0?first+count:first-1));
6966 SCVAL(smb_buf(req->outbuf),0,1);
6967 SSVAL(smb_buf(req->outbuf),1,28*count);
6971 DEBUG(3, ("%u entries returned in queue\n",
6975 if (b && is_valid_policy_hnd(&handle)) {
6976 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6981 END_PROFILE(SMBsplretq);
6985 /****************************************************************************
6986 Reply to a printwrite.
6987 ****************************************************************************/
6989 void reply_printwrite(struct smb_request *req)
6991 connection_struct *conn = req->conn;
6996 START_PROFILE(SMBsplwr);
6999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7000 END_PROFILE(SMBsplwr);
7004 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7006 if (!check_fsp(conn, req, fsp)) {
7007 END_PROFILE(SMBsplwr);
7011 if (!fsp->print_file) {
7012 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7013 END_PROFILE(SMBsplwr);
7017 if (!CHECK_WRITE(fsp)) {
7018 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7019 END_PROFILE(SMBsplwr);
7023 numtowrite = SVAL(req->buf, 1);
7026 * This already protects us against CVE-2017-12163.
7028 if (req->buflen < numtowrite + 3) {
7029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7030 END_PROFILE(SMBsplwr);
7034 data = (const char *)req->buf + 3;
7036 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7037 reply_nterror(req, map_nt_error_from_unix(errno));
7038 END_PROFILE(SMBsplwr);
7042 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7044 END_PROFILE(SMBsplwr);
7048 /****************************************************************************
7050 ****************************************************************************/
7052 void reply_mkdir(struct smb_request *req)
7054 connection_struct *conn = req->conn;
7055 struct smb_filename *smb_dname = NULL;
7056 char *directory = NULL;
7059 TALLOC_CTX *ctx = talloc_tos();
7061 START_PROFILE(SMBmkdir);
7063 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7064 STR_TERMINATE, &status);
7065 if (!NT_STATUS_IS_OK(status)) {
7066 reply_nterror(req, status);
7070 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7071 status = filename_convert(ctx, conn,
7076 if (!NT_STATUS_IS_OK(status)) {
7077 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7078 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7079 ERRSRV, ERRbadpath);
7082 reply_nterror(req, status);
7086 status = create_directory(conn, req, smb_dname);
7088 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7090 if (!NT_STATUS_IS_OK(status)) {
7092 if (!use_nt_status()
7093 && NT_STATUS_EQUAL(status,
7094 NT_STATUS_OBJECT_NAME_COLLISION)) {
7096 * Yes, in the DOS error code case we get a
7097 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7098 * samba4 torture test.
7100 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7103 reply_nterror(req, status);
7107 reply_outbuf(req, 0, 0);
7109 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7111 TALLOC_FREE(smb_dname);
7112 END_PROFILE(SMBmkdir);
7116 /****************************************************************************
7118 ****************************************************************************/
7120 void reply_rmdir(struct smb_request *req)
7122 connection_struct *conn = req->conn;
7123 struct smb_filename *smb_dname = NULL;
7124 char *directory = NULL;
7126 TALLOC_CTX *ctx = talloc_tos();
7127 files_struct *fsp = NULL;
7129 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7131 START_PROFILE(SMBrmdir);
7133 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7134 STR_TERMINATE, &status);
7135 if (!NT_STATUS_IS_OK(status)) {
7136 reply_nterror(req, status);
7140 status = filename_convert(ctx, conn,
7145 if (!NT_STATUS_IS_OK(status)) {
7146 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7147 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7148 ERRSRV, ERRbadpath);
7151 reply_nterror(req, status);
7155 if (is_ntfs_stream_smb_fname(smb_dname)) {
7156 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7160 status = SMB_VFS_CREATE_FILE(
7163 smb_dname, /* fname */
7164 DELETE_ACCESS, /* access_mask */
7165 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7167 FILE_OPEN, /* create_disposition*/
7168 FILE_DIRECTORY_FILE, /* create_options */
7169 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7170 0, /* oplock_request */
7172 0, /* allocation_size */
7173 0, /* private_flags */
7178 NULL, NULL); /* create context */
7180 if (!NT_STATUS_IS_OK(status)) {
7181 if (open_was_deferred(req->xconn, req->mid)) {
7182 /* We have re-scheduled this call. */
7185 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7186 bool ok = defer_smb1_sharing_violation(req);
7191 reply_nterror(req, status);
7195 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7196 if (!NT_STATUS_IS_OK(status)) {
7197 close_file(req, fsp, ERROR_CLOSE);
7198 reply_nterror(req, status);
7202 if (!set_delete_on_close(fsp, true,
7203 conn->session_info->security_token,
7204 conn->session_info->unix_token)) {
7205 close_file(req, fsp, ERROR_CLOSE);
7206 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7210 status = close_file(req, fsp, NORMAL_CLOSE);
7211 if (!NT_STATUS_IS_OK(status)) {
7212 reply_nterror(req, status);
7214 reply_outbuf(req, 0, 0);
7217 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7219 TALLOC_FREE(smb_dname);
7220 END_PROFILE(SMBrmdir);
7224 /*******************************************************************
7225 Resolve wildcards in a filename rename.
7226 ********************************************************************/
7228 static bool resolve_wildcards(TALLOC_CTX *ctx,
7233 char *name2_copy = NULL;
7238 char *p,*p2, *pname1, *pname2;
7240 name2_copy = talloc_strdup(ctx, name2);
7245 pname1 = strrchr_m(name1,'/');
7246 pname2 = strrchr_m(name2_copy,'/');
7248 if (!pname1 || !pname2) {
7252 /* Truncate the copy of name2 at the last '/' */
7255 /* Now go past the '/' */
7259 root1 = talloc_strdup(ctx, pname1);
7260 root2 = talloc_strdup(ctx, pname2);
7262 if (!root1 || !root2) {
7266 p = strrchr_m(root1,'.');
7269 ext1 = talloc_strdup(ctx, p+1);
7271 ext1 = talloc_strdup(ctx, "");
7273 p = strrchr_m(root2,'.');
7276 ext2 = talloc_strdup(ctx, p+1);
7278 ext2 = talloc_strdup(ctx, "");
7281 if (!ext1 || !ext2) {
7289 /* Hmmm. Should this be mb-aware ? */
7292 } else if (*p2 == '*') {
7294 root2 = talloc_asprintf(ctx, "%s%s",
7313 /* Hmmm. Should this be mb-aware ? */
7316 } else if (*p2 == '*') {
7318 ext2 = talloc_asprintf(ctx, "%s%s",
7334 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7339 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7351 /****************************************************************************
7352 Ensure open files have their names updated. Updated to notify other smbd's
7354 ****************************************************************************/
7356 static void rename_open_files(connection_struct *conn,
7357 struct share_mode_lock *lck,
7359 uint32_t orig_name_hash,
7360 const struct smb_filename *smb_fname_dst)
7363 bool did_rename = False;
7365 uint32_t new_name_hash = 0;
7367 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7368 fsp = file_find_di_next(fsp)) {
7369 struct file_id_buf idbuf;
7370 /* fsp_name is a relative path under the fsp. To change this for other
7371 sharepaths we need to manipulate relative paths. */
7372 /* TODO - create the absolute path and manipulate the newname
7373 relative to the sharepath. */
7374 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7377 if (fsp->name_hash != orig_name_hash) {
7380 DBG_DEBUG("renaming file %s "
7381 "(file_id %s) from %s -> %s\n",
7383 file_id_str_buf(fsp->file_id, &idbuf),
7385 smb_fname_str_dbg(smb_fname_dst));
7387 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7388 if (NT_STATUS_IS_OK(status)) {
7390 new_name_hash = fsp->name_hash;
7395 struct file_id_buf idbuf;
7396 DBG_DEBUG("no open files on file_id %s "
7398 file_id_str_buf(id, &idbuf),
7399 smb_fname_str_dbg(smb_fname_dst));
7402 /* Send messages to all smbd's (not ourself) that the name has changed. */
7403 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7404 orig_name_hash, new_name_hash,
7409 /****************************************************************************
7410 We need to check if the source path is a parent directory of the destination
7411 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7412 refuse the rename with a sharing violation. Under UNIX the above call can
7413 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7414 probably need to check that the client is a Windows one before disallowing
7415 this as a UNIX client (one with UNIX extensions) can know the source is a
7416 symlink and make this decision intelligently. Found by an excellent bug
7417 report from <AndyLiebman@aol.com>.
7418 ****************************************************************************/
7420 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7421 const struct smb_filename *smb_fname_dst)
7423 const char *psrc = smb_fname_src->base_name;
7424 const char *pdst = smb_fname_dst->base_name;
7427 if (psrc[0] == '.' && psrc[1] == '/') {
7430 if (pdst[0] == '.' && pdst[1] == '/') {
7433 if ((slen = strlen(psrc)) > strlen(pdst)) {
7436 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7440 * Do the notify calls from a rename
7443 static void notify_rename(connection_struct *conn, bool is_dir,
7444 const struct smb_filename *smb_fname_src,
7445 const struct smb_filename *smb_fname_dst)
7447 char *parent_dir_src = NULL;
7448 char *parent_dir_dst = NULL;
7451 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7452 : FILE_NOTIFY_CHANGE_FILE_NAME;
7454 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7455 &parent_dir_src, NULL) ||
7456 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7457 &parent_dir_dst, NULL)) {
7461 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7462 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7463 smb_fname_src->base_name);
7464 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7465 smb_fname_dst->base_name);
7468 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7469 smb_fname_src->base_name);
7470 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7471 smb_fname_dst->base_name);
7474 /* this is a strange one. w2k3 gives an additional event for
7475 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7476 files, but not directories */
7478 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7479 FILE_NOTIFY_CHANGE_ATTRIBUTES
7480 |FILE_NOTIFY_CHANGE_CREATION,
7481 smb_fname_dst->base_name);
7484 TALLOC_FREE(parent_dir_src);
7485 TALLOC_FREE(parent_dir_dst);
7488 /****************************************************************************
7489 Returns an error if the parent directory for a filename is open in an
7491 ****************************************************************************/
7493 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7494 const struct smb_filename *smb_fname_dst_in)
7496 struct smb_filename *smb_fname_parent = NULL;
7498 files_struct *fsp = NULL;
7502 ok = parent_smb_fname(talloc_tos(),
7507 return NT_STATUS_NO_MEMORY;
7510 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7512 return map_nt_error_from_unix(errno);
7516 * We're only checking on this smbd here, mostly good
7517 * enough.. and will pass tests.
7520 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7521 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7522 fsp = file_find_di_next(fsp)) {
7523 if (fsp->access_mask & DELETE_ACCESS) {
7524 return NT_STATUS_SHARING_VIOLATION;
7527 return NT_STATUS_OK;
7530 /****************************************************************************
7531 Rename an open file - given an fsp.
7532 ****************************************************************************/
7534 NTSTATUS rename_internals_fsp(connection_struct *conn,
7536 const struct smb_filename *smb_fname_dst_in,
7537 const char *dst_original_lcomp,
7539 bool replace_if_exists)
7541 TALLOC_CTX *ctx = talloc_tos();
7542 struct smb_filename *smb_fname_dst = NULL;
7543 NTSTATUS status = NT_STATUS_OK;
7544 struct share_mode_lock *lck = NULL;
7545 uint32_t access_mask = SEC_DIR_ADD_FILE;
7546 bool dst_exists, old_is_stream, new_is_stream;
7549 status = check_name(conn, smb_fname_dst_in);
7550 if (!NT_STATUS_IS_OK(status)) {
7554 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7555 if (!NT_STATUS_IS_OK(status)) {
7559 if (file_has_open_streams(fsp)) {
7560 return NT_STATUS_ACCESS_DENIED;
7563 /* Make a copy of the dst smb_fname structs */
7565 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7566 if (smb_fname_dst == NULL) {
7567 status = NT_STATUS_NO_MEMORY;
7572 * Check for special case with case preserving and not
7573 * case sensitive. If the new last component differs from the original
7574 * last component only by case, then we should allow
7575 * the rename (user is trying to change the case of the
7578 if (!conn->case_sensitive && conn->case_preserve &&
7579 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7580 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7581 char *fname_dst_parent = NULL;
7582 const char *fname_dst_lcomp = NULL;
7583 char *orig_lcomp_path = NULL;
7584 char *orig_lcomp_stream = NULL;
7588 * Split off the last component of the processed
7589 * destination name. We will compare this to
7590 * the split components of dst_original_lcomp.
7592 if (!parent_dirname(ctx,
7593 smb_fname_dst->base_name,
7595 &fname_dst_lcomp)) {
7596 status = NT_STATUS_NO_MEMORY;
7601 * The dst_original_lcomp component contains
7602 * the last_component of the path + stream
7603 * name (if a stream exists).
7605 * Split off the stream name so we
7606 * can check them separately.
7609 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7610 /* POSIX - no stream component. */
7611 orig_lcomp_path = talloc_strdup(ctx,
7612 dst_original_lcomp);
7613 if (orig_lcomp_path == NULL) {
7617 ok = split_stream_filename(ctx,
7620 &orig_lcomp_stream);
7624 TALLOC_FREE(fname_dst_parent);
7625 status = NT_STATUS_NO_MEMORY;
7629 /* If the base names only differ by case, use original. */
7630 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7633 * Replace the modified last component with the
7636 if (!ISDOT(fname_dst_parent)) {
7637 tmp = talloc_asprintf(smb_fname_dst,
7642 tmp = talloc_strdup(smb_fname_dst,
7646 status = NT_STATUS_NO_MEMORY;
7647 TALLOC_FREE(fname_dst_parent);
7648 TALLOC_FREE(orig_lcomp_path);
7649 TALLOC_FREE(orig_lcomp_stream);
7652 TALLOC_FREE(smb_fname_dst->base_name);
7653 smb_fname_dst->base_name = tmp;
7656 /* If the stream_names only differ by case, use original. */
7657 if(!strcsequal(smb_fname_dst->stream_name,
7658 orig_lcomp_stream)) {
7659 /* Use the original stream. */
7660 char *tmp = talloc_strdup(smb_fname_dst,
7663 status = NT_STATUS_NO_MEMORY;
7664 TALLOC_FREE(fname_dst_parent);
7665 TALLOC_FREE(orig_lcomp_path);
7666 TALLOC_FREE(orig_lcomp_stream);
7669 TALLOC_FREE(smb_fname_dst->stream_name);
7670 smb_fname_dst->stream_name = tmp;
7672 TALLOC_FREE(fname_dst_parent);
7673 TALLOC_FREE(orig_lcomp_path);
7674 TALLOC_FREE(orig_lcomp_stream);
7678 * If the src and dest names are identical - including case,
7679 * don't do the rename, just return success.
7682 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7683 strcsequal(fsp->fsp_name->stream_name,
7684 smb_fname_dst->stream_name)) {
7685 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7686 "- returning success\n",
7687 smb_fname_str_dbg(smb_fname_dst)));
7688 status = NT_STATUS_OK;
7692 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7693 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7695 /* Return the correct error code if both names aren't streams. */
7696 if (!old_is_stream && new_is_stream) {
7697 status = NT_STATUS_OBJECT_NAME_INVALID;
7701 if (old_is_stream && !new_is_stream) {
7702 status = NT_STATUS_INVALID_PARAMETER;
7706 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7708 if(!replace_if_exists && dst_exists) {
7709 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7710 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7711 smb_fname_str_dbg(smb_fname_dst)));
7712 status = NT_STATUS_OBJECT_NAME_COLLISION;
7717 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7718 &smb_fname_dst->st);
7719 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7721 /* The file can be open when renaming a stream */
7722 if (dst_fsp && !new_is_stream) {
7723 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7724 status = NT_STATUS_ACCESS_DENIED;
7729 /* Ensure we have a valid stat struct for the source. */
7730 status = vfs_stat_fsp(fsp);
7731 if (!NT_STATUS_IS_OK(status)) {
7735 status = can_rename(conn, fsp, attrs);
7737 if (!NT_STATUS_IS_OK(status)) {
7738 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7739 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7740 smb_fname_str_dbg(smb_fname_dst)));
7741 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7742 status = NT_STATUS_ACCESS_DENIED;
7746 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7747 status = NT_STATUS_ACCESS_DENIED;
7751 /* Do we have rights to move into the destination ? */
7752 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7753 /* We're moving a directory. */
7754 access_mask = SEC_DIR_ADD_SUBDIR;
7756 status = check_parent_access(conn,
7760 if (!NT_STATUS_IS_OK(status)) {
7761 DBG_INFO("check_parent_access on "
7762 "dst %s returned %s\n",
7763 smb_fname_str_dbg(smb_fname_dst),
7768 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7771 * We have the file open ourselves, so not being able to get the
7772 * corresponding share mode lock is a fatal error.
7775 SMB_ASSERT(lck != NULL);
7777 ret = SMB_VFS_RENAMEAT(conn,
7783 uint32_t create_options = fsp->fh->private_options;
7785 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7786 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7787 smb_fname_str_dbg(smb_fname_dst)));
7789 if (!fsp->fsp_flags.is_directory &&
7790 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7791 (lp_map_archive(SNUM(conn)) ||
7792 lp_store_dos_attributes(SNUM(conn)))) {
7793 /* We must set the archive bit on the newly
7795 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7796 uint32_t old_dosmode = dos_mode(conn,
7798 file_set_dosmode(conn,
7800 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7807 fsp->fsp_flags.is_directory,
7811 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7815 * A rename acts as a new file create w.r.t. allowing an initial delete
7816 * on close, probably because in Windows there is a new handle to the
7817 * new file. If initial delete on close was requested but not
7818 * originally set, we need to set it here. This is probably not 100% correct,
7819 * but will work for the CIFSFS client which in non-posix mode
7820 * depends on these semantics. JRA.
7823 if (create_options & FILE_DELETE_ON_CLOSE) {
7824 status = can_set_delete_on_close(fsp, 0);
7826 if (NT_STATUS_IS_OK(status)) {
7827 /* Note that here we set the *initial* delete on close flag,
7828 * not the regular one. The magic gets handled in close. */
7829 fsp->fsp_flags.initial_delete_on_close = true;
7833 status = NT_STATUS_OK;
7839 if (errno == ENOTDIR || errno == EISDIR) {
7840 status = NT_STATUS_OBJECT_NAME_COLLISION;
7842 status = map_nt_error_from_unix(errno);
7845 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7846 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7847 smb_fname_str_dbg(smb_fname_dst)));
7850 TALLOC_FREE(smb_fname_dst);
7855 /****************************************************************************
7856 The guts of the rename command, split out so it may be called by the NT SMB
7858 ****************************************************************************/
7860 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7861 connection_struct *conn,
7862 struct smb_request *req,
7863 struct smb_filename *smb_fname_src,
7864 struct smb_filename *smb_fname_dst,
7865 const char *dst_original_lcomp,
7867 bool replace_if_exists,
7868 uint32_t access_mask)
7870 char *fname_src_dir = NULL;
7871 struct smb_filename *smb_fname_src_dir = NULL;
7872 char *fname_src_mask = NULL;
7874 NTSTATUS status = NT_STATUS_OK;
7875 struct smb_Dir *dir_hnd = NULL;
7876 const char *dname = NULL;
7877 char *talloced = NULL;
7879 int create_options = 0;
7880 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7881 struct smb2_create_blobs *posx = NULL;
7883 bool src_has_wild = false;
7884 bool dest_has_wild = false;
7887 * Split the old name into directory and last component
7888 * strings. Note that unix_convert may have stripped off a
7889 * leading ./ from both name and newname if the rename is
7890 * at the root of the share. We need to make sure either both
7891 * name and newname contain a / character or neither of them do
7892 * as this is checked in resolve_wildcards().
7895 /* Split up the directory from the filename/mask. */
7896 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7897 &fname_src_dir, &fname_src_mask);
7898 if (!NT_STATUS_IS_OK(status)) {
7899 status = NT_STATUS_NO_MEMORY;
7903 if (req != NULL && !req->posix_pathnames) {
7905 * Check the wildcard mask *before*
7906 * unmangling. As mangling is done
7907 * for names that can't be returned
7908 * to Windows the unmangled name may
7909 * contain Windows wildcard characters.
7911 src_has_wild = ms_has_wild(fname_src_mask);
7912 dest_has_wild = ms_has_wild(dst_original_lcomp);
7916 * We should only check the mangled cache
7917 * here if unix_convert failed. This means
7918 * that the path in 'mask' doesn't exist
7919 * on the file system and so we need to look
7920 * for a possible mangle. This patch from
7921 * Tine Smukavec <valentin.smukavec@hermes.si>.
7924 if (!VALID_STAT(smb_fname_src->st) &&
7925 mangle_is_mangled(fname_src_mask, conn->params)) {
7926 char *new_mask = NULL;
7927 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7930 TALLOC_FREE(fname_src_mask);
7931 fname_src_mask = new_mask;
7935 if (posix_pathnames) {
7936 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7937 if (!NT_STATUS_IS_OK(status)) {
7938 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7944 if (!src_has_wild) {
7948 * Only one file needs to be renamed. Append the mask back
7949 * onto the directory.
7951 TALLOC_FREE(smb_fname_src->base_name);
7952 if (ISDOT(fname_src_dir)) {
7953 /* Ensure we use canonical names on open. */
7954 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7958 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7963 if (!smb_fname_src->base_name) {
7964 status = NT_STATUS_NO_MEMORY;
7968 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7969 "case_preserve = %d, short case preserve = %d, "
7970 "directory = %s, newname = %s, "
7971 "last_component_dest = %s\n",
7972 conn->case_sensitive, conn->case_preserve,
7973 conn->short_case_preserve,
7974 smb_fname_str_dbg(smb_fname_src),
7975 smb_fname_str_dbg(smb_fname_dst),
7976 dst_original_lcomp));
7978 /* The dest name still may have wildcards. */
7979 if (dest_has_wild) {
7980 char *fname_dst_mod = NULL;
7981 if (!resolve_wildcards(smb_fname_dst,
7982 smb_fname_src->base_name,
7983 smb_fname_dst->base_name,
7985 DEBUG(6, ("rename_internals: resolve_wildcards "
7987 smb_fname_src->base_name,
7988 smb_fname_dst->base_name));
7989 status = NT_STATUS_NO_MEMORY;
7992 TALLOC_FREE(smb_fname_dst->base_name);
7993 smb_fname_dst->base_name = fname_dst_mod;
7996 ZERO_STRUCT(smb_fname_src->st);
7997 if (posix_pathnames) {
7998 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8000 rc = SMB_VFS_STAT(conn, smb_fname_src);
8003 status = map_nt_error_from_unix_common(errno);
8007 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8008 create_options |= FILE_DIRECTORY_FILE;
8011 status = SMB_VFS_CREATE_FILE(
8014 smb_fname_src, /* fname */
8015 access_mask, /* access_mask */
8016 (FILE_SHARE_READ | /* share_access */
8018 FILE_OPEN, /* create_disposition*/
8019 create_options, /* create_options */
8020 0, /* file_attributes */
8021 0, /* oplock_request */
8023 0, /* allocation_size */
8024 0, /* private_flags */
8029 posx, /* in_context_blobs */
8030 NULL); /* out_context_blobs */
8032 if (!NT_STATUS_IS_OK(status)) {
8033 DEBUG(3, ("Could not open rename source %s: %s\n",
8034 smb_fname_str_dbg(smb_fname_src),
8035 nt_errstr(status)));
8039 status = rename_internals_fsp(conn,
8046 close_file(req, fsp, NORMAL_CLOSE);
8048 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8049 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8050 smb_fname_str_dbg(smb_fname_dst)));
8056 * Wildcards - process each file that matches.
8058 if (strequal(fname_src_mask, "????????.???")) {
8059 TALLOC_FREE(fname_src_mask);
8060 fname_src_mask = talloc_strdup(ctx, "*");
8061 if (!fname_src_mask) {
8062 status = NT_STATUS_NO_MEMORY;
8067 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8071 smb_fname_src->twrp,
8072 smb_fname_src->flags);
8073 if (smb_fname_src_dir == NULL) {
8074 status = NT_STATUS_NO_MEMORY;
8078 status = check_name(conn, smb_fname_src_dir);
8079 if (!NT_STATUS_IS_OK(status)) {
8083 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8085 if (dir_hnd == NULL) {
8086 status = map_nt_error_from_unix(errno);
8090 status = NT_STATUS_NO_SUCH_FILE;
8092 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8093 * - gentest fix. JRA
8096 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8098 files_struct *fsp = NULL;
8099 char *destname = NULL;
8100 bool sysdir_entry = False;
8102 /* Quick check for "." and ".." */
8103 if (ISDOT(dname) || ISDOTDOT(dname)) {
8104 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8105 sysdir_entry = True;
8107 TALLOC_FREE(talloced);
8112 if (!is_visible_file(conn,
8117 TALLOC_FREE(talloced);
8121 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8122 TALLOC_FREE(talloced);
8127 status = NT_STATUS_OBJECT_NAME_INVALID;
8131 TALLOC_FREE(smb_fname_src->base_name);
8132 if (ISDOT(fname_src_dir)) {
8133 /* Ensure we use canonical names on open. */
8134 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8138 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8143 if (!smb_fname_src->base_name) {
8144 status = NT_STATUS_NO_MEMORY;
8148 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8149 smb_fname_dst->base_name,
8151 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8152 smb_fname_src->base_name, destname));
8153 TALLOC_FREE(talloced);
8157 status = NT_STATUS_NO_MEMORY;
8161 TALLOC_FREE(smb_fname_dst->base_name);
8162 smb_fname_dst->base_name = destname;
8164 ZERO_STRUCT(smb_fname_src->st);
8165 if (posix_pathnames) {
8166 SMB_VFS_LSTAT(conn, smb_fname_src);
8168 SMB_VFS_STAT(conn, smb_fname_src);
8173 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8174 create_options |= FILE_DIRECTORY_FILE;
8177 status = SMB_VFS_CREATE_FILE(
8180 smb_fname_src, /* fname */
8181 access_mask, /* access_mask */
8182 (FILE_SHARE_READ | /* share_access */
8184 FILE_OPEN, /* create_disposition*/
8185 create_options, /* create_options */
8186 0, /* file_attributes */
8187 0, /* oplock_request */
8189 0, /* allocation_size */
8190 0, /* private_flags */
8195 posx, /* in_context_blobs */
8196 NULL); /* out_context_blobs */
8198 if (!NT_STATUS_IS_OK(status)) {
8199 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8200 "returned %s rename %s -> %s\n",
8202 smb_fname_str_dbg(smb_fname_src),
8203 smb_fname_str_dbg(smb_fname_dst)));
8207 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8208 if (dst_original_lcomp == NULL) {
8209 status = NT_STATUS_NO_MEMORY;
8213 status = rename_internals_fsp(conn,
8220 close_file(req, fsp, NORMAL_CLOSE);
8222 if (!NT_STATUS_IS_OK(status)) {
8223 DEBUG(3, ("rename_internals_fsp returned %s for "
8224 "rename %s -> %s\n", nt_errstr(status),
8225 smb_fname_str_dbg(smb_fname_src),
8226 smb_fname_str_dbg(smb_fname_dst)));
8232 DEBUG(3,("rename_internals: doing rename on %s -> "
8233 "%s\n", smb_fname_str_dbg(smb_fname_src),
8234 smb_fname_str_dbg(smb_fname_src)));
8235 TALLOC_FREE(talloced);
8237 TALLOC_FREE(dir_hnd);
8239 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8240 status = map_nt_error_from_unix(errno);
8245 TALLOC_FREE(talloced);
8246 TALLOC_FREE(smb_fname_src_dir);
8247 TALLOC_FREE(fname_src_dir);
8248 TALLOC_FREE(fname_src_mask);
8252 /****************************************************************************
8254 ****************************************************************************/
8256 void reply_mv(struct smb_request *req)
8258 connection_struct *conn = req->conn;
8260 char *newname = NULL;
8264 TALLOC_CTX *ctx = talloc_tos();
8265 struct smb_filename *smb_fname_src = NULL;
8266 struct smb_filename *smb_fname_dst = NULL;
8267 const char *dst_original_lcomp = NULL;
8268 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8269 (req->posix_pathnames ?
8270 UCF_UNIX_NAME_LOOKUP :
8271 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8272 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8273 (req->posix_pathnames ?
8275 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8276 bool stream_rename = false;
8278 START_PROFILE(SMBmv);
8281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8285 attrs = SVAL(req->vwv+0, 0);
8287 p = (const char *)req->buf + 1;
8288 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
8290 if (!NT_STATUS_IS_OK(status)) {
8291 reply_nterror(req, status);
8295 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
8297 if (!NT_STATUS_IS_OK(status)) {
8298 reply_nterror(req, status);
8302 if (!req->posix_pathnames) {
8303 /* The newname must begin with a ':' if the
8304 name contains a ':'. */
8305 if (strchr_m(name, ':')) {
8306 if (newname[0] != ':') {
8307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8310 stream_rename = true;
8314 status = filename_convert(ctx,
8321 if (!NT_STATUS_IS_OK(status)) {
8322 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8323 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8324 ERRSRV, ERRbadpath);
8327 reply_nterror(req, status);
8331 status = filename_convert(ctx,
8338 if (!NT_STATUS_IS_OK(status)) {
8339 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8340 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8341 ERRSRV, ERRbadpath);
8344 reply_nterror(req, status);
8348 /* Get the last component of the destination for rename_internals(). */
8349 dst_original_lcomp = get_original_lcomp(ctx,
8353 if (dst_original_lcomp == NULL) {
8354 reply_nterror(req, NT_STATUS_NO_MEMORY);
8358 if (stream_rename) {
8359 /* smb_fname_dst->base_name must be the same as
8360 smb_fname_src->base_name. */
8361 TALLOC_FREE(smb_fname_dst->base_name);
8362 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8363 smb_fname_src->base_name);
8364 if (!smb_fname_dst->base_name) {
8365 reply_nterror(req, NT_STATUS_NO_MEMORY);
8370 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8371 smb_fname_str_dbg(smb_fname_dst)));
8373 status = rename_internals(ctx,
8382 if (!NT_STATUS_IS_OK(status)) {
8383 if (open_was_deferred(req->xconn, req->mid)) {
8384 /* We have re-scheduled this call. */
8387 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8388 bool ok = defer_smb1_sharing_violation(req);
8393 reply_nterror(req, status);
8397 reply_outbuf(req, 0, 0);
8399 TALLOC_FREE(smb_fname_src);
8400 TALLOC_FREE(smb_fname_dst);
8405 /*******************************************************************
8406 Copy a file as part of a reply_copy.
8407 ******************************************************************/
8410 * TODO: check error codes on all callers
8413 NTSTATUS copy_file(TALLOC_CTX *ctx,
8414 connection_struct *conn,
8415 struct smb_filename *smb_fname_src,
8416 struct smb_filename *smb_fname_dst,
8419 bool target_is_directory)
8421 struct smb_filename *smb_fname_dst_tmp = NULL;
8423 files_struct *fsp1,*fsp2;
8425 uint32_t new_create_disposition;
8429 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8430 if (smb_fname_dst_tmp == NULL) {
8431 return NT_STATUS_NO_MEMORY;
8435 * If the target is a directory, extract the last component from the
8436 * src filename and append it to the dst filename
8438 if (target_is_directory) {
8441 /* dest/target can't be a stream if it's a directory. */
8442 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8444 p = strrchr_m(smb_fname_src->base_name,'/');
8448 p = smb_fname_src->base_name;
8450 smb_fname_dst_tmp->base_name =
8451 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8453 if (!smb_fname_dst_tmp->base_name) {
8454 status = NT_STATUS_NO_MEMORY;
8459 status = vfs_file_exist(conn, smb_fname_src);
8460 if (!NT_STATUS_IS_OK(status)) {
8464 if (!target_is_directory && count) {
8465 new_create_disposition = FILE_OPEN;
8467 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8470 &new_create_disposition,
8473 status = NT_STATUS_INVALID_PARAMETER;
8478 /* Open the src file for reading. */
8479 status = SMB_VFS_CREATE_FILE(
8482 smb_fname_src, /* fname */
8483 FILE_GENERIC_READ, /* access_mask */
8484 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8485 FILE_OPEN, /* create_disposition*/
8486 0, /* create_options */
8487 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8488 INTERNAL_OPEN_ONLY, /* oplock_request */
8490 0, /* allocation_size */
8491 0, /* private_flags */
8496 NULL, NULL); /* create context */
8498 if (!NT_STATUS_IS_OK(status)) {
8502 dosattrs = dos_mode(conn, smb_fname_src);
8504 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8505 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8508 /* Open the dst file for writing. */
8509 status = SMB_VFS_CREATE_FILE(
8512 smb_fname_dst, /* fname */
8513 FILE_GENERIC_WRITE, /* access_mask */
8514 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8515 new_create_disposition, /* create_disposition*/
8516 0, /* create_options */
8517 dosattrs, /* file_attributes */
8518 INTERNAL_OPEN_ONLY, /* oplock_request */
8520 0, /* allocation_size */
8521 0, /* private_flags */
8526 NULL, NULL); /* create context */
8528 if (!NT_STATUS_IS_OK(status)) {
8529 close_file(NULL, fsp1, ERROR_CLOSE);
8533 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8534 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8536 DEBUG(0, ("error - vfs lseek returned error %s\n",
8538 status = map_nt_error_from_unix(errno);
8539 close_file(NULL, fsp1, ERROR_CLOSE);
8540 close_file(NULL, fsp2, ERROR_CLOSE);
8545 /* Do the actual copy. */
8546 if (smb_fname_src->st.st_ex_size) {
8547 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8552 close_file(NULL, fsp1, NORMAL_CLOSE);
8554 /* Ensure the modtime is set correctly on the destination file. */
8555 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8558 * As we are opening fsp1 read-only we only expect
8559 * an error on close on fsp2 if we are out of space.
8560 * Thus we don't look at the error return from the
8563 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8565 if (!NT_STATUS_IS_OK(status)) {
8569 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8570 status = NT_STATUS_DISK_FULL;
8574 status = NT_STATUS_OK;
8577 TALLOC_FREE(smb_fname_dst_tmp);
8581 /****************************************************************************
8582 Reply to a file copy.
8583 ****************************************************************************/
8585 void reply_copy(struct smb_request *req)
8587 connection_struct *conn = req->conn;
8588 struct smb_filename *smb_fname_src = NULL;
8589 struct smb_filename *smb_fname_src_dir = NULL;
8590 struct smb_filename *smb_fname_dst = NULL;
8591 char *fname_src = NULL;
8592 char *fname_dst = NULL;
8593 char *fname_src_mask = NULL;
8594 char *fname_src_dir = NULL;
8597 int error = ERRnoaccess;
8601 bool target_is_directory=False;
8602 bool source_has_wild = False;
8603 bool dest_has_wild = False;
8605 uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8606 ucf_flags_from_smb_request(req);
8607 uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8608 ucf_flags_from_smb_request(req);
8609 TALLOC_CTX *ctx = talloc_tos();
8611 START_PROFILE(SMBcopy);
8614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8618 tid2 = SVAL(req->vwv+0, 0);
8619 ofun = SVAL(req->vwv+1, 0);
8620 flags = SVAL(req->vwv+2, 0);
8622 p = (const char *)req->buf;
8623 p += srvstr_get_path_req(ctx, req, &fname_src, p, STR_TERMINATE,
8625 if (!NT_STATUS_IS_OK(status)) {
8626 reply_nterror(req, status);
8629 p += srvstr_get_path_req(ctx, req, &fname_dst, p, STR_TERMINATE,
8631 if (!NT_STATUS_IS_OK(status)) {
8632 reply_nterror(req, status);
8636 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8638 if (tid2 != conn->cnum) {
8639 /* can't currently handle inter share copies XXXX */
8640 DEBUG(3,("Rejecting inter-share copy\n"));
8641 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8645 status = filename_convert(ctx, conn,
8650 if (!NT_STATUS_IS_OK(status)) {
8651 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8652 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8653 ERRSRV, ERRbadpath);
8656 reply_nterror(req, status);
8660 status = filename_convert(ctx, conn,
8665 if (!NT_STATUS_IS_OK(status)) {
8666 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8667 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8668 ERRSRV, ERRbadpath);
8671 reply_nterror(req, status);
8675 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8677 if ((flags&1) && target_is_directory) {
8678 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8682 if ((flags&2) && !target_is_directory) {
8683 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8687 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8688 /* wants a tree copy! XXXX */
8689 DEBUG(3,("Rejecting tree copy\n"));
8690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8694 /* Split up the directory from the filename/mask. */
8695 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8696 &fname_src_dir, &fname_src_mask);
8697 if (!NT_STATUS_IS_OK(status)) {
8698 reply_nterror(req, NT_STATUS_NO_MEMORY);
8702 if (!req->posix_pathnames) {
8703 char *orig_src_lcomp = NULL;
8704 char *orig_dst_lcomp = NULL;
8706 * Check the wildcard mask *before*
8707 * unmangling. As mangling is done
8708 * for names that can't be returned
8709 * to Windows the unmangled name may
8710 * contain Windows wildcard characters.
8712 orig_src_lcomp = get_original_lcomp(ctx,
8716 if (orig_src_lcomp == NULL) {
8717 reply_nterror(req, NT_STATUS_NO_MEMORY);
8720 orig_dst_lcomp = get_original_lcomp(ctx,
8724 if (orig_dst_lcomp == NULL) {
8725 reply_nterror(req, NT_STATUS_NO_MEMORY);
8728 source_has_wild = ms_has_wild(orig_src_lcomp);
8729 dest_has_wild = ms_has_wild(orig_dst_lcomp);
8730 TALLOC_FREE(orig_src_lcomp);
8731 TALLOC_FREE(orig_dst_lcomp);
8735 * We should only check the mangled cache
8736 * here if unix_convert failed. This means
8737 * that the path in 'mask' doesn't exist
8738 * on the file system and so we need to look
8739 * for a possible mangle. This patch from
8740 * Tine Smukavec <valentin.smukavec@hermes.si>.
8742 if (!VALID_STAT(smb_fname_src->st) &&
8743 mangle_is_mangled(fname_src_mask, conn->params)) {
8744 char *new_mask = NULL;
8745 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8746 &new_mask, conn->params);
8748 /* Use demangled name if one was successfully found. */
8750 TALLOC_FREE(fname_src_mask);
8751 fname_src_mask = new_mask;
8755 if (!source_has_wild) {
8758 * Only one file needs to be copied. Append the mask back onto
8761 TALLOC_FREE(smb_fname_src->base_name);
8762 if (ISDOT(fname_src_dir)) {
8763 /* Ensure we use canonical names on open. */
8764 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8768 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8773 if (!smb_fname_src->base_name) {
8774 reply_nterror(req, NT_STATUS_NO_MEMORY);
8778 if (dest_has_wild) {
8779 char *fname_dst_mod = NULL;
8780 if (!resolve_wildcards(smb_fname_dst,
8781 smb_fname_src->base_name,
8782 smb_fname_dst->base_name,
8784 reply_nterror(req, NT_STATUS_NO_MEMORY);
8787 TALLOC_FREE(smb_fname_dst->base_name);
8788 smb_fname_dst->base_name = fname_dst_mod;
8791 status = check_name(conn, smb_fname_src);
8792 if (!NT_STATUS_IS_OK(status)) {
8793 reply_nterror(req, status);
8797 status = check_name(conn, smb_fname_dst);
8798 if (!NT_STATUS_IS_OK(status)) {
8799 reply_nterror(req, status);
8803 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8804 ofun, count, target_is_directory);
8806 if(!NT_STATUS_IS_OK(status)) {
8807 reply_nterror(req, status);
8813 struct smb_Dir *dir_hnd = NULL;
8814 const char *dname = NULL;
8815 char *talloced = NULL;
8819 * There is a wildcard that requires us to actually read the
8820 * src dir and copy each file matching the mask to the dst.
8821 * Right now streams won't be copied, but this could
8822 * presumably be added with a nested loop for reach dir entry.
8824 SMB_ASSERT(!smb_fname_src->stream_name);
8825 SMB_ASSERT(!smb_fname_dst->stream_name);
8827 smb_fname_src->stream_name = NULL;
8828 smb_fname_dst->stream_name = NULL;
8830 if (strequal(fname_src_mask,"????????.???")) {
8831 TALLOC_FREE(fname_src_mask);
8832 fname_src_mask = talloc_strdup(ctx, "*");
8833 if (!fname_src_mask) {
8834 reply_nterror(req, NT_STATUS_NO_MEMORY);
8839 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8843 smb_fname_src->twrp,
8844 smb_fname_src->flags);
8845 if (smb_fname_src_dir == NULL) {
8846 reply_nterror(req, NT_STATUS_NO_MEMORY);
8850 status = check_name(conn, smb_fname_src_dir);
8851 if (!NT_STATUS_IS_OK(status)) {
8852 reply_nterror(req, status);
8856 dir_hnd = OpenDir(ctx,
8861 if (dir_hnd == NULL) {
8862 status = map_nt_error_from_unix(errno);
8863 reply_nterror(req, status);
8869 /* Iterate over the src dir copying each entry to the dst. */
8870 while ((dname = ReadDirName(dir_hnd, &offset,
8871 &smb_fname_src->st, &talloced))) {
8872 char *destname = NULL;
8874 if (ISDOT(dname) || ISDOTDOT(dname)) {
8875 TALLOC_FREE(talloced);
8879 if (!is_visible_file(conn,
8884 TALLOC_FREE(talloced);
8888 if(!mask_match(dname, fname_src_mask,
8889 conn->case_sensitive)) {
8890 TALLOC_FREE(talloced);
8894 error = ERRnoaccess;
8896 /* Get the src smb_fname struct setup. */
8897 TALLOC_FREE(smb_fname_src->base_name);
8898 if (ISDOT(fname_src_dir)) {
8899 /* Ensure we use canonical names on open. */
8900 smb_fname_src->base_name =
8901 talloc_asprintf(smb_fname_src, "%s",
8904 smb_fname_src->base_name =
8905 talloc_asprintf(smb_fname_src, "%s/%s",
8906 fname_src_dir, dname);
8909 if (!smb_fname_src->base_name) {
8910 TALLOC_FREE(dir_hnd);
8911 TALLOC_FREE(talloced);
8912 reply_nterror(req, NT_STATUS_NO_MEMORY);
8916 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8917 smb_fname_dst->base_name,
8919 TALLOC_FREE(talloced);
8923 TALLOC_FREE(dir_hnd);
8924 TALLOC_FREE(talloced);
8925 reply_nterror(req, NT_STATUS_NO_MEMORY);
8929 TALLOC_FREE(smb_fname_dst->base_name);
8930 smb_fname_dst->base_name = destname;
8932 status = check_name(conn, smb_fname_src);
8933 if (!NT_STATUS_IS_OK(status)) {
8934 TALLOC_FREE(dir_hnd);
8935 TALLOC_FREE(talloced);
8936 reply_nterror(req, status);
8940 status = check_name(conn, smb_fname_dst);
8941 if (!NT_STATUS_IS_OK(status)) {
8942 TALLOC_FREE(dir_hnd);
8943 TALLOC_FREE(talloced);
8944 reply_nterror(req, status);
8948 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8949 smb_fname_src->base_name,
8950 smb_fname_dst->base_name));
8952 status = copy_file(ctx, conn, smb_fname_src,
8953 smb_fname_dst, ofun, count,
8954 target_is_directory);
8955 if (NT_STATUS_IS_OK(status)) {
8959 TALLOC_FREE(talloced);
8961 TALLOC_FREE(dir_hnd);
8965 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8969 reply_outbuf(req, 1, 0);
8970 SSVAL(req->outbuf,smb_vwv0,count);
8972 TALLOC_FREE(smb_fname_src);
8973 TALLOC_FREE(smb_fname_src_dir);
8974 TALLOC_FREE(smb_fname_dst);
8975 TALLOC_FREE(fname_src);
8976 TALLOC_FREE(fname_dst);
8977 TALLOC_FREE(fname_src_mask);
8978 TALLOC_FREE(fname_src_dir);
8980 END_PROFILE(SMBcopy);
8985 #define DBGC_CLASS DBGC_LOCKING
8987 /****************************************************************************
8988 Get a lock pid, dealing with large count requests.
8989 ****************************************************************************/
8991 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8992 bool large_file_format)
8994 if(!large_file_format)
8995 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8997 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9000 /****************************************************************************
9001 Get a lock count, dealing with large count requests.
9002 ****************************************************************************/
9004 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9005 bool large_file_format)
9009 if(!large_file_format) {
9010 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9013 * No BVAL, this is reversed!
9015 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9016 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9022 /****************************************************************************
9023 Get a lock offset, dealing with large offset requests.
9024 ****************************************************************************/
9026 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9027 bool large_file_format)
9029 uint64_t offset = 0;
9031 if(!large_file_format) {
9032 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9035 * No BVAL, this is reversed!
9037 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9038 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9044 struct smbd_do_unlocking_state {
9045 struct files_struct *fsp;
9046 uint16_t num_ulocks;
9047 struct smbd_lock_element *ulocks;
9048 enum brl_flavour lock_flav;
9052 static void smbd_do_unlocking_fn(
9055 bool *pmodified_dependent,
9058 struct smbd_do_unlocking_state *state = private_data;
9059 struct files_struct *fsp = state->fsp;
9060 enum brl_flavour lock_flav = state->lock_flav;
9063 for (i = 0; i < state->num_ulocks; i++) {
9064 struct smbd_lock_element *e = &state->ulocks[i];
9066 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9067 "pid %"PRIu64", file %s\n",
9073 if (e->brltype != UNLOCK_LOCK) {
9074 /* this can only happen with SMB2 */
9075 state->status = NT_STATUS_INVALID_PARAMETER;
9079 state->status = do_unlock(
9080 fsp, e->smblctx, e->count, e->offset, lock_flav);
9082 DBG_DEBUG("do_unlock returned %s\n",
9083 nt_errstr(state->status));
9085 if (!NT_STATUS_IS_OK(state->status)) {
9090 *pmodified_dependent = true;
9093 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9095 uint16_t num_ulocks,
9096 struct smbd_lock_element *ulocks,
9097 enum brl_flavour lock_flav)
9099 struct smbd_do_unlocking_state state = {
9101 .num_ulocks = num_ulocks,
9103 .lock_flav = lock_flav,
9107 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9109 status = share_mode_do_locked(
9110 fsp->file_id, smbd_do_unlocking_fn, &state);
9112 if (!NT_STATUS_IS_OK(status)) {
9113 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9117 if (!NT_STATUS_IS_OK(state.status)) {
9118 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9120 return state.status;
9123 return NT_STATUS_OK;
9126 /****************************************************************************
9127 Reply to a lockingX request.
9128 ****************************************************************************/
9130 static void reply_lockingx_done(struct tevent_req *subreq);
9132 void reply_lockingX(struct smb_request *req)
9134 connection_struct *conn = req->conn;
9136 unsigned char locktype;
9137 enum brl_type brltype;
9138 unsigned char oplocklevel;
9139 uint16_t num_ulocks;
9141 int32_t lock_timeout;
9143 const uint8_t *data;
9144 bool large_file_format;
9145 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9146 struct smbd_lock_element *locks = NULL;
9147 struct tevent_req *subreq = NULL;
9149 START_PROFILE(SMBlockingX);
9152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9153 END_PROFILE(SMBlockingX);
9157 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9158 locktype = CVAL(req->vwv+3, 0);
9159 oplocklevel = CVAL(req->vwv+3, 1);
9160 num_ulocks = SVAL(req->vwv+6, 0);
9161 num_locks = SVAL(req->vwv+7, 0);
9162 lock_timeout = IVAL(req->vwv+4, 0);
9163 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9165 if (!check_fsp(conn, req, fsp)) {
9166 END_PROFILE(SMBlockingX);
9172 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9173 /* we don't support these - and CANCEL_LOCK makes w2k
9174 and XP reboot so I don't really want to be
9175 compatible! (tridge) */
9176 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9177 END_PROFILE(SMBlockingX);
9181 /* Check if this is an oplock break on a file
9182 we have granted an oplock on.
9184 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9185 /* Client can insist on breaking to none. */
9186 bool break_to_none = (oplocklevel == 0);
9189 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9190 "for %s\n", (unsigned int)oplocklevel,
9191 fsp_fnum_dbg(fsp)));
9194 * Make sure we have granted an exclusive or batch oplock on
9198 if (fsp->oplock_type == 0) {
9200 /* The Samba4 nbench simulator doesn't understand
9201 the difference between break to level2 and break
9202 to none from level2 - it sends oplock break
9203 replies in both cases. Don't keep logging an error
9204 message here - just ignore it. JRA. */
9206 DEBUG(5,("reply_lockingX: Error : oplock break from "
9207 "client for %s (oplock=%d) and no "
9208 "oplock granted on this file (%s).\n",
9209 fsp_fnum_dbg(fsp), fsp->oplock_type,
9212 /* if this is a pure oplock break request then don't
9214 if (num_locks == 0 && num_ulocks == 0) {
9215 END_PROFILE(SMBlockingX);
9219 END_PROFILE(SMBlockingX);
9220 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9224 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9226 result = remove_oplock(fsp);
9228 result = downgrade_oplock(fsp);
9232 DEBUG(0, ("reply_lockingX: error in removing "
9233 "oplock on file %s\n", fsp_str_dbg(fsp)));
9234 /* Hmmm. Is this panic justified? */
9235 smb_panic("internal tdb error");
9238 /* if this is a pure oplock break request then don't send a
9240 if (num_locks == 0 && num_ulocks == 0) {
9241 /* Sanity check - ensure a pure oplock break is not a
9243 if (CVAL(req->vwv+0, 0) != 0xff) {
9244 DEBUG(0,("reply_lockingX: Error : pure oplock "
9245 "break is a chained %d request !\n",
9246 (unsigned int)CVAL(req->vwv+0, 0)));
9248 END_PROFILE(SMBlockingX);
9254 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9255 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9256 END_PROFILE(SMBlockingX);
9260 if (num_ulocks != 0) {
9261 struct smbd_lock_element *ulocks = NULL;
9264 ulocks = talloc_array(
9265 req, struct smbd_lock_element, num_ulocks);
9266 if (ulocks == NULL) {
9267 reply_nterror(req, NT_STATUS_NO_MEMORY);
9268 END_PROFILE(SMBlockingX);
9273 * Data now points at the beginning of the list of
9274 * smb_unlkrng structs
9276 for (i = 0; i < num_ulocks; i++) {
9277 ulocks[i].req_guid = smbd_request_guid(req,
9279 ulocks[i].smblctx = get_lock_pid(
9280 data, i, large_file_format);
9281 ulocks[i].count = get_lock_count(
9282 data, i, large_file_format);
9283 ulocks[i].offset = get_lock_offset(
9284 data, i, large_file_format);
9285 ulocks[i].brltype = UNLOCK_LOCK;
9289 * Unlock cancels pending locks
9292 ok = smbd_smb1_brl_finish_by_lock(
9299 reply_outbuf(req, 2, 0);
9300 SSVAL(req->outbuf, smb_vwv0, 0xff);
9301 SSVAL(req->outbuf, smb_vwv1, 0);
9302 END_PROFILE(SMBlockingX);
9306 status = smbd_do_unlocking(
9307 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9308 TALLOC_FREE(ulocks);
9309 if (!NT_STATUS_IS_OK(status)) {
9310 END_PROFILE(SMBlockingX);
9311 reply_nterror(req, status);
9316 /* Now do any requested locks */
9317 data += ((large_file_format ? 20 : 10)*num_ulocks);
9319 /* Data now points at the beginning of the list
9320 of smb_lkrng structs */
9322 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9323 brltype = READ_LOCK;
9325 brltype = WRITE_LOCK;
9328 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9329 if (locks == NULL) {
9330 reply_nterror(req, NT_STATUS_NO_MEMORY);
9331 END_PROFILE(SMBlockingX);
9335 for (i = 0; i < num_locks; i++) {
9336 locks[i].req_guid = smbd_request_guid(req, i),
9337 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9338 locks[i].count = get_lock_count(data, i, large_file_format);
9339 locks[i].offset = get_lock_offset(data, i, large_file_format);
9340 locks[i].brltype = brltype;
9343 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9347 if (num_locks == 0) {
9348 /* See smbtorture3 lock11 test */
9349 reply_outbuf(req, 2, 0);
9350 /* andx chain ends */
9351 SSVAL(req->outbuf, smb_vwv0, 0xff);
9352 SSVAL(req->outbuf, smb_vwv1, 0);
9353 END_PROFILE(SMBlockingX);
9357 ok = smbd_smb1_brl_finish_by_lock(
9361 locks[0], /* Windows only cancels the first lock */
9362 NT_STATUS_FILE_LOCK_CONFLICT);
9365 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9366 END_PROFILE(SMBlockingX);
9370 reply_outbuf(req, 2, 0);
9371 SSVAL(req->outbuf, smb_vwv0, 0xff);
9372 SSVAL(req->outbuf, smb_vwv1, 0);
9373 END_PROFILE(SMBlockingX);
9377 subreq = smbd_smb1_do_locks_send(
9387 if (subreq == NULL) {
9388 reply_nterror(req, NT_STATUS_NO_MEMORY);
9389 END_PROFILE(SMBlockingX);
9392 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9393 END_PROFILE(SMBlockingX);
9396 static void reply_lockingx_done(struct tevent_req *subreq)
9398 struct smb_request *req = NULL;
9402 START_PROFILE(SMBlockingX);
9404 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9407 status = smbd_smb1_do_locks_recv(subreq);
9408 TALLOC_FREE(subreq);
9410 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9412 if (NT_STATUS_IS_OK(status)) {
9413 reply_outbuf(req, 2, 0);
9414 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9415 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9417 reply_nterror(req, status);
9420 ok = srv_send_smb(req->xconn,
9421 (char *)req->outbuf,
9424 IS_CONN_ENCRYPTED(req->conn),
9427 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9430 END_PROFILE(SMBlockingX);
9434 #define DBGC_CLASS DBGC_ALL
9436 /****************************************************************************
9437 Reply to a SMBreadbmpx (read block multiplex) request.
9438 Always reply with an error, if someone has a platform really needs this,
9439 please contact vl@samba.org
9440 ****************************************************************************/
9442 void reply_readbmpx(struct smb_request *req)
9444 START_PROFILE(SMBreadBmpx);
9445 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9446 END_PROFILE(SMBreadBmpx);
9450 /****************************************************************************
9451 Reply to a SMBreadbs (read block multiplex secondary) request.
9452 Always reply with an error, if someone has a platform really needs this,
9453 please contact vl@samba.org
9454 ****************************************************************************/
9456 void reply_readbs(struct smb_request *req)
9458 START_PROFILE(SMBreadBs);
9459 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9460 END_PROFILE(SMBreadBs);
9464 /****************************************************************************
9465 Reply to a SMBsetattrE.
9466 ****************************************************************************/
9468 void reply_setattrE(struct smb_request *req)
9470 connection_struct *conn = req->conn;
9471 struct smb_file_time ft;
9475 START_PROFILE(SMBsetattrE);
9476 init_smb_file_time(&ft);
9479 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9483 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9485 if(!fsp || (fsp->conn != conn)) {
9486 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9491 * Convert the DOS times into unix times.
9494 ft.atime = time_t_to_full_timespec(
9495 srv_make_unix_date2(req->vwv+3));
9496 ft.mtime = time_t_to_full_timespec(
9497 srv_make_unix_date2(req->vwv+5));
9498 ft.create_time = time_t_to_full_timespec(
9499 srv_make_unix_date2(req->vwv+1));
9501 reply_outbuf(req, 0, 0);
9504 * Patch from Ray Frush <frush@engr.colostate.edu>
9505 * Sometimes times are sent as zero - ignore them.
9508 /* Ensure we have a valid stat struct for the source. */
9509 status = vfs_stat_fsp(fsp);
9510 if (!NT_STATUS_IS_OK(status)) {
9511 reply_nterror(req, status);
9515 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9516 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9520 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9521 if (!NT_STATUS_IS_OK(status)) {
9522 reply_nterror(req, status);
9526 if (fsp->fsp_flags.modified) {
9527 trigger_write_time_update_immediate(fsp);
9530 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9533 (unsigned int)ft.atime.tv_sec,
9534 (unsigned int)ft.mtime.tv_sec,
9535 (unsigned int)ft.create_time.tv_sec
9538 END_PROFILE(SMBsetattrE);
9543 /* Back from the dead for OS/2..... JRA. */
9545 /****************************************************************************
9546 Reply to a SMBwritebmpx (write block multiplex primary) request.
9547 Always reply with an error, if someone has a platform really needs this,
9548 please contact vl@samba.org
9549 ****************************************************************************/
9551 void reply_writebmpx(struct smb_request *req)
9553 START_PROFILE(SMBwriteBmpx);
9554 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9555 END_PROFILE(SMBwriteBmpx);
9559 /****************************************************************************
9560 Reply to a SMBwritebs (write block multiplex secondary) request.
9561 Always reply with an error, if someone has a platform really needs this,
9562 please contact vl@samba.org
9563 ****************************************************************************/
9565 void reply_writebs(struct smb_request *req)
9567 START_PROFILE(SMBwriteBs);
9568 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9569 END_PROFILE(SMBwriteBs);
9573 /****************************************************************************
9574 Reply to a SMBgetattrE.
9575 ****************************************************************************/
9577 void reply_getattrE(struct smb_request *req)
9579 connection_struct *conn = req->conn;
9582 struct timespec create_ts;
9585 START_PROFILE(SMBgetattrE);
9588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9589 END_PROFILE(SMBgetattrE);
9593 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9595 if(!fsp || (fsp->conn != conn)) {
9596 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9597 END_PROFILE(SMBgetattrE);
9601 /* Do an fstat on this file */
9602 status = vfs_stat_fsp(fsp);
9603 if (!NT_STATUS_IS_OK(status)) {
9604 reply_nterror(req, status);
9605 END_PROFILE(SMBgetattrE);
9609 mode = dos_mode(conn, fsp->fsp_name);
9612 * Convert the times into dos times. Set create
9613 * date to be last modify date as UNIX doesn't save
9617 reply_outbuf(req, 11, 0);
9619 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9620 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9621 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9622 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9623 /* Should we check pending modtime here ? JRA */
9624 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9625 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9627 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9628 SIVAL(req->outbuf, smb_vwv6, 0);
9629 SIVAL(req->outbuf, smb_vwv8, 0);
9631 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9632 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9633 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9635 SSVAL(req->outbuf,smb_vwv10, mode);
9637 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9639 END_PROFILE(SMBgetattrE);