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 "fake_file.h"
35 #include "rpc_client/rpc_client.h"
36 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
37 #include "rpc_client/cli_spoolss.h"
38 #include "rpc_client/init_spoolss.h"
39 #include "rpc_server/rpc_ncacn_np.h"
40 #include "libcli/security/security.h"
41 #include "libsmb/nmblib.h"
43 #include "smbprofile.h"
44 #include "../lib/tsocket/tsocket.h"
45 #include "lib/util/tevent_ntstatus.h"
46 #include "libcli/smb/smb_signing.h"
47 #include "lib/util/sys_rw_data.h"
48 #include "librpc/gen_ndr/open_files.h"
49 #include "smb1_utils.h"
50 #include "libcli/smb/smb2_posix.h"
51 #include "lib/util/string_wrappers.h"
52 #include "source3/printing/rap_jobid.h"
54 /****************************************************************************
55 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
56 path or anything including wildcards.
57 We're assuming here that '/' is not the second byte in any multibyte char
58 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
60 ****************************************************************************/
62 /* Custom version for processing POSIX paths. */
63 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
65 static NTSTATUS check_path_syntax_internal(char *path,
70 NTSTATUS ret = NT_STATUS_OK;
71 bool start_of_name_component = True;
72 bool stream_started = false;
73 bool last_component_contains_wcard = false;
80 return NT_STATUS_OBJECT_NAME_INVALID;
83 return NT_STATUS_OBJECT_NAME_INVALID;
85 if (strchr_m(&s[1], ':')) {
86 return NT_STATUS_OBJECT_NAME_INVALID;
92 if ((*s == ':') && !posix_path && !stream_started) {
93 if (last_component_contains_wcard) {
94 return NT_STATUS_OBJECT_NAME_INVALID;
96 /* Stream names allow more characters than file names.
97 We're overloading posix_path here to allow a wider
98 range of characters. If stream_started is true this
99 is still a Windows path even if posix_path is true.
102 stream_started = true;
103 start_of_name_component = false;
107 return NT_STATUS_OBJECT_NAME_INVALID;
111 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
113 * Safe to assume is not the second part of a mb char
114 * as this is handled below.
116 /* Eat multiple '/' or '\\' */
117 while (IS_PATH_SEP(*s,posix_path)) {
120 if ((d != path) && (*s != '\0')) {
121 /* We only care about non-leading or trailing '/' or '\\' */
125 start_of_name_component = True;
127 last_component_contains_wcard = false;
131 if (start_of_name_component) {
132 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
133 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
136 * No mb char starts with '.' so we're safe checking the directory separator here.
139 /* If we just added a '/' - delete it */
140 if ((d > path) && (*(d-1) == '/')) {
145 /* Are we at the start ? Can't go back further if so. */
147 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
150 /* Go back one level... */
151 /* We know this is safe as '/' cannot be part of a mb sequence. */
152 /* NOTE - if this assumption is invalid we are not in good shape... */
153 /* Decrement d first as d points to the *next* char to write into. */
154 for (d--; d > path; d--) {
158 s += 2; /* Else go past the .. */
159 /* We're still at the start of a name component, just the previous one. */
162 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
174 if (*s <= 0x1f || *s == '|') {
175 return NT_STATUS_OBJECT_NAME_INVALID;
183 last_component_contains_wcard = true;
192 /* Get the size of the next MB character. */
193 next_codepoint(s,&siz);
211 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
213 return NT_STATUS_INVALID_PARAMETER;
216 start_of_name_component = False;
224 /****************************************************************************
225 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
226 No wildcards allowed.
227 ****************************************************************************/
229 NTSTATUS check_path_syntax(char *path)
231 return check_path_syntax_internal(path, false);
234 /****************************************************************************
235 Check the path for a POSIX client.
236 We're assuming here that '/' is not the second byte in any multibyte char
237 set (a safe assumption).
238 ****************************************************************************/
240 NTSTATUS check_path_syntax_posix(char *path)
242 return check_path_syntax_internal(path, true);
245 /****************************************************************************
246 Pull a string and check the path allowing a wildcard - provide for error return.
247 Passes in posix flag.
248 ****************************************************************************/
250 static size_t srvstr_get_path_internal(TALLOC_CTX *ctx,
251 const char *base_ptr,
257 bool posix_pathnames,
264 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
268 *err = NT_STATUS_INVALID_PARAMETER;
272 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
274 * For a DFS path the function parse_dfs_path()
275 * will do the path processing, just make a copy.
281 if (posix_pathnames) {
282 *err = check_path_syntax_posix(*pp_dest);
284 *err = check_path_syntax(*pp_dest);
290 /****************************************************************************
291 Pull a string and check the path - provide for error return.
292 ****************************************************************************/
294 size_t srvstr_get_path(TALLOC_CTX *ctx,
295 const char *base_ptr,
303 return srvstr_get_path_internal(ctx,
314 /****************************************************************************
315 Pull a string and check the path - provide for error return.
316 posix_pathnames version.
317 ****************************************************************************/
319 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
320 const char *base_ptr,
328 return srvstr_get_path_internal(ctx,
340 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
341 char **pp_dest, const char *src, int flags,
344 ssize_t bufrem = smbreq_bufrem(req, src);
347 *err = NT_STATUS_INVALID_PARAMETER;
351 if (req->posix_pathnames) {
352 return srvstr_get_path_internal(mem_ctx,
353 (const char *)req->inbuf,
362 return srvstr_get_path_internal(mem_ctx,
363 (const char *)req->inbuf,
375 * pull a string from the smb_buf part of a packet. In this case the
376 * string can either be null terminated or it can be terminated by the
377 * end of the smbbuf area
379 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
380 char **dest, const uint8_t *src, int flags)
382 ssize_t bufrem = smbreq_bufrem(req, src);
388 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
392 /****************************************************************************
393 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
394 ****************************************************************************/
396 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
399 if ((fsp == NULL) || (conn == NULL)) {
400 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
403 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
404 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
410 /****************************************************************************
411 Check if we have a correct fsp pointing to a file.
412 ****************************************************************************/
414 bool check_fsp(connection_struct *conn, struct smb_request *req,
417 if (!check_fsp_open(conn, req, fsp)) {
420 if (fsp->fsp_flags.is_directory) {
421 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
424 if (fsp_get_pathref_fd(fsp) == -1) {
425 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
428 fsp->num_smb_operations++;
432 /****************************************************************************
433 Check if we have a correct fsp pointing to a quota fake file. Replacement for
434 the CHECK_NTQUOTA_HANDLE_OK macro.
435 ****************************************************************************/
437 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
440 if (!check_fsp_open(conn, req, fsp)) {
444 if (fsp->fsp_flags.is_directory) {
448 if (fsp->fake_file_handle == NULL) {
452 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
456 if (fsp->fake_file_handle->private_data == NULL) {
463 /****************************************************************************
464 Return the port number we've bound to on a socket.
465 ****************************************************************************/
467 static int get_socket_port(int fd)
469 struct samba_sockaddr saddr = {
470 .sa_socklen = sizeof(struct sockaddr_storage),
477 if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
478 int level = (errno == ENOTCONN) ? 2 : 0;
479 DEBUG(level, ("getsockname failed. Error was %s\n",
484 #if defined(HAVE_IPV6)
485 if (saddr.u.sa.sa_family == AF_INET6) {
486 return ntohs(saddr.u.in6.sin6_port);
489 if (saddr.u.sa.sa_family == AF_INET) {
490 return ntohs(saddr.u.in.sin_port);
495 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
496 const char *name, int name_type)
499 char *trim_name_type;
500 const char *retarget_parm;
503 int retarget_type = 0x20;
504 int retarget_port = NBT_SMB_PORT;
505 struct sockaddr_storage retarget_addr;
506 struct sockaddr_in *in_addr;
510 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
514 trim_name = talloc_strdup(talloc_tos(), name);
515 if (trim_name == NULL) {
518 trim_char(trim_name, ' ', ' ');
520 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
522 if (trim_name_type == NULL) {
526 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
527 trim_name_type, NULL);
528 if (retarget_parm == NULL) {
529 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
532 if (retarget_parm == NULL) {
536 retarget = talloc_strdup(trim_name, retarget_parm);
537 if (retarget == NULL) {
541 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
543 p = strchr(retarget, ':');
546 retarget_port = atoi(p);
549 p = strchr_m(retarget, '#');
552 if (sscanf(p, "%x", &retarget_type) != 1) {
557 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
559 DEBUG(10, ("could not resolve %s\n", retarget));
563 if (retarget_addr.ss_family != AF_INET) {
564 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
568 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
570 _smb_setlen(outbuf, 6);
571 SCVAL(outbuf, 0, 0x84);
572 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
573 *(uint16_t *)(outbuf+8) = htons(retarget_port);
575 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
577 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
583 TALLOC_FREE(trim_name);
587 static void reply_called_name_not_present(char *outbuf)
589 smb_setlen(outbuf, 1);
590 SCVAL(outbuf, 0, 0x83);
591 SCVAL(outbuf, 4, 0x82);
594 /****************************************************************************
595 Reply to a (netbios-level) special message.
596 ****************************************************************************/
598 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
600 struct smbd_server_connection *sconn = xconn->client->sconn;
601 int msg_type = CVAL(inbuf,0);
602 int msg_flags = CVAL(inbuf,1);
604 * We only really use 4 bytes of the outbuf, but for the smb_setlen
605 * calculation & friends (srv_send_smb uses that) we need the full smb
608 char outbuf[smb_size];
610 memset(outbuf, '\0', sizeof(outbuf));
612 smb_setlen(outbuf,0);
615 case NBSSrequest: /* session request */
617 /* inbuf_size is guarenteed to be at least 4. */
619 int name_type1, name_type2;
620 int name_len1, name_len2;
624 if (xconn->transport.nbt.got_session) {
625 exit_server_cleanly("multiple session request not permitted");
628 SCVAL(outbuf,0,NBSSpositive);
631 /* inbuf_size is guaranteed to be at least 4. */
632 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
633 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
634 DEBUG(0,("Invalid name length in session request\n"));
635 reply_called_name_not_present(outbuf);
638 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
639 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
640 DEBUG(0,("Invalid name length in session request\n"));
641 reply_called_name_not_present(outbuf);
645 name_type1 = name_extract((unsigned char *)inbuf,
646 inbuf_size,(unsigned int)4,name1);
647 name_type2 = name_extract((unsigned char *)inbuf,
648 inbuf_size,(unsigned int)(4 + name_len1),name2);
650 if (name_type1 == -1 || name_type2 == -1) {
651 DEBUG(0,("Invalid name type in session request\n"));
652 reply_called_name_not_present(outbuf);
656 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
657 name1, name_type1, name2, name_type2));
659 if (netbios_session_retarget(xconn, name1, name_type1)) {
660 exit_server_cleanly("retargeted client");
664 * Windows NT/2k uses "*SMBSERVER" and XP uses
665 * "*SMBSERV" arrggg!!!
667 if (strequal(name1, "*SMBSERVER ")
668 || strequal(name1, "*SMBSERV ")) {
671 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
674 exit_server_cleanly("could not allocate raddr");
677 fstrcpy(name1, raddr);
680 set_local_machine_name(name1, True);
681 set_remote_machine_name(name2, True);
683 if (is_ipaddress(sconn->remote_hostname)) {
684 char *p = discard_const_p(char, sconn->remote_hostname);
688 sconn->remote_hostname = talloc_strdup(sconn,
689 get_remote_machine_name());
690 if (sconn->remote_hostname == NULL) {
691 exit_server_cleanly("could not copy remote name");
693 xconn->remote_hostname = sconn->remote_hostname;
696 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
697 get_local_machine_name(), get_remote_machine_name(),
700 if (name_type2 == 'R') {
701 /* We are being asked for a pathworks session ---
703 reply_called_name_not_present(outbuf);
707 reload_services(sconn, conn_snum_used, true);
710 xconn->transport.nbt.got_session = true;
714 case 0x89: /* session keepalive request
715 (some old clients produce this?) */
716 SCVAL(outbuf,0,NBSSkeepalive);
720 case NBSSpositive: /* positive session response */
721 case NBSSnegative: /* negative session response */
722 case NBSSretarget: /* retarget session response */
723 DEBUG(0,("Unexpected session response\n"));
726 case NBSSkeepalive: /* session keepalive */
731 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
732 msg_type, msg_flags));
734 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
735 exit_server_cleanly("reply_special: srv_send_smb failed.");
738 if (CVAL(outbuf, 0) != 0x82) {
739 exit_server_cleanly("invalid netbios session");
744 /****************************************************************************
746 conn POINTER CAN BE NULL HERE !
747 ****************************************************************************/
749 void reply_tcon(struct smb_request *req)
751 connection_struct *conn = req->conn;
753 char *service_buf = NULL;
754 char *password = NULL;
760 TALLOC_CTX *ctx = talloc_tos();
761 struct smbXsrv_connection *xconn = req->xconn;
762 NTTIME now = timeval_to_nttime(&req->request_time);
764 START_PROFILE(SMBtcon);
766 if (req->buflen < 4) {
767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
768 END_PROFILE(SMBtcon);
773 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
775 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
777 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
780 if (service_buf == NULL || password == NULL || dev == NULL) {
781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
782 END_PROFILE(SMBtcon);
785 p2 = strrchr_m(service_buf,'\\');
789 service = service_buf;
792 conn = make_connection(req, now, service, dev,
793 req->vuid,&nt_status);
797 reply_nterror(req, nt_status);
798 END_PROFILE(SMBtcon);
802 reply_outbuf(req, 2, 0);
803 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
804 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
805 SSVAL(req->outbuf,smb_tid,conn->cnum);
807 DEBUG(3,("tcon service=%s cnum=%d\n",
808 service, conn->cnum));
810 END_PROFILE(SMBtcon);
814 /****************************************************************************
815 Reply to a tcon and X.
816 conn POINTER CAN BE NULL HERE !
817 ****************************************************************************/
819 void reply_tcon_and_X(struct smb_request *req)
821 const struct loadparm_substitution *lp_sub =
822 loadparm_s3_global_substitution();
823 connection_struct *conn = req->conn;
824 const char *service = NULL;
825 TALLOC_CTX *ctx = talloc_tos();
826 /* what the client thinks the device is */
827 char *client_devicetype = NULL;
828 /* what the server tells the client the share represents */
829 const char *server_devicetype;
836 struct smbXsrv_session *session = NULL;
837 NTTIME now = timeval_to_nttime(&req->request_time);
838 bool session_key_updated = false;
839 uint16_t optional_support = 0;
840 struct smbXsrv_connection *xconn = req->xconn;
842 START_PROFILE(SMBtconX);
845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
846 END_PROFILE(SMBtconX);
850 passlen = SVAL(req->vwv+3, 0);
851 tcon_flags = SVAL(req->vwv+2, 0);
853 /* we might have to close an old one */
854 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
855 struct smbXsrv_tcon *tcon;
863 * TODO: cancel all outstanding requests on the tcon
865 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
866 if (!NT_STATUS_IS_OK(status)) {
867 DEBUG(0, ("reply_tcon_and_X: "
868 "smbXsrv_tcon_disconnect() failed: %s\n",
871 * If we hit this case, there is something completely
872 * wrong, so we better disconnect the transport connection.
874 END_PROFILE(SMBtconX);
875 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
881 * This tree id is gone. Make sure we can't re-use it
887 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
888 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
889 END_PROFILE(SMBtconX);
893 if (xconn->smb1.negprot.encrypted_passwords) {
894 p = req->buf + passlen;
896 p = req->buf + passlen + 1;
899 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
903 END_PROFILE(SMBtconX);
908 * the service name can be either: \\server\share
909 * or share directly like on the DELL PowerVault 705
912 q = strchr_m(path+2,'\\');
914 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
915 END_PROFILE(SMBtconX);
923 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
924 &client_devicetype, p,
925 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
927 if (client_devicetype == NULL) {
928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
929 END_PROFILE(SMBtconX);
933 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
935 nt_status = smb1srv_session_lookup(xconn,
936 req->vuid, now, &session);
937 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
938 reply_force_doserror(req, ERRSRV, ERRbaduid);
939 END_PROFILE(SMBtconX);
942 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
943 reply_nterror(req, nt_status);
944 END_PROFILE(SMBtconX);
947 if (!NT_STATUS_IS_OK(nt_status)) {
948 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
949 END_PROFILE(SMBtconX);
953 if (session->global->auth_session_info == NULL) {
954 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
955 END_PROFILE(SMBtconX);
960 * If there is no application key defined yet
963 * This means we setup the application key on the
964 * first tcon that happens via the given session.
966 * Once the application key is defined, it does not
969 if (session->global->application_key_blob.length == 0 &&
970 smb2_signing_key_valid(session->global->signing_key))
972 struct smbXsrv_session *x = session;
973 struct auth_session_info *session_info =
974 session->global->auth_session_info;
975 uint8_t session_key[16];
977 ZERO_STRUCT(session_key);
978 memcpy(session_key, x->global->signing_key->blob.data,
979 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
982 * The application key is truncated/padded to 16 bytes
984 x->global->application_key_blob = data_blob_talloc(x->global,
986 sizeof(session_key));
987 ZERO_STRUCT(session_key);
988 if (x->global->application_key_blob.data == NULL) {
989 reply_nterror(req, NT_STATUS_NO_MEMORY);
990 END_PROFILE(SMBtconX);
993 talloc_keep_secret(x->global->application_key_blob.data);
995 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
998 status = smb_key_derivation(x->global->application_key_blob.data,
999 x->global->application_key_blob.length,
1000 x->global->application_key_blob.data);
1001 if (!NT_STATUS_IS_OK(status)) {
1002 DBG_ERR("smb_key_derivation failed: %s\n",
1004 END_PROFILE(SMBtconX);
1007 optional_support |= SMB_EXTENDED_SIGNATURES;
1011 * Place the application key into the session_info
1013 data_blob_clear_free(&session_info->session_key);
1014 session_info->session_key = data_blob_dup_talloc(session_info,
1015 x->global->application_key_blob);
1016 if (session_info->session_key.data == NULL) {
1017 data_blob_clear_free(&x->global->application_key_blob);
1018 reply_nterror(req, NT_STATUS_NO_MEMORY);
1019 END_PROFILE(SMBtconX);
1022 talloc_keep_secret(session_info->session_key.data);
1023 session_key_updated = true;
1026 conn = make_connection(req, now, service, client_devicetype,
1027 req->vuid, &nt_status);
1031 if (session_key_updated) {
1032 struct smbXsrv_session *x = session;
1033 struct auth_session_info *session_info =
1034 session->global->auth_session_info;
1035 data_blob_clear_free(&x->global->application_key_blob);
1036 data_blob_clear_free(&session_info->session_key);
1038 reply_nterror(req, nt_status);
1039 END_PROFILE(SMBtconX);
1044 server_devicetype = "IPC";
1045 else if ( IS_PRINT(conn) )
1046 server_devicetype = "LPT1:";
1048 server_devicetype = "A:";
1050 if (get_Protocol() < PROTOCOL_NT1) {
1051 reply_outbuf(req, 2, 0);
1052 if (message_push_string(&req->outbuf, server_devicetype,
1053 STR_TERMINATE|STR_ASCII) == -1) {
1054 reply_nterror(req, NT_STATUS_NO_MEMORY);
1055 END_PROFILE(SMBtconX);
1059 /* NT sets the fstype of IPC$ to the null string */
1060 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1062 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1063 /* Return permissions. */
1067 reply_outbuf(req, 7, 0);
1070 perm1 = FILE_ALL_ACCESS;
1071 perm2 = FILE_ALL_ACCESS;
1073 perm1 = conn->share_access;
1076 SIVAL(req->outbuf, smb_vwv3, perm1);
1077 SIVAL(req->outbuf, smb_vwv5, perm2);
1079 reply_outbuf(req, 3, 0);
1082 if ((message_push_string(&req->outbuf, server_devicetype,
1083 STR_TERMINATE|STR_ASCII) == -1)
1084 || (message_push_string(&req->outbuf, fstype,
1085 STR_TERMINATE) == -1)) {
1086 reply_nterror(req, NT_STATUS_NO_MEMORY);
1087 END_PROFILE(SMBtconX);
1091 /* what does setting this bit do? It is set by NT4 and
1092 may affect the ability to autorun mounted cdroms */
1093 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1095 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1097 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1098 DEBUG(2,("Serving %s as a Dfs root\n",
1099 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1100 optional_support |= SMB_SHARE_IN_DFS;
1103 SSVAL(req->outbuf, smb_vwv2, optional_support);
1106 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1107 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1109 DEBUG(3,("tconX service=%s \n",
1112 /* set the incoming and outgoing tid to the just created one */
1113 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1114 SSVAL(req->outbuf,smb_tid,conn->cnum);
1116 END_PROFILE(SMBtconX);
1118 req->tid = conn->cnum;
1121 /****************************************************************************
1122 Reply to an unknown type.
1123 ****************************************************************************/
1125 void reply_unknown_new(struct smb_request *req, uint8_t type)
1127 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1128 smb_fn_name(type), type, type));
1129 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1133 /****************************************************************************
1135 conn POINTER CAN BE NULL HERE !
1136 ****************************************************************************/
1138 void reply_ioctl(struct smb_request *req)
1140 const struct loadparm_substitution *lp_sub =
1141 loadparm_s3_global_substitution();
1142 connection_struct *conn = req->conn;
1145 uint32_t ioctl_code;
1149 START_PROFILE(SMBioctl);
1152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1153 END_PROFILE(SMBioctl);
1157 device = SVAL(req->vwv+1, 0);
1158 function = SVAL(req->vwv+2, 0);
1159 ioctl_code = (device << 16) + function;
1161 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1163 switch (ioctl_code) {
1164 case IOCTL_QUERY_JOB_INFO:
1168 reply_force_doserror(req, ERRSRV, ERRnosupport);
1169 END_PROFILE(SMBioctl);
1173 reply_outbuf(req, 8, replysize+1);
1174 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1175 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1176 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1177 p = smb_buf(req->outbuf);
1178 memset(p, '\0', replysize+1); /* valgrind-safe. */
1179 p += 1; /* Allow for alignment */
1181 switch (ioctl_code) {
1182 case IOCTL_QUERY_JOB_INFO:
1186 files_struct *fsp = file_fsp(
1187 req, SVAL(req->vwv+0, 0));
1189 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1190 END_PROFILE(SMBioctl);
1194 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1196 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1197 lp_netbios_name(), 15,
1198 STR_TERMINATE|STR_ASCII, &len);
1199 if (!NT_STATUS_IS_OK(status)) {
1200 reply_nterror(req, status);
1201 END_PROFILE(SMBioctl);
1205 status = srvstr_push((char *)req->outbuf, req->flags2,
1207 lp_servicename(talloc_tos(),
1210 13, STR_TERMINATE|STR_ASCII, &len);
1211 if (!NT_STATUS_IS_OK(status)) {
1212 reply_nterror(req, status);
1213 END_PROFILE(SMBioctl);
1217 memset(p+18, 0, 13);
1223 END_PROFILE(SMBioctl);
1227 /****************************************************************************
1228 Strange checkpath NTSTATUS mapping.
1229 ****************************************************************************/
1231 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1233 /* Strange DOS error code semantics only for checkpath... */
1234 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1235 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1236 /* We need to map to ERRbadpath */
1237 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1243 /****************************************************************************
1244 Reply to a checkpath.
1245 ****************************************************************************/
1247 void reply_checkpath(struct smb_request *req)
1249 connection_struct *conn = req->conn;
1250 struct smb_filename *smb_fname = NULL;
1253 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1254 TALLOC_CTX *ctx = talloc_tos();
1256 START_PROFILE(SMBcheckpath);
1258 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1259 STR_TERMINATE, &status);
1261 if (!NT_STATUS_IS_OK(status)) {
1262 status = map_checkpath_error(req->flags2, status);
1263 reply_nterror(req, status);
1264 END_PROFILE(SMBcheckpath);
1268 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1270 status = filename_convert(ctx,
1277 if (!NT_STATUS_IS_OK(status)) {
1278 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1279 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1280 ERRSRV, ERRbadpath);
1281 END_PROFILE(SMBcheckpath);
1287 if (!VALID_STAT(smb_fname->st) &&
1288 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1289 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1290 smb_fname_str_dbg(smb_fname), strerror(errno)));
1291 status = map_nt_error_from_unix(errno);
1295 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1296 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1297 ERRDOS, ERRbadpath);
1301 reply_outbuf(req, 0, 0);
1304 /* We special case this - as when a Windows machine
1305 is parsing a path is steps through the components
1306 one at a time - if a component fails it expects
1307 ERRbadpath, not ERRbadfile.
1309 status = map_checkpath_error(req->flags2, status);
1310 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1312 * Windows returns different error codes if
1313 * the parent directory is valid but not the
1314 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1315 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1316 * if the path is invalid.
1318 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1319 ERRDOS, ERRbadpath);
1323 reply_nterror(req, status);
1326 TALLOC_FREE(smb_fname);
1327 END_PROFILE(SMBcheckpath);
1331 /****************************************************************************
1333 ****************************************************************************/
1335 void reply_getatr(struct smb_request *req)
1337 connection_struct *conn = req->conn;
1338 struct smb_filename *smb_fname = NULL;
1345 TALLOC_CTX *ctx = talloc_tos();
1346 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1348 START_PROFILE(SMBgetatr);
1350 p = (const char *)req->buf + 1;
1351 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 reply_nterror(req, status);
1357 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1358 under WfWg - weird! */
1359 if (*fname == '\0') {
1360 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1361 if (!CAN_WRITE(conn)) {
1362 mode |= FILE_ATTRIBUTE_READONLY;
1367 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1368 status = filename_convert(ctx,
1374 if (!NT_STATUS_IS_OK(status)) {
1375 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1376 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1377 ERRSRV, ERRbadpath);
1380 reply_nterror(req, status);
1383 if (!VALID_STAT(smb_fname->st) &&
1384 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1385 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1386 smb_fname_str_dbg(smb_fname),
1388 reply_nterror(req, map_nt_error_from_unix(errno));
1392 mode = fdos_mode(smb_fname->fsp);
1393 size = smb_fname->st.st_ex_size;
1395 if (ask_sharemode) {
1396 struct timespec write_time_ts;
1397 struct file_id fileid;
1399 ZERO_STRUCT(write_time_ts);
1400 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1401 get_file_infos(fileid, 0, NULL, &write_time_ts);
1402 if (!is_omit_timespec(&write_time_ts)) {
1403 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1407 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1408 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1413 reply_outbuf(req, 10, 0);
1415 SSVAL(req->outbuf,smb_vwv0,mode);
1416 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1417 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1419 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1421 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1423 if (get_Protocol() >= PROTOCOL_NT1) {
1424 SSVAL(req->outbuf, smb_flg2,
1425 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1428 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1429 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1432 TALLOC_FREE(smb_fname);
1434 END_PROFILE(SMBgetatr);
1438 /****************************************************************************
1440 ****************************************************************************/
1442 void reply_setatr(struct smb_request *req)
1444 struct smb_file_time ft;
1445 connection_struct *conn = req->conn;
1446 struct smb_filename *smb_fname = NULL;
1452 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1453 TALLOC_CTX *ctx = talloc_tos();
1455 START_PROFILE(SMBsetatr);
1456 init_smb_file_time(&ft);
1459 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1463 p = (const char *)req->buf + 1;
1464 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1465 if (!NT_STATUS_IS_OK(status)) {
1466 reply_nterror(req, status);
1470 status = filename_convert(ctx,
1476 if (!NT_STATUS_IS_OK(status)) {
1477 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1478 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1479 ERRSRV, ERRbadpath);
1482 reply_nterror(req, status);
1486 if (ISDOT(smb_fname->base_name)) {
1488 * Not sure here is the right place to catch this
1489 * condition. Might be moved to somewhere else later -- vl
1491 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1495 if (smb_fname->fsp == NULL) {
1496 /* Can't set access rights on a symlink. */
1497 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1501 mode = SVAL(req->vwv+0, 0);
1502 mtime = srv_make_unix_date3(req->vwv+1);
1504 if (mode != FILE_ATTRIBUTE_NORMAL) {
1505 if (VALID_STAT_OF_DIR(smb_fname->st))
1506 mode |= FILE_ATTRIBUTE_DIRECTORY;
1508 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1510 status = smbd_check_access_rights_fsp(smb_fname->fsp,
1512 FILE_WRITE_ATTRIBUTES);
1513 if (!NT_STATUS_IS_OK(status)) {
1514 reply_nterror(req, status);
1518 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1520 reply_nterror(req, map_nt_error_from_unix(errno));
1525 ft.mtime = time_t_to_full_timespec(mtime);
1527 status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
1528 if (!NT_STATUS_IS_OK(status)) {
1529 reply_nterror(req, status);
1533 reply_outbuf(req, 0, 0);
1535 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1538 TALLOC_FREE(smb_fname);
1539 END_PROFILE(SMBsetatr);
1543 /****************************************************************************
1545 ****************************************************************************/
1547 void reply_dskattr(struct smb_request *req)
1549 connection_struct *conn = req->conn;
1551 uint64_t dfree,dsize,bsize;
1552 struct smb_filename smb_fname;
1553 START_PROFILE(SMBdskattr);
1555 ZERO_STRUCT(smb_fname);
1556 smb_fname.base_name = discard_const_p(char, ".");
1558 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1559 reply_nterror(req, map_nt_error_from_unix(errno));
1560 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1561 END_PROFILE(SMBdskattr);
1565 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1566 if (ret == (uint64_t)-1) {
1567 reply_nterror(req, map_nt_error_from_unix(errno));
1568 END_PROFILE(SMBdskattr);
1573 * Force max to fit in 16 bit fields.
1575 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1579 if (bsize > (WORDMAX*512)) {
1580 bsize = (WORDMAX*512);
1581 if (dsize > WORDMAX)
1583 if (dfree > WORDMAX)
1589 reply_outbuf(req, 5, 0);
1591 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1592 double total_space, free_space;
1593 /* we need to scale this to a number that DOS6 can handle. We
1594 use floating point so we can handle large drives on systems
1595 that don't have 64 bit integers
1597 we end up displaying a maximum of 2G to DOS systems
1599 total_space = dsize * (double)bsize;
1600 free_space = dfree * (double)bsize;
1602 dsize = (uint64_t)((total_space+63*512) / (64*512));
1603 dfree = (uint64_t)((free_space+63*512) / (64*512));
1605 if (dsize > 0xFFFF) dsize = 0xFFFF;
1606 if (dfree > 0xFFFF) dfree = 0xFFFF;
1608 SSVAL(req->outbuf,smb_vwv0,dsize);
1609 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1610 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1611 SSVAL(req->outbuf,smb_vwv3,dfree);
1613 SSVAL(req->outbuf,smb_vwv0,dsize);
1614 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1615 SSVAL(req->outbuf,smb_vwv2,512);
1616 SSVAL(req->outbuf,smb_vwv3,dfree);
1619 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1621 END_PROFILE(SMBdskattr);
1626 * Utility function to split the filename from the directory.
1628 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1629 char **fname_dir_out,
1630 char **fname_mask_out)
1632 const char *p = NULL;
1633 char *fname_dir = NULL;
1634 char *fname_mask = NULL;
1636 p = strrchr_m(fname_in, '/');
1638 fname_dir = talloc_strdup(ctx, ".");
1639 fname_mask = talloc_strdup(ctx, fname_in);
1641 fname_dir = talloc_strndup(ctx, fname_in,
1642 PTR_DIFF(p, fname_in));
1643 fname_mask = talloc_strdup(ctx, p+1);
1646 if (!fname_dir || !fname_mask) {
1647 TALLOC_FREE(fname_dir);
1648 TALLOC_FREE(fname_mask);
1649 return NT_STATUS_NO_MEMORY;
1652 *fname_dir_out = fname_dir;
1653 *fname_mask_out = fname_mask;
1654 return NT_STATUS_OK;
1657 /****************************************************************************
1659 ****************************************************************************/
1661 static bool make_dir_struct(TALLOC_CTX *ctx,
1671 char *mask2 = talloc_strdup(ctx, mask);
1677 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1681 memset(buf+1,' ',11);
1682 if ((p = strchr_m(mask2,'.')) != NULL) {
1684 push_ascii(buf+1,mask2,8, 0);
1685 push_ascii(buf+9,p+1,3, 0);
1688 push_ascii(buf+1,mask2,11, 0);
1691 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1693 srv_put_dos_date(buf,22,date);
1694 SSVAL(buf,26,size & 0xFFFF);
1695 SSVAL(buf,28,(size >> 16)&0xFFFF);
1696 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1697 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1698 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1699 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1703 /****************************************************************************
1705 Can be called from SMBsearch, SMBffirst or SMBfunique.
1706 ****************************************************************************/
1708 void reply_search(struct smb_request *req)
1710 connection_struct *conn = req->conn;
1713 char *directory = NULL;
1714 struct smb_filename *smb_fname = NULL;
1718 struct timespec date;
1720 unsigned int numentries = 0;
1721 unsigned int maxentries = 0;
1722 bool finished = False;
1727 bool check_descend = False;
1728 bool expect_close = False;
1730 bool mask_contains_wcard = False;
1731 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1732 TALLOC_CTX *ctx = talloc_tos();
1733 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1734 struct smbXsrv_connection *xconn = req->xconn;
1735 struct smbd_server_connection *sconn = req->sconn;
1736 files_struct *fsp = NULL;
1737 const struct loadparm_substitution *lp_sub =
1738 loadparm_s3_global_substitution();
1740 START_PROFILE(SMBsearch);
1743 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1747 if (req->posix_pathnames) {
1748 reply_unknown_new(req, req->cmd);
1752 /* If we were called as SMBffirst then we must expect close. */
1753 if(req->cmd == SMBffirst) {
1754 expect_close = True;
1757 reply_outbuf(req, 1, 3);
1758 maxentries = SVAL(req->vwv+0, 0);
1759 dirtype = SVAL(req->vwv+1, 0);
1760 p = (const char *)req->buf + 1;
1761 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1763 if (!NT_STATUS_IS_OK(nt_status)) {
1764 reply_nterror(req, nt_status);
1768 if (smbreq_bufrem(req, p) < 3) {
1769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1774 status_len = SVAL(p, 0);
1777 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1779 if (status_len == 0) {
1781 struct smb_filename *smb_dname = NULL;
1782 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1783 ucf_flags_from_smb_request(req);
1784 nt_status = filename_convert(ctx, conn,
1789 if (!NT_STATUS_IS_OK(nt_status)) {
1790 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1791 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1792 ERRSRV, ERRbadpath);
1795 reply_nterror(req, nt_status);
1799 directory = smb_fname->base_name;
1801 p = strrchr_m(directory,'/');
1802 if ((p != NULL) && (*directory != '/')) {
1803 mask = talloc_strdup(ctx, p + 1);
1804 directory = talloc_strndup(ctx, directory,
1805 PTR_DIFF(p, directory));
1807 mask = talloc_strdup(ctx, directory);
1808 directory = talloc_strdup(ctx,".");
1812 reply_nterror(req, NT_STATUS_NO_MEMORY);
1816 memset((char *)status,'\0',21);
1817 SCVAL(status,0,(dirtype & 0x1F));
1819 smb_dname = synthetic_smb_fname(talloc_tos(),
1825 if (smb_dname == NULL) {
1826 reply_nterror(req, NT_STATUS_NO_MEMORY);
1831 * As we've cut off the last component from
1832 * smb_fname we need to re-stat smb_dname
1833 * so FILE_OPEN disposition knows the directory
1836 ret = vfs_stat(conn, smb_dname);
1838 nt_status = map_nt_error_from_unix(errno);
1839 reply_nterror(req, nt_status);
1843 nt_status = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
1844 if (!NT_STATUS_IS_OK(nt_status)) {
1845 reply_nterror(req, nt_status);
1850 * Open an fsp on this directory for the dptr.
1852 nt_status = SMB_VFS_CREATE_FILE(
1855 smb_dname, /* dname */
1856 FILE_LIST_DIRECTORY, /* access_mask */
1858 FILE_SHARE_WRITE, /* share_access */
1859 FILE_OPEN, /* create_disposition*/
1860 FILE_DIRECTORY_FILE, /* create_options */
1861 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1862 NO_OPLOCK, /* oplock_request */
1864 0, /* allocation_size */
1865 0, /* private_flags */
1870 NULL, /* in_context */
1871 NULL);/* out_context */
1873 if (!NT_STATUS_IS_OK(nt_status)) {
1874 DBG_ERR("failed to open directory %s\n",
1875 smb_fname_str_dbg(smb_dname));
1876 reply_nterror(req, nt_status);
1880 nt_status = dptr_create(conn,
1890 TALLOC_FREE(smb_dname);
1892 if (!NT_STATUS_IS_OK(nt_status)) {
1894 * Use NULL here for the first parameter (req)
1895 * as this is not a client visible handle so
1896 * can'tbe part of an SMB1 chain.
1898 close_file(NULL, fsp, NORMAL_CLOSE);
1900 reply_nterror(req, nt_status);
1904 dptr_num = dptr_dnum(fsp->dptr);
1908 const char *dirpath;
1910 if (smbreq_bufrem(req, p) < 21) {
1911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1915 memcpy(status,p,21);
1916 status_dirtype = CVAL(status,0) & 0x1F;
1917 if (status_dirtype != (dirtype & 0x1F)) {
1918 dirtype = status_dirtype;
1921 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1925 dirpath = dptr_path(sconn, dptr_num);
1926 directory = talloc_strdup(ctx, dirpath);
1928 reply_nterror(req, NT_STATUS_NO_MEMORY);
1932 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1936 dirtype = dptr_attr(sconn, dptr_num);
1939 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1941 DEBUG(4,("dptr_num is %d\n",dptr_num));
1943 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1944 char buf[DIR_STRUCT_SIZE];
1945 memcpy(buf,status,21);
1946 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1947 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1948 reply_nterror(req, NT_STATUS_NO_MEMORY);
1951 dptr_fill(sconn, buf+12,dptr_num);
1952 if (dptr_zero(buf+12) && (status_len==0)) {
1957 if (message_push_blob(&req->outbuf,
1958 data_blob_const(buf, sizeof(buf)))
1960 reply_nterror(req, NT_STATUS_NO_MEMORY);
1965 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1966 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1968 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1970 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1971 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1972 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1973 check_descend = True;
1976 for (i=numentries;(i<maxentries) && !finished;i++) {
1977 finished = !get_dir_entry(ctx,
1988 char buf[DIR_STRUCT_SIZE];
1989 memcpy(buf,status,21);
1990 if (!make_dir_struct(ctx,
1996 convert_timespec_to_time_t(date),
1997 !allow_long_path_components)) {
1998 reply_nterror(req, NT_STATUS_NO_MEMORY);
2001 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2004 if (message_push_blob(&req->outbuf,
2005 data_blob_const(buf, sizeof(buf)))
2007 reply_nterror(req, NT_STATUS_NO_MEMORY);
2017 /* If we were called as SMBffirst with smb_search_id == NULL
2018 and no entries were found then return error and close fsp->dptr
2021 if (numentries == 0) {
2024 close_file(NULL, fsp, NORMAL_CLOSE);
2027 } else if(expect_close && status_len == 0) {
2028 /* Close the dptr - we know it's gone */
2031 close_file(NULL, fsp, NORMAL_CLOSE);
2036 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2037 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2039 /* fsp may have been closed above. */
2041 close_file(NULL, fsp, NORMAL_CLOSE);
2046 if ((numentries == 0) && !mask_contains_wcard) {
2047 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2051 SSVAL(req->outbuf,smb_vwv0,numentries);
2052 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2053 SCVAL(smb_buf(req->outbuf),0,5);
2054 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2056 /* The replies here are never long name. */
2057 SSVAL(req->outbuf, smb_flg2,
2058 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2059 if (!allow_long_path_components) {
2060 SSVAL(req->outbuf, smb_flg2,
2061 SVAL(req->outbuf, smb_flg2)
2062 & (~FLAGS2_LONG_PATH_COMPONENTS));
2065 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2066 SSVAL(req->outbuf, smb_flg2,
2067 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2069 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2070 smb_fn_name(req->cmd),
2077 TALLOC_FREE(directory);
2079 TALLOC_FREE(smb_fname);
2080 END_PROFILE(SMBsearch);
2084 /****************************************************************************
2085 Reply to a fclose (stop directory search).
2086 ****************************************************************************/
2088 void reply_fclose(struct smb_request *req)
2096 TALLOC_CTX *ctx = talloc_tos();
2097 struct smbd_server_connection *sconn = req->sconn;
2098 files_struct *fsp = NULL;
2100 START_PROFILE(SMBfclose);
2102 if (req->posix_pathnames) {
2103 reply_unknown_new(req, req->cmd);
2104 END_PROFILE(SMBfclose);
2108 p = (const char *)req->buf + 1;
2109 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
2111 if (!NT_STATUS_IS_OK(err)) {
2112 reply_nterror(req, err);
2113 END_PROFILE(SMBfclose);
2117 if (smbreq_bufrem(req, p) < 3) {
2118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2119 END_PROFILE(SMBfclose);
2124 status_len = SVAL(p,0);
2127 if (status_len == 0) {
2128 reply_force_doserror(req, ERRSRV, ERRsrverror);
2129 END_PROFILE(SMBfclose);
2133 if (smbreq_bufrem(req, p) < 21) {
2134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2135 END_PROFILE(SMBfclose);
2139 memcpy(status,p,21);
2141 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2143 /* Close the file - we know it's gone */
2144 close_file(NULL, fsp, NORMAL_CLOSE);
2149 reply_outbuf(req, 1, 0);
2150 SSVAL(req->outbuf,smb_vwv0,0);
2152 DEBUG(3,("search close\n"));
2154 END_PROFILE(SMBfclose);
2158 /****************************************************************************
2160 ****************************************************************************/
2162 void reply_open(struct smb_request *req)
2164 connection_struct *conn = req->conn;
2165 struct smb_filename *smb_fname = NULL;
2175 uint32_t access_mask;
2176 uint32_t share_mode;
2177 uint32_t create_disposition;
2178 uint32_t create_options = 0;
2179 uint32_t private_flags = 0;
2182 TALLOC_CTX *ctx = talloc_tos();
2184 START_PROFILE(SMBopen);
2187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2191 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2192 deny_mode = SVAL(req->vwv+0, 0);
2193 dos_attr = SVAL(req->vwv+1, 0);
2195 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2196 STR_TERMINATE, &status);
2197 if (!NT_STATUS_IS_OK(status)) {
2198 reply_nterror(req, status);
2202 if (!map_open_params_to_ntcreate(fname, deny_mode,
2203 OPENX_FILE_EXISTS_OPEN, &access_mask,
2204 &share_mode, &create_disposition,
2205 &create_options, &private_flags)) {
2206 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2210 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2212 status = filename_convert(ctx,
2218 if (!NT_STATUS_IS_OK(status)) {
2219 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2220 reply_botherror(req,
2221 NT_STATUS_PATH_NOT_COVERED,
2222 ERRSRV, ERRbadpath);
2225 reply_nterror(req, status);
2229 status = SMB_VFS_CREATE_FILE(
2232 smb_fname, /* fname */
2233 access_mask, /* access_mask */
2234 share_mode, /* share_access */
2235 create_disposition, /* create_disposition*/
2236 create_options, /* create_options */
2237 dos_attr, /* file_attributes */
2238 oplock_request, /* oplock_request */
2240 0, /* allocation_size */
2246 NULL, NULL); /* create context */
2248 if (!NT_STATUS_IS_OK(status)) {
2249 if (open_was_deferred(req->xconn, req->mid)) {
2250 /* We have re-scheduled this call. */
2254 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2255 reply_openerror(req, status);
2259 fsp = fcb_or_dos_open(
2266 bool ok = defer_smb1_sharing_violation(req);
2270 reply_openerror(req, status);
2275 /* Ensure we're pointing at the correct stat struct. */
2276 TALLOC_FREE(smb_fname);
2277 smb_fname = fsp->fsp_name;
2279 size = smb_fname->st.st_ex_size;
2280 fattr = fdos_mode(fsp);
2282 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2284 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2285 DEBUG(3,("attempt to open a directory %s\n",
2287 close_file(req, fsp, ERROR_CLOSE);
2288 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2289 ERRDOS, ERRnoaccess);
2293 reply_outbuf(req, 7, 0);
2294 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2295 SSVAL(req->outbuf,smb_vwv1,fattr);
2296 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2297 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2299 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2301 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2302 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2304 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2305 SCVAL(req->outbuf,smb_flg,
2306 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2309 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2310 SCVAL(req->outbuf,smb_flg,
2311 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2314 END_PROFILE(SMBopen);
2318 /****************************************************************************
2319 Reply to an open and X.
2320 ****************************************************************************/
2322 void reply_open_and_X(struct smb_request *req)
2324 connection_struct *conn = req->conn;
2325 struct smb_filename *smb_fname = NULL;
2327 uint16_t open_flags;
2330 /* Breakout the oplock request bits so we can set the
2331 reply bits separately. */
2332 int ex_oplock_request;
2333 int core_oplock_request;
2336 int smb_sattr = SVAL(req->vwv+4, 0);
2337 uint32_t smb_time = make_unix_date3(req->vwv+6);
2345 uint64_t allocation_size;
2346 ssize_t retval = -1;
2347 uint32_t access_mask;
2348 uint32_t share_mode;
2349 uint32_t create_disposition;
2350 uint32_t create_options = 0;
2351 uint32_t private_flags = 0;
2353 TALLOC_CTX *ctx = talloc_tos();
2355 START_PROFILE(SMBopenX);
2357 if (req->wct < 15) {
2358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2362 open_flags = SVAL(req->vwv+2, 0);
2363 deny_mode = SVAL(req->vwv+3, 0);
2364 smb_attr = SVAL(req->vwv+5, 0);
2365 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2366 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2367 oplock_request = ex_oplock_request | core_oplock_request;
2368 smb_ofun = SVAL(req->vwv+8, 0);
2369 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2371 /* If it's an IPC, pass off the pipe handler. */
2373 if (lp_nt_pipe_support()) {
2374 reply_open_pipe_and_X(conn, req);
2376 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2381 /* XXXX we need to handle passed times, sattr and flags */
2382 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2383 STR_TERMINATE, &status);
2384 if (!NT_STATUS_IS_OK(status)) {
2385 reply_nterror(req, status);
2389 if (!map_open_params_to_ntcreate(fname, deny_mode,
2391 &access_mask, &share_mode,
2392 &create_disposition,
2395 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2399 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2401 status = filename_convert(ctx,
2407 if (!NT_STATUS_IS_OK(status)) {
2408 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2409 reply_botherror(req,
2410 NT_STATUS_PATH_NOT_COVERED,
2411 ERRSRV, ERRbadpath);
2414 reply_nterror(req, status);
2418 status = SMB_VFS_CREATE_FILE(
2421 smb_fname, /* fname */
2422 access_mask, /* access_mask */
2423 share_mode, /* share_access */
2424 create_disposition, /* create_disposition*/
2425 create_options, /* create_options */
2426 smb_attr, /* file_attributes */
2427 oplock_request, /* oplock_request */
2429 0, /* allocation_size */
2434 &smb_action, /* pinfo */
2435 NULL, NULL); /* create context */
2437 if (!NT_STATUS_IS_OK(status)) {
2438 if (open_was_deferred(req->xconn, req->mid)) {
2439 /* We have re-scheduled this call. */
2443 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2444 reply_openerror(req, status);
2448 fsp = fcb_or_dos_open(
2455 bool ok = defer_smb1_sharing_violation(req);
2459 reply_openerror(req, status);
2464 smb_action = FILE_WAS_OPENED;
2467 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2468 if the file is truncated or created. */
2469 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2470 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2471 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2472 close_file(req, fsp, ERROR_CLOSE);
2473 reply_nterror(req, NT_STATUS_DISK_FULL);
2476 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2478 close_file(req, fsp, ERROR_CLOSE);
2479 reply_nterror(req, NT_STATUS_DISK_FULL);
2482 status = vfs_stat_fsp(fsp);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 close_file(req, fsp, ERROR_CLOSE);
2485 reply_nterror(req, status);
2490 fattr = fdos_mode(fsp);
2491 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2492 close_file(req, fsp, ERROR_CLOSE);
2493 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2496 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2498 /* If the caller set the extended oplock request bit
2499 and we granted one (by whatever means) - set the
2500 correct bit for extended oplock reply.
2503 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2504 smb_action |= EXTENDED_OPLOCK_GRANTED;
2507 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2508 smb_action |= EXTENDED_OPLOCK_GRANTED;
2511 /* If the caller set the core oplock request bit
2512 and we granted one (by whatever means) - set the
2513 correct bit for core oplock reply.
2516 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2517 reply_outbuf(req, 19, 0);
2519 reply_outbuf(req, 15, 0);
2522 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2523 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2525 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2526 SCVAL(req->outbuf, smb_flg,
2527 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2530 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2531 SCVAL(req->outbuf, smb_flg,
2532 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2535 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2536 SSVAL(req->outbuf,smb_vwv3,fattr);
2537 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2538 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2540 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2542 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2543 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2544 SSVAL(req->outbuf,smb_vwv11,smb_action);
2546 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2547 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2551 TALLOC_FREE(smb_fname);
2552 END_PROFILE(SMBopenX);
2556 /****************************************************************************
2557 Reply to a SMBulogoffX.
2558 ****************************************************************************/
2560 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2561 struct smbXsrv_session *session);
2562 static void reply_ulogoffX_done(struct tevent_req *req);
2564 void reply_ulogoffX(struct smb_request *smb1req)
2566 struct timeval now = timeval_current();
2567 struct smbXsrv_session *session = NULL;
2568 struct tevent_req *req;
2572 * Don't setup the profile charge here, take
2573 * it in reply_ulogoffX_done(). Not strictly correct
2574 * but better than the other SMB1 async
2575 * code that double-charges at the moment.
2578 status = smb1srv_session_lookup(smb1req->xconn,
2580 timeval_to_nttime(&now),
2582 if (!NT_STATUS_IS_OK(status)) {
2583 /* Not going async, profile here. */
2584 START_PROFILE(SMBulogoffX);
2585 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2586 (unsigned long long)smb1req->vuid);
2588 smb1req->vuid = UID_FIELD_INVALID;
2589 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2590 END_PROFILE(SMBulogoffX);
2594 req = reply_ulogoffX_send(smb1req, session);
2596 /* Not going async, profile here. */
2597 START_PROFILE(SMBulogoffX);
2598 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2599 END_PROFILE(SMBulogoffX);
2603 /* We're async. This will complete later. */
2604 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2608 struct reply_ulogoffX_state {
2609 struct tevent_queue *wait_queue;
2610 struct smbXsrv_session *session;
2613 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2615 /****************************************************************************
2616 Async SMB1 ulogoffX.
2617 Note, on failure here we deallocate and return NULL to allow the caller to
2618 SMB1 return an error of ERRnomem immediately.
2619 ****************************************************************************/
2621 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2622 struct smbXsrv_session *session)
2624 struct tevent_req *req;
2625 struct reply_ulogoffX_state *state;
2626 struct tevent_req *subreq;
2628 struct smbd_server_connection *sconn = session->client->sconn;
2629 uint64_t vuid = session->global->session_wire_id;
2631 req = tevent_req_create(smb1req, &state,
2632 struct reply_ulogoffX_state);
2636 state->wait_queue = tevent_queue_create(state,
2637 "reply_ulogoffX_wait_queue");
2638 if (tevent_req_nomem(state->wait_queue, req)) {
2642 state->session = session;
2645 * Make sure that no new request will be able to use this session.
2646 * This ensures that once all outstanding fsp->aio_requests
2647 * on this session are done, we are safe to close it.
2649 session->status = NT_STATUS_USER_SESSION_DELETED;
2651 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2652 if (fsp->vuid != vuid) {
2656 * Flag the file as close in progress.
2657 * This will prevent any more IO being
2660 fsp->fsp_flags.closing = true;
2662 if (fsp->num_aio_requests > 0) {
2664 * Now wait until all aio requests on this fsp are
2667 * We don't set a callback, as we just want to block the
2668 * wait queue and the talloc_free() of fsp->aio_request
2669 * will remove the item from the wait queue.
2671 subreq = tevent_queue_wait_send(fsp->aio_requests,
2674 if (tevent_req_nomem(subreq, req)) {
2682 * Now we add our own waiter to the end of the queue,
2683 * this way we get notified when all pending requests are finished
2684 * and reply to the outstanding SMB1 request.
2686 subreq = tevent_queue_wait_send(state,
2689 if (tevent_req_nomem(subreq, req)) {
2695 * We're really going async - move the SMB1 request from
2696 * a talloc stackframe above us to the sconn talloc-context.
2697 * We need this to stick around until the wait_done
2698 * callback is invoked.
2700 smb1req = talloc_move(sconn, &smb1req);
2702 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2707 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2709 struct tevent_req *req = tevent_req_callback_data(
2710 subreq, struct tevent_req);
2712 tevent_queue_wait_recv(subreq);
2713 TALLOC_FREE(subreq);
2714 tevent_req_done(req);
2717 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2719 return tevent_req_simple_recv_ntstatus(req);
2722 static void reply_ulogoffX_done(struct tevent_req *req)
2724 struct smb_request *smb1req = tevent_req_callback_data(
2725 req, struct smb_request);
2726 struct reply_ulogoffX_state *state = tevent_req_data(req,
2727 struct reply_ulogoffX_state);
2728 struct smbXsrv_session *session = state->session;
2732 * Take the profile charge here. Not strictly
2733 * correct but better than the other SMB1 async
2734 * code that double-charges at the moment.
2736 START_PROFILE(SMBulogoffX);
2738 status = reply_ulogoffX_recv(req);
2740 if (!NT_STATUS_IS_OK(status)) {
2741 TALLOC_FREE(smb1req);
2742 END_PROFILE(SMBulogoffX);
2743 exit_server(__location__ ": reply_ulogoffX_recv failed");
2747 status = smbXsrv_session_logoff(session);
2748 if (!NT_STATUS_IS_OK(status)) {
2749 TALLOC_FREE(smb1req);
2750 END_PROFILE(SMBulogoffX);
2751 exit_server(__location__ ": smbXsrv_session_logoff failed");
2755 TALLOC_FREE(session);
2757 reply_outbuf(smb1req, 2, 0);
2758 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2759 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2761 DBG_NOTICE("ulogoffX vuid=%llu\n",
2762 (unsigned long long)smb1req->vuid);
2764 smb1req->vuid = UID_FIELD_INVALID;
2766 * The following call is needed to push the
2767 * reply data back out the socket after async
2768 * return. Plus it frees smb1req.
2770 smb_request_done(smb1req);
2771 END_PROFILE(SMBulogoffX);
2774 /****************************************************************************
2775 Reply to a mknew or a create.
2776 ****************************************************************************/
2778 void reply_mknew(struct smb_request *req)
2780 connection_struct *conn = req->conn;
2781 struct smb_filename *smb_fname = NULL;
2784 struct smb_file_time ft;
2786 int oplock_request = 0;
2788 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2789 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2790 uint32_t create_disposition;
2791 uint32_t create_options = 0;
2793 TALLOC_CTX *ctx = talloc_tos();
2795 START_PROFILE(SMBcreate);
2796 init_smb_file_time(&ft);
2799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2803 fattr = SVAL(req->vwv+0, 0);
2804 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2806 if (req->cmd == SMBmknew) {
2807 /* We should fail if file exists. */
2808 create_disposition = FILE_CREATE;
2810 /* Create if file doesn't exist, truncate if it does. */
2811 create_disposition = FILE_OVERWRITE_IF;
2815 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2817 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2818 STR_TERMINATE, &status);
2819 if (!NT_STATUS_IS_OK(status)) {
2820 reply_nterror(req, status);
2824 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2825 status = filename_convert(ctx,
2831 if (!NT_STATUS_IS_OK(status)) {
2832 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2833 reply_botherror(req,
2834 NT_STATUS_PATH_NOT_COVERED,
2835 ERRSRV, ERRbadpath);
2838 reply_nterror(req, status);
2842 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2843 DEBUG(0,("Attempt to create file (%s) with volid set - "
2844 "please report this\n",
2845 smb_fname_str_dbg(smb_fname)));
2848 status = SMB_VFS_CREATE_FILE(
2851 smb_fname, /* fname */
2852 access_mask, /* access_mask */
2853 share_mode, /* share_access */
2854 create_disposition, /* create_disposition*/
2855 create_options, /* create_options */
2856 fattr, /* file_attributes */
2857 oplock_request, /* oplock_request */
2859 0, /* allocation_size */
2860 0, /* private_flags */
2865 NULL, NULL); /* create context */
2867 if (!NT_STATUS_IS_OK(status)) {
2868 if (open_was_deferred(req->xconn, req->mid)) {
2869 /* We have re-scheduled this call. */
2872 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2873 bool ok = defer_smb1_sharing_violation(req);
2878 reply_openerror(req, status);
2882 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2883 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2884 if (!NT_STATUS_IS_OK(status)) {
2885 END_PROFILE(SMBcreate);
2889 reply_outbuf(req, 1, 0);
2890 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2892 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2893 SCVAL(req->outbuf,smb_flg,
2894 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2897 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2898 SCVAL(req->outbuf,smb_flg,
2899 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2902 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2903 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2904 smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2905 (unsigned int)fattr));
2908 TALLOC_FREE(smb_fname);
2909 END_PROFILE(SMBcreate);
2913 /****************************************************************************
2914 Reply to a create temporary file.
2915 ****************************************************************************/
2917 void reply_ctemp(struct smb_request *req)
2919 connection_struct *conn = req->conn;
2920 struct smb_filename *smb_fname = NULL;
2921 char *wire_name = NULL;
2930 TALLOC_CTX *ctx = talloc_tos();
2932 START_PROFILE(SMBctemp);
2935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2939 fattr = SVAL(req->vwv+0, 0);
2940 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2942 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2943 STR_TERMINATE, &status);
2944 if (!NT_STATUS_IS_OK(status)) {
2945 reply_nterror(req, status);
2949 for (i = 0; i < 10; i++) {
2951 fname = talloc_asprintf(ctx,
2954 generate_random_str_list(ctx, 5, "0123456789"));
2956 fname = talloc_asprintf(ctx,
2958 generate_random_str_list(ctx, 5, "0123456789"));
2962 reply_nterror(req, NT_STATUS_NO_MEMORY);
2966 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2967 status = filename_convert(ctx, conn,
2972 if (!NT_STATUS_IS_OK(status)) {
2973 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2974 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2975 ERRSRV, ERRbadpath);
2978 reply_nterror(req, status);
2982 /* Create the file. */
2983 status = SMB_VFS_CREATE_FILE(
2986 smb_fname, /* fname */
2987 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2988 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2989 FILE_CREATE, /* create_disposition*/
2990 0, /* create_options */
2991 fattr, /* file_attributes */
2992 oplock_request, /* oplock_request */
2994 0, /* allocation_size */
2995 0, /* private_flags */
3000 NULL, NULL); /* create context */
3002 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3004 TALLOC_FREE(smb_fname);
3008 if (!NT_STATUS_IS_OK(status)) {
3009 if (open_was_deferred(req->xconn, req->mid)) {
3010 /* We have re-scheduled this call. */
3013 if (NT_STATUS_EQUAL(
3014 status, NT_STATUS_SHARING_VIOLATION)) {
3015 bool ok = defer_smb1_sharing_violation(req);
3020 reply_openerror(req, status);
3028 /* Collision after 10 times... */
3029 reply_nterror(req, status);
3033 reply_outbuf(req, 1, 0);
3034 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3036 /* the returned filename is relative to the directory */
3037 s = strrchr_m(fsp->fsp_name->base_name, '/');
3039 s = fsp->fsp_name->base_name;
3045 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3046 thing in the byte section. JRA */
3047 SSVALS(p, 0, -1); /* what is this? not in spec */
3049 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3051 reply_nterror(req, NT_STATUS_NO_MEMORY);
3055 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3056 SCVAL(req->outbuf, smb_flg,
3057 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3060 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3061 SCVAL(req->outbuf, smb_flg,
3062 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3065 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3066 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3067 fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
3069 TALLOC_FREE(smb_fname);
3070 TALLOC_FREE(wire_name);
3071 END_PROFILE(SMBctemp);
3075 /*******************************************************************
3076 Check if a user is allowed to rename a file.
3077 ********************************************************************/
3079 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3082 if (!CAN_WRITE(conn)) {
3083 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3086 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3087 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3088 /* Only bother to read the DOS attribute if we might deny the
3089 rename on the grounds of attribute mismatch. */
3090 uint32_t fmode = fdos_mode(fsp);
3091 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3092 return NT_STATUS_NO_SUCH_FILE;
3096 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3097 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3098 return NT_STATUS_OK;
3101 /* If no pathnames are open below this
3102 directory, allow the rename. */
3104 if (lp_strict_rename(SNUM(conn))) {
3106 * Strict rename, check open file db.
3108 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3109 return NT_STATUS_ACCESS_DENIED;
3111 } else if (file_find_subpath(fsp)) {
3113 * No strict rename, just look in local process.
3115 return NT_STATUS_ACCESS_DENIED;
3117 return NT_STATUS_OK;
3120 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3121 return NT_STATUS_OK;
3124 return NT_STATUS_ACCESS_DENIED;
3127 /*******************************************************************
3128 * unlink a file with all relevant access checks
3129 *******************************************************************/
3131 static NTSTATUS do_unlink(connection_struct *conn,
3132 struct smb_request *req,
3133 struct smb_filename *smb_fname,
3138 uint32_t dirtype_orig = dirtype;
3141 struct smb2_create_blobs *posx = NULL;
3143 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3144 smb_fname_str_dbg(smb_fname),
3147 if (!CAN_WRITE(conn)) {
3148 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3151 ret = vfs_stat(conn, smb_fname);
3153 return map_nt_error_from_unix(errno);
3156 fattr = fdos_mode(smb_fname->fsp);
3158 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3159 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3162 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3164 return NT_STATUS_NO_SUCH_FILE;
3167 if (!dir_check_ftype(fattr, dirtype)) {
3168 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3169 return NT_STATUS_FILE_IS_A_DIRECTORY;
3171 return NT_STATUS_NO_SUCH_FILE;
3174 if (dirtype_orig & 0x8000) {
3175 /* These will never be set for POSIX. */
3176 return NT_STATUS_NO_SUCH_FILE;
3180 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3181 return NT_STATUS_FILE_IS_A_DIRECTORY;
3184 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3185 return NT_STATUS_NO_SUCH_FILE;
3188 if (dirtype & 0xFF00) {
3189 /* These will never be set for POSIX. */
3190 return NT_STATUS_NO_SUCH_FILE;
3195 return NT_STATUS_NO_SUCH_FILE;
3198 /* Can't delete a directory. */
3199 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3200 return NT_STATUS_FILE_IS_A_DIRECTORY;
3205 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3206 return NT_STATUS_OBJECT_NAME_INVALID;
3207 #endif /* JRATEST */
3209 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
3210 status = make_smb2_posix_create_ctx(
3211 talloc_tos(), &posx, 0777);
3212 if (!NT_STATUS_IS_OK(status)) {
3213 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3219 /* On open checks the open itself will check the share mode, so
3220 don't do it here as we'll get it wrong. */
3222 status = SMB_VFS_CREATE_FILE
3225 smb_fname, /* fname */
3226 DELETE_ACCESS, /* access_mask */
3227 FILE_SHARE_NONE, /* share_access */
3228 FILE_OPEN, /* create_disposition*/
3229 FILE_NON_DIRECTORY_FILE, /* create_options */
3230 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3231 0, /* oplock_request */
3233 0, /* allocation_size */
3234 0, /* private_flags */
3239 posx, /* in_context_blobs */
3240 NULL); /* out_context_blobs */
3244 if (!NT_STATUS_IS_OK(status)) {
3245 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3246 nt_errstr(status)));
3250 status = can_set_delete_on_close(fsp, fattr);
3251 if (!NT_STATUS_IS_OK(status)) {
3252 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3254 smb_fname_str_dbg(smb_fname),
3255 nt_errstr(status)));
3256 close_file(req, fsp, NORMAL_CLOSE);
3260 /* The set is across all open files on this dev/inode pair. */
3261 if (!set_delete_on_close(fsp, True,
3262 conn->session_info->security_token,
3263 conn->session_info->unix_token)) {
3264 close_file(req, fsp, NORMAL_CLOSE);
3265 return NT_STATUS_ACCESS_DENIED;
3268 return close_file(req, fsp, NORMAL_CLOSE);
3271 /****************************************************************************
3272 The guts of the unlink command, split out so it may be called by the NT SMB
3274 ****************************************************************************/
3276 NTSTATUS unlink_internals(connection_struct *conn,
3277 struct smb_request *req,
3279 struct smb_filename *smb_fname,
3282 char *fname_dir = NULL;
3283 char *fname_mask = NULL;
3285 NTSTATUS status = NT_STATUS_OK;
3286 struct smb_filename *smb_fname_dir = NULL;
3287 TALLOC_CTX *ctx = talloc_tos();
3290 /* Split up the directory from the filename/mask. */
3291 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3292 &fname_dir, &fname_mask);
3293 if (!NT_STATUS_IS_OK(status)) {
3298 * We should only check the mangled cache
3299 * here if unix_convert failed. This means
3300 * that the path in 'mask' doesn't exist
3301 * on the file system and so we need to look
3302 * for a possible mangle. This patch from
3303 * Tine Smukavec <valentin.smukavec@hermes.si>.
3306 if (!VALID_STAT(smb_fname->st) &&
3307 mangle_is_mangled(fname_mask, conn->params)) {
3308 char *new_mask = NULL;
3309 mangle_lookup_name_from_8_3(ctx, fname_mask,
3310 &new_mask, conn->params);
3312 TALLOC_FREE(fname_mask);
3313 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);
3349 if (!NT_STATUS_IS_OK(status)) {
3355 struct smb_Dir *dir_hnd = NULL;
3357 const char *dname = NULL;
3358 char *talloced = NULL;
3360 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3361 status = NT_STATUS_OBJECT_NAME_INVALID;
3365 dirtype = FILE_ATTRIBUTE_NORMAL;
3368 if (strequal(fname_mask,"????????.???")) {
3369 TALLOC_FREE(fname_mask);
3370 fname_mask = talloc_strdup(ctx, "*");
3372 status = NT_STATUS_NO_MEMORY;
3377 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3383 if (smb_fname_dir == NULL) {
3384 status = NT_STATUS_NO_MEMORY;
3388 status = check_name(conn, smb_fname_dir);
3389 if (!NT_STATUS_IS_OK(status)) {
3393 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3395 if (dir_hnd == NULL) {
3396 status = map_nt_error_from_unix(errno);
3400 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3401 the pattern matches against the long name, otherwise the short name
3402 We don't implement this yet XXXX
3405 status = NT_STATUS_NO_SUCH_FILE;
3407 while ((dname = ReadDirName(dir_hnd, &offset,
3408 &smb_fname->st, &talloced))) {
3409 TALLOC_CTX *frame = talloc_stackframe();
3411 struct smb_filename *f = NULL;
3413 /* Quick check for "." and ".." */
3414 if (ISDOT(dname) || ISDOTDOT(dname)) {
3416 TALLOC_FREE(talloced);
3420 if (IS_VETO_PATH(conn, dname)) {
3422 TALLOC_FREE(talloced);
3426 if(!mask_match(dname, fname_mask,
3427 conn->case_sensitive)) {
3429 TALLOC_FREE(talloced);
3433 if (ISDOT(fname_dir)) {
3434 /* Ensure we use canonical names on open. */
3435 p = talloc_asprintf(smb_fname, "%s", dname);
3437 p = talloc_asprintf(smb_fname, "%s/%s",
3441 TALLOC_FREE(dir_hnd);
3442 status = NT_STATUS_NO_MEMORY;
3444 TALLOC_FREE(talloced);
3447 f = synthetic_smb_fname(frame,
3454 TALLOC_FREE(dir_hnd);
3455 status = NT_STATUS_NO_MEMORY;
3457 TALLOC_FREE(talloced);
3461 ret = vfs_stat(conn, f);
3463 status = map_nt_error_from_unix(errno);
3464 TALLOC_FREE(dir_hnd);
3466 TALLOC_FREE(talloced);
3470 status = openat_pathref_fsp(conn->cwd_fsp, f);
3471 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
3472 (f->flags & SMB_FILENAME_POSIX_PATH) &&
3473 S_ISLNK(f->st.st_ex_mode))
3475 status = NT_STATUS_OK;
3477 if (!NT_STATUS_IS_OK(status)) {
3478 TALLOC_FREE(dir_hnd);
3480 TALLOC_FREE(talloced);
3484 if (!is_visible_fsp(f->fsp, false)) {
3486 TALLOC_FREE(talloced);
3490 status = check_name(conn, f);
3491 if (!NT_STATUS_IS_OK(status)) {
3492 TALLOC_FREE(dir_hnd);
3494 TALLOC_FREE(talloced);
3498 status = do_unlink(conn, req, f, dirtype);
3499 if (!NT_STATUS_IS_OK(status)) {
3500 TALLOC_FREE(dir_hnd);
3502 TALLOC_FREE(talloced);
3507 DBG_DEBUG("successful unlink [%s]\n",
3508 smb_fname_str_dbg(f));
3511 TALLOC_FREE(talloced);
3513 TALLOC_FREE(dir_hnd);
3516 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3517 status = map_nt_error_from_unix(errno);
3521 TALLOC_FREE(smb_fname_dir);
3522 TALLOC_FREE(fname_dir);
3523 TALLOC_FREE(fname_mask);
3527 /****************************************************************************
3529 ****************************************************************************/
3531 void reply_unlink(struct smb_request *req)
3533 connection_struct *conn = req->conn;
3535 struct smb_filename *smb_fname = NULL;
3538 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3539 ucf_flags_from_smb_request(req);
3540 TALLOC_CTX *ctx = talloc_tos();
3541 bool has_wild = false;
3543 START_PROFILE(SMBunlink);
3546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3550 dirtype = SVAL(req->vwv+0, 0);
3552 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
3553 STR_TERMINATE, &status);
3554 if (!NT_STATUS_IS_OK(status)) {
3555 reply_nterror(req, status);
3559 status = filename_convert(ctx, conn,
3564 if (!NT_STATUS_IS_OK(status)) {
3565 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3566 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3567 ERRSRV, ERRbadpath);
3570 reply_nterror(req, status);
3574 if (req != NULL && !req->posix_pathnames) {
3575 char *lcomp = get_original_lcomp(ctx,
3579 if (lcomp == NULL) {
3580 reply_nterror(req, NT_STATUS_NO_MEMORY);
3583 has_wild = ms_has_wild(lcomp);
3587 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3589 status = unlink_internals(conn, req, dirtype, smb_fname, has_wild);
3590 if (!NT_STATUS_IS_OK(status)) {
3591 if (open_was_deferred(req->xconn, req->mid)) {
3592 /* We have re-scheduled this call. */
3595 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3596 bool ok = defer_smb1_sharing_violation(req);
3601 reply_nterror(req, status);
3605 reply_outbuf(req, 0, 0);
3607 TALLOC_FREE(smb_fname);
3608 END_PROFILE(SMBunlink);
3612 /****************************************************************************
3614 ****************************************************************************/
3616 static void fail_readraw(void)
3618 const char *errstr = talloc_asprintf(talloc_tos(),
3619 "FAIL ! reply_readbraw: socket write fail (%s)",
3624 exit_server_cleanly(errstr);
3627 /****************************************************************************
3628 Fake (read/write) sendfile. Returns -1 on read or write fail.
3629 ****************************************************************************/
3631 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3632 off_t startpos, size_t nread)
3635 size_t tosend = nread;
3642 bufsize = MIN(nread, 65536);
3644 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3648 while (tosend > 0) {
3652 cur_read = MIN(tosend, bufsize);
3653 ret = read_file(fsp,buf,startpos,cur_read);
3659 /* If we had a short read, fill with zeros. */
3660 if (ret < cur_read) {
3661 memset(buf + ret, '\0', cur_read - ret);
3664 ret = write_data(xconn->transport.sock, buf, cur_read);
3665 if (ret != cur_read) {
3666 int saved_errno = errno;
3668 * Try and give an error message saying what
3671 DEBUG(0, ("write_data failed for client %s. "
3673 smbXsrv_connection_dbg(xconn),
3674 strerror(saved_errno)));
3676 errno = saved_errno;
3680 startpos += cur_read;
3684 return (ssize_t)nread;
3687 /****************************************************************************
3688 Deal with the case of sendfile reading less bytes from the file than
3689 requested. Fill with zeros (all we can do). Returns 0 on success
3690 ****************************************************************************/
3692 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3698 #define SHORT_SEND_BUFSIZE 1024
3699 if (nread < headersize) {
3700 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3701 "header for file %s (%s). Terminating\n",
3702 fsp_str_dbg(fsp), strerror(errno)));
3706 nread -= headersize;
3708 if (nread < smb_maxcnt) {
3709 char buf[SHORT_SEND_BUFSIZE] = { 0 };
3711 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3712 "with zeros !\n", fsp_str_dbg(fsp)));
3714 while (nread < smb_maxcnt) {
3716 * We asked for the real file size and told sendfile
3717 * to not go beyond the end of the file. But it can
3718 * happen that in between our fstat call and the
3719 * sendfile call the file was truncated. This is very
3720 * bad because we have already announced the larger
3721 * number of bytes to the client.
3723 * The best we can do now is to send 0-bytes, just as
3724 * a read from a hole in a sparse file would do.
3726 * This should happen rarely enough that I don't care
3727 * about efficiency here :-)
3732 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3733 ret = write_data(xconn->transport.sock, buf, to_write);
3734 if (ret != to_write) {
3735 int saved_errno = errno;
3737 * Try and give an error message saying what
3740 DEBUG(0, ("write_data failed for client %s. "
3742 smbXsrv_connection_dbg(xconn),
3743 strerror(saved_errno)));
3744 errno = saved_errno;
3754 /****************************************************************************
3755 Return a readbraw error (4 bytes of zero).
3756 ****************************************************************************/
3758 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3764 smbd_lock_socket(xconn);
3765 if (write_data(xconn->transport.sock,header,4) != 4) {
3766 int saved_errno = errno;
3768 * Try and give an error message saying what
3771 DEBUG(0, ("write_data failed for client %s. "
3773 smbXsrv_connection_dbg(xconn),
3774 strerror(saved_errno)));
3775 errno = saved_errno;
3779 smbd_unlock_socket(xconn);
3782 /*******************************************************************
3783 Ensure we don't use sendfile if server smb signing is active.
3784 ********************************************************************/
3786 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3788 bool sign_active = false;
3790 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3791 if (get_Protocol() < PROTOCOL_NT1) {
3794 if (signing_state) {
3795 sign_active = smb_signing_is_active(signing_state);
3797 return (lp__use_sendfile(snum) &&
3798 (get_remote_arch() != RA_WIN95) &&
3801 /****************************************************************************
3802 Use sendfile in readbraw.
3803 ****************************************************************************/
3805 static void send_file_readbraw(connection_struct *conn,
3806 struct smb_request *req,
3812 struct smbXsrv_connection *xconn = req->xconn;
3813 char *outbuf = NULL;
3817 * We can only use sendfile on a non-chained packet
3818 * but we can use on a non-oplocked file. tridge proved this
3819 * on a train in Germany :-). JRA.
3820 * reply_readbraw has already checked the length.
3823 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3824 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3825 ssize_t sendfile_read = -1;
3827 DATA_BLOB header_blob;
3829 _smb_setlen(header,nread);
3830 header_blob = data_blob_const(header, 4);
3832 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3833 &header_blob, startpos,
3835 if (sendfile_read == -1) {
3836 /* Returning ENOSYS means no data at all was sent.
3837 * Do this as a normal read. */
3838 if (errno == ENOSYS) {
3839 goto normal_readbraw;
3843 * Special hack for broken Linux with no working sendfile. If we
3844 * return EINTR we sent the header but not the rest of the data.
3845 * Fake this up by doing read/write calls.
3847 if (errno == EINTR) {
3848 /* Ensure we don't do this again. */
3849 set_use_sendfile(SNUM(conn), False);
3850 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3852 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3853 DEBUG(0,("send_file_readbraw: "
3854 "fake_sendfile failed for "
3858 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3863 DEBUG(0,("send_file_readbraw: sendfile failed for "
3864 "file %s (%s). Terminating\n",
3865 fsp_str_dbg(fsp), strerror(errno)));
3866 exit_server_cleanly("send_file_readbraw sendfile failed");
3867 } else if (sendfile_read == 0) {
3869 * Some sendfile implementations return 0 to indicate
3870 * that there was a short read, but nothing was
3871 * actually written to the socket. In this case,
3872 * fallback to the normal read path so the header gets
3873 * the correct byte count.
3875 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3876 "bytes falling back to the normal read: "
3877 "%s\n", fsp_str_dbg(fsp)));
3878 goto normal_readbraw;
3881 /* Deal with possible short send. */
3882 if (sendfile_read != 4+nread) {
3883 ret = sendfile_short_send(xconn, fsp,
3884 sendfile_read, 4, nread);
3894 outbuf = talloc_array(NULL, char, nread+4);
3896 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3897 (unsigned)(nread+4)));
3898 reply_readbraw_error(xconn);
3903 ret = read_file(fsp,outbuf+4,startpos,nread);
3904 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3913 _smb_setlen(outbuf,ret);
3914 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3915 int saved_errno = errno;
3917 * Try and give an error message saying what
3920 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3921 smbXsrv_connection_dbg(xconn),
3922 strerror(saved_errno)));
3923 errno = saved_errno;
3928 TALLOC_FREE(outbuf);
3931 /****************************************************************************
3932 Reply to a readbraw (core+ protocol).
3933 ****************************************************************************/
3935 void reply_readbraw(struct smb_request *req)
3937 connection_struct *conn = req->conn;
3938 struct smbXsrv_connection *xconn = req->xconn;
3939 ssize_t maxcount,mincount;
3943 struct lock_struct lock;
3947 START_PROFILE(SMBreadbraw);
3949 if (srv_is_signing_active(xconn) || req->encrypted) {
3950 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3951 "raw reads/writes are disallowed.");
3955 reply_readbraw_error(xconn);
3956 END_PROFILE(SMBreadbraw);
3960 if (xconn->smb1.echo_handler.trusted_fde) {
3961 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3962 "'async smb echo handler = yes'\n"));
3963 reply_readbraw_error(xconn);
3964 END_PROFILE(SMBreadbraw);
3969 * Special check if an oplock break has been issued
3970 * and the readraw request croses on the wire, we must
3971 * return a zero length response here.
3974 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3977 * We have to do a check_fsp by hand here, as
3978 * we must always return 4 zero bytes on error,
3984 conn != fsp->conn ||
3985 req->vuid != fsp->vuid ||
3986 fsp->fsp_flags.is_directory ||
3987 fsp_get_io_fd(fsp) == -1)
3990 * fsp could be NULL here so use the value from the packet. JRA.
3992 DEBUG(3,("reply_readbraw: fnum %d not valid "
3994 (int)SVAL(req->vwv+0, 0)));
3995 reply_readbraw_error(xconn);
3996 END_PROFILE(SMBreadbraw);
4000 /* Do a "by hand" version of CHECK_READ. */
4001 if (!(fsp->fsp_flags.can_read ||
4002 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
4003 (fsp->access_mask & FILE_EXECUTE)))) {
4004 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4005 (int)SVAL(req->vwv+0, 0)));
4006 reply_readbraw_error(xconn);
4007 END_PROFILE(SMBreadbraw);
4011 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
4012 if(req->wct == 10) {
4014 * This is a large offset (64 bit) read.
4017 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4020 DEBUG(0,("reply_readbraw: negative 64 bit "
4021 "readraw offset (%.0f) !\n",
4022 (double)startpos ));
4023 reply_readbraw_error(xconn);
4024 END_PROFILE(SMBreadbraw);
4029 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4030 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4032 /* ensure we don't overrun the packet size */
4033 maxcount = MIN(65535,maxcount);
4035 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4036 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4039 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4040 reply_readbraw_error(xconn);
4041 END_PROFILE(SMBreadbraw);
4045 status = vfs_stat_fsp(fsp);
4046 if (NT_STATUS_IS_OK(status)) {
4047 size = fsp->fsp_name->st.st_ex_size;
4050 if (startpos >= size) {
4053 nread = MIN(maxcount,(size - startpos));
4056 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4057 if (nread < mincount)
4061 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4062 "min=%lu nread=%lu\n",
4063 fsp_fnum_dbg(fsp), (double)startpos,
4064 (unsigned long)maxcount,
4065 (unsigned long)mincount,
4066 (unsigned long)nread ) );
4068 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4070 DEBUG(5,("reply_readbraw finished\n"));
4072 END_PROFILE(SMBreadbraw);
4077 #define DBGC_CLASS DBGC_LOCKING
4079 /****************************************************************************
4080 Reply to a lockread (core+ protocol).
4081 ****************************************************************************/
4083 static void reply_lockread_locked(struct tevent_req *subreq);
4085 void reply_lockread(struct smb_request *req)
4087 struct tevent_req *subreq = NULL;
4088 connection_struct *conn = req->conn;
4090 struct smbd_lock_element *lck = NULL;
4092 START_PROFILE(SMBlockread);
4095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4096 END_PROFILE(SMBlockread);
4100 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4102 if (!check_fsp(conn, req, fsp)) {
4103 END_PROFILE(SMBlockread);
4107 if (!CHECK_READ(fsp,req)) {
4108 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4109 END_PROFILE(SMBlockread);
4113 lck = talloc(req, struct smbd_lock_element);
4115 reply_nterror(req, NT_STATUS_NO_MEMORY);
4116 END_PROFILE(SMBlockread);
4121 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4122 * protocol request that predates the read/write lock concept.
4123 * Thus instead of asking for a read lock here we need to ask
4124 * for a write lock. JRA.
4125 * Note that the requested lock size is unaffected by max_send.
4128 *lck = (struct smbd_lock_element) {
4129 .req_guid = smbd_request_guid(req, 0),
4130 .smblctx = req->smbpid,
4131 .brltype = WRITE_LOCK,
4132 .count = SVAL(req->vwv+1, 0),
4133 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4136 subreq = smbd_smb1_do_locks_send(
4142 false, /* large_offset */
4146 if (subreq == NULL) {
4147 reply_nterror(req, NT_STATUS_NO_MEMORY);
4148 END_PROFILE(SMBlockread);
4151 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4152 END_PROFILE(SMBlockread);
4155 static void reply_lockread_locked(struct tevent_req *subreq)
4157 struct smb_request *req = NULL;
4163 size_t numtoread, maxtoread;
4164 struct files_struct *fsp = NULL;
4167 START_PROFILE(SMBlockread);
4169 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4172 status = smbd_smb1_do_locks_recv(subreq);
4173 TALLOC_FREE(subreq);
4175 if (!NT_STATUS_IS_OK(status)) {
4176 reply_nterror(req, status);
4180 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4182 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4186 numtoread = SVAL(req->vwv+1, 0);
4187 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4190 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4192 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4194 if (numtoread > maxtoread) {
4195 DBG_WARNING("requested read size (%zu) is greater than "
4196 "maximum allowed (%zu/%d). "
4197 "Returning short read of maximum allowed for "
4198 "compatibility with Windows 2000.\n",
4201 req->xconn->smb1.sessions.max_send);
4202 numtoread = maxtoread;
4205 reply_outbuf(req, 5, numtoread + 3);
4207 data = smb_buf(req->outbuf) + 3;
4209 nread = read_file(fsp,data,startpos,numtoread);
4212 reply_nterror(req, map_nt_error_from_unix(errno));
4216 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4218 SSVAL(req->outbuf,smb_vwv0,nread);
4219 SSVAL(req->outbuf,smb_vwv5,nread+3);
4220 p = smb_buf(req->outbuf);
4221 SCVAL(p,0,0); /* pad byte. */
4224 DEBUG(3,("lockread %s num=%d nread=%d\n",
4225 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4228 ok = srv_send_smb(req->xconn,
4229 (char *)req->outbuf,
4232 IS_CONN_ENCRYPTED(req->conn),
4235 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4238 END_PROFILE(SMBlockread);
4243 #define DBGC_CLASS DBGC_ALL
4245 /****************************************************************************
4247 ****************************************************************************/
4249 void reply_read(struct smb_request *req)
4251 connection_struct *conn = req->conn;
4258 struct lock_struct lock;
4259 struct smbXsrv_connection *xconn = req->xconn;
4261 START_PROFILE(SMBread);
4264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4265 END_PROFILE(SMBread);
4269 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4271 if (!check_fsp(conn, req, fsp)) {
4272 END_PROFILE(SMBread);
4276 if (!CHECK_READ(fsp,req)) {
4277 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4278 END_PROFILE(SMBread);
4282 numtoread = SVAL(req->vwv+1, 0);
4283 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4286 * The requested read size cannot be greater than max_send. JRA.
4288 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4290 if (numtoread > maxtoread) {
4291 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4292 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4293 (unsigned int)numtoread, (unsigned int)maxtoread,
4294 (unsigned int)xconn->smb1.sessions.max_send));
4295 numtoread = maxtoread;
4298 reply_outbuf(req, 5, numtoread+3);
4300 data = smb_buf(req->outbuf) + 3;
4302 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4303 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4306 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4307 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4308 END_PROFILE(SMBread);
4313 nread = read_file(fsp,data,startpos,numtoread);
4316 reply_nterror(req, map_nt_error_from_unix(errno));
4320 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4322 SSVAL(req->outbuf,smb_vwv0,nread);
4323 SSVAL(req->outbuf,smb_vwv5,nread+3);
4324 SCVAL(smb_buf(req->outbuf),0,1);
4325 SSVAL(smb_buf(req->outbuf),1,nread);
4327 DEBUG(3, ("read %s num=%d nread=%d\n",
4328 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4331 END_PROFILE(SMBread);
4335 /****************************************************************************
4337 ****************************************************************************/
4339 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4343 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4346 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4348 SCVAL(outbuf,smb_vwv0,0xFF);
4349 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4350 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4351 SSVAL(outbuf,smb_vwv6,
4352 (smb_wct - 4) /* offset from smb header to wct */
4353 + 1 /* the wct field */
4354 + 12 * sizeof(uint16_t) /* vwv */
4355 + 2 /* the buflen field */
4356 + 1); /* padding byte */
4357 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4358 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4359 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4360 _smb_setlen_large(outbuf,
4361 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4365 /****************************************************************************
4366 Reply to a read and X - possibly using sendfile.
4367 ****************************************************************************/
4369 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4370 files_struct *fsp, off_t startpos,
4373 struct smbXsrv_connection *xconn = req->xconn;
4375 struct lock_struct lock;
4376 int saved_errno = 0;
4379 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4380 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4383 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4384 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4389 * We can only use sendfile on a non-chained packet
4390 * but we can use on a non-oplocked file. tridge proved this
4391 * on a train in Germany :-). JRA.
4394 if (!req_is_in_chain(req) &&
4396 (fsp->base_fsp == NULL) &&
4397 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4398 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4401 status = vfs_stat_fsp(fsp);
4402 if (!NT_STATUS_IS_OK(status)) {
4403 reply_nterror(req, status);
4407 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4408 (startpos > fsp->fsp_name->st.st_ex_size) ||
4409 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4411 * We already know that we would do a short read, so don't
4412 * try the sendfile() path.
4414 goto nosendfile_read;
4418 * Set up the packet header before send. We
4419 * assume here the sendfile will work (get the
4420 * correct amount of data).
4423 header = data_blob_const(headerbuf, sizeof(headerbuf));
4425 construct_reply_common_req(req, (char *)headerbuf);
4426 setup_readX_header((char *)headerbuf, smb_maxcnt);
4428 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4429 startpos, smb_maxcnt);
4431 saved_errno = errno;
4433 /* Returning ENOSYS means no data at all was sent.
4434 Do this as a normal read. */
4435 if (errno == ENOSYS) {
4440 * Special hack for broken Linux with no working sendfile. If we
4441 * return EINTR we sent the header but not the rest of the data.
4442 * Fake this up by doing read/write calls.
4445 if (errno == EINTR) {
4446 /* Ensure we don't do this again. */
4447 set_use_sendfile(SNUM(conn), False);
4448 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4449 nread = fake_sendfile(xconn, fsp, startpos,
4452 saved_errno = errno;
4453 DEBUG(0,("send_file_readX: "
4454 "fake_sendfile failed for "
4455 "file %s (%s) for client %s. "
4458 smbXsrv_connection_dbg(xconn),
4459 strerror(saved_errno)));
4460 errno = saved_errno;
4461 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4463 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4464 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4465 /* No outbuf here means successful sendfile. */
4469 DEBUG(0,("send_file_readX: sendfile failed for file "
4470 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4472 exit_server_cleanly("send_file_readX sendfile failed");
4473 } else if (nread == 0) {
4475 * Some sendfile implementations return 0 to indicate
4476 * that there was a short read, but nothing was
4477 * actually written to the socket. In this case,
4478 * fallback to the normal read path so the header gets
4479 * the correct byte count.
4481 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4482 "falling back to the normal read: %s\n",
4487 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4488 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4490 /* Deal with possible short send. */
4491 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4494 ret = sendfile_short_send(xconn, fsp, nread,
4495 sizeof(headerbuf), smb_maxcnt);
4498 r = "send_file_readX: sendfile_short_send failed";
4499 DEBUG(0,("%s for file %s (%s).\n",
4500 r, fsp_str_dbg(fsp), strerror(errno)));
4501 exit_server_cleanly(r);
4504 /* No outbuf here means successful sendfile. */
4505 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4506 SMB_PERFCOUNT_END(&req->pcd);
4512 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4513 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4516 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4517 (startpos > fsp->fsp_name->st.st_ex_size) ||
4518 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4520 * We already know that we would do a short
4521 * read, so don't try the sendfile() path.
4523 goto nosendfile_read;
4526 construct_reply_common_req(req, (char *)headerbuf);
4527 setup_readX_header((char *)headerbuf, smb_maxcnt);
4529 /* Send out the header. */
4530 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4532 if (ret != sizeof(headerbuf)) {
4533 saved_errno = errno;
4535 * Try and give an error message saying what
4538 DEBUG(0,("send_file_readX: write_data failed for file "
4539 "%s (%s) for client %s. Terminating\n",
4541 smbXsrv_connection_dbg(xconn),
4542 strerror(saved_errno)));
4543 errno = saved_errno;
4544 exit_server_cleanly("send_file_readX sendfile failed");
4546 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4548 saved_errno = errno;
4549 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4550 "%s (%s) for client %s. Terminating\n",
4552 smbXsrv_connection_dbg(xconn),
4553 strerror(saved_errno)));
4554 errno = saved_errno;
4555 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4562 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4563 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4564 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4566 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4567 startpos, smb_maxcnt);
4568 saved_errno = errno;
4571 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4575 setup_readX_header((char *)req->outbuf, nread);
4577 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4578 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4582 TALLOC_FREE(req->outbuf);
4586 /****************************************************************************
4587 Work out how much space we have for a read return.
4588 ****************************************************************************/
4590 static size_t calc_max_read_pdu(const struct smb_request *req)
4592 struct smbXsrv_connection *xconn = req->xconn;
4594 if (xconn->protocol < PROTOCOL_NT1) {
4595 return xconn->smb1.sessions.max_send;
4598 if (!lp_large_readwrite()) {
4599 return xconn->smb1.sessions.max_send;
4602 if (req_is_in_chain(req)) {
4603 return xconn->smb1.sessions.max_send;
4606 if (req->encrypted) {
4608 * Don't take encrypted traffic up to the
4609 * limit. There are padding considerations
4610 * that make that tricky.
4612 return xconn->smb1.sessions.max_send;
4615 if (srv_is_signing_active(xconn)) {
4619 if (!lp_unix_extensions()) {
4624 * We can do ultra-large POSIX reads.
4629 /****************************************************************************
4630 Calculate how big a read can be. Copes with all clients. It's always
4631 safe to return a short read - Windows does this.
4632 ****************************************************************************/
4634 static size_t calc_read_size(const struct smb_request *req,
4638 struct smbXsrv_connection *xconn = req->xconn;
4639 size_t max_pdu = calc_max_read_pdu(req);
4640 size_t total_size = 0;
4641 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4642 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4645 * Windows explicitly ignores upper size of 0xFFFF.
4646 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4647 * We must do the same as these will never fit even in
4648 * an extended size NetBIOS packet.
4650 if (upper_size == 0xFFFF) {
4654 if (xconn->protocol < PROTOCOL_NT1) {
4658 total_size = ((upper_size<<16) | lower_size);
4661 * LARGE_READX test shows it's always safe to return
4662 * a short read. Windows does so.
4664 return MIN(total_size, max_len);
4667 /****************************************************************************
4668 Reply to a read and X.
4669 ****************************************************************************/
4671 void reply_read_and_X(struct smb_request *req)
4673 connection_struct *conn = req->conn;
4678 bool big_readX = False;
4680 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4683 START_PROFILE(SMBreadX);
4685 if ((req->wct != 10) && (req->wct != 12)) {
4686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4690 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4691 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4692 smb_maxcnt = SVAL(req->vwv+5, 0);
4694 /* If it's an IPC, pass off the pipe handler. */
4696 reply_pipe_read_and_X(req);
4697 END_PROFILE(SMBreadX);
4701 if (!check_fsp(conn, req, fsp)) {
4702 END_PROFILE(SMBreadX);
4706 if (!CHECK_READ(fsp,req)) {
4707 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4708 END_PROFILE(SMBreadX);
4712 upper_size = SVAL(req->vwv+7, 0);
4713 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4714 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4716 * This is a heuristic to avoid keeping large
4717 * outgoing buffers around over long-lived aio
4723 if (req->wct == 12) {
4725 * This is a large offset (64 bit) read.
4727 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4732 NTSTATUS status = schedule_aio_read_and_X(conn,
4737 if (NT_STATUS_IS_OK(status)) {
4738 /* Read scheduled - we're done. */
4741 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4742 /* Real error - report to client. */
4743 END_PROFILE(SMBreadX);
4744 reply_nterror(req, status);
4747 /* NT_STATUS_RETRY - fall back to sync read. */
4750 smbd_lock_socket(req->xconn);
4751 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4752 smbd_unlock_socket(req->xconn);
4755 END_PROFILE(SMBreadX);
4759 /****************************************************************************
4760 Error replies to writebraw must have smb_wct == 1. Fix this up.
4761 ****************************************************************************/
4763 void error_to_writebrawerr(struct smb_request *req)
4765 uint8_t *old_outbuf = req->outbuf;
4767 reply_outbuf(req, 1, 0);
4769 memcpy(req->outbuf, old_outbuf, smb_size);
4770 TALLOC_FREE(old_outbuf);
4773 /****************************************************************************
4774 Read 4 bytes of a smb packet and return the smb length of the packet.
4775 Store the result in the buffer. This version of the function will
4776 never return a session keepalive (length of zero).
4777 Timeout is in milliseconds.
4778 ****************************************************************************/
4780 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4783 uint8_t msgtype = NBSSkeepalive;
4785 while (msgtype == NBSSkeepalive) {
4788 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4790 if (!NT_STATUS_IS_OK(status)) {
4791 char addr[INET6_ADDRSTRLEN];
4792 /* Try and give an error message
4793 * saying what client failed. */
4794 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4795 "client %s read error = %s.\n",
4796 get_peer_addr(fd,addr,sizeof(addr)),
4797 nt_errstr(status)));
4801 msgtype = CVAL(inbuf, 0);
4804 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4805 (unsigned long)len));
4807 return NT_STATUS_OK;
4810 /****************************************************************************
4811 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4812 ****************************************************************************/
4814 void reply_writebraw(struct smb_request *req)
4816 connection_struct *conn = req->conn;
4817 struct smbXsrv_connection *xconn = req->xconn;
4820 ssize_t total_written=0;
4821 size_t numtowrite=0;
4824 const char *data=NULL;
4827 struct lock_struct lock;
4830 START_PROFILE(SMBwritebraw);
4833 * If we ever reply with an error, it must have the SMB command
4834 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4837 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4839 if (srv_is_signing_active(xconn)) {
4840 END_PROFILE(SMBwritebraw);
4841 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4842 "raw reads/writes are disallowed.");
4845 if (req->wct < 12) {
4846 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4847 error_to_writebrawerr(req);
4848 END_PROFILE(SMBwritebraw);
4852 if (xconn->smb1.echo_handler.trusted_fde) {
4853 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4854 "'async smb echo handler = yes'\n"));
4855 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4856 error_to_writebrawerr(req);
4857 END_PROFILE(SMBwritebraw);
4861 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4862 if (!check_fsp(conn, req, fsp)) {
4863 error_to_writebrawerr(req);
4864 END_PROFILE(SMBwritebraw);
4868 if (!CHECK_WRITE(fsp)) {
4869 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4870 error_to_writebrawerr(req);
4871 END_PROFILE(SMBwritebraw);
4875 tcount = IVAL(req->vwv+1, 0);
4876 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4877 write_through = BITSETW(req->vwv+7,0);
4879 /* We have to deal with slightly different formats depending
4880 on whether we are using the core+ or lanman1.0 protocol */
4882 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4883 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4884 data = smb_buf_const(req->inbuf);
4886 numtowrite = SVAL(req->vwv+10, 0);
4887 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4890 /* Ensure we don't write bytes past the end of this packet. */
4892 * This already protects us against CVE-2017-12163.
4894 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4896 error_to_writebrawerr(req);
4897 END_PROFILE(SMBwritebraw);
4901 if (!fsp->print_file) {
4902 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4903 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4906 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4907 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4908 error_to_writebrawerr(req);
4909 END_PROFILE(SMBwritebraw);
4915 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4918 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4919 "wrote=%d sync=%d\n",
4920 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4921 (int)nwritten, (int)write_through));
4923 if (nwritten < (ssize_t)numtowrite) {
4924 reply_nterror(req, NT_STATUS_DISK_FULL);
4925 error_to_writebrawerr(req);
4929 total_written = nwritten;
4931 /* Allocate a buffer of 64k + length. */
4932 buf = talloc_array(NULL, char, 65540);
4934 reply_nterror(req, NT_STATUS_NO_MEMORY);
4935 error_to_writebrawerr(req);
4939 /* Return a SMBwritebraw message to the redirector to tell
4940 * it to send more bytes */
4942 memcpy(buf, req->inbuf, smb_size);
4943 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4944 SCVAL(buf,smb_com,SMBwritebraw);
4945 SSVALS(buf,smb_vwv0,0xFFFF);
4947 if (!srv_send_smb(req->xconn,
4949 false, 0, /* no signing */
4950 IS_CONN_ENCRYPTED(conn),
4952 exit_server_cleanly("reply_writebraw: srv_send_smb "
4956 /* Now read the raw data into the buffer and write it */
4957 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4959 if (!NT_STATUS_IS_OK(status)) {
4960 exit_server_cleanly("secondary writebraw failed");
4963 /* Set up outbuf to return the correct size */
4964 reply_outbuf(req, 1, 0);
4966 if (numtowrite != 0) {
4968 if (numtowrite > 0xFFFF) {
4969 DEBUG(0,("reply_writebraw: Oversize secondary write "
4970 "raw requested (%u). Terminating\n",
4971 (unsigned int)numtowrite ));
4972 exit_server_cleanly("secondary writebraw failed");
4975 if (tcount > nwritten+numtowrite) {
4976 DEBUG(3,("reply_writebraw: Client overestimated the "
4978 (int)tcount,(int)nwritten,(int)numtowrite));
4981 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4984 if (!NT_STATUS_IS_OK(status)) {
4985 /* Try and give an error message
4986 * saying what client failed. */
4987 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4988 "raw read failed (%s) for client %s. "
4989 "Terminating\n", nt_errstr(status),
4990 smbXsrv_connection_dbg(xconn)));
4991 exit_server_cleanly("secondary writebraw failed");
4995 * We are not vulnerable to CVE-2017-12163
4996 * here as we are guaranteed to have numtowrite
4997 * bytes available - we just read from the client.
4999 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
5000 if (nwritten == -1) {
5002 reply_nterror(req, map_nt_error_from_unix(errno));
5003 error_to_writebrawerr(req);
5007 if (nwritten < (ssize_t)numtowrite) {
5008 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5009 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5013 total_written += nwritten;
5018 SSVAL(req->outbuf,smb_vwv0,total_written);
5020 status = sync_file(conn, fsp, write_through);
5021 if (!NT_STATUS_IS_OK(status)) {
5022 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5023 fsp_str_dbg(fsp), nt_errstr(status)));
5024 reply_nterror(req, status);
5025 error_to_writebrawerr(req);
5029 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5031 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5032 (int)total_written));
5034 /* We won't return a status if write through is not selected - this
5035 * follows what WfWg does */
5036 END_PROFILE(SMBwritebraw);
5038 if (!write_through && total_written==tcount) {
5040 #if RABBIT_PELLET_FIX
5042 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5043 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5046 if (!send_keepalive(xconn->transport.sock)) {
5047 exit_server_cleanly("reply_writebraw: send of "
5048 "keepalive failed");
5051 TALLOC_FREE(req->outbuf);
5056 END_PROFILE(SMBwritebraw);
5061 #define DBGC_CLASS DBGC_LOCKING
5063 /****************************************************************************
5064 Reply to a writeunlock (core+).
5065 ****************************************************************************/
5067 void reply_writeunlock(struct smb_request *req)
5069 connection_struct *conn = req->conn;
5070 ssize_t nwritten = -1;
5075 NTSTATUS status = NT_STATUS_OK;
5077 struct lock_struct lock;
5078 int saved_errno = 0;
5080 START_PROFILE(SMBwriteunlock);
5083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5084 END_PROFILE(SMBwriteunlock);
5088 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5090 if (!check_fsp(conn, req, fsp)) {
5091 END_PROFILE(SMBwriteunlock);
5095 if (!CHECK_WRITE(fsp)) {
5096 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5097 END_PROFILE(SMBwriteunlock);
5101 numtowrite = SVAL(req->vwv+1, 0);
5102 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5103 data = (const char *)req->buf + 3;
5106 * Ensure client isn't asking us to write more than
5107 * they sent. CVE-2017-12163.
5109 remaining = smbreq_bufrem(req, data);
5110 if (numtowrite > remaining) {
5111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5112 END_PROFILE(SMBwriteunlock);
5116 if (!fsp->print_file && numtowrite > 0) {
5117 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5118 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5121 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5122 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5123 END_PROFILE(SMBwriteunlock);
5128 /* The special X/Open SMB protocol handling of
5129 zero length writes is *NOT* done for
5131 if(numtowrite == 0) {
5134 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5135 saved_errno = errno;
5138 status = sync_file(conn, fsp, False /* write through */);
5139 if (!NT_STATUS_IS_OK(status)) {
5140 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5141 fsp_str_dbg(fsp), nt_errstr(status)));
5142 reply_nterror(req, status);
5147 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5151 if((nwritten < numtowrite) && (numtowrite != 0)) {
5152 reply_nterror(req, NT_STATUS_DISK_FULL);
5156 if (numtowrite && !fsp->print_file) {
5157 struct smbd_lock_element l = {
5158 .req_guid = smbd_request_guid(req, 0),
5159 .smblctx = req->smbpid,
5160 .brltype = UNLOCK_LOCK,
5162 .count = numtowrite,
5164 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5165 if (NT_STATUS_V(status)) {
5166 reply_nterror(req, status);
5171 reply_outbuf(req, 1, 0);
5173 SSVAL(req->outbuf,smb_vwv0,nwritten);
5175 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5176 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5179 END_PROFILE(SMBwriteunlock);
5184 #define DBGC_CLASS DBGC_ALL
5186 /****************************************************************************
5188 ****************************************************************************/
5190 void reply_write(struct smb_request *req)
5192 connection_struct *conn = req->conn;
5195 ssize_t nwritten = -1;
5199 struct lock_struct lock;
5201 int saved_errno = 0;
5203 START_PROFILE(SMBwrite);
5206 END_PROFILE(SMBwrite);
5207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5211 /* If it's an IPC, pass off the pipe handler. */
5213 reply_pipe_write(req);
5214 END_PROFILE(SMBwrite);
5218 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5220 if (!check_fsp(conn, req, fsp)) {
5221 END_PROFILE(SMBwrite);
5225 if (!CHECK_WRITE(fsp)) {
5226 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5227 END_PROFILE(SMBwrite);
5231 numtowrite = SVAL(req->vwv+1, 0);
5232 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5233 data = (const char *)req->buf + 3;
5236 * Ensure client isn't asking us to write more than
5237 * they sent. CVE-2017-12163.
5239 remaining = smbreq_bufrem(req, data);
5240 if (numtowrite > remaining) {
5241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5242 END_PROFILE(SMBwrite);
5246 if (!fsp->print_file) {
5247 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5248 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5251 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5252 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5253 END_PROFILE(SMBwrite);
5259 * X/Open SMB protocol says that if smb_vwv1 is
5260 * zero then the file size should be extended or
5261 * truncated to the size given in smb_vwv[2-3].
5264 if(numtowrite == 0) {
5266 * This is actually an allocate call, and set EOF. JRA.
5268 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5270 reply_nterror(req, NT_STATUS_DISK_FULL);
5273 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5275 reply_nterror(req, NT_STATUS_DISK_FULL);
5278 trigger_write_time_update_immediate(fsp);
5280 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5283 status = sync_file(conn, fsp, False);
5284 if (!NT_STATUS_IS_OK(status)) {
5285 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5286 fsp_str_dbg(fsp), nt_errstr(status)));
5287 reply_nterror(req, status);
5292 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5296 if((nwritten == 0) && (numtowrite != 0)) {
5297 reply_nterror(req, NT_STATUS_DISK_FULL);
5301 reply_outbuf(req, 1, 0);
5303 SSVAL(req->outbuf,smb_vwv0,nwritten);
5305 if (nwritten < (ssize_t)numtowrite) {
5306 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5307 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5310 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5313 END_PROFILE(SMBwrite);
5317 /****************************************************************************
5318 Ensure a buffer is a valid writeX for recvfile purposes.
5319 ****************************************************************************/
5321 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5322 (2*14) + /* word count (including bcc) */ \
5325 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5326 const uint8_t *inbuf)
5329 unsigned int doff = 0;
5330 size_t len = smb_len_large(inbuf);
5332 struct smbXsrv_open *op = NULL;
5333 struct files_struct *fsp = NULL;
5336 if (is_encrypted_packet(inbuf)) {
5337 /* Can't do this on encrypted
5342 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5346 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5347 CVAL(inbuf,smb_wct) != 14) {
5348 DEBUG(10,("is_valid_writeX_buffer: chained or "
5349 "invalid word length.\n"));
5353 fnum = SVAL(inbuf, smb_vwv2);
5354 status = smb1srv_open_lookup(xconn,
5358 if (!NT_STATUS_IS_OK(status)) {
5359 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5364 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5367 if (fsp->conn == NULL) {
5368 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5372 if (IS_IPC(fsp->conn)) {
5373 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5376 if (IS_PRINT(fsp->conn)) {
5377 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5380 if (fsp->base_fsp != NULL) {
5381 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5384 doff = SVAL(inbuf,smb_vwv11);
5386 numtowrite = SVAL(inbuf,smb_vwv10);
5388 if (len > doff && len - doff > 0xFFFF) {
5389 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5392 if (numtowrite == 0) {
5393 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5397 /* Ensure the sizes match up. */
5398 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5399 /* no pad byte...old smbclient :-( */
5400 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5402 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5406 if (len - doff != numtowrite) {
5407 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5408 "len = %u, doff = %u, numtowrite = %u\n",
5411 (unsigned int)numtowrite ));
5415 DEBUG(10,("is_valid_writeX_buffer: true "
5416 "len = %u, doff = %u, numtowrite = %u\n",
5419 (unsigned int)numtowrite ));
5424 /****************************************************************************
5425 Reply to a write and X.
5426 ****************************************************************************/
5428 void reply_write_and_X(struct smb_request *req)
5430 connection_struct *conn = req->conn;
5431 struct smbXsrv_connection *xconn = req->xconn;
5433 struct lock_struct lock;
5438 unsigned int smb_doff;
5439 unsigned int smblen;
5442 int saved_errno = 0;
5444 START_PROFILE(SMBwriteX);
5446 if ((req->wct != 12) && (req->wct != 14)) {
5447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5451 numtowrite = SVAL(req->vwv+10, 0);
5452 smb_doff = SVAL(req->vwv+11, 0);
5453 smblen = smb_len(req->inbuf);
5455 if (req->unread_bytes > 0xFFFF ||
5456 (smblen > smb_doff &&
5457 smblen - smb_doff > 0xFFFF)) {
5458 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5461 if (req->unread_bytes) {
5462 /* Can't do a recvfile write on IPC$ */
5464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5467 if (numtowrite != req->unread_bytes) {
5468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5473 * This already protects us against CVE-2017-12163.
5475 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5476 smb_doff + numtowrite > smblen) {
5477 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5482 /* If it's an IPC, pass off the pipe handler. */
5484 if (req->unread_bytes) {
5485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5488 reply_pipe_write_and_X(req);
5492 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5493 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5494 write_through = BITSETW(req->vwv+7,0);
5496 if (!check_fsp(conn, req, fsp)) {
5500 if (!CHECK_WRITE(fsp)) {
5501 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5505 data = smb_base(req->inbuf) + smb_doff;
5507 if(req->wct == 14) {
5509 * This is a large offset (64 bit) write.
5511 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5515 /* X/Open SMB protocol says that, unlike SMBwrite
5516 if the length is zero then NO truncation is
5517 done, just a write of zero. To truncate a file,
5520 if(numtowrite == 0) {
5523 if (req->unread_bytes == 0) {
5524 status = schedule_aio_write_and_X(conn,
5531 if (NT_STATUS_IS_OK(status)) {
5532 /* write scheduled - we're done. */
5535 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5536 /* Real error - report to client. */
5537 reply_nterror(req, status);
5540 /* NT_STATUS_RETRY - fall through to sync write. */
5543 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5544 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5547 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5548 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5552 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5553 saved_errno = errno;
5557 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5561 if((nwritten == 0) && (numtowrite != 0)) {
5562 reply_nterror(req, NT_STATUS_DISK_FULL);
5566 reply_outbuf(req, 6, 0);
5567 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5568 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5569 SSVAL(req->outbuf,smb_vwv2,nwritten);
5570 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5572 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5573 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5575 status = sync_file(conn, fsp, write_through);
5576 if (!NT_STATUS_IS_OK(status)) {
5577 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5578 fsp_str_dbg(fsp), nt_errstr(status)));
5579 reply_nterror(req, status);
5583 END_PROFILE(SMBwriteX);
5587 if (req->unread_bytes) {
5588 /* writeX failed. drain socket. */
5589 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5590 req->unread_bytes) {
5591 smb_panic("failed to drain pending bytes");
5593 req->unread_bytes = 0;
5596 END_PROFILE(SMBwriteX);
5600 /****************************************************************************
5602 ****************************************************************************/
5604 void reply_lseek(struct smb_request *req)
5606 connection_struct *conn = req->conn;
5613 START_PROFILE(SMBlseek);
5616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5617 END_PROFILE(SMBlseek);
5621 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5623 if (!check_fsp(conn, req, fsp)) {
5627 mode = SVAL(req->vwv+1, 0) & 3;
5628 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5629 startpos = (off_t)IVALS(req->vwv+2, 0);
5638 res = fh_get_pos(fsp->fh) + startpos;
5649 if (umode == SEEK_END) {
5650 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5651 if(errno == EINVAL) {
5652 off_t current_pos = startpos;
5654 status = vfs_stat_fsp(fsp);
5655 if (!NT_STATUS_IS_OK(status)) {
5656 reply_nterror(req, status);
5657 END_PROFILE(SMBlseek);
5661 current_pos += fsp->fsp_name->st.st_ex_size;
5663 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5668 reply_nterror(req, map_nt_error_from_unix(errno));
5669 END_PROFILE(SMBlseek);
5674 fh_set_pos(fsp->fh, res);
5676 reply_outbuf(req, 2, 0);
5677 SIVAL(req->outbuf,smb_vwv0,res);
5679 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5680 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5682 END_PROFILE(SMBlseek);
5686 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5689 connection_struct *conn = talloc_get_type_abort(
5690 private_data, connection_struct);
5692 if (conn != fsp->conn) {
5695 if (fsp_get_io_fd(fsp) == -1) {
5698 sync_file(conn, fsp, True /* write through */);
5700 if (fsp->fsp_flags.modified) {
5701 trigger_write_time_update_immediate(fsp);
5707 /****************************************************************************
5709 ****************************************************************************/
5711 void reply_flush(struct smb_request *req)
5713 connection_struct *conn = req->conn;
5717 START_PROFILE(SMBflush);
5720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5724 fnum = SVAL(req->vwv+0, 0);
5725 fsp = file_fsp(req, fnum);
5727 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5732 files_forall(req->sconn, file_sync_one_fn, conn);
5734 NTSTATUS status = sync_file(conn, fsp, True);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5737 fsp_str_dbg(fsp), nt_errstr(status)));
5738 reply_nterror(req, status);
5739 END_PROFILE(SMBflush);
5742 if (fsp->fsp_flags.modified) {
5743 trigger_write_time_update_immediate(fsp);
5747 reply_outbuf(req, 0, 0);
5749 DEBUG(3,("flush\n"));
5750 END_PROFILE(SMBflush);
5754 /****************************************************************************
5756 conn POINTER CAN BE NULL HERE !
5757 ****************************************************************************/
5759 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5760 static void reply_exit_done(struct tevent_req *req);
5762 void reply_exit(struct smb_request *smb1req)
5764 struct tevent_req *req;
5767 * Don't setup the profile charge here, take
5768 * it in reply_exit_done(). Not strictly correct
5769 * but better than the other SMB1 async
5770 * code that double-charges at the moment.
5772 req = reply_exit_send(smb1req);
5774 /* Not going async, profile here. */
5775 START_PROFILE(SMBexit);
5776 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5777 END_PROFILE(SMBexit);
5781 /* We're async. This will complete later. */
5782 tevent_req_set_callback(req, reply_exit_done, smb1req);
5786 struct reply_exit_state {
5787 struct tevent_queue *wait_queue;
5790 static void reply_exit_wait_done(struct tevent_req *subreq);
5792 /****************************************************************************
5794 Note, on failure here we deallocate and return NULL to allow the caller to
5795 SMB1 return an error of ERRnomem immediately.
5796 ****************************************************************************/
5798 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5800 struct tevent_req *req;
5801 struct reply_exit_state *state;
5802 struct tevent_req *subreq;
5804 struct smbd_server_connection *sconn = smb1req->sconn;
5806 req = tevent_req_create(smb1req, &state,
5807 struct reply_exit_state);
5811 state->wait_queue = tevent_queue_create(state,
5812 "reply_exit_wait_queue");
5813 if (tevent_req_nomem(state->wait_queue, req)) {
5818 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5819 if (fsp->file_pid != smb1req->smbpid) {
5822 if (fsp->vuid != smb1req->vuid) {
5826 * Flag the file as close in progress.
5827 * This will prevent any more IO being
5830 fsp->fsp_flags.closing = true;
5832 if (fsp->num_aio_requests > 0) {
5834 * Now wait until all aio requests on this fsp are
5837 * We don't set a callback, as we just want to block the
5838 * wait queue and the talloc_free() of fsp->aio_request
5839 * will remove the item from the wait queue.
5841 subreq = tevent_queue_wait_send(fsp->aio_requests,
5844 if (tevent_req_nomem(subreq, req)) {
5852 * Now we add our own waiter to the end of the queue,
5853 * this way we get notified when all pending requests are finished
5854 * and reply to the outstanding SMB1 request.
5856 subreq = tevent_queue_wait_send(state,
5859 if (tevent_req_nomem(subreq, req)) {
5865 * We're really going async - move the SMB1 request from
5866 * a talloc stackframe above us to the conn talloc-context.
5867 * We need this to stick around until the wait_done
5868 * callback is invoked.
5870 smb1req = talloc_move(sconn, &smb1req);
5872 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5877 static void reply_exit_wait_done(struct tevent_req *subreq)
5879 struct tevent_req *req = tevent_req_callback_data(
5880 subreq, struct tevent_req);
5882 tevent_queue_wait_recv(subreq);
5883 TALLOC_FREE(subreq);
5884 tevent_req_done(req);
5887 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5889 return tevent_req_simple_recv_ntstatus(req);
5892 static void reply_exit_done(struct tevent_req *req)
5894 struct smb_request *smb1req = tevent_req_callback_data(
5895 req, struct smb_request);
5896 struct smbd_server_connection *sconn = smb1req->sconn;
5897 struct smbXsrv_connection *xconn = smb1req->xconn;
5898 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5899 struct smbXsrv_session *session = NULL;
5900 files_struct *fsp, *next;
5904 * Take the profile charge here. Not strictly
5905 * correct but better than the other SMB1 async
5906 * code that double-charges at the moment.
5908 START_PROFILE(SMBexit);
5910 status = reply_exit_recv(req);
5912 if (!NT_STATUS_IS_OK(status)) {
5913 TALLOC_FREE(smb1req);
5914 END_PROFILE(SMBexit);
5915 exit_server(__location__ ": reply_exit_recv failed");
5920 * Ensure the session is still valid.
5922 status = smb1srv_session_lookup(xconn,
5926 if (!NT_STATUS_IS_OK(status)) {
5927 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5928 smb_request_done(smb1req);
5929 END_PROFILE(SMBexit);
5933 * Ensure the vuid is still valid - no one
5934 * called reply_ulogoffX() in the meantime.
5935 * reply_exit() doesn't have AS_USER set, so
5936 * use set_current_user_info() directly.
5937 * This is the same logic as in switch_message().
5939 if (session->global->auth_session_info != NULL) {
5940 set_current_user_info(
5941 session->global->auth_session_info->unix_info->sanitized_username,
5942 session->global->auth_session_info->unix_info->unix_name,
5943 session->global->auth_session_info->info->domain_name);
5946 /* No more aio - do the actual closes. */
5947 for (fsp = sconn->files; fsp; fsp = next) {
5951 if (fsp->file_pid != smb1req->smbpid) {
5954 if (fsp->vuid != smb1req->vuid) {
5957 if (!fsp->fsp_flags.closing) {
5962 * reply_exit() has the DO_CHDIR flag set.
5964 ok = chdir_current_service(fsp->conn);
5966 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5967 smb_request_done(smb1req);
5968 END_PROFILE(SMBexit);
5970 close_file(NULL, fsp, SHUTDOWN_CLOSE);
5973 reply_outbuf(smb1req, 0, 0);
5975 * The following call is needed to push the
5976 * reply data back out the socket after async
5977 * return. Plus it frees smb1req.
5979 smb_request_done(smb1req);
5980 DBG_INFO("reply_exit complete\n");
5981 END_PROFILE(SMBexit);
5985 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5987 static void reply_close_done(struct tevent_req *req);
5989 void reply_close(struct smb_request *smb1req)
5991 connection_struct *conn = smb1req->conn;
5992 NTSTATUS status = NT_STATUS_OK;
5993 files_struct *fsp = NULL;
5994 START_PROFILE(SMBclose);
5996 if (smb1req->wct < 3) {
5997 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5998 END_PROFILE(SMBclose);
6002 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
6005 * We can only use check_fsp if we know it's not a directory.
6008 if (!check_fsp_open(conn, smb1req, fsp)) {
6009 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
6010 END_PROFILE(SMBclose);
6014 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6015 fsp->fsp_flags.is_directory ?
6016 "directory" : "file",
6017 fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
6018 conn->num_files_open);
6020 if (!fsp->fsp_flags.is_directory) {
6024 * Take care of any time sent in the close.
6027 t = srv_make_unix_date3(smb1req->vwv+1);
6028 set_close_write_time(fsp, time_t_to_full_timespec(t));
6031 if (fsp->num_aio_requests != 0) {
6032 struct tevent_req *req;
6034 req = reply_close_send(smb1req, fsp);
6036 status = NT_STATUS_NO_MEMORY;
6039 /* We're async. This will complete later. */
6040 tevent_req_set_callback(req, reply_close_done, smb1req);
6041 END_PROFILE(SMBclose);
6046 * close_file() returns the unix errno if an error was detected on
6047 * close - normally this is due to a disk full error. If not then it
6048 * was probably an I/O error.
6051 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6053 if (!NT_STATUS_IS_OK(status)) {
6054 reply_nterror(smb1req, status);
6055 END_PROFILE(SMBclose);
6059 reply_outbuf(smb1req, 0, 0);
6060 END_PROFILE(SMBclose);
6064 struct reply_close_state {
6066 struct tevent_queue *wait_queue;
6069 static void reply_close_wait_done(struct tevent_req *subreq);
6071 /****************************************************************************
6073 Note, on failure here we deallocate and return NULL to allow the caller to
6074 SMB1 return an error of ERRnomem immediately.
6075 ****************************************************************************/
6077 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6080 struct tevent_req *req;
6081 struct reply_close_state *state;
6082 struct tevent_req *subreq;
6083 struct smbd_server_connection *sconn = smb1req->sconn;
6085 req = tevent_req_create(smb1req, &state,
6086 struct reply_close_state);
6090 state->wait_queue = tevent_queue_create(state,
6091 "reply_close_wait_queue");
6092 if (tevent_req_nomem(state->wait_queue, req)) {
6098 * Flag the file as close in progress.
6099 * This will prevent any more IO being
6102 fsp->fsp_flags.closing = true;
6105 * Now wait until all aio requests on this fsp are
6108 * We don't set a callback, as we just want to block the
6109 * wait queue and the talloc_free() of fsp->aio_request
6110 * will remove the item from the wait queue.
6112 subreq = tevent_queue_wait_send(fsp->aio_requests,
6115 if (tevent_req_nomem(subreq, req)) {
6121 * Now we add our own waiter to the end of the queue,
6122 * this way we get notified when all pending requests are finished
6123 * and reply to the outstanding SMB1 request.
6125 subreq = tevent_queue_wait_send(state,
6128 if (tevent_req_nomem(subreq, req)) {
6134 * We're really going async - move the SMB1 request from
6135 * a talloc stackframe above us to the conn talloc-context.
6136 * We need this to stick around until the wait_done
6137 * callback is invoked.
6139 smb1req = talloc_move(sconn, &smb1req);
6141 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6146 static void reply_close_wait_done(struct tevent_req *subreq)
6148 struct tevent_req *req = tevent_req_callback_data(
6149 subreq, struct tevent_req);
6151 tevent_queue_wait_recv(subreq);
6152 TALLOC_FREE(subreq);
6153 tevent_req_done(req);
6156 static NTSTATUS reply_close_recv(struct tevent_req *req)
6158 return tevent_req_simple_recv_ntstatus(req);
6161 static void reply_close_done(struct tevent_req *req)
6163 struct smb_request *smb1req = tevent_req_callback_data(
6164 req, struct smb_request);
6165 struct reply_close_state *state = tevent_req_data(req,
6166 struct reply_close_state);
6169 status = reply_close_recv(req);
6171 if (!NT_STATUS_IS_OK(status)) {
6172 TALLOC_FREE(smb1req);
6173 exit_server(__location__ ": reply_close_recv failed");
6177 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6178 if (NT_STATUS_IS_OK(status)) {
6179 reply_outbuf(smb1req, 0, 0);
6181 reply_nterror(smb1req, status);
6184 * The following call is needed to push the
6185 * reply data back out the socket after async
6186 * return. Plus it frees smb1req.
6188 smb_request_done(smb1req);
6191 /****************************************************************************
6192 Reply to a writeclose (Core+ protocol).
6193 ****************************************************************************/
6195 void reply_writeclose(struct smb_request *req)
6197 connection_struct *conn = req->conn;
6200 ssize_t nwritten = -1;
6201 NTSTATUS close_status = NT_STATUS_OK;
6204 struct timespec mtime;
6206 struct lock_struct lock;
6208 START_PROFILE(SMBwriteclose);
6211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6212 END_PROFILE(SMBwriteclose);
6216 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6218 if (!check_fsp(conn, req, fsp)) {
6219 END_PROFILE(SMBwriteclose);
6222 if (!CHECK_WRITE(fsp)) {
6223 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6224 END_PROFILE(SMBwriteclose);
6228 numtowrite = SVAL(req->vwv+1, 0);
6229 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6230 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6231 data = (const char *)req->buf + 1;
6234 * Ensure client isn't asking us to write more than
6235 * they sent. CVE-2017-12163.
6237 remaining = smbreq_bufrem(req, data);
6238 if (numtowrite > remaining) {
6239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6240 END_PROFILE(SMBwriteclose);
6244 if (fsp->print_file == NULL) {
6245 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6246 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6249 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6250 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6251 END_PROFILE(SMBwriteclose);
6256 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6258 set_close_write_time(fsp, mtime);
6261 * More insanity. W2K only closes the file if writelen > 0.
6265 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6266 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6267 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6270 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6271 "file %s\n", fsp_str_dbg(fsp)));
6272 close_status = close_file(req, fsp, NORMAL_CLOSE);
6276 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6277 reply_nterror(req, NT_STATUS_DISK_FULL);
6281 if(!NT_STATUS_IS_OK(close_status)) {
6282 reply_nterror(req, close_status);
6286 reply_outbuf(req, 1, 0);
6288 SSVAL(req->outbuf,smb_vwv0,nwritten);
6292 END_PROFILE(SMBwriteclose);
6297 #define DBGC_CLASS DBGC_LOCKING
6299 /****************************************************************************
6301 ****************************************************************************/
6303 static void reply_lock_done(struct tevent_req *subreq);
6305 void reply_lock(struct smb_request *req)
6307 struct tevent_req *subreq = NULL;
6308 connection_struct *conn = req->conn;
6310 struct smbd_lock_element *lck = NULL;
6312 START_PROFILE(SMBlock);
6315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6316 END_PROFILE(SMBlock);
6320 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6322 if (!check_fsp(conn, req, fsp)) {
6323 END_PROFILE(SMBlock);
6327 lck = talloc(req, struct smbd_lock_element);
6329 reply_nterror(req, NT_STATUS_NO_MEMORY);
6330 END_PROFILE(SMBlock);
6334 *lck = (struct smbd_lock_element) {
6335 .req_guid = smbd_request_guid(req, 0),
6336 .smblctx = req->smbpid,
6337 .brltype = WRITE_LOCK,
6338 .count = IVAL(req->vwv+1, 0),
6339 .offset = IVAL(req->vwv+3, 0),
6342 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6348 subreq = smbd_smb1_do_locks_send(
6354 false, /* large_offset */
6358 if (subreq == NULL) {
6359 reply_nterror(req, NT_STATUS_NO_MEMORY);
6360 END_PROFILE(SMBlock);
6363 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6364 END_PROFILE(SMBlock);
6367 static void reply_lock_done(struct tevent_req *subreq)
6369 struct smb_request *req = NULL;
6373 START_PROFILE(SMBlock);
6375 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6378 status = smbd_smb1_do_locks_recv(subreq);
6379 TALLOC_FREE(subreq);
6381 if (NT_STATUS_IS_OK(status)) {
6382 reply_outbuf(req, 0, 0);
6384 reply_nterror(req, status);
6387 ok = srv_send_smb(req->xconn,
6388 (char *)req->outbuf,
6391 IS_CONN_ENCRYPTED(req->conn),
6394 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6397 END_PROFILE(SMBlock);
6400 /****************************************************************************
6402 ****************************************************************************/
6404 void reply_unlock(struct smb_request *req)
6406 connection_struct *conn = req->conn;
6409 struct smbd_lock_element lck;
6411 START_PROFILE(SMBunlock);
6414 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6415 END_PROFILE(SMBunlock);
6419 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6421 if (!check_fsp(conn, req, fsp)) {
6422 END_PROFILE(SMBunlock);
6426 lck = (struct smbd_lock_element) {
6427 .req_guid = smbd_request_guid(req, 0),
6428 .smblctx = req->smbpid,
6429 .brltype = UNLOCK_LOCK,
6430 .offset = IVAL(req->vwv+3, 0),
6431 .count = IVAL(req->vwv+1, 0),
6434 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6436 if (!NT_STATUS_IS_OK(status)) {
6437 reply_nterror(req, status);
6438 END_PROFILE(SMBunlock);
6442 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6448 reply_outbuf(req, 0, 0);
6450 END_PROFILE(SMBunlock);
6455 #define DBGC_CLASS DBGC_ALL
6457 /****************************************************************************
6459 conn POINTER CAN BE NULL HERE !
6460 ****************************************************************************/
6462 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6463 static void reply_tdis_done(struct tevent_req *req);
6465 void reply_tdis(struct smb_request *smb1req)
6467 connection_struct *conn = smb1req->conn;
6468 struct tevent_req *req;
6471 * Don't setup the profile charge here, take
6472 * it in reply_tdis_done(). Not strictly correct
6473 * but better than the other SMB1 async
6474 * code that double-charges at the moment.
6478 /* Not going async, profile here. */
6479 START_PROFILE(SMBtdis);
6480 DBG_INFO("Invalid connection in tdis\n");
6481 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6482 END_PROFILE(SMBtdis);
6486 req = reply_tdis_send(smb1req);
6488 /* Not going async, profile here. */
6489 START_PROFILE(SMBtdis);
6490 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6491 END_PROFILE(SMBtdis);
6494 /* We're async. This will complete later. */
6495 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6499 struct reply_tdis_state {
6500 struct tevent_queue *wait_queue;
6503 static void reply_tdis_wait_done(struct tevent_req *subreq);
6505 /****************************************************************************
6507 Note, on failure here we deallocate and return NULL to allow the caller to
6508 SMB1 return an error of ERRnomem immediately.
6509 ****************************************************************************/
6511 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6513 struct tevent_req *req;
6514 struct reply_tdis_state *state;
6515 struct tevent_req *subreq;
6516 connection_struct *conn = smb1req->conn;
6519 req = tevent_req_create(smb1req, &state,
6520 struct reply_tdis_state);
6524 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6525 if (tevent_req_nomem(state->wait_queue, req)) {
6531 * Make sure that no new request will be able to use this tcon.
6532 * This ensures that once all outstanding fsp->aio_requests
6533 * on this tcon are done, we are safe to close it.
6535 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6537 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6538 if (fsp->conn != conn) {
6542 * Flag the file as close in progress.
6543 * This will prevent any more IO being
6544 * done on it. Not strictly needed, but
6545 * doesn't hurt to flag it as closing.
6547 fsp->fsp_flags.closing = true;
6549 if (fsp->num_aio_requests > 0) {
6551 * Now wait until all aio requests on this fsp are
6554 * We don't set a callback, as we just want to block the
6555 * wait queue and the talloc_free() of fsp->aio_request
6556 * will remove the item from the wait queue.
6558 subreq = tevent_queue_wait_send(fsp->aio_requests,
6559 conn->sconn->ev_ctx,
6561 if (tevent_req_nomem(subreq, req)) {
6569 * Now we add our own waiter to the end of the queue,
6570 * this way we get notified when all pending requests are finished
6571 * and reply to the outstanding SMB1 request.
6573 subreq = tevent_queue_wait_send(state,
6574 conn->sconn->ev_ctx,
6576 if (tevent_req_nomem(subreq, req)) {
6582 * We're really going async - move the SMB1 request from
6583 * a talloc stackframe above us to the sconn talloc-context.
6584 * We need this to stick around until the wait_done
6585 * callback is invoked.
6587 smb1req = talloc_move(smb1req->sconn, &smb1req);
6589 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6594 static void reply_tdis_wait_done(struct tevent_req *subreq)
6596 struct tevent_req *req = tevent_req_callback_data(
6597 subreq, struct tevent_req);
6599 tevent_queue_wait_recv(subreq);
6600 TALLOC_FREE(subreq);
6601 tevent_req_done(req);
6604 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6606 return tevent_req_simple_recv_ntstatus(req);
6609 static void reply_tdis_done(struct tevent_req *req)
6611 struct smb_request *smb1req = tevent_req_callback_data(
6612 req, struct smb_request);
6614 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6618 * Take the profile charge here. Not strictly
6619 * correct but better than the other SMB1 async
6620 * code that double-charges at the moment.
6622 START_PROFILE(SMBtdis);
6624 status = reply_tdis_recv(req);
6626 if (!NT_STATUS_IS_OK(status)) {
6627 TALLOC_FREE(smb1req);
6628 END_PROFILE(SMBtdis);
6629 exit_server(__location__ ": reply_tdis_recv failed");
6634 * As we've been awoken, we may have changed
6635 * directory in the meantime.
6636 * reply_tdis() has the DO_CHDIR flag set.
6638 ok = chdir_current_service(smb1req->conn);
6640 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6641 smb_request_done(smb1req);
6642 END_PROFILE(SMBtdis);
6645 status = smbXsrv_tcon_disconnect(tcon,
6647 if (!NT_STATUS_IS_OK(status)) {
6648 TALLOC_FREE(smb1req);
6649 END_PROFILE(SMBtdis);
6650 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6654 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6655 smb1req->conn = NULL;
6659 reply_outbuf(smb1req, 0, 0);
6661 * The following call is needed to push the
6662 * reply data back out the socket after async
6663 * return. Plus it frees smb1req.
6665 smb_request_done(smb1req);
6666 END_PROFILE(SMBtdis);
6669 /****************************************************************************
6671 conn POINTER CAN BE NULL HERE !
6672 ****************************************************************************/
6674 void reply_echo(struct smb_request *req)
6676 connection_struct *conn = req->conn;
6677 struct smb_perfcount_data local_pcd;
6678 struct smb_perfcount_data *cur_pcd;
6682 START_PROFILE(SMBecho);
6684 smb_init_perfcount_data(&local_pcd);
6687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6688 END_PROFILE(SMBecho);
6692 smb_reverb = SVAL(req->vwv+0, 0);
6694 reply_outbuf(req, 1, req->buflen);
6696 /* copy any incoming data back out */
6697 if (req->buflen > 0) {
6698 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6701 if (smb_reverb > 100) {
6702 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6706 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6708 /* this makes sure we catch the request pcd */
6709 if (seq_num == smb_reverb) {
6710 cur_pcd = &req->pcd;
6712 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6713 cur_pcd = &local_pcd;
6716 SSVAL(req->outbuf,smb_vwv0,seq_num);
6718 show_msg((char *)req->outbuf);
6719 if (!srv_send_smb(req->xconn,
6720 (char *)req->outbuf,
6721 true, req->seqnum+1,
6722 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6724 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6727 DEBUG(3,("echo %d times\n", smb_reverb));
6729 TALLOC_FREE(req->outbuf);
6731 END_PROFILE(SMBecho);
6735 /****************************************************************************
6736 Reply to a printopen.
6737 ****************************************************************************/
6739 void reply_printopen(struct smb_request *req)
6741 connection_struct *conn = req->conn;
6745 START_PROFILE(SMBsplopen);
6748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6749 END_PROFILE(SMBsplopen);
6753 if (!CAN_PRINT(conn)) {
6754 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6755 END_PROFILE(SMBsplopen);
6759 status = file_new(req, conn, &fsp);
6760 if(!NT_STATUS_IS_OK(status)) {
6761 reply_nterror(req, status);
6762 END_PROFILE(SMBsplopen);
6766 /* Open for exclusive use, write only. */
6767 status = print_spool_open(fsp, NULL, req->vuid);
6769 if (!NT_STATUS_IS_OK(status)) {
6770 file_free(req, fsp);
6771 reply_nterror(req, status);
6772 END_PROFILE(SMBsplopen);
6776 reply_outbuf(req, 1, 0);
6777 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6779 DEBUG(3,("openprint fd=%d %s\n",
6780 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
6782 END_PROFILE(SMBsplopen);
6786 /****************************************************************************
6787 Reply to a printclose.
6788 ****************************************************************************/
6790 void reply_printclose(struct smb_request *req)
6792 connection_struct *conn = req->conn;
6796 START_PROFILE(SMBsplclose);
6799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6800 END_PROFILE(SMBsplclose);
6804 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6806 if (!check_fsp(conn, req, fsp)) {
6807 END_PROFILE(SMBsplclose);
6811 if (!CAN_PRINT(conn)) {
6812 reply_force_doserror(req, ERRSRV, ERRerror);
6813 END_PROFILE(SMBsplclose);
6817 DEBUG(3,("printclose fd=%d %s\n",
6818 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
6820 status = close_file(req, fsp, NORMAL_CLOSE);
6822 if(!NT_STATUS_IS_OK(status)) {
6823 reply_nterror(req, status);
6824 END_PROFILE(SMBsplclose);
6828 reply_outbuf(req, 0, 0);
6830 END_PROFILE(SMBsplclose);
6834 /****************************************************************************
6835 Reply to a printqueue.
6836 ****************************************************************************/
6838 void reply_printqueue(struct smb_request *req)
6840 const struct loadparm_substitution *lp_sub =
6841 loadparm_s3_global_substitution();
6842 connection_struct *conn = req->conn;
6846 START_PROFILE(SMBsplretq);
6849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6850 END_PROFILE(SMBsplretq);
6854 max_count = SVAL(req->vwv+0, 0);
6855 start_index = SVAL(req->vwv+1, 0);
6857 /* we used to allow the client to get the cnum wrong, but that
6858 is really quite gross and only worked when there was only
6859 one printer - I think we should now only accept it if they
6860 get it right (tridge) */
6861 if (!CAN_PRINT(conn)) {
6862 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6863 END_PROFILE(SMBsplretq);
6867 reply_outbuf(req, 2, 3);
6868 SSVAL(req->outbuf,smb_vwv0,0);
6869 SSVAL(req->outbuf,smb_vwv1,0);
6870 SCVAL(smb_buf(req->outbuf),0,1);
6871 SSVAL(smb_buf(req->outbuf),1,0);
6873 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6874 start_index, max_count));
6877 TALLOC_CTX *mem_ctx = talloc_tos();
6880 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6881 struct rpc_pipe_client *cli = NULL;
6882 struct dcerpc_binding_handle *b = NULL;
6883 struct policy_handle handle;
6884 struct spoolss_DevmodeContainer devmode_ctr;
6885 union spoolss_JobInfo *info;
6887 uint32_t num_to_get;
6891 ZERO_STRUCT(handle);
6893 status = rpc_pipe_open_interface(mem_ctx,
6896 conn->sconn->remote_address,
6897 conn->sconn->local_address,
6898 conn->sconn->msg_ctx,
6900 if (!NT_STATUS_IS_OK(status)) {
6901 DEBUG(0, ("reply_printqueue: "
6902 "could not connect to spoolss: %s\n",
6903 nt_errstr(status)));
6904 reply_nterror(req, status);
6907 b = cli->binding_handle;
6909 ZERO_STRUCT(devmode_ctr);
6911 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6914 SEC_FLAG_MAXIMUM_ALLOWED,
6917 if (!NT_STATUS_IS_OK(status)) {
6918 reply_nterror(req, status);
6921 if (!W_ERROR_IS_OK(werr)) {
6922 reply_nterror(req, werror_to_ntstatus(werr));
6926 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6934 if (!W_ERROR_IS_OK(werr)) {
6935 reply_nterror(req, werror_to_ntstatus(werr));
6939 if (max_count > 0) {
6940 first = start_index;
6942 first = start_index + max_count + 1;
6945 if (first >= count) {
6948 num_to_get = first + MIN(ABS(max_count), count - first);
6951 for (i = first; i < num_to_get; i++) {
6954 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6957 uint16_t qrapjobid = pjobid_to_rap(sharename,
6958 info[i].info2.job_id);
6960 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6966 srv_put_dos_date2(p, 0, qtime);
6967 SCVAL(p, 4, qstatus);
6968 SSVAL(p, 5, qrapjobid);
6969 SIVAL(p, 7, info[i].info2.size);
6971 status = srvstr_push(blob, req->flags2, p+12,
6972 info[i].info2.notify_name, 16, STR_ASCII, &len);
6973 if (!NT_STATUS_IS_OK(status)) {
6974 reply_nterror(req, status);
6977 if (message_push_blob(
6980 blob, sizeof(blob))) == -1) {
6981 reply_nterror(req, NT_STATUS_NO_MEMORY);
6987 SSVAL(req->outbuf,smb_vwv0,count);
6988 SSVAL(req->outbuf,smb_vwv1,
6989 (max_count>0?first+count:first-1));
6990 SCVAL(smb_buf(req->outbuf),0,1);
6991 SSVAL(smb_buf(req->outbuf),1,28*count);
6995 DEBUG(3, ("%u entries returned in queue\n",
6999 if (b && is_valid_policy_hnd(&handle)) {
7000 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
7005 END_PROFILE(SMBsplretq);
7009 /****************************************************************************
7010 Reply to a printwrite.
7011 ****************************************************************************/
7013 void reply_printwrite(struct smb_request *req)
7015 connection_struct *conn = req->conn;
7020 START_PROFILE(SMBsplwr);
7023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7024 END_PROFILE(SMBsplwr);
7028 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7030 if (!check_fsp(conn, req, fsp)) {
7031 END_PROFILE(SMBsplwr);
7035 if (!fsp->print_file) {
7036 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7037 END_PROFILE(SMBsplwr);
7041 if (!CHECK_WRITE(fsp)) {
7042 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7043 END_PROFILE(SMBsplwr);
7047 numtowrite = SVAL(req->buf, 1);
7050 * This already protects us against CVE-2017-12163.
7052 if (req->buflen < numtowrite + 3) {
7053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7054 END_PROFILE(SMBsplwr);
7058 data = (const char *)req->buf + 3;
7060 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7061 reply_nterror(req, map_nt_error_from_unix(errno));
7062 END_PROFILE(SMBsplwr);
7066 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7068 reply_outbuf(req, 0, 0);
7070 END_PROFILE(SMBsplwr);
7074 /****************************************************************************
7076 ****************************************************************************/
7078 void reply_mkdir(struct smb_request *req)
7080 connection_struct *conn = req->conn;
7081 struct smb_filename *smb_dname = NULL;
7082 char *directory = NULL;
7085 TALLOC_CTX *ctx = talloc_tos();
7087 START_PROFILE(SMBmkdir);
7089 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7090 STR_TERMINATE, &status);
7091 if (!NT_STATUS_IS_OK(status)) {
7092 reply_nterror(req, status);
7096 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7097 status = filename_convert(ctx, conn,
7102 if (!NT_STATUS_IS_OK(status)) {
7103 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7104 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7105 ERRSRV, ERRbadpath);
7108 reply_nterror(req, status);
7112 status = create_directory(conn, req, smb_dname);
7114 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7116 if (!NT_STATUS_IS_OK(status)) {
7118 if (!use_nt_status()
7119 && NT_STATUS_EQUAL(status,
7120 NT_STATUS_OBJECT_NAME_COLLISION)) {
7122 * Yes, in the DOS error code case we get a
7123 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7124 * samba4 torture test.
7126 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7129 reply_nterror(req, status);
7133 reply_outbuf(req, 0, 0);
7135 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7137 TALLOC_FREE(smb_dname);
7138 END_PROFILE(SMBmkdir);
7142 /****************************************************************************
7144 ****************************************************************************/
7146 void reply_rmdir(struct smb_request *req)
7148 connection_struct *conn = req->conn;
7149 struct smb_filename *smb_dname = NULL;
7150 char *directory = NULL;
7152 TALLOC_CTX *ctx = talloc_tos();
7153 files_struct *fsp = NULL;
7155 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7157 START_PROFILE(SMBrmdir);
7159 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7160 STR_TERMINATE, &status);
7161 if (!NT_STATUS_IS_OK(status)) {
7162 reply_nterror(req, status);
7166 status = filename_convert(ctx, conn,
7171 if (!NT_STATUS_IS_OK(status)) {
7172 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7173 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7174 ERRSRV, ERRbadpath);
7177 reply_nterror(req, status);
7181 if (is_ntfs_stream_smb_fname(smb_dname)) {
7182 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7186 status = SMB_VFS_CREATE_FILE(
7189 smb_dname, /* fname */
7190 DELETE_ACCESS, /* access_mask */
7191 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7193 FILE_OPEN, /* create_disposition*/
7194 FILE_DIRECTORY_FILE, /* create_options */
7195 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7196 0, /* oplock_request */
7198 0, /* allocation_size */
7199 0, /* private_flags */
7204 NULL, NULL); /* create context */
7206 if (!NT_STATUS_IS_OK(status)) {
7207 if (open_was_deferred(req->xconn, req->mid)) {
7208 /* We have re-scheduled this call. */
7211 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7212 bool ok = defer_smb1_sharing_violation(req);
7217 reply_nterror(req, status);
7221 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7222 if (!NT_STATUS_IS_OK(status)) {
7223 close_file(req, fsp, ERROR_CLOSE);
7224 reply_nterror(req, status);
7228 if (!set_delete_on_close(fsp, true,
7229 conn->session_info->security_token,
7230 conn->session_info->unix_token)) {
7231 close_file(req, fsp, ERROR_CLOSE);
7232 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7236 status = close_file(req, fsp, NORMAL_CLOSE);
7237 if (!NT_STATUS_IS_OK(status)) {
7238 reply_nterror(req, status);
7240 reply_outbuf(req, 0, 0);
7243 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7245 TALLOC_FREE(smb_dname);
7246 END_PROFILE(SMBrmdir);
7250 /*******************************************************************
7251 Resolve wildcards in a filename rename.
7252 ********************************************************************/
7254 static bool resolve_wildcards(TALLOC_CTX *ctx,
7259 char *name2_copy = NULL;
7264 char *p,*p2, *pname1, *pname2;
7266 name2_copy = talloc_strdup(ctx, name2);
7271 pname1 = strrchr_m(name1,'/');
7272 pname2 = strrchr_m(name2_copy,'/');
7274 if (!pname1 || !pname2) {
7278 /* Truncate the copy of name2 at the last '/' */
7281 /* Now go past the '/' */
7285 root1 = talloc_strdup(ctx, pname1);
7286 root2 = talloc_strdup(ctx, pname2);
7288 if (!root1 || !root2) {
7292 p = strrchr_m(root1,'.');
7295 ext1 = talloc_strdup(ctx, p+1);
7297 ext1 = talloc_strdup(ctx, "");
7299 p = strrchr_m(root2,'.');
7302 ext2 = talloc_strdup(ctx, p+1);
7304 ext2 = talloc_strdup(ctx, "");
7307 if (!ext1 || !ext2) {
7315 /* Hmmm. Should this be mb-aware ? */
7318 } else if (*p2 == '*') {
7320 root2 = talloc_asprintf(ctx, "%s%s",
7339 /* Hmmm. Should this be mb-aware ? */
7342 } else if (*p2 == '*') {
7344 ext2 = talloc_asprintf(ctx, "%s%s",
7360 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7365 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7377 /****************************************************************************
7378 Ensure open files have their names updated. Updated to notify other smbd's
7380 ****************************************************************************/
7382 static void rename_open_files(connection_struct *conn,
7383 struct share_mode_lock *lck,
7385 uint32_t orig_name_hash,
7386 const struct smb_filename *smb_fname_dst)
7389 bool did_rename = False;
7391 uint32_t new_name_hash = 0;
7393 for(fsp = file_find_di_first(conn->sconn, id, false); fsp;
7394 fsp = file_find_di_next(fsp, false)) {
7395 struct file_id_buf idbuf;
7396 /* fsp_name is a relative path under the fsp. To change this for other
7397 sharepaths we need to manipulate relative paths. */
7398 /* TODO - create the absolute path and manipulate the newname
7399 relative to the sharepath. */
7400 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7403 if (fsp->name_hash != orig_name_hash) {
7406 DBG_DEBUG("renaming file %s "
7407 "(file_id %s) from %s -> %s\n",
7409 file_id_str_buf(fsp->file_id, &idbuf),
7411 smb_fname_str_dbg(smb_fname_dst));
7413 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7414 if (NT_STATUS_IS_OK(status)) {
7416 new_name_hash = fsp->name_hash;
7421 struct file_id_buf idbuf;
7422 DBG_DEBUG("no open files on file_id %s "
7424 file_id_str_buf(id, &idbuf),
7425 smb_fname_str_dbg(smb_fname_dst));
7428 /* Send messages to all smbd's (not ourself) that the name has changed. */
7429 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7430 orig_name_hash, new_name_hash,
7435 /****************************************************************************
7436 We need to check if the source path is a parent directory of the destination
7437 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7438 refuse the rename with a sharing violation. Under UNIX the above call can
7439 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7440 probably need to check that the client is a Windows one before disallowing
7441 this as a UNIX client (one with UNIX extensions) can know the source is a
7442 symlink and make this decision intelligently. Found by an excellent bug
7443 report from <AndyLiebman@aol.com>.
7444 ****************************************************************************/
7446 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7447 const struct smb_filename *smb_fname_dst)
7449 const char *psrc = smb_fname_src->base_name;
7450 const char *pdst = smb_fname_dst->base_name;
7453 if (psrc[0] == '.' && psrc[1] == '/') {
7456 if (pdst[0] == '.' && pdst[1] == '/') {
7459 if ((slen = strlen(psrc)) > strlen(pdst)) {
7462 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7466 * Do the notify calls from a rename
7469 static void notify_rename(connection_struct *conn, bool is_dir,
7470 const struct smb_filename *smb_fname_src,
7471 const struct smb_filename *smb_fname_dst)
7473 char *parent_dir_src = NULL;
7474 char *parent_dir_dst = NULL;
7477 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7478 : FILE_NOTIFY_CHANGE_FILE_NAME;
7480 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7481 &parent_dir_src, NULL) ||
7482 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7483 &parent_dir_dst, NULL)) {
7487 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7488 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7489 smb_fname_src->base_name);
7490 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7491 smb_fname_dst->base_name);
7494 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7495 smb_fname_src->base_name);
7496 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7497 smb_fname_dst->base_name);
7500 /* this is a strange one. w2k3 gives an additional event for
7501 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7502 files, but not directories */
7504 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7505 FILE_NOTIFY_CHANGE_ATTRIBUTES
7506 |FILE_NOTIFY_CHANGE_CREATION,
7507 smb_fname_dst->base_name);
7510 TALLOC_FREE(parent_dir_src);
7511 TALLOC_FREE(parent_dir_dst);
7514 /****************************************************************************
7515 Returns an error if the parent directory for a filename is open in an
7517 ****************************************************************************/
7519 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7520 const struct smb_filename *smb_fname_dst_in)
7522 struct smb_filename *smb_fname_parent = NULL;
7524 files_struct *fsp = NULL;
7528 status = SMB_VFS_PARENT_PATHNAME(conn,
7533 if (!NT_STATUS_IS_OK(status)) {
7537 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7539 return map_nt_error_from_unix(errno);
7543 * We're only checking on this smbd here, mostly good
7544 * enough.. and will pass tests.
7547 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7548 for (fsp = file_find_di_first(conn->sconn, id, true); fsp;
7549 fsp = file_find_di_next(fsp, true)) {
7550 if (fsp->access_mask & DELETE_ACCESS) {
7551 return NT_STATUS_SHARING_VIOLATION;
7554 return NT_STATUS_OK;
7557 /****************************************************************************
7558 Rename an open file - given an fsp.
7559 ****************************************************************************/
7561 NTSTATUS rename_internals_fsp(connection_struct *conn,
7563 struct smb_filename *smb_fname_dst_in,
7564 const char *dst_original_lcomp,
7566 bool replace_if_exists)
7568 TALLOC_CTX *ctx = talloc_tos();
7569 struct smb_filename *parent_dir_fname_dst = NULL;
7570 struct smb_filename *parent_dir_fname_dst_atname = NULL;
7571 struct smb_filename *smb_fname_dst = NULL;
7572 NTSTATUS status = NT_STATUS_OK;
7573 struct share_mode_lock *lck = NULL;
7574 uint32_t access_mask = SEC_DIR_ADD_FILE;
7575 bool dst_exists, old_is_stream, new_is_stream;
7578 status = check_name(conn, smb_fname_dst_in);
7579 if (!NT_STATUS_IS_OK(status)) {
7583 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7584 if (!NT_STATUS_IS_OK(status)) {
7588 if (file_has_open_streams(fsp)) {
7589 return NT_STATUS_ACCESS_DENIED;
7592 /* Make a copy of the dst smb_fname structs */
7594 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7595 if (smb_fname_dst == NULL) {
7596 status = NT_STATUS_NO_MEMORY;
7601 * Check for special case with case preserving and not
7602 * case sensitive. If the new last component differs from the original
7603 * last component only by case, then we should allow
7604 * the rename (user is trying to change the case of the
7607 if (!conn->case_sensitive && conn->case_preserve &&
7608 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7609 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7610 char *fname_dst_parent = NULL;
7611 const char *fname_dst_lcomp = NULL;
7612 char *orig_lcomp_path = NULL;
7613 char *orig_lcomp_stream = NULL;
7617 * Split off the last component of the processed
7618 * destination name. We will compare this to
7619 * the split components of dst_original_lcomp.
7621 if (!parent_dirname(ctx,
7622 smb_fname_dst->base_name,
7624 &fname_dst_lcomp)) {
7625 status = NT_STATUS_NO_MEMORY;
7630 * The dst_original_lcomp component contains
7631 * the last_component of the path + stream
7632 * name (if a stream exists).
7634 * Split off the stream name so we
7635 * can check them separately.
7638 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7639 /* POSIX - no stream component. */
7640 orig_lcomp_path = talloc_strdup(ctx,
7641 dst_original_lcomp);
7642 if (orig_lcomp_path == NULL) {
7646 ok = split_stream_filename(ctx,
7649 &orig_lcomp_stream);
7653 TALLOC_FREE(fname_dst_parent);
7654 status = NT_STATUS_NO_MEMORY;
7658 /* If the base names only differ by case, use original. */
7659 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7662 * Replace the modified last component with the
7665 if (!ISDOT(fname_dst_parent)) {
7666 tmp = talloc_asprintf(smb_fname_dst,
7671 tmp = talloc_strdup(smb_fname_dst,
7675 status = NT_STATUS_NO_MEMORY;
7676 TALLOC_FREE(fname_dst_parent);
7677 TALLOC_FREE(orig_lcomp_path);
7678 TALLOC_FREE(orig_lcomp_stream);
7681 TALLOC_FREE(smb_fname_dst->base_name);
7682 smb_fname_dst->base_name = tmp;
7685 /* If the stream_names only differ by case, use original. */
7686 if(!strcsequal(smb_fname_dst->stream_name,
7687 orig_lcomp_stream)) {
7688 /* Use the original stream. */
7689 char *tmp = talloc_strdup(smb_fname_dst,
7692 status = NT_STATUS_NO_MEMORY;
7693 TALLOC_FREE(fname_dst_parent);
7694 TALLOC_FREE(orig_lcomp_path);
7695 TALLOC_FREE(orig_lcomp_stream);
7698 TALLOC_FREE(smb_fname_dst->stream_name);
7699 smb_fname_dst->stream_name = tmp;
7701 TALLOC_FREE(fname_dst_parent);
7702 TALLOC_FREE(orig_lcomp_path);
7703 TALLOC_FREE(orig_lcomp_stream);
7707 * If the src and dest names are identical - including case,
7708 * don't do the rename, just return success.
7711 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7712 strcsequal(fsp->fsp_name->stream_name,
7713 smb_fname_dst->stream_name)) {
7714 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7715 "- returning success\n",
7716 smb_fname_str_dbg(smb_fname_dst)));
7717 status = NT_STATUS_OK;
7721 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7722 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7724 /* Return the correct error code if both names aren't streams. */
7725 if (!old_is_stream && new_is_stream) {
7726 status = NT_STATUS_OBJECT_NAME_INVALID;
7730 if (old_is_stream && !new_is_stream) {
7731 status = NT_STATUS_INVALID_PARAMETER;
7735 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7737 if(!replace_if_exists && dst_exists) {
7738 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7739 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7740 smb_fname_str_dbg(smb_fname_dst)));
7741 status = NT_STATUS_OBJECT_NAME_COLLISION;
7746 * Drop the pathref fsp on the destination otherwise we trip upon in in
7747 * the below check for open files check.
7749 if (smb_fname_dst_in->fsp != NULL) {
7750 fd_close(smb_fname_dst_in->fsp);
7751 file_free(NULL, smb_fname_dst_in->fsp);
7752 SMB_ASSERT(smb_fname_dst_in->fsp == NULL);
7756 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7757 &smb_fname_dst->st);
7758 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7760 /* The file can be open when renaming a stream */
7761 if (dst_fsp && !new_is_stream) {
7762 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7763 status = NT_STATUS_ACCESS_DENIED;
7768 /* Ensure we have a valid stat struct for the source. */
7769 status = vfs_stat_fsp(fsp);
7770 if (!NT_STATUS_IS_OK(status)) {
7774 status = can_rename(conn, fsp, attrs);
7776 if (!NT_STATUS_IS_OK(status)) {
7777 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7778 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7779 smb_fname_str_dbg(smb_fname_dst)));
7780 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7781 status = NT_STATUS_ACCESS_DENIED;
7785 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7786 status = NT_STATUS_ACCESS_DENIED;
7790 /* Do we have rights to move into the destination ? */
7791 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7792 /* We're moving a directory. */
7793 access_mask = SEC_DIR_ADD_SUBDIR;
7797 * Get a pathref on the parent directory, so
7798 * we can call check_parent_access_fsp().
7800 status = parent_pathref(ctx,
7803 &parent_dir_fname_dst,
7804 &parent_dir_fname_dst_atname);
7805 if (!NT_STATUS_IS_OK(status)) {
7809 status = check_parent_access_fsp(parent_dir_fname_dst->fsp,
7811 if (!NT_STATUS_IS_OK(status)) {
7812 DBG_INFO("check_parent_access_fsp on "
7813 "dst %s returned %s\n",
7814 smb_fname_str_dbg(smb_fname_dst),
7819 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7822 * We have the file open ourselves, so not being able to get the
7823 * corresponding share mode lock is a fatal error.
7826 SMB_ASSERT(lck != NULL);
7828 ret = SMB_VFS_RENAMEAT(conn,
7834 uint32_t create_options = fh_get_private_options(fsp->fh);
7836 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7837 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7838 smb_fname_str_dbg(smb_fname_dst)));
7841 fsp->fsp_flags.is_directory,
7845 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7848 if (!fsp->fsp_flags.is_directory &&
7849 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7850 (lp_map_archive(SNUM(conn)) ||
7851 lp_store_dos_attributes(SNUM(conn))))
7854 * We must set the archive bit on the newly renamed
7857 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
7859 uint32_t old_dosmode;
7860 old_dosmode = fdos_mode(fsp);
7862 * We can use fsp->fsp_name here as it has
7863 * already been changed to the new name.
7865 SMB_ASSERT(fsp->fsp_name->fsp == fsp);
7866 file_set_dosmode(conn,
7868 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7875 * A rename acts as a new file create w.r.t. allowing an initial delete
7876 * on close, probably because in Windows there is a new handle to the
7877 * new file. If initial delete on close was requested but not
7878 * originally set, we need to set it here. This is probably not 100% correct,
7879 * but will work for the CIFSFS client which in non-posix mode
7880 * depends on these semantics. JRA.
7883 if (create_options & FILE_DELETE_ON_CLOSE) {
7884 status = can_set_delete_on_close(fsp, 0);
7886 if (NT_STATUS_IS_OK(status)) {
7887 /* Note that here we set the *initial* delete on close flag,
7888 * not the regular one. The magic gets handled in close. */
7889 fsp->fsp_flags.initial_delete_on_close = true;
7893 status = NT_STATUS_OK;
7899 if (errno == ENOTDIR || errno == EISDIR) {
7900 status = NT_STATUS_OBJECT_NAME_COLLISION;
7902 status = map_nt_error_from_unix(errno);
7905 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7906 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7907 smb_fname_str_dbg(smb_fname_dst)));
7910 TALLOC_FREE(smb_fname_dst);
7915 /****************************************************************************
7916 The guts of the rename command, split out so it may be called by the NT SMB
7918 ****************************************************************************/
7920 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7921 connection_struct *conn,
7922 struct smb_request *req,
7923 struct smb_filename *smb_fname_src,
7924 const char *src_original_lcomp,
7925 struct smb_filename *smb_fname_dst,
7926 const char *dst_original_lcomp,
7928 bool replace_if_exists,
7929 uint32_t access_mask)
7931 char *fname_src_dir = NULL;
7932 struct smb_filename *smb_fname_src_dir = NULL;
7933 char *fname_src_mask = NULL;
7935 NTSTATUS status = NT_STATUS_OK;
7936 struct smb_Dir *dir_hnd = NULL;
7937 const char *dname = NULL;
7938 char *talloced = NULL;
7940 int create_options = 0;
7941 struct smb2_create_blobs *posx = NULL;
7943 bool src_has_wild = false;
7944 bool dest_has_wild = false;
7947 * Split the old name into directory and last component
7948 * strings. Note that unix_convert may have stripped off a
7949 * leading ./ from both name and newname if the rename is
7950 * at the root of the share. We need to make sure either both
7951 * name and newname contain a / character or neither of them do
7952 * as this is checked in resolve_wildcards().
7955 /* Split up the directory from the filename/mask. */
7956 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7957 &fname_src_dir, &fname_src_mask);
7958 if (!NT_STATUS_IS_OK(status)) {
7959 status = NT_STATUS_NO_MEMORY;
7963 if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
7965 * Check the wildcard mask *before*
7966 * unmangling. As mangling is done
7967 * for names that can't be returned
7968 * to Windows the unmangled name may
7969 * contain Windows wildcard characters.
7971 if (src_original_lcomp != NULL) {
7972 src_has_wild = ms_has_wild(src_original_lcomp);
7974 dest_has_wild = ms_has_wild(dst_original_lcomp);
7978 * We should only check the mangled cache
7979 * here if unix_convert failed. This means
7980 * that the path in 'mask' doesn't exist
7981 * on the file system and so we need to look
7982 * for a possible mangle. This patch from
7983 * Tine Smukavec <valentin.smukavec@hermes.si>.
7986 if (!VALID_STAT(smb_fname_src->st) &&
7987 mangle_is_mangled(fname_src_mask, conn->params)) {
7988 char *new_mask = NULL;
7989 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7992 TALLOC_FREE(fname_src_mask);
7993 fname_src_mask = new_mask;
7997 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7998 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7999 if (!NT_STATUS_IS_OK(status)) {
8000 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8006 if (!src_has_wild) {
8010 * Only one file needs to be renamed. Append the mask back
8011 * onto the directory.
8013 TALLOC_FREE(smb_fname_src->base_name);
8014 if (ISDOT(fname_src_dir)) {
8015 /* Ensure we use canonical names on open. */
8016 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8020 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8025 if (!smb_fname_src->base_name) {
8026 status = NT_STATUS_NO_MEMORY;
8030 DEBUG(3, ("rename_internals: case_sensitive = %d, "
8031 "case_preserve = %d, short case preserve = %d, "
8032 "directory = %s, newname = %s, "
8033 "last_component_dest = %s\n",
8034 conn->case_sensitive, conn->case_preserve,
8035 conn->short_case_preserve,
8036 smb_fname_str_dbg(smb_fname_src),
8037 smb_fname_str_dbg(smb_fname_dst),
8038 dst_original_lcomp));
8040 /* The dest name still may have wildcards. */
8041 if (dest_has_wild) {
8042 char *fname_dst_mod = NULL;
8043 if (!resolve_wildcards(smb_fname_dst,
8044 smb_fname_src->base_name,
8045 smb_fname_dst->base_name,
8047 DEBUG(6, ("rename_internals: resolve_wildcards "
8049 smb_fname_src->base_name,
8050 smb_fname_dst->base_name));
8051 status = NT_STATUS_NO_MEMORY;
8054 TALLOC_FREE(smb_fname_dst->base_name);
8055 smb_fname_dst->base_name = fname_dst_mod;
8058 ZERO_STRUCT(smb_fname_src->st);
8060 rc = vfs_stat(conn, smb_fname_src);
8062 status = map_nt_error_from_unix_common(errno);
8066 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
8067 if (!NT_STATUS_IS_OK(status)) {
8068 if (!NT_STATUS_EQUAL(status,
8069 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8073 * Possible symlink src.
8075 if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
8078 if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) {
8083 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8084 create_options |= FILE_DIRECTORY_FILE;
8087 status = SMB_VFS_CREATE_FILE(
8090 smb_fname_src, /* fname */
8091 access_mask, /* access_mask */
8092 (FILE_SHARE_READ | /* share_access */
8094 FILE_OPEN, /* create_disposition*/
8095 create_options, /* create_options */
8096 0, /* file_attributes */
8097 0, /* oplock_request */
8099 0, /* allocation_size */
8100 0, /* private_flags */
8105 posx, /* in_context_blobs */
8106 NULL); /* out_context_blobs */
8108 if (!NT_STATUS_IS_OK(status)) {
8109 DEBUG(3, ("Could not open rename source %s: %s\n",
8110 smb_fname_str_dbg(smb_fname_src),
8111 nt_errstr(status)));
8115 status = rename_internals_fsp(conn,
8122 close_file(req, fsp, NORMAL_CLOSE);
8124 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8125 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8126 smb_fname_str_dbg(smb_fname_dst)));
8132 * Wildcards - process each file that matches.
8134 if (strequal(fname_src_mask, "????????.???")) {
8135 TALLOC_FREE(fname_src_mask);
8136 fname_src_mask = talloc_strdup(ctx, "*");
8137 if (!fname_src_mask) {
8138 status = NT_STATUS_NO_MEMORY;
8143 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8147 smb_fname_src->twrp,
8148 smb_fname_src->flags);
8149 if (smb_fname_src_dir == NULL) {
8150 status = NT_STATUS_NO_MEMORY;
8154 status = check_name(conn, smb_fname_src_dir);
8155 if (!NT_STATUS_IS_OK(status)) {
8159 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8161 if (dir_hnd == NULL) {
8162 status = map_nt_error_from_unix(errno);
8166 status = NT_STATUS_NO_SUCH_FILE;
8168 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8169 * - gentest fix. JRA
8172 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8174 files_struct *fsp = NULL;
8175 char *destname = NULL;
8176 bool sysdir_entry = False;
8178 /* Quick check for "." and ".." */
8179 if (ISDOT(dname) || ISDOTDOT(dname)) {
8180 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8181 sysdir_entry = True;
8183 TALLOC_FREE(talloced);
8188 if (!is_visible_file(conn,
8193 TALLOC_FREE(talloced);
8197 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8198 TALLOC_FREE(talloced);
8203 status = NT_STATUS_OBJECT_NAME_INVALID;
8207 TALLOC_FREE(smb_fname_src->base_name);
8208 if (ISDOT(fname_src_dir)) {
8209 /* Ensure we use canonical names on open. */
8210 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8214 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8219 if (!smb_fname_src->base_name) {
8220 status = NT_STATUS_NO_MEMORY;
8224 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8225 smb_fname_dst->base_name,
8227 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8228 smb_fname_src->base_name, destname));
8229 TALLOC_FREE(talloced);
8233 status = NT_STATUS_NO_MEMORY;
8237 TALLOC_FREE(smb_fname_dst->base_name);
8238 smb_fname_dst->base_name = destname;
8240 ZERO_STRUCT(smb_fname_src->st);
8241 vfs_stat(conn, smb_fname_src);
8243 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
8244 if (!NT_STATUS_IS_OK(status)) {
8245 DBG_INFO("openat_pathref_fsp [%s] failed: %s\n",
8246 smb_fname_str_dbg(smb_fname_src),
8253 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8254 create_options |= FILE_DIRECTORY_FILE;
8257 status = SMB_VFS_CREATE_FILE(
8260 smb_fname_src, /* fname */
8261 access_mask, /* access_mask */
8262 (FILE_SHARE_READ | /* share_access */
8264 FILE_OPEN, /* create_disposition*/
8265 create_options, /* create_options */
8266 0, /* file_attributes */
8267 0, /* oplock_request */
8269 0, /* allocation_size */
8270 0, /* private_flags */
8275 posx, /* in_context_blobs */
8276 NULL); /* out_context_blobs */
8278 if (!NT_STATUS_IS_OK(status)) {
8279 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8280 "returned %s rename %s -> %s\n",
8282 smb_fname_str_dbg(smb_fname_src),
8283 smb_fname_str_dbg(smb_fname_dst)));
8287 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8288 if (dst_original_lcomp == NULL) {
8289 status = NT_STATUS_NO_MEMORY;
8293 status = rename_internals_fsp(conn,
8300 close_file(req, fsp, NORMAL_CLOSE);
8302 if (!NT_STATUS_IS_OK(status)) {
8303 DEBUG(3, ("rename_internals_fsp returned %s for "
8304 "rename %s -> %s\n", nt_errstr(status),
8305 smb_fname_str_dbg(smb_fname_src),
8306 smb_fname_str_dbg(smb_fname_dst)));
8312 DEBUG(3,("rename_internals: doing rename on %s -> "
8313 "%s\n", smb_fname_str_dbg(smb_fname_src),
8314 smb_fname_str_dbg(smb_fname_src)));
8315 TALLOC_FREE(talloced);
8317 TALLOC_FREE(dir_hnd);
8319 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8320 status = map_nt_error_from_unix(errno);
8325 TALLOC_FREE(talloced);
8326 TALLOC_FREE(smb_fname_src_dir);
8327 TALLOC_FREE(fname_src_dir);
8328 TALLOC_FREE(fname_src_mask);
8332 /****************************************************************************
8334 ****************************************************************************/
8336 void reply_mv(struct smb_request *req)
8338 connection_struct *conn = req->conn;
8340 char *newname = NULL;
8344 TALLOC_CTX *ctx = talloc_tos();
8345 struct smb_filename *smb_fname_src = NULL;
8346 const char *src_original_lcomp = NULL;
8347 struct smb_filename *smb_fname_dst = NULL;
8348 const char *dst_original_lcomp = NULL;
8349 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8350 (!req->posix_pathnames ? UCF_ALWAYS_ALLOW_WCARD_LCOMP : 0);
8351 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8352 (!req->posix_pathnames ? UCF_ALWAYS_ALLOW_WCARD_LCOMP : 0);
8353 bool stream_rename = false;
8355 START_PROFILE(SMBmv);
8358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8362 attrs = SVAL(req->vwv+0, 0);
8364 p = (const char *)req->buf + 1;
8365 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
8367 if (!NT_STATUS_IS_OK(status)) {
8368 reply_nterror(req, status);
8372 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
8374 if (!NT_STATUS_IS_OK(status)) {
8375 reply_nterror(req, status);
8379 if (!req->posix_pathnames) {
8380 /* The newname must begin with a ':' if the
8381 name contains a ':'. */
8382 if (strchr_m(name, ':')) {
8383 if (newname[0] != ':') {
8384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8387 stream_rename = true;
8391 status = filename_convert(ctx,
8398 if (!NT_STATUS_IS_OK(status)) {
8399 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8400 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8401 ERRSRV, ERRbadpath);
8404 reply_nterror(req, status);
8408 /* Get the last component of the source for rename_internals(). */
8409 src_original_lcomp = get_original_lcomp(ctx,
8413 if (src_original_lcomp == NULL) {
8414 reply_nterror(req, NT_STATUS_NO_MEMORY);
8418 status = filename_convert(ctx,
8425 if (!NT_STATUS_IS_OK(status)) {
8426 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8427 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8428 ERRSRV, ERRbadpath);
8431 reply_nterror(req, status);
8435 /* Get the last component of the destination for rename_internals(). */
8436 dst_original_lcomp = get_original_lcomp(ctx,
8440 if (dst_original_lcomp == NULL) {
8441 reply_nterror(req, NT_STATUS_NO_MEMORY);
8445 if (stream_rename) {
8446 /* smb_fname_dst->base_name must be the same as
8447 smb_fname_src->base_name. */
8448 TALLOC_FREE(smb_fname_dst->base_name);
8449 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8450 smb_fname_src->base_name);
8451 if (!smb_fname_dst->base_name) {
8452 reply_nterror(req, NT_STATUS_NO_MEMORY);
8457 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8458 smb_fname_str_dbg(smb_fname_dst)));
8460 status = rename_internals(ctx,
8470 if (!NT_STATUS_IS_OK(status)) {
8471 if (open_was_deferred(req->xconn, req->mid)) {
8472 /* We have re-scheduled this call. */
8475 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8476 bool ok = defer_smb1_sharing_violation(req);
8481 reply_nterror(req, status);
8485 reply_outbuf(req, 0, 0);
8487 TALLOC_FREE(smb_fname_src);
8488 TALLOC_FREE(smb_fname_dst);
8493 /*******************************************************************
8494 Copy a file as part of a reply_copy.
8495 ******************************************************************/
8498 * TODO: check error codes on all callers
8501 NTSTATUS copy_file(TALLOC_CTX *ctx,
8502 connection_struct *conn,
8503 struct smb_filename *smb_fname_src,
8504 struct smb_filename *smb_fname_dst,
8507 bool target_is_directory)
8509 struct smb_filename *smb_fname_dst_tmp = NULL;
8511 files_struct *fsp1,*fsp2;
8513 uint32_t new_create_disposition;
8517 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8518 if (smb_fname_dst_tmp == NULL) {
8519 return NT_STATUS_NO_MEMORY;
8523 * If the target is a directory, extract the last component from the
8524 * src filename and append it to the dst filename
8526 if (target_is_directory) {
8529 /* dest/target can't be a stream if it's a directory. */
8530 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8532 p = strrchr_m(smb_fname_src->base_name,'/');
8536 p = smb_fname_src->base_name;
8538 smb_fname_dst_tmp->base_name =
8539 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8541 if (!smb_fname_dst_tmp->base_name) {
8542 status = NT_STATUS_NO_MEMORY;
8547 status = vfs_file_exist(conn, smb_fname_src);
8548 if (!NT_STATUS_IS_OK(status)) {
8552 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
8553 if (!NT_STATUS_IS_OK(status)) {
8557 if (!target_is_directory && count) {
8558 new_create_disposition = FILE_OPEN;
8560 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8563 &new_create_disposition,
8566 status = NT_STATUS_INVALID_PARAMETER;
8571 /* Open the src file for reading. */
8572 status = SMB_VFS_CREATE_FILE(
8575 smb_fname_src, /* fname */
8576 FILE_GENERIC_READ, /* access_mask */
8577 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8578 FILE_OPEN, /* create_disposition*/
8579 0, /* create_options */
8580 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8581 INTERNAL_OPEN_ONLY, /* oplock_request */
8583 0, /* allocation_size */
8584 0, /* private_flags */
8589 NULL, NULL); /* create context */
8591 if (!NT_STATUS_IS_OK(status)) {
8595 dosattrs = fdos_mode(fsp1);
8597 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8598 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8601 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_dst);
8602 if (!NT_STATUS_IS_OK(status) &&
8603 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
8608 /* Open the dst file for writing. */
8609 status = SMB_VFS_CREATE_FILE(
8612 smb_fname_dst, /* fname */
8613 FILE_GENERIC_WRITE, /* access_mask */
8614 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8615 new_create_disposition, /* create_disposition*/
8616 0, /* create_options */
8617 dosattrs, /* file_attributes */
8618 INTERNAL_OPEN_ONLY, /* oplock_request */
8620 0, /* allocation_size */
8621 0, /* private_flags */
8626 NULL, NULL); /* create context */
8628 if (!NT_STATUS_IS_OK(status)) {
8629 close_file(NULL, fsp1, ERROR_CLOSE);
8633 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8634 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8636 DEBUG(0, ("error - vfs lseek returned error %s\n",
8638 status = map_nt_error_from_unix(errno);
8639 close_file(NULL, fsp1, ERROR_CLOSE);
8640 close_file(NULL, fsp2, ERROR_CLOSE);
8645 /* Do the actual copy. */
8646 if (smb_fname_src->st.st_ex_size) {
8647 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8652 close_file(NULL, fsp1, NORMAL_CLOSE);
8654 /* Ensure the modtime is set correctly on the destination file. */
8655 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8658 * As we are opening fsp1 read-only we only expect
8659 * an error on close on fsp2 if we are out of space.
8660 * Thus we don't look at the error return from the
8663 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8665 if (!NT_STATUS_IS_OK(status)) {
8669 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8670 status = NT_STATUS_DISK_FULL;
8674 status = NT_STATUS_OK;
8677 TALLOC_FREE(smb_fname_dst_tmp);
8681 /****************************************************************************
8682 Reply to a file copy.
8683 ****************************************************************************/
8685 void reply_copy(struct smb_request *req)
8687 connection_struct *conn = req->conn;
8688 struct smb_filename *smb_fname_src = NULL;
8689 struct smb_filename *smb_fname_src_dir = NULL;
8690 struct smb_filename *smb_fname_dst = NULL;
8691 char *fname_src = NULL;
8692 char *fname_dst = NULL;
8693 char *fname_src_mask = NULL;
8694 char *fname_src_dir = NULL;
8697 int error = ERRnoaccess;
8701 bool target_is_directory=False;
8702 bool source_has_wild = False;
8703 bool dest_has_wild = False;
8705 uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8706 ucf_flags_from_smb_request(req);
8707 uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8708 ucf_flags_from_smb_request(req);
8709 TALLOC_CTX *ctx = talloc_tos();
8711 START_PROFILE(SMBcopy);
8714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8718 tid2 = SVAL(req->vwv+0, 0);
8719 ofun = SVAL(req->vwv+1, 0);
8720 flags = SVAL(req->vwv+2, 0);
8722 p = (const char *)req->buf;
8723 p += srvstr_get_path_req(ctx, req, &fname_src, p, STR_TERMINATE,
8725 if (!NT_STATUS_IS_OK(status)) {
8726 reply_nterror(req, status);
8729 p += srvstr_get_path_req(ctx, req, &fname_dst, p, STR_TERMINATE,
8731 if (!NT_STATUS_IS_OK(status)) {
8732 reply_nterror(req, status);
8736 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8738 if (tid2 != conn->cnum) {
8739 /* can't currently handle inter share copies XXXX */
8740 DEBUG(3,("Rejecting inter-share copy\n"));
8741 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8745 status = filename_convert(ctx, conn,
8750 if (!NT_STATUS_IS_OK(status)) {
8751 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8752 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8753 ERRSRV, ERRbadpath);
8756 reply_nterror(req, status);
8760 status = filename_convert(ctx, conn,
8765 if (!NT_STATUS_IS_OK(status)) {
8766 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8767 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8768 ERRSRV, ERRbadpath);
8771 reply_nterror(req, status);
8775 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8777 if ((flags&1) && target_is_directory) {
8778 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8782 if ((flags&2) && !target_is_directory) {
8783 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8787 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8788 /* wants a tree copy! XXXX */
8789 DEBUG(3,("Rejecting tree copy\n"));
8790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8794 /* Split up the directory from the filename/mask. */
8795 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8796 &fname_src_dir, &fname_src_mask);
8797 if (!NT_STATUS_IS_OK(status)) {
8798 reply_nterror(req, NT_STATUS_NO_MEMORY);
8802 if (!req->posix_pathnames) {
8803 char *orig_src_lcomp = NULL;
8804 char *orig_dst_lcomp = NULL;
8806 * Check the wildcard mask *before*
8807 * unmangling. As mangling is done
8808 * for names that can't be returned
8809 * to Windows the unmangled name may
8810 * contain Windows wildcard characters.
8812 orig_src_lcomp = get_original_lcomp(ctx,
8816 if (orig_src_lcomp == NULL) {
8817 reply_nterror(req, NT_STATUS_NO_MEMORY);
8820 orig_dst_lcomp = get_original_lcomp(ctx,
8824 if (orig_dst_lcomp == NULL) {
8825 reply_nterror(req, NT_STATUS_NO_MEMORY);
8828 source_has_wild = ms_has_wild(orig_src_lcomp);
8829 dest_has_wild = ms_has_wild(orig_dst_lcomp);
8830 TALLOC_FREE(orig_src_lcomp);
8831 TALLOC_FREE(orig_dst_lcomp);
8835 * We should only check the mangled cache
8836 * here if unix_convert failed. This means
8837 * that the path in 'mask' doesn't exist
8838 * on the file system and so we need to look
8839 * for a possible mangle. This patch from
8840 * Tine Smukavec <valentin.smukavec@hermes.si>.
8842 if (!VALID_STAT(smb_fname_src->st) &&
8843 mangle_is_mangled(fname_src_mask, conn->params)) {
8844 char *new_mask = NULL;
8845 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8846 &new_mask, conn->params);
8848 /* Use demangled name if one was successfully found. */
8850 TALLOC_FREE(fname_src_mask);
8851 fname_src_mask = new_mask;
8855 if (!source_has_wild) {
8858 * Only one file needs to be copied. Append the mask back onto
8861 TALLOC_FREE(smb_fname_src->base_name);
8862 if (ISDOT(fname_src_dir)) {
8863 /* Ensure we use canonical names on open. */
8864 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8868 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8873 if (!smb_fname_src->base_name) {
8874 reply_nterror(req, NT_STATUS_NO_MEMORY);
8878 if (dest_has_wild) {
8879 char *fname_dst_mod = NULL;
8880 if (!resolve_wildcards(smb_fname_dst,
8881 smb_fname_src->base_name,
8882 smb_fname_dst->base_name,
8884 reply_nterror(req, NT_STATUS_NO_MEMORY);
8887 TALLOC_FREE(smb_fname_dst->base_name);
8888 smb_fname_dst->base_name = fname_dst_mod;
8891 status = check_name(conn, smb_fname_src);
8892 if (!NT_STATUS_IS_OK(status)) {
8893 reply_nterror(req, status);
8897 status = check_name(conn, smb_fname_dst);
8898 if (!NT_STATUS_IS_OK(status)) {
8899 reply_nterror(req, status);
8903 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8904 ofun, count, target_is_directory);
8906 if(!NT_STATUS_IS_OK(status)) {
8907 reply_nterror(req, status);
8913 struct smb_Dir *dir_hnd = NULL;
8914 const char *dname = NULL;
8915 char *talloced = NULL;
8919 * There is a wildcard that requires us to actually read the
8920 * src dir and copy each file matching the mask to the dst.
8921 * Right now streams won't be copied, but this could
8922 * presumably be added with a nested loop for reach dir entry.
8924 SMB_ASSERT(!smb_fname_src->stream_name);
8925 SMB_ASSERT(!smb_fname_dst->stream_name);
8927 smb_fname_src->stream_name = NULL;
8928 smb_fname_dst->stream_name = NULL;
8930 if (strequal(fname_src_mask,"????????.???")) {
8931 TALLOC_FREE(fname_src_mask);
8932 fname_src_mask = talloc_strdup(ctx, "*");
8933 if (!fname_src_mask) {
8934 reply_nterror(req, NT_STATUS_NO_MEMORY);
8939 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8943 smb_fname_src->twrp,
8944 smb_fname_src->flags);
8945 if (smb_fname_src_dir == NULL) {
8946 reply_nterror(req, NT_STATUS_NO_MEMORY);
8950 status = check_name(conn, smb_fname_src_dir);
8951 if (!NT_STATUS_IS_OK(status)) {
8952 reply_nterror(req, status);
8956 dir_hnd = OpenDir(ctx,
8961 if (dir_hnd == NULL) {
8962 status = map_nt_error_from_unix(errno);
8963 reply_nterror(req, status);
8969 /* Iterate over the src dir copying each entry to the dst. */
8970 while ((dname = ReadDirName(dir_hnd, &offset,
8971 &smb_fname_src->st, &talloced))) {
8972 char *destname = NULL;
8974 if (ISDOT(dname) || ISDOTDOT(dname)) {
8975 TALLOC_FREE(talloced);
8979 if (!is_visible_file(conn,
8984 TALLOC_FREE(talloced);
8988 if(!mask_match(dname, fname_src_mask,
8989 conn->case_sensitive)) {
8990 TALLOC_FREE(talloced);
8994 error = ERRnoaccess;
8996 /* Get the src smb_fname struct setup. */
8997 TALLOC_FREE(smb_fname_src->base_name);
8998 if (ISDOT(fname_src_dir)) {
8999 /* Ensure we use canonical names on open. */
9000 smb_fname_src->base_name =
9001 talloc_asprintf(smb_fname_src, "%s",
9004 smb_fname_src->base_name =
9005 talloc_asprintf(smb_fname_src, "%s/%s",
9006 fname_src_dir, dname);
9009 if (!smb_fname_src->base_name) {
9010 TALLOC_FREE(dir_hnd);
9011 TALLOC_FREE(talloced);
9012 reply_nterror(req, NT_STATUS_NO_MEMORY);
9016 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
9017 smb_fname_dst->base_name,
9019 TALLOC_FREE(talloced);
9023 TALLOC_FREE(dir_hnd);
9024 TALLOC_FREE(talloced);
9025 reply_nterror(req, NT_STATUS_NO_MEMORY);
9029 TALLOC_FREE(smb_fname_dst->base_name);
9030 smb_fname_dst->base_name = destname;
9032 status = check_name(conn, smb_fname_src);
9033 if (!NT_STATUS_IS_OK(status)) {
9034 TALLOC_FREE(dir_hnd);
9035 TALLOC_FREE(talloced);
9036 reply_nterror(req, status);
9040 status = check_name(conn, smb_fname_dst);
9041 if (!NT_STATUS_IS_OK(status)) {
9042 TALLOC_FREE(dir_hnd);
9043 TALLOC_FREE(talloced);
9044 reply_nterror(req, status);
9048 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
9049 smb_fname_src->base_name,
9050 smb_fname_dst->base_name));
9052 status = copy_file(ctx, conn, smb_fname_src,
9053 smb_fname_dst, ofun, count,
9054 target_is_directory);
9055 if (NT_STATUS_IS_OK(status)) {
9059 TALLOC_FREE(talloced);
9061 TALLOC_FREE(dir_hnd);
9065 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
9069 reply_outbuf(req, 1, 0);
9070 SSVAL(req->outbuf,smb_vwv0,count);
9072 TALLOC_FREE(smb_fname_src);
9073 TALLOC_FREE(smb_fname_src_dir);
9074 TALLOC_FREE(smb_fname_dst);
9075 TALLOC_FREE(fname_src);
9076 TALLOC_FREE(fname_dst);
9077 TALLOC_FREE(fname_src_mask);
9078 TALLOC_FREE(fname_src_dir);
9080 END_PROFILE(SMBcopy);
9085 #define DBGC_CLASS DBGC_LOCKING
9087 /****************************************************************************
9088 Get a lock pid, dealing with large count requests.
9089 ****************************************************************************/
9091 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
9092 bool large_file_format)
9094 if(!large_file_format)
9095 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9097 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9100 /****************************************************************************
9101 Get a lock count, dealing with large count requests.
9102 ****************************************************************************/
9104 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9105 bool large_file_format)
9109 if(!large_file_format) {
9110 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9113 * No BVAL, this is reversed!
9115 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9116 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9122 /****************************************************************************
9123 Get a lock offset, dealing with large offset requests.
9124 ****************************************************************************/
9126 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9127 bool large_file_format)
9129 uint64_t offset = 0;
9131 if(!large_file_format) {
9132 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9135 * No BVAL, this is reversed!
9137 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9138 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9144 struct smbd_do_unlocking_state {
9145 struct files_struct *fsp;
9146 uint16_t num_ulocks;
9147 struct smbd_lock_element *ulocks;
9148 enum brl_flavour lock_flav;
9152 static void smbd_do_unlocking_fn(
9155 bool *pmodified_dependent,
9158 struct smbd_do_unlocking_state *state = private_data;
9159 struct files_struct *fsp = state->fsp;
9160 enum brl_flavour lock_flav = state->lock_flav;
9163 for (i = 0; i < state->num_ulocks; i++) {
9164 struct smbd_lock_element *e = &state->ulocks[i];
9166 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9167 "pid %"PRIu64", file %s\n",
9173 if (e->brltype != UNLOCK_LOCK) {
9174 /* this can only happen with SMB2 */
9175 state->status = NT_STATUS_INVALID_PARAMETER;
9179 state->status = do_unlock(
9180 fsp, e->smblctx, e->count, e->offset, lock_flav);
9182 DBG_DEBUG("do_unlock returned %s\n",
9183 nt_errstr(state->status));
9185 if (!NT_STATUS_IS_OK(state->status)) {
9190 *pmodified_dependent = true;
9193 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9195 uint16_t num_ulocks,
9196 struct smbd_lock_element *ulocks,
9197 enum brl_flavour lock_flav)
9199 struct smbd_do_unlocking_state state = {
9201 .num_ulocks = num_ulocks,
9203 .lock_flav = lock_flav,
9207 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9209 status = share_mode_do_locked(
9210 fsp->file_id, smbd_do_unlocking_fn, &state);
9212 if (!NT_STATUS_IS_OK(status)) {
9213 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9217 if (!NT_STATUS_IS_OK(state.status)) {
9218 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9220 return state.status;
9223 return NT_STATUS_OK;
9226 /****************************************************************************
9227 Reply to a lockingX request.
9228 ****************************************************************************/
9230 static void reply_lockingx_done(struct tevent_req *subreq);
9232 void reply_lockingX(struct smb_request *req)
9234 connection_struct *conn = req->conn;
9236 unsigned char locktype;
9237 enum brl_type brltype;
9238 unsigned char oplocklevel;
9239 uint16_t num_ulocks;
9241 int32_t lock_timeout;
9243 const uint8_t *data;
9244 bool large_file_format;
9245 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9246 struct smbd_lock_element *locks = NULL;
9247 struct tevent_req *subreq = NULL;
9249 START_PROFILE(SMBlockingX);
9252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9253 END_PROFILE(SMBlockingX);
9257 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9258 locktype = CVAL(req->vwv+3, 0);
9259 oplocklevel = CVAL(req->vwv+3, 1);
9260 num_ulocks = SVAL(req->vwv+6, 0);
9261 num_locks = SVAL(req->vwv+7, 0);
9262 lock_timeout = IVAL(req->vwv+4, 0);
9263 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9265 if (!check_fsp(conn, req, fsp)) {
9266 END_PROFILE(SMBlockingX);
9272 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9273 /* we don't support these - and CANCEL_LOCK makes w2k
9274 and XP reboot so I don't really want to be
9275 compatible! (tridge) */
9276 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9277 END_PROFILE(SMBlockingX);
9281 /* Check if this is an oplock break on a file
9282 we have granted an oplock on.
9284 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9285 /* Client can insist on breaking to none. */
9286 bool break_to_none = (oplocklevel == 0);
9289 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9290 "for %s\n", (unsigned int)oplocklevel,
9291 fsp_fnum_dbg(fsp)));
9294 * Make sure we have granted an exclusive or batch oplock on
9298 if (fsp->oplock_type == 0) {
9300 /* The Samba4 nbench simulator doesn't understand
9301 the difference between break to level2 and break
9302 to none from level2 - it sends oplock break
9303 replies in both cases. Don't keep logging an error
9304 message here - just ignore it. JRA. */
9306 DEBUG(5,("reply_lockingX: Error : oplock break from "
9307 "client for %s (oplock=%d) and no "
9308 "oplock granted on this file (%s).\n",
9309 fsp_fnum_dbg(fsp), fsp->oplock_type,
9312 /* if this is a pure oplock break request then don't
9314 if (num_locks == 0 && num_ulocks == 0) {
9315 END_PROFILE(SMBlockingX);
9319 END_PROFILE(SMBlockingX);
9320 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9324 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9326 result = remove_oplock(fsp);
9328 result = downgrade_oplock(fsp);
9332 DEBUG(0, ("reply_lockingX: error in removing "
9333 "oplock on file %s\n", fsp_str_dbg(fsp)));
9334 /* Hmmm. Is this panic justified? */
9335 smb_panic("internal tdb error");
9338 /* if this is a pure oplock break request then don't send a
9340 if (num_locks == 0 && num_ulocks == 0) {
9341 /* Sanity check - ensure a pure oplock break is not a
9343 if (CVAL(req->vwv+0, 0) != 0xff) {
9344 DEBUG(0,("reply_lockingX: Error : pure oplock "
9345 "break is a chained %d request !\n",
9346 (unsigned int)CVAL(req->vwv+0, 0)));
9348 END_PROFILE(SMBlockingX);
9354 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9356 END_PROFILE(SMBlockingX);
9360 if (num_ulocks != 0) {
9361 struct smbd_lock_element *ulocks = NULL;
9364 ulocks = talloc_array(
9365 req, struct smbd_lock_element, num_ulocks);
9366 if (ulocks == NULL) {
9367 reply_nterror(req, NT_STATUS_NO_MEMORY);
9368 END_PROFILE(SMBlockingX);
9373 * Data now points at the beginning of the list of
9374 * smb_unlkrng structs
9376 for (i = 0; i < num_ulocks; i++) {
9377 ulocks[i].req_guid = smbd_request_guid(req,
9379 ulocks[i].smblctx = get_lock_pid(
9380 data, i, large_file_format);
9381 ulocks[i].count = get_lock_count(
9382 data, i, large_file_format);
9383 ulocks[i].offset = get_lock_offset(
9384 data, i, large_file_format);
9385 ulocks[i].brltype = UNLOCK_LOCK;
9389 * Unlock cancels pending locks
9392 ok = smbd_smb1_brl_finish_by_lock(
9399 reply_outbuf(req, 2, 0);
9400 SSVAL(req->outbuf, smb_vwv0, 0xff);
9401 SSVAL(req->outbuf, smb_vwv1, 0);
9402 END_PROFILE(SMBlockingX);
9406 status = smbd_do_unlocking(
9407 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9408 TALLOC_FREE(ulocks);
9409 if (!NT_STATUS_IS_OK(status)) {
9410 END_PROFILE(SMBlockingX);
9411 reply_nterror(req, status);
9416 /* Now do any requested locks */
9417 data += ((large_file_format ? 20 : 10)*num_ulocks);
9419 /* Data now points at the beginning of the list
9420 of smb_lkrng structs */
9422 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9423 brltype = READ_LOCK;
9425 brltype = WRITE_LOCK;
9428 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9429 if (locks == NULL) {
9430 reply_nterror(req, NT_STATUS_NO_MEMORY);
9431 END_PROFILE(SMBlockingX);
9435 for (i = 0; i < num_locks; i++) {
9436 locks[i].req_guid = smbd_request_guid(req, i),
9437 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9438 locks[i].count = get_lock_count(data, i, large_file_format);
9439 locks[i].offset = get_lock_offset(data, i, large_file_format);
9440 locks[i].brltype = brltype;
9443 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9447 if (num_locks == 0) {
9448 /* See smbtorture3 lock11 test */
9449 reply_outbuf(req, 2, 0);
9450 /* andx chain ends */
9451 SSVAL(req->outbuf, smb_vwv0, 0xff);
9452 SSVAL(req->outbuf, smb_vwv1, 0);
9453 END_PROFILE(SMBlockingX);
9457 ok = smbd_smb1_brl_finish_by_lock(
9461 locks[0], /* Windows only cancels the first lock */
9462 NT_STATUS_FILE_LOCK_CONFLICT);
9465 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9466 END_PROFILE(SMBlockingX);
9470 reply_outbuf(req, 2, 0);
9471 SSVAL(req->outbuf, smb_vwv0, 0xff);
9472 SSVAL(req->outbuf, smb_vwv1, 0);
9473 END_PROFILE(SMBlockingX);
9477 subreq = smbd_smb1_do_locks_send(
9487 if (subreq == NULL) {
9488 reply_nterror(req, NT_STATUS_NO_MEMORY);
9489 END_PROFILE(SMBlockingX);
9492 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9493 END_PROFILE(SMBlockingX);
9496 static void reply_lockingx_done(struct tevent_req *subreq)
9498 struct smb_request *req = NULL;
9502 START_PROFILE(SMBlockingX);
9504 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9507 status = smbd_smb1_do_locks_recv(subreq);
9508 TALLOC_FREE(subreq);
9510 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9512 if (NT_STATUS_IS_OK(status)) {
9513 reply_outbuf(req, 2, 0);
9514 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9515 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9517 reply_nterror(req, status);
9520 ok = srv_send_smb(req->xconn,
9521 (char *)req->outbuf,
9524 IS_CONN_ENCRYPTED(req->conn),
9527 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9530 END_PROFILE(SMBlockingX);
9534 #define DBGC_CLASS DBGC_ALL
9536 /****************************************************************************
9537 Reply to a SMBreadbmpx (read block multiplex) request.
9538 Always reply with an error, if someone has a platform really needs this,
9539 please contact vl@samba.org
9540 ****************************************************************************/
9542 void reply_readbmpx(struct smb_request *req)
9544 START_PROFILE(SMBreadBmpx);
9545 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9546 END_PROFILE(SMBreadBmpx);
9550 /****************************************************************************
9551 Reply to a SMBreadbs (read block multiplex secondary) request.
9552 Always reply with an error, if someone has a platform really needs this,
9553 please contact vl@samba.org
9554 ****************************************************************************/
9556 void reply_readbs(struct smb_request *req)
9558 START_PROFILE(SMBreadBs);
9559 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9560 END_PROFILE(SMBreadBs);
9564 /****************************************************************************
9565 Reply to a SMBsetattrE.
9566 ****************************************************************************/
9568 void reply_setattrE(struct smb_request *req)
9570 connection_struct *conn = req->conn;
9571 struct smb_file_time ft;
9575 START_PROFILE(SMBsetattrE);
9576 init_smb_file_time(&ft);
9579 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9583 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9585 if(!fsp || (fsp->conn != conn)) {
9586 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9591 * Convert the DOS times into unix times.
9594 ft.atime = time_t_to_full_timespec(
9595 srv_make_unix_date2(req->vwv+3));
9596 ft.mtime = time_t_to_full_timespec(
9597 srv_make_unix_date2(req->vwv+5));
9598 ft.create_time = time_t_to_full_timespec(
9599 srv_make_unix_date2(req->vwv+1));
9601 reply_outbuf(req, 0, 0);
9604 * Patch from Ray Frush <frush@engr.colostate.edu>
9605 * Sometimes times are sent as zero - ignore them.
9608 /* Ensure we have a valid stat struct for the source. */
9609 status = vfs_stat_fsp(fsp);
9610 if (!NT_STATUS_IS_OK(status)) {
9611 reply_nterror(req, status);
9615 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9616 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9620 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9621 if (!NT_STATUS_IS_OK(status)) {
9622 reply_nterror(req, status);
9626 if (fsp->fsp_flags.modified) {
9627 trigger_write_time_update_immediate(fsp);
9630 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9633 (unsigned int)ft.atime.tv_sec,
9634 (unsigned int)ft.mtime.tv_sec,
9635 (unsigned int)ft.create_time.tv_sec
9638 END_PROFILE(SMBsetattrE);
9643 /* Back from the dead for OS/2..... JRA. */
9645 /****************************************************************************
9646 Reply to a SMBwritebmpx (write block multiplex primary) request.
9647 Always reply with an error, if someone has a platform really needs this,
9648 please contact vl@samba.org
9649 ****************************************************************************/
9651 void reply_writebmpx(struct smb_request *req)
9653 START_PROFILE(SMBwriteBmpx);
9654 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9655 END_PROFILE(SMBwriteBmpx);
9659 /****************************************************************************
9660 Reply to a SMBwritebs (write block multiplex secondary) request.
9661 Always reply with an error, if someone has a platform really needs this,
9662 please contact vl@samba.org
9663 ****************************************************************************/
9665 void reply_writebs(struct smb_request *req)
9667 START_PROFILE(SMBwriteBs);
9668 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9669 END_PROFILE(SMBwriteBs);
9673 /****************************************************************************
9674 Reply to a SMBgetattrE.
9675 ****************************************************************************/
9677 void reply_getattrE(struct smb_request *req)
9679 connection_struct *conn = req->conn;
9682 struct timespec create_ts;
9685 START_PROFILE(SMBgetattrE);
9688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9689 END_PROFILE(SMBgetattrE);
9693 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9695 if(!fsp || (fsp->conn != conn)) {
9696 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9697 END_PROFILE(SMBgetattrE);
9701 /* Do an fstat on this file */
9702 status = vfs_stat_fsp(fsp);
9703 if (!NT_STATUS_IS_OK(status)) {
9704 reply_nterror(req, status);
9705 END_PROFILE(SMBgetattrE);
9709 mode = fdos_mode(fsp);
9712 * Convert the times into dos times. Set create
9713 * date to be last modify date as UNIX doesn't save
9717 reply_outbuf(req, 11, 0);
9719 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9720 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9721 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9722 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9723 /* Should we check pending modtime here ? JRA */
9724 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9725 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9727 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9728 SIVAL(req->outbuf, smb_vwv6, 0);
9729 SIVAL(req->outbuf, smb_vwv8, 0);
9731 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9732 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9733 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9735 SSVAL(req->outbuf,smb_vwv10, mode);
9737 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9739 END_PROFILE(SMBgetattrE);