2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/util/tevent_ntstatus.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "librpc/gen_ndr/open_files.h"
48 #include "smb1_utils.h"
49 #include "libcli/smb/smb2_posix.h"
50 #include "lib/util/string_wrappers.h"
52 /****************************************************************************
53 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
54 path or anything including wildcards.
55 We're assuming here that '/' is not the second byte in any multibyte char
56 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
58 ****************************************************************************/
60 /* Custom version for processing POSIX paths. */
61 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
63 static NTSTATUS check_path_syntax_internal(char *path,
65 bool *p_last_component_contains_wcard)
69 NTSTATUS ret = NT_STATUS_OK;
70 bool start_of_name_component = True;
71 bool stream_started = false;
73 *p_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 (*p_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 *p_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 *p_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)
232 return check_path_syntax_internal(path, False, &ignore);
235 /****************************************************************************
236 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
237 Wildcards allowed - p_contains_wcard returns true if the last component contained
239 ****************************************************************************/
241 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
243 return check_path_syntax_internal(path, False, p_contains_wcard);
246 /****************************************************************************
247 Check the path for a POSIX client.
248 We're assuming here that '/' is not the second byte in any multibyte char
249 set (a safe assumption).
250 ****************************************************************************/
252 NTSTATUS check_path_syntax_posix(char *path)
255 return check_path_syntax_internal(path, True, &ignore);
258 /****************************************************************************
259 Pull a string and check the path allowing a wildcard - provide for error return.
260 Passes in posix flag.
261 ****************************************************************************/
263 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
264 const char *base_ptr,
270 bool posix_pathnames,
278 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
282 *err = NT_STATUS_INVALID_PARAMETER;
286 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
288 * For a DFS path the function parse_dfs_path()
289 * will do the path processing, just make a copy.
295 if (posix_pathnames) {
296 *err = check_path_syntax_posix(*pp_dest);
298 *err = check_path_syntax_wcard(*pp_dest, &ignore);
304 /****************************************************************************
305 Pull a string and check the path - provide for error return.
306 ****************************************************************************/
308 size_t srvstr_get_path(TALLOC_CTX *ctx,
309 const char *base_ptr,
317 return srvstr_get_path_wcard_internal(ctx,
328 /****************************************************************************
329 Pull a string and check the path - provide for error return.
330 posix_pathnames version.
331 ****************************************************************************/
333 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
334 const char *base_ptr,
342 return srvstr_get_path_wcard_internal(ctx,
354 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
355 char **pp_dest, const char *src, int flags,
358 ssize_t bufrem = smbreq_bufrem(req, src);
361 *err = NT_STATUS_INVALID_PARAMETER;
365 if (req->posix_pathnames) {
366 return srvstr_get_path_wcard_internal(mem_ctx,
367 (const char *)req->inbuf,
376 return srvstr_get_path_wcard_internal(mem_ctx,
377 (const char *)req->inbuf,
389 * pull a string from the smb_buf part of a packet. In this case the
390 * string can either be null terminated or it can be terminated by the
391 * end of the smbbuf area
393 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
394 char **dest, const uint8_t *src, int flags)
396 ssize_t bufrem = smbreq_bufrem(req, src);
402 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
406 /****************************************************************************
407 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
408 ****************************************************************************/
410 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
413 if ((fsp == NULL) || (conn == NULL)) {
414 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
417 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
418 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
424 /****************************************************************************
425 Check if we have a correct fsp pointing to a file.
426 ****************************************************************************/
428 bool check_fsp(connection_struct *conn, struct smb_request *req,
431 if (!check_fsp_open(conn, req, fsp)) {
434 if (fsp->fsp_flags.is_directory) {
435 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
438 if (fsp->fh->fd == -1) {
439 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
442 fsp->num_smb_operations++;
446 /****************************************************************************
447 Check if we have a correct fsp pointing to a quota fake file. Replacement for
448 the CHECK_NTQUOTA_HANDLE_OK macro.
449 ****************************************************************************/
451 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
454 if (!check_fsp_open(conn, req, fsp)) {
458 if (fsp->fsp_flags.is_directory) {
462 if (fsp->fake_file_handle == NULL) {
466 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
470 if (fsp->fake_file_handle->private_data == NULL) {
477 /****************************************************************************
478 Return the port number we've bound to on a socket.
479 ****************************************************************************/
481 static int get_socket_port(int fd)
483 struct samba_sockaddr saddr = {
484 .sa_socklen = sizeof(struct sockaddr_storage),
491 if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
492 int level = (errno == ENOTCONN) ? 2 : 0;
493 DEBUG(level, ("getsockname failed. Error was %s\n",
498 #if defined(HAVE_IPV6)
499 if (saddr.u.sa.sa_family == AF_INET6) {
500 return ntohs(saddr.u.in6.sin6_port);
503 if (saddr.u.sa.sa_family == AF_INET) {
504 return ntohs(saddr.u.in.sin_port);
509 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
510 const char *name, int name_type)
513 char *trim_name_type;
514 const char *retarget_parm;
517 int retarget_type = 0x20;
518 int retarget_port = NBT_SMB_PORT;
519 struct sockaddr_storage retarget_addr;
520 struct sockaddr_in *in_addr;
524 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
528 trim_name = talloc_strdup(talloc_tos(), name);
529 if (trim_name == NULL) {
532 trim_char(trim_name, ' ', ' ');
534 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
536 if (trim_name_type == NULL) {
540 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
541 trim_name_type, NULL);
542 if (retarget_parm == NULL) {
543 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
546 if (retarget_parm == NULL) {
550 retarget = talloc_strdup(trim_name, retarget_parm);
551 if (retarget == NULL) {
555 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
557 p = strchr(retarget, ':');
560 retarget_port = atoi(p);
563 p = strchr_m(retarget, '#');
566 if (sscanf(p, "%x", &retarget_type) != 1) {
571 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
573 DEBUG(10, ("could not resolve %s\n", retarget));
577 if (retarget_addr.ss_family != AF_INET) {
578 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
582 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
584 _smb_setlen(outbuf, 6);
585 SCVAL(outbuf, 0, 0x84);
586 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
587 *(uint16_t *)(outbuf+8) = htons(retarget_port);
589 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
591 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
597 TALLOC_FREE(trim_name);
601 static void reply_called_name_not_present(char *outbuf)
603 smb_setlen(outbuf, 1);
604 SCVAL(outbuf, 0, 0x83);
605 SCVAL(outbuf, 4, 0x82);
608 /****************************************************************************
609 Reply to a (netbios-level) special message.
610 ****************************************************************************/
612 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
614 struct smbd_server_connection *sconn = xconn->client->sconn;
615 int msg_type = CVAL(inbuf,0);
616 int msg_flags = CVAL(inbuf,1);
618 * We only really use 4 bytes of the outbuf, but for the smb_setlen
619 * calculation & friends (srv_send_smb uses that) we need the full smb
622 char outbuf[smb_size];
624 memset(outbuf, '\0', sizeof(outbuf));
626 smb_setlen(outbuf,0);
629 case NBSSrequest: /* session request */
631 /* inbuf_size is guarenteed to be at least 4. */
633 int name_type1, name_type2;
634 int name_len1, name_len2;
638 if (xconn->transport.nbt.got_session) {
639 exit_server_cleanly("multiple session request not permitted");
642 SCVAL(outbuf,0,NBSSpositive);
645 /* inbuf_size is guaranteed to be at least 4. */
646 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
647 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
648 DEBUG(0,("Invalid name length in session request\n"));
649 reply_called_name_not_present(outbuf);
652 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
653 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
654 DEBUG(0,("Invalid name length in session request\n"));
655 reply_called_name_not_present(outbuf);
659 name_type1 = name_extract((unsigned char *)inbuf,
660 inbuf_size,(unsigned int)4,name1);
661 name_type2 = name_extract((unsigned char *)inbuf,
662 inbuf_size,(unsigned int)(4 + name_len1),name2);
664 if (name_type1 == -1 || name_type2 == -1) {
665 DEBUG(0,("Invalid name type in session request\n"));
666 reply_called_name_not_present(outbuf);
670 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
671 name1, name_type1, name2, name_type2));
673 if (netbios_session_retarget(xconn, name1, name_type1)) {
674 exit_server_cleanly("retargeted client");
678 * Windows NT/2k uses "*SMBSERVER" and XP uses
679 * "*SMBSERV" arrggg!!!
681 if (strequal(name1, "*SMBSERVER ")
682 || strequal(name1, "*SMBSERV ")) {
685 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
688 exit_server_cleanly("could not allocate raddr");
691 fstrcpy(name1, raddr);
694 set_local_machine_name(name1, True);
695 set_remote_machine_name(name2, True);
697 if (is_ipaddress(sconn->remote_hostname)) {
698 char *p = discard_const_p(char, sconn->remote_hostname);
702 sconn->remote_hostname = talloc_strdup(sconn,
703 get_remote_machine_name());
704 if (sconn->remote_hostname == NULL) {
705 exit_server_cleanly("could not copy remote name");
707 xconn->remote_hostname = sconn->remote_hostname;
710 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
711 get_local_machine_name(), get_remote_machine_name(),
714 if (name_type2 == 'R') {
715 /* We are being asked for a pathworks session ---
717 reply_called_name_not_present(outbuf);
721 reload_services(sconn, conn_snum_used, true);
724 xconn->transport.nbt.got_session = true;
728 case 0x89: /* session keepalive request
729 (some old clients produce this?) */
730 SCVAL(outbuf,0,NBSSkeepalive);
734 case NBSSpositive: /* positive session response */
735 case NBSSnegative: /* negative session response */
736 case NBSSretarget: /* retarget session response */
737 DEBUG(0,("Unexpected session response\n"));
740 case NBSSkeepalive: /* session keepalive */
745 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
746 msg_type, msg_flags));
748 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
749 exit_server_cleanly("reply_special: srv_send_smb failed.");
752 if (CVAL(outbuf, 0) != 0x82) {
753 exit_server_cleanly("invalid netbios session");
758 /****************************************************************************
760 conn POINTER CAN BE NULL HERE !
761 ****************************************************************************/
763 void reply_tcon(struct smb_request *req)
765 connection_struct *conn = req->conn;
767 char *service_buf = NULL;
768 char *password = NULL;
774 TALLOC_CTX *ctx = talloc_tos();
775 struct smbXsrv_connection *xconn = req->xconn;
776 NTTIME now = timeval_to_nttime(&req->request_time);
778 START_PROFILE(SMBtcon);
780 if (req->buflen < 4) {
781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
782 END_PROFILE(SMBtcon);
787 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
789 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
791 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
794 if (service_buf == NULL || password == NULL || dev == NULL) {
795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
796 END_PROFILE(SMBtcon);
799 p2 = strrchr_m(service_buf,'\\');
803 service = service_buf;
806 conn = make_connection(req, now, service, dev,
807 req->vuid,&nt_status);
811 reply_nterror(req, nt_status);
812 END_PROFILE(SMBtcon);
816 reply_outbuf(req, 2, 0);
817 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
818 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
819 SSVAL(req->outbuf,smb_tid,conn->cnum);
821 DEBUG(3,("tcon service=%s cnum=%d\n",
822 service, conn->cnum));
824 END_PROFILE(SMBtcon);
828 /****************************************************************************
829 Reply to a tcon and X.
830 conn POINTER CAN BE NULL HERE !
831 ****************************************************************************/
833 void reply_tcon_and_X(struct smb_request *req)
835 const struct loadparm_substitution *lp_sub =
836 loadparm_s3_global_substitution();
837 connection_struct *conn = req->conn;
838 const char *service = NULL;
839 TALLOC_CTX *ctx = talloc_tos();
840 /* what the client thinks the device is */
841 char *client_devicetype = NULL;
842 /* what the server tells the client the share represents */
843 const char *server_devicetype;
850 struct smbXsrv_session *session = NULL;
851 NTTIME now = timeval_to_nttime(&req->request_time);
852 bool session_key_updated = false;
853 uint16_t optional_support = 0;
854 struct smbXsrv_connection *xconn = req->xconn;
856 START_PROFILE(SMBtconX);
859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
860 END_PROFILE(SMBtconX);
864 passlen = SVAL(req->vwv+3, 0);
865 tcon_flags = SVAL(req->vwv+2, 0);
867 /* we might have to close an old one */
868 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
869 struct smbXsrv_tcon *tcon;
877 * TODO: cancel all outstanding requests on the tcon
879 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
880 if (!NT_STATUS_IS_OK(status)) {
881 DEBUG(0, ("reply_tcon_and_X: "
882 "smbXsrv_tcon_disconnect() failed: %s\n",
885 * If we hit this case, there is something completely
886 * wrong, so we better disconnect the transport connection.
888 END_PROFILE(SMBtconX);
889 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
895 * This tree id is gone. Make sure we can't re-use it
901 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
902 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
903 END_PROFILE(SMBtconX);
907 if (xconn->smb1.negprot.encrypted_passwords) {
908 p = req->buf + passlen;
910 p = req->buf + passlen + 1;
913 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
917 END_PROFILE(SMBtconX);
922 * the service name can be either: \\server\share
923 * or share directly like on the DELL PowerVault 705
926 q = strchr_m(path+2,'\\');
928 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
929 END_PROFILE(SMBtconX);
937 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
938 &client_devicetype, p,
939 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
941 if (client_devicetype == NULL) {
942 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
943 END_PROFILE(SMBtconX);
947 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
949 nt_status = smb1srv_session_lookup(xconn,
950 req->vuid, now, &session);
951 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
952 reply_force_doserror(req, ERRSRV, ERRbaduid);
953 END_PROFILE(SMBtconX);
956 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
957 reply_nterror(req, nt_status);
958 END_PROFILE(SMBtconX);
961 if (!NT_STATUS_IS_OK(nt_status)) {
962 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
963 END_PROFILE(SMBtconX);
967 if (session->global->auth_session_info == NULL) {
968 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
969 END_PROFILE(SMBtconX);
974 * If there is no application key defined yet
977 * This means we setup the application key on the
978 * first tcon that happens via the given session.
980 * Once the application key is defined, it does not
983 if (session->global->application_key.length == 0 &&
984 smb2_signing_key_valid(session->global->signing_key))
986 struct smbXsrv_session *x = session;
987 struct auth_session_info *session_info =
988 session->global->auth_session_info;
989 uint8_t session_key[16];
991 ZERO_STRUCT(session_key);
992 memcpy(session_key, x->global->signing_key->blob.data,
993 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
996 * The application key is truncated/padded to 16 bytes
998 x->global->application_key = data_blob_talloc(x->global,
1000 sizeof(session_key));
1001 ZERO_STRUCT(session_key);
1002 if (x->global->application_key.data == NULL) {
1003 reply_nterror(req, NT_STATUS_NO_MEMORY);
1004 END_PROFILE(SMBtconX);
1008 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1011 status = smb_key_derivation(x->global->application_key.data,
1012 x->global->application_key.length,
1013 x->global->application_key.data);
1014 if (!NT_STATUS_IS_OK(status)) {
1015 DBG_ERR("smb_key_derivation failed: %s\n",
1017 END_PROFILE(SMBtconX);
1020 optional_support |= SMB_EXTENDED_SIGNATURES;
1024 * Place the application key into the session_info
1026 data_blob_clear_free(&session_info->session_key);
1027 session_info->session_key = data_blob_dup_talloc(session_info,
1028 x->global->application_key);
1029 if (session_info->session_key.data == NULL) {
1030 data_blob_clear_free(&x->global->application_key);
1031 reply_nterror(req, NT_STATUS_NO_MEMORY);
1032 END_PROFILE(SMBtconX);
1035 session_key_updated = true;
1038 conn = make_connection(req, now, service, client_devicetype,
1039 req->vuid, &nt_status);
1043 if (session_key_updated) {
1044 struct smbXsrv_session *x = session;
1045 struct auth_session_info *session_info =
1046 session->global->auth_session_info;
1047 data_blob_clear_free(&x->global->application_key);
1048 data_blob_clear_free(&session_info->session_key);
1050 reply_nterror(req, nt_status);
1051 END_PROFILE(SMBtconX);
1056 server_devicetype = "IPC";
1057 else if ( IS_PRINT(conn) )
1058 server_devicetype = "LPT1:";
1060 server_devicetype = "A:";
1062 if (get_Protocol() < PROTOCOL_NT1) {
1063 reply_outbuf(req, 2, 0);
1064 if (message_push_string(&req->outbuf, server_devicetype,
1065 STR_TERMINATE|STR_ASCII) == -1) {
1066 reply_nterror(req, NT_STATUS_NO_MEMORY);
1067 END_PROFILE(SMBtconX);
1071 /* NT sets the fstype of IPC$ to the null string */
1072 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1074 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1075 /* Return permissions. */
1079 reply_outbuf(req, 7, 0);
1082 perm1 = FILE_ALL_ACCESS;
1083 perm2 = FILE_ALL_ACCESS;
1085 perm1 = conn->share_access;
1088 SIVAL(req->outbuf, smb_vwv3, perm1);
1089 SIVAL(req->outbuf, smb_vwv5, perm2);
1091 reply_outbuf(req, 3, 0);
1094 if ((message_push_string(&req->outbuf, server_devicetype,
1095 STR_TERMINATE|STR_ASCII) == -1)
1096 || (message_push_string(&req->outbuf, fstype,
1097 STR_TERMINATE) == -1)) {
1098 reply_nterror(req, NT_STATUS_NO_MEMORY);
1099 END_PROFILE(SMBtconX);
1103 /* what does setting this bit do? It is set by NT4 and
1104 may affect the ability to autorun mounted cdroms */
1105 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1107 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1109 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1110 DEBUG(2,("Serving %s as a Dfs root\n",
1111 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1112 optional_support |= SMB_SHARE_IN_DFS;
1115 SSVAL(req->outbuf, smb_vwv2, optional_support);
1118 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1119 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1121 DEBUG(3,("tconX service=%s \n",
1124 /* set the incoming and outgoing tid to the just created one */
1125 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1126 SSVAL(req->outbuf,smb_tid,conn->cnum);
1128 END_PROFILE(SMBtconX);
1130 req->tid = conn->cnum;
1133 /****************************************************************************
1134 Reply to an unknown type.
1135 ****************************************************************************/
1137 void reply_unknown_new(struct smb_request *req, uint8_t type)
1139 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1140 smb_fn_name(type), type, type));
1141 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1145 /****************************************************************************
1147 conn POINTER CAN BE NULL HERE !
1148 ****************************************************************************/
1150 void reply_ioctl(struct smb_request *req)
1152 const struct loadparm_substitution *lp_sub =
1153 loadparm_s3_global_substitution();
1154 connection_struct *conn = req->conn;
1157 uint32_t ioctl_code;
1161 START_PROFILE(SMBioctl);
1164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1165 END_PROFILE(SMBioctl);
1169 device = SVAL(req->vwv+1, 0);
1170 function = SVAL(req->vwv+2, 0);
1171 ioctl_code = (device << 16) + function;
1173 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1175 switch (ioctl_code) {
1176 case IOCTL_QUERY_JOB_INFO:
1180 reply_force_doserror(req, ERRSRV, ERRnosupport);
1181 END_PROFILE(SMBioctl);
1185 reply_outbuf(req, 8, replysize+1);
1186 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1187 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1188 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1189 p = smb_buf(req->outbuf);
1190 memset(p, '\0', replysize+1); /* valgrind-safe. */
1191 p += 1; /* Allow for alignment */
1193 switch (ioctl_code) {
1194 case IOCTL_QUERY_JOB_INFO:
1198 files_struct *fsp = file_fsp(
1199 req, SVAL(req->vwv+0, 0));
1201 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1202 END_PROFILE(SMBioctl);
1206 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1208 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1209 lp_netbios_name(), 15,
1210 STR_TERMINATE|STR_ASCII, &len);
1211 if (!NT_STATUS_IS_OK(status)) {
1212 reply_nterror(req, status);
1213 END_PROFILE(SMBioctl);
1217 status = srvstr_push((char *)req->outbuf, req->flags2,
1219 lp_servicename(talloc_tos(),
1222 13, STR_TERMINATE|STR_ASCII, &len);
1223 if (!NT_STATUS_IS_OK(status)) {
1224 reply_nterror(req, status);
1225 END_PROFILE(SMBioctl);
1229 memset(p+18, 0, 13);
1235 END_PROFILE(SMBioctl);
1239 /****************************************************************************
1240 Strange checkpath NTSTATUS mapping.
1241 ****************************************************************************/
1243 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1245 /* Strange DOS error code semantics only for checkpath... */
1246 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1247 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1248 /* We need to map to ERRbadpath */
1249 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1255 /****************************************************************************
1256 Reply to a checkpath.
1257 ****************************************************************************/
1259 void reply_checkpath(struct smb_request *req)
1261 connection_struct *conn = req->conn;
1262 struct smb_filename *smb_fname = NULL;
1265 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1266 TALLOC_CTX *ctx = talloc_tos();
1268 START_PROFILE(SMBcheckpath);
1270 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1271 STR_TERMINATE, &status);
1273 if (!NT_STATUS_IS_OK(status)) {
1274 status = map_checkpath_error(req->flags2, status);
1275 reply_nterror(req, status);
1276 END_PROFILE(SMBcheckpath);
1280 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1282 status = filename_convert(ctx,
1290 if (!NT_STATUS_IS_OK(status)) {
1291 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1292 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1293 ERRSRV, ERRbadpath);
1294 END_PROFILE(SMBcheckpath);
1300 if (!VALID_STAT(smb_fname->st) &&
1301 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1302 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1303 smb_fname_str_dbg(smb_fname), strerror(errno)));
1304 status = map_nt_error_from_unix(errno);
1308 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1309 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1310 ERRDOS, ERRbadpath);
1314 reply_outbuf(req, 0, 0);
1317 /* We special case this - as when a Windows machine
1318 is parsing a path is steps through the components
1319 one at a time - if a component fails it expects
1320 ERRbadpath, not ERRbadfile.
1322 status = map_checkpath_error(req->flags2, status);
1323 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1325 * Windows returns different error codes if
1326 * the parent directory is valid but not the
1327 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1328 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1329 * if the path is invalid.
1331 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1332 ERRDOS, ERRbadpath);
1336 reply_nterror(req, status);
1339 TALLOC_FREE(smb_fname);
1340 END_PROFILE(SMBcheckpath);
1344 /****************************************************************************
1346 ****************************************************************************/
1348 void reply_getatr(struct smb_request *req)
1350 connection_struct *conn = req->conn;
1351 struct smb_filename *smb_fname = NULL;
1358 TALLOC_CTX *ctx = talloc_tos();
1359 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1361 START_PROFILE(SMBgetatr);
1363 p = (const char *)req->buf + 1;
1364 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1365 if (!NT_STATUS_IS_OK(status)) {
1366 reply_nterror(req, status);
1370 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1371 under WfWg - weird! */
1372 if (*fname == '\0') {
1373 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1374 if (!CAN_WRITE(conn)) {
1375 mode |= FILE_ATTRIBUTE_READONLY;
1380 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1381 status = filename_convert(ctx,
1388 if (!NT_STATUS_IS_OK(status)) {
1389 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1390 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1391 ERRSRV, ERRbadpath);
1394 reply_nterror(req, status);
1397 if (!VALID_STAT(smb_fname->st) &&
1398 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1399 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1400 smb_fname_str_dbg(smb_fname),
1402 reply_nterror(req, map_nt_error_from_unix(errno));
1406 mode = dos_mode(conn, smb_fname);
1407 size = smb_fname->st.st_ex_size;
1409 if (ask_sharemode) {
1410 struct timespec write_time_ts;
1411 struct file_id fileid;
1413 ZERO_STRUCT(write_time_ts);
1414 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1415 get_file_infos(fileid, 0, NULL, &write_time_ts);
1416 if (!is_omit_timespec(&write_time_ts)) {
1417 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1421 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1422 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1427 reply_outbuf(req, 10, 0);
1429 SSVAL(req->outbuf,smb_vwv0,mode);
1430 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1431 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1433 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1435 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1437 if (get_Protocol() >= PROTOCOL_NT1) {
1438 SSVAL(req->outbuf, smb_flg2,
1439 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1442 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1443 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1446 TALLOC_FREE(smb_fname);
1448 END_PROFILE(SMBgetatr);
1452 /****************************************************************************
1454 ****************************************************************************/
1456 void reply_setatr(struct smb_request *req)
1458 struct smb_file_time ft;
1459 connection_struct *conn = req->conn;
1460 struct smb_filename *smb_fname = NULL;
1466 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1467 TALLOC_CTX *ctx = talloc_tos();
1469 START_PROFILE(SMBsetatr);
1470 init_smb_file_time(&ft);
1473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1477 p = (const char *)req->buf + 1;
1478 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1479 if (!NT_STATUS_IS_OK(status)) {
1480 reply_nterror(req, status);
1484 status = filename_convert(ctx,
1491 if (!NT_STATUS_IS_OK(status)) {
1492 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1493 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1494 ERRSRV, ERRbadpath);
1497 reply_nterror(req, status);
1501 if (ISDOT(smb_fname->base_name)) {
1503 * Not sure here is the right place to catch this
1504 * condition. Might be moved to somewhere else later -- vl
1506 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1510 mode = SVAL(req->vwv+0, 0);
1511 mtime = srv_make_unix_date3(req->vwv+1);
1513 if (mode != FILE_ATTRIBUTE_NORMAL) {
1514 if (VALID_STAT_OF_DIR(smb_fname->st))
1515 mode |= FILE_ATTRIBUTE_DIRECTORY;
1517 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1519 status = smbd_check_access_rights(conn,
1523 FILE_WRITE_ATTRIBUTES);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 reply_nterror(req, status);
1529 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1531 reply_nterror(req, map_nt_error_from_unix(errno));
1536 ft.mtime = time_t_to_full_timespec(mtime);
1538 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1539 if (!NT_STATUS_IS_OK(status)) {
1540 reply_nterror(req, status);
1544 reply_outbuf(req, 0, 0);
1546 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1549 TALLOC_FREE(smb_fname);
1550 END_PROFILE(SMBsetatr);
1554 /****************************************************************************
1556 ****************************************************************************/
1558 void reply_dskattr(struct smb_request *req)
1560 connection_struct *conn = req->conn;
1562 uint64_t dfree,dsize,bsize;
1563 struct smb_filename smb_fname;
1564 START_PROFILE(SMBdskattr);
1566 ZERO_STRUCT(smb_fname);
1567 smb_fname.base_name = discard_const_p(char, ".");
1569 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1570 reply_nterror(req, map_nt_error_from_unix(errno));
1571 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1572 END_PROFILE(SMBdskattr);
1576 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1577 if (ret == (uint64_t)-1) {
1578 reply_nterror(req, map_nt_error_from_unix(errno));
1579 END_PROFILE(SMBdskattr);
1584 * Force max to fit in 16 bit fields.
1586 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1590 if (bsize > (WORDMAX*512)) {
1591 bsize = (WORDMAX*512);
1592 if (dsize > WORDMAX)
1594 if (dfree > WORDMAX)
1600 reply_outbuf(req, 5, 0);
1602 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1603 double total_space, free_space;
1604 /* we need to scale this to a number that DOS6 can handle. We
1605 use floating point so we can handle large drives on systems
1606 that don't have 64 bit integers
1608 we end up displaying a maximum of 2G to DOS systems
1610 total_space = dsize * (double)bsize;
1611 free_space = dfree * (double)bsize;
1613 dsize = (uint64_t)((total_space+63*512) / (64*512));
1614 dfree = (uint64_t)((free_space+63*512) / (64*512));
1616 if (dsize > 0xFFFF) dsize = 0xFFFF;
1617 if (dfree > 0xFFFF) dfree = 0xFFFF;
1619 SSVAL(req->outbuf,smb_vwv0,dsize);
1620 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1621 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1622 SSVAL(req->outbuf,smb_vwv3,dfree);
1624 SSVAL(req->outbuf,smb_vwv0,dsize);
1625 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1626 SSVAL(req->outbuf,smb_vwv2,512);
1627 SSVAL(req->outbuf,smb_vwv3,dfree);
1630 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1632 END_PROFILE(SMBdskattr);
1637 * Utility function to split the filename from the directory.
1639 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1640 char **fname_dir_out,
1641 char **fname_mask_out)
1643 const char *p = NULL;
1644 char *fname_dir = NULL;
1645 char *fname_mask = NULL;
1647 p = strrchr_m(fname_in, '/');
1649 fname_dir = talloc_strdup(ctx, ".");
1650 fname_mask = talloc_strdup(ctx, fname_in);
1652 fname_dir = talloc_strndup(ctx, fname_in,
1653 PTR_DIFF(p, fname_in));
1654 fname_mask = talloc_strdup(ctx, p+1);
1657 if (!fname_dir || !fname_mask) {
1658 TALLOC_FREE(fname_dir);
1659 TALLOC_FREE(fname_mask);
1660 return NT_STATUS_NO_MEMORY;
1663 *fname_dir_out = fname_dir;
1664 *fname_mask_out = fname_mask;
1665 return NT_STATUS_OK;
1668 /****************************************************************************
1670 ****************************************************************************/
1672 static bool make_dir_struct(TALLOC_CTX *ctx,
1682 char *mask2 = talloc_strdup(ctx, mask);
1688 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1692 memset(buf+1,' ',11);
1693 if ((p = strchr_m(mask2,'.')) != NULL) {
1695 push_ascii(buf+1,mask2,8, 0);
1696 push_ascii(buf+9,p+1,3, 0);
1699 push_ascii(buf+1,mask2,11, 0);
1702 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1704 srv_put_dos_date(buf,22,date);
1705 SSVAL(buf,26,size & 0xFFFF);
1706 SSVAL(buf,28,(size >> 16)&0xFFFF);
1707 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1708 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1709 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1710 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1714 /****************************************************************************
1716 Can be called from SMBsearch, SMBffirst or SMBfunique.
1717 ****************************************************************************/
1719 void reply_search(struct smb_request *req)
1721 connection_struct *conn = req->conn;
1724 char *directory = NULL;
1725 struct smb_filename *smb_fname = NULL;
1729 struct timespec date;
1731 unsigned int numentries = 0;
1732 unsigned int maxentries = 0;
1733 bool finished = False;
1738 bool check_descend = False;
1739 bool expect_close = False;
1741 bool mask_contains_wcard = False;
1742 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1743 TALLOC_CTX *ctx = talloc_tos();
1744 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1745 struct smbXsrv_connection *xconn = req->xconn;
1746 struct smbd_server_connection *sconn = req->sconn;
1747 files_struct *fsp = NULL;
1748 const struct loadparm_substitution *lp_sub =
1749 loadparm_s3_global_substitution();
1751 START_PROFILE(SMBsearch);
1754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1758 if (req->posix_pathnames) {
1759 reply_unknown_new(req, req->cmd);
1763 /* If we were called as SMBffirst then we must expect close. */
1764 if(req->cmd == SMBffirst) {
1765 expect_close = True;
1768 reply_outbuf(req, 1, 3);
1769 maxentries = SVAL(req->vwv+0, 0);
1770 dirtype = SVAL(req->vwv+1, 0);
1771 p = (const char *)req->buf + 1;
1772 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1774 if (!NT_STATUS_IS_OK(nt_status)) {
1775 reply_nterror(req, nt_status);
1779 if (smbreq_bufrem(req, p) < 3) {
1780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1785 status_len = SVAL(p, 0);
1788 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1790 if (status_len == 0) {
1792 struct smb_filename *smb_dname = NULL;
1793 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1794 ucf_flags_from_smb_request(req);
1795 nt_status = filename_convert(ctx, conn,
1801 if (!NT_STATUS_IS_OK(nt_status)) {
1802 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1803 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1804 ERRSRV, ERRbadpath);
1807 reply_nterror(req, nt_status);
1811 directory = smb_fname->base_name;
1813 p = strrchr_m(directory,'/');
1814 if ((p != NULL) && (*directory != '/')) {
1815 mask = talloc_strdup(ctx, p + 1);
1816 directory = talloc_strndup(ctx, directory,
1817 PTR_DIFF(p, directory));
1819 mask = talloc_strdup(ctx, directory);
1820 directory = talloc_strdup(ctx,".");
1824 reply_nterror(req, NT_STATUS_NO_MEMORY);
1828 memset((char *)status,'\0',21);
1829 SCVAL(status,0,(dirtype & 0x1F));
1831 smb_dname = synthetic_smb_fname(talloc_tos(),
1837 if (smb_dname == NULL) {
1838 reply_nterror(req, NT_STATUS_NO_MEMORY);
1843 * As we've cut off the last component from
1844 * smb_fname we need to re-stat smb_dname
1845 * so FILE_OPEN disposition knows the directory
1848 if (req->posix_pathnames) {
1849 ret = SMB_VFS_LSTAT(conn, smb_dname);
1851 ret = SMB_VFS_STAT(conn, smb_dname);
1854 nt_status = map_nt_error_from_unix(errno);
1855 reply_nterror(req, nt_status);
1860 * Open an fsp on this directory for the dptr.
1862 nt_status = SMB_VFS_CREATE_FILE(
1865 &conn->cwd_fsp, /* dirfsp */
1866 smb_dname, /* dname */
1867 FILE_LIST_DIRECTORY, /* access_mask */
1869 FILE_SHARE_WRITE, /* share_access */
1870 FILE_OPEN, /* create_disposition*/
1871 FILE_DIRECTORY_FILE, /* create_options */
1872 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1873 NO_OPLOCK, /* oplock_request */
1875 0, /* allocation_size */
1876 0, /* private_flags */
1881 NULL, /* in_context */
1882 NULL);/* out_context */
1884 if (!NT_STATUS_IS_OK(nt_status)) {
1885 DBG_ERR("failed to open directory %s\n",
1886 smb_fname_str_dbg(smb_dname));
1887 reply_nterror(req, nt_status);
1891 nt_status = dptr_create(conn,
1901 TALLOC_FREE(smb_dname);
1903 if (!NT_STATUS_IS_OK(nt_status)) {
1905 * Use NULL here for the first parameter (req)
1906 * as this is not a client visible handle so
1907 * can'tbe part of an SMB1 chain.
1909 close_file(NULL, fsp, NORMAL_CLOSE);
1911 reply_nterror(req, nt_status);
1915 dptr_num = dptr_dnum(fsp->dptr);
1919 const char *dirpath;
1921 if (smbreq_bufrem(req, p) < 21) {
1922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1926 memcpy(status,p,21);
1927 status_dirtype = CVAL(status,0) & 0x1F;
1928 if (status_dirtype != (dirtype & 0x1F)) {
1929 dirtype = status_dirtype;
1932 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1936 dirpath = dptr_path(sconn, dptr_num);
1937 directory = talloc_strdup(ctx, dirpath);
1939 reply_nterror(req, NT_STATUS_NO_MEMORY);
1943 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1947 dirtype = dptr_attr(sconn, dptr_num);
1950 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1952 DEBUG(4,("dptr_num is %d\n",dptr_num));
1954 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1955 char buf[DIR_STRUCT_SIZE];
1956 memcpy(buf,status,21);
1957 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1958 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1959 reply_nterror(req, NT_STATUS_NO_MEMORY);
1962 dptr_fill(sconn, buf+12,dptr_num);
1963 if (dptr_zero(buf+12) && (status_len==0)) {
1968 if (message_push_blob(&req->outbuf,
1969 data_blob_const(buf, sizeof(buf)))
1971 reply_nterror(req, NT_STATUS_NO_MEMORY);
1976 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1977 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1979 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1981 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1982 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1983 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1984 check_descend = True;
1987 for (i=numentries;(i<maxentries) && !finished;i++) {
1988 finished = !get_dir_entry(ctx,
1999 char buf[DIR_STRUCT_SIZE];
2000 memcpy(buf,status,21);
2001 if (!make_dir_struct(ctx,
2007 convert_timespec_to_time_t(date),
2008 !allow_long_path_components)) {
2009 reply_nterror(req, NT_STATUS_NO_MEMORY);
2012 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2015 if (message_push_blob(&req->outbuf,
2016 data_blob_const(buf, sizeof(buf)))
2018 reply_nterror(req, NT_STATUS_NO_MEMORY);
2028 /* If we were called as SMBffirst with smb_search_id == NULL
2029 and no entries were found then return error and close fsp->dptr
2032 if (numentries == 0) {
2035 close_file(NULL, fsp, NORMAL_CLOSE);
2038 } else if(expect_close && status_len == 0) {
2039 /* Close the dptr - we know it's gone */
2042 close_file(NULL, fsp, NORMAL_CLOSE);
2047 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2048 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2050 /* fsp may have been closed above. */
2052 close_file(NULL, fsp, NORMAL_CLOSE);
2057 if ((numentries == 0) && !mask_contains_wcard) {
2058 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2062 SSVAL(req->outbuf,smb_vwv0,numentries);
2063 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2064 SCVAL(smb_buf(req->outbuf),0,5);
2065 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2067 /* The replies here are never long name. */
2068 SSVAL(req->outbuf, smb_flg2,
2069 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2070 if (!allow_long_path_components) {
2071 SSVAL(req->outbuf, smb_flg2,
2072 SVAL(req->outbuf, smb_flg2)
2073 & (~FLAGS2_LONG_PATH_COMPONENTS));
2076 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2077 SSVAL(req->outbuf, smb_flg2,
2078 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2080 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2081 smb_fn_name(req->cmd),
2088 TALLOC_FREE(directory);
2090 TALLOC_FREE(smb_fname);
2091 END_PROFILE(SMBsearch);
2095 /****************************************************************************
2096 Reply to a fclose (stop directory search).
2097 ****************************************************************************/
2099 void reply_fclose(struct smb_request *req)
2107 TALLOC_CTX *ctx = talloc_tos();
2108 struct smbd_server_connection *sconn = req->sconn;
2109 files_struct *fsp = NULL;
2111 START_PROFILE(SMBfclose);
2113 if (req->posix_pathnames) {
2114 reply_unknown_new(req, req->cmd);
2115 END_PROFILE(SMBfclose);
2119 p = (const char *)req->buf + 1;
2120 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
2122 if (!NT_STATUS_IS_OK(err)) {
2123 reply_nterror(req, err);
2124 END_PROFILE(SMBfclose);
2128 if (smbreq_bufrem(req, p) < 3) {
2129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2130 END_PROFILE(SMBfclose);
2135 status_len = SVAL(p,0);
2138 if (status_len == 0) {
2139 reply_force_doserror(req, ERRSRV, ERRsrverror);
2140 END_PROFILE(SMBfclose);
2144 if (smbreq_bufrem(req, p) < 21) {
2145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2146 END_PROFILE(SMBfclose);
2150 memcpy(status,p,21);
2152 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2154 /* Close the file - we know it's gone */
2155 close_file(NULL, fsp, NORMAL_CLOSE);
2160 reply_outbuf(req, 1, 0);
2161 SSVAL(req->outbuf,smb_vwv0,0);
2163 DEBUG(3,("search close\n"));
2165 END_PROFILE(SMBfclose);
2169 /****************************************************************************
2171 ****************************************************************************/
2173 void reply_open(struct smb_request *req)
2175 connection_struct *conn = req->conn;
2176 struct smb_filename *smb_fname = NULL;
2186 uint32_t access_mask;
2187 uint32_t share_mode;
2188 uint32_t create_disposition;
2189 uint32_t create_options = 0;
2190 uint32_t private_flags = 0;
2193 TALLOC_CTX *ctx = talloc_tos();
2195 START_PROFILE(SMBopen);
2198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2202 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2203 deny_mode = SVAL(req->vwv+0, 0);
2204 dos_attr = SVAL(req->vwv+1, 0);
2206 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2207 STR_TERMINATE, &status);
2208 if (!NT_STATUS_IS_OK(status)) {
2209 reply_nterror(req, status);
2213 if (!map_open_params_to_ntcreate(fname, deny_mode,
2214 OPENX_FILE_EXISTS_OPEN, &access_mask,
2215 &share_mode, &create_disposition,
2216 &create_options, &private_flags)) {
2217 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2221 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2223 status = filename_convert(ctx,
2230 if (!NT_STATUS_IS_OK(status)) {
2231 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2232 reply_botherror(req,
2233 NT_STATUS_PATH_NOT_COVERED,
2234 ERRSRV, ERRbadpath);
2237 reply_nterror(req, status);
2241 status = SMB_VFS_CREATE_FILE(
2244 &conn->cwd_fsp, /* dirfsp */
2245 smb_fname, /* fname */
2246 access_mask, /* access_mask */
2247 share_mode, /* share_access */
2248 create_disposition, /* create_disposition*/
2249 create_options, /* create_options */
2250 dos_attr, /* file_attributes */
2251 oplock_request, /* oplock_request */
2253 0, /* allocation_size */
2259 NULL, NULL); /* create context */
2261 if (!NT_STATUS_IS_OK(status)) {
2262 if (open_was_deferred(req->xconn, req->mid)) {
2263 /* We have re-scheduled this call. */
2267 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2268 reply_openerror(req, status);
2272 fsp = fcb_or_dos_open(
2279 bool ok = defer_smb1_sharing_violation(req);
2283 reply_openerror(req, status);
2288 /* Ensure we're pointing at the correct stat struct. */
2289 TALLOC_FREE(smb_fname);
2290 smb_fname = fsp->fsp_name;
2292 size = smb_fname->st.st_ex_size;
2293 fattr = dos_mode(conn, smb_fname);
2295 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2297 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2298 DEBUG(3,("attempt to open a directory %s\n",
2300 close_file(req, fsp, ERROR_CLOSE);
2301 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2302 ERRDOS, ERRnoaccess);
2306 reply_outbuf(req, 7, 0);
2307 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2308 SSVAL(req->outbuf,smb_vwv1,fattr);
2309 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2310 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2312 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2314 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2315 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2317 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2318 SCVAL(req->outbuf,smb_flg,
2319 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2322 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2323 SCVAL(req->outbuf,smb_flg,
2324 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2327 END_PROFILE(SMBopen);
2331 /****************************************************************************
2332 Reply to an open and X.
2333 ****************************************************************************/
2335 void reply_open_and_X(struct smb_request *req)
2337 connection_struct *conn = req->conn;
2338 struct smb_filename *smb_fname = NULL;
2340 uint16_t open_flags;
2343 /* Breakout the oplock request bits so we can set the
2344 reply bits separately. */
2345 int ex_oplock_request;
2346 int core_oplock_request;
2349 int smb_sattr = SVAL(req->vwv+4, 0);
2350 uint32_t smb_time = make_unix_date3(req->vwv+6);
2358 uint64_t allocation_size;
2359 ssize_t retval = -1;
2360 uint32_t access_mask;
2361 uint32_t share_mode;
2362 uint32_t create_disposition;
2363 uint32_t create_options = 0;
2364 uint32_t private_flags = 0;
2366 TALLOC_CTX *ctx = talloc_tos();
2368 START_PROFILE(SMBopenX);
2370 if (req->wct < 15) {
2371 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2375 open_flags = SVAL(req->vwv+2, 0);
2376 deny_mode = SVAL(req->vwv+3, 0);
2377 smb_attr = SVAL(req->vwv+5, 0);
2378 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2379 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2380 oplock_request = ex_oplock_request | core_oplock_request;
2381 smb_ofun = SVAL(req->vwv+8, 0);
2382 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2384 /* If it's an IPC, pass off the pipe handler. */
2386 if (lp_nt_pipe_support()) {
2387 reply_open_pipe_and_X(conn, req);
2389 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2394 /* XXXX we need to handle passed times, sattr and flags */
2395 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2396 STR_TERMINATE, &status);
2397 if (!NT_STATUS_IS_OK(status)) {
2398 reply_nterror(req, status);
2402 if (!map_open_params_to_ntcreate(fname, deny_mode,
2404 &access_mask, &share_mode,
2405 &create_disposition,
2408 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2412 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2414 status = filename_convert(ctx,
2421 if (!NT_STATUS_IS_OK(status)) {
2422 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2423 reply_botherror(req,
2424 NT_STATUS_PATH_NOT_COVERED,
2425 ERRSRV, ERRbadpath);
2428 reply_nterror(req, status);
2432 status = SMB_VFS_CREATE_FILE(
2435 &conn->cwd_fsp, /* dirfsp */
2436 smb_fname, /* fname */
2437 access_mask, /* access_mask */
2438 share_mode, /* share_access */
2439 create_disposition, /* create_disposition*/
2440 create_options, /* create_options */
2441 smb_attr, /* file_attributes */
2442 oplock_request, /* oplock_request */
2444 0, /* allocation_size */
2449 &smb_action, /* pinfo */
2450 NULL, NULL); /* create context */
2452 if (!NT_STATUS_IS_OK(status)) {
2453 if (open_was_deferred(req->xconn, req->mid)) {
2454 /* We have re-scheduled this call. */
2458 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2459 reply_openerror(req, status);
2463 fsp = fcb_or_dos_open(
2470 bool ok = defer_smb1_sharing_violation(req);
2474 reply_openerror(req, status);
2479 smb_action = FILE_WAS_OPENED;
2482 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2483 if the file is truncated or created. */
2484 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2485 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2486 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2487 close_file(req, fsp, ERROR_CLOSE);
2488 reply_nterror(req, NT_STATUS_DISK_FULL);
2491 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2493 close_file(req, fsp, ERROR_CLOSE);
2494 reply_nterror(req, NT_STATUS_DISK_FULL);
2497 status = vfs_stat_fsp(fsp);
2498 if (!NT_STATUS_IS_OK(status)) {
2499 close_file(req, fsp, ERROR_CLOSE);
2500 reply_nterror(req, status);
2505 fattr = dos_mode(conn, fsp->fsp_name);
2506 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2507 close_file(req, fsp, ERROR_CLOSE);
2508 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2511 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2513 /* If the caller set the extended oplock request bit
2514 and we granted one (by whatever means) - set the
2515 correct bit for extended oplock reply.
2518 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2519 smb_action |= EXTENDED_OPLOCK_GRANTED;
2522 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2523 smb_action |= EXTENDED_OPLOCK_GRANTED;
2526 /* If the caller set the core oplock request bit
2527 and we granted one (by whatever means) - set the
2528 correct bit for core oplock reply.
2531 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2532 reply_outbuf(req, 19, 0);
2534 reply_outbuf(req, 15, 0);
2537 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2538 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2540 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2541 SCVAL(req->outbuf, smb_flg,
2542 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2545 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2546 SCVAL(req->outbuf, smb_flg,
2547 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2550 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2551 SSVAL(req->outbuf,smb_vwv3,fattr);
2552 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2553 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2555 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2557 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2558 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2559 SSVAL(req->outbuf,smb_vwv11,smb_action);
2561 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2562 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2566 TALLOC_FREE(smb_fname);
2567 END_PROFILE(SMBopenX);
2571 /****************************************************************************
2572 Reply to a SMBulogoffX.
2573 ****************************************************************************/
2575 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2576 struct smbXsrv_session *session);
2577 static void reply_ulogoffX_done(struct tevent_req *req);
2579 void reply_ulogoffX(struct smb_request *smb1req)
2581 struct timeval now = timeval_current();
2582 struct smbXsrv_session *session = NULL;
2583 struct tevent_req *req;
2587 * Don't setup the profile charge here, take
2588 * it in reply_ulogoffX_done(). Not strictly correct
2589 * but better than the other SMB1 async
2590 * code that double-charges at the moment.
2593 status = smb1srv_session_lookup(smb1req->xconn,
2595 timeval_to_nttime(&now),
2597 if (!NT_STATUS_IS_OK(status)) {
2598 /* Not going async, profile here. */
2599 START_PROFILE(SMBulogoffX);
2600 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2601 (unsigned long long)smb1req->vuid);
2603 smb1req->vuid = UID_FIELD_INVALID;
2604 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2605 END_PROFILE(SMBulogoffX);
2609 req = reply_ulogoffX_send(smb1req, session);
2611 /* Not going async, profile here. */
2612 START_PROFILE(SMBulogoffX);
2613 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2614 END_PROFILE(SMBulogoffX);
2618 /* We're async. This will complete later. */
2619 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2623 struct reply_ulogoffX_state {
2624 struct tevent_queue *wait_queue;
2625 struct smbXsrv_session *session;
2628 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2630 /****************************************************************************
2631 Async SMB1 ulogoffX.
2632 Note, on failure here we deallocate and return NULL to allow the caller to
2633 SMB1 return an error of ERRnomem immediately.
2634 ****************************************************************************/
2636 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2637 struct smbXsrv_session *session)
2639 struct tevent_req *req;
2640 struct reply_ulogoffX_state *state;
2641 struct tevent_req *subreq;
2643 struct smbd_server_connection *sconn = session->client->sconn;
2644 uint64_t vuid = session->global->session_wire_id;
2646 req = tevent_req_create(smb1req, &state,
2647 struct reply_ulogoffX_state);
2651 state->wait_queue = tevent_queue_create(state,
2652 "reply_ulogoffX_wait_queue");
2653 if (tevent_req_nomem(state->wait_queue, req)) {
2657 state->session = session;
2660 * Make sure that no new request will be able to use this session.
2661 * This ensures that once all outstanding fsp->aio_requests
2662 * on this session are done, we are safe to close it.
2664 session->status = NT_STATUS_USER_SESSION_DELETED;
2666 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2667 if (fsp->vuid != vuid) {
2671 * Flag the file as close in progress.
2672 * This will prevent any more IO being
2675 fsp->fsp_flags.closing = true;
2677 if (fsp->num_aio_requests > 0) {
2679 * Now wait until all aio requests on this fsp are
2682 * We don't set a callback, as we just want to block the
2683 * wait queue and the talloc_free() of fsp->aio_request
2684 * will remove the item from the wait queue.
2686 subreq = tevent_queue_wait_send(fsp->aio_requests,
2689 if (tevent_req_nomem(subreq, req)) {
2697 * Now we add our own waiter to the end of the queue,
2698 * this way we get notified when all pending requests are finished
2699 * and reply to the outstanding SMB1 request.
2701 subreq = tevent_queue_wait_send(state,
2704 if (tevent_req_nomem(subreq, req)) {
2710 * We're really going async - move the SMB1 request from
2711 * a talloc stackframe above us to the sconn talloc-context.
2712 * We need this to stick around until the wait_done
2713 * callback is invoked.
2715 smb1req = talloc_move(sconn, &smb1req);
2717 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2722 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2724 struct tevent_req *req = tevent_req_callback_data(
2725 subreq, struct tevent_req);
2727 tevent_queue_wait_recv(subreq);
2728 TALLOC_FREE(subreq);
2729 tevent_req_done(req);
2732 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2734 return tevent_req_simple_recv_ntstatus(req);
2737 static void reply_ulogoffX_done(struct tevent_req *req)
2739 struct smb_request *smb1req = tevent_req_callback_data(
2740 req, struct smb_request);
2741 struct reply_ulogoffX_state *state = tevent_req_data(req,
2742 struct reply_ulogoffX_state);
2743 struct smbXsrv_session *session = state->session;
2747 * Take the profile charge here. Not strictly
2748 * correct but better than the other SMB1 async
2749 * code that double-charges at the moment.
2751 START_PROFILE(SMBulogoffX);
2753 status = reply_ulogoffX_recv(req);
2755 if (!NT_STATUS_IS_OK(status)) {
2756 TALLOC_FREE(smb1req);
2757 END_PROFILE(SMBulogoffX);
2758 exit_server(__location__ ": reply_ulogoffX_recv failed");
2762 status = smbXsrv_session_logoff(session);
2763 if (!NT_STATUS_IS_OK(status)) {
2764 TALLOC_FREE(smb1req);
2765 END_PROFILE(SMBulogoffX);
2766 exit_server(__location__ ": smbXsrv_session_logoff failed");
2770 TALLOC_FREE(session);
2772 reply_outbuf(smb1req, 2, 0);
2773 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2774 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2776 DBG_NOTICE("ulogoffX vuid=%llu\n",
2777 (unsigned long long)smb1req->vuid);
2779 smb1req->vuid = UID_FIELD_INVALID;
2781 * The following call is needed to push the
2782 * reply data back out the socket after async
2783 * return. Plus it frees smb1req.
2785 smb_request_done(smb1req);
2786 END_PROFILE(SMBulogoffX);
2789 /****************************************************************************
2790 Reply to a mknew or a create.
2791 ****************************************************************************/
2793 void reply_mknew(struct smb_request *req)
2795 connection_struct *conn = req->conn;
2796 struct smb_filename *smb_fname = NULL;
2799 struct smb_file_time ft;
2801 int oplock_request = 0;
2803 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2804 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2805 uint32_t create_disposition;
2806 uint32_t create_options = 0;
2808 TALLOC_CTX *ctx = talloc_tos();
2810 START_PROFILE(SMBcreate);
2811 init_smb_file_time(&ft);
2814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2818 fattr = SVAL(req->vwv+0, 0);
2819 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2821 if (req->cmd == SMBmknew) {
2822 /* We should fail if file exists. */
2823 create_disposition = FILE_CREATE;
2825 /* Create if file doesn't exist, truncate if it does. */
2826 create_disposition = FILE_OVERWRITE_IF;
2830 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2832 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2833 STR_TERMINATE, &status);
2834 if (!NT_STATUS_IS_OK(status)) {
2835 reply_nterror(req, status);
2839 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2840 status = filename_convert(ctx,
2847 if (!NT_STATUS_IS_OK(status)) {
2848 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2849 reply_botherror(req,
2850 NT_STATUS_PATH_NOT_COVERED,
2851 ERRSRV, ERRbadpath);
2854 reply_nterror(req, status);
2858 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2859 DEBUG(0,("Attempt to create file (%s) with volid set - "
2860 "please report this\n",
2861 smb_fname_str_dbg(smb_fname)));
2864 status = SMB_VFS_CREATE_FILE(
2867 &conn->cwd_fsp, /* dirfsp */
2868 smb_fname, /* fname */
2869 access_mask, /* access_mask */
2870 share_mode, /* share_access */
2871 create_disposition, /* create_disposition*/
2872 create_options, /* create_options */
2873 fattr, /* file_attributes */
2874 oplock_request, /* oplock_request */
2876 0, /* allocation_size */
2877 0, /* private_flags */
2882 NULL, NULL); /* create context */
2884 if (!NT_STATUS_IS_OK(status)) {
2885 if (open_was_deferred(req->xconn, req->mid)) {
2886 /* We have re-scheduled this call. */
2889 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2890 bool ok = defer_smb1_sharing_violation(req);
2895 reply_openerror(req, status);
2899 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2900 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2901 if (!NT_STATUS_IS_OK(status)) {
2902 END_PROFILE(SMBcreate);
2906 reply_outbuf(req, 1, 0);
2907 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2909 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2910 SCVAL(req->outbuf,smb_flg,
2911 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2914 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2915 SCVAL(req->outbuf,smb_flg,
2916 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2919 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2920 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2921 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2922 (unsigned int)fattr));
2925 TALLOC_FREE(smb_fname);
2926 END_PROFILE(SMBcreate);
2930 /****************************************************************************
2931 Reply to a create temporary file.
2932 ****************************************************************************/
2934 void reply_ctemp(struct smb_request *req)
2936 connection_struct *conn = req->conn;
2937 struct smb_filename *smb_fname = NULL;
2938 char *wire_name = NULL;
2947 TALLOC_CTX *ctx = talloc_tos();
2949 START_PROFILE(SMBctemp);
2952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2956 fattr = SVAL(req->vwv+0, 0);
2957 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2959 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2960 STR_TERMINATE, &status);
2961 if (!NT_STATUS_IS_OK(status)) {
2962 reply_nterror(req, status);
2966 for (i = 0; i < 10; i++) {
2968 fname = talloc_asprintf(ctx,
2971 generate_random_str_list(ctx, 5, "0123456789"));
2973 fname = talloc_asprintf(ctx,
2975 generate_random_str_list(ctx, 5, "0123456789"));
2979 reply_nterror(req, NT_STATUS_NO_MEMORY);
2983 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2984 status = filename_convert(ctx, conn,
2990 if (!NT_STATUS_IS_OK(status)) {
2991 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2992 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2993 ERRSRV, ERRbadpath);
2996 reply_nterror(req, status);
3000 /* Create the file. */
3001 status = SMB_VFS_CREATE_FILE(
3004 &conn->cwd_fsp, /* dirfsp */
3005 smb_fname, /* fname */
3006 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
3007 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
3008 FILE_CREATE, /* create_disposition*/
3009 0, /* create_options */
3010 fattr, /* file_attributes */
3011 oplock_request, /* oplock_request */
3013 0, /* allocation_size */
3014 0, /* private_flags */
3019 NULL, NULL); /* create context */
3021 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3023 TALLOC_FREE(smb_fname);
3027 if (!NT_STATUS_IS_OK(status)) {
3028 if (open_was_deferred(req->xconn, req->mid)) {
3029 /* We have re-scheduled this call. */
3032 if (NT_STATUS_EQUAL(
3033 status, NT_STATUS_SHARING_VIOLATION)) {
3034 bool ok = defer_smb1_sharing_violation(req);
3039 reply_openerror(req, status);
3047 /* Collision after 10 times... */
3048 reply_nterror(req, status);
3052 reply_outbuf(req, 1, 0);
3053 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3055 /* the returned filename is relative to the directory */
3056 s = strrchr_m(fsp->fsp_name->base_name, '/');
3058 s = fsp->fsp_name->base_name;
3064 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3065 thing in the byte section. JRA */
3066 SSVALS(p, 0, -1); /* what is this? not in spec */
3068 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3070 reply_nterror(req, NT_STATUS_NO_MEMORY);
3074 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3075 SCVAL(req->outbuf, smb_flg,
3076 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3079 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3080 SCVAL(req->outbuf, smb_flg,
3081 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3084 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3085 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3086 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
3088 TALLOC_FREE(smb_fname);
3089 TALLOC_FREE(wire_name);
3090 END_PROFILE(SMBctemp);
3094 /*******************************************************************
3095 Check if a user is allowed to rename a file.
3096 ********************************************************************/
3098 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3101 if (!CAN_WRITE(conn)) {
3102 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3105 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3106 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3107 /* Only bother to read the DOS attribute if we might deny the
3108 rename on the grounds of attribute mismatch. */
3109 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3110 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3111 return NT_STATUS_NO_SUCH_FILE;
3115 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3116 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3117 return NT_STATUS_OK;
3120 /* If no pathnames are open below this
3121 directory, allow the rename. */
3123 if (lp_strict_rename(SNUM(conn))) {
3125 * Strict rename, check open file db.
3127 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3128 return NT_STATUS_ACCESS_DENIED;
3130 } else if (file_find_subpath(fsp)) {
3132 * No strict rename, just look in local process.
3134 return NT_STATUS_ACCESS_DENIED;
3136 return NT_STATUS_OK;
3139 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3140 return NT_STATUS_OK;
3143 return NT_STATUS_ACCESS_DENIED;
3146 /*******************************************************************
3147 * unlink a file with all relevant access checks
3148 *******************************************************************/
3150 static NTSTATUS do_unlink(connection_struct *conn,
3151 struct smb_request *req,
3152 struct smb_filename *smb_fname,
3157 uint32_t dirtype_orig = dirtype;
3160 bool posix_paths = (req != NULL && req->posix_pathnames);
3161 struct smb2_create_blobs *posx = NULL;
3163 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3164 smb_fname_str_dbg(smb_fname),
3167 if (!CAN_WRITE(conn)) {
3168 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3172 ret = SMB_VFS_LSTAT(conn, smb_fname);
3174 ret = SMB_VFS_STAT(conn, smb_fname);
3177 return map_nt_error_from_unix(errno);
3180 fattr = dos_mode(conn, smb_fname);
3182 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3183 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3186 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3188 return NT_STATUS_NO_SUCH_FILE;
3191 if (!dir_check_ftype(fattr, dirtype)) {
3192 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3193 return NT_STATUS_FILE_IS_A_DIRECTORY;
3195 return NT_STATUS_NO_SUCH_FILE;
3198 if (dirtype_orig & 0x8000) {
3199 /* These will never be set for POSIX. */
3200 return NT_STATUS_NO_SUCH_FILE;
3204 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3205 return NT_STATUS_FILE_IS_A_DIRECTORY;
3208 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3209 return NT_STATUS_NO_SUCH_FILE;
3212 if (dirtype & 0xFF00) {
3213 /* These will never be set for POSIX. */
3214 return NT_STATUS_NO_SUCH_FILE;
3219 return NT_STATUS_NO_SUCH_FILE;
3222 /* Can't delete a directory. */
3223 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3224 return NT_STATUS_FILE_IS_A_DIRECTORY;
3229 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3230 return NT_STATUS_OBJECT_NAME_INVALID;
3231 #endif /* JRATEST */
3234 status = make_smb2_posix_create_ctx(
3235 talloc_tos(), &posx, 0777);
3236 if (!NT_STATUS_IS_OK(status)) {
3237 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3243 /* On open checks the open itself will check the share mode, so
3244 don't do it here as we'll get it wrong. */
3246 status = SMB_VFS_CREATE_FILE
3249 &conn->cwd_fsp, /* dirfsp */
3250 smb_fname, /* fname */
3251 DELETE_ACCESS, /* access_mask */
3252 FILE_SHARE_NONE, /* share_access */
3253 FILE_OPEN, /* create_disposition*/
3254 FILE_NON_DIRECTORY_FILE, /* create_options */
3255 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
3256 0, /* oplock_request */
3258 0, /* allocation_size */
3259 0, /* private_flags */
3264 posx, /* in_context_blobs */
3265 NULL); /* out_context_blobs */
3269 if (!NT_STATUS_IS_OK(status)) {
3270 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3271 nt_errstr(status)));
3275 status = can_set_delete_on_close(fsp, fattr);
3276 if (!NT_STATUS_IS_OK(status)) {
3277 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3279 smb_fname_str_dbg(smb_fname),
3280 nt_errstr(status)));
3281 close_file(req, fsp, NORMAL_CLOSE);
3285 /* The set is across all open files on this dev/inode pair. */
3286 if (!set_delete_on_close(fsp, True,
3287 conn->session_info->security_token,
3288 conn->session_info->unix_token)) {
3289 close_file(req, fsp, NORMAL_CLOSE);
3290 return NT_STATUS_ACCESS_DENIED;
3293 return close_file(req, fsp, NORMAL_CLOSE);
3296 /****************************************************************************
3297 The guts of the unlink command, split out so it may be called by the NT SMB
3299 ****************************************************************************/
3301 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3302 uint32_t dirtype, struct smb_filename *smb_fname)
3304 char *fname_dir = NULL;
3305 char *fname_mask = NULL;
3307 NTSTATUS status = NT_STATUS_OK;
3308 struct smb_filename *smb_fname_dir = NULL;
3309 bool has_wild = false;
3310 TALLOC_CTX *ctx = talloc_tos();
3312 /* Split up the directory from the filename/mask. */
3313 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3314 &fname_dir, &fname_mask);
3315 if (!NT_STATUS_IS_OK(status)) {
3319 if (req != NULL && !req->posix_pathnames) {
3321 * Check the wildcard mask *before*
3322 * unmangling. As mangling is done
3323 * for names that can't be returned
3324 * to Windows the unmangled name may
3325 * contain Windows wildcard characters.
3327 has_wild = ms_has_wild(fname_mask);
3331 * We should only check the mangled cache
3332 * here if unix_convert failed. This means
3333 * that the path in 'mask' doesn't exist
3334 * on the file system and so we need to look
3335 * for a possible mangle. This patch from
3336 * Tine Smukavec <valentin.smukavec@hermes.si>.
3339 if (!VALID_STAT(smb_fname->st) &&
3340 mangle_is_mangled(fname_mask, conn->params)) {
3341 char *new_mask = NULL;
3342 mangle_lookup_name_from_8_3(ctx, fname_mask,
3343 &new_mask, conn->params);
3345 TALLOC_FREE(fname_mask);
3346 fname_mask = new_mask;
3353 * Only one file needs to be unlinked. Append the mask back
3354 * onto the directory.
3356 TALLOC_FREE(smb_fname->base_name);
3357 if (ISDOT(fname_dir)) {
3358 /* Ensure we use canonical names on open. */
3359 smb_fname->base_name = talloc_asprintf(smb_fname,
3363 smb_fname->base_name = talloc_asprintf(smb_fname,
3368 if (!smb_fname->base_name) {
3369 status = NT_STATUS_NO_MEMORY;
3373 dirtype = FILE_ATTRIBUTE_NORMAL;
3376 status = check_name(conn, smb_fname);
3377 if (!NT_STATUS_IS_OK(status)) {
3381 status = do_unlink(conn, req, smb_fname, dirtype);
3382 if (!NT_STATUS_IS_OK(status)) {
3388 struct smb_Dir *dir_hnd = NULL;
3390 const char *dname = NULL;
3391 char *talloced = NULL;
3393 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3394 status = NT_STATUS_OBJECT_NAME_INVALID;
3398 dirtype = FILE_ATTRIBUTE_NORMAL;
3401 if (strequal(fname_mask,"????????.???")) {
3402 TALLOC_FREE(fname_mask);
3403 fname_mask = talloc_strdup(ctx, "*");
3405 status = NT_STATUS_NO_MEMORY;
3410 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3416 if (smb_fname_dir == NULL) {
3417 status = NT_STATUS_NO_MEMORY;
3421 status = check_name(conn, smb_fname_dir);
3422 if (!NT_STATUS_IS_OK(status)) {
3426 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3428 if (dir_hnd == NULL) {
3429 status = map_nt_error_from_unix(errno);
3433 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3434 the pattern matches against the long name, otherwise the short name
3435 We don't implement this yet XXXX
3438 status = NT_STATUS_NO_SUCH_FILE;
3440 while ((dname = ReadDirName(dir_hnd, &offset,
3441 &smb_fname->st, &talloced))) {
3442 TALLOC_CTX *frame = talloc_stackframe();
3444 struct smb_filename *f = NULL;
3446 if (!is_visible_file(conn,
3452 TALLOC_FREE(talloced);
3456 /* Quick check for "." and ".." */
3457 if (ISDOT(dname) || ISDOTDOT(dname)) {
3459 TALLOC_FREE(talloced);
3463 if(!mask_match(dname, fname_mask,
3464 conn->case_sensitive)) {
3466 TALLOC_FREE(talloced);
3470 if (ISDOT(fname_dir)) {
3471 /* Ensure we use canonical names on open. */
3472 p = talloc_asprintf(smb_fname, "%s", dname);
3474 p = talloc_asprintf(smb_fname, "%s/%s",
3478 TALLOC_FREE(dir_hnd);
3479 status = NT_STATUS_NO_MEMORY;
3481 TALLOC_FREE(talloced);
3484 f = synthetic_smb_fname(frame,
3491 TALLOC_FREE(dir_hnd);
3492 status = NT_STATUS_NO_MEMORY;
3494 TALLOC_FREE(talloced);
3498 status = check_name(conn, f);
3499 if (!NT_STATUS_IS_OK(status)) {
3500 TALLOC_FREE(dir_hnd);
3502 TALLOC_FREE(talloced);
3506 status = do_unlink(conn, req, f, dirtype);
3507 if (!NT_STATUS_IS_OK(status)) {
3508 TALLOC_FREE(dir_hnd);
3510 TALLOC_FREE(talloced);
3515 DBG_DEBUG("successful unlink [%s]\n",
3516 smb_fname_str_dbg(f));
3519 TALLOC_FREE(talloced);
3521 TALLOC_FREE(dir_hnd);
3524 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3525 status = map_nt_error_from_unix(errno);
3529 TALLOC_FREE(smb_fname_dir);
3530 TALLOC_FREE(fname_dir);
3531 TALLOC_FREE(fname_mask);
3535 /****************************************************************************
3537 ****************************************************************************/
3539 void reply_unlink(struct smb_request *req)
3541 connection_struct *conn = req->conn;
3543 struct smb_filename *smb_fname = NULL;
3546 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
3547 ucf_flags_from_smb_request(req);
3548 TALLOC_CTX *ctx = talloc_tos();
3550 START_PROFILE(SMBunlink);
3553 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3557 dirtype = SVAL(req->vwv+0, 0);
3559 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
3560 STR_TERMINATE, &status);
3561 if (!NT_STATUS_IS_OK(status)) {
3562 reply_nterror(req, status);
3566 status = filename_convert(ctx, conn,
3572 if (!NT_STATUS_IS_OK(status)) {
3573 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3574 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3575 ERRSRV, ERRbadpath);
3578 reply_nterror(req, status);
3582 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3584 status = unlink_internals(conn, req, dirtype, smb_fname);
3585 if (!NT_STATUS_IS_OK(status)) {
3586 if (open_was_deferred(req->xconn, req->mid)) {
3587 /* We have re-scheduled this call. */
3590 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3591 bool ok = defer_smb1_sharing_violation(req);
3596 reply_nterror(req, status);
3600 reply_outbuf(req, 0, 0);
3602 TALLOC_FREE(smb_fname);
3603 END_PROFILE(SMBunlink);
3607 /****************************************************************************
3609 ****************************************************************************/
3611 static void fail_readraw(void)
3613 const char *errstr = talloc_asprintf(talloc_tos(),
3614 "FAIL ! reply_readbraw: socket write fail (%s)",
3619 exit_server_cleanly(errstr);
3622 /****************************************************************************
3623 Fake (read/write) sendfile. Returns -1 on read or write fail.
3624 ****************************************************************************/
3626 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3627 off_t startpos, size_t nread)
3630 size_t tosend = nread;
3637 bufsize = MIN(nread, 65536);
3639 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3643 while (tosend > 0) {
3647 cur_read = MIN(tosend, bufsize);
3648 ret = read_file(fsp,buf,startpos,cur_read);
3654 /* If we had a short read, fill with zeros. */
3655 if (ret < cur_read) {
3656 memset(buf + ret, '\0', cur_read - ret);
3659 ret = write_data(xconn->transport.sock, buf, cur_read);
3660 if (ret != cur_read) {
3661 int saved_errno = errno;
3663 * Try and give an error message saying what
3666 DEBUG(0, ("write_data failed for client %s. "
3668 smbXsrv_connection_dbg(xconn),
3669 strerror(saved_errno)));
3671 errno = saved_errno;
3675 startpos += cur_read;
3679 return (ssize_t)nread;
3682 /****************************************************************************
3683 Deal with the case of sendfile reading less bytes from the file than
3684 requested. Fill with zeros (all we can do). Returns 0 on success
3685 ****************************************************************************/
3687 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3693 #define SHORT_SEND_BUFSIZE 1024
3694 if (nread < headersize) {
3695 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3696 "header for file %s (%s). Terminating\n",
3697 fsp_str_dbg(fsp), strerror(errno)));
3701 nread -= headersize;
3703 if (nread < smb_maxcnt) {
3704 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3706 DEBUG(0,("sendfile_short_send: malloc failed "
3707 "for file %s (%s). Terminating\n",
3708 fsp_str_dbg(fsp), strerror(errno)));
3712 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3713 "with zeros !\n", fsp_str_dbg(fsp)));
3715 while (nread < smb_maxcnt) {
3717 * We asked for the real file size and told sendfile
3718 * to not go beyond the end of the file. But it can
3719 * happen that in between our fstat call and the
3720 * sendfile call the file was truncated. This is very
3721 * bad because we have already announced the larger
3722 * number of bytes to the client.
3724 * The best we can do now is to send 0-bytes, just as
3725 * a read from a hole in a sparse file would do.
3727 * This should happen rarely enough that I don't care
3728 * about efficiency here :-)
3733 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3734 ret = write_data(xconn->transport.sock, buf, to_write);
3735 if (ret != to_write) {
3736 int saved_errno = errno;
3738 * Try and give an error message saying what
3741 DEBUG(0, ("write_data failed for client %s. "
3743 smbXsrv_connection_dbg(xconn),
3744 strerror(saved_errno)));
3745 errno = saved_errno;
3756 /****************************************************************************
3757 Return a readbraw error (4 bytes of zero).
3758 ****************************************************************************/
3760 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3766 smbd_lock_socket(xconn);
3767 if (write_data(xconn->transport.sock,header,4) != 4) {
3768 int saved_errno = errno;
3770 * Try and give an error message saying what
3773 DEBUG(0, ("write_data failed for client %s. "
3775 smbXsrv_connection_dbg(xconn),
3776 strerror(saved_errno)));
3777 errno = saved_errno;
3781 smbd_unlock_socket(xconn);
3784 /*******************************************************************
3785 Ensure we don't use sendfile if server smb signing is active.
3786 ********************************************************************/
3788 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3790 bool sign_active = false;
3792 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3793 if (get_Protocol() < PROTOCOL_NT1) {
3796 if (signing_state) {
3797 sign_active = smb_signing_is_active(signing_state);
3799 return (lp__use_sendfile(snum) &&
3800 (get_remote_arch() != RA_WIN95) &&
3803 /****************************************************************************
3804 Use sendfile in readbraw.
3805 ****************************************************************************/
3807 static void send_file_readbraw(connection_struct *conn,
3808 struct smb_request *req,
3814 struct smbXsrv_connection *xconn = req->xconn;
3815 char *outbuf = NULL;
3819 * We can only use sendfile on a non-chained packet
3820 * but we can use on a non-oplocked file. tridge proved this
3821 * on a train in Germany :-). JRA.
3822 * reply_readbraw has already checked the length.
3825 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3826 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3827 ssize_t sendfile_read = -1;
3829 DATA_BLOB header_blob;
3831 _smb_setlen(header,nread);
3832 header_blob = data_blob_const(header, 4);
3834 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3835 &header_blob, startpos,
3837 if (sendfile_read == -1) {
3838 /* Returning ENOSYS means no data at all was sent.
3839 * Do this as a normal read. */
3840 if (errno == ENOSYS) {
3841 goto normal_readbraw;
3845 * Special hack for broken Linux with no working sendfile. If we
3846 * return EINTR we sent the header but not the rest of the data.
3847 * Fake this up by doing read/write calls.
3849 if (errno == EINTR) {
3850 /* Ensure we don't do this again. */
3851 set_use_sendfile(SNUM(conn), False);
3852 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3854 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3855 DEBUG(0,("send_file_readbraw: "
3856 "fake_sendfile failed for "
3860 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3865 DEBUG(0,("send_file_readbraw: sendfile failed for "
3866 "file %s (%s). Terminating\n",
3867 fsp_str_dbg(fsp), strerror(errno)));
3868 exit_server_cleanly("send_file_readbraw sendfile failed");
3869 } else if (sendfile_read == 0) {
3871 * Some sendfile implementations return 0 to indicate
3872 * that there was a short read, but nothing was
3873 * actually written to the socket. In this case,
3874 * fallback to the normal read path so the header gets
3875 * the correct byte count.
3877 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3878 "bytes falling back to the normal read: "
3879 "%s\n", fsp_str_dbg(fsp)));
3880 goto normal_readbraw;
3883 /* Deal with possible short send. */
3884 if (sendfile_read != 4+nread) {
3885 ret = sendfile_short_send(xconn, fsp,
3886 sendfile_read, 4, nread);
3896 outbuf = talloc_array(NULL, char, nread+4);
3898 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3899 (unsigned)(nread+4)));
3900 reply_readbraw_error(xconn);
3905 ret = read_file(fsp,outbuf+4,startpos,nread);
3906 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3915 _smb_setlen(outbuf,ret);
3916 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3917 int saved_errno = errno;
3919 * Try and give an error message saying what
3922 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3923 smbXsrv_connection_dbg(xconn),
3924 strerror(saved_errno)));
3925 errno = saved_errno;
3930 TALLOC_FREE(outbuf);
3933 /****************************************************************************
3934 Reply to a readbraw (core+ protocol).
3935 ****************************************************************************/
3937 void reply_readbraw(struct smb_request *req)
3939 connection_struct *conn = req->conn;
3940 struct smbXsrv_connection *xconn = req->xconn;
3941 ssize_t maxcount,mincount;
3945 struct lock_struct lock;
3949 START_PROFILE(SMBreadbraw);
3951 if (srv_is_signing_active(xconn) || req->encrypted) {
3952 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3953 "raw reads/writes are disallowed.");
3957 reply_readbraw_error(xconn);
3958 END_PROFILE(SMBreadbraw);
3962 if (xconn->smb1.echo_handler.trusted_fde) {
3963 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3964 "'async smb echo handler = yes'\n"));
3965 reply_readbraw_error(xconn);
3966 END_PROFILE(SMBreadbraw);
3971 * Special check if an oplock break has been issued
3972 * and the readraw request croses on the wire, we must
3973 * return a zero length response here.
3976 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3979 * We have to do a check_fsp by hand here, as
3980 * we must always return 4 zero bytes on error,
3986 conn != fsp->conn ||
3987 req->vuid != fsp->vuid ||
3988 fsp->fsp_flags.is_directory ||
3992 * fsp could be NULL here so use the value from the packet. JRA.
3994 DEBUG(3,("reply_readbraw: fnum %d not valid "
3996 (int)SVAL(req->vwv+0, 0)));
3997 reply_readbraw_error(xconn);
3998 END_PROFILE(SMBreadbraw);
4002 /* Do a "by hand" version of CHECK_READ. */
4003 if (!(fsp->fsp_flags.can_read ||
4004 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
4005 (fsp->access_mask & FILE_EXECUTE)))) {
4006 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4007 (int)SVAL(req->vwv+0, 0)));
4008 reply_readbraw_error(xconn);
4009 END_PROFILE(SMBreadbraw);
4013 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
4014 if(req->wct == 10) {
4016 * This is a large offset (64 bit) read.
4019 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4022 DEBUG(0,("reply_readbraw: negative 64 bit "
4023 "readraw offset (%.0f) !\n",
4024 (double)startpos ));
4025 reply_readbraw_error(xconn);
4026 END_PROFILE(SMBreadbraw);
4031 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4032 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4034 /* ensure we don't overrun the packet size */
4035 maxcount = MIN(65535,maxcount);
4037 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4038 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4041 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4042 reply_readbraw_error(xconn);
4043 END_PROFILE(SMBreadbraw);
4047 status = vfs_stat_fsp(fsp);
4048 if (NT_STATUS_IS_OK(status)) {
4049 size = fsp->fsp_name->st.st_ex_size;
4052 if (startpos >= size) {
4055 nread = MIN(maxcount,(size - startpos));
4058 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4059 if (nread < mincount)
4063 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4064 "min=%lu nread=%lu\n",
4065 fsp_fnum_dbg(fsp), (double)startpos,
4066 (unsigned long)maxcount,
4067 (unsigned long)mincount,
4068 (unsigned long)nread ) );
4070 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4072 DEBUG(5,("reply_readbraw finished\n"));
4074 END_PROFILE(SMBreadbraw);
4079 #define DBGC_CLASS DBGC_LOCKING
4081 /****************************************************************************
4082 Reply to a lockread (core+ protocol).
4083 ****************************************************************************/
4085 static void reply_lockread_locked(struct tevent_req *subreq);
4087 void reply_lockread(struct smb_request *req)
4089 struct tevent_req *subreq = NULL;
4090 connection_struct *conn = req->conn;
4092 struct smbd_lock_element *lck = NULL;
4094 START_PROFILE(SMBlockread);
4097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4098 END_PROFILE(SMBlockread);
4102 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4104 if (!check_fsp(conn, req, fsp)) {
4105 END_PROFILE(SMBlockread);
4109 if (!CHECK_READ(fsp,req)) {
4110 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4111 END_PROFILE(SMBlockread);
4115 lck = talloc(req, struct smbd_lock_element);
4117 reply_nterror(req, NT_STATUS_NO_MEMORY);
4118 END_PROFILE(SMBlockread);
4123 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4124 * protocol request that predates the read/write lock concept.
4125 * Thus instead of asking for a read lock here we need to ask
4126 * for a write lock. JRA.
4127 * Note that the requested lock size is unaffected by max_send.
4130 *lck = (struct smbd_lock_element) {
4131 .req_guid = smbd_request_guid(req, 0),
4132 .smblctx = req->smbpid,
4133 .brltype = WRITE_LOCK,
4134 .count = SVAL(req->vwv+1, 0),
4135 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4138 subreq = smbd_smb1_do_locks_send(
4144 false, /* large_offset */
4148 if (subreq == NULL) {
4149 reply_nterror(req, NT_STATUS_NO_MEMORY);
4150 END_PROFILE(SMBlockread);
4153 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4154 END_PROFILE(SMBlockread);
4157 static void reply_lockread_locked(struct tevent_req *subreq)
4159 struct smb_request *req = NULL;
4165 size_t numtoread, maxtoread;
4166 struct files_struct *fsp = NULL;
4169 START_PROFILE(SMBlockread);
4171 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4174 status = smbd_smb1_do_locks_recv(subreq);
4175 TALLOC_FREE(subreq);
4177 if (!NT_STATUS_IS_OK(status)) {
4178 reply_nterror(req, status);
4182 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4184 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4188 numtoread = SVAL(req->vwv+1, 0);
4189 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4192 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4194 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4196 if (numtoread > maxtoread) {
4197 DBG_WARNING("requested read size (%zu) is greater than "
4198 "maximum allowed (%zu/%d). "
4199 "Returning short read of maximum allowed for "
4200 "compatibility with Windows 2000.\n",
4203 req->xconn->smb1.sessions.max_send);
4204 numtoread = maxtoread;
4207 reply_outbuf(req, 5, numtoread + 3);
4209 data = smb_buf(req->outbuf) + 3;
4211 nread = read_file(fsp,data,startpos,numtoread);
4214 reply_nterror(req, map_nt_error_from_unix(errno));
4218 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4220 SSVAL(req->outbuf,smb_vwv0,nread);
4221 SSVAL(req->outbuf,smb_vwv5,nread+3);
4222 p = smb_buf(req->outbuf);
4223 SCVAL(p,0,0); /* pad byte. */
4226 DEBUG(3,("lockread %s num=%d nread=%d\n",
4227 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4230 ok = srv_send_smb(req->xconn,
4231 (char *)req->outbuf,
4234 IS_CONN_ENCRYPTED(req->conn),
4237 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4240 END_PROFILE(SMBlockread);
4245 #define DBGC_CLASS DBGC_ALL
4247 /****************************************************************************
4249 ****************************************************************************/
4251 void reply_read(struct smb_request *req)
4253 connection_struct *conn = req->conn;
4260 struct lock_struct lock;
4261 struct smbXsrv_connection *xconn = req->xconn;
4263 START_PROFILE(SMBread);
4266 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4267 END_PROFILE(SMBread);
4271 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4273 if (!check_fsp(conn, req, fsp)) {
4274 END_PROFILE(SMBread);
4278 if (!CHECK_READ(fsp,req)) {
4279 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4280 END_PROFILE(SMBread);
4284 numtoread = SVAL(req->vwv+1, 0);
4285 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4288 * The requested read size cannot be greater than max_send. JRA.
4290 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4292 if (numtoread > maxtoread) {
4293 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4294 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4295 (unsigned int)numtoread, (unsigned int)maxtoread,
4296 (unsigned int)xconn->smb1.sessions.max_send));
4297 numtoread = maxtoread;
4300 reply_outbuf(req, 5, numtoread+3);
4302 data = smb_buf(req->outbuf) + 3;
4304 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4305 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4308 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4309 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4310 END_PROFILE(SMBread);
4315 nread = read_file(fsp,data,startpos,numtoread);
4318 reply_nterror(req, map_nt_error_from_unix(errno));
4322 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4324 SSVAL(req->outbuf,smb_vwv0,nread);
4325 SSVAL(req->outbuf,smb_vwv5,nread+3);
4326 SCVAL(smb_buf(req->outbuf),0,1);
4327 SSVAL(smb_buf(req->outbuf),1,nread);
4329 DEBUG(3, ("read %s num=%d nread=%d\n",
4330 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4333 END_PROFILE(SMBread);
4337 /****************************************************************************
4339 ****************************************************************************/
4341 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4345 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4348 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4350 SCVAL(outbuf,smb_vwv0,0xFF);
4351 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4352 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4353 SSVAL(outbuf,smb_vwv6,
4354 (smb_wct - 4) /* offset from smb header to wct */
4355 + 1 /* the wct field */
4356 + 12 * sizeof(uint16_t) /* vwv */
4357 + 2 /* the buflen field */
4358 + 1); /* padding byte */
4359 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4360 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4361 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4362 _smb_setlen_large(outbuf,
4363 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4367 /****************************************************************************
4368 Reply to a read and X - possibly using sendfile.
4369 ****************************************************************************/
4371 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4372 files_struct *fsp, off_t startpos,
4375 struct smbXsrv_connection *xconn = req->xconn;
4377 struct lock_struct lock;
4378 int saved_errno = 0;
4381 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4382 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4385 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4386 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4391 * We can only use sendfile on a non-chained packet
4392 * but we can use on a non-oplocked file. tridge proved this
4393 * on a train in Germany :-). JRA.
4396 if (!req_is_in_chain(req) &&
4398 (fsp->base_fsp == NULL) &&
4399 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4400 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4403 status = vfs_stat_fsp(fsp);
4404 if (!NT_STATUS_IS_OK(status)) {
4405 reply_nterror(req, status);
4409 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4410 (startpos > fsp->fsp_name->st.st_ex_size) ||
4411 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4413 * We already know that we would do a short read, so don't
4414 * try the sendfile() path.
4416 goto nosendfile_read;
4420 * Set up the packet header before send. We
4421 * assume here the sendfile will work (get the
4422 * correct amount of data).
4425 header = data_blob_const(headerbuf, sizeof(headerbuf));
4427 construct_reply_common_req(req, (char *)headerbuf);
4428 setup_readX_header((char *)headerbuf, smb_maxcnt);
4430 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4431 startpos, smb_maxcnt);
4433 saved_errno = errno;
4435 /* Returning ENOSYS means no data at all was sent.
4436 Do this as a normal read. */
4437 if (errno == ENOSYS) {
4442 * Special hack for broken Linux with no working sendfile. If we
4443 * return EINTR we sent the header but not the rest of the data.
4444 * Fake this up by doing read/write calls.
4447 if (errno == EINTR) {
4448 /* Ensure we don't do this again. */
4449 set_use_sendfile(SNUM(conn), False);
4450 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4451 nread = fake_sendfile(xconn, fsp, startpos,
4454 saved_errno = errno;
4455 DEBUG(0,("send_file_readX: "
4456 "fake_sendfile failed for "
4457 "file %s (%s) for client %s. "
4460 smbXsrv_connection_dbg(xconn),
4461 strerror(saved_errno)));
4462 errno = saved_errno;
4463 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4465 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4466 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4467 /* No outbuf here means successful sendfile. */
4471 DEBUG(0,("send_file_readX: sendfile failed for file "
4472 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4474 exit_server_cleanly("send_file_readX sendfile failed");
4475 } else if (nread == 0) {
4477 * Some sendfile implementations return 0 to indicate
4478 * that there was a short read, but nothing was
4479 * actually written to the socket. In this case,
4480 * fallback to the normal read path so the header gets
4481 * the correct byte count.
4483 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4484 "falling back to the normal read: %s\n",
4489 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4490 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4492 /* Deal with possible short send. */
4493 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4496 ret = sendfile_short_send(xconn, fsp, nread,
4497 sizeof(headerbuf), smb_maxcnt);
4500 r = "send_file_readX: sendfile_short_send failed";
4501 DEBUG(0,("%s for file %s (%s).\n",
4502 r, fsp_str_dbg(fsp), strerror(errno)));
4503 exit_server_cleanly(r);
4506 /* No outbuf here means successful sendfile. */
4507 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4508 SMB_PERFCOUNT_END(&req->pcd);
4514 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4515 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4518 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4519 (startpos > fsp->fsp_name->st.st_ex_size) ||
4520 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4522 * We already know that we would do a short
4523 * read, so don't try the sendfile() path.
4525 goto nosendfile_read;
4528 construct_reply_common_req(req, (char *)headerbuf);
4529 setup_readX_header((char *)headerbuf, smb_maxcnt);
4531 /* Send out the header. */
4532 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4534 if (ret != sizeof(headerbuf)) {
4535 saved_errno = errno;
4537 * Try and give an error message saying what
4540 DEBUG(0,("send_file_readX: write_data failed for file "
4541 "%s (%s) for client %s. Terminating\n",
4543 smbXsrv_connection_dbg(xconn),
4544 strerror(saved_errno)));
4545 errno = saved_errno;
4546 exit_server_cleanly("send_file_readX sendfile failed");
4548 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4550 saved_errno = errno;
4551 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4552 "%s (%s) for client %s. Terminating\n",
4554 smbXsrv_connection_dbg(xconn),
4555 strerror(saved_errno)));
4556 errno = saved_errno;
4557 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4564 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4565 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4566 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4568 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4569 startpos, smb_maxcnt);
4570 saved_errno = errno;
4573 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4577 setup_readX_header((char *)req->outbuf, nread);
4579 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4580 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4584 TALLOC_FREE(req->outbuf);
4588 /****************************************************************************
4589 Work out how much space we have for a read return.
4590 ****************************************************************************/
4592 static size_t calc_max_read_pdu(const struct smb_request *req)
4594 struct smbXsrv_connection *xconn = req->xconn;
4596 if (xconn->protocol < PROTOCOL_NT1) {
4597 return xconn->smb1.sessions.max_send;
4600 if (!lp_large_readwrite()) {
4601 return xconn->smb1.sessions.max_send;
4604 if (req_is_in_chain(req)) {
4605 return xconn->smb1.sessions.max_send;
4608 if (req->encrypted) {
4610 * Don't take encrypted traffic up to the
4611 * limit. There are padding considerations
4612 * that make that tricky.
4614 return xconn->smb1.sessions.max_send;
4617 if (srv_is_signing_active(xconn)) {
4621 if (!lp_unix_extensions()) {
4626 * We can do ultra-large POSIX reads.
4631 /****************************************************************************
4632 Calculate how big a read can be. Copes with all clients. It's always
4633 safe to return a short read - Windows does this.
4634 ****************************************************************************/
4636 static size_t calc_read_size(const struct smb_request *req,
4640 struct smbXsrv_connection *xconn = req->xconn;
4641 size_t max_pdu = calc_max_read_pdu(req);
4642 size_t total_size = 0;
4643 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4644 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4647 * Windows explicitly ignores upper size of 0xFFFF.
4648 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4649 * We must do the same as these will never fit even in
4650 * an extended size NetBIOS packet.
4652 if (upper_size == 0xFFFF) {
4656 if (xconn->protocol < PROTOCOL_NT1) {
4660 total_size = ((upper_size<<16) | lower_size);
4663 * LARGE_READX test shows it's always safe to return
4664 * a short read. Windows does so.
4666 return MIN(total_size, max_len);
4669 /****************************************************************************
4670 Reply to a read and X.
4671 ****************************************************************************/
4673 void reply_read_and_X(struct smb_request *req)
4675 connection_struct *conn = req->conn;
4680 bool big_readX = False;
4682 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4685 START_PROFILE(SMBreadX);
4687 if ((req->wct != 10) && (req->wct != 12)) {
4688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4692 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4693 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4694 smb_maxcnt = SVAL(req->vwv+5, 0);
4696 /* If it's an IPC, pass off the pipe handler. */
4698 reply_pipe_read_and_X(req);
4699 END_PROFILE(SMBreadX);
4703 if (!check_fsp(conn, req, fsp)) {
4704 END_PROFILE(SMBreadX);
4708 if (!CHECK_READ(fsp,req)) {
4709 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4710 END_PROFILE(SMBreadX);
4714 upper_size = SVAL(req->vwv+7, 0);
4715 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4716 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4718 * This is a heuristic to avoid keeping large
4719 * outgoing buffers around over long-lived aio
4725 if (req->wct == 12) {
4727 * This is a large offset (64 bit) read.
4729 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4734 NTSTATUS status = schedule_aio_read_and_X(conn,
4739 if (NT_STATUS_IS_OK(status)) {
4740 /* Read scheduled - we're done. */
4743 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4744 /* Real error - report to client. */
4745 END_PROFILE(SMBreadX);
4746 reply_nterror(req, status);
4749 /* NT_STATUS_RETRY - fall back to sync read. */
4752 smbd_lock_socket(req->xconn);
4753 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4754 smbd_unlock_socket(req->xconn);
4757 END_PROFILE(SMBreadX);
4761 /****************************************************************************
4762 Error replies to writebraw must have smb_wct == 1. Fix this up.
4763 ****************************************************************************/
4765 void error_to_writebrawerr(struct smb_request *req)
4767 uint8_t *old_outbuf = req->outbuf;
4769 reply_outbuf(req, 1, 0);
4771 memcpy(req->outbuf, old_outbuf, smb_size);
4772 TALLOC_FREE(old_outbuf);
4775 /****************************************************************************
4776 Read 4 bytes of a smb packet and return the smb length of the packet.
4777 Store the result in the buffer. This version of the function will
4778 never return a session keepalive (length of zero).
4779 Timeout is in milliseconds.
4780 ****************************************************************************/
4782 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4785 uint8_t msgtype = NBSSkeepalive;
4787 while (msgtype == NBSSkeepalive) {
4790 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4792 if (!NT_STATUS_IS_OK(status)) {
4793 char addr[INET6_ADDRSTRLEN];
4794 /* Try and give an error message
4795 * saying what client failed. */
4796 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4797 "client %s read error = %s.\n",
4798 get_peer_addr(fd,addr,sizeof(addr)),
4799 nt_errstr(status)));
4803 msgtype = CVAL(inbuf, 0);
4806 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4807 (unsigned long)len));
4809 return NT_STATUS_OK;
4812 /****************************************************************************
4813 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4814 ****************************************************************************/
4816 void reply_writebraw(struct smb_request *req)
4818 connection_struct *conn = req->conn;
4819 struct smbXsrv_connection *xconn = req->xconn;
4822 ssize_t total_written=0;
4823 size_t numtowrite=0;
4826 const char *data=NULL;
4829 struct lock_struct lock;
4832 START_PROFILE(SMBwritebraw);
4835 * If we ever reply with an error, it must have the SMB command
4836 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4839 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4841 if (srv_is_signing_active(xconn)) {
4842 END_PROFILE(SMBwritebraw);
4843 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4844 "raw reads/writes are disallowed.");
4847 if (req->wct < 12) {
4848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4849 error_to_writebrawerr(req);
4850 END_PROFILE(SMBwritebraw);
4854 if (xconn->smb1.echo_handler.trusted_fde) {
4855 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4856 "'async smb echo handler = yes'\n"));
4857 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4858 error_to_writebrawerr(req);
4859 END_PROFILE(SMBwritebraw);
4863 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4864 if (!check_fsp(conn, req, fsp)) {
4865 error_to_writebrawerr(req);
4866 END_PROFILE(SMBwritebraw);
4870 if (!CHECK_WRITE(fsp)) {
4871 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4872 error_to_writebrawerr(req);
4873 END_PROFILE(SMBwritebraw);
4877 tcount = IVAL(req->vwv+1, 0);
4878 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4879 write_through = BITSETW(req->vwv+7,0);
4881 /* We have to deal with slightly different formats depending
4882 on whether we are using the core+ or lanman1.0 protocol */
4884 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4885 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4886 data = smb_buf_const(req->inbuf);
4888 numtowrite = SVAL(req->vwv+10, 0);
4889 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4892 /* Ensure we don't write bytes past the end of this packet. */
4894 * This already protects us against CVE-2017-12163.
4896 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4898 error_to_writebrawerr(req);
4899 END_PROFILE(SMBwritebraw);
4903 if (!fsp->print_file) {
4904 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4905 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4908 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4909 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4910 error_to_writebrawerr(req);
4911 END_PROFILE(SMBwritebraw);
4917 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4920 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4921 "wrote=%d sync=%d\n",
4922 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4923 (int)nwritten, (int)write_through));
4925 if (nwritten < (ssize_t)numtowrite) {
4926 reply_nterror(req, NT_STATUS_DISK_FULL);
4927 error_to_writebrawerr(req);
4931 total_written = nwritten;
4933 /* Allocate a buffer of 64k + length. */
4934 buf = talloc_array(NULL, char, 65540);
4936 reply_nterror(req, NT_STATUS_NO_MEMORY);
4937 error_to_writebrawerr(req);
4941 /* Return a SMBwritebraw message to the redirector to tell
4942 * it to send more bytes */
4944 memcpy(buf, req->inbuf, smb_size);
4945 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4946 SCVAL(buf,smb_com,SMBwritebraw);
4947 SSVALS(buf,smb_vwv0,0xFFFF);
4949 if (!srv_send_smb(req->xconn,
4951 false, 0, /* no signing */
4952 IS_CONN_ENCRYPTED(conn),
4954 exit_server_cleanly("reply_writebraw: srv_send_smb "
4958 /* Now read the raw data into the buffer and write it */
4959 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4961 if (!NT_STATUS_IS_OK(status)) {
4962 exit_server_cleanly("secondary writebraw failed");
4965 /* Set up outbuf to return the correct size */
4966 reply_outbuf(req, 1, 0);
4968 if (numtowrite != 0) {
4970 if (numtowrite > 0xFFFF) {
4971 DEBUG(0,("reply_writebraw: Oversize secondary write "
4972 "raw requested (%u). Terminating\n",
4973 (unsigned int)numtowrite ));
4974 exit_server_cleanly("secondary writebraw failed");
4977 if (tcount > nwritten+numtowrite) {
4978 DEBUG(3,("reply_writebraw: Client overestimated the "
4980 (int)tcount,(int)nwritten,(int)numtowrite));
4983 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4986 if (!NT_STATUS_IS_OK(status)) {
4987 /* Try and give an error message
4988 * saying what client failed. */
4989 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4990 "raw read failed (%s) for client %s. "
4991 "Terminating\n", nt_errstr(status),
4992 smbXsrv_connection_dbg(xconn)));
4993 exit_server_cleanly("secondary writebraw failed");
4997 * We are not vulnerable to CVE-2017-12163
4998 * here as we are guaranteed to have numtowrite
4999 * bytes available - we just read from the client.
5001 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
5002 if (nwritten == -1) {
5004 reply_nterror(req, map_nt_error_from_unix(errno));
5005 error_to_writebrawerr(req);
5009 if (nwritten < (ssize_t)numtowrite) {
5010 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5011 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5015 total_written += nwritten;
5020 SSVAL(req->outbuf,smb_vwv0,total_written);
5022 status = sync_file(conn, fsp, write_through);
5023 if (!NT_STATUS_IS_OK(status)) {
5024 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5025 fsp_str_dbg(fsp), nt_errstr(status)));
5026 reply_nterror(req, status);
5027 error_to_writebrawerr(req);
5031 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5033 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5034 (int)total_written));
5036 /* We won't return a status if write through is not selected - this
5037 * follows what WfWg does */
5038 END_PROFILE(SMBwritebraw);
5040 if (!write_through && total_written==tcount) {
5042 #if RABBIT_PELLET_FIX
5044 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5045 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5048 if (!send_keepalive(xconn->transport.sock)) {
5049 exit_server_cleanly("reply_writebraw: send of "
5050 "keepalive failed");
5053 TALLOC_FREE(req->outbuf);
5058 END_PROFILE(SMBwritebraw);
5063 #define DBGC_CLASS DBGC_LOCKING
5065 /****************************************************************************
5066 Reply to a writeunlock (core+).
5067 ****************************************************************************/
5069 void reply_writeunlock(struct smb_request *req)
5071 connection_struct *conn = req->conn;
5072 ssize_t nwritten = -1;
5077 NTSTATUS status = NT_STATUS_OK;
5079 struct lock_struct lock;
5080 int saved_errno = 0;
5082 START_PROFILE(SMBwriteunlock);
5085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5086 END_PROFILE(SMBwriteunlock);
5090 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5092 if (!check_fsp(conn, req, fsp)) {
5093 END_PROFILE(SMBwriteunlock);
5097 if (!CHECK_WRITE(fsp)) {
5098 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5099 END_PROFILE(SMBwriteunlock);
5103 numtowrite = SVAL(req->vwv+1, 0);
5104 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5105 data = (const char *)req->buf + 3;
5108 * Ensure client isn't asking us to write more than
5109 * they sent. CVE-2017-12163.
5111 remaining = smbreq_bufrem(req, data);
5112 if (numtowrite > remaining) {
5113 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5114 END_PROFILE(SMBwriteunlock);
5118 if (!fsp->print_file && numtowrite > 0) {
5119 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5120 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5123 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5124 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5125 END_PROFILE(SMBwriteunlock);
5130 /* The special X/Open SMB protocol handling of
5131 zero length writes is *NOT* done for
5133 if(numtowrite == 0) {
5136 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5137 saved_errno = errno;
5140 status = sync_file(conn, fsp, False /* write through */);
5141 if (!NT_STATUS_IS_OK(status)) {
5142 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5143 fsp_str_dbg(fsp), nt_errstr(status)));
5144 reply_nterror(req, status);
5149 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5153 if((nwritten < numtowrite) && (numtowrite != 0)) {
5154 reply_nterror(req, NT_STATUS_DISK_FULL);
5158 if (numtowrite && !fsp->print_file) {
5159 struct smbd_lock_element l = {
5160 .req_guid = smbd_request_guid(req, 0),
5161 .smblctx = req->smbpid,
5162 .brltype = UNLOCK_LOCK,
5164 .count = numtowrite,
5166 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5167 if (NT_STATUS_V(status)) {
5168 reply_nterror(req, status);
5173 reply_outbuf(req, 1, 0);
5175 SSVAL(req->outbuf,smb_vwv0,nwritten);
5177 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5178 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5181 END_PROFILE(SMBwriteunlock);
5186 #define DBGC_CLASS DBGC_ALL
5188 /****************************************************************************
5190 ****************************************************************************/
5192 void reply_write(struct smb_request *req)
5194 connection_struct *conn = req->conn;
5197 ssize_t nwritten = -1;
5201 struct lock_struct lock;
5203 int saved_errno = 0;
5205 START_PROFILE(SMBwrite);
5208 END_PROFILE(SMBwrite);
5209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5213 /* If it's an IPC, pass off the pipe handler. */
5215 reply_pipe_write(req);
5216 END_PROFILE(SMBwrite);
5220 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5222 if (!check_fsp(conn, req, fsp)) {
5223 END_PROFILE(SMBwrite);
5227 if (!CHECK_WRITE(fsp)) {
5228 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5229 END_PROFILE(SMBwrite);
5233 numtowrite = SVAL(req->vwv+1, 0);
5234 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5235 data = (const char *)req->buf + 3;
5238 * Ensure client isn't asking us to write more than
5239 * they sent. CVE-2017-12163.
5241 remaining = smbreq_bufrem(req, data);
5242 if (numtowrite > remaining) {
5243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5244 END_PROFILE(SMBwrite);
5248 if (!fsp->print_file) {
5249 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5250 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5253 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5254 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5255 END_PROFILE(SMBwrite);
5261 * X/Open SMB protocol says that if smb_vwv1 is
5262 * zero then the file size should be extended or
5263 * truncated to the size given in smb_vwv[2-3].
5266 if(numtowrite == 0) {
5268 * This is actually an allocate call, and set EOF. JRA.
5270 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5272 reply_nterror(req, NT_STATUS_DISK_FULL);
5275 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5277 reply_nterror(req, NT_STATUS_DISK_FULL);
5280 trigger_write_time_update_immediate(fsp);
5282 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5285 status = sync_file(conn, fsp, False);
5286 if (!NT_STATUS_IS_OK(status)) {
5287 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5288 fsp_str_dbg(fsp), nt_errstr(status)));
5289 reply_nterror(req, status);
5294 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5298 if((nwritten == 0) && (numtowrite != 0)) {
5299 reply_nterror(req, NT_STATUS_DISK_FULL);
5303 reply_outbuf(req, 1, 0);
5305 SSVAL(req->outbuf,smb_vwv0,nwritten);
5307 if (nwritten < (ssize_t)numtowrite) {
5308 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5309 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5312 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5315 END_PROFILE(SMBwrite);
5319 /****************************************************************************
5320 Ensure a buffer is a valid writeX for recvfile purposes.
5321 ****************************************************************************/
5323 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5324 (2*14) + /* word count (including bcc) */ \
5327 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5328 const uint8_t *inbuf)
5331 unsigned int doff = 0;
5332 size_t len = smb_len_large(inbuf);
5334 struct smbXsrv_open *op = NULL;
5335 struct files_struct *fsp = NULL;
5338 if (is_encrypted_packet(inbuf)) {
5339 /* Can't do this on encrypted
5344 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5348 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5349 CVAL(inbuf,smb_wct) != 14) {
5350 DEBUG(10,("is_valid_writeX_buffer: chained or "
5351 "invalid word length.\n"));
5355 fnum = SVAL(inbuf, smb_vwv2);
5356 status = smb1srv_open_lookup(xconn,
5360 if (!NT_STATUS_IS_OK(status)) {
5361 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5366 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5369 if (fsp->conn == NULL) {
5370 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5374 if (IS_IPC(fsp->conn)) {
5375 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5378 if (IS_PRINT(fsp->conn)) {
5379 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5382 if (fsp->base_fsp != NULL) {
5383 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5386 doff = SVAL(inbuf,smb_vwv11);
5388 numtowrite = SVAL(inbuf,smb_vwv10);
5390 if (len > doff && len - doff > 0xFFFF) {
5391 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5394 if (numtowrite == 0) {
5395 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5399 /* Ensure the sizes match up. */
5400 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5401 /* no pad byte...old smbclient :-( */
5402 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5404 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5408 if (len - doff != numtowrite) {
5409 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5410 "len = %u, doff = %u, numtowrite = %u\n",
5413 (unsigned int)numtowrite ));
5417 DEBUG(10,("is_valid_writeX_buffer: true "
5418 "len = %u, doff = %u, numtowrite = %u\n",
5421 (unsigned int)numtowrite ));
5426 /****************************************************************************
5427 Reply to a write and X.
5428 ****************************************************************************/
5430 void reply_write_and_X(struct smb_request *req)
5432 connection_struct *conn = req->conn;
5433 struct smbXsrv_connection *xconn = req->xconn;
5435 struct lock_struct lock;
5440 unsigned int smb_doff;
5441 unsigned int smblen;
5444 int saved_errno = 0;
5446 START_PROFILE(SMBwriteX);
5448 if ((req->wct != 12) && (req->wct != 14)) {
5449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5453 numtowrite = SVAL(req->vwv+10, 0);
5454 smb_doff = SVAL(req->vwv+11, 0);
5455 smblen = smb_len(req->inbuf);
5457 if (req->unread_bytes > 0xFFFF ||
5458 (smblen > smb_doff &&
5459 smblen - smb_doff > 0xFFFF)) {
5460 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5463 if (req->unread_bytes) {
5464 /* Can't do a recvfile write on IPC$ */
5466 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5469 if (numtowrite != req->unread_bytes) {
5470 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5475 * This already protects us against CVE-2017-12163.
5477 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5478 smb_doff + numtowrite > smblen) {
5479 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5484 /* If it's an IPC, pass off the pipe handler. */
5486 if (req->unread_bytes) {
5487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5490 reply_pipe_write_and_X(req);
5494 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5495 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5496 write_through = BITSETW(req->vwv+7,0);
5498 if (!check_fsp(conn, req, fsp)) {
5502 if (!CHECK_WRITE(fsp)) {
5503 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5507 data = smb_base(req->inbuf) + smb_doff;
5509 if(req->wct == 14) {
5511 * This is a large offset (64 bit) write.
5513 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5517 /* X/Open SMB protocol says that, unlike SMBwrite
5518 if the length is zero then NO truncation is
5519 done, just a write of zero. To truncate a file,
5522 if(numtowrite == 0) {
5525 if (req->unread_bytes == 0) {
5526 status = schedule_aio_write_and_X(conn,
5533 if (NT_STATUS_IS_OK(status)) {
5534 /* write scheduled - we're done. */
5537 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5538 /* Real error - report to client. */
5539 reply_nterror(req, status);
5542 /* NT_STATUS_RETRY - fall through to sync write. */
5545 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5546 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5549 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5550 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5554 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5555 saved_errno = errno;
5559 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5563 if((nwritten == 0) && (numtowrite != 0)) {
5564 reply_nterror(req, NT_STATUS_DISK_FULL);
5568 reply_outbuf(req, 6, 0);
5569 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5570 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5571 SSVAL(req->outbuf,smb_vwv2,nwritten);
5572 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5574 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5575 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5577 status = sync_file(conn, fsp, write_through);
5578 if (!NT_STATUS_IS_OK(status)) {
5579 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5580 fsp_str_dbg(fsp), nt_errstr(status)));
5581 reply_nterror(req, status);
5585 END_PROFILE(SMBwriteX);
5589 if (req->unread_bytes) {
5590 /* writeX failed. drain socket. */
5591 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5592 req->unread_bytes) {
5593 smb_panic("failed to drain pending bytes");
5595 req->unread_bytes = 0;
5598 END_PROFILE(SMBwriteX);
5602 /****************************************************************************
5604 ****************************************************************************/
5606 void reply_lseek(struct smb_request *req)
5608 connection_struct *conn = req->conn;
5615 START_PROFILE(SMBlseek);
5618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5619 END_PROFILE(SMBlseek);
5623 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5625 if (!check_fsp(conn, req, fsp)) {
5629 mode = SVAL(req->vwv+1, 0) & 3;
5630 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5631 startpos = (off_t)IVALS(req->vwv+2, 0);
5640 res = fsp->fh->pos + startpos;
5651 if (umode == SEEK_END) {
5652 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5653 if(errno == EINVAL) {
5654 off_t current_pos = startpos;
5656 status = vfs_stat_fsp(fsp);
5657 if (!NT_STATUS_IS_OK(status)) {
5658 reply_nterror(req, status);
5659 END_PROFILE(SMBlseek);
5663 current_pos += fsp->fsp_name->st.st_ex_size;
5665 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5670 reply_nterror(req, map_nt_error_from_unix(errno));
5671 END_PROFILE(SMBlseek);
5678 reply_outbuf(req, 2, 0);
5679 SIVAL(req->outbuf,smb_vwv0,res);
5681 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5682 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5684 END_PROFILE(SMBlseek);
5688 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5691 connection_struct *conn = talloc_get_type_abort(
5692 private_data, connection_struct);
5694 if (conn != fsp->conn) {
5697 if (fsp->fh->fd == -1) {
5700 sync_file(conn, fsp, True /* write through */);
5702 if (fsp->fsp_flags.modified) {
5703 trigger_write_time_update_immediate(fsp);
5709 /****************************************************************************
5711 ****************************************************************************/
5713 void reply_flush(struct smb_request *req)
5715 connection_struct *conn = req->conn;
5719 START_PROFILE(SMBflush);
5722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5726 fnum = SVAL(req->vwv+0, 0);
5727 fsp = file_fsp(req, fnum);
5729 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5734 files_forall(req->sconn, file_sync_one_fn, conn);
5736 NTSTATUS status = sync_file(conn, fsp, True);
5737 if (!NT_STATUS_IS_OK(status)) {
5738 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5739 fsp_str_dbg(fsp), nt_errstr(status)));
5740 reply_nterror(req, status);
5741 END_PROFILE(SMBflush);
5744 if (fsp->fsp_flags.modified) {
5745 trigger_write_time_update_immediate(fsp);
5749 reply_outbuf(req, 0, 0);
5751 DEBUG(3,("flush\n"));
5752 END_PROFILE(SMBflush);
5756 /****************************************************************************
5758 conn POINTER CAN BE NULL HERE !
5759 ****************************************************************************/
5761 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5762 static void reply_exit_done(struct tevent_req *req);
5764 void reply_exit(struct smb_request *smb1req)
5766 struct tevent_req *req;
5769 * Don't setup the profile charge here, take
5770 * it in reply_exit_done(). Not strictly correct
5771 * but better than the other SMB1 async
5772 * code that double-charges at the moment.
5774 req = reply_exit_send(smb1req);
5776 /* Not going async, profile here. */
5777 START_PROFILE(SMBexit);
5778 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5779 END_PROFILE(SMBexit);
5783 /* We're async. This will complete later. */
5784 tevent_req_set_callback(req, reply_exit_done, smb1req);
5788 struct reply_exit_state {
5789 struct tevent_queue *wait_queue;
5792 static void reply_exit_wait_done(struct tevent_req *subreq);
5794 /****************************************************************************
5796 Note, on failure here we deallocate and return NULL to allow the caller to
5797 SMB1 return an error of ERRnomem immediately.
5798 ****************************************************************************/
5800 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5802 struct tevent_req *req;
5803 struct reply_exit_state *state;
5804 struct tevent_req *subreq;
5806 struct smbd_server_connection *sconn = smb1req->sconn;
5808 req = tevent_req_create(smb1req, &state,
5809 struct reply_exit_state);
5813 state->wait_queue = tevent_queue_create(state,
5814 "reply_exit_wait_queue");
5815 if (tevent_req_nomem(state->wait_queue, req)) {
5820 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5821 if (fsp->file_pid != smb1req->smbpid) {
5824 if (fsp->vuid != smb1req->vuid) {
5828 * Flag the file as close in progress.
5829 * This will prevent any more IO being
5832 fsp->fsp_flags.closing = true;
5834 if (fsp->num_aio_requests > 0) {
5836 * Now wait until all aio requests on this fsp are
5839 * We don't set a callback, as we just want to block the
5840 * wait queue and the talloc_free() of fsp->aio_request
5841 * will remove the item from the wait queue.
5843 subreq = tevent_queue_wait_send(fsp->aio_requests,
5846 if (tevent_req_nomem(subreq, req)) {
5854 * Now we add our own waiter to the end of the queue,
5855 * this way we get notified when all pending requests are finished
5856 * and reply to the outstanding SMB1 request.
5858 subreq = tevent_queue_wait_send(state,
5861 if (tevent_req_nomem(subreq, req)) {
5867 * We're really going async - move the SMB1 request from
5868 * a talloc stackframe above us to the conn talloc-context.
5869 * We need this to stick around until the wait_done
5870 * callback is invoked.
5872 smb1req = talloc_move(sconn, &smb1req);
5874 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5879 static void reply_exit_wait_done(struct tevent_req *subreq)
5881 struct tevent_req *req = tevent_req_callback_data(
5882 subreq, struct tevent_req);
5884 tevent_queue_wait_recv(subreq);
5885 TALLOC_FREE(subreq);
5886 tevent_req_done(req);
5889 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5891 return tevent_req_simple_recv_ntstatus(req);
5894 static void reply_exit_done(struct tevent_req *req)
5896 struct smb_request *smb1req = tevent_req_callback_data(
5897 req, struct smb_request);
5898 struct smbd_server_connection *sconn = smb1req->sconn;
5899 struct smbXsrv_connection *xconn = smb1req->xconn;
5900 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5901 struct smbXsrv_session *session = NULL;
5902 files_struct *fsp, *next;
5906 * Take the profile charge here. Not strictly
5907 * correct but better than the other SMB1 async
5908 * code that double-charges at the moment.
5910 START_PROFILE(SMBexit);
5912 status = reply_exit_recv(req);
5914 if (!NT_STATUS_IS_OK(status)) {
5915 TALLOC_FREE(smb1req);
5916 END_PROFILE(SMBexit);
5917 exit_server(__location__ ": reply_exit_recv failed");
5922 * Ensure the session is still valid.
5924 status = smb1srv_session_lookup(xconn,
5928 if (!NT_STATUS_IS_OK(status)) {
5929 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5930 smb_request_done(smb1req);
5931 END_PROFILE(SMBexit);
5935 * Ensure the vuid is still valid - no one
5936 * called reply_ulogoffX() in the meantime.
5937 * reply_exit() doesn't have AS_USER set, so
5938 * use set_current_user_info() directly.
5939 * This is the same logic as in switch_message().
5941 if (session->global->auth_session_info != NULL) {
5942 set_current_user_info(
5943 session->global->auth_session_info->unix_info->sanitized_username,
5944 session->global->auth_session_info->unix_info->unix_name,
5945 session->global->auth_session_info->info->domain_name);
5948 /* No more aio - do the actual closes. */
5949 for (fsp = sconn->files; fsp; fsp = next) {
5953 if (fsp->file_pid != smb1req->smbpid) {
5956 if (fsp->vuid != smb1req->vuid) {
5959 if (!fsp->fsp_flags.closing) {
5964 * reply_exit() has the DO_CHDIR flag set.
5966 ok = chdir_current_service(fsp->conn);
5968 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5969 smb_request_done(smb1req);
5970 END_PROFILE(SMBexit);
5972 close_file(NULL, fsp, SHUTDOWN_CLOSE);
5975 reply_outbuf(smb1req, 0, 0);
5977 * The following call is needed to push the
5978 * reply data back out the socket after async
5979 * return. Plus it frees smb1req.
5981 smb_request_done(smb1req);
5982 DBG_INFO("reply_exit complete\n");
5983 END_PROFILE(SMBexit);
5987 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5989 static void reply_close_done(struct tevent_req *req);
5991 void reply_close(struct smb_request *smb1req)
5993 connection_struct *conn = smb1req->conn;
5994 NTSTATUS status = NT_STATUS_OK;
5995 files_struct *fsp = NULL;
5996 START_PROFILE(SMBclose);
5998 if (smb1req->wct < 3) {
5999 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
6000 END_PROFILE(SMBclose);
6004 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
6007 * We can only use check_fsp if we know it's not a directory.
6010 if (!check_fsp_open(conn, smb1req, fsp)) {
6011 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
6012 END_PROFILE(SMBclose);
6016 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6017 fsp->fsp_flags.is_directory ?
6018 "directory" : "file",
6019 fsp->fh->fd, fsp_fnum_dbg(fsp),
6020 conn->num_files_open);
6022 if (!fsp->fsp_flags.is_directory) {
6026 * Take care of any time sent in the close.
6029 t = srv_make_unix_date3(smb1req->vwv+1);
6030 set_close_write_time(fsp, time_t_to_full_timespec(t));
6033 if (fsp->num_aio_requests != 0) {
6034 struct tevent_req *req;
6036 req = reply_close_send(smb1req, fsp);
6038 status = NT_STATUS_NO_MEMORY;
6041 /* We're async. This will complete later. */
6042 tevent_req_set_callback(req, reply_close_done, smb1req);
6043 END_PROFILE(SMBclose);
6048 * close_file() returns the unix errno if an error was detected on
6049 * close - normally this is due to a disk full error. If not then it
6050 * was probably an I/O error.
6053 status = close_file(smb1req, fsp, NORMAL_CLOSE);
6055 if (!NT_STATUS_IS_OK(status)) {
6056 reply_nterror(smb1req, status);
6057 END_PROFILE(SMBclose);
6061 reply_outbuf(smb1req, 0, 0);
6062 END_PROFILE(SMBclose);
6066 struct reply_close_state {
6068 struct tevent_queue *wait_queue;
6071 static void reply_close_wait_done(struct tevent_req *subreq);
6073 /****************************************************************************
6075 Note, on failure here we deallocate and return NULL to allow the caller to
6076 SMB1 return an error of ERRnomem immediately.
6077 ****************************************************************************/
6079 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
6082 struct tevent_req *req;
6083 struct reply_close_state *state;
6084 struct tevent_req *subreq;
6085 struct smbd_server_connection *sconn = smb1req->sconn;
6087 req = tevent_req_create(smb1req, &state,
6088 struct reply_close_state);
6092 state->wait_queue = tevent_queue_create(state,
6093 "reply_close_wait_queue");
6094 if (tevent_req_nomem(state->wait_queue, req)) {
6100 * Flag the file as close in progress.
6101 * This will prevent any more IO being
6104 fsp->fsp_flags.closing = true;
6107 * Now wait until all aio requests on this fsp are
6110 * We don't set a callback, as we just want to block the
6111 * wait queue and the talloc_free() of fsp->aio_request
6112 * will remove the item from the wait queue.
6114 subreq = tevent_queue_wait_send(fsp->aio_requests,
6117 if (tevent_req_nomem(subreq, req)) {
6123 * Now we add our own waiter to the end of the queue,
6124 * this way we get notified when all pending requests are finished
6125 * and reply to the outstanding SMB1 request.
6127 subreq = tevent_queue_wait_send(state,
6130 if (tevent_req_nomem(subreq, req)) {
6136 * We're really going async - move the SMB1 request from
6137 * a talloc stackframe above us to the conn talloc-context.
6138 * We need this to stick around until the wait_done
6139 * callback is invoked.
6141 smb1req = talloc_move(sconn, &smb1req);
6143 tevent_req_set_callback(subreq, reply_close_wait_done, req);
6148 static void reply_close_wait_done(struct tevent_req *subreq)
6150 struct tevent_req *req = tevent_req_callback_data(
6151 subreq, struct tevent_req);
6153 tevent_queue_wait_recv(subreq);
6154 TALLOC_FREE(subreq);
6155 tevent_req_done(req);
6158 static NTSTATUS reply_close_recv(struct tevent_req *req)
6160 return tevent_req_simple_recv_ntstatus(req);
6163 static void reply_close_done(struct tevent_req *req)
6165 struct smb_request *smb1req = tevent_req_callback_data(
6166 req, struct smb_request);
6167 struct reply_close_state *state = tevent_req_data(req,
6168 struct reply_close_state);
6171 status = reply_close_recv(req);
6173 if (!NT_STATUS_IS_OK(status)) {
6174 TALLOC_FREE(smb1req);
6175 exit_server(__location__ ": reply_close_recv failed");
6179 status = close_file(smb1req, state->fsp, NORMAL_CLOSE);
6180 if (NT_STATUS_IS_OK(status)) {
6181 reply_outbuf(smb1req, 0, 0);
6183 reply_nterror(smb1req, status);
6186 * The following call is needed to push the
6187 * reply data back out the socket after async
6188 * return. Plus it frees smb1req.
6190 smb_request_done(smb1req);
6193 /****************************************************************************
6194 Reply to a writeclose (Core+ protocol).
6195 ****************************************************************************/
6197 void reply_writeclose(struct smb_request *req)
6199 connection_struct *conn = req->conn;
6202 ssize_t nwritten = -1;
6203 NTSTATUS close_status = NT_STATUS_OK;
6206 struct timespec mtime;
6208 struct lock_struct lock;
6210 START_PROFILE(SMBwriteclose);
6213 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6214 END_PROFILE(SMBwriteclose);
6218 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6220 if (!check_fsp(conn, req, fsp)) {
6221 END_PROFILE(SMBwriteclose);
6224 if (!CHECK_WRITE(fsp)) {
6225 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6226 END_PROFILE(SMBwriteclose);
6230 numtowrite = SVAL(req->vwv+1, 0);
6231 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6232 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6233 data = (const char *)req->buf + 1;
6236 * Ensure client isn't asking us to write more than
6237 * they sent. CVE-2017-12163.
6239 remaining = smbreq_bufrem(req, data);
6240 if (numtowrite > remaining) {
6241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6242 END_PROFILE(SMBwriteclose);
6246 if (fsp->print_file == NULL) {
6247 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6248 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6251 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6252 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6253 END_PROFILE(SMBwriteclose);
6258 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6260 set_close_write_time(fsp, mtime);
6263 * More insanity. W2K only closes the file if writelen > 0.
6267 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6268 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6269 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6272 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6273 "file %s\n", fsp_str_dbg(fsp)));
6274 close_status = close_file(req, fsp, NORMAL_CLOSE);
6278 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6279 reply_nterror(req, NT_STATUS_DISK_FULL);
6283 if(!NT_STATUS_IS_OK(close_status)) {
6284 reply_nterror(req, close_status);
6288 reply_outbuf(req, 1, 0);
6290 SSVAL(req->outbuf,smb_vwv0,nwritten);
6294 END_PROFILE(SMBwriteclose);
6299 #define DBGC_CLASS DBGC_LOCKING
6301 /****************************************************************************
6303 ****************************************************************************/
6305 static void reply_lock_done(struct tevent_req *subreq);
6307 void reply_lock(struct smb_request *req)
6309 struct tevent_req *subreq = NULL;
6310 connection_struct *conn = req->conn;
6312 struct smbd_lock_element *lck = NULL;
6314 START_PROFILE(SMBlock);
6317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6318 END_PROFILE(SMBlock);
6322 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6324 if (!check_fsp(conn, req, fsp)) {
6325 END_PROFILE(SMBlock);
6329 lck = talloc(req, struct smbd_lock_element);
6331 reply_nterror(req, NT_STATUS_NO_MEMORY);
6332 END_PROFILE(SMBlock);
6336 *lck = (struct smbd_lock_element) {
6337 .req_guid = smbd_request_guid(req, 0),
6338 .smblctx = req->smbpid,
6339 .brltype = WRITE_LOCK,
6340 .count = IVAL(req->vwv+1, 0),
6341 .offset = IVAL(req->vwv+3, 0),
6344 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6350 subreq = smbd_smb1_do_locks_send(
6356 false, /* large_offset */
6360 if (subreq == NULL) {
6361 reply_nterror(req, NT_STATUS_NO_MEMORY);
6362 END_PROFILE(SMBlock);
6365 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6366 END_PROFILE(SMBlock);
6369 static void reply_lock_done(struct tevent_req *subreq)
6371 struct smb_request *req = NULL;
6375 START_PROFILE(SMBlock);
6377 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6380 status = smbd_smb1_do_locks_recv(subreq);
6381 TALLOC_FREE(subreq);
6383 if (NT_STATUS_IS_OK(status)) {
6384 reply_outbuf(req, 0, 0);
6386 reply_nterror(req, status);
6389 ok = srv_send_smb(req->xconn,
6390 (char *)req->outbuf,
6393 IS_CONN_ENCRYPTED(req->conn),
6396 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6399 END_PROFILE(SMBlock);
6402 /****************************************************************************
6404 ****************************************************************************/
6406 void reply_unlock(struct smb_request *req)
6408 connection_struct *conn = req->conn;
6411 struct smbd_lock_element lck;
6413 START_PROFILE(SMBunlock);
6416 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6417 END_PROFILE(SMBunlock);
6421 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6423 if (!check_fsp(conn, req, fsp)) {
6424 END_PROFILE(SMBunlock);
6428 lck = (struct smbd_lock_element) {
6429 .req_guid = smbd_request_guid(req, 0),
6430 .smblctx = req->smbpid,
6431 .brltype = UNLOCK_LOCK,
6432 .offset = IVAL(req->vwv+3, 0),
6433 .count = IVAL(req->vwv+1, 0),
6436 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6438 if (!NT_STATUS_IS_OK(status)) {
6439 reply_nterror(req, status);
6440 END_PROFILE(SMBunlock);
6444 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6450 reply_outbuf(req, 0, 0);
6452 END_PROFILE(SMBunlock);
6457 #define DBGC_CLASS DBGC_ALL
6459 /****************************************************************************
6461 conn POINTER CAN BE NULL HERE !
6462 ****************************************************************************/
6464 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6465 static void reply_tdis_done(struct tevent_req *req);
6467 void reply_tdis(struct smb_request *smb1req)
6469 connection_struct *conn = smb1req->conn;
6470 struct tevent_req *req;
6473 * Don't setup the profile charge here, take
6474 * it in reply_tdis_done(). Not strictly correct
6475 * but better than the other SMB1 async
6476 * code that double-charges at the moment.
6480 /* Not going async, profile here. */
6481 START_PROFILE(SMBtdis);
6482 DBG_INFO("Invalid connection in tdis\n");
6483 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6484 END_PROFILE(SMBtdis);
6488 req = reply_tdis_send(smb1req);
6490 /* Not going async, profile here. */
6491 START_PROFILE(SMBtdis);
6492 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6493 END_PROFILE(SMBtdis);
6496 /* We're async. This will complete later. */
6497 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6501 struct reply_tdis_state {
6502 struct tevent_queue *wait_queue;
6505 static void reply_tdis_wait_done(struct tevent_req *subreq);
6507 /****************************************************************************
6509 Note, on failure here we deallocate and return NULL to allow the caller to
6510 SMB1 return an error of ERRnomem immediately.
6511 ****************************************************************************/
6513 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6515 struct tevent_req *req;
6516 struct reply_tdis_state *state;
6517 struct tevent_req *subreq;
6518 connection_struct *conn = smb1req->conn;
6521 req = tevent_req_create(smb1req, &state,
6522 struct reply_tdis_state);
6526 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6527 if (tevent_req_nomem(state->wait_queue, req)) {
6533 * Make sure that no new request will be able to use this tcon.
6534 * This ensures that once all outstanding fsp->aio_requests
6535 * on this tcon are done, we are safe to close it.
6537 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6539 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6540 if (fsp->conn != conn) {
6544 * Flag the file as close in progress.
6545 * This will prevent any more IO being
6546 * done on it. Not strictly needed, but
6547 * doesn't hurt to flag it as closing.
6549 fsp->fsp_flags.closing = true;
6551 if (fsp->num_aio_requests > 0) {
6553 * Now wait until all aio requests on this fsp are
6556 * We don't set a callback, as we just want to block the
6557 * wait queue and the talloc_free() of fsp->aio_request
6558 * will remove the item from the wait queue.
6560 subreq = tevent_queue_wait_send(fsp->aio_requests,
6561 conn->sconn->ev_ctx,
6563 if (tevent_req_nomem(subreq, req)) {
6571 * Now we add our own waiter to the end of the queue,
6572 * this way we get notified when all pending requests are finished
6573 * and reply to the outstanding SMB1 request.
6575 subreq = tevent_queue_wait_send(state,
6576 conn->sconn->ev_ctx,
6578 if (tevent_req_nomem(subreq, req)) {
6584 * We're really going async - move the SMB1 request from
6585 * a talloc stackframe above us to the sconn talloc-context.
6586 * We need this to stick around until the wait_done
6587 * callback is invoked.
6589 smb1req = talloc_move(smb1req->sconn, &smb1req);
6591 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6596 static void reply_tdis_wait_done(struct tevent_req *subreq)
6598 struct tevent_req *req = tevent_req_callback_data(
6599 subreq, struct tevent_req);
6601 tevent_queue_wait_recv(subreq);
6602 TALLOC_FREE(subreq);
6603 tevent_req_done(req);
6606 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6608 return tevent_req_simple_recv_ntstatus(req);
6611 static void reply_tdis_done(struct tevent_req *req)
6613 struct smb_request *smb1req = tevent_req_callback_data(
6614 req, struct smb_request);
6616 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6620 * Take the profile charge here. Not strictly
6621 * correct but better than the other SMB1 async
6622 * code that double-charges at the moment.
6624 START_PROFILE(SMBtdis);
6626 status = reply_tdis_recv(req);
6628 if (!NT_STATUS_IS_OK(status)) {
6629 TALLOC_FREE(smb1req);
6630 END_PROFILE(SMBtdis);
6631 exit_server(__location__ ": reply_tdis_recv failed");
6636 * As we've been awoken, we may have changed
6637 * directory in the meantime.
6638 * reply_tdis() has the DO_CHDIR flag set.
6640 ok = chdir_current_service(smb1req->conn);
6642 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6643 smb_request_done(smb1req);
6644 END_PROFILE(SMBtdis);
6647 status = smbXsrv_tcon_disconnect(tcon,
6649 if (!NT_STATUS_IS_OK(status)) {
6650 TALLOC_FREE(smb1req);
6651 END_PROFILE(SMBtdis);
6652 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6656 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6657 smb1req->conn = NULL;
6661 reply_outbuf(smb1req, 0, 0);
6663 * The following call is needed to push the
6664 * reply data back out the socket after async
6665 * return. Plus it frees smb1req.
6667 smb_request_done(smb1req);
6668 END_PROFILE(SMBtdis);
6671 /****************************************************************************
6673 conn POINTER CAN BE NULL HERE !
6674 ****************************************************************************/
6676 void reply_echo(struct smb_request *req)
6678 connection_struct *conn = req->conn;
6679 struct smb_perfcount_data local_pcd;
6680 struct smb_perfcount_data *cur_pcd;
6684 START_PROFILE(SMBecho);
6686 smb_init_perfcount_data(&local_pcd);
6689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6690 END_PROFILE(SMBecho);
6694 smb_reverb = SVAL(req->vwv+0, 0);
6696 reply_outbuf(req, 1, req->buflen);
6698 /* copy any incoming data back out */
6699 if (req->buflen > 0) {
6700 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6703 if (smb_reverb > 100) {
6704 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6708 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6710 /* this makes sure we catch the request pcd */
6711 if (seq_num == smb_reverb) {
6712 cur_pcd = &req->pcd;
6714 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6715 cur_pcd = &local_pcd;
6718 SSVAL(req->outbuf,smb_vwv0,seq_num);
6720 show_msg((char *)req->outbuf);
6721 if (!srv_send_smb(req->xconn,
6722 (char *)req->outbuf,
6723 true, req->seqnum+1,
6724 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6726 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6729 DEBUG(3,("echo %d times\n", smb_reverb));
6731 TALLOC_FREE(req->outbuf);
6733 END_PROFILE(SMBecho);
6737 /****************************************************************************
6738 Reply to a printopen.
6739 ****************************************************************************/
6741 void reply_printopen(struct smb_request *req)
6743 connection_struct *conn = req->conn;
6747 START_PROFILE(SMBsplopen);
6750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6751 END_PROFILE(SMBsplopen);
6755 if (!CAN_PRINT(conn)) {
6756 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6757 END_PROFILE(SMBsplopen);
6761 status = file_new(req, conn, &fsp);
6762 if(!NT_STATUS_IS_OK(status)) {
6763 reply_nterror(req, status);
6764 END_PROFILE(SMBsplopen);
6768 /* Open for exclusive use, write only. */
6769 status = print_spool_open(fsp, NULL, req->vuid);
6771 if (!NT_STATUS_IS_OK(status)) {
6772 file_free(req, fsp);
6773 reply_nterror(req, status);
6774 END_PROFILE(SMBsplopen);
6778 reply_outbuf(req, 1, 0);
6779 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6781 DEBUG(3,("openprint fd=%d %s\n",
6782 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6784 END_PROFILE(SMBsplopen);
6788 /****************************************************************************
6789 Reply to a printclose.
6790 ****************************************************************************/
6792 void reply_printclose(struct smb_request *req)
6794 connection_struct *conn = req->conn;
6798 START_PROFILE(SMBsplclose);
6801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6802 END_PROFILE(SMBsplclose);
6806 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6808 if (!check_fsp(conn, req, fsp)) {
6809 END_PROFILE(SMBsplclose);
6813 if (!CAN_PRINT(conn)) {
6814 reply_force_doserror(req, ERRSRV, ERRerror);
6815 END_PROFILE(SMBsplclose);
6819 DEBUG(3,("printclose fd=%d %s\n",
6820 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6822 status = close_file(req, fsp, NORMAL_CLOSE);
6824 if(!NT_STATUS_IS_OK(status)) {
6825 reply_nterror(req, status);
6826 END_PROFILE(SMBsplclose);
6830 reply_outbuf(req, 0, 0);
6832 END_PROFILE(SMBsplclose);
6836 /****************************************************************************
6837 Reply to a printqueue.
6838 ****************************************************************************/
6840 void reply_printqueue(struct smb_request *req)
6842 const struct loadparm_substitution *lp_sub =
6843 loadparm_s3_global_substitution();
6844 connection_struct *conn = req->conn;
6848 START_PROFILE(SMBsplretq);
6851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6852 END_PROFILE(SMBsplretq);
6856 max_count = SVAL(req->vwv+0, 0);
6857 start_index = SVAL(req->vwv+1, 0);
6859 /* we used to allow the client to get the cnum wrong, but that
6860 is really quite gross and only worked when there was only
6861 one printer - I think we should now only accept it if they
6862 get it right (tridge) */
6863 if (!CAN_PRINT(conn)) {
6864 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6865 END_PROFILE(SMBsplretq);
6869 reply_outbuf(req, 2, 3);
6870 SSVAL(req->outbuf,smb_vwv0,0);
6871 SSVAL(req->outbuf,smb_vwv1,0);
6872 SCVAL(smb_buf(req->outbuf),0,1);
6873 SSVAL(smb_buf(req->outbuf),1,0);
6875 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6876 start_index, max_count));
6879 TALLOC_CTX *mem_ctx = talloc_tos();
6882 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6883 struct rpc_pipe_client *cli = NULL;
6884 struct dcerpc_binding_handle *b = NULL;
6885 struct policy_handle handle;
6886 struct spoolss_DevmodeContainer devmode_ctr;
6887 union spoolss_JobInfo *info;
6889 uint32_t num_to_get;
6893 ZERO_STRUCT(handle);
6895 status = rpc_pipe_open_interface(mem_ctx,
6898 conn->sconn->remote_address,
6899 conn->sconn->local_address,
6900 conn->sconn->msg_ctx,
6902 if (!NT_STATUS_IS_OK(status)) {
6903 DEBUG(0, ("reply_printqueue: "
6904 "could not connect to spoolss: %s\n",
6905 nt_errstr(status)));
6906 reply_nterror(req, status);
6909 b = cli->binding_handle;
6911 ZERO_STRUCT(devmode_ctr);
6913 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6916 SEC_FLAG_MAXIMUM_ALLOWED,
6919 if (!NT_STATUS_IS_OK(status)) {
6920 reply_nterror(req, status);
6923 if (!W_ERROR_IS_OK(werr)) {
6924 reply_nterror(req, werror_to_ntstatus(werr));
6928 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6936 if (!W_ERROR_IS_OK(werr)) {
6937 reply_nterror(req, werror_to_ntstatus(werr));
6941 if (max_count > 0) {
6942 first = start_index;
6944 first = start_index + max_count + 1;
6947 if (first >= count) {
6950 num_to_get = first + MIN(ABS(max_count), count - first);
6953 for (i = first; i < num_to_get; i++) {
6956 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6959 uint16_t qrapjobid = pjobid_to_rap(sharename,
6960 info[i].info2.job_id);
6962 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6968 srv_put_dos_date2(p, 0, qtime);
6969 SCVAL(p, 4, qstatus);
6970 SSVAL(p, 5, qrapjobid);
6971 SIVAL(p, 7, info[i].info2.size);
6973 status = srvstr_push(blob, req->flags2, p+12,
6974 info[i].info2.notify_name, 16, STR_ASCII, &len);
6975 if (!NT_STATUS_IS_OK(status)) {
6976 reply_nterror(req, status);
6979 if (message_push_blob(
6982 blob, sizeof(blob))) == -1) {
6983 reply_nterror(req, NT_STATUS_NO_MEMORY);
6989 SSVAL(req->outbuf,smb_vwv0,count);
6990 SSVAL(req->outbuf,smb_vwv1,
6991 (max_count>0?first+count:first-1));
6992 SCVAL(smb_buf(req->outbuf),0,1);
6993 SSVAL(smb_buf(req->outbuf),1,28*count);
6997 DEBUG(3, ("%u entries returned in queue\n",
7001 if (b && is_valid_policy_hnd(&handle)) {
7002 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
7007 END_PROFILE(SMBsplretq);
7011 /****************************************************************************
7012 Reply to a printwrite.
7013 ****************************************************************************/
7015 void reply_printwrite(struct smb_request *req)
7017 connection_struct *conn = req->conn;
7022 START_PROFILE(SMBsplwr);
7025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7026 END_PROFILE(SMBsplwr);
7030 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7032 if (!check_fsp(conn, req, fsp)) {
7033 END_PROFILE(SMBsplwr);
7037 if (!fsp->print_file) {
7038 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7039 END_PROFILE(SMBsplwr);
7043 if (!CHECK_WRITE(fsp)) {
7044 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7045 END_PROFILE(SMBsplwr);
7049 numtowrite = SVAL(req->buf, 1);
7052 * This already protects us against CVE-2017-12163.
7054 if (req->buflen < numtowrite + 3) {
7055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7056 END_PROFILE(SMBsplwr);
7060 data = (const char *)req->buf + 3;
7062 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7063 reply_nterror(req, map_nt_error_from_unix(errno));
7064 END_PROFILE(SMBsplwr);
7068 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
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,
7103 if (!NT_STATUS_IS_OK(status)) {
7104 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7105 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7106 ERRSRV, ERRbadpath);
7109 reply_nterror(req, status);
7113 status = create_directory(conn, req, smb_dname);
7115 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7117 if (!NT_STATUS_IS_OK(status)) {
7119 if (!use_nt_status()
7120 && NT_STATUS_EQUAL(status,
7121 NT_STATUS_OBJECT_NAME_COLLISION)) {
7123 * Yes, in the DOS error code case we get a
7124 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7125 * samba4 torture test.
7127 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7130 reply_nterror(req, status);
7134 reply_outbuf(req, 0, 0);
7136 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7138 TALLOC_FREE(smb_dname);
7139 END_PROFILE(SMBmkdir);
7143 /****************************************************************************
7145 ****************************************************************************/
7147 void reply_rmdir(struct smb_request *req)
7149 connection_struct *conn = req->conn;
7150 struct smb_filename *smb_dname = NULL;
7151 char *directory = NULL;
7153 TALLOC_CTX *ctx = talloc_tos();
7154 files_struct *fsp = NULL;
7156 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7158 START_PROFILE(SMBrmdir);
7160 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7161 STR_TERMINATE, &status);
7162 if (!NT_STATUS_IS_OK(status)) {
7163 reply_nterror(req, status);
7167 status = filename_convert(ctx, conn,
7173 if (!NT_STATUS_IS_OK(status)) {
7174 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7175 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7176 ERRSRV, ERRbadpath);
7179 reply_nterror(req, status);
7183 if (is_ntfs_stream_smb_fname(smb_dname)) {
7184 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7188 status = SMB_VFS_CREATE_FILE(
7191 &conn->cwd_fsp, /* dirfsp */
7192 smb_dname, /* fname */
7193 DELETE_ACCESS, /* access_mask */
7194 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7196 FILE_OPEN, /* create_disposition*/
7197 FILE_DIRECTORY_FILE, /* create_options */
7198 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7199 0, /* oplock_request */
7201 0, /* allocation_size */
7202 0, /* private_flags */
7207 NULL, NULL); /* create context */
7209 if (!NT_STATUS_IS_OK(status)) {
7210 if (open_was_deferred(req->xconn, req->mid)) {
7211 /* We have re-scheduled this call. */
7214 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7215 bool ok = defer_smb1_sharing_violation(req);
7220 reply_nterror(req, status);
7224 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7225 if (!NT_STATUS_IS_OK(status)) {
7226 close_file(req, fsp, ERROR_CLOSE);
7227 reply_nterror(req, status);
7231 if (!set_delete_on_close(fsp, true,
7232 conn->session_info->security_token,
7233 conn->session_info->unix_token)) {
7234 close_file(req, fsp, ERROR_CLOSE);
7235 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7239 status = close_file(req, fsp, NORMAL_CLOSE);
7240 if (!NT_STATUS_IS_OK(status)) {
7241 reply_nterror(req, status);
7243 reply_outbuf(req, 0, 0);
7246 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7248 TALLOC_FREE(smb_dname);
7249 END_PROFILE(SMBrmdir);
7253 /*******************************************************************
7254 Resolve wildcards in a filename rename.
7255 ********************************************************************/
7257 static bool resolve_wildcards(TALLOC_CTX *ctx,
7262 char *name2_copy = NULL;
7267 char *p,*p2, *pname1, *pname2;
7269 name2_copy = talloc_strdup(ctx, name2);
7274 pname1 = strrchr_m(name1,'/');
7275 pname2 = strrchr_m(name2_copy,'/');
7277 if (!pname1 || !pname2) {
7281 /* Truncate the copy of name2 at the last '/' */
7284 /* Now go past the '/' */
7288 root1 = talloc_strdup(ctx, pname1);
7289 root2 = talloc_strdup(ctx, pname2);
7291 if (!root1 || !root2) {
7295 p = strrchr_m(root1,'.');
7298 ext1 = talloc_strdup(ctx, p+1);
7300 ext1 = talloc_strdup(ctx, "");
7302 p = strrchr_m(root2,'.');
7305 ext2 = talloc_strdup(ctx, p+1);
7307 ext2 = talloc_strdup(ctx, "");
7310 if (!ext1 || !ext2) {
7318 /* Hmmm. Should this be mb-aware ? */
7321 } else if (*p2 == '*') {
7323 root2 = talloc_asprintf(ctx, "%s%s",
7342 /* Hmmm. Should this be mb-aware ? */
7345 } else if (*p2 == '*') {
7347 ext2 = talloc_asprintf(ctx, "%s%s",
7363 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7368 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7380 /****************************************************************************
7381 Ensure open files have their names updated. Updated to notify other smbd's
7383 ****************************************************************************/
7385 static void rename_open_files(connection_struct *conn,
7386 struct share_mode_lock *lck,
7388 uint32_t orig_name_hash,
7389 const struct smb_filename *smb_fname_dst)
7392 bool did_rename = False;
7394 uint32_t new_name_hash = 0;
7396 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7397 fsp = file_find_di_next(fsp)) {
7398 struct file_id_buf idbuf;
7399 /* fsp_name is a relative path under the fsp. To change this for other
7400 sharepaths we need to manipulate relative paths. */
7401 /* TODO - create the absolute path and manipulate the newname
7402 relative to the sharepath. */
7403 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7406 if (fsp->name_hash != orig_name_hash) {
7409 DBG_DEBUG("renaming file %s "
7410 "(file_id %s) from %s -> %s\n",
7412 file_id_str_buf(fsp->file_id, &idbuf),
7414 smb_fname_str_dbg(smb_fname_dst));
7416 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7417 if (NT_STATUS_IS_OK(status)) {
7419 new_name_hash = fsp->name_hash;
7424 struct file_id_buf idbuf;
7425 DBG_DEBUG("no open files on file_id %s "
7427 file_id_str_buf(id, &idbuf),
7428 smb_fname_str_dbg(smb_fname_dst));
7431 /* Send messages to all smbd's (not ourself) that the name has changed. */
7432 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7433 orig_name_hash, new_name_hash,
7438 /****************************************************************************
7439 We need to check if the source path is a parent directory of the destination
7440 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7441 refuse the rename with a sharing violation. Under UNIX the above call can
7442 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7443 probably need to check that the client is a Windows one before disallowing
7444 this as a UNIX client (one with UNIX extensions) can know the source is a
7445 symlink and make this decision intelligently. Found by an excellent bug
7446 report from <AndyLiebman@aol.com>.
7447 ****************************************************************************/
7449 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7450 const struct smb_filename *smb_fname_dst)
7452 const char *psrc = smb_fname_src->base_name;
7453 const char *pdst = smb_fname_dst->base_name;
7456 if (psrc[0] == '.' && psrc[1] == '/') {
7459 if (pdst[0] == '.' && pdst[1] == '/') {
7462 if ((slen = strlen(psrc)) > strlen(pdst)) {
7465 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7469 * Do the notify calls from a rename
7472 static void notify_rename(connection_struct *conn, bool is_dir,
7473 const struct smb_filename *smb_fname_src,
7474 const struct smb_filename *smb_fname_dst)
7476 char *parent_dir_src = NULL;
7477 char *parent_dir_dst = NULL;
7480 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7481 : FILE_NOTIFY_CHANGE_FILE_NAME;
7483 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7484 &parent_dir_src, NULL) ||
7485 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7486 &parent_dir_dst, NULL)) {
7490 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7491 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7492 smb_fname_src->base_name);
7493 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7494 smb_fname_dst->base_name);
7497 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7498 smb_fname_src->base_name);
7499 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7500 smb_fname_dst->base_name);
7503 /* this is a strange one. w2k3 gives an additional event for
7504 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7505 files, but not directories */
7507 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7508 FILE_NOTIFY_CHANGE_ATTRIBUTES
7509 |FILE_NOTIFY_CHANGE_CREATION,
7510 smb_fname_dst->base_name);
7513 TALLOC_FREE(parent_dir_src);
7514 TALLOC_FREE(parent_dir_dst);
7517 /****************************************************************************
7518 Returns an error if the parent directory for a filename is open in an
7520 ****************************************************************************/
7522 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7523 const struct smb_filename *smb_fname_dst_in)
7525 struct smb_filename *smb_fname_parent = NULL;
7527 files_struct *fsp = NULL;
7531 ok = parent_smb_fname(talloc_tos(),
7536 return NT_STATUS_NO_MEMORY;
7539 ret = SMB_VFS_LSTAT(conn, smb_fname_parent);
7541 return map_nt_error_from_unix(errno);
7545 * We're only checking on this smbd here, mostly good
7546 * enough.. and will pass tests.
7549 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
7550 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7551 fsp = file_find_di_next(fsp)) {
7552 if (fsp->access_mask & DELETE_ACCESS) {
7553 return NT_STATUS_SHARING_VIOLATION;
7556 return NT_STATUS_OK;
7559 /****************************************************************************
7560 Rename an open file - given an fsp.
7561 ****************************************************************************/
7563 NTSTATUS rename_internals_fsp(connection_struct *conn,
7565 const struct smb_filename *smb_fname_dst_in,
7566 const char *dst_original_lcomp,
7568 bool replace_if_exists)
7570 TALLOC_CTX *ctx = talloc_tos();
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 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7747 &smb_fname_dst->st);
7748 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7750 /* The file can be open when renaming a stream */
7751 if (dst_fsp && !new_is_stream) {
7752 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7753 status = NT_STATUS_ACCESS_DENIED;
7758 /* Ensure we have a valid stat struct for the source. */
7759 status = vfs_stat_fsp(fsp);
7760 if (!NT_STATUS_IS_OK(status)) {
7764 status = can_rename(conn, fsp, attrs);
7766 if (!NT_STATUS_IS_OK(status)) {
7767 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7768 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7769 smb_fname_str_dbg(smb_fname_dst)));
7770 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7771 status = NT_STATUS_ACCESS_DENIED;
7775 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7776 status = NT_STATUS_ACCESS_DENIED;
7780 /* Do we have rights to move into the destination ? */
7781 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7782 /* We're moving a directory. */
7783 access_mask = SEC_DIR_ADD_SUBDIR;
7785 status = check_parent_access(conn,
7789 if (!NT_STATUS_IS_OK(status)) {
7790 DBG_INFO("check_parent_access on "
7791 "dst %s returned %s\n",
7792 smb_fname_str_dbg(smb_fname_dst),
7797 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7800 * We have the file open ourselves, so not being able to get the
7801 * corresponding share mode lock is a fatal error.
7804 SMB_ASSERT(lck != NULL);
7806 ret = SMB_VFS_RENAMEAT(conn,
7812 uint32_t create_options = fsp->fh->private_options;
7814 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7815 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7816 smb_fname_str_dbg(smb_fname_dst)));
7818 if (!fsp->fsp_flags.is_directory &&
7819 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7820 (lp_map_archive(SNUM(conn)) ||
7821 lp_store_dos_attributes(SNUM(conn)))) {
7822 /* We must set the archive bit on the newly
7824 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7825 uint32_t old_dosmode = dos_mode(conn,
7827 file_set_dosmode(conn,
7829 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7836 fsp->fsp_flags.is_directory,
7840 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7844 * A rename acts as a new file create w.r.t. allowing an initial delete
7845 * on close, probably because in Windows there is a new handle to the
7846 * new file. If initial delete on close was requested but not
7847 * originally set, we need to set it here. This is probably not 100% correct,
7848 * but will work for the CIFSFS client which in non-posix mode
7849 * depends on these semantics. JRA.
7852 if (create_options & FILE_DELETE_ON_CLOSE) {
7853 status = can_set_delete_on_close(fsp, 0);
7855 if (NT_STATUS_IS_OK(status)) {
7856 /* Note that here we set the *initial* delete on close flag,
7857 * not the regular one. The magic gets handled in close. */
7858 fsp->fsp_flags.initial_delete_on_close = true;
7862 status = NT_STATUS_OK;
7868 if (errno == ENOTDIR || errno == EISDIR) {
7869 status = NT_STATUS_OBJECT_NAME_COLLISION;
7871 status = map_nt_error_from_unix(errno);
7874 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7875 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7876 smb_fname_str_dbg(smb_fname_dst)));
7879 TALLOC_FREE(smb_fname_dst);
7884 /****************************************************************************
7885 The guts of the rename command, split out so it may be called by the NT SMB
7887 ****************************************************************************/
7889 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7890 connection_struct *conn,
7891 struct smb_request *req,
7892 struct smb_filename *smb_fname_src,
7893 struct smb_filename *smb_fname_dst,
7894 const char *dst_original_lcomp,
7896 bool replace_if_exists,
7897 uint32_t access_mask)
7899 char *fname_src_dir = NULL;
7900 struct smb_filename *smb_fname_src_dir = NULL;
7901 char *fname_src_mask = NULL;
7903 NTSTATUS status = NT_STATUS_OK;
7904 struct smb_Dir *dir_hnd = NULL;
7905 const char *dname = NULL;
7906 char *talloced = NULL;
7908 int create_options = 0;
7909 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7910 struct smb2_create_blobs *posx = NULL;
7912 bool src_has_wild = false;
7913 bool dest_has_wild = false;
7916 * Split the old name into directory and last component
7917 * strings. Note that unix_convert may have stripped off a
7918 * leading ./ from both name and newname if the rename is
7919 * at the root of the share. We need to make sure either both
7920 * name and newname contain a / character or neither of them do
7921 * as this is checked in resolve_wildcards().
7924 /* Split up the directory from the filename/mask. */
7925 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7926 &fname_src_dir, &fname_src_mask);
7927 if (!NT_STATUS_IS_OK(status)) {
7928 status = NT_STATUS_NO_MEMORY;
7932 if (req != NULL && !req->posix_pathnames) {
7934 * Check the wildcard mask *before*
7935 * unmangling. As mangling is done
7936 * for names that can't be returned
7937 * to Windows the unmangled name may
7938 * contain Windows wildcard characters.
7940 src_has_wild = ms_has_wild(fname_src_mask);
7941 dest_has_wild = ms_has_wild(dst_original_lcomp);
7945 * We should only check the mangled cache
7946 * here if unix_convert failed. This means
7947 * that the path in 'mask' doesn't exist
7948 * on the file system and so we need to look
7949 * for a possible mangle. This patch from
7950 * Tine Smukavec <valentin.smukavec@hermes.si>.
7953 if (!VALID_STAT(smb_fname_src->st) &&
7954 mangle_is_mangled(fname_src_mask, conn->params)) {
7955 char *new_mask = NULL;
7956 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7959 TALLOC_FREE(fname_src_mask);
7960 fname_src_mask = new_mask;
7964 if (posix_pathnames) {
7965 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
7966 if (!NT_STATUS_IS_OK(status)) {
7967 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7973 if (!src_has_wild) {
7977 * Only one file needs to be renamed. Append the mask back
7978 * onto the directory.
7980 TALLOC_FREE(smb_fname_src->base_name);
7981 if (ISDOT(fname_src_dir)) {
7982 /* Ensure we use canonical names on open. */
7983 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7987 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7992 if (!smb_fname_src->base_name) {
7993 status = NT_STATUS_NO_MEMORY;
7997 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7998 "case_preserve = %d, short case preserve = %d, "
7999 "directory = %s, newname = %s, "
8000 "last_component_dest = %s\n",
8001 conn->case_sensitive, conn->case_preserve,
8002 conn->short_case_preserve,
8003 smb_fname_str_dbg(smb_fname_src),
8004 smb_fname_str_dbg(smb_fname_dst),
8005 dst_original_lcomp));
8007 /* The dest name still may have wildcards. */
8008 if (dest_has_wild) {
8009 char *fname_dst_mod = NULL;
8010 if (!resolve_wildcards(smb_fname_dst,
8011 smb_fname_src->base_name,
8012 smb_fname_dst->base_name,
8014 DEBUG(6, ("rename_internals: resolve_wildcards "
8016 smb_fname_src->base_name,
8017 smb_fname_dst->base_name));
8018 status = NT_STATUS_NO_MEMORY;
8021 TALLOC_FREE(smb_fname_dst->base_name);
8022 smb_fname_dst->base_name = fname_dst_mod;
8025 ZERO_STRUCT(smb_fname_src->st);
8026 if (posix_pathnames) {
8027 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
8029 rc = SMB_VFS_STAT(conn, smb_fname_src);
8032 status = map_nt_error_from_unix_common(errno);
8036 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8037 create_options |= FILE_DIRECTORY_FILE;
8040 status = SMB_VFS_CREATE_FILE(
8043 &conn->cwd_fsp, /* dirfsp */
8044 smb_fname_src, /* fname */
8045 access_mask, /* access_mask */
8046 (FILE_SHARE_READ | /* share_access */
8048 FILE_OPEN, /* create_disposition*/
8049 create_options, /* create_options */
8050 0, /* file_attributes */
8051 0, /* oplock_request */
8053 0, /* allocation_size */
8054 0, /* private_flags */
8059 posx, /* in_context_blobs */
8060 NULL); /* out_context_blobs */
8062 if (!NT_STATUS_IS_OK(status)) {
8063 DEBUG(3, ("Could not open rename source %s: %s\n",
8064 smb_fname_str_dbg(smb_fname_src),
8065 nt_errstr(status)));
8069 status = rename_internals_fsp(conn,
8076 close_file(req, fsp, NORMAL_CLOSE);
8078 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8079 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
8080 smb_fname_str_dbg(smb_fname_dst)));
8086 * Wildcards - process each file that matches.
8088 if (strequal(fname_src_mask, "????????.???")) {
8089 TALLOC_FREE(fname_src_mask);
8090 fname_src_mask = talloc_strdup(ctx, "*");
8091 if (!fname_src_mask) {
8092 status = NT_STATUS_NO_MEMORY;
8097 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8101 smb_fname_src->twrp,
8102 smb_fname_src->flags);
8103 if (smb_fname_src_dir == NULL) {
8104 status = NT_STATUS_NO_MEMORY;
8108 status = check_name(conn, smb_fname_src_dir);
8109 if (!NT_STATUS_IS_OK(status)) {
8113 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8115 if (dir_hnd == NULL) {
8116 status = map_nt_error_from_unix(errno);
8120 status = NT_STATUS_NO_SUCH_FILE;
8122 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8123 * - gentest fix. JRA
8126 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8128 files_struct *fsp = NULL;
8129 char *destname = NULL;
8130 bool sysdir_entry = False;
8132 /* Quick check for "." and ".." */
8133 if (ISDOT(dname) || ISDOTDOT(dname)) {
8134 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8135 sysdir_entry = True;
8137 TALLOC_FREE(talloced);
8142 if (!is_visible_file(conn,
8147 TALLOC_FREE(talloced);
8151 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8152 TALLOC_FREE(talloced);
8157 status = NT_STATUS_OBJECT_NAME_INVALID;
8161 TALLOC_FREE(smb_fname_src->base_name);
8162 if (ISDOT(fname_src_dir)) {
8163 /* Ensure we use canonical names on open. */
8164 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8168 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8173 if (!smb_fname_src->base_name) {
8174 status = NT_STATUS_NO_MEMORY;
8178 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8179 smb_fname_dst->base_name,
8181 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8182 smb_fname_src->base_name, destname));
8183 TALLOC_FREE(talloced);
8187 status = NT_STATUS_NO_MEMORY;
8191 TALLOC_FREE(smb_fname_dst->base_name);
8192 smb_fname_dst->base_name = destname;
8194 ZERO_STRUCT(smb_fname_src->st);
8195 if (posix_pathnames) {
8196 SMB_VFS_LSTAT(conn, smb_fname_src);
8198 SMB_VFS_STAT(conn, smb_fname_src);
8203 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8204 create_options |= FILE_DIRECTORY_FILE;
8207 status = SMB_VFS_CREATE_FILE(
8210 &conn->cwd_fsp, /* dirfsp */
8211 smb_fname_src, /* fname */
8212 access_mask, /* access_mask */
8213 (FILE_SHARE_READ | /* share_access */
8215 FILE_OPEN, /* create_disposition*/
8216 create_options, /* create_options */
8217 0, /* file_attributes */
8218 0, /* oplock_request */
8220 0, /* allocation_size */
8221 0, /* private_flags */
8226 posx, /* in_context_blobs */
8227 NULL); /* out_context_blobs */
8229 if (!NT_STATUS_IS_OK(status)) {
8230 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8231 "returned %s rename %s -> %s\n",
8233 smb_fname_str_dbg(smb_fname_src),
8234 smb_fname_str_dbg(smb_fname_dst)));
8238 dst_original_lcomp = talloc_strdup(smb_fname_dst, dname);
8239 if (dst_original_lcomp == NULL) {
8240 status = NT_STATUS_NO_MEMORY;
8244 status = rename_internals_fsp(conn,
8251 close_file(req, fsp, NORMAL_CLOSE);
8253 if (!NT_STATUS_IS_OK(status)) {
8254 DEBUG(3, ("rename_internals_fsp returned %s for "
8255 "rename %s -> %s\n", nt_errstr(status),
8256 smb_fname_str_dbg(smb_fname_src),
8257 smb_fname_str_dbg(smb_fname_dst)));
8263 DEBUG(3,("rename_internals: doing rename on %s -> "
8264 "%s\n", smb_fname_str_dbg(smb_fname_src),
8265 smb_fname_str_dbg(smb_fname_src)));
8266 TALLOC_FREE(talloced);
8268 TALLOC_FREE(dir_hnd);
8270 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8271 status = map_nt_error_from_unix(errno);
8276 TALLOC_FREE(talloced);
8277 TALLOC_FREE(smb_fname_src_dir);
8278 TALLOC_FREE(fname_src_dir);
8279 TALLOC_FREE(fname_src_mask);
8283 /****************************************************************************
8285 ****************************************************************************/
8287 void reply_mv(struct smb_request *req)
8289 connection_struct *conn = req->conn;
8291 char *newname = NULL;
8295 TALLOC_CTX *ctx = talloc_tos();
8296 struct smb_filename *smb_fname_src = NULL;
8297 struct smb_filename *smb_fname_dst = NULL;
8298 const char *dst_original_lcomp = NULL;
8299 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8300 (req->posix_pathnames ?
8301 UCF_UNIX_NAME_LOOKUP :
8302 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8303 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8304 (req->posix_pathnames ?
8306 UCF_ALWAYS_ALLOW_WCARD_LCOMP);
8307 bool stream_rename = false;
8309 START_PROFILE(SMBmv);
8312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8316 attrs = SVAL(req->vwv+0, 0);
8318 p = (const char *)req->buf + 1;
8319 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
8321 if (!NT_STATUS_IS_OK(status)) {
8322 reply_nterror(req, status);
8326 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
8328 if (!NT_STATUS_IS_OK(status)) {
8329 reply_nterror(req, status);
8333 if (!req->posix_pathnames) {
8334 /* The newname must begin with a ':' if the
8335 name contains a ':'. */
8336 if (strchr_m(name, ':')) {
8337 if (newname[0] != ':') {
8338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8341 stream_rename = true;
8345 status = filename_convert(ctx,
8353 if (!NT_STATUS_IS_OK(status)) {
8354 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8355 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8356 ERRSRV, ERRbadpath);
8359 reply_nterror(req, status);
8363 status = filename_convert(ctx,
8371 if (!NT_STATUS_IS_OK(status)) {
8372 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8373 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8374 ERRSRV, ERRbadpath);
8377 reply_nterror(req, status);
8381 /* Get the last component of the destination for rename_internals(). */
8382 dst_original_lcomp = get_original_lcomp(ctx,
8386 if (dst_original_lcomp == NULL) {
8387 reply_nterror(req, NT_STATUS_NO_MEMORY);
8391 if (stream_rename) {
8392 /* smb_fname_dst->base_name must be the same as
8393 smb_fname_src->base_name. */
8394 TALLOC_FREE(smb_fname_dst->base_name);
8395 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8396 smb_fname_src->base_name);
8397 if (!smb_fname_dst->base_name) {
8398 reply_nterror(req, NT_STATUS_NO_MEMORY);
8403 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8404 smb_fname_str_dbg(smb_fname_dst)));
8406 status = rename_internals(ctx,
8415 if (!NT_STATUS_IS_OK(status)) {
8416 if (open_was_deferred(req->xconn, req->mid)) {
8417 /* We have re-scheduled this call. */
8420 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8421 bool ok = defer_smb1_sharing_violation(req);
8426 reply_nterror(req, status);
8430 reply_outbuf(req, 0, 0);
8432 TALLOC_FREE(smb_fname_src);
8433 TALLOC_FREE(smb_fname_dst);
8438 /*******************************************************************
8439 Copy a file as part of a reply_copy.
8440 ******************************************************************/
8443 * TODO: check error codes on all callers
8446 NTSTATUS copy_file(TALLOC_CTX *ctx,
8447 connection_struct *conn,
8448 struct smb_filename *smb_fname_src,
8449 struct smb_filename *smb_fname_dst,
8452 bool target_is_directory)
8454 struct smb_filename *smb_fname_dst_tmp = NULL;
8456 files_struct *fsp1,*fsp2;
8458 uint32_t new_create_disposition;
8462 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8463 if (smb_fname_dst_tmp == NULL) {
8464 return NT_STATUS_NO_MEMORY;
8468 * If the target is a directory, extract the last component from the
8469 * src filename and append it to the dst filename
8471 if (target_is_directory) {
8474 /* dest/target can't be a stream if it's a directory. */
8475 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8477 p = strrchr_m(smb_fname_src->base_name,'/');
8481 p = smb_fname_src->base_name;
8483 smb_fname_dst_tmp->base_name =
8484 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8486 if (!smb_fname_dst_tmp->base_name) {
8487 status = NT_STATUS_NO_MEMORY;
8492 status = vfs_file_exist(conn, smb_fname_src);
8493 if (!NT_STATUS_IS_OK(status)) {
8497 if (!target_is_directory && count) {
8498 new_create_disposition = FILE_OPEN;
8500 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8503 &new_create_disposition,
8506 status = NT_STATUS_INVALID_PARAMETER;
8511 /* Open the src file for reading. */
8512 status = SMB_VFS_CREATE_FILE(
8515 &conn->cwd_fsp, /* dirfsp */
8516 smb_fname_src, /* fname */
8517 FILE_GENERIC_READ, /* access_mask */
8518 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8519 FILE_OPEN, /* create_disposition*/
8520 0, /* create_options */
8521 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8522 INTERNAL_OPEN_ONLY, /* oplock_request */
8524 0, /* allocation_size */
8525 0, /* private_flags */
8530 NULL, NULL); /* create context */
8532 if (!NT_STATUS_IS_OK(status)) {
8536 dosattrs = dos_mode(conn, smb_fname_src);
8538 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8539 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8542 /* Open the dst file for writing. */
8543 status = SMB_VFS_CREATE_FILE(
8546 &conn->cwd_fsp, /* dirfsp */
8547 smb_fname_dst, /* fname */
8548 FILE_GENERIC_WRITE, /* access_mask */
8549 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8550 new_create_disposition, /* create_disposition*/
8551 0, /* create_options */
8552 dosattrs, /* file_attributes */
8553 INTERNAL_OPEN_ONLY, /* oplock_request */
8555 0, /* allocation_size */
8556 0, /* private_flags */
8561 NULL, NULL); /* create context */
8563 if (!NT_STATUS_IS_OK(status)) {
8564 close_file(NULL, fsp1, ERROR_CLOSE);
8568 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8569 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8571 DEBUG(0, ("error - vfs lseek returned error %s\n",
8573 status = map_nt_error_from_unix(errno);
8574 close_file(NULL, fsp1, ERROR_CLOSE);
8575 close_file(NULL, fsp2, ERROR_CLOSE);
8580 /* Do the actual copy. */
8581 if (smb_fname_src->st.st_ex_size) {
8582 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8587 close_file(NULL, fsp1, NORMAL_CLOSE);
8589 /* Ensure the modtime is set correctly on the destination file. */
8590 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8593 * As we are opening fsp1 read-only we only expect
8594 * an error on close on fsp2 if we are out of space.
8595 * Thus we don't look at the error return from the
8598 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8600 if (!NT_STATUS_IS_OK(status)) {
8604 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8605 status = NT_STATUS_DISK_FULL;
8609 status = NT_STATUS_OK;
8612 TALLOC_FREE(smb_fname_dst_tmp);
8616 /****************************************************************************
8617 Reply to a file copy.
8618 ****************************************************************************/
8620 void reply_copy(struct smb_request *req)
8622 connection_struct *conn = req->conn;
8623 struct smb_filename *smb_fname_src = NULL;
8624 struct smb_filename *smb_fname_src_dir = NULL;
8625 struct smb_filename *smb_fname_dst = NULL;
8626 char *fname_src = NULL;
8627 char *fname_dst = NULL;
8628 char *fname_src_mask = NULL;
8629 char *fname_src_dir = NULL;
8632 int error = ERRnoaccess;
8636 bool target_is_directory=False;
8637 bool source_has_wild = False;
8638 bool dest_has_wild = False;
8640 uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8641 ucf_flags_from_smb_request(req);
8642 uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
8643 ucf_flags_from_smb_request(req);
8644 TALLOC_CTX *ctx = talloc_tos();
8646 START_PROFILE(SMBcopy);
8649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8653 tid2 = SVAL(req->vwv+0, 0);
8654 ofun = SVAL(req->vwv+1, 0);
8655 flags = SVAL(req->vwv+2, 0);
8657 p = (const char *)req->buf;
8658 p += srvstr_get_path_req(ctx, req, &fname_src, p, STR_TERMINATE,
8660 if (!NT_STATUS_IS_OK(status)) {
8661 reply_nterror(req, status);
8664 p += srvstr_get_path_req(ctx, req, &fname_dst, p, STR_TERMINATE,
8666 if (!NT_STATUS_IS_OK(status)) {
8667 reply_nterror(req, status);
8671 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8673 if (tid2 != conn->cnum) {
8674 /* can't currently handle inter share copies XXXX */
8675 DEBUG(3,("Rejecting inter-share copy\n"));
8676 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8680 status = filename_convert(ctx, conn,
8686 if (!NT_STATUS_IS_OK(status)) {
8687 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8688 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8689 ERRSRV, ERRbadpath);
8692 reply_nterror(req, status);
8696 status = filename_convert(ctx, conn,
8702 if (!NT_STATUS_IS_OK(status)) {
8703 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8704 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8705 ERRSRV, ERRbadpath);
8708 reply_nterror(req, status);
8712 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8714 if ((flags&1) && target_is_directory) {
8715 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8719 if ((flags&2) && !target_is_directory) {
8720 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8724 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8725 /* wants a tree copy! XXXX */
8726 DEBUG(3,("Rejecting tree copy\n"));
8727 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8731 /* Split up the directory from the filename/mask. */
8732 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8733 &fname_src_dir, &fname_src_mask);
8734 if (!NT_STATUS_IS_OK(status)) {
8735 reply_nterror(req, NT_STATUS_NO_MEMORY);
8739 if (!req->posix_pathnames) {
8741 * Check the wildcard mask *before*
8742 * unmangling. As mangling is done
8743 * for names that can't be returned
8744 * to Windows the unmangled name may
8745 * contain Windows wildcard characters.
8747 source_has_wild = ms_has_wild(fname_src_mask);
8748 dest_has_wild = ms_has_wild(smb_fname_dst->base_name);
8752 * We should only check the mangled cache
8753 * here if unix_convert failed. This means
8754 * that the path in 'mask' doesn't exist
8755 * on the file system and so we need to look
8756 * for a possible mangle. This patch from
8757 * Tine Smukavec <valentin.smukavec@hermes.si>.
8759 if (!VALID_STAT(smb_fname_src->st) &&
8760 mangle_is_mangled(fname_src_mask, conn->params)) {
8761 char *new_mask = NULL;
8762 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8763 &new_mask, conn->params);
8765 /* Use demangled name if one was successfully found. */
8767 TALLOC_FREE(fname_src_mask);
8768 fname_src_mask = new_mask;
8772 if (!source_has_wild) {
8775 * Only one file needs to be copied. Append the mask back onto
8778 TALLOC_FREE(smb_fname_src->base_name);
8779 if (ISDOT(fname_src_dir)) {
8780 /* Ensure we use canonical names on open. */
8781 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8785 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8790 if (!smb_fname_src->base_name) {
8791 reply_nterror(req, NT_STATUS_NO_MEMORY);
8795 if (dest_has_wild) {
8796 char *fname_dst_mod = NULL;
8797 if (!resolve_wildcards(smb_fname_dst,
8798 smb_fname_src->base_name,
8799 smb_fname_dst->base_name,
8801 reply_nterror(req, NT_STATUS_NO_MEMORY);
8804 TALLOC_FREE(smb_fname_dst->base_name);
8805 smb_fname_dst->base_name = fname_dst_mod;
8808 status = check_name(conn, smb_fname_src);
8809 if (!NT_STATUS_IS_OK(status)) {
8810 reply_nterror(req, status);
8814 status = check_name(conn, smb_fname_dst);
8815 if (!NT_STATUS_IS_OK(status)) {
8816 reply_nterror(req, status);
8820 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8821 ofun, count, target_is_directory);
8823 if(!NT_STATUS_IS_OK(status)) {
8824 reply_nterror(req, status);
8830 struct smb_Dir *dir_hnd = NULL;
8831 const char *dname = NULL;
8832 char *talloced = NULL;
8836 * There is a wildcard that requires us to actually read the
8837 * src dir and copy each file matching the mask to the dst.
8838 * Right now streams won't be copied, but this could
8839 * presumably be added with a nested loop for reach dir entry.
8841 SMB_ASSERT(!smb_fname_src->stream_name);
8842 SMB_ASSERT(!smb_fname_dst->stream_name);
8844 smb_fname_src->stream_name = NULL;
8845 smb_fname_dst->stream_name = NULL;
8847 if (strequal(fname_src_mask,"????????.???")) {
8848 TALLOC_FREE(fname_src_mask);
8849 fname_src_mask = talloc_strdup(ctx, "*");
8850 if (!fname_src_mask) {
8851 reply_nterror(req, NT_STATUS_NO_MEMORY);
8856 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8860 smb_fname_src->twrp,
8861 smb_fname_src->flags);
8862 if (smb_fname_src_dir == NULL) {
8863 reply_nterror(req, NT_STATUS_NO_MEMORY);
8867 status = check_name(conn, smb_fname_src_dir);
8868 if (!NT_STATUS_IS_OK(status)) {
8869 reply_nterror(req, status);
8873 dir_hnd = OpenDir(ctx,
8878 if (dir_hnd == NULL) {
8879 status = map_nt_error_from_unix(errno);
8880 reply_nterror(req, status);
8886 /* Iterate over the src dir copying each entry to the dst. */
8887 while ((dname = ReadDirName(dir_hnd, &offset,
8888 &smb_fname_src->st, &talloced))) {
8889 char *destname = NULL;
8891 if (ISDOT(dname) || ISDOTDOT(dname)) {
8892 TALLOC_FREE(talloced);
8896 if (!is_visible_file(conn,
8901 TALLOC_FREE(talloced);
8905 if(!mask_match(dname, fname_src_mask,
8906 conn->case_sensitive)) {
8907 TALLOC_FREE(talloced);
8911 error = ERRnoaccess;
8913 /* Get the src smb_fname struct setup. */
8914 TALLOC_FREE(smb_fname_src->base_name);
8915 if (ISDOT(fname_src_dir)) {
8916 /* Ensure we use canonical names on open. */
8917 smb_fname_src->base_name =
8918 talloc_asprintf(smb_fname_src, "%s",
8921 smb_fname_src->base_name =
8922 talloc_asprintf(smb_fname_src, "%s/%s",
8923 fname_src_dir, dname);
8926 if (!smb_fname_src->base_name) {
8927 TALLOC_FREE(dir_hnd);
8928 TALLOC_FREE(talloced);
8929 reply_nterror(req, NT_STATUS_NO_MEMORY);
8933 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8934 smb_fname_dst->base_name,
8936 TALLOC_FREE(talloced);
8940 TALLOC_FREE(dir_hnd);
8941 TALLOC_FREE(talloced);
8942 reply_nterror(req, NT_STATUS_NO_MEMORY);
8946 TALLOC_FREE(smb_fname_dst->base_name);
8947 smb_fname_dst->base_name = destname;
8949 status = check_name(conn, smb_fname_src);
8950 if (!NT_STATUS_IS_OK(status)) {
8951 TALLOC_FREE(dir_hnd);
8952 TALLOC_FREE(talloced);
8953 reply_nterror(req, status);
8957 status = check_name(conn, smb_fname_dst);
8958 if (!NT_STATUS_IS_OK(status)) {
8959 TALLOC_FREE(dir_hnd);
8960 TALLOC_FREE(talloced);
8961 reply_nterror(req, status);
8965 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8966 smb_fname_src->base_name,
8967 smb_fname_dst->base_name));
8969 status = copy_file(ctx, conn, smb_fname_src,
8970 smb_fname_dst, ofun, count,
8971 target_is_directory);
8972 if (NT_STATUS_IS_OK(status)) {
8976 TALLOC_FREE(talloced);
8978 TALLOC_FREE(dir_hnd);
8982 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8986 reply_outbuf(req, 1, 0);
8987 SSVAL(req->outbuf,smb_vwv0,count);
8989 TALLOC_FREE(smb_fname_src);
8990 TALLOC_FREE(smb_fname_src_dir);
8991 TALLOC_FREE(smb_fname_dst);
8992 TALLOC_FREE(fname_src);
8993 TALLOC_FREE(fname_dst);
8994 TALLOC_FREE(fname_src_mask);
8995 TALLOC_FREE(fname_src_dir);
8997 END_PROFILE(SMBcopy);
9002 #define DBGC_CLASS DBGC_LOCKING
9004 /****************************************************************************
9005 Get a lock pid, dealing with large count requests.
9006 ****************************************************************************/
9008 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
9009 bool large_file_format)
9011 if(!large_file_format)
9012 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
9014 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
9017 /****************************************************************************
9018 Get a lock count, dealing with large count requests.
9019 ****************************************************************************/
9021 uint64_t get_lock_count(const uint8_t *data, int data_offset,
9022 bool large_file_format)
9026 if(!large_file_format) {
9027 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
9030 * No BVAL, this is reversed!
9032 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
9033 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
9039 /****************************************************************************
9040 Get a lock offset, dealing with large offset requests.
9041 ****************************************************************************/
9043 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
9044 bool large_file_format)
9046 uint64_t offset = 0;
9048 if(!large_file_format) {
9049 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
9052 * No BVAL, this is reversed!
9054 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
9055 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
9061 struct smbd_do_unlocking_state {
9062 struct files_struct *fsp;
9063 uint16_t num_ulocks;
9064 struct smbd_lock_element *ulocks;
9065 enum brl_flavour lock_flav;
9069 static void smbd_do_unlocking_fn(
9072 bool *pmodified_dependent,
9075 struct smbd_do_unlocking_state *state = private_data;
9076 struct files_struct *fsp = state->fsp;
9077 enum brl_flavour lock_flav = state->lock_flav;
9080 for (i = 0; i < state->num_ulocks; i++) {
9081 struct smbd_lock_element *e = &state->ulocks[i];
9083 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
9084 "pid %"PRIu64", file %s\n",
9090 if (e->brltype != UNLOCK_LOCK) {
9091 /* this can only happen with SMB2 */
9092 state->status = NT_STATUS_INVALID_PARAMETER;
9096 state->status = do_unlock(
9097 fsp, e->smblctx, e->count, e->offset, lock_flav);
9099 DBG_DEBUG("do_unlock returned %s\n",
9100 nt_errstr(state->status));
9102 if (!NT_STATUS_IS_OK(state->status)) {
9107 *pmodified_dependent = true;
9110 NTSTATUS smbd_do_unlocking(struct smb_request *req,
9112 uint16_t num_ulocks,
9113 struct smbd_lock_element *ulocks,
9114 enum brl_flavour lock_flav)
9116 struct smbd_do_unlocking_state state = {
9118 .num_ulocks = num_ulocks,
9120 .lock_flav = lock_flav,
9124 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
9126 status = share_mode_do_locked(
9127 fsp->file_id, smbd_do_unlocking_fn, &state);
9129 if (!NT_STATUS_IS_OK(status)) {
9130 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9134 if (!NT_STATUS_IS_OK(state.status)) {
9135 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9137 return state.status;
9140 return NT_STATUS_OK;
9143 /****************************************************************************
9144 Reply to a lockingX request.
9145 ****************************************************************************/
9147 static void reply_lockingx_done(struct tevent_req *subreq);
9149 void reply_lockingX(struct smb_request *req)
9151 connection_struct *conn = req->conn;
9153 unsigned char locktype;
9154 enum brl_type brltype;
9155 unsigned char oplocklevel;
9156 uint16_t num_ulocks;
9158 int32_t lock_timeout;
9160 const uint8_t *data;
9161 bool large_file_format;
9162 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9163 struct smbd_lock_element *locks = NULL;
9164 struct tevent_req *subreq = NULL;
9166 START_PROFILE(SMBlockingX);
9169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9170 END_PROFILE(SMBlockingX);
9174 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9175 locktype = CVAL(req->vwv+3, 0);
9176 oplocklevel = CVAL(req->vwv+3, 1);
9177 num_ulocks = SVAL(req->vwv+6, 0);
9178 num_locks = SVAL(req->vwv+7, 0);
9179 lock_timeout = IVAL(req->vwv+4, 0);
9180 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9182 if (!check_fsp(conn, req, fsp)) {
9183 END_PROFILE(SMBlockingX);
9189 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9190 /* we don't support these - and CANCEL_LOCK makes w2k
9191 and XP reboot so I don't really want to be
9192 compatible! (tridge) */
9193 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9194 END_PROFILE(SMBlockingX);
9198 /* Check if this is an oplock break on a file
9199 we have granted an oplock on.
9201 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9202 /* Client can insist on breaking to none. */
9203 bool break_to_none = (oplocklevel == 0);
9206 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9207 "for %s\n", (unsigned int)oplocklevel,
9208 fsp_fnum_dbg(fsp)));
9211 * Make sure we have granted an exclusive or batch oplock on
9215 if (fsp->oplock_type == 0) {
9217 /* The Samba4 nbench simulator doesn't understand
9218 the difference between break to level2 and break
9219 to none from level2 - it sends oplock break
9220 replies in both cases. Don't keep logging an error
9221 message here - just ignore it. JRA. */
9223 DEBUG(5,("reply_lockingX: Error : oplock break from "
9224 "client for %s (oplock=%d) and no "
9225 "oplock granted on this file (%s).\n",
9226 fsp_fnum_dbg(fsp), fsp->oplock_type,
9229 /* if this is a pure oplock break request then don't
9231 if (num_locks == 0 && num_ulocks == 0) {
9232 END_PROFILE(SMBlockingX);
9236 END_PROFILE(SMBlockingX);
9237 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9241 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9243 result = remove_oplock(fsp);
9245 result = downgrade_oplock(fsp);
9249 DEBUG(0, ("reply_lockingX: error in removing "
9250 "oplock on file %s\n", fsp_str_dbg(fsp)));
9251 /* Hmmm. Is this panic justified? */
9252 smb_panic("internal tdb error");
9255 /* if this is a pure oplock break request then don't send a
9257 if (num_locks == 0 && num_ulocks == 0) {
9258 /* Sanity check - ensure a pure oplock break is not a
9260 if (CVAL(req->vwv+0, 0) != 0xff) {
9261 DEBUG(0,("reply_lockingX: Error : pure oplock "
9262 "break is a chained %d request !\n",
9263 (unsigned int)CVAL(req->vwv+0, 0)));
9265 END_PROFILE(SMBlockingX);
9271 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9273 END_PROFILE(SMBlockingX);
9277 if (num_ulocks != 0) {
9278 struct smbd_lock_element *ulocks = NULL;
9281 ulocks = talloc_array(
9282 req, struct smbd_lock_element, num_ulocks);
9283 if (ulocks == NULL) {
9284 reply_nterror(req, NT_STATUS_NO_MEMORY);
9285 END_PROFILE(SMBlockingX);
9290 * Data now points at the beginning of the list of
9291 * smb_unlkrng structs
9293 for (i = 0; i < num_ulocks; i++) {
9294 ulocks[i].req_guid = smbd_request_guid(req,
9296 ulocks[i].smblctx = get_lock_pid(
9297 data, i, large_file_format);
9298 ulocks[i].count = get_lock_count(
9299 data, i, large_file_format);
9300 ulocks[i].offset = get_lock_offset(
9301 data, i, large_file_format);
9302 ulocks[i].brltype = UNLOCK_LOCK;
9306 * Unlock cancels pending locks
9309 ok = smbd_smb1_brl_finish_by_lock(
9316 reply_outbuf(req, 2, 0);
9317 SSVAL(req->outbuf, smb_vwv0, 0xff);
9318 SSVAL(req->outbuf, smb_vwv1, 0);
9319 END_PROFILE(SMBlockingX);
9323 status = smbd_do_unlocking(
9324 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9325 TALLOC_FREE(ulocks);
9326 if (!NT_STATUS_IS_OK(status)) {
9327 END_PROFILE(SMBlockingX);
9328 reply_nterror(req, status);
9333 /* Now do any requested locks */
9334 data += ((large_file_format ? 20 : 10)*num_ulocks);
9336 /* Data now points at the beginning of the list
9337 of smb_lkrng structs */
9339 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9340 brltype = READ_LOCK;
9342 brltype = WRITE_LOCK;
9345 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9346 if (locks == NULL) {
9347 reply_nterror(req, NT_STATUS_NO_MEMORY);
9348 END_PROFILE(SMBlockingX);
9352 for (i = 0; i < num_locks; i++) {
9353 locks[i].req_guid = smbd_request_guid(req, i),
9354 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9355 locks[i].count = get_lock_count(data, i, large_file_format);
9356 locks[i].offset = get_lock_offset(data, i, large_file_format);
9357 locks[i].brltype = brltype;
9360 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9364 if (num_locks == 0) {
9365 /* See smbtorture3 lock11 test */
9366 reply_outbuf(req, 2, 0);
9367 /* andx chain ends */
9368 SSVAL(req->outbuf, smb_vwv0, 0xff);
9369 SSVAL(req->outbuf, smb_vwv1, 0);
9370 END_PROFILE(SMBlockingX);
9374 ok = smbd_smb1_brl_finish_by_lock(
9378 locks[0], /* Windows only cancels the first lock */
9379 NT_STATUS_FILE_LOCK_CONFLICT);
9382 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9383 END_PROFILE(SMBlockingX);
9387 reply_outbuf(req, 2, 0);
9388 SSVAL(req->outbuf, smb_vwv0, 0xff);
9389 SSVAL(req->outbuf, smb_vwv1, 0);
9390 END_PROFILE(SMBlockingX);
9394 subreq = smbd_smb1_do_locks_send(
9404 if (subreq == NULL) {
9405 reply_nterror(req, NT_STATUS_NO_MEMORY);
9406 END_PROFILE(SMBlockingX);
9409 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9410 END_PROFILE(SMBlockingX);
9413 static void reply_lockingx_done(struct tevent_req *subreq)
9415 struct smb_request *req = NULL;
9419 START_PROFILE(SMBlockingX);
9421 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9424 status = smbd_smb1_do_locks_recv(subreq);
9425 TALLOC_FREE(subreq);
9427 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9429 if (NT_STATUS_IS_OK(status)) {
9430 reply_outbuf(req, 2, 0);
9431 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9432 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9434 reply_nterror(req, status);
9437 ok = srv_send_smb(req->xconn,
9438 (char *)req->outbuf,
9441 IS_CONN_ENCRYPTED(req->conn),
9444 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9447 END_PROFILE(SMBlockingX);
9451 #define DBGC_CLASS DBGC_ALL
9453 /****************************************************************************
9454 Reply to a SMBreadbmpx (read block multiplex) request.
9455 Always reply with an error, if someone has a platform really needs this,
9456 please contact vl@samba.org
9457 ****************************************************************************/
9459 void reply_readbmpx(struct smb_request *req)
9461 START_PROFILE(SMBreadBmpx);
9462 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9463 END_PROFILE(SMBreadBmpx);
9467 /****************************************************************************
9468 Reply to a SMBreadbs (read block multiplex secondary) request.
9469 Always reply with an error, if someone has a platform really needs this,
9470 please contact vl@samba.org
9471 ****************************************************************************/
9473 void reply_readbs(struct smb_request *req)
9475 START_PROFILE(SMBreadBs);
9476 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9477 END_PROFILE(SMBreadBs);
9481 /****************************************************************************
9482 Reply to a SMBsetattrE.
9483 ****************************************************************************/
9485 void reply_setattrE(struct smb_request *req)
9487 connection_struct *conn = req->conn;
9488 struct smb_file_time ft;
9492 START_PROFILE(SMBsetattrE);
9493 init_smb_file_time(&ft);
9496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9500 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9502 if(!fsp || (fsp->conn != conn)) {
9503 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9508 * Convert the DOS times into unix times.
9511 ft.atime = time_t_to_full_timespec(
9512 srv_make_unix_date2(req->vwv+3));
9513 ft.mtime = time_t_to_full_timespec(
9514 srv_make_unix_date2(req->vwv+5));
9515 ft.create_time = time_t_to_full_timespec(
9516 srv_make_unix_date2(req->vwv+1));
9518 reply_outbuf(req, 0, 0);
9521 * Patch from Ray Frush <frush@engr.colostate.edu>
9522 * Sometimes times are sent as zero - ignore them.
9525 /* Ensure we have a valid stat struct for the source. */
9526 status = vfs_stat_fsp(fsp);
9527 if (!NT_STATUS_IS_OK(status)) {
9528 reply_nterror(req, status);
9532 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9533 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9537 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9538 if (!NT_STATUS_IS_OK(status)) {
9539 reply_nterror(req, status);
9543 if (fsp->fsp_flags.modified) {
9544 trigger_write_time_update_immediate(fsp);
9547 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9550 (unsigned int)ft.atime.tv_sec,
9551 (unsigned int)ft.mtime.tv_sec,
9552 (unsigned int)ft.create_time.tv_sec
9555 END_PROFILE(SMBsetattrE);
9560 /* Back from the dead for OS/2..... JRA. */
9562 /****************************************************************************
9563 Reply to a SMBwritebmpx (write block multiplex primary) request.
9564 Always reply with an error, if someone has a platform really needs this,
9565 please contact vl@samba.org
9566 ****************************************************************************/
9568 void reply_writebmpx(struct smb_request *req)
9570 START_PROFILE(SMBwriteBmpx);
9571 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9572 END_PROFILE(SMBwriteBmpx);
9576 /****************************************************************************
9577 Reply to a SMBwritebs (write block multiplex secondary) request.
9578 Always reply with an error, if someone has a platform really needs this,
9579 please contact vl@samba.org
9580 ****************************************************************************/
9582 void reply_writebs(struct smb_request *req)
9584 START_PROFILE(SMBwriteBs);
9585 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9586 END_PROFILE(SMBwriteBs);
9590 /****************************************************************************
9591 Reply to a SMBgetattrE.
9592 ****************************************************************************/
9594 void reply_getattrE(struct smb_request *req)
9596 connection_struct *conn = req->conn;
9599 struct timespec create_ts;
9602 START_PROFILE(SMBgetattrE);
9605 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9606 END_PROFILE(SMBgetattrE);
9610 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9612 if(!fsp || (fsp->conn != conn)) {
9613 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9614 END_PROFILE(SMBgetattrE);
9618 /* Do an fstat on this file */
9619 status = vfs_stat_fsp(fsp);
9620 if (!NT_STATUS_IS_OK(status)) {
9621 reply_nterror(req, status);
9622 END_PROFILE(SMBgetattrE);
9626 mode = dos_mode(conn, fsp->fsp_name);
9629 * Convert the times into dos times. Set create
9630 * date to be last modify date as UNIX doesn't save
9634 reply_outbuf(req, 11, 0);
9636 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9637 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9638 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9639 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9640 /* Should we check pending modtime here ? JRA */
9641 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9642 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9644 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9645 SIVAL(req->outbuf, smb_vwv6, 0);
9646 SIVAL(req->outbuf, smb_vwv8, 0);
9648 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9649 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9650 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9652 SSVAL(req->outbuf,smb_vwv10, mode);
9654 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9656 END_PROFILE(SMBgetattrE);