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 "locking/share_mode_lock.h"
32 #include "smbd/smbd.h"
33 #include "smbd/globals.h"
34 #include "smbd/smbXsrv_open.h"
35 #include "fake_file.h"
36 #include "rpc_client/rpc_client.h"
37 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
38 #include "rpc_client/cli_spoolss.h"
39 #include "rpc_client/init_spoolss.h"
40 #include "rpc_server/rpc_ncacn_np.h"
41 #include "libcli/security/security.h"
42 #include "libsmb/nmblib.h"
44 #include "smbprofile.h"
45 #include "../lib/tsocket/tsocket.h"
46 #include "lib/util/tevent_ntstatus.h"
47 #include "libcli/smb/smb_signing.h"
48 #include "lib/util/sys_rw_data.h"
49 #include "librpc/gen_ndr/open_files.h"
50 #include "smb1_utils.h"
51 #include "libcli/smb/smb2_posix.h"
52 #include "lib/util/string_wrappers.h"
53 #include "source3/printing/rap_jobid.h"
54 #include "source3/lib/substitute.h"
56 /****************************************************************************
57 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
58 path or anything including wildcards.
59 We're assuming here that '/' is not the second byte in any multibyte char
60 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
62 ****************************************************************************/
64 /* Custom version for processing POSIX paths. */
65 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
67 static NTSTATUS check_path_syntax_internal(char *path,
72 NTSTATUS ret = NT_STATUS_OK;
73 bool start_of_name_component = True;
74 bool stream_started = false;
75 bool last_component_contains_wcard = false;
82 return NT_STATUS_OBJECT_NAME_INVALID;
85 return NT_STATUS_OBJECT_NAME_INVALID;
87 if (strchr_m(&s[1], ':')) {
88 return NT_STATUS_OBJECT_NAME_INVALID;
94 if ((*s == ':') && !posix_path && !stream_started) {
95 if (last_component_contains_wcard) {
96 return NT_STATUS_OBJECT_NAME_INVALID;
98 /* Stream names allow more characters than file names.
99 We're overloading posix_path here to allow a wider
100 range of characters. If stream_started is true this
101 is still a Windows path even if posix_path is true.
104 stream_started = true;
105 start_of_name_component = false;
109 return NT_STATUS_OBJECT_NAME_INVALID;
113 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
115 * Safe to assume is not the second part of a mb char
116 * as this is handled below.
118 /* Eat multiple '/' or '\\' */
119 while (IS_PATH_SEP(*s,posix_path)) {
122 if ((d != path) && (*s != '\0')) {
123 /* We only care about non-leading or trailing '/' or '\\' */
127 start_of_name_component = True;
129 last_component_contains_wcard = false;
133 if (start_of_name_component) {
134 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
135 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
138 * No mb char starts with '.' so we're safe checking the directory separator here.
141 /* If we just added a '/' - delete it */
142 if ((d > path) && (*(d-1) == '/')) {
147 /* Are we at the start ? Can't go back further if so. */
149 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
152 /* Go back one level... */
153 /* We know this is safe as '/' cannot be part of a mb sequence. */
154 /* NOTE - if this assumption is invalid we are not in good shape... */
155 /* Decrement d first as d points to the *next* char to write into. */
156 for (d--; d > path; d--) {
160 s += 2; /* Else go past the .. */
161 /* We're still at the start of a name component, just the previous one. */
164 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
176 if (*s <= 0x1f || *s == '|') {
177 return NT_STATUS_OBJECT_NAME_INVALID;
185 last_component_contains_wcard = true;
194 /* Get the size of the next MB character. */
195 next_codepoint(s,&siz);
213 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
215 return NT_STATUS_INVALID_PARAMETER;
218 start_of_name_component = False;
226 /****************************************************************************
227 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
228 No wildcards allowed.
229 ****************************************************************************/
231 NTSTATUS check_path_syntax(char *path)
233 return check_path_syntax_internal(path, false);
236 /****************************************************************************
237 Check the path for a POSIX client.
238 We're assuming here that '/' is not the second byte in any multibyte char
239 set (a safe assumption).
240 ****************************************************************************/
242 NTSTATUS check_path_syntax_posix(char *path)
244 return check_path_syntax_internal(path, true);
247 /****************************************************************************
248 Pull a string and check the path allowing a wildcard - provide for error return.
249 Passes in posix flag.
250 ****************************************************************************/
252 static size_t srvstr_get_path_internal(TALLOC_CTX *ctx,
253 const char *base_ptr,
259 bool posix_pathnames,
266 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
270 *err = NT_STATUS_INVALID_PARAMETER;
274 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
276 * For a DFS path the function parse_dfs_path()
277 * will do the path processing, just make a copy.
283 if (posix_pathnames) {
284 *err = check_path_syntax_posix(*pp_dest);
286 *err = check_path_syntax(*pp_dest);
292 /****************************************************************************
293 Pull a string and check the path - provide for error return.
294 ****************************************************************************/
296 size_t srvstr_get_path(TALLOC_CTX *ctx,
297 const char *base_ptr,
305 return srvstr_get_path_internal(ctx,
316 /****************************************************************************
317 Pull a string and check the path - provide for error return.
318 posix_pathnames version.
319 ****************************************************************************/
321 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
322 const char *base_ptr,
330 return srvstr_get_path_internal(ctx,
342 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
343 char **pp_dest, const char *src, int flags,
346 ssize_t bufrem = smbreq_bufrem(req, src);
349 *err = NT_STATUS_INVALID_PARAMETER;
353 if (req->posix_pathnames) {
354 return srvstr_get_path_internal(mem_ctx,
355 (const char *)req->inbuf,
364 return srvstr_get_path_internal(mem_ctx,
365 (const char *)req->inbuf,
377 * pull a string from the smb_buf part of a packet. In this case the
378 * string can either be null terminated or it can be terminated by the
379 * end of the smbbuf area
381 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
382 char **dest, const uint8_t *src, int flags)
384 ssize_t bufrem = smbreq_bufrem(req, src);
390 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
394 /****************************************************************************
395 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
396 ****************************************************************************/
398 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
401 if ((fsp == NULL) || (conn == NULL)) {
402 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
405 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
412 /****************************************************************************
413 Check if we have a correct fsp pointing to a file.
414 ****************************************************************************/
416 bool check_fsp(connection_struct *conn, struct smb_request *req,
419 if (!check_fsp_open(conn, req, fsp)) {
422 if (fsp->fsp_flags.is_directory) {
423 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
426 if (fsp_get_pathref_fd(fsp) == -1) {
427 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
430 fsp->num_smb_operations++;
434 /****************************************************************************
435 Check if we have a correct fsp pointing to a quota fake file. Replacement for
436 the CHECK_NTQUOTA_HANDLE_OK macro.
437 ****************************************************************************/
439 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
442 if (!check_fsp_open(conn, req, fsp)) {
446 if (fsp->fsp_flags.is_directory) {
450 if (fsp->fake_file_handle == NULL) {
454 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
458 if (fsp->fake_file_handle->private_data == NULL) {
465 /****************************************************************************
466 Return the port number we've bound to on a socket.
467 ****************************************************************************/
469 static int get_socket_port(int fd)
471 struct samba_sockaddr saddr = {
472 .sa_socklen = sizeof(struct sockaddr_storage),
479 if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
480 int level = (errno == ENOTCONN) ? 2 : 0;
481 DEBUG(level, ("getsockname failed. Error was %s\n",
486 #if defined(HAVE_IPV6)
487 if (saddr.u.sa.sa_family == AF_INET6) {
488 return ntohs(saddr.u.in6.sin6_port);
491 if (saddr.u.sa.sa_family == AF_INET) {
492 return ntohs(saddr.u.in.sin_port);
497 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
498 const char *name, int name_type)
501 char *trim_name_type;
502 const char *retarget_parm;
505 int retarget_type = 0x20;
506 int retarget_port = NBT_SMB_PORT;
507 struct sockaddr_storage retarget_addr;
508 struct sockaddr_in *in_addr;
512 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
516 trim_name = talloc_strdup(talloc_tos(), name);
517 if (trim_name == NULL) {
520 trim_char(trim_name, ' ', ' ');
522 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
524 if (trim_name_type == NULL) {
528 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
529 trim_name_type, NULL);
530 if (retarget_parm == NULL) {
531 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
534 if (retarget_parm == NULL) {
538 retarget = talloc_strdup(trim_name, retarget_parm);
539 if (retarget == NULL) {
543 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
545 p = strchr(retarget, ':');
548 retarget_port = atoi(p);
551 p = strchr_m(retarget, '#');
554 if (sscanf(p, "%x", &retarget_type) != 1) {
559 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
561 DEBUG(10, ("could not resolve %s\n", retarget));
565 if (retarget_addr.ss_family != AF_INET) {
566 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
570 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
572 _smb_setlen(outbuf, 6);
573 SCVAL(outbuf, 0, 0x84);
574 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
575 *(uint16_t *)(outbuf+8) = htons(retarget_port);
577 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
579 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
585 TALLOC_FREE(trim_name);
589 static void reply_called_name_not_present(char *outbuf)
591 smb_setlen(outbuf, 1);
592 SCVAL(outbuf, 0, 0x83);
593 SCVAL(outbuf, 4, 0x82);
596 /****************************************************************************
597 Reply to a (netbios-level) special message.
598 ****************************************************************************/
600 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
602 struct smbd_server_connection *sconn = xconn->client->sconn;
603 int msg_type = CVAL(inbuf,0);
604 int msg_flags = CVAL(inbuf,1);
606 * We only really use 4 bytes of the outbuf, but for the smb_setlen
607 * calculation & friends (srv_send_smb uses that) we need the full smb
610 char outbuf[smb_size];
612 memset(outbuf, '\0', sizeof(outbuf));
614 smb_setlen(outbuf,0);
617 case NBSSrequest: /* session request */
619 /* inbuf_size is guarenteed to be at least 4. */
621 int name_type1, name_type2;
622 int name_len1, name_len2;
626 if (xconn->transport.nbt.got_session) {
627 exit_server_cleanly("multiple session request not permitted");
630 SCVAL(outbuf,0,NBSSpositive);
633 /* inbuf_size is guaranteed to be at least 4. */
634 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
635 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
636 DEBUG(0,("Invalid name length in session request\n"));
637 reply_called_name_not_present(outbuf);
640 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
641 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
642 DEBUG(0,("Invalid name length in session request\n"));
643 reply_called_name_not_present(outbuf);
647 name_type1 = name_extract((unsigned char *)inbuf,
648 inbuf_size,(unsigned int)4,name1);
649 name_type2 = name_extract((unsigned char *)inbuf,
650 inbuf_size,(unsigned int)(4 + name_len1),name2);
652 if (name_type1 == -1 || name_type2 == -1) {
653 DEBUG(0,("Invalid name type in session request\n"));
654 reply_called_name_not_present(outbuf);
658 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
659 name1, name_type1, name2, name_type2));
661 if (netbios_session_retarget(xconn, name1, name_type1)) {
662 exit_server_cleanly("retargeted client");
666 * Windows NT/2k uses "*SMBSERVER" and XP uses
667 * "*SMBSERV" arrggg!!!
669 if (strequal(name1, "*SMBSERVER ")
670 || strequal(name1, "*SMBSERV ")) {
673 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
676 exit_server_cleanly("could not allocate raddr");
679 fstrcpy(name1, raddr);
682 set_local_machine_name(name1, True);
683 set_remote_machine_name(name2, True);
685 if (is_ipaddress(sconn->remote_hostname)) {
686 char *p = discard_const_p(char, sconn->remote_hostname);
690 sconn->remote_hostname = talloc_strdup(sconn,
691 get_remote_machine_name());
692 if (sconn->remote_hostname == NULL) {
693 exit_server_cleanly("could not copy remote name");
695 xconn->remote_hostname = sconn->remote_hostname;
698 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
699 get_local_machine_name(), get_remote_machine_name(),
702 if (name_type2 == 'R') {
703 /* We are being asked for a pathworks session ---
705 reply_called_name_not_present(outbuf);
709 reload_services(sconn, conn_snum_used, true);
712 xconn->transport.nbt.got_session = true;
716 case 0x89: /* session keepalive request
717 (some old clients produce this?) */
718 SCVAL(outbuf,0,NBSSkeepalive);
722 case NBSSpositive: /* positive session response */
723 case NBSSnegative: /* negative session response */
724 case NBSSretarget: /* retarget session response */
725 DEBUG(0,("Unexpected session response\n"));
728 case NBSSkeepalive: /* session keepalive */
733 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
734 msg_type, msg_flags));
736 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
737 exit_server_cleanly("reply_special: srv_send_smb failed.");
740 if (CVAL(outbuf, 0) != 0x82) {
741 exit_server_cleanly("invalid netbios session");
746 /****************************************************************************
748 conn POINTER CAN BE NULL HERE !
749 ****************************************************************************/
751 void reply_tcon(struct smb_request *req)
753 connection_struct *conn = req->conn;
755 char *service_buf = NULL;
756 char *password = NULL;
762 TALLOC_CTX *ctx = talloc_tos();
763 struct smbXsrv_connection *xconn = req->xconn;
764 NTTIME now = timeval_to_nttime(&req->request_time);
766 START_PROFILE(SMBtcon);
768 if (req->buflen < 4) {
769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
770 END_PROFILE(SMBtcon);
775 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
777 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
779 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
782 if (service_buf == NULL || password == NULL || dev == NULL) {
783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
784 END_PROFILE(SMBtcon);
787 p2 = strrchr_m(service_buf,'\\');
791 service = service_buf;
794 conn = make_connection(req, now, service, dev,
795 req->vuid,&nt_status);
799 reply_nterror(req, nt_status);
800 END_PROFILE(SMBtcon);
804 reply_outbuf(req, 2, 0);
805 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
806 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
807 SSVAL(req->outbuf,smb_tid,conn->cnum);
809 DEBUG(3,("tcon service=%s cnum=%d\n",
810 service, conn->cnum));
812 END_PROFILE(SMBtcon);
816 /****************************************************************************
817 Reply to a tcon and X.
818 conn POINTER CAN BE NULL HERE !
819 ****************************************************************************/
821 void reply_tcon_and_X(struct smb_request *req)
823 const struct loadparm_substitution *lp_sub =
824 loadparm_s3_global_substitution();
825 connection_struct *conn = req->conn;
826 const char *service = NULL;
827 TALLOC_CTX *ctx = talloc_tos();
828 /* what the client thinks the device is */
829 char *client_devicetype = NULL;
830 /* what the server tells the client the share represents */
831 const char *server_devicetype;
838 struct smbXsrv_session *session = NULL;
839 NTTIME now = timeval_to_nttime(&req->request_time);
840 bool session_key_updated = false;
841 uint16_t optional_support = 0;
842 struct smbXsrv_connection *xconn = req->xconn;
844 START_PROFILE(SMBtconX);
847 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
848 END_PROFILE(SMBtconX);
852 passlen = SVAL(req->vwv+3, 0);
853 tcon_flags = SVAL(req->vwv+2, 0);
855 /* we might have to close an old one */
856 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
857 struct smbXsrv_tcon *tcon;
865 * TODO: cancel all outstanding requests on the tcon
867 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
868 if (!NT_STATUS_IS_OK(status)) {
869 DEBUG(0, ("reply_tcon_and_X: "
870 "smbXsrv_tcon_disconnect() failed: %s\n",
873 * If we hit this case, there is something completely
874 * wrong, so we better disconnect the transport connection.
876 END_PROFILE(SMBtconX);
877 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
883 * This tree id is gone. Make sure we can't re-use it
889 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
890 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
891 END_PROFILE(SMBtconX);
895 if (xconn->smb1.negprot.encrypted_passwords) {
896 p = req->buf + passlen;
898 p = req->buf + passlen + 1;
901 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
905 END_PROFILE(SMBtconX);
910 * the service name can be either: \\server\share
911 * or share directly like on the DELL PowerVault 705
914 q = strchr_m(path+2,'\\');
916 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
917 END_PROFILE(SMBtconX);
925 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
926 &client_devicetype, p,
927 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
929 if (client_devicetype == NULL) {
930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
931 END_PROFILE(SMBtconX);
935 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
937 nt_status = smb1srv_session_lookup(xconn,
938 req->vuid, now, &session);
939 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
940 reply_force_doserror(req, ERRSRV, ERRbaduid);
941 END_PROFILE(SMBtconX);
944 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
945 reply_nterror(req, nt_status);
946 END_PROFILE(SMBtconX);
949 if (!NT_STATUS_IS_OK(nt_status)) {
950 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
951 END_PROFILE(SMBtconX);
955 if (session->global->auth_session_info == NULL) {
956 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
957 END_PROFILE(SMBtconX);
962 * If there is no application key defined yet
965 * This means we setup the application key on the
966 * first tcon that happens via the given session.
968 * Once the application key is defined, it does not
971 if (session->global->application_key_blob.length == 0 &&
972 smb2_signing_key_valid(session->global->signing_key))
974 struct smbXsrv_session *x = session;
975 struct auth_session_info *session_info =
976 session->global->auth_session_info;
977 uint8_t session_key[16];
979 ZERO_STRUCT(session_key);
980 memcpy(session_key, x->global->signing_key->blob.data,
981 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
984 * The application key is truncated/padded to 16 bytes
986 x->global->application_key_blob = data_blob_talloc(x->global,
988 sizeof(session_key));
989 ZERO_STRUCT(session_key);
990 if (x->global->application_key_blob.data == NULL) {
991 reply_nterror(req, NT_STATUS_NO_MEMORY);
992 END_PROFILE(SMBtconX);
995 talloc_keep_secret(x->global->application_key_blob.data);
997 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1000 status = smb_key_derivation(x->global->application_key_blob.data,
1001 x->global->application_key_blob.length,
1002 x->global->application_key_blob.data);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 DBG_ERR("smb_key_derivation failed: %s\n",
1006 END_PROFILE(SMBtconX);
1009 optional_support |= SMB_EXTENDED_SIGNATURES;
1013 * Place the application key into the session_info
1015 data_blob_clear_free(&session_info->session_key);
1016 session_info->session_key = data_blob_dup_talloc(session_info,
1017 x->global->application_key_blob);
1018 if (session_info->session_key.data == NULL) {
1019 data_blob_clear_free(&x->global->application_key_blob);
1020 reply_nterror(req, NT_STATUS_NO_MEMORY);
1021 END_PROFILE(SMBtconX);
1024 talloc_keep_secret(session_info->session_key.data);
1025 session_key_updated = true;
1028 conn = make_connection(req, now, service, client_devicetype,
1029 req->vuid, &nt_status);
1033 if (session_key_updated) {
1034 struct smbXsrv_session *x = session;
1035 struct auth_session_info *session_info =
1036 session->global->auth_session_info;
1037 data_blob_clear_free(&x->global->application_key_blob);
1038 data_blob_clear_free(&session_info->session_key);
1040 reply_nterror(req, nt_status);
1041 END_PROFILE(SMBtconX);
1046 server_devicetype = "IPC";
1047 else if ( IS_PRINT(conn) )
1048 server_devicetype = "LPT1:";
1050 server_devicetype = "A:";
1052 if (get_Protocol() < PROTOCOL_NT1) {
1053 reply_outbuf(req, 2, 0);
1054 if (message_push_string(&req->outbuf, server_devicetype,
1055 STR_TERMINATE|STR_ASCII) == -1) {
1056 reply_nterror(req, NT_STATUS_NO_MEMORY);
1057 END_PROFILE(SMBtconX);
1061 /* NT sets the fstype of IPC$ to the null string */
1062 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1064 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1065 /* Return permissions. */
1069 reply_outbuf(req, 7, 0);
1072 perm1 = FILE_ALL_ACCESS;
1073 perm2 = FILE_ALL_ACCESS;
1075 perm1 = conn->share_access;
1078 SIVAL(req->outbuf, smb_vwv3, perm1);
1079 SIVAL(req->outbuf, smb_vwv5, perm2);
1081 reply_outbuf(req, 3, 0);
1084 if ((message_push_string(&req->outbuf, server_devicetype,
1085 STR_TERMINATE|STR_ASCII) == -1)
1086 || (message_push_string(&req->outbuf, fstype,
1087 STR_TERMINATE) == -1)) {
1088 reply_nterror(req, NT_STATUS_NO_MEMORY);
1089 END_PROFILE(SMBtconX);
1093 /* what does setting this bit do? It is set by NT4 and
1094 may affect the ability to autorun mounted cdroms */
1095 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1097 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1099 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1100 DEBUG(2,("Serving %s as a Dfs root\n",
1101 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1102 optional_support |= SMB_SHARE_IN_DFS;
1105 SSVAL(req->outbuf, smb_vwv2, optional_support);
1108 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1109 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1111 DEBUG(3,("tconX service=%s \n",
1114 /* set the incoming and outgoing tid to the just created one */
1115 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1116 SSVAL(req->outbuf,smb_tid,conn->cnum);
1118 END_PROFILE(SMBtconX);
1120 req->tid = conn->cnum;
1123 /****************************************************************************
1124 Reply to an unknown type.
1125 ****************************************************************************/
1127 void reply_unknown_new(struct smb_request *req, uint8_t type)
1129 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1130 smb_fn_name(type), type, type));
1131 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1135 /****************************************************************************
1137 conn POINTER CAN BE NULL HERE !
1138 ****************************************************************************/
1140 void reply_ioctl(struct smb_request *req)
1142 const struct loadparm_substitution *lp_sub =
1143 loadparm_s3_global_substitution();
1144 connection_struct *conn = req->conn;
1147 uint32_t ioctl_code;
1151 START_PROFILE(SMBioctl);
1154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1155 END_PROFILE(SMBioctl);
1159 device = SVAL(req->vwv+1, 0);
1160 function = SVAL(req->vwv+2, 0);
1161 ioctl_code = (device << 16) + function;
1163 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1165 switch (ioctl_code) {
1166 case IOCTL_QUERY_JOB_INFO:
1170 reply_force_doserror(req, ERRSRV, ERRnosupport);
1171 END_PROFILE(SMBioctl);
1175 reply_outbuf(req, 8, replysize+1);
1176 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1177 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1178 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1179 p = smb_buf(req->outbuf);
1180 memset(p, '\0', replysize+1); /* valgrind-safe. */
1181 p += 1; /* Allow for alignment */
1183 switch (ioctl_code) {
1184 case IOCTL_QUERY_JOB_INFO:
1188 files_struct *fsp = file_fsp(
1189 req, SVAL(req->vwv+0, 0));
1191 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1192 END_PROFILE(SMBioctl);
1196 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1198 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1199 lp_netbios_name(), 15,
1200 STR_TERMINATE|STR_ASCII, &len);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 reply_nterror(req, status);
1203 END_PROFILE(SMBioctl);
1207 status = srvstr_push((char *)req->outbuf, req->flags2,
1209 lp_servicename(talloc_tos(),
1212 13, STR_TERMINATE|STR_ASCII, &len);
1213 if (!NT_STATUS_IS_OK(status)) {
1214 reply_nterror(req, status);
1215 END_PROFILE(SMBioctl);
1219 memset(p+18, 0, 13);
1225 END_PROFILE(SMBioctl);
1229 /****************************************************************************
1230 Strange checkpath NTSTATUS mapping.
1231 ****************************************************************************/
1233 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1235 /* Strange DOS error code semantics only for checkpath... */
1236 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1237 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1238 /* We need to map to ERRbadpath */
1239 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1245 /****************************************************************************
1246 Reply to a checkpath.
1247 ****************************************************************************/
1249 void reply_checkpath(struct smb_request *req)
1251 connection_struct *conn = req->conn;
1252 struct smb_filename *smb_fname = NULL;
1255 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1256 TALLOC_CTX *ctx = talloc_tos();
1258 START_PROFILE(SMBcheckpath);
1260 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1261 STR_TERMINATE, &status);
1263 if (!NT_STATUS_IS_OK(status)) {
1264 status = map_checkpath_error(req->flags2, status);
1265 reply_nterror(req, status);
1266 END_PROFILE(SMBcheckpath);
1270 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1272 status = filename_convert(ctx,
1279 if (!NT_STATUS_IS_OK(status)) {
1280 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1281 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1282 ERRSRV, ERRbadpath);
1283 END_PROFILE(SMBcheckpath);
1289 if (!VALID_STAT(smb_fname->st) &&
1290 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1291 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1292 smb_fname_str_dbg(smb_fname), strerror(errno)));
1293 status = map_nt_error_from_unix(errno);
1297 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1298 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1299 ERRDOS, ERRbadpath);
1303 reply_outbuf(req, 0, 0);
1306 /* We special case this - as when a Windows machine
1307 is parsing a path is steps through the components
1308 one at a time - if a component fails it expects
1309 ERRbadpath, not ERRbadfile.
1311 status = map_checkpath_error(req->flags2, status);
1312 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1314 * Windows returns different error codes if
1315 * the parent directory is valid but not the
1316 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1317 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1318 * if the path is invalid.
1320 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1321 ERRDOS, ERRbadpath);
1325 reply_nterror(req, status);
1328 TALLOC_FREE(smb_fname);
1329 END_PROFILE(SMBcheckpath);
1333 /****************************************************************************
1335 ****************************************************************************/
1337 void reply_getatr(struct smb_request *req)
1339 connection_struct *conn = req->conn;
1340 struct smb_filename *smb_fname = NULL;
1347 TALLOC_CTX *ctx = talloc_tos();
1348 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1350 START_PROFILE(SMBgetatr);
1352 p = (const char *)req->buf + 1;
1353 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1354 if (!NT_STATUS_IS_OK(status)) {
1355 reply_nterror(req, status);
1359 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1360 under WfWg - weird! */
1361 if (*fname == '\0') {
1362 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1363 if (!CAN_WRITE(conn)) {
1364 mode |= FILE_ATTRIBUTE_READONLY;
1369 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1370 status = filename_convert(ctx,
1376 if (!NT_STATUS_IS_OK(status)) {
1377 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1378 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1379 ERRSRV, ERRbadpath);
1382 reply_nterror(req, status);
1385 if (!VALID_STAT(smb_fname->st) &&
1386 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1387 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1388 smb_fname_str_dbg(smb_fname),
1390 reply_nterror(req, map_nt_error_from_unix(errno));
1394 mode = fdos_mode(smb_fname->fsp);
1395 size = smb_fname->st.st_ex_size;
1397 if (ask_sharemode) {
1398 struct timespec write_time_ts;
1399 struct file_id fileid;
1401 ZERO_STRUCT(write_time_ts);
1402 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1403 get_file_infos(fileid, 0, NULL, &write_time_ts);
1404 if (!is_omit_timespec(&write_time_ts)) {
1405 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1409 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1410 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1415 reply_outbuf(req, 10, 0);
1417 SSVAL(req->outbuf,smb_vwv0,mode);
1418 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1419 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1421 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1423 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1425 if (get_Protocol() >= PROTOCOL_NT1) {
1426 SSVAL(req->outbuf, smb_flg2,
1427 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1430 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1431 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1434 TALLOC_FREE(smb_fname);
1436 END_PROFILE(SMBgetatr);
1440 /****************************************************************************
1442 ****************************************************************************/
1444 void reply_setatr(struct smb_request *req)
1446 struct smb_file_time ft;
1447 connection_struct *conn = req->conn;
1448 struct smb_filename *smb_fname = NULL;
1454 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1455 TALLOC_CTX *ctx = talloc_tos();
1457 START_PROFILE(SMBsetatr);
1458 init_smb_file_time(&ft);
1461 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1465 p = (const char *)req->buf + 1;
1466 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1467 if (!NT_STATUS_IS_OK(status)) {
1468 reply_nterror(req, status);
1472 status = filename_convert(ctx,
1478 if (!NT_STATUS_IS_OK(status)) {
1479 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1480 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1481 ERRSRV, ERRbadpath);
1484 reply_nterror(req, status);
1488 if (ISDOT(smb_fname->base_name)) {
1490 * Not sure here is the right place to catch this
1491 * condition. Might be moved to somewhere else later -- vl
1493 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1497 if (smb_fname->fsp == NULL) {
1498 /* Can't set access rights on a symlink. */
1499 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1503 mode = SVAL(req->vwv+0, 0);
1504 mtime = srv_make_unix_date3(req->vwv+1);
1506 if (mode != FILE_ATTRIBUTE_NORMAL) {
1507 if (VALID_STAT_OF_DIR(smb_fname->st))
1508 mode |= FILE_ATTRIBUTE_DIRECTORY;
1510 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1512 status = smbd_check_access_rights_fsp(conn->cwd_fsp,
1515 FILE_WRITE_ATTRIBUTES);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 reply_nterror(req, status);
1521 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1523 reply_nterror(req, map_nt_error_from_unix(errno));
1528 ft.mtime = time_t_to_full_timespec(mtime);
1530 status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
1531 if (!NT_STATUS_IS_OK(status)) {
1532 reply_nterror(req, status);
1536 reply_outbuf(req, 0, 0);
1538 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1541 TALLOC_FREE(smb_fname);
1542 END_PROFILE(SMBsetatr);
1546 /****************************************************************************
1548 ****************************************************************************/
1550 void reply_dskattr(struct smb_request *req)
1552 connection_struct *conn = req->conn;
1554 uint64_t dfree,dsize,bsize;
1555 struct smb_filename smb_fname;
1556 START_PROFILE(SMBdskattr);
1558 ZERO_STRUCT(smb_fname);
1559 smb_fname.base_name = discard_const_p(char, ".");
1561 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1562 reply_nterror(req, map_nt_error_from_unix(errno));
1563 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1564 END_PROFILE(SMBdskattr);
1568 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1569 if (ret == (uint64_t)-1) {
1570 reply_nterror(req, map_nt_error_from_unix(errno));
1571 END_PROFILE(SMBdskattr);
1576 * Force max to fit in 16 bit fields.
1578 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1582 if (bsize > (WORDMAX*512)) {
1583 bsize = (WORDMAX*512);
1584 if (dsize > WORDMAX)
1586 if (dfree > WORDMAX)
1592 reply_outbuf(req, 5, 0);
1594 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1595 double total_space, free_space;
1596 /* we need to scale this to a number that DOS6 can handle. We
1597 use floating point so we can handle large drives on systems
1598 that don't have 64 bit integers
1600 we end up displaying a maximum of 2G to DOS systems
1602 total_space = dsize * (double)bsize;
1603 free_space = dfree * (double)bsize;
1605 dsize = (uint64_t)((total_space+63*512) / (64*512));
1606 dfree = (uint64_t)((free_space+63*512) / (64*512));
1608 if (dsize > 0xFFFF) dsize = 0xFFFF;
1609 if (dfree > 0xFFFF) dfree = 0xFFFF;
1611 SSVAL(req->outbuf,smb_vwv0,dsize);
1612 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1613 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1614 SSVAL(req->outbuf,smb_vwv3,dfree);
1616 SSVAL(req->outbuf,smb_vwv0,dsize);
1617 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1618 SSVAL(req->outbuf,smb_vwv2,512);
1619 SSVAL(req->outbuf,smb_vwv3,dfree);
1622 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1624 END_PROFILE(SMBdskattr);
1629 * Utility function to split the filename from the directory.
1631 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1632 char **fname_dir_out,
1633 char **fname_mask_out)
1635 const char *p = NULL;
1636 char *fname_dir = NULL;
1637 char *fname_mask = NULL;
1639 p = strrchr_m(fname_in, '/');
1641 fname_dir = talloc_strdup(ctx, ".");
1642 fname_mask = talloc_strdup(ctx, fname_in);
1644 fname_dir = talloc_strndup(ctx, fname_in,
1645 PTR_DIFF(p, fname_in));
1646 fname_mask = talloc_strdup(ctx, p+1);
1649 if (!fname_dir || !fname_mask) {
1650 TALLOC_FREE(fname_dir);
1651 TALLOC_FREE(fname_mask);
1652 return NT_STATUS_NO_MEMORY;
1655 *fname_dir_out = fname_dir;
1656 *fname_mask_out = fname_mask;
1657 return NT_STATUS_OK;
1660 /****************************************************************************
1662 ****************************************************************************/
1664 static bool make_dir_struct(TALLOC_CTX *ctx,
1674 char *mask2 = talloc_strdup(ctx, mask);
1680 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1684 memset(buf+1,' ',11);
1685 if ((p = strchr_m(mask2,'.')) != NULL) {
1687 push_ascii(buf+1,mask2,8, 0);
1688 push_ascii(buf+9,p+1,3, 0);
1691 push_ascii(buf+1,mask2,11, 0);
1694 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1696 srv_put_dos_date(buf,22,date);
1697 SSVAL(buf,26,size & 0xFFFF);
1698 SSVAL(buf,28,(size >> 16)&0xFFFF);
1699 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1700 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1701 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1702 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1706 /****************************************************************************
1708 Can be called from SMBsearch, SMBffirst or SMBfunique.
1709 ****************************************************************************/
1711 void reply_search(struct smb_request *req)
1713 connection_struct *conn = req->conn;
1716 char *directory = NULL;
1717 struct smb_filename *smb_fname = NULL;
1721 struct timespec date;
1723 unsigned int numentries = 0;
1724 unsigned int maxentries = 0;
1725 bool finished = False;
1730 bool check_descend = False;
1731 bool expect_close = False;
1733 bool mask_contains_wcard = False;
1734 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1735 TALLOC_CTX *ctx = talloc_tos();
1736 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1737 struct smbXsrv_connection *xconn = req->xconn;
1738 struct smbd_server_connection *sconn = req->sconn;
1739 files_struct *fsp = NULL;
1740 const struct loadparm_substitution *lp_sub =
1741 loadparm_s3_global_substitution();
1743 START_PROFILE(SMBsearch);
1746 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1750 if (req->posix_pathnames) {
1751 reply_unknown_new(req, req->cmd);
1755 /* If we were called as SMBffirst then we must expect close. */
1756 if(req->cmd == SMBffirst) {
1757 expect_close = True;
1760 reply_outbuf(req, 1, 3);
1761 maxentries = SVAL(req->vwv+0, 0);
1762 dirtype = SVAL(req->vwv+1, 0);
1763 p = (const char *)req->buf + 1;
1764 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1766 if (!NT_STATUS_IS_OK(nt_status)) {
1767 reply_nterror(req, nt_status);
1771 if (smbreq_bufrem(req, p) < 3) {
1772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1777 status_len = SVAL(p, 0);
1780 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1782 if (status_len == 0) {
1784 struct smb_filename *smb_dname = NULL;
1785 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1786 ucf_flags_from_smb_request(req);
1787 nt_status = filename_convert(ctx, conn,
1792 if (!NT_STATUS_IS_OK(nt_status)) {
1793 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1794 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1795 ERRSRV, ERRbadpath);
1798 reply_nterror(req, nt_status);
1802 directory = smb_fname->base_name;
1804 p = strrchr_m(directory,'/');
1805 if ((p != NULL) && (*directory != '/')) {
1806 mask = talloc_strdup(ctx, p + 1);
1807 directory = talloc_strndup(ctx, directory,
1808 PTR_DIFF(p, directory));
1810 mask = talloc_strdup(ctx, directory);
1811 directory = talloc_strdup(ctx,".");
1815 reply_nterror(req, NT_STATUS_NO_MEMORY);
1819 memset((char *)status,'\0',21);
1820 SCVAL(status,0,(dirtype & 0x1F));
1822 smb_dname = synthetic_smb_fname(talloc_tos(),
1828 if (smb_dname == NULL) {
1829 reply_nterror(req, NT_STATUS_NO_MEMORY);
1834 * As we've cut off the last component from
1835 * smb_fname we need to re-stat smb_dname
1836 * so FILE_OPEN disposition knows the directory
1839 ret = vfs_stat(conn, smb_dname);
1841 nt_status = map_nt_error_from_unix(errno);
1842 reply_nterror(req, nt_status);
1846 nt_status = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
1847 if (!NT_STATUS_IS_OK(nt_status)) {
1848 reply_nterror(req, nt_status);
1853 * Open an fsp on this directory for the dptr.
1855 nt_status = SMB_VFS_CREATE_FILE(
1858 smb_dname, /* dname */
1859 FILE_LIST_DIRECTORY, /* access_mask */
1861 FILE_SHARE_WRITE, /* share_access */
1862 FILE_OPEN, /* create_disposition*/
1863 FILE_DIRECTORY_FILE, /* create_options */
1864 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1865 NO_OPLOCK, /* oplock_request */
1867 0, /* allocation_size */
1868 0, /* private_flags */
1873 NULL, /* in_context */
1874 NULL);/* out_context */
1876 if (!NT_STATUS_IS_OK(nt_status)) {
1877 DBG_ERR("failed to open directory %s\n",
1878 smb_fname_str_dbg(smb_dname));
1879 reply_nterror(req, nt_status);
1883 nt_status = dptr_create(conn,
1893 TALLOC_FREE(smb_dname);
1895 if (!NT_STATUS_IS_OK(nt_status)) {
1897 * Use NULL here for the first parameter (req)
1898 * as this is not a client visible handle so
1899 * can'tbe part of an SMB1 chain.
1901 close_file(NULL, fsp, NORMAL_CLOSE);
1903 reply_nterror(req, nt_status);
1907 dptr_num = dptr_dnum(fsp->dptr);
1911 const char *dirpath;
1913 if (smbreq_bufrem(req, p) < 21) {
1914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1918 memcpy(status,p,21);
1919 status_dirtype = CVAL(status,0) & 0x1F;
1920 if (status_dirtype != (dirtype & 0x1F)) {
1921 dirtype = status_dirtype;
1924 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1928 dirpath = dptr_path(sconn, dptr_num);
1929 directory = talloc_strdup(ctx, dirpath);
1931 reply_nterror(req, NT_STATUS_NO_MEMORY);
1935 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1939 dirtype = dptr_attr(sconn, dptr_num);
1942 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1944 DEBUG(4,("dptr_num is %d\n",dptr_num));
1946 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1947 char buf[DIR_STRUCT_SIZE];
1948 memcpy(buf,status,21);
1949 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1950 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1951 reply_nterror(req, NT_STATUS_NO_MEMORY);
1954 dptr_fill(sconn, buf+12,dptr_num);
1955 if (dptr_zero(buf+12) && (status_len==0)) {
1960 if (message_push_blob(&req->outbuf,
1961 data_blob_const(buf, sizeof(buf)))
1963 reply_nterror(req, NT_STATUS_NO_MEMORY);
1968 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1969 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1971 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1973 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1974 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1975 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1976 check_descend = True;
1979 for (i=numentries;(i<maxentries) && !finished;i++) {
1980 finished = !get_dir_entry(ctx,
1991 char buf[DIR_STRUCT_SIZE];
1992 memcpy(buf,status,21);
1993 if (!make_dir_struct(ctx,
1999 convert_timespec_to_time_t(date),
2000 !allow_long_path_components)) {
2001 reply_nterror(req, NT_STATUS_NO_MEMORY);
2004 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2007 if (message_push_blob(&req->outbuf,
2008 data_blob_const(buf, sizeof(buf)))
2010 reply_nterror(req, NT_STATUS_NO_MEMORY);
2020 /* If we were called as SMBffirst with smb_search_id == NULL
2021 and no entries were found then return error and close fsp->dptr
2024 if (numentries == 0) {
2027 close_file(NULL, fsp, NORMAL_CLOSE);
2030 } else if(expect_close && status_len == 0) {
2031 /* Close the dptr - we know it's gone */
2034 close_file(NULL, fsp, NORMAL_CLOSE);
2039 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2040 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2042 /* fsp may have been closed above. */
2044 close_file(NULL, fsp, NORMAL_CLOSE);
2049 if ((numentries == 0) && !mask_contains_wcard) {
2050 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2054 SSVAL(req->outbuf,smb_vwv0,numentries);
2055 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2056 SCVAL(smb_buf(req->outbuf),0,5);
2057 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2059 /* The replies here are never long name. */
2060 SSVAL(req->outbuf, smb_flg2,
2061 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2062 if (!allow_long_path_components) {
2063 SSVAL(req->outbuf, smb_flg2,
2064 SVAL(req->outbuf, smb_flg2)
2065 & (~FLAGS2_LONG_PATH_COMPONENTS));
2068 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2069 SSVAL(req->outbuf, smb_flg2,
2070 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2072 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2073 smb_fn_name(req->cmd),
2080 TALLOC_FREE(directory);
2082 TALLOC_FREE(smb_fname);
2083 END_PROFILE(SMBsearch);
2087 /****************************************************************************
2088 Reply to a fclose (stop directory search).
2089 ****************************************************************************/
2091 void reply_fclose(struct smb_request *req)
2099 TALLOC_CTX *ctx = talloc_tos();
2100 struct smbd_server_connection *sconn = req->sconn;
2101 files_struct *fsp = NULL;
2103 START_PROFILE(SMBfclose);
2105 if (req->posix_pathnames) {
2106 reply_unknown_new(req, req->cmd);
2107 END_PROFILE(SMBfclose);
2111 p = (const char *)req->buf + 1;
2112 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
2114 if (!NT_STATUS_IS_OK(err)) {
2115 reply_nterror(req, err);
2116 END_PROFILE(SMBfclose);
2120 if (smbreq_bufrem(req, p) < 3) {
2121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2122 END_PROFILE(SMBfclose);
2127 status_len = SVAL(p,0);
2130 if (status_len == 0) {
2131 reply_force_doserror(req, ERRSRV, ERRsrverror);
2132 END_PROFILE(SMBfclose);
2136 if (smbreq_bufrem(req, p) < 21) {
2137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2138 END_PROFILE(SMBfclose);
2142 memcpy(status,p,21);
2144 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2146 /* Close the file - we know it's gone */
2147 close_file(NULL, fsp, NORMAL_CLOSE);
2152 reply_outbuf(req, 1, 0);
2153 SSVAL(req->outbuf,smb_vwv0,0);
2155 DEBUG(3,("search close\n"));
2157 END_PROFILE(SMBfclose);
2161 /****************************************************************************
2163 ****************************************************************************/
2165 void reply_open(struct smb_request *req)
2167 connection_struct *conn = req->conn;
2168 struct smb_filename *smb_fname = NULL;
2178 uint32_t access_mask;
2179 uint32_t share_mode;
2180 uint32_t create_disposition;
2181 uint32_t create_options = 0;
2182 uint32_t private_flags = 0;
2185 TALLOC_CTX *ctx = talloc_tos();
2187 START_PROFILE(SMBopen);
2190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2194 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2195 deny_mode = SVAL(req->vwv+0, 0);
2196 dos_attr = SVAL(req->vwv+1, 0);
2198 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2199 STR_TERMINATE, &status);
2200 if (!NT_STATUS_IS_OK(status)) {
2201 reply_nterror(req, status);
2205 if (!map_open_params_to_ntcreate(fname, deny_mode,
2206 OPENX_FILE_EXISTS_OPEN, &access_mask,
2207 &share_mode, &create_disposition,
2208 &create_options, &private_flags)) {
2209 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2213 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2215 status = filename_convert(ctx,
2221 if (!NT_STATUS_IS_OK(status)) {
2222 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2223 reply_botherror(req,
2224 NT_STATUS_PATH_NOT_COVERED,
2225 ERRSRV, ERRbadpath);
2228 reply_nterror(req, status);
2232 status = SMB_VFS_CREATE_FILE(
2235 smb_fname, /* fname */
2236 access_mask, /* access_mask */
2237 share_mode, /* share_access */
2238 create_disposition, /* create_disposition*/
2239 create_options, /* create_options */
2240 dos_attr, /* file_attributes */
2241 oplock_request, /* oplock_request */
2243 0, /* allocation_size */
2249 NULL, NULL); /* create context */
2251 if (!NT_STATUS_IS_OK(status)) {
2252 if (open_was_deferred(req->xconn, req->mid)) {
2253 /* We have re-scheduled this call. */
2257 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2258 reply_openerror(req, status);
2262 fsp = fcb_or_dos_open(
2269 bool ok = defer_smb1_sharing_violation(req);
2273 reply_openerror(req, status);
2278 /* Ensure we're pointing at the correct stat struct. */
2279 TALLOC_FREE(smb_fname);
2280 smb_fname = fsp->fsp_name;
2282 size = smb_fname->st.st_ex_size;
2283 fattr = fdos_mode(fsp);
2285 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2287 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2288 DEBUG(3,("attempt to open a directory %s\n",
2290 close_file(req, fsp, ERROR_CLOSE);
2291 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2292 ERRDOS, ERRnoaccess);
2296 reply_outbuf(req, 7, 0);
2297 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2298 SSVAL(req->outbuf,smb_vwv1,fattr);
2299 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2300 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2302 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2304 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2305 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2307 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2308 SCVAL(req->outbuf,smb_flg,
2309 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2312 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2313 SCVAL(req->outbuf,smb_flg,
2314 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2317 END_PROFILE(SMBopen);
2321 /****************************************************************************
2322 Reply to an open and X.
2323 ****************************************************************************/
2325 void reply_open_and_X(struct smb_request *req)
2327 connection_struct *conn = req->conn;
2328 struct smb_filename *smb_fname = NULL;
2330 uint16_t open_flags;
2333 /* Breakout the oplock request bits so we can set the
2334 reply bits separately. */
2335 int ex_oplock_request;
2336 int core_oplock_request;
2339 int smb_sattr = SVAL(req->vwv+4, 0);
2340 uint32_t smb_time = make_unix_date3(req->vwv+6);
2348 uint64_t allocation_size;
2349 ssize_t retval = -1;
2350 uint32_t access_mask;
2351 uint32_t share_mode;
2352 uint32_t create_disposition;
2353 uint32_t create_options = 0;
2354 uint32_t private_flags = 0;
2356 TALLOC_CTX *ctx = talloc_tos();
2358 START_PROFILE(SMBopenX);
2360 if (req->wct < 15) {
2361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2365 open_flags = SVAL(req->vwv+2, 0);
2366 deny_mode = SVAL(req->vwv+3, 0);
2367 smb_attr = SVAL(req->vwv+5, 0);
2368 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2369 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2370 oplock_request = ex_oplock_request | core_oplock_request;
2371 smb_ofun = SVAL(req->vwv+8, 0);
2372 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2374 /* If it's an IPC, pass off the pipe handler. */
2376 if (lp_nt_pipe_support()) {
2377 reply_open_pipe_and_X(conn, req);
2379 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2384 /* XXXX we need to handle passed times, sattr and flags */
2385 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2386 STR_TERMINATE, &status);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 reply_nterror(req, status);
2392 if (!map_open_params_to_ntcreate(fname, deny_mode,
2394 &access_mask, &share_mode,
2395 &create_disposition,
2398 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2402 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2404 status = filename_convert(ctx,
2410 if (!NT_STATUS_IS_OK(status)) {
2411 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2412 reply_botherror(req,
2413 NT_STATUS_PATH_NOT_COVERED,
2414 ERRSRV, ERRbadpath);
2417 reply_nterror(req, status);
2421 status = SMB_VFS_CREATE_FILE(
2424 smb_fname, /* fname */
2425 access_mask, /* access_mask */
2426 share_mode, /* share_access */
2427 create_disposition, /* create_disposition*/
2428 create_options, /* create_options */
2429 smb_attr, /* file_attributes */
2430 oplock_request, /* oplock_request */
2432 0, /* allocation_size */
2437 &smb_action, /* pinfo */
2438 NULL, NULL); /* create context */
2440 if (!NT_STATUS_IS_OK(status)) {
2441 if (open_was_deferred(req->xconn, req->mid)) {
2442 /* We have re-scheduled this call. */
2446 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2447 reply_openerror(req, status);
2451 fsp = fcb_or_dos_open(
2458 bool ok = defer_smb1_sharing_violation(req);
2462 reply_openerror(req, status);
2467 smb_action = FILE_WAS_OPENED;
2470 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2471 if the file is truncated or created. */
2472 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2473 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2474 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2475 close_file(req, fsp, ERROR_CLOSE);
2476 reply_nterror(req, NT_STATUS_DISK_FULL);
2479 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2481 close_file(req, fsp, ERROR_CLOSE);
2482 reply_nterror(req, NT_STATUS_DISK_FULL);
2485 status = vfs_stat_fsp(fsp);
2486 if (!NT_STATUS_IS_OK(status)) {
2487 close_file(req, fsp, ERROR_CLOSE);
2488 reply_nterror(req, status);
2493 fattr = fdos_mode(fsp);
2494 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2495 close_file(req, fsp, ERROR_CLOSE);
2496 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2499 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2501 /* If the caller set the extended oplock request bit
2502 and we granted one (by whatever means) - set the
2503 correct bit for extended oplock reply.
2506 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2507 smb_action |= EXTENDED_OPLOCK_GRANTED;
2510 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2511 smb_action |= EXTENDED_OPLOCK_GRANTED;
2514 /* If the caller set the core oplock request bit
2515 and we granted one (by whatever means) - set the
2516 correct bit for core oplock reply.
2519 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2520 reply_outbuf(req, 19, 0);
2522 reply_outbuf(req, 15, 0);
2525 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2526 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2528 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2529 SCVAL(req->outbuf, smb_flg,
2530 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2533 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2534 SCVAL(req->outbuf, smb_flg,
2535 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2538 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2539 SSVAL(req->outbuf,smb_vwv3,fattr);
2540 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2541 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2543 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2545 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2546 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2547 SSVAL(req->outbuf,smb_vwv11,smb_action);
2549 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2550 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2554 TALLOC_FREE(smb_fname);
2555 END_PROFILE(SMBopenX);
2559 /****************************************************************************
2560 Reply to a SMBulogoffX.
2561 ****************************************************************************/
2563 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2564 struct smbXsrv_session *session);
2565 static void reply_ulogoffX_done(struct tevent_req *req);
2567 void reply_ulogoffX(struct smb_request *smb1req)
2569 struct timeval now = timeval_current();
2570 struct smbXsrv_session *session = NULL;
2571 struct tevent_req *req;
2575 * Don't setup the profile charge here, take
2576 * it in reply_ulogoffX_done(). Not strictly correct
2577 * but better than the other SMB1 async
2578 * code that double-charges at the moment.
2581 status = smb1srv_session_lookup(smb1req->xconn,
2583 timeval_to_nttime(&now),
2585 if (!NT_STATUS_IS_OK(status)) {
2586 /* Not going async, profile here. */
2587 START_PROFILE(SMBulogoffX);
2588 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2589 (unsigned long long)smb1req->vuid);
2591 smb1req->vuid = UID_FIELD_INVALID;
2592 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2593 END_PROFILE(SMBulogoffX);
2597 req = reply_ulogoffX_send(smb1req, session);
2599 /* Not going async, profile here. */
2600 START_PROFILE(SMBulogoffX);
2601 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2602 END_PROFILE(SMBulogoffX);
2606 /* We're async. This will complete later. */
2607 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2611 struct reply_ulogoffX_state {
2612 struct tevent_queue *wait_queue;
2613 struct smbXsrv_session *session;
2616 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2618 /****************************************************************************
2619 Async SMB1 ulogoffX.
2620 Note, on failure here we deallocate and return NULL to allow the caller to
2621 SMB1 return an error of ERRnomem immediately.
2622 ****************************************************************************/
2624 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2625 struct smbXsrv_session *session)
2627 struct tevent_req *req;
2628 struct reply_ulogoffX_state *state;
2629 struct tevent_req *subreq;
2631 struct smbd_server_connection *sconn = session->client->sconn;
2632 uint64_t vuid = session->global->session_wire_id;
2634 req = tevent_req_create(smb1req, &state,
2635 struct reply_ulogoffX_state);
2639 state->wait_queue = tevent_queue_create(state,
2640 "reply_ulogoffX_wait_queue");
2641 if (tevent_req_nomem(state->wait_queue, req)) {
2645 state->session = session;
2648 * Make sure that no new request will be able to use this session.
2649 * This ensures that once all outstanding fsp->aio_requests
2650 * on this session are done, we are safe to close it.
2652 session->status = NT_STATUS_USER_SESSION_DELETED;
2654 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2655 if (fsp->vuid != vuid) {
2659 * Flag the file as close in progress.
2660 * This will prevent any more IO being
2663 fsp->fsp_flags.closing = true;
2665 if (fsp->num_aio_requests > 0) {
2667 * Now wait until all aio requests on this fsp are
2670 * We don't set a callback, as we just want to block the
2671 * wait queue and the talloc_free() of fsp->aio_request
2672 * will remove the item from the wait queue.
2674 subreq = tevent_queue_wait_send(fsp->aio_requests,
2677 if (tevent_req_nomem(subreq, req)) {
2685 * Now we add our own waiter to the end of the queue,
2686 * this way we get notified when all pending requests are finished
2687 * and reply to the outstanding SMB1 request.
2689 subreq = tevent_queue_wait_send(state,
2692 if (tevent_req_nomem(subreq, req)) {
2698 * We're really going async - move the SMB1 request from
2699 * a talloc stackframe above us to the sconn talloc-context.
2700 * We need this to stick around until the wait_done
2701 * callback is invoked.
2703 smb1req = talloc_move(sconn, &smb1req);
2705 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2710 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2712 struct tevent_req *req = tevent_req_callback_data(
2713 subreq, struct tevent_req);
2715 tevent_queue_wait_recv(subreq);
2716 TALLOC_FREE(subreq);
2717 tevent_req_done(req);
2720 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2722 return tevent_req_simple_recv_ntstatus(req);
2725 static void reply_ulogoffX_done(struct tevent_req *req)
2727 struct smb_request *smb1req = tevent_req_callback_data(
2728 req, struct smb_request);
2729 struct reply_ulogoffX_state *state = tevent_req_data(req,
2730 struct reply_ulogoffX_state);
2731 struct smbXsrv_session *session = state->session;
2735 * Take the profile charge here. Not strictly
2736 * correct but better than the other SMB1 async
2737 * code that double-charges at the moment.
2739 START_PROFILE(SMBulogoffX);
2741 status = reply_ulogoffX_recv(req);
2743 if (!NT_STATUS_IS_OK(status)) {
2744 TALLOC_FREE(smb1req);
2745 END_PROFILE(SMBulogoffX);
2746 exit_server(__location__ ": reply_ulogoffX_recv failed");
2750 status = smbXsrv_session_logoff(session);
2751 if (!NT_STATUS_IS_OK(status)) {
2752 TALLOC_FREE(smb1req);
2753 END_PROFILE(SMBulogoffX);
2754 exit_server(__location__ ": smbXsrv_session_logoff failed");
2758 TALLOC_FREE(session);
2760 reply_outbuf(smb1req, 2, 0);
2761 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2762 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2764 DBG_NOTICE("ulogoffX vuid=%llu\n",
2765 (unsigned long long)smb1req->vuid);
2767 smb1req->vuid = UID_FIELD_INVALID;
2769 * The following call is needed to push the
2770 * reply data back out the socket after async
2771 * return. Plus it frees smb1req.
2773 smb_request_done(smb1req);
2774 END_PROFILE(SMBulogoffX);
2777 /****************************************************************************
2778 Reply to a mknew or a create.
2779 ****************************************************************************/
2781 void reply_mknew(struct smb_request *req)
2783 connection_struct *conn = req->conn;
2784 struct smb_filename *smb_fname = NULL;
2787 struct smb_file_time ft;
2789 int oplock_request = 0;
2791 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2792 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2793 uint32_t create_disposition;
2794 uint32_t create_options = 0;
2796 TALLOC_CTX *ctx = talloc_tos();
2798 START_PROFILE(SMBcreate);
2799 init_smb_file_time(&ft);
2802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2806 fattr = SVAL(req->vwv+0, 0);
2807 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2809 if (req->cmd == SMBmknew) {
2810 /* We should fail if file exists. */
2811 create_disposition = FILE_CREATE;
2813 /* Create if file doesn't exist, truncate if it does. */
2814 create_disposition = FILE_OVERWRITE_IF;
2818 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2820 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2821 STR_TERMINATE, &status);
2822 if (!NT_STATUS_IS_OK(status)) {
2823 reply_nterror(req, status);
2827 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2828 status = filename_convert(ctx,
2834 if (!NT_STATUS_IS_OK(status)) {
2835 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2836 reply_botherror(req,
2837 NT_STATUS_PATH_NOT_COVERED,
2838 ERRSRV, ERRbadpath);
2841 reply_nterror(req, status);
2845 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2846 DEBUG(0,("Attempt to create file (%s) with volid set - "
2847 "please report this\n",
2848 smb_fname_str_dbg(smb_fname)));
2851 status = SMB_VFS_CREATE_FILE(
2854 smb_fname, /* fname */
2855 access_mask, /* access_mask */
2856 share_mode, /* share_access */
2857 create_disposition, /* create_disposition*/
2858 create_options, /* create_options */
2859 fattr, /* file_attributes */
2860 oplock_request, /* oplock_request */
2862 0, /* allocation_size */
2863 0, /* private_flags */
2868 NULL, NULL); /* create context */
2870 if (!NT_STATUS_IS_OK(status)) {
2871 if (open_was_deferred(req->xconn, req->mid)) {
2872 /* We have re-scheduled this call. */
2875 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2876 bool ok = defer_smb1_sharing_violation(req);
2881 reply_openerror(req, status);
2885 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2886 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2887 if (!NT_STATUS_IS_OK(status)) {
2888 END_PROFILE(SMBcreate);
2892 reply_outbuf(req, 1, 0);
2893 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2895 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2896 SCVAL(req->outbuf,smb_flg,
2897 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2900 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2901 SCVAL(req->outbuf,smb_flg,
2902 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2905 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2906 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2907 smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2908 (unsigned int)fattr));
2911 TALLOC_FREE(smb_fname);
2912 END_PROFILE(SMBcreate);
2916 /****************************************************************************
2917 Reply to a create temporary file.
2918 ****************************************************************************/
2920 void reply_ctemp(struct smb_request *req)
2922 connection_struct *conn = req->conn;
2923 struct smb_filename *smb_fname = NULL;
2924 char *wire_name = NULL;
2933 TALLOC_CTX *ctx = talloc_tos();
2935 START_PROFILE(SMBctemp);
2938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2942 fattr = SVAL(req->vwv+0, 0);
2943 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2945 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2946 STR_TERMINATE, &status);
2947 if (!NT_STATUS_IS_OK(status)) {
2948 reply_nterror(req, status);
2952 for (i = 0; i < 10; i++) {
2954 fname = talloc_asprintf(ctx,
2957 generate_random_str_list(ctx, 5, "0123456789"));
2959 fname = talloc_asprintf(ctx,
2961 generate_random_str_list(ctx, 5, "0123456789"));
2965 reply_nterror(req, NT_STATUS_NO_MEMORY);
2969 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2970 status = filename_convert(ctx, conn,
2975 if (!NT_STATUS_IS_OK(status)) {
2976 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2977 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2978 ERRSRV, ERRbadpath);
2981 reply_nterror(req, status);
2985 /* Create the file. */
2986 status = SMB_VFS_CREATE_FILE(
2989 smb_fname, /* fname */
2990 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2991 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2992 FILE_CREATE, /* create_disposition*/
2993 0, /* create_options */
2994 fattr, /* file_attributes */
2995 oplock_request, /* oplock_request */
2997 0, /* allocation_size */
2998 0, /* private_flags */
3003 NULL, NULL); /* create context */
3005 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3007 TALLOC_FREE(smb_fname);
3011 if (!NT_STATUS_IS_OK(status)) {
3012 if (open_was_deferred(req->xconn, req->mid)) {
3013 /* We have re-scheduled this call. */
3016 if (NT_STATUS_EQUAL(
3017 status, NT_STATUS_SHARING_VIOLATION)) {
3018 bool ok = defer_smb1_sharing_violation(req);
3023 reply_openerror(req, status);
3031 /* Collision after 10 times... */
3032 reply_nterror(req, status);
3036 reply_outbuf(req, 1, 0);
3037 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3039 /* the returned filename is relative to the directory */
3040 s = strrchr_m(fsp->fsp_name->base_name, '/');
3042 s = fsp->fsp_name->base_name;
3048 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3049 thing in the byte section. JRA */
3050 SSVALS(p, 0, -1); /* what is this? not in spec */
3052 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3054 reply_nterror(req, NT_STATUS_NO_MEMORY);
3058 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3059 SCVAL(req->outbuf, smb_flg,
3060 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3063 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3064 SCVAL(req->outbuf, smb_flg,
3065 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3068 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3069 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3070 fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
3072 TALLOC_FREE(smb_fname);
3073 TALLOC_FREE(wire_name);
3074 END_PROFILE(SMBctemp);
3078 /*******************************************************************
3079 Check if a user is allowed to rename a file.
3080 ********************************************************************/
3082 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3085 if (!CAN_WRITE(conn)) {
3086 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3089 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3090 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3091 /* Only bother to read the DOS attribute if we might deny the
3092 rename on the grounds of attribute mismatch. */
3093 uint32_t fmode = fdos_mode(fsp);
3094 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3095 return NT_STATUS_NO_SUCH_FILE;
3099 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3100 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3101 return NT_STATUS_OK;
3104 /* If no pathnames are open below this
3105 directory, allow the rename. */
3107 if (lp_strict_rename(SNUM(conn))) {
3109 * Strict rename, check open file db.
3111 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3112 return NT_STATUS_ACCESS_DENIED;
3114 } else if (file_find_subpath(fsp)) {
3116 * No strict rename, just look in local process.
3118 return NT_STATUS_ACCESS_DENIED;
3120 return NT_STATUS_OK;
3123 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3124 return NT_STATUS_OK;
3127 return NT_STATUS_ACCESS_DENIED;
3130 /*******************************************************************
3131 * unlink a file with all relevant access checks
3132 *******************************************************************/
3134 static NTSTATUS do_unlink(connection_struct *conn,
3135 struct smb_request *req,
3136 struct smb_filename *smb_fname,
3141 uint32_t dirtype_orig = dirtype;
3144 struct smb2_create_blobs *posx = NULL;
3146 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3147 smb_fname_str_dbg(smb_fname),
3150 if (!CAN_WRITE(conn)) {
3151 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3154 ret = vfs_stat(conn, smb_fname);
3156 return map_nt_error_from_unix(errno);
3159 fattr = fdos_mode(smb_fname->fsp);
3161 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3162 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3165 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3167 return NT_STATUS_NO_SUCH_FILE;
3170 if (!dir_check_ftype(fattr, dirtype)) {
3171 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3172 return NT_STATUS_FILE_IS_A_DIRECTORY;
3174 return NT_STATUS_NO_SUCH_FILE;
3177 if (dirtype_orig & 0x8000) {
3178 /* These will never be set for POSIX. */
3179 return NT_STATUS_NO_SUCH_FILE;
3183 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3184 return NT_STATUS_FILE_IS_A_DIRECTORY;
3187 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3188 return NT_STATUS_NO_SUCH_FILE;
3191 if (dirtype & 0xFF00) {
3192 /* These will never be set for POSIX. */
3193 return NT_STATUS_NO_SUCH_FILE;
3198 return NT_STATUS_NO_SUCH_FILE;
3201 /* Can't delete a directory. */
3202 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3203 return NT_STATUS_FILE_IS_A_DIRECTORY;
3208 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3209 return NT_STATUS_OBJECT_NAME_INVALID;
3210 #endif /* JRATEST */
3212 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
3213 status = make_smb2_posix_create_ctx(
3214 talloc_tos(), &posx, 0777);
3215 if (!NT_STATUS_IS_OK(status)) {
3216 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3222 /* On open checks the open itself will check the share mode, so
3223 don't do it here as we'll get it wrong. */
3225 status = SMB_VFS_CREATE_FILE
3228 smb_fname, /* fname */
3229 DELETE_ACCESS, /* access_mask */
3230 FILE_SHARE_NONE, /* share_access */
3231 FILE_OPEN, /* create_disposition*/
3232 FILE_NON_DIRECTORY_FILE, /* create_options */
3233 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3234 0, /* oplock_request */
3236 0, /* allocation_size */
3237 0, /* private_flags */
3242 posx, /* in_context_blobs */
3243 NULL); /* out_context_blobs */
3247 if (!NT_STATUS_IS_OK(status)) {
3248 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3249 nt_errstr(status)));
3253 status = can_set_delete_on_close(fsp, fattr);
3254 if (!NT_STATUS_IS_OK(status)) {
3255 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3257 smb_fname_str_dbg(smb_fname),
3258 nt_errstr(status)));
3259 close_file(req, fsp, NORMAL_CLOSE);
3263 /* The set is across all open files on this dev/inode pair. */
3264 if (!set_delete_on_close(fsp, True,
3265 conn->session_info->security_token,
3266 conn->session_info->unix_token)) {
3267 close_file(req, fsp, NORMAL_CLOSE);
3268 return NT_STATUS_ACCESS_DENIED;
3271 return close_file(req, fsp, NORMAL_CLOSE);
3274 /****************************************************************************
3275 The guts of the unlink command, split out so it may be called by the NT SMB
3277 ****************************************************************************/
3279 NTSTATUS unlink_internals(connection_struct *conn,
3280 struct smb_request *req,
3282 struct smb_filename *smb_fname)
3284 char *fname_dir = NULL;
3285 char *fname_mask = NULL;
3286 NTSTATUS status = NT_STATUS_OK;
3287 struct smb_filename *smb_fname_dir = NULL;
3288 TALLOC_CTX *ctx = talloc_tos();
3289 bool posix_pathname = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
3291 /* Split up the directory from the filename/mask. */
3292 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3293 &fname_dir, &fname_mask);
3294 if (!NT_STATUS_IS_OK(status)) {
3299 * We should only check the mangled cache
3300 * here if unix_convert failed. This means
3301 * that the path in 'mask' doesn't exist
3302 * on the file system and so we need to look
3303 * for a possible mangle. This patch from
3304 * Tine Smukavec <valentin.smukavec@hermes.si>.
3307 if (!VALID_STAT(smb_fname->st) &&
3309 mangle_is_mangled(fname_mask, conn->params)) {
3310 char *new_mask = NULL;
3311 mangle_lookup_name_from_8_3(ctx, fname_mask,
3312 &new_mask, conn->params);
3314 TALLOC_FREE(fname_mask);
3315 fname_mask = new_mask;
3320 * Only one file needs to be unlinked. Append the mask back
3321 * onto the directory.
3323 TALLOC_FREE(smb_fname->base_name);
3324 if (ISDOT(fname_dir)) {
3325 /* Ensure we use canonical names on open. */
3326 smb_fname->base_name = talloc_asprintf(smb_fname,
3330 smb_fname->base_name = talloc_asprintf(smb_fname,
3335 if (!smb_fname->base_name) {
3336 status = NT_STATUS_NO_MEMORY;
3340 dirtype = FILE_ATTRIBUTE_NORMAL;
3343 status = check_name(conn, smb_fname);
3344 if (!NT_STATUS_IS_OK(status)) {
3348 status = do_unlink(conn, req, smb_fname, dirtype);
3351 TALLOC_FREE(smb_fname_dir);
3352 TALLOC_FREE(fname_dir);
3353 TALLOC_FREE(fname_mask);
3357 /****************************************************************************
3359 ****************************************************************************/
3361 void reply_unlink(struct smb_request *req)
3363 connection_struct *conn = req->conn;
3365 struct smb_filename *smb_fname = NULL;
3368 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
3369 TALLOC_CTX *ctx = talloc_tos();
3371 START_PROFILE(SMBunlink);
3374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3378 dirtype = SVAL(req->vwv+0, 0);
3380 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
3381 STR_TERMINATE, &status);
3382 if (!NT_STATUS_IS_OK(status)) {
3383 reply_nterror(req, status);
3387 status = filename_convert(ctx, conn,
3392 if (!NT_STATUS_IS_OK(status)) {
3393 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3394 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3395 ERRSRV, ERRbadpath);
3398 reply_nterror(req, status);
3402 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3404 status = unlink_internals(conn, req, dirtype, smb_fname);
3405 if (!NT_STATUS_IS_OK(status)) {
3406 if (open_was_deferred(req->xconn, req->mid)) {
3407 /* We have re-scheduled this call. */
3410 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3411 bool ok = defer_smb1_sharing_violation(req);
3416 reply_nterror(req, status);
3420 reply_outbuf(req, 0, 0);
3422 TALLOC_FREE(smb_fname);
3423 END_PROFILE(SMBunlink);
3427 /****************************************************************************
3429 ****************************************************************************/
3431 static void fail_readraw(void)
3433 const char *errstr = talloc_asprintf(talloc_tos(),
3434 "FAIL ! reply_readbraw: socket write fail (%s)",
3439 exit_server_cleanly(errstr);
3442 /****************************************************************************
3443 Fake (read/write) sendfile. Returns -1 on read or write fail.
3444 ****************************************************************************/
3446 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3447 off_t startpos, size_t nread)
3450 size_t tosend = nread;
3457 bufsize = MIN(nread, 65536);
3459 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3463 while (tosend > 0) {
3467 cur_read = MIN(tosend, bufsize);
3468 ret = read_file(fsp,buf,startpos,cur_read);
3474 /* If we had a short read, fill with zeros. */
3475 if (ret < cur_read) {
3476 memset(buf + ret, '\0', cur_read - ret);
3479 ret = write_data(xconn->transport.sock, buf, cur_read);
3480 if (ret != cur_read) {
3481 int saved_errno = errno;
3483 * Try and give an error message saying what
3486 DEBUG(0, ("write_data failed for client %s. "
3488 smbXsrv_connection_dbg(xconn),
3489 strerror(saved_errno)));
3491 errno = saved_errno;
3495 startpos += cur_read;
3499 return (ssize_t)nread;
3502 /****************************************************************************
3503 Deal with the case of sendfile reading less bytes from the file than
3504 requested. Fill with zeros (all we can do). Returns 0 on success
3505 ****************************************************************************/
3507 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3513 #define SHORT_SEND_BUFSIZE 1024
3514 if (nread < headersize) {
3515 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3516 "header for file %s (%s). Terminating\n",
3517 fsp_str_dbg(fsp), strerror(errno)));
3521 nread -= headersize;
3523 if (nread < smb_maxcnt) {
3524 char buf[SHORT_SEND_BUFSIZE] = { 0 };
3526 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3527 "with zeros !\n", fsp_str_dbg(fsp)));
3529 while (nread < smb_maxcnt) {
3531 * We asked for the real file size and told sendfile
3532 * to not go beyond the end of the file. But it can
3533 * happen that in between our fstat call and the
3534 * sendfile call the file was truncated. This is very
3535 * bad because we have already announced the larger
3536 * number of bytes to the client.
3538 * The best we can do now is to send 0-bytes, just as
3539 * a read from a hole in a sparse file would do.
3541 * This should happen rarely enough that I don't care
3542 * about efficiency here :-)
3547 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3548 ret = write_data(xconn->transport.sock, buf, to_write);
3549 if (ret != to_write) {
3550 int saved_errno = errno;
3552 * Try and give an error message saying what
3555 DEBUG(0, ("write_data failed for client %s. "
3557 smbXsrv_connection_dbg(xconn),
3558 strerror(saved_errno)));
3559 errno = saved_errno;
3569 /****************************************************************************
3570 Return a readbraw error (4 bytes of zero).
3571 ****************************************************************************/
3573 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3579 smbd_lock_socket(xconn);
3580 if (write_data(xconn->transport.sock,header,4) != 4) {
3581 int saved_errno = errno;
3583 * Try and give an error message saying what
3586 DEBUG(0, ("write_data failed for client %s. "
3588 smbXsrv_connection_dbg(xconn),
3589 strerror(saved_errno)));
3590 errno = saved_errno;
3594 smbd_unlock_socket(xconn);
3597 /*******************************************************************
3598 Ensure we don't use sendfile if server smb signing is active.
3599 ********************************************************************/
3601 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3603 bool sign_active = false;
3605 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3606 if (get_Protocol() < PROTOCOL_NT1) {
3609 if (signing_state) {
3610 sign_active = smb_signing_is_active(signing_state);
3612 return (lp__use_sendfile(snum) &&
3613 (get_remote_arch() != RA_WIN95) &&
3616 /****************************************************************************
3617 Use sendfile in readbraw.
3618 ****************************************************************************/
3620 static void send_file_readbraw(connection_struct *conn,
3621 struct smb_request *req,
3627 struct smbXsrv_connection *xconn = req->xconn;
3628 char *outbuf = NULL;
3632 * We can only use sendfile on a non-chained packet
3633 * but we can use on a non-oplocked file. tridge proved this
3634 * on a train in Germany :-). JRA.
3635 * reply_readbraw has already checked the length.
3638 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3639 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3640 ssize_t sendfile_read = -1;
3642 DATA_BLOB header_blob;
3644 _smb_setlen(header,nread);
3645 header_blob = data_blob_const(header, 4);
3647 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3648 &header_blob, startpos,
3650 if (sendfile_read == -1) {
3651 /* Returning ENOSYS means no data at all was sent.
3652 * Do this as a normal read. */
3653 if (errno == ENOSYS) {
3654 goto normal_readbraw;
3658 * Special hack for broken Linux with no working sendfile. If we
3659 * return EINTR we sent the header but not the rest of the data.
3660 * Fake this up by doing read/write calls.
3662 if (errno == EINTR) {
3663 /* Ensure we don't do this again. */
3664 set_use_sendfile(SNUM(conn), False);
3665 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3667 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3668 DEBUG(0,("send_file_readbraw: "
3669 "fake_sendfile failed for "
3673 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3678 DEBUG(0,("send_file_readbraw: sendfile failed for "
3679 "file %s (%s). Terminating\n",
3680 fsp_str_dbg(fsp), strerror(errno)));
3681 exit_server_cleanly("send_file_readbraw sendfile failed");
3682 } else if (sendfile_read == 0) {
3684 * Some sendfile implementations return 0 to indicate
3685 * that there was a short read, but nothing was
3686 * actually written to the socket. In this case,
3687 * fallback to the normal read path so the header gets
3688 * the correct byte count.
3690 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3691 "bytes falling back to the normal read: "
3692 "%s\n", fsp_str_dbg(fsp)));
3693 goto normal_readbraw;
3696 /* Deal with possible short send. */
3697 if (sendfile_read != 4+nread) {
3698 ret = sendfile_short_send(xconn, fsp,
3699 sendfile_read, 4, nread);
3709 outbuf = talloc_array(NULL, char, nread+4);
3711 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3712 (unsigned)(nread+4)));
3713 reply_readbraw_error(xconn);
3718 ret = read_file(fsp,outbuf+4,startpos,nread);
3719 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3728 _smb_setlen(outbuf,ret);
3729 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3730 int saved_errno = errno;
3732 * Try and give an error message saying what
3735 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3736 smbXsrv_connection_dbg(xconn),
3737 strerror(saved_errno)));
3738 errno = saved_errno;
3743 TALLOC_FREE(outbuf);
3746 /****************************************************************************
3747 Reply to a readbraw (core+ protocol).
3748 ****************************************************************************/
3750 void reply_readbraw(struct smb_request *req)
3752 connection_struct *conn = req->conn;
3753 struct smbXsrv_connection *xconn = req->xconn;
3754 ssize_t maxcount,mincount;
3758 struct lock_struct lock;
3762 START_PROFILE(SMBreadbraw);
3764 if (srv_is_signing_active(xconn) || req->encrypted) {
3765 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3766 "raw reads/writes are disallowed.");
3770 reply_readbraw_error(xconn);
3771 END_PROFILE(SMBreadbraw);
3775 if (xconn->smb1.echo_handler.trusted_fde) {
3776 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3777 "'async smb echo handler = yes'\n"));
3778 reply_readbraw_error(xconn);
3779 END_PROFILE(SMBreadbraw);
3784 * Special check if an oplock break has been issued
3785 * and the readraw request croses on the wire, we must
3786 * return a zero length response here.
3789 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3792 * We have to do a check_fsp by hand here, as
3793 * we must always return 4 zero bytes on error,
3799 conn != fsp->conn ||
3800 req->vuid != fsp->vuid ||
3801 fsp->fsp_flags.is_directory ||
3802 fsp_get_io_fd(fsp) == -1)
3805 * fsp could be NULL here so use the value from the packet. JRA.
3807 DEBUG(3,("reply_readbraw: fnum %d not valid "
3809 (int)SVAL(req->vwv+0, 0)));
3810 reply_readbraw_error(xconn);
3811 END_PROFILE(SMBreadbraw);
3815 /* Do a "by hand" version of CHECK_READ. */
3816 if (!(fsp->fsp_flags.can_read ||
3817 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3818 (fsp->access_mask & FILE_EXECUTE)))) {
3819 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3820 (int)SVAL(req->vwv+0, 0)));
3821 reply_readbraw_error(xconn);
3822 END_PROFILE(SMBreadbraw);
3826 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3827 if(req->wct == 10) {
3829 * This is a large offset (64 bit) read.
3832 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3835 DEBUG(0,("reply_readbraw: negative 64 bit "
3836 "readraw offset (%.0f) !\n",
3837 (double)startpos ));
3838 reply_readbraw_error(xconn);
3839 END_PROFILE(SMBreadbraw);
3844 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3845 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3847 /* ensure we don't overrun the packet size */
3848 maxcount = MIN(65535,maxcount);
3850 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3851 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3854 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3855 reply_readbraw_error(xconn);
3856 END_PROFILE(SMBreadbraw);
3860 status = vfs_stat_fsp(fsp);
3861 if (NT_STATUS_IS_OK(status)) {
3862 size = fsp->fsp_name->st.st_ex_size;
3865 if (startpos >= size) {
3868 nread = MIN(maxcount,(size - startpos));
3871 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3872 if (nread < mincount)
3876 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3877 "min=%lu nread=%lu\n",
3878 fsp_fnum_dbg(fsp), (double)startpos,
3879 (unsigned long)maxcount,
3880 (unsigned long)mincount,
3881 (unsigned long)nread ) );
3883 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3885 DEBUG(5,("reply_readbraw finished\n"));
3887 END_PROFILE(SMBreadbraw);
3892 #define DBGC_CLASS DBGC_LOCKING
3894 /****************************************************************************
3895 Reply to a lockread (core+ protocol).
3896 ****************************************************************************/
3898 static void reply_lockread_locked(struct tevent_req *subreq);
3900 void reply_lockread(struct smb_request *req)
3902 struct tevent_req *subreq = NULL;
3903 connection_struct *conn = req->conn;
3905 struct smbd_lock_element *lck = NULL;
3907 START_PROFILE(SMBlockread);
3910 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3911 END_PROFILE(SMBlockread);
3915 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3917 if (!check_fsp(conn, req, fsp)) {
3918 END_PROFILE(SMBlockread);
3922 if (!CHECK_READ(fsp,req)) {
3923 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3924 END_PROFILE(SMBlockread);
3928 lck = talloc(req, struct smbd_lock_element);
3930 reply_nterror(req, NT_STATUS_NO_MEMORY);
3931 END_PROFILE(SMBlockread);
3936 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3937 * protocol request that predates the read/write lock concept.
3938 * Thus instead of asking for a read lock here we need to ask
3939 * for a write lock. JRA.
3940 * Note that the requested lock size is unaffected by max_send.
3943 *lck = (struct smbd_lock_element) {
3944 .req_guid = smbd_request_guid(req, 0),
3945 .smblctx = req->smbpid,
3946 .brltype = WRITE_LOCK,
3947 .count = SVAL(req->vwv+1, 0),
3948 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3951 subreq = smbd_smb1_do_locks_send(
3957 false, /* large_offset */
3961 if (subreq == NULL) {
3962 reply_nterror(req, NT_STATUS_NO_MEMORY);
3963 END_PROFILE(SMBlockread);
3966 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3967 END_PROFILE(SMBlockread);
3970 static void reply_lockread_locked(struct tevent_req *subreq)
3972 struct smb_request *req = NULL;
3978 size_t numtoread, maxtoread;
3979 struct files_struct *fsp = NULL;
3982 START_PROFILE(SMBlockread);
3984 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3987 status = smbd_smb1_do_locks_recv(subreq);
3988 TALLOC_FREE(subreq);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 reply_nterror(req, status);
3995 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3997 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4001 numtoread = SVAL(req->vwv+1, 0);
4002 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4005 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4007 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4009 if (numtoread > maxtoread) {
4010 DBG_WARNING("requested read size (%zu) is greater than "
4011 "maximum allowed (%zu/%d). "
4012 "Returning short read of maximum allowed for "
4013 "compatibility with Windows 2000.\n",
4016 req->xconn->smb1.sessions.max_send);
4017 numtoread = maxtoread;
4020 reply_outbuf(req, 5, numtoread + 3);
4022 data = smb_buf(req->outbuf) + 3;
4024 nread = read_file(fsp,data,startpos,numtoread);
4027 reply_nterror(req, map_nt_error_from_unix(errno));
4031 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4033 SSVAL(req->outbuf,smb_vwv0,nread);
4034 SSVAL(req->outbuf,smb_vwv5,nread+3);
4035 p = smb_buf(req->outbuf);
4036 SCVAL(p,0,0); /* pad byte. */
4039 DEBUG(3,("lockread %s num=%d nread=%d\n",
4040 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4043 ok = srv_send_smb(req->xconn,
4044 (char *)req->outbuf,
4047 IS_CONN_ENCRYPTED(req->conn),
4050 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4053 END_PROFILE(SMBlockread);
4058 #define DBGC_CLASS DBGC_ALL
4060 /****************************************************************************
4062 ****************************************************************************/
4064 void reply_read(struct smb_request *req)
4066 connection_struct *conn = req->conn;
4073 struct lock_struct lock;
4074 struct smbXsrv_connection *xconn = req->xconn;
4076 START_PROFILE(SMBread);
4079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4080 END_PROFILE(SMBread);
4084 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4086 if (!check_fsp(conn, req, fsp)) {
4087 END_PROFILE(SMBread);
4091 if (!CHECK_READ(fsp,req)) {
4092 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4093 END_PROFILE(SMBread);
4097 numtoread = SVAL(req->vwv+1, 0);
4098 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4101 * The requested read size cannot be greater than max_send. JRA.
4103 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4105 if (numtoread > maxtoread) {
4106 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4107 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4108 (unsigned int)numtoread, (unsigned int)maxtoread,
4109 (unsigned int)xconn->smb1.sessions.max_send));
4110 numtoread = maxtoread;
4113 reply_outbuf(req, 5, numtoread+3);
4115 data = smb_buf(req->outbuf) + 3;
4117 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4118 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4121 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4122 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4123 END_PROFILE(SMBread);
4128 nread = read_file(fsp,data,startpos,numtoread);
4131 reply_nterror(req, map_nt_error_from_unix(errno));
4135 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4137 SSVAL(req->outbuf,smb_vwv0,nread);
4138 SSVAL(req->outbuf,smb_vwv5,nread+3);
4139 SCVAL(smb_buf(req->outbuf),0,1);
4140 SSVAL(smb_buf(req->outbuf),1,nread);
4142 DEBUG(3, ("read %s num=%d nread=%d\n",
4143 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4146 END_PROFILE(SMBread);
4150 /****************************************************************************
4152 ****************************************************************************/
4154 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4158 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4161 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4163 SCVAL(outbuf,smb_vwv0,0xFF);
4164 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4165 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4166 SSVAL(outbuf,smb_vwv6,
4167 (smb_wct - 4) /* offset from smb header to wct */
4168 + 1 /* the wct field */
4169 + 12 * sizeof(uint16_t) /* vwv */
4170 + 2 /* the buflen field */
4171 + 1); /* padding byte */
4172 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4173 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4174 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4175 _smb_setlen_large(outbuf,
4176 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4180 /****************************************************************************
4181 Reply to a read and X - possibly using sendfile.
4182 ****************************************************************************/
4184 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4185 files_struct *fsp, off_t startpos,
4188 struct smbXsrv_connection *xconn = req->xconn;
4190 struct lock_struct lock;
4191 int saved_errno = 0;
4194 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4195 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4198 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4199 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4204 * We can only use sendfile on a non-chained packet
4205 * but we can use on a non-oplocked file. tridge proved this
4206 * on a train in Germany :-). JRA.
4209 if (!req_is_in_chain(req) &&
4211 (fsp->base_fsp == NULL) &&
4212 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4213 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4216 status = vfs_stat_fsp(fsp);
4217 if (!NT_STATUS_IS_OK(status)) {
4218 reply_nterror(req, status);
4222 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4223 (startpos > fsp->fsp_name->st.st_ex_size) ||
4224 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4226 * We already know that we would do a short read, so don't
4227 * try the sendfile() path.
4229 goto nosendfile_read;
4233 * Set up the packet header before send. We
4234 * assume here the sendfile will work (get the
4235 * correct amount of data).
4238 header = data_blob_const(headerbuf, sizeof(headerbuf));
4240 construct_reply_common_req(req, (char *)headerbuf);
4241 setup_readX_header((char *)headerbuf, smb_maxcnt);
4243 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4244 startpos, smb_maxcnt);
4246 saved_errno = errno;
4248 /* Returning ENOSYS means no data at all was sent.
4249 Do this as a normal read. */
4250 if (errno == ENOSYS) {
4255 * Special hack for broken Linux with no working sendfile. If we
4256 * return EINTR we sent the header but not the rest of the data.
4257 * Fake this up by doing read/write calls.
4260 if (errno == EINTR) {
4261 /* Ensure we don't do this again. */
4262 set_use_sendfile(SNUM(conn), False);
4263 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4264 nread = fake_sendfile(xconn, fsp, startpos,
4267 saved_errno = errno;
4268 DEBUG(0,("send_file_readX: "
4269 "fake_sendfile failed for "
4270 "file %s (%s) for client %s. "
4273 smbXsrv_connection_dbg(xconn),
4274 strerror(saved_errno)));
4275 errno = saved_errno;
4276 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4278 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4279 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4280 /* No outbuf here means successful sendfile. */
4284 DEBUG(0,("send_file_readX: sendfile failed for file "
4285 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4287 exit_server_cleanly("send_file_readX sendfile failed");
4288 } else if (nread == 0) {
4290 * Some sendfile implementations return 0 to indicate
4291 * that there was a short read, but nothing was
4292 * actually written to the socket. In this case,
4293 * fallback to the normal read path so the header gets
4294 * the correct byte count.
4296 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4297 "falling back to the normal read: %s\n",
4302 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4303 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4305 /* Deal with possible short send. */
4306 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4309 ret = sendfile_short_send(xconn, fsp, nread,
4310 sizeof(headerbuf), smb_maxcnt);
4313 r = "send_file_readX: sendfile_short_send failed";
4314 DEBUG(0,("%s for file %s (%s).\n",
4315 r, fsp_str_dbg(fsp), strerror(errno)));
4316 exit_server_cleanly(r);
4319 /* No outbuf here means successful sendfile. */
4320 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4321 SMB_PERFCOUNT_END(&req->pcd);
4327 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4328 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4331 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4332 (startpos > fsp->fsp_name->st.st_ex_size) ||
4333 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4335 * We already know that we would do a short
4336 * read, so don't try the sendfile() path.
4338 goto nosendfile_read;
4341 construct_reply_common_req(req, (char *)headerbuf);
4342 setup_readX_header((char *)headerbuf, smb_maxcnt);
4344 /* Send out the header. */
4345 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4347 if (ret != sizeof(headerbuf)) {
4348 saved_errno = errno;
4350 * Try and give an error message saying what
4353 DEBUG(0,("send_file_readX: write_data failed for file "
4354 "%s (%s) for client %s. Terminating\n",
4356 smbXsrv_connection_dbg(xconn),
4357 strerror(saved_errno)));
4358 errno = saved_errno;
4359 exit_server_cleanly("send_file_readX sendfile failed");
4361 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4363 saved_errno = errno;
4364 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4365 "%s (%s) for client %s. Terminating\n",
4367 smbXsrv_connection_dbg(xconn),
4368 strerror(saved_errno)));
4369 errno = saved_errno;
4370 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4377 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4378 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4379 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4381 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4382 startpos, smb_maxcnt);
4383 saved_errno = errno;
4386 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4390 setup_readX_header((char *)req->outbuf, nread);
4392 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4393 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4397 TALLOC_FREE(req->outbuf);
4401 /****************************************************************************
4402 Work out how much space we have for a read return.
4403 ****************************************************************************/
4405 static size_t calc_max_read_pdu(const struct smb_request *req)
4407 struct smbXsrv_connection *xconn = req->xconn;
4409 if (xconn->protocol < PROTOCOL_NT1) {
4410 return xconn->smb1.sessions.max_send;
4413 if (!lp_large_readwrite()) {
4414 return xconn->smb1.sessions.max_send;
4417 if (req_is_in_chain(req)) {
4418 return xconn->smb1.sessions.max_send;
4421 if (req->encrypted) {
4423 * Don't take encrypted traffic up to the
4424 * limit. There are padding considerations
4425 * that make that tricky.
4427 return xconn->smb1.sessions.max_send;
4430 if (srv_is_signing_active(xconn)) {
4434 if (!lp_unix_extensions()) {
4439 * We can do ultra-large POSIX reads.
4444 /****************************************************************************
4445 Calculate how big a read can be. Copes with all clients. It's always
4446 safe to return a short read - Windows does this.
4447 ****************************************************************************/
4449 static size_t calc_read_size(const struct smb_request *req,
4453 struct smbXsrv_connection *xconn = req->xconn;
4454 size_t max_pdu = calc_max_read_pdu(req);
4455 size_t total_size = 0;
4456 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4457 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4460 * Windows explicitly ignores upper size of 0xFFFF.
4461 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4462 * We must do the same as these will never fit even in
4463 * an extended size NetBIOS packet.
4465 if (upper_size == 0xFFFF) {
4469 if (xconn->protocol < PROTOCOL_NT1) {
4473 total_size = ((upper_size<<16) | lower_size);
4476 * LARGE_READX test shows it's always safe to return
4477 * a short read. Windows does so.
4479 return MIN(total_size, max_len);
4482 /****************************************************************************
4483 Reply to a read and X.
4484 ****************************************************************************/
4486 void reply_read_and_X(struct smb_request *req)
4488 connection_struct *conn = req->conn;
4493 bool big_readX = False;
4495 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4498 START_PROFILE(SMBreadX);
4500 if ((req->wct != 10) && (req->wct != 12)) {
4501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4505 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4506 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4507 smb_maxcnt = SVAL(req->vwv+5, 0);
4509 /* If it's an IPC, pass off the pipe handler. */
4511 reply_pipe_read_and_X(req);
4512 END_PROFILE(SMBreadX);
4516 if (!check_fsp(conn, req, fsp)) {
4517 END_PROFILE(SMBreadX);
4521 if (!CHECK_READ(fsp,req)) {
4522 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4523 END_PROFILE(SMBreadX);
4527 upper_size = SVAL(req->vwv+7, 0);
4528 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4529 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4531 * This is a heuristic to avoid keeping large
4532 * outgoing buffers around over long-lived aio
4538 if (req->wct == 12) {
4540 * This is a large offset (64 bit) read.
4542 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4547 NTSTATUS status = schedule_aio_read_and_X(conn,
4552 if (NT_STATUS_IS_OK(status)) {
4553 /* Read scheduled - we're done. */
4556 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4557 /* Real error - report to client. */
4558 END_PROFILE(SMBreadX);
4559 reply_nterror(req, status);
4562 /* NT_STATUS_RETRY - fall back to sync read. */
4565 smbd_lock_socket(req->xconn);
4566 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4567 smbd_unlock_socket(req->xconn);
4570 END_PROFILE(SMBreadX);
4574 /****************************************************************************
4575 Error replies to writebraw must have smb_wct == 1. Fix this up.
4576 ****************************************************************************/
4578 void error_to_writebrawerr(struct smb_request *req)
4580 uint8_t *old_outbuf = req->outbuf;
4582 reply_outbuf(req, 1, 0);
4584 memcpy(req->outbuf, old_outbuf, smb_size);
4585 TALLOC_FREE(old_outbuf);
4588 /****************************************************************************
4589 Read 4 bytes of a smb packet and return the smb length of the packet.
4590 Store the result in the buffer. This version of the function will
4591 never return a session keepalive (length of zero).
4592 Timeout is in milliseconds.
4593 ****************************************************************************/
4595 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4598 uint8_t msgtype = NBSSkeepalive;
4600 while (msgtype == NBSSkeepalive) {
4603 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4605 if (!NT_STATUS_IS_OK(status)) {
4606 char addr[INET6_ADDRSTRLEN];
4607 /* Try and give an error message
4608 * saying what client failed. */
4609 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4610 "client %s read error = %s.\n",
4611 get_peer_addr(fd,addr,sizeof(addr)),
4612 nt_errstr(status)));
4616 msgtype = CVAL(inbuf, 0);
4619 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4620 (unsigned long)len));
4622 return NT_STATUS_OK;
4625 /****************************************************************************
4626 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4627 ****************************************************************************/
4629 void reply_writebraw(struct smb_request *req)
4631 connection_struct *conn = req->conn;
4632 struct smbXsrv_connection *xconn = req->xconn;
4635 ssize_t total_written=0;
4636 size_t numtowrite=0;
4639 const char *data=NULL;
4642 struct lock_struct lock;
4645 START_PROFILE(SMBwritebraw);
4648 * If we ever reply with an error, it must have the SMB command
4649 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4652 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4654 if (srv_is_signing_active(xconn)) {
4655 END_PROFILE(SMBwritebraw);
4656 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4657 "raw reads/writes are disallowed.");
4660 if (req->wct < 12) {
4661 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4662 error_to_writebrawerr(req);
4663 END_PROFILE(SMBwritebraw);
4667 if (xconn->smb1.echo_handler.trusted_fde) {
4668 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4669 "'async smb echo handler = yes'\n"));
4670 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4671 error_to_writebrawerr(req);
4672 END_PROFILE(SMBwritebraw);
4676 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4677 if (!check_fsp(conn, req, fsp)) {
4678 error_to_writebrawerr(req);
4679 END_PROFILE(SMBwritebraw);
4683 if (!CHECK_WRITE(fsp)) {
4684 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4685 error_to_writebrawerr(req);
4686 END_PROFILE(SMBwritebraw);
4690 tcount = IVAL(req->vwv+1, 0);
4691 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4692 write_through = BITSETW(req->vwv+7,0);
4694 /* We have to deal with slightly different formats depending
4695 on whether we are using the core+ or lanman1.0 protocol */
4697 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4698 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4699 data = smb_buf_const(req->inbuf);
4701 numtowrite = SVAL(req->vwv+10, 0);
4702 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4705 /* Ensure we don't write bytes past the end of this packet. */
4707 * This already protects us against CVE-2017-12163.
4709 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4710 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4711 error_to_writebrawerr(req);
4712 END_PROFILE(SMBwritebraw);
4716 if (!fsp->print_file) {
4717 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4718 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4721 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4722 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4723 error_to_writebrawerr(req);
4724 END_PROFILE(SMBwritebraw);
4730 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4733 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4734 "wrote=%d sync=%d\n",
4735 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4736 (int)nwritten, (int)write_through));
4738 if (nwritten < (ssize_t)numtowrite) {
4739 reply_nterror(req, NT_STATUS_DISK_FULL);
4740 error_to_writebrawerr(req);
4744 total_written = nwritten;
4746 /* Allocate a buffer of 64k + length. */
4747 buf = talloc_array(NULL, char, 65540);
4749 reply_nterror(req, NT_STATUS_NO_MEMORY);
4750 error_to_writebrawerr(req);
4754 /* Return a SMBwritebraw message to the redirector to tell
4755 * it to send more bytes */
4757 memcpy(buf, req->inbuf, smb_size);
4758 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4759 SCVAL(buf,smb_com,SMBwritebraw);
4760 SSVALS(buf,smb_vwv0,0xFFFF);
4762 if (!srv_send_smb(req->xconn,
4764 false, 0, /* no signing */
4765 IS_CONN_ENCRYPTED(conn),
4767 exit_server_cleanly("reply_writebraw: srv_send_smb "
4771 /* Now read the raw data into the buffer and write it */
4772 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4774 if (!NT_STATUS_IS_OK(status)) {
4775 exit_server_cleanly("secondary writebraw failed");
4778 /* Set up outbuf to return the correct size */
4779 reply_outbuf(req, 1, 0);
4781 if (numtowrite != 0) {
4783 if (numtowrite > 0xFFFF) {
4784 DEBUG(0,("reply_writebraw: Oversize secondary write "
4785 "raw requested (%u). Terminating\n",
4786 (unsigned int)numtowrite ));
4787 exit_server_cleanly("secondary writebraw failed");
4790 if (tcount > nwritten+numtowrite) {
4791 DEBUG(3,("reply_writebraw: Client overestimated the "
4793 (int)tcount,(int)nwritten,(int)numtowrite));
4796 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4799 if (!NT_STATUS_IS_OK(status)) {
4800 /* Try and give an error message
4801 * saying what client failed. */
4802 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4803 "raw read failed (%s) for client %s. "
4804 "Terminating\n", nt_errstr(status),
4805 smbXsrv_connection_dbg(xconn)));
4806 exit_server_cleanly("secondary writebraw failed");
4810 * We are not vulnerable to CVE-2017-12163
4811 * here as we are guaranteed to have numtowrite
4812 * bytes available - we just read from the client.
4814 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4815 if (nwritten == -1) {
4817 reply_nterror(req, map_nt_error_from_unix(errno));
4818 error_to_writebrawerr(req);
4822 if (nwritten < (ssize_t)numtowrite) {
4823 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4824 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4828 total_written += nwritten;
4833 SSVAL(req->outbuf,smb_vwv0,total_written);
4835 status = sync_file(conn, fsp, write_through);
4836 if (!NT_STATUS_IS_OK(status)) {
4837 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4838 fsp_str_dbg(fsp), nt_errstr(status)));
4839 reply_nterror(req, status);
4840 error_to_writebrawerr(req);
4844 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4846 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4847 (int)total_written));
4849 /* We won't return a status if write through is not selected - this
4850 * follows what WfWg does */
4851 END_PROFILE(SMBwritebraw);
4853 if (!write_through && total_written==tcount) {
4855 #if RABBIT_PELLET_FIX
4857 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4858 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4861 if (!send_keepalive(xconn->transport.sock)) {
4862 exit_server_cleanly("reply_writebraw: send of "
4863 "keepalive failed");
4866 TALLOC_FREE(req->outbuf);
4871 END_PROFILE(SMBwritebraw);
4876 #define DBGC_CLASS DBGC_LOCKING
4878 /****************************************************************************
4879 Reply to a writeunlock (core+).
4880 ****************************************************************************/
4882 void reply_writeunlock(struct smb_request *req)
4884 connection_struct *conn = req->conn;
4885 ssize_t nwritten = -1;
4890 NTSTATUS status = NT_STATUS_OK;
4892 struct lock_struct lock;
4893 int saved_errno = 0;
4895 START_PROFILE(SMBwriteunlock);
4898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4899 END_PROFILE(SMBwriteunlock);
4903 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4905 if (!check_fsp(conn, req, fsp)) {
4906 END_PROFILE(SMBwriteunlock);
4910 if (!CHECK_WRITE(fsp)) {
4911 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4912 END_PROFILE(SMBwriteunlock);
4916 numtowrite = SVAL(req->vwv+1, 0);
4917 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4918 data = (const char *)req->buf + 3;
4921 * Ensure client isn't asking us to write more than
4922 * they sent. CVE-2017-12163.
4924 remaining = smbreq_bufrem(req, data);
4925 if (numtowrite > remaining) {
4926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4927 END_PROFILE(SMBwriteunlock);
4931 if (!fsp->print_file && numtowrite > 0) {
4932 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4933 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4936 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4937 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4938 END_PROFILE(SMBwriteunlock);
4943 /* The special X/Open SMB protocol handling of
4944 zero length writes is *NOT* done for
4946 if(numtowrite == 0) {
4949 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4950 saved_errno = errno;
4953 status = sync_file(conn, fsp, False /* write through */);
4954 if (!NT_STATUS_IS_OK(status)) {
4955 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4956 fsp_str_dbg(fsp), nt_errstr(status)));
4957 reply_nterror(req, status);
4962 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4966 if((nwritten < numtowrite) && (numtowrite != 0)) {
4967 reply_nterror(req, NT_STATUS_DISK_FULL);
4971 if (numtowrite && !fsp->print_file) {
4972 struct smbd_lock_element l = {
4973 .req_guid = smbd_request_guid(req, 0),
4974 .smblctx = req->smbpid,
4975 .brltype = UNLOCK_LOCK,
4977 .count = numtowrite,
4979 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
4980 if (NT_STATUS_V(status)) {
4981 reply_nterror(req, status);
4986 reply_outbuf(req, 1, 0);
4988 SSVAL(req->outbuf,smb_vwv0,nwritten);
4990 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4991 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4994 END_PROFILE(SMBwriteunlock);
4999 #define DBGC_CLASS DBGC_ALL
5001 /****************************************************************************
5003 ****************************************************************************/
5005 void reply_write(struct smb_request *req)
5007 connection_struct *conn = req->conn;
5010 ssize_t nwritten = -1;
5014 struct lock_struct lock;
5016 int saved_errno = 0;
5018 START_PROFILE(SMBwrite);
5021 END_PROFILE(SMBwrite);
5022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5026 /* If it's an IPC, pass off the pipe handler. */
5028 reply_pipe_write(req);
5029 END_PROFILE(SMBwrite);
5033 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5035 if (!check_fsp(conn, req, fsp)) {
5036 END_PROFILE(SMBwrite);
5040 if (!CHECK_WRITE(fsp)) {
5041 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5042 END_PROFILE(SMBwrite);
5046 numtowrite = SVAL(req->vwv+1, 0);
5047 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5048 data = (const char *)req->buf + 3;
5051 * Ensure client isn't asking us to write more than
5052 * they sent. CVE-2017-12163.
5054 remaining = smbreq_bufrem(req, data);
5055 if (numtowrite > remaining) {
5056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5057 END_PROFILE(SMBwrite);
5061 if (!fsp->print_file) {
5062 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5063 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5066 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5067 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5068 END_PROFILE(SMBwrite);
5074 * X/Open SMB protocol says that if smb_vwv1 is
5075 * zero then the file size should be extended or
5076 * truncated to the size given in smb_vwv[2-3].
5079 if(numtowrite == 0) {
5081 * This is actually an allocate call, and set EOF. JRA.
5083 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5085 reply_nterror(req, NT_STATUS_DISK_FULL);
5088 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5090 reply_nterror(req, NT_STATUS_DISK_FULL);
5093 trigger_write_time_update_immediate(fsp);
5095 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5098 status = sync_file(conn, fsp, False);
5099 if (!NT_STATUS_IS_OK(status)) {
5100 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5101 fsp_str_dbg(fsp), nt_errstr(status)));
5102 reply_nterror(req, status);
5107 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5111 if((nwritten == 0) && (numtowrite != 0)) {
5112 reply_nterror(req, NT_STATUS_DISK_FULL);
5116 reply_outbuf(req, 1, 0);
5118 SSVAL(req->outbuf,smb_vwv0,nwritten);
5120 if (nwritten < (ssize_t)numtowrite) {
5121 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5122 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5125 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5128 END_PROFILE(SMBwrite);
5132 /****************************************************************************
5133 Ensure a buffer is a valid writeX for recvfile purposes.
5134 ****************************************************************************/
5136 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5137 (2*14) + /* word count (including bcc) */ \
5140 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5141 const uint8_t *inbuf)
5144 unsigned int doff = 0;
5145 size_t len = smb_len_large(inbuf);
5147 struct smbXsrv_open *op = NULL;
5148 struct files_struct *fsp = NULL;
5151 if (is_encrypted_packet(inbuf)) {
5152 /* Can't do this on encrypted
5157 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5161 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5162 CVAL(inbuf,smb_wct) != 14) {
5163 DEBUG(10,("is_valid_writeX_buffer: chained or "
5164 "invalid word length.\n"));
5168 fnum = SVAL(inbuf, smb_vwv2);
5169 status = smb1srv_open_lookup(xconn,
5173 if (!NT_STATUS_IS_OK(status)) {
5174 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5179 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5182 if (fsp->conn == NULL) {
5183 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5187 if (IS_IPC(fsp->conn)) {
5188 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5191 if (IS_PRINT(fsp->conn)) {
5192 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5195 if (fsp->base_fsp != NULL) {
5196 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5199 doff = SVAL(inbuf,smb_vwv11);
5201 numtowrite = SVAL(inbuf,smb_vwv10);
5203 if (len > doff && len - doff > 0xFFFF) {
5204 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5207 if (numtowrite == 0) {
5208 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5212 /* Ensure the sizes match up. */
5213 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5214 /* no pad byte...old smbclient :-( */
5215 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5217 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5221 if (len - doff != numtowrite) {
5222 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5223 "len = %u, doff = %u, numtowrite = %u\n",
5226 (unsigned int)numtowrite ));
5230 DEBUG(10,("is_valid_writeX_buffer: true "
5231 "len = %u, doff = %u, numtowrite = %u\n",
5234 (unsigned int)numtowrite ));
5239 /****************************************************************************
5240 Reply to a write and X.
5241 ****************************************************************************/
5243 void reply_write_and_X(struct smb_request *req)
5245 connection_struct *conn = req->conn;
5246 struct smbXsrv_connection *xconn = req->xconn;
5248 struct lock_struct lock;
5253 unsigned int smb_doff;
5254 unsigned int smblen;
5257 int saved_errno = 0;
5259 START_PROFILE(SMBwriteX);
5261 if ((req->wct != 12) && (req->wct != 14)) {
5262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5266 numtowrite = SVAL(req->vwv+10, 0);
5267 smb_doff = SVAL(req->vwv+11, 0);
5268 smblen = smb_len(req->inbuf);
5270 if (req->unread_bytes > 0xFFFF ||
5271 (smblen > smb_doff &&
5272 smblen - smb_doff > 0xFFFF)) {
5273 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5276 if (req->unread_bytes) {
5277 /* Can't do a recvfile write on IPC$ */
5279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5282 if (numtowrite != req->unread_bytes) {
5283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5288 * This already protects us against CVE-2017-12163.
5290 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5291 smb_doff + numtowrite > smblen) {
5292 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5297 /* If it's an IPC, pass off the pipe handler. */
5299 if (req->unread_bytes) {
5300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5303 reply_pipe_write_and_X(req);
5307 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5308 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5309 write_through = BITSETW(req->vwv+7,0);
5311 if (!check_fsp(conn, req, fsp)) {
5315 if (!CHECK_WRITE(fsp)) {
5316 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5320 data = smb_base(req->inbuf) + smb_doff;
5322 if(req->wct == 14) {
5324 * This is a large offset (64 bit) write.
5326 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5330 /* X/Open SMB protocol says that, unlike SMBwrite
5331 if the length is zero then NO truncation is
5332 done, just a write of zero. To truncate a file,
5335 if(numtowrite == 0) {
5338 if (req->unread_bytes == 0) {
5339 status = schedule_aio_write_and_X(conn,
5346 if (NT_STATUS_IS_OK(status)) {
5347 /* write scheduled - we're done. */
5350 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5351 /* Real error - report to client. */
5352 reply_nterror(req, status);
5355 /* NT_STATUS_RETRY - fall through to sync write. */
5358 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5359 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5362 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5363 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5367 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5368 saved_errno = errno;
5372 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5376 if((nwritten == 0) && (numtowrite != 0)) {
5377 reply_nterror(req, NT_STATUS_DISK_FULL);
5381 reply_outbuf(req, 6, 0);
5382 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5383 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5384 SSVAL(req->outbuf,smb_vwv2,nwritten);
5385 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5387 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5388 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5390 status = sync_file(conn, fsp, write_through);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5393 fsp_str_dbg(fsp), nt_errstr(status)));
5394 reply_nterror(req, status);
5398 END_PROFILE(SMBwriteX);
5402 if (req->unread_bytes) {
5403 /* writeX failed. drain socket. */
5404 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5405 req->unread_bytes) {
5406 smb_panic("failed to drain pending bytes");
5408 req->unread_bytes = 0;
5411 END_PROFILE(SMBwriteX);
5415 /****************************************************************************
5417 ****************************************************************************/
5419 void reply_lseek(struct smb_request *req)
5421 connection_struct *conn = req->conn;
5428 START_PROFILE(SMBlseek);
5431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5432 END_PROFILE(SMBlseek);
5436 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5438 if (!check_fsp(conn, req, fsp)) {
5442 mode = SVAL(req->vwv+1, 0) & 3;
5443 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5444 startpos = (off_t)IVALS(req->vwv+2, 0);
5453 res = fh_get_pos(fsp->fh) + startpos;
5464 if (umode == SEEK_END) {
5465 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5466 if(errno == EINVAL) {
5467 off_t current_pos = startpos;
5469 status = vfs_stat_fsp(fsp);
5470 if (!NT_STATUS_IS_OK(status)) {
5471 reply_nterror(req, status);
5472 END_PROFILE(SMBlseek);
5476 current_pos += fsp->fsp_name->st.st_ex_size;
5478 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5483 reply_nterror(req, map_nt_error_from_unix(errno));
5484 END_PROFILE(SMBlseek);
5489 fh_set_pos(fsp->fh, res);
5491 reply_outbuf(req, 2, 0);
5492 SIVAL(req->outbuf,smb_vwv0,res);
5494 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5495 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5497 END_PROFILE(SMBlseek);
5501 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5504 connection_struct *conn = talloc_get_type_abort(
5505 private_data, connection_struct);
5507 if (conn != fsp->conn) {
5510 if (fsp_get_io_fd(fsp) == -1) {
5513 sync_file(conn, fsp, True /* write through */);
5515 if (fsp->fsp_flags.modified) {
5516 trigger_write_time_update_immediate(fsp);
5522 /****************************************************************************
5524 ****************************************************************************/
5526 void reply_flush(struct smb_request *req)
5528 connection_struct *conn = req->conn;
5532 START_PROFILE(SMBflush);
5535 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5539 fnum = SVAL(req->vwv+0, 0);
5540 fsp = file_fsp(req, fnum);
5542 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5547 files_forall(req->sconn, file_sync_one_fn, conn);
5549 NTSTATUS status = sync_file(conn, fsp, True);
5550 if (!NT_STATUS_IS_OK(status)) {
5551 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5552 fsp_str_dbg(fsp), nt_errstr(status)));
5553 reply_nterror(req, status);
5554 END_PROFILE(SMBflush);
5557 if (fsp->fsp_flags.modified) {
5558 trigger_write_time_update_immediate(fsp);
5562 reply_outbuf(req, 0, 0);
5564 DEBUG(3,("flush\n"));
5565 END_PROFILE(SMBflush);
5569 /****************************************************************************
5571 conn POINTER CAN BE NULL HERE !
5572 ****************************************************************************/
5574 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5575 static void reply_exit_done(struct tevent_req *req);
5577 void reply_exit(struct smb_request *smb1req)
5579 struct tevent_req *req;
5582 * Don't setup the profile charge here, take
5583 * it in reply_exit_done(). Not strictly correct
5584 * but better than the other SMB1 async
5585 * code that double-charges at the moment.
5587 req = reply_exit_send(smb1req);
5589 /* Not going async, profile here. */
5590 START_PROFILE(SMBexit);
5591 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5592 END_PROFILE(SMBexit);
5596 /* We're async. This will complete later. */
5597 tevent_req_set_callback(req, reply_exit_done, smb1req);
5601 struct reply_exit_state {
5602 struct tevent_queue *wait_queue;
5605 static void reply_exit_wait_done(struct tevent_req *subreq);
5607 /****************************************************************************
5609 Note, on failure here we deallocate and return NULL to allow the caller to
5610 SMB1 return an error of ERRnomem immediately.
5611 ****************************************************************************/
5613 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5615 struct tevent_req *req;
5616 struct reply_exit_state *state;
5617 struct tevent_req *subreq;
5619 struct smbd_server_connection *sconn = smb1req->sconn;
5621 req = tevent_req_create(smb1req, &state,
5622 struct reply_exit_state);
5626 state->wait_queue = tevent_queue_create(state,
5627 "reply_exit_wait_queue");
5628 if (tevent_req_nomem(state->wait_queue, req)) {
5633 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5634 if (fsp->file_pid != smb1req->smbpid) {
5637 if (fsp->vuid != smb1req->vuid) {
5641 * Flag the file as close in progress.
5642 * This will prevent any more IO being
5645 fsp->fsp_flags.closing = true;
5647 if (fsp->num_aio_requests > 0) {
5649 * Now wait until all aio requests on this fsp are
5652 * We don't set a callback, as we just want to block the
5653 * wait queue and the talloc_free() of fsp->aio_request
5654 * will remove the item from the wait queue.
5656 subreq = tevent_queue_wait_send(fsp->aio_requests,
5659 if (tevent_req_nomem(subreq, req)) {
5667 * Now we add our own waiter to the end of the queue,
5668 * this way we get notified when all pending requests are finished
5669 * and reply to the outstanding SMB1 request.
5671 subreq = tevent_queue_wait_send(state,
5674 if (tevent_req_nomem(subreq, req)) {
5680 * We're really going async - move the SMB1 request from
5681 * a talloc stackframe above us to the conn talloc-context.
5682 * We need this to stick around until the wait_done
5683 * callback is invoked.
5685 smb1req = talloc_move(sconn, &smb1req);
5687 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5692 static void reply_exit_wait_done(struct tevent_req *subreq)
5694 struct tevent_req *req = tevent_req_callback_data(
5695 subreq, struct tevent_req);
5697 tevent_queue_wait_recv(subreq);
5698 TALLOC_FREE(subreq);
5699 tevent_req_done(req);
5702 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5704 return tevent_req_simple_recv_ntstatus(req);
5707 static void reply_exit_done(struct tevent_req *req)
5709 struct smb_request *smb1req = tevent_req_callback_data(
5710 req, struct smb_request);
5711 struct smbd_server_connection *sconn = smb1req->sconn;
5712 struct smbXsrv_connection *xconn = smb1req->xconn;
5713 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5714 struct smbXsrv_session *session = NULL;
5715 files_struct *fsp, *next;
5719 * Take the profile charge here. Not strictly
5720 * correct but better than the other SMB1 async
5721 * code that double-charges at the moment.
5723 START_PROFILE(SMBexit);
5725 status = reply_exit_recv(req);
5727 if (!NT_STATUS_IS_OK(status)) {
5728 TALLOC_FREE(smb1req);
5729 END_PROFILE(SMBexit);
5730 exit_server(__location__ ": reply_exit_recv failed");
5735 * Ensure the session is still valid.
5737 status = smb1srv_session_lookup(xconn,
5741 if (!NT_STATUS_IS_OK(status)) {
5742 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5743 smb_request_done(smb1req);
5744 END_PROFILE(SMBexit);
5748 * Ensure the vuid is still valid - no one
5749 * called reply_ulogoffX() in the meantime.
5750 * reply_exit() doesn't have AS_USER set, so
5751 * use set_current_user_info() directly.
5752 * This is the same logic as in switch_message().
5754 if (session->global->auth_session_info != NULL) {
5755 set_current_user_info(
5756 session->global->auth_session_info->unix_info->sanitized_username,
5757 session->global->auth_session_info->unix_info->unix_name,
5758 session->global->auth_session_info->info->domain_name);
5761 /* No more aio - do the actual closes. */
5762 for (fsp = sconn->files; fsp; fsp = next) {
5766 if (fsp->file_pid != smb1req->smbpid) {
5769 if (fsp->vuid != smb1req->vuid) {
5772 if (!fsp->fsp_flags.closing) {
5777 * reply_exit() has the DO_CHDIR flag set.
5779 ok = chdir_current_service(fsp->conn);
5781 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5782 smb_request_done(smb1req);
5783 END_PROFILE(SMBexit);
5785 close_file(NULL, fsp, SHUTDOWN_CLOSE);
5788 reply_outbuf(smb1req, 0, 0);
5790 * The following call is needed to push the
5791 * reply data back out the socket after async
5792 * return. Plus it frees smb1req.
5794 smb_request_done(smb1req);
5795 DBG_INFO("reply_exit complete\n");
5796 END_PROFILE(SMBexit);
5800 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5802 static void reply_close_done(struct tevent_req *req);
5804 void reply_close(struct smb_request *smb1req)
5806 connection_struct *conn = smb1req->conn;
5807 NTSTATUS status = NT_STATUS_OK;
5808 files_struct *fsp = NULL;
5809 START_PROFILE(SMBclose);
5811 if (smb1req->wct < 3) {
5812 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5813 END_PROFILE(SMBclose);
5817 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5820 * We can only use check_fsp if we know it's not a directory.
5823 if (!check_fsp_open(conn, smb1req, fsp)) {
5824 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
5825 END_PROFILE(SMBclose);
5829 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5830 fsp->fsp_flags.is_directory ?
5831 "directory" : "file",
5832 fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
5833 conn->num_files_open);
5835 if (!fsp->fsp_flags.is_directory) {
5839 * Take care of any time sent in the close.
5842 t = srv_make_unix_date3(smb1req->vwv+1);
5843 set_close_write_time(fsp, time_t_to_full_timespec(t));
5846 if (fsp->num_aio_requests != 0) {
5847 struct tevent_req *req;
5849 req = reply_close_send(smb1req, fsp);
5851 status = NT_STATUS_NO_MEMORY;
5854 /* We're async. This will complete later. */
5855 tevent_req_set_callback(req, reply_close_done, smb1req);
5856 END_PROFILE(SMBclose);
5861 * close_file() returns the unix errno if an error was detected on
5862 * close - normally this is due to a disk full error. If not then it
5863 * was probably an I/O error.
5866 status = close_file(smb1req, fsp, NORMAL_CLOSE);
5868 if (!NT_STATUS_IS_OK(status)) {
5869 reply_nterror(smb1req, status);
5870 END_PROFILE(SMBclose);
5874 reply_outbuf(smb1req, 0, 0);
5875 END_PROFILE(SMBclose);
5879 struct reply_close_state {
5881 struct tevent_queue *wait_queue;
5884 static void reply_close_wait_done(struct tevent_req *subreq);
5886 /****************************************************************************
5888 Note, on failure here we deallocate and return NULL to allow the caller to
5889 SMB1 return an error of ERRnomem immediately.
5890 ****************************************************************************/
5892 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5895 struct tevent_req *req;
5896 struct reply_close_state *state;
5897 struct tevent_req *subreq;
5898 struct smbd_server_connection *sconn = smb1req->sconn;
5900 req = tevent_req_create(smb1req, &state,
5901 struct reply_close_state);
5905 state->wait_queue = tevent_queue_create(state,
5906 "reply_close_wait_queue");
5907 if (tevent_req_nomem(state->wait_queue, req)) {
5913 * Flag the file as close in progress.
5914 * This will prevent any more IO being
5917 fsp->fsp_flags.closing = true;
5920 * Now wait until all aio requests on this fsp are
5923 * We don't set a callback, as we just want to block the
5924 * wait queue and the talloc_free() of fsp->aio_request
5925 * will remove the item from the wait queue.
5927 subreq = tevent_queue_wait_send(fsp->aio_requests,
5930 if (tevent_req_nomem(subreq, req)) {
5936 * Now we add our own waiter to the end of the queue,
5937 * this way we get notified when all pending requests are finished
5938 * and reply to the outstanding SMB1 request.
5940 subreq = tevent_queue_wait_send(state,
5943 if (tevent_req_nomem(subreq, req)) {
5949 * We're really going async - move the SMB1 request from
5950 * a talloc stackframe above us to the conn talloc-context.
5951 * We need this to stick around until the wait_done
5952 * callback is invoked.
5954 smb1req = talloc_move(sconn, &smb1req);
5956 tevent_req_set_callback(subreq, reply_close_wait_done, req);
5961 static void reply_close_wait_done(struct tevent_req *subreq)
5963 struct tevent_req *req = tevent_req_callback_data(
5964 subreq, struct tevent_req);
5966 tevent_queue_wait_recv(subreq);
5967 TALLOC_FREE(subreq);
5968 tevent_req_done(req);
5971 static NTSTATUS reply_close_recv(struct tevent_req *req)
5973 return tevent_req_simple_recv_ntstatus(req);
5976 static void reply_close_done(struct tevent_req *req)
5978 struct smb_request *smb1req = tevent_req_callback_data(
5979 req, struct smb_request);
5980 struct reply_close_state *state = tevent_req_data(req,
5981 struct reply_close_state);
5984 status = reply_close_recv(req);
5986 if (!NT_STATUS_IS_OK(status)) {
5987 TALLOC_FREE(smb1req);
5988 exit_server(__location__ ": reply_close_recv failed");
5992 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
5993 if (NT_STATUS_IS_OK(status)) {
5994 reply_outbuf(smb1req, 0, 0);
5996 reply_nterror(smb1req, status);
5999 * The following call is needed to push the
6000 * reply data back out the socket after async
6001 * return. Plus it frees smb1req.
6003 smb_request_done(smb1req);
6006 /****************************************************************************
6007 Reply to a writeclose (Core+ protocol).
6008 ****************************************************************************/
6010 void reply_writeclose(struct smb_request *req)
6012 connection_struct *conn = req->conn;
6015 ssize_t nwritten = -1;
6016 NTSTATUS close_status = NT_STATUS_OK;
6019 struct timespec mtime;
6021 struct lock_struct lock;
6023 START_PROFILE(SMBwriteclose);
6026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6027 END_PROFILE(SMBwriteclose);
6031 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6033 if (!check_fsp(conn, req, fsp)) {
6034 END_PROFILE(SMBwriteclose);
6037 if (!CHECK_WRITE(fsp)) {
6038 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6039 END_PROFILE(SMBwriteclose);
6043 numtowrite = SVAL(req->vwv+1, 0);
6044 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6045 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6046 data = (const char *)req->buf + 1;
6049 * Ensure client isn't asking us to write more than
6050 * they sent. CVE-2017-12163.
6052 remaining = smbreq_bufrem(req, data);
6053 if (numtowrite > remaining) {
6054 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6055 END_PROFILE(SMBwriteclose);
6059 if (fsp->print_file == NULL) {
6060 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6061 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6064 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6065 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6066 END_PROFILE(SMBwriteclose);
6071 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6073 set_close_write_time(fsp, mtime);
6076 * More insanity. W2K only closes the file if writelen > 0.
6080 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6081 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6082 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6085 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6086 "file %s\n", fsp_str_dbg(fsp)));
6087 close_status = close_file(req, fsp, NORMAL_CLOSE);
6091 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6092 reply_nterror(req, NT_STATUS_DISK_FULL);
6096 if(!NT_STATUS_IS_OK(close_status)) {
6097 reply_nterror(req, close_status);
6101 reply_outbuf(req, 1, 0);
6103 SSVAL(req->outbuf,smb_vwv0,nwritten);
6107 END_PROFILE(SMBwriteclose);
6112 #define DBGC_CLASS DBGC_LOCKING
6114 /****************************************************************************
6116 ****************************************************************************/
6118 static void reply_lock_done(struct tevent_req *subreq);
6120 void reply_lock(struct smb_request *req)
6122 struct tevent_req *subreq = NULL;
6123 connection_struct *conn = req->conn;
6125 struct smbd_lock_element *lck = NULL;
6127 START_PROFILE(SMBlock);
6130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6131 END_PROFILE(SMBlock);
6135 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6137 if (!check_fsp(conn, req, fsp)) {
6138 END_PROFILE(SMBlock);
6142 lck = talloc(req, struct smbd_lock_element);
6144 reply_nterror(req, NT_STATUS_NO_MEMORY);
6145 END_PROFILE(SMBlock);
6149 *lck = (struct smbd_lock_element) {
6150 .req_guid = smbd_request_guid(req, 0),
6151 .smblctx = req->smbpid,
6152 .brltype = WRITE_LOCK,
6153 .count = IVAL(req->vwv+1, 0),
6154 .offset = IVAL(req->vwv+3, 0),
6157 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6163 subreq = smbd_smb1_do_locks_send(
6169 false, /* large_offset */
6173 if (subreq == NULL) {
6174 reply_nterror(req, NT_STATUS_NO_MEMORY);
6175 END_PROFILE(SMBlock);
6178 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6179 END_PROFILE(SMBlock);
6182 static void reply_lock_done(struct tevent_req *subreq)
6184 struct smb_request *req = NULL;
6188 START_PROFILE(SMBlock);
6190 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6193 status = smbd_smb1_do_locks_recv(subreq);
6194 TALLOC_FREE(subreq);
6196 if (NT_STATUS_IS_OK(status)) {
6197 reply_outbuf(req, 0, 0);
6199 reply_nterror(req, status);
6202 ok = srv_send_smb(req->xconn,
6203 (char *)req->outbuf,
6206 IS_CONN_ENCRYPTED(req->conn),
6209 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6212 END_PROFILE(SMBlock);
6215 /****************************************************************************
6217 ****************************************************************************/
6219 void reply_unlock(struct smb_request *req)
6221 connection_struct *conn = req->conn;
6224 struct smbd_lock_element lck;
6226 START_PROFILE(SMBunlock);
6229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6230 END_PROFILE(SMBunlock);
6234 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6236 if (!check_fsp(conn, req, fsp)) {
6237 END_PROFILE(SMBunlock);
6241 lck = (struct smbd_lock_element) {
6242 .req_guid = smbd_request_guid(req, 0),
6243 .smblctx = req->smbpid,
6244 .brltype = UNLOCK_LOCK,
6245 .offset = IVAL(req->vwv+3, 0),
6246 .count = IVAL(req->vwv+1, 0),
6249 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 reply_nterror(req, status);
6253 END_PROFILE(SMBunlock);
6257 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6263 reply_outbuf(req, 0, 0);
6265 END_PROFILE(SMBunlock);
6270 #define DBGC_CLASS DBGC_ALL
6272 /****************************************************************************
6274 conn POINTER CAN BE NULL HERE !
6275 ****************************************************************************/
6277 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6278 static void reply_tdis_done(struct tevent_req *req);
6280 void reply_tdis(struct smb_request *smb1req)
6282 connection_struct *conn = smb1req->conn;
6283 struct tevent_req *req;
6286 * Don't setup the profile charge here, take
6287 * it in reply_tdis_done(). Not strictly correct
6288 * but better than the other SMB1 async
6289 * code that double-charges at the moment.
6293 /* Not going async, profile here. */
6294 START_PROFILE(SMBtdis);
6295 DBG_INFO("Invalid connection in tdis\n");
6296 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6297 END_PROFILE(SMBtdis);
6301 req = reply_tdis_send(smb1req);
6303 /* Not going async, profile here. */
6304 START_PROFILE(SMBtdis);
6305 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6306 END_PROFILE(SMBtdis);
6309 /* We're async. This will complete later. */
6310 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6314 struct reply_tdis_state {
6315 struct tevent_queue *wait_queue;
6318 static void reply_tdis_wait_done(struct tevent_req *subreq);
6320 /****************************************************************************
6322 Note, on failure here we deallocate and return NULL to allow the caller to
6323 SMB1 return an error of ERRnomem immediately.
6324 ****************************************************************************/
6326 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6328 struct tevent_req *req;
6329 struct reply_tdis_state *state;
6330 struct tevent_req *subreq;
6331 connection_struct *conn = smb1req->conn;
6334 req = tevent_req_create(smb1req, &state,
6335 struct reply_tdis_state);
6339 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6340 if (tevent_req_nomem(state->wait_queue, req)) {
6346 * Make sure that no new request will be able to use this tcon.
6347 * This ensures that once all outstanding fsp->aio_requests
6348 * on this tcon are done, we are safe to close it.
6350 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6352 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6353 if (fsp->conn != conn) {
6357 * Flag the file as close in progress.
6358 * This will prevent any more IO being
6359 * done on it. Not strictly needed, but
6360 * doesn't hurt to flag it as closing.
6362 fsp->fsp_flags.closing = true;
6364 if (fsp->num_aio_requests > 0) {
6366 * Now wait until all aio requests on this fsp are
6369 * We don't set a callback, as we just want to block the
6370 * wait queue and the talloc_free() of fsp->aio_request
6371 * will remove the item from the wait queue.
6373 subreq = tevent_queue_wait_send(fsp->aio_requests,
6374 conn->sconn->ev_ctx,
6376 if (tevent_req_nomem(subreq, req)) {
6384 * Now we add our own waiter to the end of the queue,
6385 * this way we get notified when all pending requests are finished
6386 * and reply to the outstanding SMB1 request.
6388 subreq = tevent_queue_wait_send(state,
6389 conn->sconn->ev_ctx,
6391 if (tevent_req_nomem(subreq, req)) {
6397 * We're really going async - move the SMB1 request from
6398 * a talloc stackframe above us to the sconn talloc-context.
6399 * We need this to stick around until the wait_done
6400 * callback is invoked.
6402 smb1req = talloc_move(smb1req->sconn, &smb1req);
6404 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6409 static void reply_tdis_wait_done(struct tevent_req *subreq)
6411 struct tevent_req *req = tevent_req_callback_data(
6412 subreq, struct tevent_req);
6414 tevent_queue_wait_recv(subreq);
6415 TALLOC_FREE(subreq);
6416 tevent_req_done(req);
6419 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6421 return tevent_req_simple_recv_ntstatus(req);
6424 static void reply_tdis_done(struct tevent_req *req)
6426 struct smb_request *smb1req = tevent_req_callback_data(
6427 req, struct smb_request);
6429 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6433 * Take the profile charge here. Not strictly
6434 * correct but better than the other SMB1 async
6435 * code that double-charges at the moment.
6437 START_PROFILE(SMBtdis);
6439 status = reply_tdis_recv(req);
6441 if (!NT_STATUS_IS_OK(status)) {
6442 TALLOC_FREE(smb1req);
6443 END_PROFILE(SMBtdis);
6444 exit_server(__location__ ": reply_tdis_recv failed");
6449 * As we've been awoken, we may have changed
6450 * directory in the meantime.
6451 * reply_tdis() has the DO_CHDIR flag set.
6453 ok = chdir_current_service(smb1req->conn);
6455 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6456 smb_request_done(smb1req);
6457 END_PROFILE(SMBtdis);
6460 status = smbXsrv_tcon_disconnect(tcon,
6462 if (!NT_STATUS_IS_OK(status)) {
6463 TALLOC_FREE(smb1req);
6464 END_PROFILE(SMBtdis);
6465 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6469 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6470 smb1req->conn = NULL;
6474 reply_outbuf(smb1req, 0, 0);
6476 * The following call is needed to push the
6477 * reply data back out the socket after async
6478 * return. Plus it frees smb1req.
6480 smb_request_done(smb1req);
6481 END_PROFILE(SMBtdis);
6484 /****************************************************************************
6486 conn POINTER CAN BE NULL HERE !
6487 ****************************************************************************/
6489 void reply_echo(struct smb_request *req)
6491 connection_struct *conn = req->conn;
6492 struct smb_perfcount_data local_pcd;
6493 struct smb_perfcount_data *cur_pcd;
6497 START_PROFILE(SMBecho);
6499 smb_init_perfcount_data(&local_pcd);
6502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6503 END_PROFILE(SMBecho);
6507 smb_reverb = SVAL(req->vwv+0, 0);
6509 reply_outbuf(req, 1, req->buflen);
6511 /* copy any incoming data back out */
6512 if (req->buflen > 0) {
6513 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6516 if (smb_reverb > 100) {
6517 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6521 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6523 /* this makes sure we catch the request pcd */
6524 if (seq_num == smb_reverb) {
6525 cur_pcd = &req->pcd;
6527 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6528 cur_pcd = &local_pcd;
6531 SSVAL(req->outbuf,smb_vwv0,seq_num);
6533 show_msg((char *)req->outbuf);
6534 if (!srv_send_smb(req->xconn,
6535 (char *)req->outbuf,
6536 true, req->seqnum+1,
6537 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6539 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6542 DEBUG(3,("echo %d times\n", smb_reverb));
6544 TALLOC_FREE(req->outbuf);
6546 END_PROFILE(SMBecho);
6550 /****************************************************************************
6551 Reply to a printopen.
6552 ****************************************************************************/
6554 void reply_printopen(struct smb_request *req)
6556 connection_struct *conn = req->conn;
6560 START_PROFILE(SMBsplopen);
6563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6564 END_PROFILE(SMBsplopen);
6568 if (!CAN_PRINT(conn)) {
6569 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6570 END_PROFILE(SMBsplopen);
6574 status = file_new(req, conn, &fsp);
6575 if(!NT_STATUS_IS_OK(status)) {
6576 reply_nterror(req, status);
6577 END_PROFILE(SMBsplopen);
6581 /* Open for exclusive use, write only. */
6582 status = print_spool_open(fsp, NULL, req->vuid);
6584 if (!NT_STATUS_IS_OK(status)) {
6585 file_free(req, fsp);
6586 reply_nterror(req, status);
6587 END_PROFILE(SMBsplopen);
6591 reply_outbuf(req, 1, 0);
6592 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6594 DEBUG(3,("openprint fd=%d %s\n",
6595 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
6597 END_PROFILE(SMBsplopen);
6601 /****************************************************************************
6602 Reply to a printclose.
6603 ****************************************************************************/
6605 void reply_printclose(struct smb_request *req)
6607 connection_struct *conn = req->conn;
6611 START_PROFILE(SMBsplclose);
6614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6615 END_PROFILE(SMBsplclose);
6619 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6621 if (!check_fsp(conn, req, fsp)) {
6622 END_PROFILE(SMBsplclose);
6626 if (!CAN_PRINT(conn)) {
6627 reply_force_doserror(req, ERRSRV, ERRerror);
6628 END_PROFILE(SMBsplclose);
6632 DEBUG(3,("printclose fd=%d %s\n",
6633 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
6635 status = close_file(req, fsp, NORMAL_CLOSE);
6637 if(!NT_STATUS_IS_OK(status)) {
6638 reply_nterror(req, status);
6639 END_PROFILE(SMBsplclose);
6643 reply_outbuf(req, 0, 0);
6645 END_PROFILE(SMBsplclose);
6649 /****************************************************************************
6650 Reply to a printqueue.
6651 ****************************************************************************/
6653 void reply_printqueue(struct smb_request *req)
6655 const struct loadparm_substitution *lp_sub =
6656 loadparm_s3_global_substitution();
6657 connection_struct *conn = req->conn;
6661 START_PROFILE(SMBsplretq);
6664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6665 END_PROFILE(SMBsplretq);
6669 max_count = SVAL(req->vwv+0, 0);
6670 start_index = SVAL(req->vwv+1, 0);
6672 /* we used to allow the client to get the cnum wrong, but that
6673 is really quite gross and only worked when there was only
6674 one printer - I think we should now only accept it if they
6675 get it right (tridge) */
6676 if (!CAN_PRINT(conn)) {
6677 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6678 END_PROFILE(SMBsplretq);
6682 reply_outbuf(req, 2, 3);
6683 SSVAL(req->outbuf,smb_vwv0,0);
6684 SSVAL(req->outbuf,smb_vwv1,0);
6685 SCVAL(smb_buf(req->outbuf),0,1);
6686 SSVAL(smb_buf(req->outbuf),1,0);
6688 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6689 start_index, max_count));
6692 TALLOC_CTX *mem_ctx = talloc_tos();
6695 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6696 struct rpc_pipe_client *cli = NULL;
6697 struct dcerpc_binding_handle *b = NULL;
6698 struct policy_handle handle;
6699 struct spoolss_DevmodeContainer devmode_ctr;
6700 union spoolss_JobInfo *info;
6702 uint32_t num_to_get;
6706 ZERO_STRUCT(handle);
6708 status = rpc_pipe_open_interface(mem_ctx,
6711 conn->sconn->remote_address,
6712 conn->sconn->local_address,
6713 conn->sconn->msg_ctx,
6715 if (!NT_STATUS_IS_OK(status)) {
6716 DEBUG(0, ("reply_printqueue: "
6717 "could not connect to spoolss: %s\n",
6718 nt_errstr(status)));
6719 reply_nterror(req, status);
6722 b = cli->binding_handle;
6724 ZERO_STRUCT(devmode_ctr);
6726 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6729 SEC_FLAG_MAXIMUM_ALLOWED,
6732 if (!NT_STATUS_IS_OK(status)) {
6733 reply_nterror(req, status);
6736 if (!W_ERROR_IS_OK(werr)) {
6737 reply_nterror(req, werror_to_ntstatus(werr));
6741 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6749 if (!W_ERROR_IS_OK(werr)) {
6750 reply_nterror(req, werror_to_ntstatus(werr));
6754 if (max_count > 0) {
6755 first = start_index;
6757 first = start_index + max_count + 1;
6760 if (first >= count) {
6763 num_to_get = first + MIN(ABS(max_count), count - first);
6766 for (i = first; i < num_to_get; i++) {
6769 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6772 uint16_t qrapjobid = pjobid_to_rap(sharename,
6773 info[i].info2.job_id);
6775 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6781 srv_put_dos_date2(p, 0, qtime);
6782 SCVAL(p, 4, qstatus);
6783 SSVAL(p, 5, qrapjobid);
6784 SIVAL(p, 7, info[i].info2.size);
6786 status = srvstr_push(blob, req->flags2, p+12,
6787 info[i].info2.notify_name, 16, STR_ASCII, &len);
6788 if (!NT_STATUS_IS_OK(status)) {
6789 reply_nterror(req, status);
6792 if (message_push_blob(
6795 blob, sizeof(blob))) == -1) {
6796 reply_nterror(req, NT_STATUS_NO_MEMORY);
6802 SSVAL(req->outbuf,smb_vwv0,count);
6803 SSVAL(req->outbuf,smb_vwv1,
6804 (max_count>0?first+count:first-1));
6805 SCVAL(smb_buf(req->outbuf),0,1);
6806 SSVAL(smb_buf(req->outbuf),1,28*count);
6810 DEBUG(3, ("%u entries returned in queue\n",
6814 if (b && is_valid_policy_hnd(&handle)) {
6815 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6820 END_PROFILE(SMBsplretq);
6824 /****************************************************************************
6825 Reply to a printwrite.
6826 ****************************************************************************/
6828 void reply_printwrite(struct smb_request *req)
6830 connection_struct *conn = req->conn;
6835 START_PROFILE(SMBsplwr);
6838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6839 END_PROFILE(SMBsplwr);
6843 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6845 if (!check_fsp(conn, req, fsp)) {
6846 END_PROFILE(SMBsplwr);
6850 if (!fsp->print_file) {
6851 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6852 END_PROFILE(SMBsplwr);
6856 if (!CHECK_WRITE(fsp)) {
6857 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6858 END_PROFILE(SMBsplwr);
6862 numtowrite = SVAL(req->buf, 1);
6865 * This already protects us against CVE-2017-12163.
6867 if (req->buflen < numtowrite + 3) {
6868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6869 END_PROFILE(SMBsplwr);
6873 data = (const char *)req->buf + 3;
6875 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6876 reply_nterror(req, map_nt_error_from_unix(errno));
6877 END_PROFILE(SMBsplwr);
6881 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6883 reply_outbuf(req, 0, 0);
6885 END_PROFILE(SMBsplwr);
6889 /****************************************************************************
6891 ****************************************************************************/
6893 void reply_mkdir(struct smb_request *req)
6895 connection_struct *conn = req->conn;
6896 struct smb_filename *smb_dname = NULL;
6897 char *directory = NULL;
6900 TALLOC_CTX *ctx = talloc_tos();
6902 START_PROFILE(SMBmkdir);
6904 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6905 STR_TERMINATE, &status);
6906 if (!NT_STATUS_IS_OK(status)) {
6907 reply_nterror(req, status);
6911 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6912 status = filename_convert(ctx, conn,
6917 if (!NT_STATUS_IS_OK(status)) {
6918 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6919 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6920 ERRSRV, ERRbadpath);
6923 reply_nterror(req, status);
6927 status = create_directory(conn, req, smb_dname);
6929 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6931 if (!NT_STATUS_IS_OK(status)) {
6933 if (!use_nt_status()
6934 && NT_STATUS_EQUAL(status,
6935 NT_STATUS_OBJECT_NAME_COLLISION)) {
6937 * Yes, in the DOS error code case we get a
6938 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6939 * samba4 torture test.
6941 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6944 reply_nterror(req, status);
6948 reply_outbuf(req, 0, 0);
6950 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6952 TALLOC_FREE(smb_dname);
6953 END_PROFILE(SMBmkdir);
6957 /****************************************************************************
6959 ****************************************************************************/
6961 void reply_rmdir(struct smb_request *req)
6963 connection_struct *conn = req->conn;
6964 struct smb_filename *smb_dname = NULL;
6965 char *directory = NULL;
6967 TALLOC_CTX *ctx = talloc_tos();
6968 files_struct *fsp = NULL;
6970 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6972 START_PROFILE(SMBrmdir);
6974 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6975 STR_TERMINATE, &status);
6976 if (!NT_STATUS_IS_OK(status)) {
6977 reply_nterror(req, status);
6981 status = filename_convert(ctx, conn,
6986 if (!NT_STATUS_IS_OK(status)) {
6987 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6988 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6989 ERRSRV, ERRbadpath);
6992 reply_nterror(req, status);
6996 if (is_ntfs_stream_smb_fname(smb_dname)) {
6997 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7001 status = SMB_VFS_CREATE_FILE(
7004 smb_dname, /* fname */
7005 DELETE_ACCESS, /* access_mask */
7006 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7008 FILE_OPEN, /* create_disposition*/
7009 FILE_DIRECTORY_FILE, /* create_options */
7010 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7011 0, /* oplock_request */
7013 0, /* allocation_size */
7014 0, /* private_flags */
7019 NULL, NULL); /* create context */
7021 if (!NT_STATUS_IS_OK(status)) {
7022 if (open_was_deferred(req->xconn, req->mid)) {
7023 /* We have re-scheduled this call. */
7026 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7027 bool ok = defer_smb1_sharing_violation(req);
7032 reply_nterror(req, status);
7036 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7037 if (!NT_STATUS_IS_OK(status)) {
7038 close_file(req, fsp, ERROR_CLOSE);
7039 reply_nterror(req, status);
7043 if (!set_delete_on_close(fsp, true,
7044 conn->session_info->security_token,
7045 conn->session_info->unix_token)) {
7046 close_file(req, fsp, ERROR_CLOSE);
7047 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7051 status = close_file(req, fsp, NORMAL_CLOSE);
7052 if (!NT_STATUS_IS_OK(status)) {
7053 reply_nterror(req, status);
7055 reply_outbuf(req, 0, 0);
7058 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7060 TALLOC_FREE(smb_dname);
7061 END_PROFILE(SMBrmdir);
7065 /*******************************************************************
7066 Resolve wildcards in a filename rename.
7067 ********************************************************************/
7069 static bool resolve_wildcards(TALLOC_CTX *ctx,
7074 char *name2_copy = NULL;
7079 char *p,*p2, *pname1, *pname2;
7081 name2_copy = talloc_strdup(ctx, name2);
7086 pname1 = strrchr_m(name1,'/');
7087 pname2 = strrchr_m(name2_copy,'/');
7089 if (!pname1 || !pname2) {
7093 /* Truncate the copy of name2 at the last '/' */
7096 /* Now go past the '/' */
7100 root1 = talloc_strdup(ctx, pname1);
7101 root2 = talloc_strdup(ctx, pname2);
7103 if (!root1 || !root2) {
7107 p = strrchr_m(root1,'.');
7110 ext1 = talloc_strdup(ctx, p+1);
7112 ext1 = talloc_strdup(ctx, "");
7114 p = strrchr_m(root2,'.');
7117 ext2 = talloc_strdup(ctx, p+1);
7119 ext2 = talloc_strdup(ctx, "");
7122 if (!ext1 || !ext2) {
7130 /* Hmmm. Should this be mb-aware ? */
7133 } else if (*p2 == '*') {
7135 root2 = talloc_asprintf(ctx, "%s%s",
7154 /* Hmmm. Should this be mb-aware ? */
7157 } else if (*p2 == '*') {
7159 ext2 = talloc_asprintf(ctx, "%s%s",
7175 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7180 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7192 /****************************************************************************
7193 Ensure open files have their names updated. Updated to notify other smbd's
7195 ****************************************************************************/
7197 static void rename_open_files(connection_struct *conn,
7198 struct share_mode_lock *lck,
7200 uint32_t orig_name_hash,
7201 const struct smb_filename *smb_fname_dst)
7204 bool did_rename = False;
7206 uint32_t new_name_hash = 0;
7208 for(fsp = file_find_di_first(conn->sconn, id, false); fsp;
7209 fsp = file_find_di_next(fsp, false)) {
7210 struct file_id_buf idbuf;
7211 /* fsp_name is a relative path under the fsp. To change this for other
7212 sharepaths we need to manipulate relative paths. */
7213 /* TODO - create the absolute path and manipulate the newname
7214 relative to the sharepath. */
7215 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7218 if (fsp->name_hash != orig_name_hash) {
7221 DBG_DEBUG("renaming file %s "
7222 "(file_id %s) from %s -> %s\n",
7224 file_id_str_buf(fsp->file_id, &idbuf),
7226 smb_fname_str_dbg(smb_fname_dst));
7228 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7229 if (NT_STATUS_IS_OK(status)) {
7231 new_name_hash = fsp->name_hash;
7236 struct file_id_buf idbuf;
7237 DBG_DEBUG("no open files on file_id %s "
7239 file_id_str_buf(id, &idbuf),
7240 smb_fname_str_dbg(smb_fname_dst));
7243 /* Send messages to all smbd's (not ourself) that the name has changed. */
7244 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7245 orig_name_hash, new_name_hash,
7250 /****************************************************************************
7251 We need to check if the source path is a parent directory of the destination
7252 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7253 refuse the rename with a sharing violation. Under UNIX the above call can
7254 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7255 probably need to check that the client is a Windows one before disallowing
7256 this as a UNIX client (one with UNIX extensions) can know the source is a
7257 symlink and make this decision intelligently. Found by an excellent bug
7258 report from <AndyLiebman@aol.com>.
7259 ****************************************************************************/
7261 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7262 const struct smb_filename *smb_fname_dst)
7264 const char *psrc = smb_fname_src->base_name;
7265 const char *pdst = smb_fname_dst->base_name;
7268 if (psrc[0] == '.' && psrc[1] == '/') {
7271 if (pdst[0] == '.' && pdst[1] == '/') {
7274 if ((slen = strlen(psrc)) > strlen(pdst)) {
7277 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7281 * Do the notify calls from a rename
7284 static void notify_rename(connection_struct *conn, bool is_dir,
7285 const struct smb_filename *smb_fname_src,
7286 const struct smb_filename *smb_fname_dst)
7288 char *parent_dir_src = NULL;
7289 char *parent_dir_dst = NULL;
7292 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7293 : FILE_NOTIFY_CHANGE_FILE_NAME;
7295 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7296 &parent_dir_src, NULL) ||
7297 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7298 &parent_dir_dst, NULL)) {
7302 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7303 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7304 smb_fname_src->base_name);
7305 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7306 smb_fname_dst->base_name);
7309 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7310 smb_fname_src->base_name);
7311 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7312 smb_fname_dst->base_name);
7315 /* this is a strange one. w2k3 gives an additional event for
7316 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7317 files, but not directories */
7319 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7320 FILE_NOTIFY_CHANGE_ATTRIBUTES
7321 |FILE_NOTIFY_CHANGE_CREATION,
7322 smb_fname_dst->base_name);
7325 TALLOC_FREE(parent_dir_src);
7326 TALLOC_FREE(parent_dir_dst);
7329 /****************************************************************************
7330 Returns an error if the parent directory for a filename is open in an
7332 ****************************************************************************/
7334 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7335 const struct smb_filename *smb_fname_dst_in)
7337 struct smb_filename *smb_fname_parent = NULL;
7339 files_struct *fsp = NULL;
7343 status = SMB_VFS_PARENT_PATHNAME(conn,
7348 if (!NT_STATUS_IS_OK(status)) {
7352 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7354 return map_nt_error_from_unix(errno);
7358 * We're only checking on this smbd here, mostly good
7359 * enough.. and will pass tests.
7362 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7363 for (fsp = file_find_di_first(conn->sconn, id, true); fsp;
7364 fsp = file_find_di_next(fsp, true)) {
7365 if (fsp->access_mask & DELETE_ACCESS) {
7366 return NT_STATUS_SHARING_VIOLATION;
7369 return NT_STATUS_OK;
7372 /****************************************************************************
7373 Rename an open file - given an fsp.
7374 ****************************************************************************/
7376 NTSTATUS rename_internals_fsp(connection_struct *conn,
7378 struct smb_filename *smb_fname_dst_in,
7379 const char *dst_original_lcomp,
7381 bool replace_if_exists)
7383 TALLOC_CTX *ctx = talloc_tos();
7384 struct smb_filename *parent_dir_fname_dst = NULL;
7385 struct smb_filename *parent_dir_fname_dst_atname = NULL;
7386 struct smb_filename *parent_dir_fname_src = NULL;
7387 struct smb_filename *parent_dir_fname_src_atname = NULL;
7388 struct smb_filename *smb_fname_dst = NULL;
7389 NTSTATUS status = NT_STATUS_OK;
7390 struct share_mode_lock *lck = NULL;
7391 uint32_t access_mask = SEC_DIR_ADD_FILE;
7392 bool dst_exists, old_is_stream, new_is_stream;
7394 bool case_sensitive = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
7395 true : conn->case_sensitive;
7396 bool case_preserve = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
7397 true : conn->case_preserve;
7399 status = check_name(conn, smb_fname_dst_in);
7400 if (!NT_STATUS_IS_OK(status)) {
7404 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7405 if (!NT_STATUS_IS_OK(status)) {
7409 if (file_has_open_streams(fsp)) {
7410 return NT_STATUS_ACCESS_DENIED;
7413 /* Make a copy of the dst smb_fname structs */
7415 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7416 if (smb_fname_dst == NULL) {
7417 status = NT_STATUS_NO_MEMORY;
7422 * Check for special case with case preserving and not
7423 * case sensitive. If the new last component differs from the original
7424 * last component only by case, then we should allow
7425 * the rename (user is trying to change the case of the
7428 if (!case_sensitive && case_preserve &&
7429 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7430 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7431 char *fname_dst_parent = NULL;
7432 const char *fname_dst_lcomp = NULL;
7433 char *orig_lcomp_path = NULL;
7434 char *orig_lcomp_stream = NULL;
7438 * Split off the last component of the processed
7439 * destination name. We will compare this to
7440 * the split components of dst_original_lcomp.
7442 if (!parent_dirname(ctx,
7443 smb_fname_dst->base_name,
7445 &fname_dst_lcomp)) {
7446 status = NT_STATUS_NO_MEMORY;
7451 * The dst_original_lcomp component contains
7452 * the last_component of the path + stream
7453 * name (if a stream exists).
7455 * Split off the stream name so we
7456 * can check them separately.
7459 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7460 /* POSIX - no stream component. */
7461 orig_lcomp_path = talloc_strdup(ctx,
7462 dst_original_lcomp);
7463 if (orig_lcomp_path == NULL) {
7467 ok = split_stream_filename(ctx,
7470 &orig_lcomp_stream);
7474 TALLOC_FREE(fname_dst_parent);
7475 status = NT_STATUS_NO_MEMORY;
7479 /* If the base names only differ by case, use original. */
7480 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7483 * Replace the modified last component with the
7486 if (!ISDOT(fname_dst_parent)) {
7487 tmp = talloc_asprintf(smb_fname_dst,
7492 tmp = talloc_strdup(smb_fname_dst,
7496 status = NT_STATUS_NO_MEMORY;
7497 TALLOC_FREE(fname_dst_parent);
7498 TALLOC_FREE(orig_lcomp_path);
7499 TALLOC_FREE(orig_lcomp_stream);
7502 TALLOC_FREE(smb_fname_dst->base_name);
7503 smb_fname_dst->base_name = tmp;
7506 /* If the stream_names only differ by case, use original. */
7507 if(!strcsequal(smb_fname_dst->stream_name,
7508 orig_lcomp_stream)) {
7509 /* Use the original stream. */
7510 char *tmp = talloc_strdup(smb_fname_dst,
7513 status = NT_STATUS_NO_MEMORY;
7514 TALLOC_FREE(fname_dst_parent);
7515 TALLOC_FREE(orig_lcomp_path);
7516 TALLOC_FREE(orig_lcomp_stream);
7519 TALLOC_FREE(smb_fname_dst->stream_name);
7520 smb_fname_dst->stream_name = tmp;
7522 TALLOC_FREE(fname_dst_parent);
7523 TALLOC_FREE(orig_lcomp_path);
7524 TALLOC_FREE(orig_lcomp_stream);
7528 * If the src and dest names are identical - including case,
7529 * don't do the rename, just return success.
7532 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7533 strcsequal(fsp->fsp_name->stream_name,
7534 smb_fname_dst->stream_name)) {
7535 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7536 "- returning success\n",
7537 smb_fname_str_dbg(smb_fname_dst)));
7538 status = NT_STATUS_OK;
7542 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7543 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7545 /* Return the correct error code if both names aren't streams. */
7546 if (!old_is_stream && new_is_stream) {
7547 status = NT_STATUS_OBJECT_NAME_INVALID;
7551 if (old_is_stream && !new_is_stream) {
7552 status = NT_STATUS_INVALID_PARAMETER;
7556 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7558 if(!replace_if_exists && dst_exists) {
7559 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7560 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7561 smb_fname_str_dbg(smb_fname_dst)));
7562 status = NT_STATUS_OBJECT_NAME_COLLISION;
7567 * Drop the pathref fsp on the destination otherwise we trip upon in in
7568 * the below check for open files check.
7570 if (smb_fname_dst_in->fsp != NULL) {
7571 fd_close(smb_fname_dst_in->fsp);
7572 file_free(NULL, smb_fname_dst_in->fsp);
7573 SMB_ASSERT(smb_fname_dst_in->fsp == NULL);
7577 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7578 &smb_fname_dst->st);
7579 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7581 /* The file can be open when renaming a stream */
7582 if (dst_fsp && !new_is_stream) {
7583 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7584 status = NT_STATUS_ACCESS_DENIED;
7589 /* Ensure we have a valid stat struct for the source. */
7590 status = vfs_stat_fsp(fsp);
7591 if (!NT_STATUS_IS_OK(status)) {
7595 status = can_rename(conn, fsp, attrs);
7597 if (!NT_STATUS_IS_OK(status)) {
7598 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7599 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7600 smb_fname_str_dbg(smb_fname_dst)));
7601 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7602 status = NT_STATUS_ACCESS_DENIED;
7606 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7607 status = NT_STATUS_ACCESS_DENIED;
7611 /* Do we have rights to move into the destination ? */
7612 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7613 /* We're moving a directory. */
7614 access_mask = SEC_DIR_ADD_SUBDIR;
7618 * Get a pathref on the destination parent directory, so
7619 * we can call check_parent_access_fsp().
7621 status = parent_pathref(ctx,
7624 &parent_dir_fname_dst,
7625 &parent_dir_fname_dst_atname);
7626 if (!NT_STATUS_IS_OK(status)) {
7630 status = check_parent_access_fsp(parent_dir_fname_dst->fsp,
7632 if (!NT_STATUS_IS_OK(status)) {
7633 DBG_INFO("check_parent_access_fsp on "
7634 "dst %s returned %s\n",
7635 smb_fname_str_dbg(smb_fname_dst),
7641 * If the target existed, make sure the destination
7642 * atname has the same stat struct.
7644 parent_dir_fname_dst_atname->st = smb_fname_dst->st;
7647 * It's very common that source and
7648 * destination directories are the same.
7649 * Optimize by not opening the
7650 * second parent_pathref if we know
7654 status = SMB_VFS_PARENT_PATHNAME(conn,
7657 &parent_dir_fname_src,
7658 &parent_dir_fname_src_atname);
7659 if (!NT_STATUS_IS_OK(status)) {
7664 * We do a case-sensitive string comparison. We want to be *sure*
7665 * this is the same path. The worst that can happen if
7666 * the case doesn't match is we lose out on the optimization,
7667 * the code still works.
7669 * We can ignore twrp fields here. Rename is not allowed on
7670 * shadow copy handles.
7673 if (strcmp(parent_dir_fname_src->base_name,
7674 parent_dir_fname_dst->base_name) == 0) {
7676 * parent directory is the same for source
7679 /* Reparent the src_atname to the parent_dir_dest fname. */
7680 parent_dir_fname_src_atname = talloc_move(
7681 parent_dir_fname_dst,
7682 &parent_dir_fname_src_atname);
7683 /* Free the unneeded duplicate parent name. */
7684 TALLOC_FREE(parent_dir_fname_src);
7686 * And make the source parent name a copy of the
7687 * destination parent name.
7689 parent_dir_fname_src = parent_dir_fname_dst;
7692 * source and destingation parent directories are
7695 * Get a pathref on the source parent directory, so
7696 * we can do a relative rename.
7698 TALLOC_FREE(parent_dir_fname_src);
7699 status = parent_pathref(ctx,
7702 &parent_dir_fname_src,
7703 &parent_dir_fname_src_atname);
7704 if (!NT_STATUS_IS_OK(status)) {
7710 * Some modules depend on the source smb_fname having a valid stat.
7711 * The parent_dir_fname_src_atname is the relative name of the
7712 * currently open file, so just copy the stat from the open fsp.
7714 parent_dir_fname_src_atname->st = fsp->fsp_name->st;
7716 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7719 * We have the file open ourselves, so not being able to get the
7720 * corresponding share mode lock is a fatal error.
7723 SMB_ASSERT(lck != NULL);
7725 ret = SMB_VFS_RENAMEAT(conn,
7726 parent_dir_fname_src->fsp,
7727 parent_dir_fname_src_atname,
7728 parent_dir_fname_dst->fsp,
7729 parent_dir_fname_dst_atname);
7731 uint32_t create_options = fh_get_private_options(fsp->fh);
7733 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7734 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7735 smb_fname_str_dbg(smb_fname_dst)));
7738 fsp->fsp_flags.is_directory,
7742 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7745 if (!fsp->fsp_flags.is_directory &&
7746 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7747 (lp_map_archive(SNUM(conn)) ||
7748 lp_store_dos_attributes(SNUM(conn))))
7751 * We must set the archive bit on the newly renamed
7754 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
7756 uint32_t old_dosmode;
7757 old_dosmode = fdos_mode(fsp);
7759 * We can use fsp->fsp_name here as it has
7760 * already been changed to the new name.
7762 SMB_ASSERT(fsp->fsp_name->fsp == fsp);
7763 file_set_dosmode(conn,
7765 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7772 * A rename acts as a new file create w.r.t. allowing an initial delete
7773 * on close, probably because in Windows there is a new handle to the
7774 * new file. If initial delete on close was requested but not
7775 * originally set, we need to set it here. This is probably not 100% correct,
7776 * but will work for the CIFSFS client which in non-posix mode
7777 * depends on these semantics. JRA.
7780 if (create_options & FILE_DELETE_ON_CLOSE) {
7781 status = can_set_delete_on_close(fsp, 0);
7783 if (NT_STATUS_IS_OK(status)) {
7784 /* Note that here we set the *initial* delete on close flag,
7785 * not the regular one. The magic gets handled in close. */
7786 fsp->fsp_flags.initial_delete_on_close = true;
7790 status = NT_STATUS_OK;
7796 if (errno == ENOTDIR || errno == EISDIR) {
7797 status = NT_STATUS_OBJECT_NAME_COLLISION;
7799 status = map_nt_error_from_unix(errno);
7802 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7803 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7804 smb_fname_str_dbg(smb_fname_dst)));
7809 * parent_dir_fname_src may be a copy of parent_dir_fname_dst.
7810 * See the optimization for same source and destination directory
7811 * above. Only free one in that case.
7813 if (parent_dir_fname_src != parent_dir_fname_dst) {
7814 TALLOC_FREE(parent_dir_fname_src);
7816 TALLOC_FREE(parent_dir_fname_dst);
7817 TALLOC_FREE(smb_fname_dst);
7822 /****************************************************************************
7823 The guts of the rename command, split out so it may be called by the NT SMB
7825 ****************************************************************************/
7827 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7828 connection_struct *conn,
7829 struct smb_request *req,
7830 struct smb_filename *smb_fname_src,
7831 const char *src_original_lcomp,
7832 struct smb_filename *smb_fname_dst,
7833 const char *dst_original_lcomp,
7835 bool replace_if_exists,
7836 uint32_t access_mask)
7838 char *fname_src_dir = NULL;
7839 struct smb_filename *smb_fname_src_dir = NULL;
7840 char *fname_src_mask = NULL;
7842 NTSTATUS status = NT_STATUS_OK;
7843 struct smb_Dir *dir_hnd = NULL;
7844 const char *dname = NULL;
7845 char *talloced = NULL;
7847 int create_options = 0;
7848 struct smb2_create_blobs *posx = NULL;
7850 bool src_has_wild = false;
7851 bool dest_has_wild = false;
7852 bool posix_pathname = (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH);
7853 bool case_sensitive = posix_pathname ? true : conn->case_sensitive;
7854 bool case_preserve = posix_pathname ? true : conn->case_preserve;
7855 bool short_case_preserve = posix_pathname ? true :
7856 conn->short_case_preserve;
7859 * Split the old name into directory and last component
7860 * strings. Note that unix_convert may have stripped off a
7861 * leading ./ from both name and newname if the rename is
7862 * at the root of the share. We need to make sure either both
7863 * name and newname contain a / character or neither of them do
7864 * as this is checked in resolve_wildcards().
7867 /* Split up the directory from the filename/mask. */
7868 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7869 &fname_src_dir, &fname_src_mask);
7870 if (!NT_STATUS_IS_OK(status)) {
7871 status = NT_STATUS_NO_MEMORY;
7876 * We should only check the mangled cache
7877 * here if unix_convert failed. This means
7878 * that the path in 'mask' doesn't exist
7879 * on the file system and so we need to look
7880 * for a possible mangle. This patch from
7881 * Tine Smukavec <valentin.smukavec@hermes.si>.
7884 if (!VALID_STAT(smb_fname_src->st) &&
7886 mangle_is_mangled(fname_src_mask, conn->params)) {
7887 char *new_mask = NULL;
7888 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7891 TALLOC_FREE(fname_src_mask);
7892 fname_src_mask = new_mask;
7896 if (posix_pathname) {
7897 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7898 if (!NT_STATUS_IS_OK(status)) {
7899 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7905 if (!src_has_wild) {
7909 * Only one file needs to be renamed. Append the mask back
7910 * onto the directory.
7912 TALLOC_FREE(smb_fname_src->base_name);
7913 if (ISDOT(fname_src_dir)) {
7914 /* Ensure we use canonical names on open. */
7915 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7919 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7924 if (!smb_fname_src->base_name) {
7925 status = NT_STATUS_NO_MEMORY;
7929 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7930 "case_preserve = %d, short case preserve = %d, "
7931 "directory = %s, newname = %s, "
7932 "last_component_dest = %s\n",
7933 case_sensitive, case_preserve,
7934 short_case_preserve,
7935 smb_fname_str_dbg(smb_fname_src),
7936 smb_fname_str_dbg(smb_fname_dst),
7937 dst_original_lcomp));
7939 /* The dest name still may have wildcards. */
7940 if (dest_has_wild) {
7941 char *fname_dst_mod = NULL;
7942 if (!resolve_wildcards(smb_fname_dst,
7943 smb_fname_src->base_name,
7944 smb_fname_dst->base_name,
7946 DEBUG(6, ("rename_internals: resolve_wildcards "
7948 smb_fname_src->base_name,
7949 smb_fname_dst->base_name));
7950 status = NT_STATUS_NO_MEMORY;
7953 TALLOC_FREE(smb_fname_dst->base_name);
7954 smb_fname_dst->base_name = fname_dst_mod;
7957 ZERO_STRUCT(smb_fname_src->st);
7959 rc = vfs_stat(conn, smb_fname_src);
7961 status = map_nt_error_from_unix_common(errno);
7965 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
7966 if (!NT_STATUS_IS_OK(status)) {
7967 if (!NT_STATUS_EQUAL(status,
7968 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7972 * Possible symlink src.
7974 if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
7977 if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) {
7982 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7983 create_options |= FILE_DIRECTORY_FILE;
7986 status = SMB_VFS_CREATE_FILE(
7989 smb_fname_src, /* fname */
7990 access_mask, /* access_mask */
7991 (FILE_SHARE_READ | /* share_access */
7993 FILE_OPEN, /* create_disposition*/
7994 create_options, /* create_options */
7995 0, /* file_attributes */
7996 0, /* oplock_request */
7998 0, /* allocation_size */
7999 0, /* private_flags */
8004 posx, /* in_context_blobs */
8005 NULL); /* out_context_blobs */
8007 if (!NT_STATUS_IS_OK(status)) {
8008 DEBUG(3, ("Could not open rename source %s: %s\n",
8009 smb_fname_str_dbg(smb_fname_src),
8010 nt_errstr(status)));
8014 status = rename_internals_fsp(conn,
8021 close_file(req, fsp, NORMAL_CLOSE);
8023 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8024 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8025 smb_fname_str_dbg(smb_fname_dst)));
8031 * Wildcards - process each file that matches.
8033 if (strequal(fname_src_mask, "????????.???")) {
8034 TALLOC_FREE(fname_src_mask);
8035 fname_src_mask = talloc_strdup(ctx, "*");
8036 if (!fname_src_mask) {
8037 status = NT_STATUS_NO_MEMORY;
8042 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8046 smb_fname_src->twrp,
8047 smb_fname_src->flags);
8048 if (smb_fname_src_dir == NULL) {
8049 status = NT_STATUS_NO_MEMORY;
8053 status = check_name(conn, smb_fname_src_dir);
8054 if (!NT_STATUS_IS_OK(status)) {
8058 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8060 if (dir_hnd == NULL) {
8061 status = map_nt_error_from_unix(errno);
8065 status = NT_STATUS_NO_SUCH_FILE;
8067 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8068 * - gentest fix. JRA
8071 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8073 files_struct *fsp = NULL;
8074 char *destname = NULL;
8075 bool sysdir_entry = False;
8077 /* Quick check for "." and ".." */
8078 if (ISDOT(dname) || ISDOTDOT(dname)) {
8079 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8080 sysdir_entry = True;
8082 TALLOC_FREE(talloced);
8087 if(!mask_match(dname, fname_src_mask, case_sensitive)) {
8088 TALLOC_FREE(talloced);
8093 status = NT_STATUS_OBJECT_NAME_INVALID;
8097 TALLOC_FREE(smb_fname_src->base_name);
8098 if (ISDOT(fname_src_dir)) {
8099 /* Ensure we use canonical names on open. */
8100 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8104 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8109 if (!smb_fname_src->base_name) {
8110 status = NT_STATUS_NO_MEMORY;
8114 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8115 smb_fname_dst->base_name,
8117 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8118 smb_fname_src->base_name, destname));
8119 TALLOC_FREE(talloced);
8123 status = NT_STATUS_NO_MEMORY;
8127 TALLOC_FREE(smb_fname_dst->base_name);
8128 smb_fname_dst->base_name = destname;
8130 ZERO_STRUCT(smb_fname_src->st);
8131 vfs_stat(conn, smb_fname_src);
8133 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
8134 if (!NT_STATUS_IS_OK(status)) {
8135 DBG_INFO("openat_pathref_fsp [%s] failed: %s\n",
8136 smb_fname_str_dbg(smb_fname_src),
8141 if (!is_visible_fsp(smb_fname_src->fsp)) {
8142 TALLOC_FREE(talloced);
8148 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8149 create_options |= FILE_DIRECTORY_FILE;
8152 status = SMB_VFS_CREATE_FILE(
8155 smb_fname_src, /* fname */
8156 access_mask, /* access_mask */
8157 (FILE_SHARE_READ | /* share_access */
8159 FILE_OPEN, /* create_disposition*/
8160 create_options, /* create_options */
8161 0, /* file_attributes */
8162 0, /* oplock_request */
8164 0, /* allocation_size */
8165 0, /* private_flags */
8170 posx, /* in_context_blobs */
8171 NULL); /* out_context_blobs */
8173 if (!NT_STATUS_IS_OK(status)) {
8174 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8175 "returned %s rename %s -> %s\n",
8177 smb_fname_str_dbg(smb_fname_src),
8178 smb_fname_str_dbg(smb_fname_dst)));
8182 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8183 if (dst_original_lcomp == NULL) {
8184 status = NT_STATUS_NO_MEMORY;
8188 status = rename_internals_fsp(conn,
8195 close_file(req, fsp, NORMAL_CLOSE);
8197 if (!NT_STATUS_IS_OK(status)) {
8198 DEBUG(3, ("rename_internals_fsp returned %s for "
8199 "rename %s -> %s\n", nt_errstr(status),
8200 smb_fname_str_dbg(smb_fname_src),
8201 smb_fname_str_dbg(smb_fname_dst)));
8207 DEBUG(3,("rename_internals: doing rename on %s -> "
8208 "%s\n", smb_fname_str_dbg(smb_fname_src),
8209 smb_fname_str_dbg(smb_fname_src)));
8210 TALLOC_FREE(talloced);
8212 TALLOC_FREE(dir_hnd);
8214 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8215 status = map_nt_error_from_unix(errno);
8220 TALLOC_FREE(talloced);
8221 TALLOC_FREE(smb_fname_src_dir);
8222 TALLOC_FREE(fname_src_dir);
8223 TALLOC_FREE(fname_src_mask);
8227 /****************************************************************************
8229 ****************************************************************************/
8231 void reply_mv(struct smb_request *req)
8233 connection_struct *conn = req->conn;
8235 char *newname = NULL;
8239 TALLOC_CTX *ctx = talloc_tos();
8240 struct smb_filename *smb_fname_src = NULL;
8241 const char *src_original_lcomp = NULL;
8242 struct smb_filename *smb_fname_dst = NULL;
8243 const char *dst_original_lcomp = NULL;
8244 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req);
8245 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req);
8246 bool stream_rename = false;
8248 START_PROFILE(SMBmv);
8251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8255 attrs = SVAL(req->vwv+0, 0);
8257 p = (const char *)req->buf + 1;
8258 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
8260 if (!NT_STATUS_IS_OK(status)) {
8261 reply_nterror(req, status);
8265 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
8267 if (!NT_STATUS_IS_OK(status)) {
8268 reply_nterror(req, status);
8272 if (!req->posix_pathnames) {
8273 /* The newname must begin with a ':' if the
8274 name contains a ':'. */
8275 if (strchr_m(name, ':')) {
8276 if (newname[0] != ':') {
8277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8280 stream_rename = true;
8284 status = filename_convert(ctx,
8291 if (!NT_STATUS_IS_OK(status)) {
8292 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8293 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8294 ERRSRV, ERRbadpath);
8297 reply_nterror(req, status);
8301 /* Get the last component of the source for rename_internals(). */
8302 src_original_lcomp = get_original_lcomp(ctx,
8306 if (src_original_lcomp == NULL) {
8307 reply_nterror(req, NT_STATUS_NO_MEMORY);
8311 status = filename_convert(ctx,
8318 if (!NT_STATUS_IS_OK(status)) {
8319 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8320 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8321 ERRSRV, ERRbadpath);
8324 reply_nterror(req, status);
8328 /* Get the last component of the destination for rename_internals(). */
8329 dst_original_lcomp = get_original_lcomp(ctx,
8333 if (dst_original_lcomp == NULL) {
8334 reply_nterror(req, NT_STATUS_NO_MEMORY);
8338 if (stream_rename) {
8339 /* smb_fname_dst->base_name must be the same as
8340 smb_fname_src->base_name. */
8341 TALLOC_FREE(smb_fname_dst->base_name);
8342 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8343 smb_fname_src->base_name);
8344 if (!smb_fname_dst->base_name) {
8345 reply_nterror(req, NT_STATUS_NO_MEMORY);
8350 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8351 smb_fname_str_dbg(smb_fname_dst)));
8353 status = rename_internals(ctx,
8363 if (!NT_STATUS_IS_OK(status)) {
8364 if (open_was_deferred(req->xconn, req->mid)) {
8365 /* We have re-scheduled this call. */
8368 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8369 bool ok = defer_smb1_sharing_violation(req);
8374 reply_nterror(req, status);
8378 reply_outbuf(req, 0, 0);
8380 TALLOC_FREE(smb_fname_src);
8381 TALLOC_FREE(smb_fname_dst);
8386 /*******************************************************************
8387 Copy a file as part of a reply_copy.
8388 ******************************************************************/
8391 * TODO: check error codes on all callers
8394 NTSTATUS copy_file(TALLOC_CTX *ctx,
8395 connection_struct *conn,
8396 struct smb_filename *smb_fname_src,
8397 struct smb_filename *smb_fname_dst,
8400 bool target_is_directory)
8402 struct smb_filename *smb_fname_dst_tmp = NULL;
8404 files_struct *fsp1,*fsp2;
8406 uint32_t new_create_disposition;
8410 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8411 if (smb_fname_dst_tmp == NULL) {
8412 return NT_STATUS_NO_MEMORY;
8416 * If the target is a directory, extract the last component from the
8417 * src filename and append it to the dst filename
8419 if (target_is_directory) {
8422 /* dest/target can't be a stream if it's a directory. */
8423 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8425 p = strrchr_m(smb_fname_src->base_name,'/');
8429 p = smb_fname_src->base_name;
8431 smb_fname_dst_tmp->base_name =
8432 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8434 if (!smb_fname_dst_tmp->base_name) {
8435 status = NT_STATUS_NO_MEMORY;
8440 status = vfs_file_exist(conn, smb_fname_src);
8441 if (!NT_STATUS_IS_OK(status)) {
8445 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
8446 if (!NT_STATUS_IS_OK(status)) {
8450 if (!target_is_directory && count) {
8451 new_create_disposition = FILE_OPEN;
8453 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8456 &new_create_disposition,
8459 status = NT_STATUS_INVALID_PARAMETER;
8464 /* Open the src file for reading. */
8465 status = SMB_VFS_CREATE_FILE(
8468 smb_fname_src, /* fname */
8469 FILE_GENERIC_READ, /* access_mask */
8470 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8471 FILE_OPEN, /* create_disposition*/
8472 0, /* create_options */
8473 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8474 INTERNAL_OPEN_ONLY, /* oplock_request */
8476 0, /* allocation_size */
8477 0, /* private_flags */
8482 NULL, NULL); /* create context */
8484 if (!NT_STATUS_IS_OK(status)) {
8488 dosattrs = fdos_mode(fsp1);
8490 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8491 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8494 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_dst);
8495 if (!NT_STATUS_IS_OK(status) &&
8496 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
8501 /* Open the dst file for writing. */
8502 status = SMB_VFS_CREATE_FILE(
8505 smb_fname_dst, /* fname */
8506 FILE_GENERIC_WRITE, /* access_mask */
8507 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8508 new_create_disposition, /* create_disposition*/
8509 0, /* create_options */
8510 dosattrs, /* file_attributes */
8511 INTERNAL_OPEN_ONLY, /* oplock_request */
8513 0, /* allocation_size */
8514 0, /* private_flags */
8519 NULL, NULL); /* create context */
8521 if (!NT_STATUS_IS_OK(status)) {
8522 close_file(NULL, fsp1, ERROR_CLOSE);
8526 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8527 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8529 DEBUG(0, ("error - vfs lseek returned error %s\n",
8531 status = map_nt_error_from_unix(errno);
8532 close_file(NULL, fsp1, ERROR_CLOSE);
8533 close_file(NULL, fsp2, ERROR_CLOSE);
8538 /* Do the actual copy. */
8539 if (smb_fname_src->st.st_ex_size) {
8540 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8545 close_file(NULL, fsp1, NORMAL_CLOSE);
8547 /* Ensure the modtime is set correctly on the destination file. */
8548 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8551 * As we are opening fsp1 read-only we only expect
8552 * an error on close on fsp2 if we are out of space.
8553 * Thus we don't look at the error return from the
8556 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8558 if (!NT_STATUS_IS_OK(status)) {
8562 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8563 status = NT_STATUS_DISK_FULL;
8567 status = NT_STATUS_OK;
8570 TALLOC_FREE(smb_fname_dst_tmp);
8574 /****************************************************************************
8575 Reply to a file copy.
8579 This command was introduced in the LAN Manager 1.0 dialect
8580 It was rendered obsolete in the NT LAN Manager dialect.
8581 This command was used to perform server-side file copies, but
8582 is no longer used. Clients SHOULD
8583 NOT send requests using this command code.
8584 Servers receiving requests with this command code
8585 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
8586 ****************************************************************************/
8588 void reply_copy(struct smb_request *req)
8590 START_PROFILE(SMBcopy);
8591 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8592 END_PROFILE(SMBcopy);
8597 #define DBGC_CLASS DBGC_LOCKING
8599 /****************************************************************************
8600 Get a lock pid, dealing with large count requests.
8601 ****************************************************************************/
8603 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8604 bool large_file_format)
8606 if(!large_file_format)
8607 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8609 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8612 /****************************************************************************
8613 Get a lock count, dealing with large count requests.
8614 ****************************************************************************/
8616 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8617 bool large_file_format)
8621 if(!large_file_format) {
8622 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8625 * No BVAL, this is reversed!
8627 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8628 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8634 /****************************************************************************
8635 Get a lock offset, dealing with large offset requests.
8636 ****************************************************************************/
8638 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8639 bool large_file_format)
8641 uint64_t offset = 0;
8643 if(!large_file_format) {
8644 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8647 * No BVAL, this is reversed!
8649 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8650 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8656 struct smbd_do_unlocking_state {
8657 struct files_struct *fsp;
8658 uint16_t num_ulocks;
8659 struct smbd_lock_element *ulocks;
8660 enum brl_flavour lock_flav;
8664 static void smbd_do_unlocking_fn(
8667 bool *pmodified_dependent,
8670 struct smbd_do_unlocking_state *state = private_data;
8671 struct files_struct *fsp = state->fsp;
8672 enum brl_flavour lock_flav = state->lock_flav;
8675 for (i = 0; i < state->num_ulocks; i++) {
8676 struct smbd_lock_element *e = &state->ulocks[i];
8678 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
8679 "pid %"PRIu64", file %s\n",
8685 if (e->brltype != UNLOCK_LOCK) {
8686 /* this can only happen with SMB2 */
8687 state->status = NT_STATUS_INVALID_PARAMETER;
8691 state->status = do_unlock(
8692 fsp, e->smblctx, e->count, e->offset, lock_flav);
8694 DBG_DEBUG("do_unlock returned %s\n",
8695 nt_errstr(state->status));
8697 if (!NT_STATUS_IS_OK(state->status)) {
8702 *pmodified_dependent = true;
8705 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8707 uint16_t num_ulocks,
8708 struct smbd_lock_element *ulocks,
8709 enum brl_flavour lock_flav)
8711 struct smbd_do_unlocking_state state = {
8713 .num_ulocks = num_ulocks,
8715 .lock_flav = lock_flav,
8719 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
8721 status = share_mode_do_locked(
8722 fsp->file_id, smbd_do_unlocking_fn, &state);
8724 if (!NT_STATUS_IS_OK(status)) {
8725 DBG_DEBUG("share_mode_do_locked failed: %s\n",
8729 if (!NT_STATUS_IS_OK(state.status)) {
8730 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
8732 return state.status;
8735 return NT_STATUS_OK;
8738 /****************************************************************************
8739 Reply to a lockingX request.
8740 ****************************************************************************/
8742 static void reply_lockingx_done(struct tevent_req *subreq);
8744 void reply_lockingX(struct smb_request *req)
8746 connection_struct *conn = req->conn;
8748 unsigned char locktype;
8749 enum brl_type brltype;
8750 unsigned char oplocklevel;
8751 uint16_t num_ulocks;
8753 int32_t lock_timeout;
8755 const uint8_t *data;
8756 bool large_file_format;
8757 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8758 struct smbd_lock_element *locks = NULL;
8759 struct tevent_req *subreq = NULL;
8761 START_PROFILE(SMBlockingX);
8764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8765 END_PROFILE(SMBlockingX);
8769 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8770 locktype = CVAL(req->vwv+3, 0);
8771 oplocklevel = CVAL(req->vwv+3, 1);
8772 num_ulocks = SVAL(req->vwv+6, 0);
8773 num_locks = SVAL(req->vwv+7, 0);
8774 lock_timeout = IVAL(req->vwv+4, 0);
8775 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8777 if (!check_fsp(conn, req, fsp)) {
8778 END_PROFILE(SMBlockingX);
8784 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8785 /* we don't support these - and CANCEL_LOCK makes w2k
8786 and XP reboot so I don't really want to be
8787 compatible! (tridge) */
8788 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8789 END_PROFILE(SMBlockingX);
8793 /* Check if this is an oplock break on a file
8794 we have granted an oplock on.
8796 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8797 /* Client can insist on breaking to none. */
8798 bool break_to_none = (oplocklevel == 0);
8801 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8802 "for %s\n", (unsigned int)oplocklevel,
8803 fsp_fnum_dbg(fsp)));
8806 * Make sure we have granted an exclusive or batch oplock on
8810 if (fsp->oplock_type == 0) {
8812 /* The Samba4 nbench simulator doesn't understand
8813 the difference between break to level2 and break
8814 to none from level2 - it sends oplock break
8815 replies in both cases. Don't keep logging an error
8816 message here - just ignore it. JRA. */
8818 DEBUG(5,("reply_lockingX: Error : oplock break from "
8819 "client for %s (oplock=%d) and no "
8820 "oplock granted on this file (%s).\n",
8821 fsp_fnum_dbg(fsp), fsp->oplock_type,
8824 /* if this is a pure oplock break request then don't
8826 if (num_locks == 0 && num_ulocks == 0) {
8827 END_PROFILE(SMBlockingX);
8831 END_PROFILE(SMBlockingX);
8832 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8836 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8838 result = remove_oplock(fsp);
8840 result = downgrade_oplock(fsp);
8844 DEBUG(0, ("reply_lockingX: error in removing "
8845 "oplock on file %s\n", fsp_str_dbg(fsp)));
8846 /* Hmmm. Is this panic justified? */
8847 smb_panic("internal tdb error");
8850 /* if this is a pure oplock break request then don't send a
8852 if (num_locks == 0 && num_ulocks == 0) {
8853 /* Sanity check - ensure a pure oplock break is not a
8855 if (CVAL(req->vwv+0, 0) != 0xff) {
8856 DEBUG(0,("reply_lockingX: Error : pure oplock "
8857 "break is a chained %d request !\n",
8858 (unsigned int)CVAL(req->vwv+0, 0)));
8860 END_PROFILE(SMBlockingX);
8866 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8868 END_PROFILE(SMBlockingX);
8872 if (num_ulocks != 0) {
8873 struct smbd_lock_element *ulocks = NULL;
8876 ulocks = talloc_array(
8877 req, struct smbd_lock_element, num_ulocks);
8878 if (ulocks == NULL) {
8879 reply_nterror(req, NT_STATUS_NO_MEMORY);
8880 END_PROFILE(SMBlockingX);
8885 * Data now points at the beginning of the list of
8886 * smb_unlkrng structs
8888 for (i = 0; i < num_ulocks; i++) {
8889 ulocks[i].req_guid = smbd_request_guid(req,
8891 ulocks[i].smblctx = get_lock_pid(
8892 data, i, large_file_format);
8893 ulocks[i].count = get_lock_count(
8894 data, i, large_file_format);
8895 ulocks[i].offset = get_lock_offset(
8896 data, i, large_file_format);
8897 ulocks[i].brltype = UNLOCK_LOCK;
8901 * Unlock cancels pending locks
8904 ok = smbd_smb1_brl_finish_by_lock(
8911 reply_outbuf(req, 2, 0);
8912 SSVAL(req->outbuf, smb_vwv0, 0xff);
8913 SSVAL(req->outbuf, smb_vwv1, 0);
8914 END_PROFILE(SMBlockingX);
8918 status = smbd_do_unlocking(
8919 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
8920 TALLOC_FREE(ulocks);
8921 if (!NT_STATUS_IS_OK(status)) {
8922 END_PROFILE(SMBlockingX);
8923 reply_nterror(req, status);
8928 /* Now do any requested locks */
8929 data += ((large_file_format ? 20 : 10)*num_ulocks);
8931 /* Data now points at the beginning of the list
8932 of smb_lkrng structs */
8934 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8935 brltype = READ_LOCK;
8937 brltype = WRITE_LOCK;
8940 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8941 if (locks == NULL) {
8942 reply_nterror(req, NT_STATUS_NO_MEMORY);
8943 END_PROFILE(SMBlockingX);
8947 for (i = 0; i < num_locks; i++) {
8948 locks[i].req_guid = smbd_request_guid(req, i),
8949 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8950 locks[i].count = get_lock_count(data, i, large_file_format);
8951 locks[i].offset = get_lock_offset(data, i, large_file_format);
8952 locks[i].brltype = brltype;
8955 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8959 if (num_locks == 0) {
8960 /* See smbtorture3 lock11 test */
8961 reply_outbuf(req, 2, 0);
8962 /* andx chain ends */
8963 SSVAL(req->outbuf, smb_vwv0, 0xff);
8964 SSVAL(req->outbuf, smb_vwv1, 0);
8965 END_PROFILE(SMBlockingX);
8969 ok = smbd_smb1_brl_finish_by_lock(
8973 locks[0], /* Windows only cancels the first lock */
8974 NT_STATUS_FILE_LOCK_CONFLICT);
8977 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
8978 END_PROFILE(SMBlockingX);
8982 reply_outbuf(req, 2, 0);
8983 SSVAL(req->outbuf, smb_vwv0, 0xff);
8984 SSVAL(req->outbuf, smb_vwv1, 0);
8985 END_PROFILE(SMBlockingX);
8989 subreq = smbd_smb1_do_locks_send(
8999 if (subreq == NULL) {
9000 reply_nterror(req, NT_STATUS_NO_MEMORY);
9001 END_PROFILE(SMBlockingX);
9004 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9005 END_PROFILE(SMBlockingX);
9008 static void reply_lockingx_done(struct tevent_req *subreq)
9010 struct smb_request *req = NULL;
9014 START_PROFILE(SMBlockingX);
9016 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9019 status = smbd_smb1_do_locks_recv(subreq);
9020 TALLOC_FREE(subreq);
9022 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9024 if (NT_STATUS_IS_OK(status)) {
9025 reply_outbuf(req, 2, 0);
9026 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9027 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9029 reply_nterror(req, status);
9032 ok = srv_send_smb(req->xconn,
9033 (char *)req->outbuf,
9036 IS_CONN_ENCRYPTED(req->conn),
9039 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9042 END_PROFILE(SMBlockingX);
9046 #define DBGC_CLASS DBGC_ALL
9048 /****************************************************************************
9049 Reply to a SMBreadbmpx (read block multiplex) request.
9050 Always reply with an error, if someone has a platform really needs this,
9051 please contact vl@samba.org
9052 ****************************************************************************/
9054 void reply_readbmpx(struct smb_request *req)
9056 START_PROFILE(SMBreadBmpx);
9057 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9058 END_PROFILE(SMBreadBmpx);
9062 /****************************************************************************
9063 Reply to a SMBreadbs (read block multiplex secondary) request.
9064 Always reply with an error, if someone has a platform really needs this,
9065 please contact vl@samba.org
9066 ****************************************************************************/
9068 void reply_readbs(struct smb_request *req)
9070 START_PROFILE(SMBreadBs);
9071 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9072 END_PROFILE(SMBreadBs);
9076 /****************************************************************************
9077 Reply to a SMBsetattrE.
9078 ****************************************************************************/
9080 void reply_setattrE(struct smb_request *req)
9082 connection_struct *conn = req->conn;
9083 struct smb_file_time ft;
9087 START_PROFILE(SMBsetattrE);
9088 init_smb_file_time(&ft);
9091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9095 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9097 if(!fsp || (fsp->conn != conn)) {
9098 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9103 * Convert the DOS times into unix times.
9106 ft.atime = time_t_to_full_timespec(
9107 srv_make_unix_date2(req->vwv+3));
9108 ft.mtime = time_t_to_full_timespec(
9109 srv_make_unix_date2(req->vwv+5));
9110 ft.create_time = time_t_to_full_timespec(
9111 srv_make_unix_date2(req->vwv+1));
9113 reply_outbuf(req, 0, 0);
9116 * Patch from Ray Frush <frush@engr.colostate.edu>
9117 * Sometimes times are sent as zero - ignore them.
9120 /* Ensure we have a valid stat struct for the source. */
9121 status = vfs_stat_fsp(fsp);
9122 if (!NT_STATUS_IS_OK(status)) {
9123 reply_nterror(req, status);
9127 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9128 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9132 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9133 if (!NT_STATUS_IS_OK(status)) {
9134 reply_nterror(req, status);
9138 if (fsp->fsp_flags.modified) {
9139 trigger_write_time_update_immediate(fsp);
9142 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9145 (unsigned int)ft.atime.tv_sec,
9146 (unsigned int)ft.mtime.tv_sec,
9147 (unsigned int)ft.create_time.tv_sec
9150 END_PROFILE(SMBsetattrE);
9155 /* Back from the dead for OS/2..... JRA. */
9157 /****************************************************************************
9158 Reply to a SMBwritebmpx (write block multiplex primary) request.
9159 Always reply with an error, if someone has a platform really needs this,
9160 please contact vl@samba.org
9161 ****************************************************************************/
9163 void reply_writebmpx(struct smb_request *req)
9165 START_PROFILE(SMBwriteBmpx);
9166 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9167 END_PROFILE(SMBwriteBmpx);
9171 /****************************************************************************
9172 Reply to a SMBwritebs (write block multiplex secondary) request.
9173 Always reply with an error, if someone has a platform really needs this,
9174 please contact vl@samba.org
9175 ****************************************************************************/
9177 void reply_writebs(struct smb_request *req)
9179 START_PROFILE(SMBwriteBs);
9180 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9181 END_PROFILE(SMBwriteBs);
9185 /****************************************************************************
9186 Reply to a SMBgetattrE.
9187 ****************************************************************************/
9189 void reply_getattrE(struct smb_request *req)
9191 connection_struct *conn = req->conn;
9194 struct timespec create_ts;
9197 START_PROFILE(SMBgetattrE);
9200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9201 END_PROFILE(SMBgetattrE);
9205 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9207 if(!fsp || (fsp->conn != conn)) {
9208 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9209 END_PROFILE(SMBgetattrE);
9213 /* Do an fstat on this file */
9214 status = vfs_stat_fsp(fsp);
9215 if (!NT_STATUS_IS_OK(status)) {
9216 reply_nterror(req, status);
9217 END_PROFILE(SMBgetattrE);
9221 mode = fdos_mode(fsp);
9224 * Convert the times into dos times. Set create
9225 * date to be last modify date as UNIX doesn't save
9229 reply_outbuf(req, 11, 0);
9231 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9232 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9233 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9234 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9235 /* Should we check pending modtime here ? JRA */
9236 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9237 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9239 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9240 SIVAL(req->outbuf, smb_vwv6, 0);
9241 SIVAL(req->outbuf, smb_vwv8, 0);
9243 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9244 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9245 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9247 SSVAL(req->outbuf,smb_vwv10, mode);
9249 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9251 END_PROFILE(SMBgetattrE);