2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
31 #include "locking/share_mode_lock.h"
32 #include "smbd/smbd.h"
33 #include "smbd/globals.h"
34 #include "fake_file.h"
35 #include "rpc_client/rpc_client.h"
36 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
37 #include "rpc_client/cli_spoolss.h"
38 #include "rpc_client/init_spoolss.h"
39 #include "rpc_server/rpc_ncacn_np.h"
40 #include "libcli/security/security.h"
41 #include "libsmb/nmblib.h"
43 #include "smbprofile.h"
44 #include "../lib/tsocket/tsocket.h"
45 #include "lib/util/tevent_ntstatus.h"
46 #include "libcli/smb/smb_signing.h"
47 #include "lib/util/sys_rw_data.h"
48 #include "librpc/gen_ndr/open_files.h"
49 #include "smb1_utils.h"
50 #include "libcli/smb/smb2_posix.h"
51 #include "lib/util/string_wrappers.h"
53 /****************************************************************************
54 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
55 path or anything including wildcards.
56 We're assuming here that '/' is not the second byte in any multibyte char
57 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
59 ****************************************************************************/
61 /* Custom version for processing POSIX paths. */
62 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
64 static NTSTATUS
check_path_syntax_internal(char *path
,
69 NTSTATUS ret
= NT_STATUS_OK
;
70 bool start_of_name_component
= True
;
71 bool stream_started
= false;
72 bool last_component_contains_wcard
= false;
79 return NT_STATUS_OBJECT_NAME_INVALID
;
82 return NT_STATUS_OBJECT_NAME_INVALID
;
84 if (strchr_m(&s
[1], ':')) {
85 return NT_STATUS_OBJECT_NAME_INVALID
;
91 if ((*s
== ':') && !posix_path
&& !stream_started
) {
92 if (last_component_contains_wcard
) {
93 return NT_STATUS_OBJECT_NAME_INVALID
;
95 /* Stream names allow more characters than file names.
96 We're overloading posix_path here to allow a wider
97 range of characters. If stream_started is true this
98 is still a Windows path even if posix_path is true.
101 stream_started
= true;
102 start_of_name_component
= false;
106 return NT_STATUS_OBJECT_NAME_INVALID
;
110 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
112 * Safe to assume is not the second part of a mb char
113 * as this is handled below.
115 /* Eat multiple '/' or '\\' */
116 while (IS_PATH_SEP(*s
,posix_path
)) {
119 if ((d
!= path
) && (*s
!= '\0')) {
120 /* We only care about non-leading or trailing '/' or '\\' */
124 start_of_name_component
= True
;
126 last_component_contains_wcard
= false;
130 if (start_of_name_component
) {
131 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
132 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
135 * No mb char starts with '.' so we're safe checking the directory separator here.
138 /* If we just added a '/' - delete it */
139 if ((d
> path
) && (*(d
-1) == '/')) {
144 /* Are we at the start ? Can't go back further if so. */
146 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
149 /* Go back one level... */
150 /* We know this is safe as '/' cannot be part of a mb sequence. */
151 /* NOTE - if this assumption is invalid we are not in good shape... */
152 /* Decrement d first as d points to the *next* char to write into. */
153 for (d
--; d
> path
; d
--) {
157 s
+= 2; /* Else go past the .. */
158 /* We're still at the start of a name component, just the previous one. */
161 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
173 if (*s
<= 0x1f || *s
== '|') {
174 return NT_STATUS_OBJECT_NAME_INVALID
;
182 last_component_contains_wcard
= true;
191 /* Get the size of the next MB character. */
192 next_codepoint(s
,&siz
);
210 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
212 return NT_STATUS_INVALID_PARAMETER
;
215 start_of_name_component
= False
;
223 /****************************************************************************
224 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
225 No wildcards allowed.
226 ****************************************************************************/
228 NTSTATUS
check_path_syntax(char *path
)
230 return check_path_syntax_internal(path
, false);
233 /****************************************************************************
234 Check the path for a POSIX client.
235 We're assuming here that '/' is not the second byte in any multibyte char
236 set (a safe assumption).
237 ****************************************************************************/
239 NTSTATUS
check_path_syntax_posix(char *path
)
241 return check_path_syntax_internal(path
, true);
244 /****************************************************************************
245 Pull a string and check the path allowing a wildcard - provide for error return.
246 Passes in posix flag.
247 ****************************************************************************/
249 static size_t srvstr_get_path_internal(TALLOC_CTX
*ctx
,
250 const char *base_ptr
,
256 bool posix_pathnames
,
263 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
267 *err
= NT_STATUS_INVALID_PARAMETER
;
271 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
273 * For a DFS path the function parse_dfs_path()
274 * will do the path processing, just make a copy.
280 if (posix_pathnames
) {
281 *err
= check_path_syntax_posix(*pp_dest
);
283 *err
= check_path_syntax(*pp_dest
);
289 /****************************************************************************
290 Pull a string and check the path - provide for error return.
291 ****************************************************************************/
293 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
294 const char *base_ptr
,
302 return srvstr_get_path_internal(ctx
,
313 /****************************************************************************
314 Pull a string and check the path - provide for error return.
315 posix_pathnames version.
316 ****************************************************************************/
318 size_t srvstr_get_path_posix(TALLOC_CTX
*ctx
,
319 const char *base_ptr
,
327 return srvstr_get_path_internal(ctx
,
339 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
340 char **pp_dest
, const char *src
, int flags
,
343 ssize_t bufrem
= smbreq_bufrem(req
, src
);
346 *err
= NT_STATUS_INVALID_PARAMETER
;
350 if (req
->posix_pathnames
) {
351 return srvstr_get_path_internal(mem_ctx
,
352 (const char *)req
->inbuf
,
361 return srvstr_get_path_internal(mem_ctx
,
362 (const char *)req
->inbuf
,
374 * pull a string from the smb_buf part of a packet. In this case the
375 * string can either be null terminated or it can be terminated by the
376 * end of the smbbuf area
378 size_t srvstr_pull_req_talloc(TALLOC_CTX
*ctx
, struct smb_request
*req
,
379 char **dest
, const uint8_t *src
, int flags
)
381 ssize_t bufrem
= smbreq_bufrem(req
, src
);
387 return pull_string_talloc(ctx
, req
->inbuf
, req
->flags2
, dest
, src
,
391 /****************************************************************************
392 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
393 ****************************************************************************/
395 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
398 if ((fsp
== NULL
) || (conn
== NULL
)) {
399 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
402 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
403 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
409 /****************************************************************************
410 Check if we have a correct fsp pointing to a file.
411 ****************************************************************************/
413 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
416 if (!check_fsp_open(conn
, req
, fsp
)) {
419 if (fsp
->fsp_flags
.is_directory
) {
420 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
423 if (fsp_get_pathref_fd(fsp
) == -1) {
424 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
427 fsp
->num_smb_operations
++;
431 /****************************************************************************
432 Check if we have a correct fsp pointing to a quota fake file. Replacement for
433 the CHECK_NTQUOTA_HANDLE_OK macro.
434 ****************************************************************************/
436 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
439 if (!check_fsp_open(conn
, req
, fsp
)) {
443 if (fsp
->fsp_flags
.is_directory
) {
447 if (fsp
->fake_file_handle
== NULL
) {
451 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
455 if (fsp
->fake_file_handle
->private_data
== NULL
) {
462 /****************************************************************************
463 Return the port number we've bound to on a socket.
464 ****************************************************************************/
466 static int get_socket_port(int fd
)
468 struct samba_sockaddr saddr
= {
469 .sa_socklen
= sizeof(struct sockaddr_storage
),
476 if (getsockname(fd
, &saddr
.u
.sa
, &saddr
.sa_socklen
) < 0) {
477 int level
= (errno
== ENOTCONN
) ? 2 : 0;
478 DEBUG(level
, ("getsockname failed. Error was %s\n",
483 #if defined(HAVE_IPV6)
484 if (saddr
.u
.sa
.sa_family
== AF_INET6
) {
485 return ntohs(saddr
.u
.in6
.sin6_port
);
488 if (saddr
.u
.sa
.sa_family
== AF_INET
) {
489 return ntohs(saddr
.u
.in
.sin_port
);
494 static bool netbios_session_retarget(struct smbXsrv_connection
*xconn
,
495 const char *name
, int name_type
)
498 char *trim_name_type
;
499 const char *retarget_parm
;
502 int retarget_type
= 0x20;
503 int retarget_port
= NBT_SMB_PORT
;
504 struct sockaddr_storage retarget_addr
;
505 struct sockaddr_in
*in_addr
;
509 if (get_socket_port(xconn
->transport
.sock
) != NBT_SMB_PORT
) {
513 trim_name
= talloc_strdup(talloc_tos(), name
);
514 if (trim_name
== NULL
) {
517 trim_char(trim_name
, ' ', ' ');
519 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
521 if (trim_name_type
== NULL
) {
525 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
526 trim_name_type
, NULL
);
527 if (retarget_parm
== NULL
) {
528 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
531 if (retarget_parm
== NULL
) {
535 retarget
= talloc_strdup(trim_name
, retarget_parm
);
536 if (retarget
== NULL
) {
540 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
542 p
= strchr(retarget
, ':');
545 retarget_port
= atoi(p
);
548 p
= strchr_m(retarget
, '#');
551 if (sscanf(p
, "%x", &retarget_type
) != 1) {
556 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
558 DEBUG(10, ("could not resolve %s\n", retarget
));
562 if (retarget_addr
.ss_family
!= AF_INET
) {
563 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
567 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
569 _smb_setlen(outbuf
, 6);
570 SCVAL(outbuf
, 0, 0x84);
571 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
572 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
574 if (!srv_send_smb(xconn
, (char *)outbuf
, false, 0, false,
576 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
582 TALLOC_FREE(trim_name
);
586 static void reply_called_name_not_present(char *outbuf
)
588 smb_setlen(outbuf
, 1);
589 SCVAL(outbuf
, 0, 0x83);
590 SCVAL(outbuf
, 4, 0x82);
593 /****************************************************************************
594 Reply to a (netbios-level) special message.
595 ****************************************************************************/
597 void reply_special(struct smbXsrv_connection
*xconn
, char *inbuf
, size_t inbuf_size
)
599 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
600 int msg_type
= CVAL(inbuf
,0);
601 int msg_flags
= CVAL(inbuf
,1);
603 * We only really use 4 bytes of the outbuf, but for the smb_setlen
604 * calculation & friends (srv_send_smb uses that) we need the full smb
607 char outbuf
[smb_size
];
609 memset(outbuf
, '\0', sizeof(outbuf
));
611 smb_setlen(outbuf
,0);
614 case NBSSrequest
: /* session request */
616 /* inbuf_size is guarenteed to be at least 4. */
618 int name_type1
, name_type2
;
619 int name_len1
, name_len2
;
623 if (xconn
->transport
.nbt
.got_session
) {
624 exit_server_cleanly("multiple session request not permitted");
627 SCVAL(outbuf
,0,NBSSpositive
);
630 /* inbuf_size is guaranteed to be at least 4. */
631 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
632 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
633 DEBUG(0,("Invalid name length in session request\n"));
634 reply_called_name_not_present(outbuf
);
637 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
638 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
639 DEBUG(0,("Invalid name length in session request\n"));
640 reply_called_name_not_present(outbuf
);
644 name_type1
= name_extract((unsigned char *)inbuf
,
645 inbuf_size
,(unsigned int)4,name1
);
646 name_type2
= name_extract((unsigned char *)inbuf
,
647 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
649 if (name_type1
== -1 || name_type2
== -1) {
650 DEBUG(0,("Invalid name type in session request\n"));
651 reply_called_name_not_present(outbuf
);
655 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
656 name1
, name_type1
, name2
, name_type2
));
658 if (netbios_session_retarget(xconn
, name1
, name_type1
)) {
659 exit_server_cleanly("retargeted client");
663 * Windows NT/2k uses "*SMBSERVER" and XP uses
664 * "*SMBSERV" arrggg!!!
666 if (strequal(name1
, "*SMBSERVER ")
667 || strequal(name1
, "*SMBSERV ")) {
670 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
673 exit_server_cleanly("could not allocate raddr");
676 fstrcpy(name1
, raddr
);
679 set_local_machine_name(name1
, True
);
680 set_remote_machine_name(name2
, True
);
682 if (is_ipaddress(sconn
->remote_hostname
)) {
683 char *p
= discard_const_p(char, sconn
->remote_hostname
);
687 sconn
->remote_hostname
= talloc_strdup(sconn
,
688 get_remote_machine_name());
689 if (sconn
->remote_hostname
== NULL
) {
690 exit_server_cleanly("could not copy remote name");
692 xconn
->remote_hostname
= sconn
->remote_hostname
;
695 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
696 get_local_machine_name(), get_remote_machine_name(),
699 if (name_type2
== 'R') {
700 /* We are being asked for a pathworks session ---
702 reply_called_name_not_present(outbuf
);
706 reload_services(sconn
, conn_snum_used
, true);
709 xconn
->transport
.nbt
.got_session
= true;
713 case 0x89: /* session keepalive request
714 (some old clients produce this?) */
715 SCVAL(outbuf
,0,NBSSkeepalive
);
719 case NBSSpositive
: /* positive session response */
720 case NBSSnegative
: /* negative session response */
721 case NBSSretarget
: /* retarget session response */
722 DEBUG(0,("Unexpected session response\n"));
725 case NBSSkeepalive
: /* session keepalive */
730 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
731 msg_type
, msg_flags
));
733 if (!srv_send_smb(xconn
, outbuf
, false, 0, false, NULL
)) {
734 exit_server_cleanly("reply_special: srv_send_smb failed.");
737 if (CVAL(outbuf
, 0) != 0x82) {
738 exit_server_cleanly("invalid netbios session");
743 /****************************************************************************
745 conn POINTER CAN BE NULL HERE !
746 ****************************************************************************/
748 void reply_tcon(struct smb_request
*req
)
750 connection_struct
*conn
= req
->conn
;
752 char *service_buf
= NULL
;
753 char *password
= NULL
;
759 TALLOC_CTX
*ctx
= talloc_tos();
760 struct smbXsrv_connection
*xconn
= req
->xconn
;
761 NTTIME now
= timeval_to_nttime(&req
->request_time
);
763 START_PROFILE(SMBtcon
);
765 if (req
->buflen
< 4) {
766 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
767 END_PROFILE(SMBtcon
);
772 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
774 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
776 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
779 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
780 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
781 END_PROFILE(SMBtcon
);
784 p2
= strrchr_m(service_buf
,'\\');
788 service
= service_buf
;
791 conn
= make_connection(req
, now
, service
, dev
,
792 req
->vuid
,&nt_status
);
796 reply_nterror(req
, nt_status
);
797 END_PROFILE(SMBtcon
);
801 reply_outbuf(req
, 2, 0);
802 SSVAL(req
->outbuf
,smb_vwv0
,xconn
->smb1
.negprot
.max_recv
);
803 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
804 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
806 DEBUG(3,("tcon service=%s cnum=%d\n",
807 service
, conn
->cnum
));
809 END_PROFILE(SMBtcon
);
813 /****************************************************************************
814 Reply to a tcon and X.
815 conn POINTER CAN BE NULL HERE !
816 ****************************************************************************/
818 void reply_tcon_and_X(struct smb_request
*req
)
820 const struct loadparm_substitution
*lp_sub
=
821 loadparm_s3_global_substitution();
822 connection_struct
*conn
= req
->conn
;
823 const char *service
= NULL
;
824 TALLOC_CTX
*ctx
= talloc_tos();
825 /* what the client thinks the device is */
826 char *client_devicetype
= NULL
;
827 /* what the server tells the client the share represents */
828 const char *server_devicetype
;
835 struct smbXsrv_session
*session
= NULL
;
836 NTTIME now
= timeval_to_nttime(&req
->request_time
);
837 bool session_key_updated
= false;
838 uint16_t optional_support
= 0;
839 struct smbXsrv_connection
*xconn
= req
->xconn
;
841 START_PROFILE(SMBtconX
);
844 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
845 END_PROFILE(SMBtconX
);
849 passlen
= SVAL(req
->vwv
+3, 0);
850 tcon_flags
= SVAL(req
->vwv
+2, 0);
852 /* we might have to close an old one */
853 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
854 struct smbXsrv_tcon
*tcon
;
862 * TODO: cancel all outstanding requests on the tcon
864 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
865 if (!NT_STATUS_IS_OK(status
)) {
866 DEBUG(0, ("reply_tcon_and_X: "
867 "smbXsrv_tcon_disconnect() failed: %s\n",
870 * If we hit this case, there is something completely
871 * wrong, so we better disconnect the transport connection.
873 END_PROFILE(SMBtconX
);
874 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
880 * This tree id is gone. Make sure we can't re-use it
886 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
887 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
888 END_PROFILE(SMBtconX
);
892 if (xconn
->smb1
.negprot
.encrypted_passwords
) {
893 p
= req
->buf
+ passlen
;
895 p
= req
->buf
+ passlen
+ 1;
898 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
901 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
902 END_PROFILE(SMBtconX
);
907 * the service name can be either: \\server\share
908 * or share directly like on the DELL PowerVault 705
911 q
= strchr_m(path
+2,'\\');
913 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
914 END_PROFILE(SMBtconX
);
922 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
923 &client_devicetype
, p
,
924 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
926 if (client_devicetype
== NULL
) {
927 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
928 END_PROFILE(SMBtconX
);
932 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
934 nt_status
= smb1srv_session_lookup(xconn
,
935 req
->vuid
, now
, &session
);
936 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
937 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
938 END_PROFILE(SMBtconX
);
941 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
942 reply_nterror(req
, nt_status
);
943 END_PROFILE(SMBtconX
);
946 if (!NT_STATUS_IS_OK(nt_status
)) {
947 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
948 END_PROFILE(SMBtconX
);
952 if (session
->global
->auth_session_info
== NULL
) {
953 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
954 END_PROFILE(SMBtconX
);
959 * If there is no application key defined yet
962 * This means we setup the application key on the
963 * first tcon that happens via the given session.
965 * Once the application key is defined, it does not
968 if (session
->global
->application_key
.length
== 0 &&
969 smb2_signing_key_valid(session
->global
->signing_key
))
971 struct smbXsrv_session
*x
= session
;
972 struct auth_session_info
*session_info
=
973 session
->global
->auth_session_info
;
974 uint8_t session_key
[16];
976 ZERO_STRUCT(session_key
);
977 memcpy(session_key
, x
->global
->signing_key
->blob
.data
,
978 MIN(x
->global
->signing_key
->blob
.length
, sizeof(session_key
)));
981 * The application key is truncated/padded to 16 bytes
983 x
->global
->application_key
= data_blob_talloc(x
->global
,
985 sizeof(session_key
));
986 ZERO_STRUCT(session_key
);
987 if (x
->global
->application_key
.data
== NULL
) {
988 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
989 END_PROFILE(SMBtconX
);
993 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
996 status
= smb_key_derivation(x
->global
->application_key
.data
,
997 x
->global
->application_key
.length
,
998 x
->global
->application_key
.data
);
999 if (!NT_STATUS_IS_OK(status
)) {
1000 DBG_ERR("smb_key_derivation failed: %s\n",
1002 END_PROFILE(SMBtconX
);
1005 optional_support
|= SMB_EXTENDED_SIGNATURES
;
1009 * Place the application key into the session_info
1011 data_blob_clear_free(&session_info
->session_key
);
1012 session_info
->session_key
= data_blob_dup_talloc(session_info
,
1013 x
->global
->application_key
);
1014 if (session_info
->session_key
.data
== NULL
) {
1015 data_blob_clear_free(&x
->global
->application_key
);
1016 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1017 END_PROFILE(SMBtconX
);
1020 session_key_updated
= true;
1023 conn
= make_connection(req
, now
, service
, client_devicetype
,
1024 req
->vuid
, &nt_status
);
1028 if (session_key_updated
) {
1029 struct smbXsrv_session
*x
= session
;
1030 struct auth_session_info
*session_info
=
1031 session
->global
->auth_session_info
;
1032 data_blob_clear_free(&x
->global
->application_key
);
1033 data_blob_clear_free(&session_info
->session_key
);
1035 reply_nterror(req
, nt_status
);
1036 END_PROFILE(SMBtconX
);
1041 server_devicetype
= "IPC";
1042 else if ( IS_PRINT(conn
) )
1043 server_devicetype
= "LPT1:";
1045 server_devicetype
= "A:";
1047 if (get_Protocol() < PROTOCOL_NT1
) {
1048 reply_outbuf(req
, 2, 0);
1049 if (message_push_string(&req
->outbuf
, server_devicetype
,
1050 STR_TERMINATE
|STR_ASCII
) == -1) {
1051 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1052 END_PROFILE(SMBtconX
);
1056 /* NT sets the fstype of IPC$ to the null string */
1057 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
1059 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
1060 /* Return permissions. */
1064 reply_outbuf(req
, 7, 0);
1067 perm1
= FILE_ALL_ACCESS
;
1068 perm2
= FILE_ALL_ACCESS
;
1070 perm1
= conn
->share_access
;
1073 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
1074 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
1076 reply_outbuf(req
, 3, 0);
1079 if ((message_push_string(&req
->outbuf
, server_devicetype
,
1080 STR_TERMINATE
|STR_ASCII
) == -1)
1081 || (message_push_string(&req
->outbuf
, fstype
,
1082 STR_TERMINATE
) == -1)) {
1083 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1084 END_PROFILE(SMBtconX
);
1088 /* what does setting this bit do? It is set by NT4 and
1089 may affect the ability to autorun mounted cdroms */
1090 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1092 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1094 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1095 DEBUG(2,("Serving %s as a Dfs root\n",
1096 lp_servicename(ctx
, lp_sub
, SNUM(conn
)) ));
1097 optional_support
|= SMB_SHARE_IN_DFS
;
1100 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1103 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1104 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1106 DEBUG(3,("tconX service=%s \n",
1109 /* set the incoming and outgoing tid to the just created one */
1110 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1111 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1113 END_PROFILE(SMBtconX
);
1115 req
->tid
= conn
->cnum
;
1118 /****************************************************************************
1119 Reply to an unknown type.
1120 ****************************************************************************/
1122 void reply_unknown_new(struct smb_request
*req
, uint8_t type
)
1124 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1125 smb_fn_name(type
), type
, type
));
1126 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1130 /****************************************************************************
1132 conn POINTER CAN BE NULL HERE !
1133 ****************************************************************************/
1135 void reply_ioctl(struct smb_request
*req
)
1137 const struct loadparm_substitution
*lp_sub
=
1138 loadparm_s3_global_substitution();
1139 connection_struct
*conn
= req
->conn
;
1142 uint32_t ioctl_code
;
1146 START_PROFILE(SMBioctl
);
1149 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1150 END_PROFILE(SMBioctl
);
1154 device
= SVAL(req
->vwv
+1, 0);
1155 function
= SVAL(req
->vwv
+2, 0);
1156 ioctl_code
= (device
<< 16) + function
;
1158 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1160 switch (ioctl_code
) {
1161 case IOCTL_QUERY_JOB_INFO
:
1165 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1166 END_PROFILE(SMBioctl
);
1170 reply_outbuf(req
, 8, replysize
+1);
1171 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1172 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1173 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1174 p
= smb_buf(req
->outbuf
);
1175 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1176 p
+= 1; /* Allow for alignment */
1178 switch (ioctl_code
) {
1179 case IOCTL_QUERY_JOB_INFO
:
1183 files_struct
*fsp
= file_fsp(
1184 req
, SVAL(req
->vwv
+0, 0));
1186 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1187 END_PROFILE(SMBioctl
);
1191 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1193 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1194 lp_netbios_name(), 15,
1195 STR_TERMINATE
|STR_ASCII
, &len
);
1196 if (!NT_STATUS_IS_OK(status
)) {
1197 reply_nterror(req
, status
);
1198 END_PROFILE(SMBioctl
);
1202 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
,
1204 lp_servicename(talloc_tos(),
1207 13, STR_TERMINATE
|STR_ASCII
, &len
);
1208 if (!NT_STATUS_IS_OK(status
)) {
1209 reply_nterror(req
, status
);
1210 END_PROFILE(SMBioctl
);
1214 memset(p
+18, 0, 13);
1220 END_PROFILE(SMBioctl
);
1224 /****************************************************************************
1225 Strange checkpath NTSTATUS mapping.
1226 ****************************************************************************/
1228 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1230 /* Strange DOS error code semantics only for checkpath... */
1231 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1232 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1233 /* We need to map to ERRbadpath */
1234 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1240 /****************************************************************************
1241 Reply to a checkpath.
1242 ****************************************************************************/
1244 void reply_checkpath(struct smb_request
*req
)
1246 connection_struct
*conn
= req
->conn
;
1247 struct smb_filename
*smb_fname
= NULL
;
1250 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1251 TALLOC_CTX
*ctx
= talloc_tos();
1253 START_PROFILE(SMBcheckpath
);
1255 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1256 STR_TERMINATE
, &status
);
1258 if (!NT_STATUS_IS_OK(status
)) {
1259 status
= map_checkpath_error(req
->flags2
, status
);
1260 reply_nterror(req
, status
);
1261 END_PROFILE(SMBcheckpath
);
1265 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1267 status
= filename_convert(ctx
,
1274 if (!NT_STATUS_IS_OK(status
)) {
1275 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1276 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1277 ERRSRV
, ERRbadpath
);
1278 END_PROFILE(SMBcheckpath
);
1284 if (!VALID_STAT(smb_fname
->st
) &&
1285 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1286 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1287 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1288 status
= map_nt_error_from_unix(errno
);
1292 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1293 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1294 ERRDOS
, ERRbadpath
);
1298 reply_outbuf(req
, 0, 0);
1301 /* We special case this - as when a Windows machine
1302 is parsing a path is steps through the components
1303 one at a time - if a component fails it expects
1304 ERRbadpath, not ERRbadfile.
1306 status
= map_checkpath_error(req
->flags2
, status
);
1307 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1309 * Windows returns different error codes if
1310 * the parent directory is valid but not the
1311 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1312 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1313 * if the path is invalid.
1315 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1316 ERRDOS
, ERRbadpath
);
1320 reply_nterror(req
, status
);
1323 TALLOC_FREE(smb_fname
);
1324 END_PROFILE(SMBcheckpath
);
1328 /****************************************************************************
1330 ****************************************************************************/
1332 void reply_getatr(struct smb_request
*req
)
1334 connection_struct
*conn
= req
->conn
;
1335 struct smb_filename
*smb_fname
= NULL
;
1342 TALLOC_CTX
*ctx
= talloc_tos();
1343 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
1345 START_PROFILE(SMBgetatr
);
1347 p
= (const char *)req
->buf
+ 1;
1348 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1349 if (!NT_STATUS_IS_OK(status
)) {
1350 reply_nterror(req
, status
);
1354 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1355 under WfWg - weird! */
1356 if (*fname
== '\0') {
1357 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1358 if (!CAN_WRITE(conn
)) {
1359 mode
|= FILE_ATTRIBUTE_READONLY
;
1364 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1365 status
= filename_convert(ctx
,
1371 if (!NT_STATUS_IS_OK(status
)) {
1372 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1373 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1374 ERRSRV
, ERRbadpath
);
1377 reply_nterror(req
, status
);
1380 if (!VALID_STAT(smb_fname
->st
) &&
1381 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1382 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1383 smb_fname_str_dbg(smb_fname
),
1385 reply_nterror(req
, map_nt_error_from_unix(errno
));
1389 mode
= fdos_mode(smb_fname
->fsp
);
1390 size
= smb_fname
->st
.st_ex_size
;
1392 if (ask_sharemode
) {
1393 struct timespec write_time_ts
;
1394 struct file_id fileid
;
1396 ZERO_STRUCT(write_time_ts
);
1397 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1398 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1399 if (!is_omit_timespec(&write_time_ts
)) {
1400 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1404 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1405 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1410 reply_outbuf(req
, 10, 0);
1412 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1413 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1414 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1416 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1418 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
1420 if (get_Protocol() >= PROTOCOL_NT1
) {
1421 SSVAL(req
->outbuf
, smb_flg2
,
1422 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1425 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1426 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1429 TALLOC_FREE(smb_fname
);
1431 END_PROFILE(SMBgetatr
);
1435 /****************************************************************************
1437 ****************************************************************************/
1439 void reply_setatr(struct smb_request
*req
)
1441 struct smb_file_time ft
;
1442 connection_struct
*conn
= req
->conn
;
1443 struct smb_filename
*smb_fname
= NULL
;
1449 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1450 TALLOC_CTX
*ctx
= talloc_tos();
1452 START_PROFILE(SMBsetatr
);
1453 init_smb_file_time(&ft
);
1456 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1460 p
= (const char *)req
->buf
+ 1;
1461 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1462 if (!NT_STATUS_IS_OK(status
)) {
1463 reply_nterror(req
, status
);
1467 status
= filename_convert(ctx
,
1473 if (!NT_STATUS_IS_OK(status
)) {
1474 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1475 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1476 ERRSRV
, ERRbadpath
);
1479 reply_nterror(req
, status
);
1483 if (ISDOT(smb_fname
->base_name
)) {
1485 * Not sure here is the right place to catch this
1486 * condition. Might be moved to somewhere else later -- vl
1488 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1492 mode
= SVAL(req
->vwv
+0, 0);
1493 mtime
= srv_make_unix_date3(req
->vwv
+1);
1495 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1496 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1497 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1499 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1501 status
= smbd_check_access_rights(conn
,
1505 FILE_WRITE_ATTRIBUTES
);
1506 if (!NT_STATUS_IS_OK(status
)) {
1507 reply_nterror(req
, status
);
1511 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1513 reply_nterror(req
, map_nt_error_from_unix(errno
));
1518 ft
.mtime
= time_t_to_full_timespec(mtime
);
1520 status
= smb_set_file_time(conn
, smb_fname
->fsp
, smb_fname
, &ft
, true);
1521 if (!NT_STATUS_IS_OK(status
)) {
1522 reply_nterror(req
, status
);
1526 reply_outbuf(req
, 0, 0);
1528 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1531 TALLOC_FREE(smb_fname
);
1532 END_PROFILE(SMBsetatr
);
1536 /****************************************************************************
1538 ****************************************************************************/
1540 void reply_dskattr(struct smb_request
*req
)
1542 connection_struct
*conn
= req
->conn
;
1544 uint64_t dfree
,dsize
,bsize
;
1545 struct smb_filename smb_fname
;
1546 START_PROFILE(SMBdskattr
);
1548 ZERO_STRUCT(smb_fname
);
1549 smb_fname
.base_name
= discard_const_p(char, ".");
1551 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
1552 reply_nterror(req
, map_nt_error_from_unix(errno
));
1553 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
1554 END_PROFILE(SMBdskattr
);
1558 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
1559 if (ret
== (uint64_t)-1) {
1560 reply_nterror(req
, map_nt_error_from_unix(errno
));
1561 END_PROFILE(SMBdskattr
);
1566 * Force max to fit in 16 bit fields.
1568 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1572 if (bsize
> (WORDMAX
*512)) {
1573 bsize
= (WORDMAX
*512);
1574 if (dsize
> WORDMAX
)
1576 if (dfree
> WORDMAX
)
1582 reply_outbuf(req
, 5, 0);
1584 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1585 double total_space
, free_space
;
1586 /* we need to scale this to a number that DOS6 can handle. We
1587 use floating point so we can handle large drives on systems
1588 that don't have 64 bit integers
1590 we end up displaying a maximum of 2G to DOS systems
1592 total_space
= dsize
* (double)bsize
;
1593 free_space
= dfree
* (double)bsize
;
1595 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1596 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1598 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1599 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1601 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1602 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1603 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1604 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1606 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1607 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1608 SSVAL(req
->outbuf
,smb_vwv2
,512);
1609 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1612 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1614 END_PROFILE(SMBdskattr
);
1619 * Utility function to split the filename from the directory.
1621 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1622 char **fname_dir_out
,
1623 char **fname_mask_out
)
1625 const char *p
= NULL
;
1626 char *fname_dir
= NULL
;
1627 char *fname_mask
= NULL
;
1629 p
= strrchr_m(fname_in
, '/');
1631 fname_dir
= talloc_strdup(ctx
, ".");
1632 fname_mask
= talloc_strdup(ctx
, fname_in
);
1634 fname_dir
= talloc_strndup(ctx
, fname_in
,
1635 PTR_DIFF(p
, fname_in
));
1636 fname_mask
= talloc_strdup(ctx
, p
+1);
1639 if (!fname_dir
|| !fname_mask
) {
1640 TALLOC_FREE(fname_dir
);
1641 TALLOC_FREE(fname_mask
);
1642 return NT_STATUS_NO_MEMORY
;
1645 *fname_dir_out
= fname_dir
;
1646 *fname_mask_out
= fname_mask
;
1647 return NT_STATUS_OK
;
1650 /****************************************************************************
1652 ****************************************************************************/
1654 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1664 char *mask2
= talloc_strdup(ctx
, mask
);
1670 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1674 memset(buf
+1,' ',11);
1675 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1677 push_ascii(buf
+1,mask2
,8, 0);
1678 push_ascii(buf
+9,p
+1,3, 0);
1681 push_ascii(buf
+1,mask2
,11, 0);
1684 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1686 srv_put_dos_date(buf
,22,date
);
1687 SSVAL(buf
,26,size
& 0xFFFF);
1688 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1689 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1690 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1691 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1692 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1696 /****************************************************************************
1698 Can be called from SMBsearch, SMBffirst or SMBfunique.
1699 ****************************************************************************/
1701 void reply_search(struct smb_request
*req
)
1703 connection_struct
*conn
= req
->conn
;
1706 char *directory
= NULL
;
1707 struct smb_filename
*smb_fname
= NULL
;
1711 struct timespec date
;
1713 unsigned int numentries
= 0;
1714 unsigned int maxentries
= 0;
1715 bool finished
= False
;
1720 bool check_descend
= False
;
1721 bool expect_close
= False
;
1723 bool mask_contains_wcard
= False
;
1724 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1725 TALLOC_CTX
*ctx
= talloc_tos();
1726 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
1727 struct smbXsrv_connection
*xconn
= req
->xconn
;
1728 struct smbd_server_connection
*sconn
= req
->sconn
;
1729 files_struct
*fsp
= NULL
;
1730 const struct loadparm_substitution
*lp_sub
=
1731 loadparm_s3_global_substitution();
1733 START_PROFILE(SMBsearch
);
1736 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1740 if (req
->posix_pathnames
) {
1741 reply_unknown_new(req
, req
->cmd
);
1745 /* If we were called as SMBffirst then we must expect close. */
1746 if(req
->cmd
== SMBffirst
) {
1747 expect_close
= True
;
1750 reply_outbuf(req
, 1, 3);
1751 maxentries
= SVAL(req
->vwv
+0, 0);
1752 dirtype
= SVAL(req
->vwv
+1, 0);
1753 p
= (const char *)req
->buf
+ 1;
1754 p
+= srvstr_get_path_req(ctx
, req
, &path
, p
, STR_TERMINATE
,
1756 if (!NT_STATUS_IS_OK(nt_status
)) {
1757 reply_nterror(req
, nt_status
);
1761 if (smbreq_bufrem(req
, p
) < 3) {
1762 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1767 status_len
= SVAL(p
, 0);
1770 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1772 if (status_len
== 0) {
1774 struct smb_filename
*smb_dname
= NULL
;
1775 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
1776 ucf_flags_from_smb_request(req
);
1777 nt_status
= filename_convert(ctx
, conn
,
1782 if (!NT_STATUS_IS_OK(nt_status
)) {
1783 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1784 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1785 ERRSRV
, ERRbadpath
);
1788 reply_nterror(req
, nt_status
);
1792 directory
= smb_fname
->base_name
;
1794 p
= strrchr_m(directory
,'/');
1795 if ((p
!= NULL
) && (*directory
!= '/')) {
1796 mask
= talloc_strdup(ctx
, p
+ 1);
1797 directory
= talloc_strndup(ctx
, directory
,
1798 PTR_DIFF(p
, directory
));
1800 mask
= talloc_strdup(ctx
, directory
);
1801 directory
= talloc_strdup(ctx
,".");
1805 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1809 memset((char *)status
,'\0',21);
1810 SCVAL(status
,0,(dirtype
& 0x1F));
1812 smb_dname
= synthetic_smb_fname(talloc_tos(),
1818 if (smb_dname
== NULL
) {
1819 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1824 * As we've cut off the last component from
1825 * smb_fname we need to re-stat smb_dname
1826 * so FILE_OPEN disposition knows the directory
1829 ret
= vfs_stat(conn
, smb_dname
);
1831 nt_status
= map_nt_error_from_unix(errno
);
1832 reply_nterror(req
, nt_status
);
1836 nt_status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_dname
);
1837 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
1838 nt_status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1840 if (!NT_STATUS_IS_OK(nt_status
)) {
1841 reply_nterror(req
, nt_status
);
1846 * Open an fsp on this directory for the dptr.
1848 nt_status
= SMB_VFS_CREATE_FILE(
1851 smb_dname
, /* dname */
1852 FILE_LIST_DIRECTORY
, /* access_mask */
1854 FILE_SHARE_WRITE
, /* share_access */
1855 FILE_OPEN
, /* create_disposition*/
1856 FILE_DIRECTORY_FILE
, /* create_options */
1857 FILE_ATTRIBUTE_DIRECTORY
,/* file_attributes */
1858 NO_OPLOCK
, /* oplock_request */
1860 0, /* allocation_size */
1861 0, /* private_flags */
1866 NULL
, /* in_context */
1867 NULL
);/* out_context */
1869 if (!NT_STATUS_IS_OK(nt_status
)) {
1870 DBG_ERR("failed to open directory %s\n",
1871 smb_fname_str_dbg(smb_dname
));
1872 reply_nterror(req
, nt_status
);
1876 nt_status
= dptr_create(conn
,
1886 TALLOC_FREE(smb_dname
);
1888 if (!NT_STATUS_IS_OK(nt_status
)) {
1890 * Use NULL here for the first parameter (req)
1891 * as this is not a client visible handle so
1892 * can'tbe part of an SMB1 chain.
1894 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1896 reply_nterror(req
, nt_status
);
1900 dptr_num
= dptr_dnum(fsp
->dptr
);
1904 const char *dirpath
;
1906 if (smbreq_bufrem(req
, p
) < 21) {
1907 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1911 memcpy(status
,p
,21);
1912 status_dirtype
= CVAL(status
,0) & 0x1F;
1913 if (status_dirtype
!= (dirtype
& 0x1F)) {
1914 dirtype
= status_dirtype
;
1917 fsp
= dptr_fetch_fsp(sconn
, status
+12,&dptr_num
);
1921 dirpath
= dptr_path(sconn
, dptr_num
);
1922 directory
= talloc_strdup(ctx
, dirpath
);
1924 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1928 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1932 dirtype
= dptr_attr(sconn
, dptr_num
);
1935 mask_contains_wcard
= dptr_has_wild(fsp
->dptr
);
1937 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1939 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1940 char buf
[DIR_STRUCT_SIZE
];
1941 memcpy(buf
,status
,21);
1942 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1943 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1944 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1947 dptr_fill(sconn
, buf
+12,dptr_num
);
1948 if (dptr_zero(buf
+12) && (status_len
==0)) {
1953 if (message_push_blob(&req
->outbuf
,
1954 data_blob_const(buf
, sizeof(buf
)))
1956 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1961 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1962 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1964 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1966 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1967 directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
))));
1968 if (in_list(directory
, lp_dont_descend(ctx
, lp_sub
, SNUM(conn
)),True
)) {
1969 check_descend
= True
;
1972 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1973 finished
= !get_dir_entry(ctx
,
1984 char buf
[DIR_STRUCT_SIZE
];
1985 memcpy(buf
,status
,21);
1986 if (!make_dir_struct(ctx
,
1992 convert_timespec_to_time_t(date
),
1993 !allow_long_path_components
)) {
1994 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1997 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
2000 if (message_push_blob(&req
->outbuf
,
2001 data_blob_const(buf
, sizeof(buf
)))
2003 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2013 /* If we were called as SMBffirst with smb_search_id == NULL
2014 and no entries were found then return error and close fsp->dptr
2017 if (numentries
== 0) {
2020 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2023 } else if(expect_close
&& status_len
== 0) {
2024 /* Close the dptr - we know it's gone */
2027 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2032 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2033 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
2035 /* fsp may have been closed above. */
2037 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2042 if ((numentries
== 0) && !mask_contains_wcard
) {
2043 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
2047 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
2048 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
2049 SCVAL(smb_buf(req
->outbuf
),0,5);
2050 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
2052 /* The replies here are never long name. */
2053 SSVAL(req
->outbuf
, smb_flg2
,
2054 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
2055 if (!allow_long_path_components
) {
2056 SSVAL(req
->outbuf
, smb_flg2
,
2057 SVAL(req
->outbuf
, smb_flg2
)
2058 & (~FLAGS2_LONG_PATH_COMPONENTS
));
2061 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2062 SSVAL(req
->outbuf
, smb_flg2
,
2063 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
2065 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2066 smb_fn_name(req
->cmd
),
2073 TALLOC_FREE(directory
);
2075 TALLOC_FREE(smb_fname
);
2076 END_PROFILE(SMBsearch
);
2080 /****************************************************************************
2081 Reply to a fclose (stop directory search).
2082 ****************************************************************************/
2084 void reply_fclose(struct smb_request
*req
)
2092 TALLOC_CTX
*ctx
= talloc_tos();
2093 struct smbd_server_connection
*sconn
= req
->sconn
;
2094 files_struct
*fsp
= NULL
;
2096 START_PROFILE(SMBfclose
);
2098 if (req
->posix_pathnames
) {
2099 reply_unknown_new(req
, req
->cmd
);
2100 END_PROFILE(SMBfclose
);
2104 p
= (const char *)req
->buf
+ 1;
2105 p
+= srvstr_get_path_req(ctx
, req
, &path
, p
, STR_TERMINATE
,
2107 if (!NT_STATUS_IS_OK(err
)) {
2108 reply_nterror(req
, err
);
2109 END_PROFILE(SMBfclose
);
2113 if (smbreq_bufrem(req
, p
) < 3) {
2114 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2115 END_PROFILE(SMBfclose
);
2120 status_len
= SVAL(p
,0);
2123 if (status_len
== 0) {
2124 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
2125 END_PROFILE(SMBfclose
);
2129 if (smbreq_bufrem(req
, p
) < 21) {
2130 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2131 END_PROFILE(SMBfclose
);
2135 memcpy(status
,p
,21);
2137 fsp
= dptr_fetch_fsp(sconn
, status
+12,&dptr_num
);
2139 /* Close the file - we know it's gone */
2140 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2145 reply_outbuf(req
, 1, 0);
2146 SSVAL(req
->outbuf
,smb_vwv0
,0);
2148 DEBUG(3,("search close\n"));
2150 END_PROFILE(SMBfclose
);
2154 /****************************************************************************
2156 ****************************************************************************/
2158 void reply_open(struct smb_request
*req
)
2160 connection_struct
*conn
= req
->conn
;
2161 struct smb_filename
*smb_fname
= NULL
;
2171 uint32_t access_mask
;
2172 uint32_t share_mode
;
2173 uint32_t create_disposition
;
2174 uint32_t create_options
= 0;
2175 uint32_t private_flags
= 0;
2178 TALLOC_CTX
*ctx
= talloc_tos();
2180 START_PROFILE(SMBopen
);
2183 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2187 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2188 deny_mode
= SVAL(req
->vwv
+0, 0);
2189 dos_attr
= SVAL(req
->vwv
+1, 0);
2191 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2192 STR_TERMINATE
, &status
);
2193 if (!NT_STATUS_IS_OK(status
)) {
2194 reply_nterror(req
, status
);
2198 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2199 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
2200 &share_mode
, &create_disposition
,
2201 &create_options
, &private_flags
)) {
2202 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2206 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2208 status
= filename_convert(ctx
,
2214 if (!NT_STATUS_IS_OK(status
)) {
2215 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2216 reply_botherror(req
,
2217 NT_STATUS_PATH_NOT_COVERED
,
2218 ERRSRV
, ERRbadpath
);
2221 reply_nterror(req
, status
);
2225 status
= SMB_VFS_CREATE_FILE(
2228 smb_fname
, /* fname */
2229 access_mask
, /* access_mask */
2230 share_mode
, /* share_access */
2231 create_disposition
, /* create_disposition*/
2232 create_options
, /* create_options */
2233 dos_attr
, /* file_attributes */
2234 oplock_request
, /* oplock_request */
2236 0, /* allocation_size */
2242 NULL
, NULL
); /* create context */
2244 if (!NT_STATUS_IS_OK(status
)) {
2245 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2246 /* We have re-scheduled this call. */
2250 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2251 reply_openerror(req
, status
);
2255 fsp
= fcb_or_dos_open(
2262 bool ok
= defer_smb1_sharing_violation(req
);
2266 reply_openerror(req
, status
);
2271 /* Ensure we're pointing at the correct stat struct. */
2272 TALLOC_FREE(smb_fname
);
2273 smb_fname
= fsp
->fsp_name
;
2275 size
= smb_fname
->st
.st_ex_size
;
2276 fattr
= fdos_mode(fsp
);
2278 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2280 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2281 DEBUG(3,("attempt to open a directory %s\n",
2283 close_file(req
, fsp
, ERROR_CLOSE
);
2284 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2285 ERRDOS
, ERRnoaccess
);
2289 reply_outbuf(req
, 7, 0);
2290 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2291 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2292 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2293 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2295 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2297 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2298 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2300 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2301 SCVAL(req
->outbuf
,smb_flg
,
2302 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2305 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2306 SCVAL(req
->outbuf
,smb_flg
,
2307 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2310 END_PROFILE(SMBopen
);
2314 /****************************************************************************
2315 Reply to an open and X.
2316 ****************************************************************************/
2318 void reply_open_and_X(struct smb_request
*req
)
2320 connection_struct
*conn
= req
->conn
;
2321 struct smb_filename
*smb_fname
= NULL
;
2323 uint16_t open_flags
;
2326 /* Breakout the oplock request bits so we can set the
2327 reply bits separately. */
2328 int ex_oplock_request
;
2329 int core_oplock_request
;
2332 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2333 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2341 uint64_t allocation_size
;
2342 ssize_t retval
= -1;
2343 uint32_t access_mask
;
2344 uint32_t share_mode
;
2345 uint32_t create_disposition
;
2346 uint32_t create_options
= 0;
2347 uint32_t private_flags
= 0;
2349 TALLOC_CTX
*ctx
= talloc_tos();
2351 START_PROFILE(SMBopenX
);
2353 if (req
->wct
< 15) {
2354 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2358 open_flags
= SVAL(req
->vwv
+2, 0);
2359 deny_mode
= SVAL(req
->vwv
+3, 0);
2360 smb_attr
= SVAL(req
->vwv
+5, 0);
2361 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2362 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2363 oplock_request
= ex_oplock_request
| core_oplock_request
;
2364 smb_ofun
= SVAL(req
->vwv
+8, 0);
2365 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2367 /* If it's an IPC, pass off the pipe handler. */
2369 if (lp_nt_pipe_support()) {
2370 reply_open_pipe_and_X(conn
, req
);
2372 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2377 /* XXXX we need to handle passed times, sattr and flags */
2378 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2379 STR_TERMINATE
, &status
);
2380 if (!NT_STATUS_IS_OK(status
)) {
2381 reply_nterror(req
, status
);
2385 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2387 &access_mask
, &share_mode
,
2388 &create_disposition
,
2391 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2395 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2397 status
= filename_convert(ctx
,
2403 if (!NT_STATUS_IS_OK(status
)) {
2404 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2405 reply_botherror(req
,
2406 NT_STATUS_PATH_NOT_COVERED
,
2407 ERRSRV
, ERRbadpath
);
2410 reply_nterror(req
, status
);
2414 status
= SMB_VFS_CREATE_FILE(
2417 smb_fname
, /* fname */
2418 access_mask
, /* access_mask */
2419 share_mode
, /* share_access */
2420 create_disposition
, /* create_disposition*/
2421 create_options
, /* create_options */
2422 smb_attr
, /* file_attributes */
2423 oplock_request
, /* oplock_request */
2425 0, /* allocation_size */
2430 &smb_action
, /* pinfo */
2431 NULL
, NULL
); /* create context */
2433 if (!NT_STATUS_IS_OK(status
)) {
2434 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2435 /* We have re-scheduled this call. */
2439 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2440 reply_openerror(req
, status
);
2444 fsp
= fcb_or_dos_open(
2451 bool ok
= defer_smb1_sharing_violation(req
);
2455 reply_openerror(req
, status
);
2460 smb_action
= FILE_WAS_OPENED
;
2463 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2464 if the file is truncated or created. */
2465 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2466 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2467 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2468 close_file(req
, fsp
, ERROR_CLOSE
);
2469 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2472 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2474 close_file(req
, fsp
, ERROR_CLOSE
);
2475 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2478 status
= vfs_stat_fsp(fsp
);
2479 if (!NT_STATUS_IS_OK(status
)) {
2480 close_file(req
, fsp
, ERROR_CLOSE
);
2481 reply_nterror(req
, status
);
2486 fattr
= fdos_mode(fsp
);
2487 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2488 close_file(req
, fsp
, ERROR_CLOSE
);
2489 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2492 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2494 /* If the caller set the extended oplock request bit
2495 and we granted one (by whatever means) - set the
2496 correct bit for extended oplock reply.
2499 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2500 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2503 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2504 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2507 /* If the caller set the core oplock request bit
2508 and we granted one (by whatever means) - set the
2509 correct bit for core oplock reply.
2512 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2513 reply_outbuf(req
, 19, 0);
2515 reply_outbuf(req
, 15, 0);
2518 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2519 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2521 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2522 SCVAL(req
->outbuf
, smb_flg
,
2523 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2526 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2527 SCVAL(req
->outbuf
, smb_flg
,
2528 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2531 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2532 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2533 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2534 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2536 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2538 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2539 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2540 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2542 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2543 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2547 TALLOC_FREE(smb_fname
);
2548 END_PROFILE(SMBopenX
);
2552 /****************************************************************************
2553 Reply to a SMBulogoffX.
2554 ****************************************************************************/
2556 static struct tevent_req
*reply_ulogoffX_send(struct smb_request
*smb1req
,
2557 struct smbXsrv_session
*session
);
2558 static void reply_ulogoffX_done(struct tevent_req
*req
);
2560 void reply_ulogoffX(struct smb_request
*smb1req
)
2562 struct timeval now
= timeval_current();
2563 struct smbXsrv_session
*session
= NULL
;
2564 struct tevent_req
*req
;
2568 * Don't setup the profile charge here, take
2569 * it in reply_ulogoffX_done(). Not strictly correct
2570 * but better than the other SMB1 async
2571 * code that double-charges at the moment.
2574 status
= smb1srv_session_lookup(smb1req
->xconn
,
2576 timeval_to_nttime(&now
),
2578 if (!NT_STATUS_IS_OK(status
)) {
2579 /* Not going async, profile here. */
2580 START_PROFILE(SMBulogoffX
);
2581 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2582 (unsigned long long)smb1req
->vuid
);
2584 smb1req
->vuid
= UID_FIELD_INVALID
;
2585 reply_force_doserror(smb1req
, ERRSRV
, ERRbaduid
);
2586 END_PROFILE(SMBulogoffX
);
2590 req
= reply_ulogoffX_send(smb1req
, session
);
2592 /* Not going async, profile here. */
2593 START_PROFILE(SMBulogoffX
);
2594 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
2595 END_PROFILE(SMBulogoffX
);
2599 /* We're async. This will complete later. */
2600 tevent_req_set_callback(req
, reply_ulogoffX_done
, smb1req
);
2604 struct reply_ulogoffX_state
{
2605 struct tevent_queue
*wait_queue
;
2606 struct smbXsrv_session
*session
;
2609 static void reply_ulogoffX_wait_done(struct tevent_req
*subreq
);
2611 /****************************************************************************
2612 Async SMB1 ulogoffX.
2613 Note, on failure here we deallocate and return NULL to allow the caller to
2614 SMB1 return an error of ERRnomem immediately.
2615 ****************************************************************************/
2617 static struct tevent_req
*reply_ulogoffX_send(struct smb_request
*smb1req
,
2618 struct smbXsrv_session
*session
)
2620 struct tevent_req
*req
;
2621 struct reply_ulogoffX_state
*state
;
2622 struct tevent_req
*subreq
;
2624 struct smbd_server_connection
*sconn
= session
->client
->sconn
;
2625 uint64_t vuid
= session
->global
->session_wire_id
;
2627 req
= tevent_req_create(smb1req
, &state
,
2628 struct reply_ulogoffX_state
);
2632 state
->wait_queue
= tevent_queue_create(state
,
2633 "reply_ulogoffX_wait_queue");
2634 if (tevent_req_nomem(state
->wait_queue
, req
)) {
2638 state
->session
= session
;
2641 * Make sure that no new request will be able to use this session.
2642 * This ensures that once all outstanding fsp->aio_requests
2643 * on this session are done, we are safe to close it.
2645 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
2647 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
) {
2648 if (fsp
->vuid
!= vuid
) {
2652 * Flag the file as close in progress.
2653 * This will prevent any more IO being
2656 fsp
->fsp_flags
.closing
= true;
2658 if (fsp
->num_aio_requests
> 0) {
2660 * Now wait until all aio requests on this fsp are
2663 * We don't set a callback, as we just want to block the
2664 * wait queue and the talloc_free() of fsp->aio_request
2665 * will remove the item from the wait queue.
2667 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
2670 if (tevent_req_nomem(subreq
, req
)) {
2678 * Now we add our own waiter to the end of the queue,
2679 * this way we get notified when all pending requests are finished
2680 * and reply to the outstanding SMB1 request.
2682 subreq
= tevent_queue_wait_send(state
,
2685 if (tevent_req_nomem(subreq
, req
)) {
2691 * We're really going async - move the SMB1 request from
2692 * a talloc stackframe above us to the sconn talloc-context.
2693 * We need this to stick around until the wait_done
2694 * callback is invoked.
2696 smb1req
= talloc_move(sconn
, &smb1req
);
2698 tevent_req_set_callback(subreq
, reply_ulogoffX_wait_done
, req
);
2703 static void reply_ulogoffX_wait_done(struct tevent_req
*subreq
)
2705 struct tevent_req
*req
= tevent_req_callback_data(
2706 subreq
, struct tevent_req
);
2708 tevent_queue_wait_recv(subreq
);
2709 TALLOC_FREE(subreq
);
2710 tevent_req_done(req
);
2713 static NTSTATUS
reply_ulogoffX_recv(struct tevent_req
*req
)
2715 return tevent_req_simple_recv_ntstatus(req
);
2718 static void reply_ulogoffX_done(struct tevent_req
*req
)
2720 struct smb_request
*smb1req
= tevent_req_callback_data(
2721 req
, struct smb_request
);
2722 struct reply_ulogoffX_state
*state
= tevent_req_data(req
,
2723 struct reply_ulogoffX_state
);
2724 struct smbXsrv_session
*session
= state
->session
;
2728 * Take the profile charge here. Not strictly
2729 * correct but better than the other SMB1 async
2730 * code that double-charges at the moment.
2732 START_PROFILE(SMBulogoffX
);
2734 status
= reply_ulogoffX_recv(req
);
2736 if (!NT_STATUS_IS_OK(status
)) {
2737 TALLOC_FREE(smb1req
);
2738 END_PROFILE(SMBulogoffX
);
2739 exit_server(__location__
": reply_ulogoffX_recv failed");
2743 status
= smbXsrv_session_logoff(session
);
2744 if (!NT_STATUS_IS_OK(status
)) {
2745 TALLOC_FREE(smb1req
);
2746 END_PROFILE(SMBulogoffX
);
2747 exit_server(__location__
": smbXsrv_session_logoff failed");
2751 TALLOC_FREE(session
);
2753 reply_outbuf(smb1req
, 2, 0);
2754 SSVAL(smb1req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2755 SSVAL(smb1req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2757 DBG_NOTICE("ulogoffX vuid=%llu\n",
2758 (unsigned long long)smb1req
->vuid
);
2760 smb1req
->vuid
= UID_FIELD_INVALID
;
2762 * The following call is needed to push the
2763 * reply data back out the socket after async
2764 * return. Plus it frees smb1req.
2766 smb_request_done(smb1req
);
2767 END_PROFILE(SMBulogoffX
);
2770 /****************************************************************************
2771 Reply to a mknew or a create.
2772 ****************************************************************************/
2774 void reply_mknew(struct smb_request
*req
)
2776 connection_struct
*conn
= req
->conn
;
2777 struct smb_filename
*smb_fname
= NULL
;
2780 struct smb_file_time ft
;
2782 int oplock_request
= 0;
2784 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2785 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2786 uint32_t create_disposition
;
2787 uint32_t create_options
= 0;
2789 TALLOC_CTX
*ctx
= talloc_tos();
2791 START_PROFILE(SMBcreate
);
2792 init_smb_file_time(&ft
);
2795 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2799 fattr
= SVAL(req
->vwv
+0, 0);
2800 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2802 if (req
->cmd
== SMBmknew
) {
2803 /* We should fail if file exists. */
2804 create_disposition
= FILE_CREATE
;
2806 /* Create if file doesn't exist, truncate if it does. */
2807 create_disposition
= FILE_OVERWRITE_IF
;
2811 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date3(req
->vwv
+1));
2813 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2814 STR_TERMINATE
, &status
);
2815 if (!NT_STATUS_IS_OK(status
)) {
2816 reply_nterror(req
, status
);
2820 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2821 status
= filename_convert(ctx
,
2827 if (!NT_STATUS_IS_OK(status
)) {
2828 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2829 reply_botherror(req
,
2830 NT_STATUS_PATH_NOT_COVERED
,
2831 ERRSRV
, ERRbadpath
);
2834 reply_nterror(req
, status
);
2838 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2839 DEBUG(0,("Attempt to create file (%s) with volid set - "
2840 "please report this\n",
2841 smb_fname_str_dbg(smb_fname
)));
2844 status
= SMB_VFS_CREATE_FILE(
2847 smb_fname
, /* fname */
2848 access_mask
, /* access_mask */
2849 share_mode
, /* share_access */
2850 create_disposition
, /* create_disposition*/
2851 create_options
, /* create_options */
2852 fattr
, /* file_attributes */
2853 oplock_request
, /* oplock_request */
2855 0, /* allocation_size */
2856 0, /* private_flags */
2861 NULL
, NULL
); /* create context */
2863 if (!NT_STATUS_IS_OK(status
)) {
2864 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2865 /* We have re-scheduled this call. */
2868 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2869 bool ok
= defer_smb1_sharing_violation(req
);
2874 reply_openerror(req
, status
);
2878 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2879 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2880 if (!NT_STATUS_IS_OK(status
)) {
2881 END_PROFILE(SMBcreate
);
2885 reply_outbuf(req
, 1, 0);
2886 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2888 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2889 SCVAL(req
->outbuf
,smb_flg
,
2890 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2893 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2894 SCVAL(req
->outbuf
,smb_flg
,
2895 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2898 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2899 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2900 smb_fname_str_dbg(smb_fname
), fsp_get_io_fd(fsp
),
2901 (unsigned int)fattr
));
2904 TALLOC_FREE(smb_fname
);
2905 END_PROFILE(SMBcreate
);
2909 /****************************************************************************
2910 Reply to a create temporary file.
2911 ****************************************************************************/
2913 void reply_ctemp(struct smb_request
*req
)
2915 connection_struct
*conn
= req
->conn
;
2916 struct smb_filename
*smb_fname
= NULL
;
2917 char *wire_name
= NULL
;
2926 TALLOC_CTX
*ctx
= talloc_tos();
2928 START_PROFILE(SMBctemp
);
2931 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2935 fattr
= SVAL(req
->vwv
+0, 0);
2936 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2938 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2939 STR_TERMINATE
, &status
);
2940 if (!NT_STATUS_IS_OK(status
)) {
2941 reply_nterror(req
, status
);
2945 for (i
= 0; i
< 10; i
++) {
2947 fname
= talloc_asprintf(ctx
,
2950 generate_random_str_list(ctx
, 5, "0123456789"));
2952 fname
= talloc_asprintf(ctx
,
2954 generate_random_str_list(ctx
, 5, "0123456789"));
2958 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2962 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2963 status
= filename_convert(ctx
, conn
,
2968 if (!NT_STATUS_IS_OK(status
)) {
2969 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2970 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2971 ERRSRV
, ERRbadpath
);
2974 reply_nterror(req
, status
);
2978 /* Create the file. */
2979 status
= SMB_VFS_CREATE_FILE(
2982 smb_fname
, /* fname */
2983 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2984 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2985 FILE_CREATE
, /* create_disposition*/
2986 0, /* create_options */
2987 fattr
, /* file_attributes */
2988 oplock_request
, /* oplock_request */
2990 0, /* allocation_size */
2991 0, /* private_flags */
2996 NULL
, NULL
); /* create context */
2998 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
3000 TALLOC_FREE(smb_fname
);
3004 if (!NT_STATUS_IS_OK(status
)) {
3005 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3006 /* We have re-scheduled this call. */
3009 if (NT_STATUS_EQUAL(
3010 status
, NT_STATUS_SHARING_VIOLATION
)) {
3011 bool ok
= defer_smb1_sharing_violation(req
);
3016 reply_openerror(req
, status
);
3024 /* Collision after 10 times... */
3025 reply_nterror(req
, status
);
3029 reply_outbuf(req
, 1, 0);
3030 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
3032 /* the returned filename is relative to the directory */
3033 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
3035 s
= fsp
->fsp_name
->base_name
;
3041 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3042 thing in the byte section. JRA */
3043 SSVALS(p
, 0, -1); /* what is this? not in spec */
3045 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
3047 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3051 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
3052 SCVAL(req
->outbuf
, smb_flg
,
3053 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
3056 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
3057 SCVAL(req
->outbuf
, smb_flg
,
3058 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
3061 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
3062 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
3063 fsp_get_io_fd(fsp
), (unsigned int)smb_fname
->st
.st_ex_mode
));
3065 TALLOC_FREE(smb_fname
);
3066 TALLOC_FREE(wire_name
);
3067 END_PROFILE(SMBctemp
);
3071 /*******************************************************************
3072 Check if a user is allowed to rename a file.
3073 ********************************************************************/
3075 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
3078 if (!CAN_WRITE(conn
)) {
3079 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
3082 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
3083 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
3084 /* Only bother to read the DOS attribute if we might deny the
3085 rename on the grounds of attribute mismatch. */
3086 uint32_t fmode
= fdos_mode(fsp
);
3087 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
3088 return NT_STATUS_NO_SUCH_FILE
;
3092 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
3093 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
3094 return NT_STATUS_OK
;
3097 /* If no pathnames are open below this
3098 directory, allow the rename. */
3100 if (lp_strict_rename(SNUM(conn
))) {
3102 * Strict rename, check open file db.
3104 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
3105 return NT_STATUS_ACCESS_DENIED
;
3107 } else if (file_find_subpath(fsp
)) {
3109 * No strict rename, just look in local process.
3111 return NT_STATUS_ACCESS_DENIED
;
3113 return NT_STATUS_OK
;
3116 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
3117 return NT_STATUS_OK
;
3120 return NT_STATUS_ACCESS_DENIED
;
3123 /*******************************************************************
3124 * unlink a file with all relevant access checks
3125 *******************************************************************/
3127 static NTSTATUS
do_unlink(connection_struct
*conn
,
3128 struct smb_request
*req
,
3129 struct smb_filename
*smb_fname
,
3134 uint32_t dirtype_orig
= dirtype
;
3137 struct smb2_create_blobs
*posx
= NULL
;
3139 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3140 smb_fname_str_dbg(smb_fname
),
3143 if (!CAN_WRITE(conn
)) {
3144 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
3147 ret
= vfs_stat(conn
, smb_fname
);
3149 return map_nt_error_from_unix(errno
);
3152 fattr
= fdos_mode(smb_fname
->fsp
);
3154 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
3155 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
3158 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
3160 return NT_STATUS_NO_SUCH_FILE
;
3163 if (!dir_check_ftype(fattr
, dirtype
)) {
3164 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
3165 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3167 return NT_STATUS_NO_SUCH_FILE
;
3170 if (dirtype_orig
& 0x8000) {
3171 /* These will never be set for POSIX. */
3172 return NT_STATUS_NO_SUCH_FILE
;
3176 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
3177 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3180 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
3181 return NT_STATUS_NO_SUCH_FILE
;
3184 if (dirtype
& 0xFF00) {
3185 /* These will never be set for POSIX. */
3186 return NT_STATUS_NO_SUCH_FILE
;
3191 return NT_STATUS_NO_SUCH_FILE
;
3194 /* Can't delete a directory. */
3195 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
3196 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3201 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
3202 return NT_STATUS_OBJECT_NAME_INVALID
;
3203 #endif /* JRATEST */
3205 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
) {
3206 status
= make_smb2_posix_create_ctx(
3207 talloc_tos(), &posx
, 0777);
3208 if (!NT_STATUS_IS_OK(status
)) {
3209 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3215 /* On open checks the open itself will check the share mode, so
3216 don't do it here as we'll get it wrong. */
3218 status
= SMB_VFS_CREATE_FILE
3221 smb_fname
, /* fname */
3222 DELETE_ACCESS
, /* access_mask */
3223 FILE_SHARE_NONE
, /* share_access */
3224 FILE_OPEN
, /* create_disposition*/
3225 FILE_NON_DIRECTORY_FILE
, /* create_options */
3226 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
3227 0, /* oplock_request */
3229 0, /* allocation_size */
3230 0, /* private_flags */
3235 posx
, /* in_context_blobs */
3236 NULL
); /* out_context_blobs */
3240 if (!NT_STATUS_IS_OK(status
)) {
3241 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3242 nt_errstr(status
)));
3246 status
= can_set_delete_on_close(fsp
, fattr
);
3247 if (!NT_STATUS_IS_OK(status
)) {
3248 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3250 smb_fname_str_dbg(smb_fname
),
3251 nt_errstr(status
)));
3252 close_file(req
, fsp
, NORMAL_CLOSE
);
3256 /* The set is across all open files on this dev/inode pair. */
3257 if (!set_delete_on_close(fsp
, True
,
3258 conn
->session_info
->security_token
,
3259 conn
->session_info
->unix_token
)) {
3260 close_file(req
, fsp
, NORMAL_CLOSE
);
3261 return NT_STATUS_ACCESS_DENIED
;
3264 return close_file(req
, fsp
, NORMAL_CLOSE
);
3267 /****************************************************************************
3268 The guts of the unlink command, split out so it may be called by the NT SMB
3270 ****************************************************************************/
3272 NTSTATUS
unlink_internals(connection_struct
*conn
,
3273 struct smb_request
*req
,
3275 struct smb_filename
*smb_fname
,
3278 char *fname_dir
= NULL
;
3279 char *fname_mask
= NULL
;
3281 NTSTATUS status
= NT_STATUS_OK
;
3282 struct smb_filename
*smb_fname_dir
= NULL
;
3283 TALLOC_CTX
*ctx
= talloc_tos();
3285 /* Split up the directory from the filename/mask. */
3286 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
3287 &fname_dir
, &fname_mask
);
3288 if (!NT_STATUS_IS_OK(status
)) {
3293 * We should only check the mangled cache
3294 * here if unix_convert failed. This means
3295 * that the path in 'mask' doesn't exist
3296 * on the file system and so we need to look
3297 * for a possible mangle. This patch from
3298 * Tine Smukavec <valentin.smukavec@hermes.si>.
3301 if (!VALID_STAT(smb_fname
->st
) &&
3302 mangle_is_mangled(fname_mask
, conn
->params
)) {
3303 char *new_mask
= NULL
;
3304 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
3305 &new_mask
, conn
->params
);
3307 TALLOC_FREE(fname_mask
);
3308 fname_mask
= new_mask
;
3315 * Only one file needs to be unlinked. Append the mask back
3316 * onto the directory.
3318 TALLOC_FREE(smb_fname
->base_name
);
3319 if (ISDOT(fname_dir
)) {
3320 /* Ensure we use canonical names on open. */
3321 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3325 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3330 if (!smb_fname
->base_name
) {
3331 status
= NT_STATUS_NO_MEMORY
;
3335 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3338 status
= check_name(conn
, smb_fname
);
3339 if (!NT_STATUS_IS_OK(status
)) {
3343 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3344 if (!NT_STATUS_IS_OK(status
)) {
3350 struct smb_Dir
*dir_hnd
= NULL
;
3352 const char *dname
= NULL
;
3353 char *talloced
= NULL
;
3355 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
3356 status
= NT_STATUS_OBJECT_NAME_INVALID
;
3360 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3363 if (strequal(fname_mask
,"????????.???")) {
3364 TALLOC_FREE(fname_mask
);
3365 fname_mask
= talloc_strdup(ctx
, "*");
3367 status
= NT_STATUS_NO_MEMORY
;
3372 smb_fname_dir
= synthetic_smb_fname(talloc_tos(),
3378 if (smb_fname_dir
== NULL
) {
3379 status
= NT_STATUS_NO_MEMORY
;
3383 status
= check_name(conn
, smb_fname_dir
);
3384 if (!NT_STATUS_IS_OK(status
)) {
3388 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_dir
, fname_mask
,
3390 if (dir_hnd
== NULL
) {
3391 status
= map_nt_error_from_unix(errno
);
3395 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3396 the pattern matches against the long name, otherwise the short name
3397 We don't implement this yet XXXX
3400 status
= NT_STATUS_NO_SUCH_FILE
;
3402 while ((dname
= ReadDirName(dir_hnd
, &offset
,
3403 &smb_fname
->st
, &talloced
))) {
3404 TALLOC_CTX
*frame
= talloc_stackframe();
3406 struct smb_filename
*f
= NULL
;
3408 if (!is_visible_file(conn
,
3414 TALLOC_FREE(talloced
);
3418 /* Quick check for "." and ".." */
3419 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
3421 TALLOC_FREE(talloced
);
3425 if(!mask_match(dname
, fname_mask
,
3426 conn
->case_sensitive
)) {
3428 TALLOC_FREE(talloced
);
3432 if (ISDOT(fname_dir
)) {
3433 /* Ensure we use canonical names on open. */
3434 p
= talloc_asprintf(smb_fname
, "%s", dname
);
3436 p
= talloc_asprintf(smb_fname
, "%s/%s",
3440 TALLOC_FREE(dir_hnd
);
3441 status
= NT_STATUS_NO_MEMORY
;
3443 TALLOC_FREE(talloced
);
3446 f
= synthetic_smb_fname(frame
,
3453 TALLOC_FREE(dir_hnd
);
3454 status
= NT_STATUS_NO_MEMORY
;
3456 TALLOC_FREE(talloced
);
3460 status
= openat_pathref_fsp(conn
->cwd_fsp
, f
);
3461 if (!NT_STATUS_IS_OK(status
) &&
3462 !NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
))
3464 TALLOC_FREE(dir_hnd
);
3466 TALLOC_FREE(talloced
);
3470 status
= check_name(conn
, f
);
3471 if (!NT_STATUS_IS_OK(status
)) {
3472 TALLOC_FREE(dir_hnd
);
3474 TALLOC_FREE(talloced
);
3478 status
= do_unlink(conn
, req
, f
, dirtype
);
3479 if (!NT_STATUS_IS_OK(status
)) {
3480 TALLOC_FREE(dir_hnd
);
3482 TALLOC_FREE(talloced
);
3487 DBG_DEBUG("successful unlink [%s]\n",
3488 smb_fname_str_dbg(f
));
3491 TALLOC_FREE(talloced
);
3493 TALLOC_FREE(dir_hnd
);
3496 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3497 status
= map_nt_error_from_unix(errno
);
3501 TALLOC_FREE(smb_fname_dir
);
3502 TALLOC_FREE(fname_dir
);
3503 TALLOC_FREE(fname_mask
);
3507 /****************************************************************************
3509 ****************************************************************************/
3511 void reply_unlink(struct smb_request
*req
)
3513 connection_struct
*conn
= req
->conn
;
3515 struct smb_filename
*smb_fname
= NULL
;
3518 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
3519 ucf_flags_from_smb_request(req
);
3520 TALLOC_CTX
*ctx
= talloc_tos();
3521 bool has_wild
= false;
3523 START_PROFILE(SMBunlink
);
3526 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3530 dirtype
= SVAL(req
->vwv
+0, 0);
3532 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3533 STR_TERMINATE
, &status
);
3534 if (!NT_STATUS_IS_OK(status
)) {
3535 reply_nterror(req
, status
);
3539 status
= filename_convert(ctx
, conn
,
3544 if (!NT_STATUS_IS_OK(status
)) {
3545 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3546 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3547 ERRSRV
, ERRbadpath
);
3550 reply_nterror(req
, status
);
3554 if (req
!= NULL
&& !req
->posix_pathnames
) {
3555 char *lcomp
= get_original_lcomp(ctx
,
3559 if (lcomp
== NULL
) {
3560 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3563 has_wild
= ms_has_wild(lcomp
);
3567 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3569 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
, has_wild
);
3570 if (!NT_STATUS_IS_OK(status
)) {
3571 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3572 /* We have re-scheduled this call. */
3575 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
3576 bool ok
= defer_smb1_sharing_violation(req
);
3581 reply_nterror(req
, status
);
3585 reply_outbuf(req
, 0, 0);
3587 TALLOC_FREE(smb_fname
);
3588 END_PROFILE(SMBunlink
);
3592 /****************************************************************************
3594 ****************************************************************************/
3596 static void fail_readraw(void)
3598 const char *errstr
= talloc_asprintf(talloc_tos(),
3599 "FAIL ! reply_readbraw: socket write fail (%s)",
3604 exit_server_cleanly(errstr
);
3607 /****************************************************************************
3608 Fake (read/write) sendfile. Returns -1 on read or write fail.
3609 ****************************************************************************/
3611 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3612 off_t startpos
, size_t nread
)
3615 size_t tosend
= nread
;
3622 bufsize
= MIN(nread
, 65536);
3624 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3628 while (tosend
> 0) {
3632 cur_read
= MIN(tosend
, bufsize
);
3633 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3639 /* If we had a short read, fill with zeros. */
3640 if (ret
< cur_read
) {
3641 memset(buf
+ ret
, '\0', cur_read
- ret
);
3644 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3645 if (ret
!= cur_read
) {
3646 int saved_errno
= errno
;
3648 * Try and give an error message saying what
3651 DEBUG(0, ("write_data failed for client %s. "
3653 smbXsrv_connection_dbg(xconn
),
3654 strerror(saved_errno
)));
3656 errno
= saved_errno
;
3660 startpos
+= cur_read
;
3664 return (ssize_t
)nread
;
3667 /****************************************************************************
3668 Deal with the case of sendfile reading less bytes from the file than
3669 requested. Fill with zeros (all we can do). Returns 0 on success
3670 ****************************************************************************/
3672 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3678 #define SHORT_SEND_BUFSIZE 1024
3679 if (nread
< headersize
) {
3680 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3681 "header for file %s (%s). Terminating\n",
3682 fsp_str_dbg(fsp
), strerror(errno
)));
3686 nread
-= headersize
;
3688 if (nread
< smb_maxcnt
) {
3689 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3691 DEBUG(0,("sendfile_short_send: malloc failed "
3692 "for file %s (%s). Terminating\n",
3693 fsp_str_dbg(fsp
), strerror(errno
)));
3697 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3698 "with zeros !\n", fsp_str_dbg(fsp
)));
3700 while (nread
< smb_maxcnt
) {
3702 * We asked for the real file size and told sendfile
3703 * to not go beyond the end of the file. But it can
3704 * happen that in between our fstat call and the
3705 * sendfile call the file was truncated. This is very
3706 * bad because we have already announced the larger
3707 * number of bytes to the client.
3709 * The best we can do now is to send 0-bytes, just as
3710 * a read from a hole in a sparse file would do.
3712 * This should happen rarely enough that I don't care
3713 * about efficiency here :-)
3718 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3719 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3720 if (ret
!= to_write
) {
3721 int saved_errno
= errno
;
3723 * Try and give an error message saying what
3726 DEBUG(0, ("write_data failed for client %s. "
3728 smbXsrv_connection_dbg(xconn
),
3729 strerror(saved_errno
)));
3730 errno
= saved_errno
;
3741 /****************************************************************************
3742 Return a readbraw error (4 bytes of zero).
3743 ****************************************************************************/
3745 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3751 smbd_lock_socket(xconn
);
3752 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3753 int saved_errno
= errno
;
3755 * Try and give an error message saying what
3758 DEBUG(0, ("write_data failed for client %s. "
3760 smbXsrv_connection_dbg(xconn
),
3761 strerror(saved_errno
)));
3762 errno
= saved_errno
;
3766 smbd_unlock_socket(xconn
);
3769 /*******************************************************************
3770 Ensure we don't use sendfile if server smb signing is active.
3771 ********************************************************************/
3773 static bool lp_use_sendfile(int snum
, struct smb_signing_state
*signing_state
)
3775 bool sign_active
= false;
3777 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3778 if (get_Protocol() < PROTOCOL_NT1
) {
3781 if (signing_state
) {
3782 sign_active
= smb_signing_is_active(signing_state
);
3784 return (lp__use_sendfile(snum
) &&
3785 (get_remote_arch() != RA_WIN95
) &&
3788 /****************************************************************************
3789 Use sendfile in readbraw.
3790 ****************************************************************************/
3792 static void send_file_readbraw(connection_struct
*conn
,
3793 struct smb_request
*req
,
3799 struct smbXsrv_connection
*xconn
= req
->xconn
;
3800 char *outbuf
= NULL
;
3804 * We can only use sendfile on a non-chained packet
3805 * but we can use on a non-oplocked file. tridge proved this
3806 * on a train in Germany :-). JRA.
3807 * reply_readbraw has already checked the length.
3810 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3811 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3812 ssize_t sendfile_read
= -1;
3814 DATA_BLOB header_blob
;
3816 _smb_setlen(header
,nread
);
3817 header_blob
= data_blob_const(header
, 4);
3819 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3820 &header_blob
, startpos
,
3822 if (sendfile_read
== -1) {
3823 /* Returning ENOSYS means no data at all was sent.
3824 * Do this as a normal read. */
3825 if (errno
== ENOSYS
) {
3826 goto normal_readbraw
;
3830 * Special hack for broken Linux with no working sendfile. If we
3831 * return EINTR we sent the header but not the rest of the data.
3832 * Fake this up by doing read/write calls.
3834 if (errno
== EINTR
) {
3835 /* Ensure we don't do this again. */
3836 set_use_sendfile(SNUM(conn
), False
);
3837 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3839 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3840 DEBUG(0,("send_file_readbraw: "
3841 "fake_sendfile failed for "
3845 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3850 DEBUG(0,("send_file_readbraw: sendfile failed for "
3851 "file %s (%s). Terminating\n",
3852 fsp_str_dbg(fsp
), strerror(errno
)));
3853 exit_server_cleanly("send_file_readbraw sendfile failed");
3854 } else if (sendfile_read
== 0) {
3856 * Some sendfile implementations return 0 to indicate
3857 * that there was a short read, but nothing was
3858 * actually written to the socket. In this case,
3859 * fallback to the normal read path so the header gets
3860 * the correct byte count.
3862 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3863 "bytes falling back to the normal read: "
3864 "%s\n", fsp_str_dbg(fsp
)));
3865 goto normal_readbraw
;
3868 /* Deal with possible short send. */
3869 if (sendfile_read
!= 4+nread
) {
3870 ret
= sendfile_short_send(xconn
, fsp
,
3871 sendfile_read
, 4, nread
);
3881 outbuf
= talloc_array(NULL
, char, nread
+4);
3883 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3884 (unsigned)(nread
+4)));
3885 reply_readbraw_error(xconn
);
3890 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3891 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3900 _smb_setlen(outbuf
,ret
);
3901 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3902 int saved_errno
= errno
;
3904 * Try and give an error message saying what
3907 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3908 smbXsrv_connection_dbg(xconn
),
3909 strerror(saved_errno
)));
3910 errno
= saved_errno
;
3915 TALLOC_FREE(outbuf
);
3918 /****************************************************************************
3919 Reply to a readbraw (core+ protocol).
3920 ****************************************************************************/
3922 void reply_readbraw(struct smb_request
*req
)
3924 connection_struct
*conn
= req
->conn
;
3925 struct smbXsrv_connection
*xconn
= req
->xconn
;
3926 ssize_t maxcount
,mincount
;
3930 struct lock_struct lock
;
3934 START_PROFILE(SMBreadbraw
);
3936 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3937 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3938 "raw reads/writes are disallowed.");
3942 reply_readbraw_error(xconn
);
3943 END_PROFILE(SMBreadbraw
);
3947 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3948 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3949 "'async smb echo handler = yes'\n"));
3950 reply_readbraw_error(xconn
);
3951 END_PROFILE(SMBreadbraw
);
3956 * Special check if an oplock break has been issued
3957 * and the readraw request croses on the wire, we must
3958 * return a zero length response here.
3961 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3964 * We have to do a check_fsp by hand here, as
3965 * we must always return 4 zero bytes on error,
3971 conn
!= fsp
->conn
||
3972 req
->vuid
!= fsp
->vuid
||
3973 fsp
->fsp_flags
.is_directory
||
3974 fsp_get_io_fd(fsp
) == -1)
3977 * fsp could be NULL here so use the value from the packet. JRA.
3979 DEBUG(3,("reply_readbraw: fnum %d not valid "
3981 (int)SVAL(req
->vwv
+0, 0)));
3982 reply_readbraw_error(xconn
);
3983 END_PROFILE(SMBreadbraw
);
3987 /* Do a "by hand" version of CHECK_READ. */
3988 if (!(fsp
->fsp_flags
.can_read
||
3989 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3990 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3991 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3992 (int)SVAL(req
->vwv
+0, 0)));
3993 reply_readbraw_error(xconn
);
3994 END_PROFILE(SMBreadbraw
);
3998 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3999 if(req
->wct
== 10) {
4001 * This is a large offset (64 bit) read.
4004 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
4007 DEBUG(0,("reply_readbraw: negative 64 bit "
4008 "readraw offset (%.0f) !\n",
4009 (double)startpos
));
4010 reply_readbraw_error(xconn
);
4011 END_PROFILE(SMBreadbraw
);
4016 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
4017 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
4019 /* ensure we don't overrun the packet size */
4020 maxcount
= MIN(65535,maxcount
);
4022 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4023 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
4026 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4027 reply_readbraw_error(xconn
);
4028 END_PROFILE(SMBreadbraw
);
4032 status
= vfs_stat_fsp(fsp
);
4033 if (NT_STATUS_IS_OK(status
)) {
4034 size
= fsp
->fsp_name
->st
.st_ex_size
;
4037 if (startpos
>= size
) {
4040 nread
= MIN(maxcount
,(size
- startpos
));
4043 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4044 if (nread
< mincount
)
4048 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4049 "min=%lu nread=%lu\n",
4050 fsp_fnum_dbg(fsp
), (double)startpos
,
4051 (unsigned long)maxcount
,
4052 (unsigned long)mincount
,
4053 (unsigned long)nread
) );
4055 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
4057 DEBUG(5,("reply_readbraw finished\n"));
4059 END_PROFILE(SMBreadbraw
);
4064 #define DBGC_CLASS DBGC_LOCKING
4066 /****************************************************************************
4067 Reply to a lockread (core+ protocol).
4068 ****************************************************************************/
4070 static void reply_lockread_locked(struct tevent_req
*subreq
);
4072 void reply_lockread(struct smb_request
*req
)
4074 struct tevent_req
*subreq
= NULL
;
4075 connection_struct
*conn
= req
->conn
;
4077 struct smbd_lock_element
*lck
= NULL
;
4079 START_PROFILE(SMBlockread
);
4082 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4083 END_PROFILE(SMBlockread
);
4087 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4089 if (!check_fsp(conn
, req
, fsp
)) {
4090 END_PROFILE(SMBlockread
);
4094 if (!CHECK_READ(fsp
,req
)) {
4095 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4096 END_PROFILE(SMBlockread
);
4100 lck
= talloc(req
, struct smbd_lock_element
);
4102 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4103 END_PROFILE(SMBlockread
);
4108 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4109 * protocol request that predates the read/write lock concept.
4110 * Thus instead of asking for a read lock here we need to ask
4111 * for a write lock. JRA.
4112 * Note that the requested lock size is unaffected by max_send.
4115 *lck
= (struct smbd_lock_element
) {
4116 .req_guid
= smbd_request_guid(req
, 0),
4117 .smblctx
= req
->smbpid
,
4118 .brltype
= WRITE_LOCK
,
4119 .count
= SVAL(req
->vwv
+1, 0),
4120 .offset
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0),
4123 subreq
= smbd_smb1_do_locks_send(
4129 false, /* large_offset */
4133 if (subreq
== NULL
) {
4134 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4135 END_PROFILE(SMBlockread
);
4138 tevent_req_set_callback(subreq
, reply_lockread_locked
, NULL
);
4139 END_PROFILE(SMBlockread
);
4142 static void reply_lockread_locked(struct tevent_req
*subreq
)
4144 struct smb_request
*req
= NULL
;
4150 size_t numtoread
, maxtoread
;
4151 struct files_struct
*fsp
= NULL
;
4154 START_PROFILE(SMBlockread
);
4156 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
4159 status
= smbd_smb1_do_locks_recv(subreq
);
4160 TALLOC_FREE(subreq
);
4162 if (!NT_STATUS_IS_OK(status
)) {
4163 reply_nterror(req
, status
);
4167 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4169 reply_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
4173 numtoread
= SVAL(req
->vwv
+1, 0);
4174 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4177 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4179 maxtoread
= req
->xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
4181 if (numtoread
> maxtoread
) {
4182 DBG_WARNING("requested read size (%zu) is greater than "
4183 "maximum allowed (%zu/%d). "
4184 "Returning short read of maximum allowed for "
4185 "compatibility with Windows 2000.\n",
4188 req
->xconn
->smb1
.sessions
.max_send
);
4189 numtoread
= maxtoread
;
4192 reply_outbuf(req
, 5, numtoread
+ 3);
4194 data
= smb_buf(req
->outbuf
) + 3;
4196 nread
= read_file(fsp
,data
,startpos
,numtoread
);
4199 reply_nterror(req
, map_nt_error_from_unix(errno
));
4203 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
4205 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
4206 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
4207 p
= smb_buf(req
->outbuf
);
4208 SCVAL(p
,0,0); /* pad byte. */
4211 DEBUG(3,("lockread %s num=%d nread=%d\n",
4212 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
4215 ok
= srv_send_smb(req
->xconn
,
4216 (char *)req
->outbuf
,
4219 IS_CONN_ENCRYPTED(req
->conn
),
4222 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4225 END_PROFILE(SMBlockread
);
4230 #define DBGC_CLASS DBGC_ALL
4232 /****************************************************************************
4234 ****************************************************************************/
4236 void reply_read(struct smb_request
*req
)
4238 connection_struct
*conn
= req
->conn
;
4245 struct lock_struct lock
;
4246 struct smbXsrv_connection
*xconn
= req
->xconn
;
4248 START_PROFILE(SMBread
);
4251 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4252 END_PROFILE(SMBread
);
4256 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4258 if (!check_fsp(conn
, req
, fsp
)) {
4259 END_PROFILE(SMBread
);
4263 if (!CHECK_READ(fsp
,req
)) {
4264 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4265 END_PROFILE(SMBread
);
4269 numtoread
= SVAL(req
->vwv
+1, 0);
4270 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4273 * The requested read size cannot be greater than max_send. JRA.
4275 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
4277 if (numtoread
> maxtoread
) {
4278 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4279 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4280 (unsigned int)numtoread
, (unsigned int)maxtoread
,
4281 (unsigned int)xconn
->smb1
.sessions
.max_send
));
4282 numtoread
= maxtoread
;
4285 reply_outbuf(req
, 5, numtoread
+3);
4287 data
= smb_buf(req
->outbuf
) + 3;
4289 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4290 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
4293 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4294 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4295 END_PROFILE(SMBread
);
4300 nread
= read_file(fsp
,data
,startpos
,numtoread
);
4303 reply_nterror(req
, map_nt_error_from_unix(errno
));
4307 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
4309 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
4310 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
4311 SCVAL(smb_buf(req
->outbuf
),0,1);
4312 SSVAL(smb_buf(req
->outbuf
),1,nread
);
4314 DEBUG(3, ("read %s num=%d nread=%d\n",
4315 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
4318 END_PROFILE(SMBread
);
4322 /****************************************************************************
4324 ****************************************************************************/
4326 size_t setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
4330 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
4333 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
4335 SCVAL(outbuf
,smb_vwv0
,0xFF);
4336 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
4337 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
4338 SSVAL(outbuf
,smb_vwv6
,
4339 (smb_wct
- 4) /* offset from smb header to wct */
4340 + 1 /* the wct field */
4341 + 12 * sizeof(uint16_t) /* vwv */
4342 + 2 /* the buflen field */
4343 + 1); /* padding byte */
4344 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
4345 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
4346 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4347 _smb_setlen_large(outbuf
,
4348 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
4352 /****************************************************************************
4353 Reply to a read and X - possibly using sendfile.
4354 ****************************************************************************/
4356 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
4357 files_struct
*fsp
, off_t startpos
,
4360 struct smbXsrv_connection
*xconn
= req
->xconn
;
4362 struct lock_struct lock
;
4363 int saved_errno
= 0;
4366 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4367 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
4370 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4371 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4376 * We can only use sendfile on a non-chained packet
4377 * but we can use on a non-oplocked file. tridge proved this
4378 * on a train in Germany :-). JRA.
4381 if (!req_is_in_chain(req
) &&
4383 (fsp
->base_fsp
== NULL
) &&
4384 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
4385 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
4388 status
= vfs_stat_fsp(fsp
);
4389 if (!NT_STATUS_IS_OK(status
)) {
4390 reply_nterror(req
, status
);
4394 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4395 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4396 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4398 * We already know that we would do a short read, so don't
4399 * try the sendfile() path.
4401 goto nosendfile_read
;
4405 * Set up the packet header before send. We
4406 * assume here the sendfile will work (get the
4407 * correct amount of data).
4410 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4412 construct_reply_common_req(req
, (char *)headerbuf
);
4413 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4415 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4416 startpos
, smb_maxcnt
);
4418 saved_errno
= errno
;
4420 /* Returning ENOSYS means no data at all was sent.
4421 Do this as a normal read. */
4422 if (errno
== ENOSYS
) {
4427 * Special hack for broken Linux with no working sendfile. If we
4428 * return EINTR we sent the header but not the rest of the data.
4429 * Fake this up by doing read/write calls.
4432 if (errno
== EINTR
) {
4433 /* Ensure we don't do this again. */
4434 set_use_sendfile(SNUM(conn
), False
);
4435 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4436 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4439 saved_errno
= errno
;
4440 DEBUG(0,("send_file_readX: "
4441 "fake_sendfile failed for "
4442 "file %s (%s) for client %s. "
4445 smbXsrv_connection_dbg(xconn
),
4446 strerror(saved_errno
)));
4447 errno
= saved_errno
;
4448 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4450 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4451 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4452 /* No outbuf here means successful sendfile. */
4456 DEBUG(0,("send_file_readX: sendfile failed for file "
4457 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4459 exit_server_cleanly("send_file_readX sendfile failed");
4460 } else if (nread
== 0) {
4462 * Some sendfile implementations return 0 to indicate
4463 * that there was a short read, but nothing was
4464 * actually written to the socket. In this case,
4465 * fallback to the normal read path so the header gets
4466 * the correct byte count.
4468 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4469 "falling back to the normal read: %s\n",
4474 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4475 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4477 /* Deal with possible short send. */
4478 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4481 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4482 sizeof(headerbuf
), smb_maxcnt
);
4485 r
= "send_file_readX: sendfile_short_send failed";
4486 DEBUG(0,("%s for file %s (%s).\n",
4487 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4488 exit_server_cleanly(r
);
4491 /* No outbuf here means successful sendfile. */
4492 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4493 SMB_PERFCOUNT_END(&req
->pcd
);
4499 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4500 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4503 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4504 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4505 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4507 * We already know that we would do a short
4508 * read, so don't try the sendfile() path.
4510 goto nosendfile_read
;
4513 construct_reply_common_req(req
, (char *)headerbuf
);
4514 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4516 /* Send out the header. */
4517 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4519 if (ret
!= sizeof(headerbuf
)) {
4520 saved_errno
= errno
;
4522 * Try and give an error message saying what
4525 DEBUG(0,("send_file_readX: write_data failed for file "
4526 "%s (%s) for client %s. Terminating\n",
4528 smbXsrv_connection_dbg(xconn
),
4529 strerror(saved_errno
)));
4530 errno
= saved_errno
;
4531 exit_server_cleanly("send_file_readX sendfile failed");
4533 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4535 saved_errno
= errno
;
4536 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4537 "%s (%s) for client %s. Terminating\n",
4539 smbXsrv_connection_dbg(xconn
),
4540 strerror(saved_errno
)));
4541 errno
= saved_errno
;
4542 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4549 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4550 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4551 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4553 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4554 startpos
, smb_maxcnt
);
4555 saved_errno
= errno
;
4558 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4562 setup_readX_header((char *)req
->outbuf
, nread
);
4564 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4565 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4569 TALLOC_FREE(req
->outbuf
);
4573 /****************************************************************************
4574 Work out how much space we have for a read return.
4575 ****************************************************************************/
4577 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4579 struct smbXsrv_connection
*xconn
= req
->xconn
;
4581 if (xconn
->protocol
< PROTOCOL_NT1
) {
4582 return xconn
->smb1
.sessions
.max_send
;
4585 if (!lp_large_readwrite()) {
4586 return xconn
->smb1
.sessions
.max_send
;
4589 if (req_is_in_chain(req
)) {
4590 return xconn
->smb1
.sessions
.max_send
;
4593 if (req
->encrypted
) {
4595 * Don't take encrypted traffic up to the
4596 * limit. There are padding considerations
4597 * that make that tricky.
4599 return xconn
->smb1
.sessions
.max_send
;
4602 if (srv_is_signing_active(xconn
)) {
4606 if (!lp_unix_extensions()) {
4611 * We can do ultra-large POSIX reads.
4616 /****************************************************************************
4617 Calculate how big a read can be. Copes with all clients. It's always
4618 safe to return a short read - Windows does this.
4619 ****************************************************************************/
4621 static size_t calc_read_size(const struct smb_request
*req
,
4625 struct smbXsrv_connection
*xconn
= req
->xconn
;
4626 size_t max_pdu
= calc_max_read_pdu(req
);
4627 size_t total_size
= 0;
4628 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4629 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4632 * Windows explicitly ignores upper size of 0xFFFF.
4633 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4634 * We must do the same as these will never fit even in
4635 * an extended size NetBIOS packet.
4637 if (upper_size
== 0xFFFF) {
4641 if (xconn
->protocol
< PROTOCOL_NT1
) {
4645 total_size
= ((upper_size
<<16) | lower_size
);
4648 * LARGE_READX test shows it's always safe to return
4649 * a short read. Windows does so.
4651 return MIN(total_size
, max_len
);
4654 /****************************************************************************
4655 Reply to a read and X.
4656 ****************************************************************************/
4658 void reply_read_and_X(struct smb_request
*req
)
4660 connection_struct
*conn
= req
->conn
;
4665 bool big_readX
= False
;
4667 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4670 START_PROFILE(SMBreadX
);
4672 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4673 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4677 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4678 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4679 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4681 /* If it's an IPC, pass off the pipe handler. */
4683 reply_pipe_read_and_X(req
);
4684 END_PROFILE(SMBreadX
);
4688 if (!check_fsp(conn
, req
, fsp
)) {
4689 END_PROFILE(SMBreadX
);
4693 if (!CHECK_READ(fsp
,req
)) {
4694 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4695 END_PROFILE(SMBreadX
);
4699 upper_size
= SVAL(req
->vwv
+7, 0);
4700 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4701 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4703 * This is a heuristic to avoid keeping large
4704 * outgoing buffers around over long-lived aio
4710 if (req
->wct
== 12) {
4712 * This is a large offset (64 bit) read.
4714 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4719 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4724 if (NT_STATUS_IS_OK(status
)) {
4725 /* Read scheduled - we're done. */
4728 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4729 /* Real error - report to client. */
4730 END_PROFILE(SMBreadX
);
4731 reply_nterror(req
, status
);
4734 /* NT_STATUS_RETRY - fall back to sync read. */
4737 smbd_lock_socket(req
->xconn
);
4738 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4739 smbd_unlock_socket(req
->xconn
);
4742 END_PROFILE(SMBreadX
);
4746 /****************************************************************************
4747 Error replies to writebraw must have smb_wct == 1. Fix this up.
4748 ****************************************************************************/
4750 void error_to_writebrawerr(struct smb_request
*req
)
4752 uint8_t *old_outbuf
= req
->outbuf
;
4754 reply_outbuf(req
, 1, 0);
4756 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4757 TALLOC_FREE(old_outbuf
);
4760 /****************************************************************************
4761 Read 4 bytes of a smb packet and return the smb length of the packet.
4762 Store the result in the buffer. This version of the function will
4763 never return a session keepalive (length of zero).
4764 Timeout is in milliseconds.
4765 ****************************************************************************/
4767 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4770 uint8_t msgtype
= NBSSkeepalive
;
4772 while (msgtype
== NBSSkeepalive
) {
4775 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4777 if (!NT_STATUS_IS_OK(status
)) {
4778 char addr
[INET6_ADDRSTRLEN
];
4779 /* Try and give an error message
4780 * saying what client failed. */
4781 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4782 "client %s read error = %s.\n",
4783 get_peer_addr(fd
,addr
,sizeof(addr
)),
4784 nt_errstr(status
)));
4788 msgtype
= CVAL(inbuf
, 0);
4791 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4792 (unsigned long)len
));
4794 return NT_STATUS_OK
;
4797 /****************************************************************************
4798 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4799 ****************************************************************************/
4801 void reply_writebraw(struct smb_request
*req
)
4803 connection_struct
*conn
= req
->conn
;
4804 struct smbXsrv_connection
*xconn
= req
->xconn
;
4807 ssize_t total_written
=0;
4808 size_t numtowrite
=0;
4811 const char *data
=NULL
;
4814 struct lock_struct lock
;
4817 START_PROFILE(SMBwritebraw
);
4820 * If we ever reply with an error, it must have the SMB command
4821 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4824 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4826 if (srv_is_signing_active(xconn
)) {
4827 END_PROFILE(SMBwritebraw
);
4828 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4829 "raw reads/writes are disallowed.");
4832 if (req
->wct
< 12) {
4833 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4834 error_to_writebrawerr(req
);
4835 END_PROFILE(SMBwritebraw
);
4839 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4840 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4841 "'async smb echo handler = yes'\n"));
4842 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4843 error_to_writebrawerr(req
);
4844 END_PROFILE(SMBwritebraw
);
4848 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4849 if (!check_fsp(conn
, req
, fsp
)) {
4850 error_to_writebrawerr(req
);
4851 END_PROFILE(SMBwritebraw
);
4855 if (!CHECK_WRITE(fsp
)) {
4856 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4857 error_to_writebrawerr(req
);
4858 END_PROFILE(SMBwritebraw
);
4862 tcount
= IVAL(req
->vwv
+1, 0);
4863 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4864 write_through
= BITSETW(req
->vwv
+7,0);
4866 /* We have to deal with slightly different formats depending
4867 on whether we are using the core+ or lanman1.0 protocol */
4869 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4870 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4871 data
= smb_buf_const(req
->inbuf
);
4873 numtowrite
= SVAL(req
->vwv
+10, 0);
4874 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4877 /* Ensure we don't write bytes past the end of this packet. */
4879 * This already protects us against CVE-2017-12163.
4881 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4882 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4883 error_to_writebrawerr(req
);
4884 END_PROFILE(SMBwritebraw
);
4888 if (!fsp
->print_file
) {
4889 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4890 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4893 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4894 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4895 error_to_writebrawerr(req
);
4896 END_PROFILE(SMBwritebraw
);
4902 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4905 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4906 "wrote=%d sync=%d\n",
4907 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4908 (int)nwritten
, (int)write_through
));
4910 if (nwritten
< (ssize_t
)numtowrite
) {
4911 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4912 error_to_writebrawerr(req
);
4916 total_written
= nwritten
;
4918 /* Allocate a buffer of 64k + length. */
4919 buf
= talloc_array(NULL
, char, 65540);
4921 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4922 error_to_writebrawerr(req
);
4926 /* Return a SMBwritebraw message to the redirector to tell
4927 * it to send more bytes */
4929 memcpy(buf
, req
->inbuf
, smb_size
);
4930 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4931 SCVAL(buf
,smb_com
,SMBwritebraw
);
4932 SSVALS(buf
,smb_vwv0
,0xFFFF);
4934 if (!srv_send_smb(req
->xconn
,
4936 false, 0, /* no signing */
4937 IS_CONN_ENCRYPTED(conn
),
4939 exit_server_cleanly("reply_writebraw: srv_send_smb "
4943 /* Now read the raw data into the buffer and write it */
4944 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4946 if (!NT_STATUS_IS_OK(status
)) {
4947 exit_server_cleanly("secondary writebraw failed");
4950 /* Set up outbuf to return the correct size */
4951 reply_outbuf(req
, 1, 0);
4953 if (numtowrite
!= 0) {
4955 if (numtowrite
> 0xFFFF) {
4956 DEBUG(0,("reply_writebraw: Oversize secondary write "
4957 "raw requested (%u). Terminating\n",
4958 (unsigned int)numtowrite
));
4959 exit_server_cleanly("secondary writebraw failed");
4962 if (tcount
> nwritten
+numtowrite
) {
4963 DEBUG(3,("reply_writebraw: Client overestimated the "
4965 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4968 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4971 if (!NT_STATUS_IS_OK(status
)) {
4972 /* Try and give an error message
4973 * saying what client failed. */
4974 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4975 "raw read failed (%s) for client %s. "
4976 "Terminating\n", nt_errstr(status
),
4977 smbXsrv_connection_dbg(xconn
)));
4978 exit_server_cleanly("secondary writebraw failed");
4982 * We are not vulnerable to CVE-2017-12163
4983 * here as we are guaranteed to have numtowrite
4984 * bytes available - we just read from the client.
4986 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4987 if (nwritten
== -1) {
4989 reply_nterror(req
, map_nt_error_from_unix(errno
));
4990 error_to_writebrawerr(req
);
4994 if (nwritten
< (ssize_t
)numtowrite
) {
4995 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4996 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
5000 total_written
+= nwritten
;
5005 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
5007 status
= sync_file(conn
, fsp
, write_through
);
5008 if (!NT_STATUS_IS_OK(status
)) {
5009 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5010 fsp_str_dbg(fsp
), nt_errstr(status
)));
5011 reply_nterror(req
, status
);
5012 error_to_writebrawerr(req
);
5016 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5018 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
5019 (int)total_written
));
5021 /* We won't return a status if write through is not selected - this
5022 * follows what WfWg does */
5023 END_PROFILE(SMBwritebraw
);
5025 if (!write_through
&& total_written
==tcount
) {
5027 #if RABBIT_PELLET_FIX
5029 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5030 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5033 if (!send_keepalive(xconn
->transport
.sock
)) {
5034 exit_server_cleanly("reply_writebraw: send of "
5035 "keepalive failed");
5038 TALLOC_FREE(req
->outbuf
);
5043 END_PROFILE(SMBwritebraw
);
5048 #define DBGC_CLASS DBGC_LOCKING
5050 /****************************************************************************
5051 Reply to a writeunlock (core+).
5052 ****************************************************************************/
5054 void reply_writeunlock(struct smb_request
*req
)
5056 connection_struct
*conn
= req
->conn
;
5057 ssize_t nwritten
= -1;
5062 NTSTATUS status
= NT_STATUS_OK
;
5064 struct lock_struct lock
;
5065 int saved_errno
= 0;
5067 START_PROFILE(SMBwriteunlock
);
5070 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5071 END_PROFILE(SMBwriteunlock
);
5075 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5077 if (!check_fsp(conn
, req
, fsp
)) {
5078 END_PROFILE(SMBwriteunlock
);
5082 if (!CHECK_WRITE(fsp
)) {
5083 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5084 END_PROFILE(SMBwriteunlock
);
5088 numtowrite
= SVAL(req
->vwv
+1, 0);
5089 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5090 data
= (const char *)req
->buf
+ 3;
5093 * Ensure client isn't asking us to write more than
5094 * they sent. CVE-2017-12163.
5096 remaining
= smbreq_bufrem(req
, data
);
5097 if (numtowrite
> remaining
) {
5098 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5099 END_PROFILE(SMBwriteunlock
);
5103 if (!fsp
->print_file
&& numtowrite
> 0) {
5104 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5105 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5108 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5109 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5110 END_PROFILE(SMBwriteunlock
);
5115 /* The special X/Open SMB protocol handling of
5116 zero length writes is *NOT* done for
5118 if(numtowrite
== 0) {
5121 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5122 saved_errno
= errno
;
5125 status
= sync_file(conn
, fsp
, False
/* write through */);
5126 if (!NT_STATUS_IS_OK(status
)) {
5127 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5128 fsp_str_dbg(fsp
), nt_errstr(status
)));
5129 reply_nterror(req
, status
);
5134 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5138 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
5139 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5143 if (numtowrite
&& !fsp
->print_file
) {
5144 struct smbd_lock_element l
= {
5145 .req_guid
= smbd_request_guid(req
, 0),
5146 .smblctx
= req
->smbpid
,
5147 .brltype
= UNLOCK_LOCK
,
5149 .count
= numtowrite
,
5151 status
= smbd_do_unlocking(req
, fsp
, 1, &l
, WINDOWS_LOCK
);
5152 if (NT_STATUS_V(status
)) {
5153 reply_nterror(req
, status
);
5158 reply_outbuf(req
, 1, 0);
5160 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5162 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5163 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5166 END_PROFILE(SMBwriteunlock
);
5171 #define DBGC_CLASS DBGC_ALL
5173 /****************************************************************************
5175 ****************************************************************************/
5177 void reply_write(struct smb_request
*req
)
5179 connection_struct
*conn
= req
->conn
;
5182 ssize_t nwritten
= -1;
5186 struct lock_struct lock
;
5188 int saved_errno
= 0;
5190 START_PROFILE(SMBwrite
);
5193 END_PROFILE(SMBwrite
);
5194 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5198 /* If it's an IPC, pass off the pipe handler. */
5200 reply_pipe_write(req
);
5201 END_PROFILE(SMBwrite
);
5205 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5207 if (!check_fsp(conn
, req
, fsp
)) {
5208 END_PROFILE(SMBwrite
);
5212 if (!CHECK_WRITE(fsp
)) {
5213 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5214 END_PROFILE(SMBwrite
);
5218 numtowrite
= SVAL(req
->vwv
+1, 0);
5219 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5220 data
= (const char *)req
->buf
+ 3;
5223 * Ensure client isn't asking us to write more than
5224 * they sent. CVE-2017-12163.
5226 remaining
= smbreq_bufrem(req
, data
);
5227 if (numtowrite
> remaining
) {
5228 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5229 END_PROFILE(SMBwrite
);
5233 if (!fsp
->print_file
) {
5234 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5235 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5238 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5239 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5240 END_PROFILE(SMBwrite
);
5246 * X/Open SMB protocol says that if smb_vwv1 is
5247 * zero then the file size should be extended or
5248 * truncated to the size given in smb_vwv[2-3].
5251 if(numtowrite
== 0) {
5253 * This is actually an allocate call, and set EOF. JRA.
5255 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
5257 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5260 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
5262 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5265 trigger_write_time_update_immediate(fsp
);
5267 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5270 status
= sync_file(conn
, fsp
, False
);
5271 if (!NT_STATUS_IS_OK(status
)) {
5272 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5273 fsp_str_dbg(fsp
), nt_errstr(status
)));
5274 reply_nterror(req
, status
);
5279 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5283 if((nwritten
== 0) && (numtowrite
!= 0)) {
5284 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5288 reply_outbuf(req
, 1, 0);
5290 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5292 if (nwritten
< (ssize_t
)numtowrite
) {
5293 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
5294 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
5297 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5300 END_PROFILE(SMBwrite
);
5304 /****************************************************************************
5305 Ensure a buffer is a valid writeX for recvfile purposes.
5306 ****************************************************************************/
5308 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5309 (2*14) + /* word count (including bcc) */ \
5312 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
5313 const uint8_t *inbuf
)
5316 unsigned int doff
= 0;
5317 size_t len
= smb_len_large(inbuf
);
5319 struct smbXsrv_open
*op
= NULL
;
5320 struct files_struct
*fsp
= NULL
;
5323 if (is_encrypted_packet(inbuf
)) {
5324 /* Can't do this on encrypted
5329 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
5333 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
5334 CVAL(inbuf
,smb_wct
) != 14) {
5335 DEBUG(10,("is_valid_writeX_buffer: chained or "
5336 "invalid word length.\n"));
5340 fnum
= SVAL(inbuf
, smb_vwv2
);
5341 status
= smb1srv_open_lookup(xconn
,
5345 if (!NT_STATUS_IS_OK(status
)) {
5346 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5351 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5354 if (fsp
->conn
== NULL
) {
5355 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5359 if (IS_IPC(fsp
->conn
)) {
5360 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5363 if (IS_PRINT(fsp
->conn
)) {
5364 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5367 if (fsp
->base_fsp
!= NULL
) {
5368 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5371 doff
= SVAL(inbuf
,smb_vwv11
);
5373 numtowrite
= SVAL(inbuf
,smb_vwv10
);
5375 if (len
> doff
&& len
- doff
> 0xFFFF) {
5376 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
5379 if (numtowrite
== 0) {
5380 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5384 /* Ensure the sizes match up. */
5385 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
5386 /* no pad byte...old smbclient :-( */
5387 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5389 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
5393 if (len
- doff
!= numtowrite
) {
5394 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5395 "len = %u, doff = %u, numtowrite = %u\n",
5398 (unsigned int)numtowrite
));
5402 DEBUG(10,("is_valid_writeX_buffer: true "
5403 "len = %u, doff = %u, numtowrite = %u\n",
5406 (unsigned int)numtowrite
));
5411 /****************************************************************************
5412 Reply to a write and X.
5413 ****************************************************************************/
5415 void reply_write_and_X(struct smb_request
*req
)
5417 connection_struct
*conn
= req
->conn
;
5418 struct smbXsrv_connection
*xconn
= req
->xconn
;
5420 struct lock_struct lock
;
5425 unsigned int smb_doff
;
5426 unsigned int smblen
;
5429 int saved_errno
= 0;
5431 START_PROFILE(SMBwriteX
);
5433 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5434 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5438 numtowrite
= SVAL(req
->vwv
+10, 0);
5439 smb_doff
= SVAL(req
->vwv
+11, 0);
5440 smblen
= smb_len(req
->inbuf
);
5442 if (req
->unread_bytes
> 0xFFFF ||
5443 (smblen
> smb_doff
&&
5444 smblen
- smb_doff
> 0xFFFF)) {
5445 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5448 if (req
->unread_bytes
) {
5449 /* Can't do a recvfile write on IPC$ */
5451 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5454 if (numtowrite
!= req
->unread_bytes
) {
5455 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5460 * This already protects us against CVE-2017-12163.
5462 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5463 smb_doff
+ numtowrite
> smblen
) {
5464 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5469 /* If it's an IPC, pass off the pipe handler. */
5471 if (req
->unread_bytes
) {
5472 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5475 reply_pipe_write_and_X(req
);
5479 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5480 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5481 write_through
= BITSETW(req
->vwv
+7,0);
5483 if (!check_fsp(conn
, req
, fsp
)) {
5487 if (!CHECK_WRITE(fsp
)) {
5488 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5492 data
= smb_base(req
->inbuf
) + smb_doff
;
5494 if(req
->wct
== 14) {
5496 * This is a large offset (64 bit) write.
5498 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5502 /* X/Open SMB protocol says that, unlike SMBwrite
5503 if the length is zero then NO truncation is
5504 done, just a write of zero. To truncate a file,
5507 if(numtowrite
== 0) {
5510 if (req
->unread_bytes
== 0) {
5511 status
= schedule_aio_write_and_X(conn
,
5518 if (NT_STATUS_IS_OK(status
)) {
5519 /* write scheduled - we're done. */
5522 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5523 /* Real error - report to client. */
5524 reply_nterror(req
, status
);
5527 /* NT_STATUS_RETRY - fall through to sync write. */
5530 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5531 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5534 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5535 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5539 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5540 saved_errno
= errno
;
5544 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5548 if((nwritten
== 0) && (numtowrite
!= 0)) {
5549 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5553 reply_outbuf(req
, 6, 0);
5554 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5555 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5556 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5557 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5559 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5560 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5562 status
= sync_file(conn
, fsp
, write_through
);
5563 if (!NT_STATUS_IS_OK(status
)) {
5564 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5565 fsp_str_dbg(fsp
), nt_errstr(status
)));
5566 reply_nterror(req
, status
);
5570 END_PROFILE(SMBwriteX
);
5574 if (req
->unread_bytes
) {
5575 /* writeX failed. drain socket. */
5576 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5577 req
->unread_bytes
) {
5578 smb_panic("failed to drain pending bytes");
5580 req
->unread_bytes
= 0;
5583 END_PROFILE(SMBwriteX
);
5587 /****************************************************************************
5589 ****************************************************************************/
5591 void reply_lseek(struct smb_request
*req
)
5593 connection_struct
*conn
= req
->conn
;
5600 START_PROFILE(SMBlseek
);
5603 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5604 END_PROFILE(SMBlseek
);
5608 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5610 if (!check_fsp(conn
, req
, fsp
)) {
5614 mode
= SVAL(req
->vwv
+1, 0) & 3;
5615 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5616 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5625 res
= fh_get_pos(fsp
->fh
) + startpos
;
5636 if (umode
== SEEK_END
) {
5637 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5638 if(errno
== EINVAL
) {
5639 off_t current_pos
= startpos
;
5641 status
= vfs_stat_fsp(fsp
);
5642 if (!NT_STATUS_IS_OK(status
)) {
5643 reply_nterror(req
, status
);
5644 END_PROFILE(SMBlseek
);
5648 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5650 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5655 reply_nterror(req
, map_nt_error_from_unix(errno
));
5656 END_PROFILE(SMBlseek
);
5661 fh_set_pos(fsp
->fh
, res
);
5663 reply_outbuf(req
, 2, 0);
5664 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5666 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5667 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5669 END_PROFILE(SMBlseek
);
5673 static struct files_struct
*file_sync_one_fn(struct files_struct
*fsp
,
5676 connection_struct
*conn
= talloc_get_type_abort(
5677 private_data
, connection_struct
);
5679 if (conn
!= fsp
->conn
) {
5682 if (fsp_get_io_fd(fsp
) == -1) {
5685 sync_file(conn
, fsp
, True
/* write through */);
5687 if (fsp
->fsp_flags
.modified
) {
5688 trigger_write_time_update_immediate(fsp
);
5694 /****************************************************************************
5696 ****************************************************************************/
5698 void reply_flush(struct smb_request
*req
)
5700 connection_struct
*conn
= req
->conn
;
5704 START_PROFILE(SMBflush
);
5707 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5711 fnum
= SVAL(req
->vwv
+0, 0);
5712 fsp
= file_fsp(req
, fnum
);
5714 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5719 files_forall(req
->sconn
, file_sync_one_fn
, conn
);
5721 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5722 if (!NT_STATUS_IS_OK(status
)) {
5723 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5724 fsp_str_dbg(fsp
), nt_errstr(status
)));
5725 reply_nterror(req
, status
);
5726 END_PROFILE(SMBflush
);
5729 if (fsp
->fsp_flags
.modified
) {
5730 trigger_write_time_update_immediate(fsp
);
5734 reply_outbuf(req
, 0, 0);
5736 DEBUG(3,("flush\n"));
5737 END_PROFILE(SMBflush
);
5741 /****************************************************************************
5743 conn POINTER CAN BE NULL HERE !
5744 ****************************************************************************/
5746 static struct tevent_req
*reply_exit_send(struct smb_request
*smb1req
);
5747 static void reply_exit_done(struct tevent_req
*req
);
5749 void reply_exit(struct smb_request
*smb1req
)
5751 struct tevent_req
*req
;
5754 * Don't setup the profile charge here, take
5755 * it in reply_exit_done(). Not strictly correct
5756 * but better than the other SMB1 async
5757 * code that double-charges at the moment.
5759 req
= reply_exit_send(smb1req
);
5761 /* Not going async, profile here. */
5762 START_PROFILE(SMBexit
);
5763 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
5764 END_PROFILE(SMBexit
);
5768 /* We're async. This will complete later. */
5769 tevent_req_set_callback(req
, reply_exit_done
, smb1req
);
5773 struct reply_exit_state
{
5774 struct tevent_queue
*wait_queue
;
5777 static void reply_exit_wait_done(struct tevent_req
*subreq
);
5779 /****************************************************************************
5781 Note, on failure here we deallocate and return NULL to allow the caller to
5782 SMB1 return an error of ERRnomem immediately.
5783 ****************************************************************************/
5785 static struct tevent_req
*reply_exit_send(struct smb_request
*smb1req
)
5787 struct tevent_req
*req
;
5788 struct reply_exit_state
*state
;
5789 struct tevent_req
*subreq
;
5791 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
5793 req
= tevent_req_create(smb1req
, &state
,
5794 struct reply_exit_state
);
5798 state
->wait_queue
= tevent_queue_create(state
,
5799 "reply_exit_wait_queue");
5800 if (tevent_req_nomem(state
->wait_queue
, req
)) {
5805 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
) {
5806 if (fsp
->file_pid
!= smb1req
->smbpid
) {
5809 if (fsp
->vuid
!= smb1req
->vuid
) {
5813 * Flag the file as close in progress.
5814 * This will prevent any more IO being
5817 fsp
->fsp_flags
.closing
= true;
5819 if (fsp
->num_aio_requests
> 0) {
5821 * Now wait until all aio requests on this fsp are
5824 * We don't set a callback, as we just want to block the
5825 * wait queue and the talloc_free() of fsp->aio_request
5826 * will remove the item from the wait queue.
5828 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
5831 if (tevent_req_nomem(subreq
, req
)) {
5839 * Now we add our own waiter to the end of the queue,
5840 * this way we get notified when all pending requests are finished
5841 * and reply to the outstanding SMB1 request.
5843 subreq
= tevent_queue_wait_send(state
,
5846 if (tevent_req_nomem(subreq
, req
)) {
5852 * We're really going async - move the SMB1 request from
5853 * a talloc stackframe above us to the conn talloc-context.
5854 * We need this to stick around until the wait_done
5855 * callback is invoked.
5857 smb1req
= talloc_move(sconn
, &smb1req
);
5859 tevent_req_set_callback(subreq
, reply_exit_wait_done
, req
);
5864 static void reply_exit_wait_done(struct tevent_req
*subreq
)
5866 struct tevent_req
*req
= tevent_req_callback_data(
5867 subreq
, struct tevent_req
);
5869 tevent_queue_wait_recv(subreq
);
5870 TALLOC_FREE(subreq
);
5871 tevent_req_done(req
);
5874 static NTSTATUS
reply_exit_recv(struct tevent_req
*req
)
5876 return tevent_req_simple_recv_ntstatus(req
);
5879 static void reply_exit_done(struct tevent_req
*req
)
5881 struct smb_request
*smb1req
= tevent_req_callback_data(
5882 req
, struct smb_request
);
5883 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
5884 struct smbXsrv_connection
*xconn
= smb1req
->xconn
;
5885 NTTIME now
= timeval_to_nttime(&smb1req
->request_time
);
5886 struct smbXsrv_session
*session
= NULL
;
5887 files_struct
*fsp
, *next
;
5891 * Take the profile charge here. Not strictly
5892 * correct but better than the other SMB1 async
5893 * code that double-charges at the moment.
5895 START_PROFILE(SMBexit
);
5897 status
= reply_exit_recv(req
);
5899 if (!NT_STATUS_IS_OK(status
)) {
5900 TALLOC_FREE(smb1req
);
5901 END_PROFILE(SMBexit
);
5902 exit_server(__location__
": reply_exit_recv failed");
5907 * Ensure the session is still valid.
5909 status
= smb1srv_session_lookup(xconn
,
5913 if (!NT_STATUS_IS_OK(status
)) {
5914 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5915 smb_request_done(smb1req
);
5916 END_PROFILE(SMBexit
);
5920 * Ensure the vuid is still valid - no one
5921 * called reply_ulogoffX() in the meantime.
5922 * reply_exit() doesn't have AS_USER set, so
5923 * use set_current_user_info() directly.
5924 * This is the same logic as in switch_message().
5926 if (session
->global
->auth_session_info
!= NULL
) {
5927 set_current_user_info(
5928 session
->global
->auth_session_info
->unix_info
->sanitized_username
,
5929 session
->global
->auth_session_info
->unix_info
->unix_name
,
5930 session
->global
->auth_session_info
->info
->domain_name
);
5933 /* No more aio - do the actual closes. */
5934 for (fsp
= sconn
->files
; fsp
; fsp
= next
) {
5938 if (fsp
->file_pid
!= smb1req
->smbpid
) {
5941 if (fsp
->vuid
!= smb1req
->vuid
) {
5944 if (!fsp
->fsp_flags
.closing
) {
5949 * reply_exit() has the DO_CHDIR flag set.
5951 ok
= chdir_current_service(fsp
->conn
);
5953 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5954 smb_request_done(smb1req
);
5955 END_PROFILE(SMBexit
);
5957 close_file(NULL
, fsp
, SHUTDOWN_CLOSE
);
5960 reply_outbuf(smb1req
, 0, 0);
5962 * The following call is needed to push the
5963 * reply data back out the socket after async
5964 * return. Plus it frees smb1req.
5966 smb_request_done(smb1req
);
5967 DBG_INFO("reply_exit complete\n");
5968 END_PROFILE(SMBexit
);
5972 static struct tevent_req
*reply_close_send(struct smb_request
*smb1req
,
5974 static void reply_close_done(struct tevent_req
*req
);
5976 void reply_close(struct smb_request
*smb1req
)
5978 connection_struct
*conn
= smb1req
->conn
;
5979 NTSTATUS status
= NT_STATUS_OK
;
5980 files_struct
*fsp
= NULL
;
5981 START_PROFILE(SMBclose
);
5983 if (smb1req
->wct
< 3) {
5984 reply_nterror(smb1req
, NT_STATUS_INVALID_PARAMETER
);
5985 END_PROFILE(SMBclose
);
5989 fsp
= file_fsp(smb1req
, SVAL(smb1req
->vwv
+0, 0));
5992 * We can only use check_fsp if we know it's not a directory.
5995 if (!check_fsp_open(conn
, smb1req
, fsp
)) {
5996 reply_nterror(smb1req
, NT_STATUS_INVALID_HANDLE
);
5997 END_PROFILE(SMBclose
);
6001 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6002 fsp
->fsp_flags
.is_directory
?
6003 "directory" : "file",
6004 fsp_get_pathref_fd(fsp
), fsp_fnum_dbg(fsp
),
6005 conn
->num_files_open
);
6007 if (!fsp
->fsp_flags
.is_directory
) {
6011 * Take care of any time sent in the close.
6014 t
= srv_make_unix_date3(smb1req
->vwv
+1);
6015 set_close_write_time(fsp
, time_t_to_full_timespec(t
));
6018 if (fsp
->num_aio_requests
!= 0) {
6019 struct tevent_req
*req
;
6021 req
= reply_close_send(smb1req
, fsp
);
6023 status
= NT_STATUS_NO_MEMORY
;
6026 /* We're async. This will complete later. */
6027 tevent_req_set_callback(req
, reply_close_done
, smb1req
);
6028 END_PROFILE(SMBclose
);
6033 * close_file() returns the unix errno if an error was detected on
6034 * close - normally this is due to a disk full error. If not then it
6035 * was probably an I/O error.
6038 status
= close_file(smb1req
, fsp
, NORMAL_CLOSE
);
6040 if (!NT_STATUS_IS_OK(status
)) {
6041 reply_nterror(smb1req
, status
);
6042 END_PROFILE(SMBclose
);
6046 reply_outbuf(smb1req
, 0, 0);
6047 END_PROFILE(SMBclose
);
6051 struct reply_close_state
{
6053 struct tevent_queue
*wait_queue
;
6056 static void reply_close_wait_done(struct tevent_req
*subreq
);
6058 /****************************************************************************
6060 Note, on failure here we deallocate and return NULL to allow the caller to
6061 SMB1 return an error of ERRnomem immediately.
6062 ****************************************************************************/
6064 static struct tevent_req
*reply_close_send(struct smb_request
*smb1req
,
6067 struct tevent_req
*req
;
6068 struct reply_close_state
*state
;
6069 struct tevent_req
*subreq
;
6070 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
6072 req
= tevent_req_create(smb1req
, &state
,
6073 struct reply_close_state
);
6077 state
->wait_queue
= tevent_queue_create(state
,
6078 "reply_close_wait_queue");
6079 if (tevent_req_nomem(state
->wait_queue
, req
)) {
6085 * Flag the file as close in progress.
6086 * This will prevent any more IO being
6089 fsp
->fsp_flags
.closing
= true;
6092 * Now wait until all aio requests on this fsp are
6095 * We don't set a callback, as we just want to block the
6096 * wait queue and the talloc_free() of fsp->aio_request
6097 * will remove the item from the wait queue.
6099 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
6102 if (tevent_req_nomem(subreq
, req
)) {
6108 * Now we add our own waiter to the end of the queue,
6109 * this way we get notified when all pending requests are finished
6110 * and reply to the outstanding SMB1 request.
6112 subreq
= tevent_queue_wait_send(state
,
6115 if (tevent_req_nomem(subreq
, req
)) {
6121 * We're really going async - move the SMB1 request from
6122 * a talloc stackframe above us to the conn talloc-context.
6123 * We need this to stick around until the wait_done
6124 * callback is invoked.
6126 smb1req
= talloc_move(sconn
, &smb1req
);
6128 tevent_req_set_callback(subreq
, reply_close_wait_done
, req
);
6133 static void reply_close_wait_done(struct tevent_req
*subreq
)
6135 struct tevent_req
*req
= tevent_req_callback_data(
6136 subreq
, struct tevent_req
);
6138 tevent_queue_wait_recv(subreq
);
6139 TALLOC_FREE(subreq
);
6140 tevent_req_done(req
);
6143 static NTSTATUS
reply_close_recv(struct tevent_req
*req
)
6145 return tevent_req_simple_recv_ntstatus(req
);
6148 static void reply_close_done(struct tevent_req
*req
)
6150 struct smb_request
*smb1req
= tevent_req_callback_data(
6151 req
, struct smb_request
);
6152 struct reply_close_state
*state
= tevent_req_data(req
,
6153 struct reply_close_state
);
6156 status
= reply_close_recv(req
);
6158 if (!NT_STATUS_IS_OK(status
)) {
6159 TALLOC_FREE(smb1req
);
6160 exit_server(__location__
": reply_close_recv failed");
6164 status
= close_file(smb1req
, state
->fsp
, NORMAL_CLOSE
);
6165 if (NT_STATUS_IS_OK(status
)) {
6166 reply_outbuf(smb1req
, 0, 0);
6168 reply_nterror(smb1req
, status
);
6171 * The following call is needed to push the
6172 * reply data back out the socket after async
6173 * return. Plus it frees smb1req.
6175 smb_request_done(smb1req
);
6178 /****************************************************************************
6179 Reply to a writeclose (Core+ protocol).
6180 ****************************************************************************/
6182 void reply_writeclose(struct smb_request
*req
)
6184 connection_struct
*conn
= req
->conn
;
6187 ssize_t nwritten
= -1;
6188 NTSTATUS close_status
= NT_STATUS_OK
;
6191 struct timespec mtime
;
6193 struct lock_struct lock
;
6195 START_PROFILE(SMBwriteclose
);
6198 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6199 END_PROFILE(SMBwriteclose
);
6203 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6205 if (!check_fsp(conn
, req
, fsp
)) {
6206 END_PROFILE(SMBwriteclose
);
6209 if (!CHECK_WRITE(fsp
)) {
6210 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6211 END_PROFILE(SMBwriteclose
);
6215 numtowrite
= SVAL(req
->vwv
+1, 0);
6216 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
6217 mtime
= time_t_to_full_timespec(srv_make_unix_date3(req
->vwv
+4));
6218 data
= (const char *)req
->buf
+ 1;
6221 * Ensure client isn't asking us to write more than
6222 * they sent. CVE-2017-12163.
6224 remaining
= smbreq_bufrem(req
, data
);
6225 if (numtowrite
> remaining
) {
6226 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6227 END_PROFILE(SMBwriteclose
);
6231 if (fsp
->print_file
== NULL
) {
6232 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
6233 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
6236 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
6237 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
6238 END_PROFILE(SMBwriteclose
);
6243 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
6245 set_close_write_time(fsp
, mtime
);
6248 * More insanity. W2K only closes the file if writelen > 0.
6252 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6253 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
6254 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
6257 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6258 "file %s\n", fsp_str_dbg(fsp
)));
6259 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6263 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
6264 reply_nterror(req
, NT_STATUS_DISK_FULL
);
6268 if(!NT_STATUS_IS_OK(close_status
)) {
6269 reply_nterror(req
, close_status
);
6273 reply_outbuf(req
, 1, 0);
6275 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
6279 END_PROFILE(SMBwriteclose
);
6284 #define DBGC_CLASS DBGC_LOCKING
6286 /****************************************************************************
6288 ****************************************************************************/
6290 static void reply_lock_done(struct tevent_req
*subreq
);
6292 void reply_lock(struct smb_request
*req
)
6294 struct tevent_req
*subreq
= NULL
;
6295 connection_struct
*conn
= req
->conn
;
6297 struct smbd_lock_element
*lck
= NULL
;
6299 START_PROFILE(SMBlock
);
6302 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6303 END_PROFILE(SMBlock
);
6307 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6309 if (!check_fsp(conn
, req
, fsp
)) {
6310 END_PROFILE(SMBlock
);
6314 lck
= talloc(req
, struct smbd_lock_element
);
6316 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6317 END_PROFILE(SMBlock
);
6321 *lck
= (struct smbd_lock_element
) {
6322 .req_guid
= smbd_request_guid(req
, 0),
6323 .smblctx
= req
->smbpid
,
6324 .brltype
= WRITE_LOCK
,
6325 .count
= IVAL(req
->vwv
+1, 0),
6326 .offset
= IVAL(req
->vwv
+3, 0),
6329 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
6335 subreq
= smbd_smb1_do_locks_send(
6341 false, /* large_offset */
6345 if (subreq
== NULL
) {
6346 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6347 END_PROFILE(SMBlock
);
6350 tevent_req_set_callback(subreq
, reply_lock_done
, NULL
);
6351 END_PROFILE(SMBlock
);
6354 static void reply_lock_done(struct tevent_req
*subreq
)
6356 struct smb_request
*req
= NULL
;
6360 START_PROFILE(SMBlock
);
6362 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
6365 status
= smbd_smb1_do_locks_recv(subreq
);
6366 TALLOC_FREE(subreq
);
6368 if (NT_STATUS_IS_OK(status
)) {
6369 reply_outbuf(req
, 0, 0);
6371 reply_nterror(req
, status
);
6374 ok
= srv_send_smb(req
->xconn
,
6375 (char *)req
->outbuf
,
6378 IS_CONN_ENCRYPTED(req
->conn
),
6381 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6384 END_PROFILE(SMBlock
);
6387 /****************************************************************************
6389 ****************************************************************************/
6391 void reply_unlock(struct smb_request
*req
)
6393 connection_struct
*conn
= req
->conn
;
6396 struct smbd_lock_element lck
;
6398 START_PROFILE(SMBunlock
);
6401 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6402 END_PROFILE(SMBunlock
);
6406 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6408 if (!check_fsp(conn
, req
, fsp
)) {
6409 END_PROFILE(SMBunlock
);
6413 lck
= (struct smbd_lock_element
) {
6414 .req_guid
= smbd_request_guid(req
, 0),
6415 .smblctx
= req
->smbpid
,
6416 .brltype
= UNLOCK_LOCK
,
6417 .offset
= IVAL(req
->vwv
+3, 0),
6418 .count
= IVAL(req
->vwv
+1, 0),
6421 status
= smbd_do_unlocking(req
, fsp
, 1, &lck
, WINDOWS_LOCK
);
6423 if (!NT_STATUS_IS_OK(status
)) {
6424 reply_nterror(req
, status
);
6425 END_PROFILE(SMBunlock
);
6429 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
6435 reply_outbuf(req
, 0, 0);
6437 END_PROFILE(SMBunlock
);
6442 #define DBGC_CLASS DBGC_ALL
6444 /****************************************************************************
6446 conn POINTER CAN BE NULL HERE !
6447 ****************************************************************************/
6449 static struct tevent_req
*reply_tdis_send(struct smb_request
*smb1req
);
6450 static void reply_tdis_done(struct tevent_req
*req
);
6452 void reply_tdis(struct smb_request
*smb1req
)
6454 connection_struct
*conn
= smb1req
->conn
;
6455 struct tevent_req
*req
;
6458 * Don't setup the profile charge here, take
6459 * it in reply_tdis_done(). Not strictly correct
6460 * but better than the other SMB1 async
6461 * code that double-charges at the moment.
6465 /* Not going async, profile here. */
6466 START_PROFILE(SMBtdis
);
6467 DBG_INFO("Invalid connection in tdis\n");
6468 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
6469 END_PROFILE(SMBtdis
);
6473 req
= reply_tdis_send(smb1req
);
6475 /* Not going async, profile here. */
6476 START_PROFILE(SMBtdis
);
6477 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
6478 END_PROFILE(SMBtdis
);
6481 /* We're async. This will complete later. */
6482 tevent_req_set_callback(req
, reply_tdis_done
, smb1req
);
6486 struct reply_tdis_state
{
6487 struct tevent_queue
*wait_queue
;
6490 static void reply_tdis_wait_done(struct tevent_req
*subreq
);
6492 /****************************************************************************
6494 Note, on failure here we deallocate and return NULL to allow the caller to
6495 SMB1 return an error of ERRnomem immediately.
6496 ****************************************************************************/
6498 static struct tevent_req
*reply_tdis_send(struct smb_request
*smb1req
)
6500 struct tevent_req
*req
;
6501 struct reply_tdis_state
*state
;
6502 struct tevent_req
*subreq
;
6503 connection_struct
*conn
= smb1req
->conn
;
6506 req
= tevent_req_create(smb1req
, &state
,
6507 struct reply_tdis_state
);
6511 state
->wait_queue
= tevent_queue_create(state
, "reply_tdis_wait_queue");
6512 if (tevent_req_nomem(state
->wait_queue
, req
)) {
6518 * Make sure that no new request will be able to use this tcon.
6519 * This ensures that once all outstanding fsp->aio_requests
6520 * on this tcon are done, we are safe to close it.
6522 conn
->tcon
->status
= NT_STATUS_NETWORK_NAME_DELETED
;
6524 for (fsp
= conn
->sconn
->files
; fsp
; fsp
= fsp
->next
) {
6525 if (fsp
->conn
!= conn
) {
6529 * Flag the file as close in progress.
6530 * This will prevent any more IO being
6531 * done on it. Not strictly needed, but
6532 * doesn't hurt to flag it as closing.
6534 fsp
->fsp_flags
.closing
= true;
6536 if (fsp
->num_aio_requests
> 0) {
6538 * Now wait until all aio requests on this fsp are
6541 * We don't set a callback, as we just want to block the
6542 * wait queue and the talloc_free() of fsp->aio_request
6543 * will remove the item from the wait queue.
6545 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
6546 conn
->sconn
->ev_ctx
,
6548 if (tevent_req_nomem(subreq
, req
)) {
6556 * Now we add our own waiter to the end of the queue,
6557 * this way we get notified when all pending requests are finished
6558 * and reply to the outstanding SMB1 request.
6560 subreq
= tevent_queue_wait_send(state
,
6561 conn
->sconn
->ev_ctx
,
6563 if (tevent_req_nomem(subreq
, req
)) {
6569 * We're really going async - move the SMB1 request from
6570 * a talloc stackframe above us to the sconn talloc-context.
6571 * We need this to stick around until the wait_done
6572 * callback is invoked.
6574 smb1req
= talloc_move(smb1req
->sconn
, &smb1req
);
6576 tevent_req_set_callback(subreq
, reply_tdis_wait_done
, req
);
6581 static void reply_tdis_wait_done(struct tevent_req
*subreq
)
6583 struct tevent_req
*req
= tevent_req_callback_data(
6584 subreq
, struct tevent_req
);
6586 tevent_queue_wait_recv(subreq
);
6587 TALLOC_FREE(subreq
);
6588 tevent_req_done(req
);
6591 static NTSTATUS
reply_tdis_recv(struct tevent_req
*req
)
6593 return tevent_req_simple_recv_ntstatus(req
);
6596 static void reply_tdis_done(struct tevent_req
*req
)
6598 struct smb_request
*smb1req
= tevent_req_callback_data(
6599 req
, struct smb_request
);
6601 struct smbXsrv_tcon
*tcon
= smb1req
->conn
->tcon
;
6605 * Take the profile charge here. Not strictly
6606 * correct but better than the other SMB1 async
6607 * code that double-charges at the moment.
6609 START_PROFILE(SMBtdis
);
6611 status
= reply_tdis_recv(req
);
6613 if (!NT_STATUS_IS_OK(status
)) {
6614 TALLOC_FREE(smb1req
);
6615 END_PROFILE(SMBtdis
);
6616 exit_server(__location__
": reply_tdis_recv failed");
6621 * As we've been awoken, we may have changed
6622 * directory in the meantime.
6623 * reply_tdis() has the DO_CHDIR flag set.
6625 ok
= chdir_current_service(smb1req
->conn
);
6627 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
6628 smb_request_done(smb1req
);
6629 END_PROFILE(SMBtdis
);
6632 status
= smbXsrv_tcon_disconnect(tcon
,
6634 if (!NT_STATUS_IS_OK(status
)) {
6635 TALLOC_FREE(smb1req
);
6636 END_PROFILE(SMBtdis
);
6637 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
6641 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6642 smb1req
->conn
= NULL
;
6646 reply_outbuf(smb1req
, 0, 0);
6648 * The following call is needed to push the
6649 * reply data back out the socket after async
6650 * return. Plus it frees smb1req.
6652 smb_request_done(smb1req
);
6653 END_PROFILE(SMBtdis
);
6656 /****************************************************************************
6658 conn POINTER CAN BE NULL HERE !
6659 ****************************************************************************/
6661 void reply_echo(struct smb_request
*req
)
6663 connection_struct
*conn
= req
->conn
;
6664 struct smb_perfcount_data local_pcd
;
6665 struct smb_perfcount_data
*cur_pcd
;
6669 START_PROFILE(SMBecho
);
6671 smb_init_perfcount_data(&local_pcd
);
6674 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6675 END_PROFILE(SMBecho
);
6679 smb_reverb
= SVAL(req
->vwv
+0, 0);
6681 reply_outbuf(req
, 1, req
->buflen
);
6683 /* copy any incoming data back out */
6684 if (req
->buflen
> 0) {
6685 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
6688 if (smb_reverb
> 100) {
6689 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
6693 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
6695 /* this makes sure we catch the request pcd */
6696 if (seq_num
== smb_reverb
) {
6697 cur_pcd
= &req
->pcd
;
6699 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
6700 cur_pcd
= &local_pcd
;
6703 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
6705 show_msg((char *)req
->outbuf
);
6706 if (!srv_send_smb(req
->xconn
,
6707 (char *)req
->outbuf
,
6708 true, req
->seqnum
+1,
6709 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
6711 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6714 DEBUG(3,("echo %d times\n", smb_reverb
));
6716 TALLOC_FREE(req
->outbuf
);
6718 END_PROFILE(SMBecho
);
6722 /****************************************************************************
6723 Reply to a printopen.
6724 ****************************************************************************/
6726 void reply_printopen(struct smb_request
*req
)
6728 connection_struct
*conn
= req
->conn
;
6732 START_PROFILE(SMBsplopen
);
6735 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6736 END_PROFILE(SMBsplopen
);
6740 if (!CAN_PRINT(conn
)) {
6741 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6742 END_PROFILE(SMBsplopen
);
6746 status
= file_new(req
, conn
, &fsp
);
6747 if(!NT_STATUS_IS_OK(status
)) {
6748 reply_nterror(req
, status
);
6749 END_PROFILE(SMBsplopen
);
6753 /* Open for exclusive use, write only. */
6754 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
6756 if (!NT_STATUS_IS_OK(status
)) {
6757 file_free(req
, fsp
);
6758 reply_nterror(req
, status
);
6759 END_PROFILE(SMBsplopen
);
6763 reply_outbuf(req
, 1, 0);
6764 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
6766 DEBUG(3,("openprint fd=%d %s\n",
6767 fsp_get_io_fd(fsp
), fsp_fnum_dbg(fsp
)));
6769 END_PROFILE(SMBsplopen
);
6773 /****************************************************************************
6774 Reply to a printclose.
6775 ****************************************************************************/
6777 void reply_printclose(struct smb_request
*req
)
6779 connection_struct
*conn
= req
->conn
;
6783 START_PROFILE(SMBsplclose
);
6786 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6787 END_PROFILE(SMBsplclose
);
6791 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6793 if (!check_fsp(conn
, req
, fsp
)) {
6794 END_PROFILE(SMBsplclose
);
6798 if (!CAN_PRINT(conn
)) {
6799 reply_force_doserror(req
, ERRSRV
, ERRerror
);
6800 END_PROFILE(SMBsplclose
);
6804 DEBUG(3,("printclose fd=%d %s\n",
6805 fsp_get_io_fd(fsp
), fsp_fnum_dbg(fsp
)));
6807 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6809 if(!NT_STATUS_IS_OK(status
)) {
6810 reply_nterror(req
, status
);
6811 END_PROFILE(SMBsplclose
);
6815 reply_outbuf(req
, 0, 0);
6817 END_PROFILE(SMBsplclose
);
6821 /****************************************************************************
6822 Reply to a printqueue.
6823 ****************************************************************************/
6825 void reply_printqueue(struct smb_request
*req
)
6827 const struct loadparm_substitution
*lp_sub
=
6828 loadparm_s3_global_substitution();
6829 connection_struct
*conn
= req
->conn
;
6833 START_PROFILE(SMBsplretq
);
6836 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6837 END_PROFILE(SMBsplretq
);
6841 max_count
= SVAL(req
->vwv
+0, 0);
6842 start_index
= SVAL(req
->vwv
+1, 0);
6844 /* we used to allow the client to get the cnum wrong, but that
6845 is really quite gross and only worked when there was only
6846 one printer - I think we should now only accept it if they
6847 get it right (tridge) */
6848 if (!CAN_PRINT(conn
)) {
6849 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6850 END_PROFILE(SMBsplretq
);
6854 reply_outbuf(req
, 2, 3);
6855 SSVAL(req
->outbuf
,smb_vwv0
,0);
6856 SSVAL(req
->outbuf
,smb_vwv1
,0);
6857 SCVAL(smb_buf(req
->outbuf
),0,1);
6858 SSVAL(smb_buf(req
->outbuf
),1,0);
6860 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6861 start_index
, max_count
));
6864 TALLOC_CTX
*mem_ctx
= talloc_tos();
6867 const char *sharename
= lp_servicename(mem_ctx
, lp_sub
, SNUM(conn
));
6868 struct rpc_pipe_client
*cli
= NULL
;
6869 struct dcerpc_binding_handle
*b
= NULL
;
6870 struct policy_handle handle
;
6871 struct spoolss_DevmodeContainer devmode_ctr
;
6872 union spoolss_JobInfo
*info
;
6874 uint32_t num_to_get
;
6878 ZERO_STRUCT(handle
);
6880 status
= rpc_pipe_open_interface(mem_ctx
,
6883 conn
->sconn
->remote_address
,
6884 conn
->sconn
->local_address
,
6885 conn
->sconn
->msg_ctx
,
6887 if (!NT_STATUS_IS_OK(status
)) {
6888 DEBUG(0, ("reply_printqueue: "
6889 "could not connect to spoolss: %s\n",
6890 nt_errstr(status
)));
6891 reply_nterror(req
, status
);
6894 b
= cli
->binding_handle
;
6896 ZERO_STRUCT(devmode_ctr
);
6898 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
6901 SEC_FLAG_MAXIMUM_ALLOWED
,
6904 if (!NT_STATUS_IS_OK(status
)) {
6905 reply_nterror(req
, status
);
6908 if (!W_ERROR_IS_OK(werr
)) {
6909 reply_nterror(req
, werror_to_ntstatus(werr
));
6913 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
6921 if (!W_ERROR_IS_OK(werr
)) {
6922 reply_nterror(req
, werror_to_ntstatus(werr
));
6926 if (max_count
> 0) {
6927 first
= start_index
;
6929 first
= start_index
+ max_count
+ 1;
6932 if (first
>= count
) {
6935 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6938 for (i
= first
; i
< num_to_get
; i
++) {
6941 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6944 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6945 info
[i
].info2
.job_id
);
6947 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6953 srv_put_dos_date2(p
, 0, qtime
);
6954 SCVAL(p
, 4, qstatus
);
6955 SSVAL(p
, 5, qrapjobid
);
6956 SIVAL(p
, 7, info
[i
].info2
.size
);
6958 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6959 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6960 if (!NT_STATUS_IS_OK(status
)) {
6961 reply_nterror(req
, status
);
6964 if (message_push_blob(
6967 blob
, sizeof(blob
))) == -1) {
6968 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6974 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6975 SSVAL(req
->outbuf
,smb_vwv1
,
6976 (max_count
>0?first
+count
:first
-1));
6977 SCVAL(smb_buf(req
->outbuf
),0,1);
6978 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6982 DEBUG(3, ("%u entries returned in queue\n",
6986 if (b
&& is_valid_policy_hnd(&handle
)) {
6987 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6992 END_PROFILE(SMBsplretq
);
6996 /****************************************************************************
6997 Reply to a printwrite.
6998 ****************************************************************************/
7000 void reply_printwrite(struct smb_request
*req
)
7002 connection_struct
*conn
= req
->conn
;
7007 START_PROFILE(SMBsplwr
);
7010 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7011 END_PROFILE(SMBsplwr
);
7015 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7017 if (!check_fsp(conn
, req
, fsp
)) {
7018 END_PROFILE(SMBsplwr
);
7022 if (!fsp
->print_file
) {
7023 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7024 END_PROFILE(SMBsplwr
);
7028 if (!CHECK_WRITE(fsp
)) {
7029 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7030 END_PROFILE(SMBsplwr
);
7034 numtowrite
= SVAL(req
->buf
, 1);
7037 * This already protects us against CVE-2017-12163.
7039 if (req
->buflen
< numtowrite
+ 3) {
7040 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7041 END_PROFILE(SMBsplwr
);
7045 data
= (const char *)req
->buf
+ 3;
7047 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
7048 reply_nterror(req
, map_nt_error_from_unix(errno
));
7049 END_PROFILE(SMBsplwr
);
7053 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
7055 END_PROFILE(SMBsplwr
);
7059 /****************************************************************************
7061 ****************************************************************************/
7063 void reply_mkdir(struct smb_request
*req
)
7065 connection_struct
*conn
= req
->conn
;
7066 struct smb_filename
*smb_dname
= NULL
;
7067 char *directory
= NULL
;
7070 TALLOC_CTX
*ctx
= talloc_tos();
7072 START_PROFILE(SMBmkdir
);
7074 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
7075 STR_TERMINATE
, &status
);
7076 if (!NT_STATUS_IS_OK(status
)) {
7077 reply_nterror(req
, status
);
7081 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
7082 status
= filename_convert(ctx
, conn
,
7087 if (!NT_STATUS_IS_OK(status
)) {
7088 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7089 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7090 ERRSRV
, ERRbadpath
);
7093 reply_nterror(req
, status
);
7097 status
= create_directory(conn
, req
, smb_dname
);
7099 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
7101 if (!NT_STATUS_IS_OK(status
)) {
7103 if (!use_nt_status()
7104 && NT_STATUS_EQUAL(status
,
7105 NT_STATUS_OBJECT_NAME_COLLISION
)) {
7107 * Yes, in the DOS error code case we get a
7108 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7109 * samba4 torture test.
7111 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
7114 reply_nterror(req
, status
);
7118 reply_outbuf(req
, 0, 0);
7120 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
7122 TALLOC_FREE(smb_dname
);
7123 END_PROFILE(SMBmkdir
);
7127 /****************************************************************************
7129 ****************************************************************************/
7131 void reply_rmdir(struct smb_request
*req
)
7133 connection_struct
*conn
= req
->conn
;
7134 struct smb_filename
*smb_dname
= NULL
;
7135 char *directory
= NULL
;
7137 TALLOC_CTX
*ctx
= talloc_tos();
7138 files_struct
*fsp
= NULL
;
7140 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
7142 START_PROFILE(SMBrmdir
);
7144 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
7145 STR_TERMINATE
, &status
);
7146 if (!NT_STATUS_IS_OK(status
)) {
7147 reply_nterror(req
, status
);
7151 status
= filename_convert(ctx
, conn
,
7156 if (!NT_STATUS_IS_OK(status
)) {
7157 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7158 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7159 ERRSRV
, ERRbadpath
);
7162 reply_nterror(req
, status
);
7166 if (is_ntfs_stream_smb_fname(smb_dname
)) {
7167 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
7171 status
= SMB_VFS_CREATE_FILE(
7174 smb_dname
, /* fname */
7175 DELETE_ACCESS
, /* access_mask */
7176 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7178 FILE_OPEN
, /* create_disposition*/
7179 FILE_DIRECTORY_FILE
, /* create_options */
7180 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
7181 0, /* oplock_request */
7183 0, /* allocation_size */
7184 0, /* private_flags */
7189 NULL
, NULL
); /* create context */
7191 if (!NT_STATUS_IS_OK(status
)) {
7192 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7193 /* We have re-scheduled this call. */
7196 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
7197 bool ok
= defer_smb1_sharing_violation(req
);
7202 reply_nterror(req
, status
);
7206 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
7207 if (!NT_STATUS_IS_OK(status
)) {
7208 close_file(req
, fsp
, ERROR_CLOSE
);
7209 reply_nterror(req
, status
);
7213 if (!set_delete_on_close(fsp
, true,
7214 conn
->session_info
->security_token
,
7215 conn
->session_info
->unix_token
)) {
7216 close_file(req
, fsp
, ERROR_CLOSE
);
7217 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7221 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
7222 if (!NT_STATUS_IS_OK(status
)) {
7223 reply_nterror(req
, status
);
7225 reply_outbuf(req
, 0, 0);
7228 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
7230 TALLOC_FREE(smb_dname
);
7231 END_PROFILE(SMBrmdir
);
7235 /*******************************************************************
7236 Resolve wildcards in a filename rename.
7237 ********************************************************************/
7239 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
7244 char *name2_copy
= NULL
;
7249 char *p
,*p2
, *pname1
, *pname2
;
7251 name2_copy
= talloc_strdup(ctx
, name2
);
7256 pname1
= strrchr_m(name1
,'/');
7257 pname2
= strrchr_m(name2_copy
,'/');
7259 if (!pname1
|| !pname2
) {
7263 /* Truncate the copy of name2 at the last '/' */
7266 /* Now go past the '/' */
7270 root1
= talloc_strdup(ctx
, pname1
);
7271 root2
= talloc_strdup(ctx
, pname2
);
7273 if (!root1
|| !root2
) {
7277 p
= strrchr_m(root1
,'.');
7280 ext1
= talloc_strdup(ctx
, p
+1);
7282 ext1
= talloc_strdup(ctx
, "");
7284 p
= strrchr_m(root2
,'.');
7287 ext2
= talloc_strdup(ctx
, p
+1);
7289 ext2
= talloc_strdup(ctx
, "");
7292 if (!ext1
|| !ext2
) {
7300 /* Hmmm. Should this be mb-aware ? */
7303 } else if (*p2
== '*') {
7305 root2
= talloc_asprintf(ctx
, "%s%s",
7324 /* Hmmm. Should this be mb-aware ? */
7327 } else if (*p2
== '*') {
7329 ext2
= talloc_asprintf(ctx
, "%s%s",
7345 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
7350 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
7362 /****************************************************************************
7363 Ensure open files have their names updated. Updated to notify other smbd's
7365 ****************************************************************************/
7367 static void rename_open_files(connection_struct
*conn
,
7368 struct share_mode_lock
*lck
,
7370 uint32_t orig_name_hash
,
7371 const struct smb_filename
*smb_fname_dst
)
7374 bool did_rename
= False
;
7376 uint32_t new_name_hash
= 0;
7378 for(fsp
= file_find_di_first(conn
->sconn
, id
, false); fsp
;
7379 fsp
= file_find_di_next(fsp
, false)) {
7380 struct file_id_buf idbuf
;
7381 /* fsp_name is a relative path under the fsp. To change this for other
7382 sharepaths we need to manipulate relative paths. */
7383 /* TODO - create the absolute path and manipulate the newname
7384 relative to the sharepath. */
7385 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
7388 if (fsp
->name_hash
!= orig_name_hash
) {
7391 DBG_DEBUG("renaming file %s "
7392 "(file_id %s) from %s -> %s\n",
7394 file_id_str_buf(fsp
->file_id
, &idbuf
),
7396 smb_fname_str_dbg(smb_fname_dst
));
7398 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
7399 if (NT_STATUS_IS_OK(status
)) {
7401 new_name_hash
= fsp
->name_hash
;
7406 struct file_id_buf idbuf
;
7407 DBG_DEBUG("no open files on file_id %s "
7409 file_id_str_buf(id
, &idbuf
),
7410 smb_fname_str_dbg(smb_fname_dst
));
7413 /* Send messages to all smbd's (not ourself) that the name has changed. */
7414 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
7415 orig_name_hash
, new_name_hash
,
7420 /****************************************************************************
7421 We need to check if the source path is a parent directory of the destination
7422 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7423 refuse the rename with a sharing violation. Under UNIX the above call can
7424 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7425 probably need to check that the client is a Windows one before disallowing
7426 this as a UNIX client (one with UNIX extensions) can know the source is a
7427 symlink and make this decision intelligently. Found by an excellent bug
7428 report from <AndyLiebman@aol.com>.
7429 ****************************************************************************/
7431 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
7432 const struct smb_filename
*smb_fname_dst
)
7434 const char *psrc
= smb_fname_src
->base_name
;
7435 const char *pdst
= smb_fname_dst
->base_name
;
7438 if (psrc
[0] == '.' && psrc
[1] == '/') {
7441 if (pdst
[0] == '.' && pdst
[1] == '/') {
7444 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
7447 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
7451 * Do the notify calls from a rename
7454 static void notify_rename(connection_struct
*conn
, bool is_dir
,
7455 const struct smb_filename
*smb_fname_src
,
7456 const struct smb_filename
*smb_fname_dst
)
7458 char *parent_dir_src
= NULL
;
7459 char *parent_dir_dst
= NULL
;
7462 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
7463 : FILE_NOTIFY_CHANGE_FILE_NAME
;
7465 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
7466 &parent_dir_src
, NULL
) ||
7467 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
7468 &parent_dir_dst
, NULL
)) {
7472 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
7473 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
7474 smb_fname_src
->base_name
);
7475 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
7476 smb_fname_dst
->base_name
);
7479 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
7480 smb_fname_src
->base_name
);
7481 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
7482 smb_fname_dst
->base_name
);
7485 /* this is a strange one. w2k3 gives an additional event for
7486 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7487 files, but not directories */
7489 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7490 FILE_NOTIFY_CHANGE_ATTRIBUTES
7491 |FILE_NOTIFY_CHANGE_CREATION
,
7492 smb_fname_dst
->base_name
);
7495 TALLOC_FREE(parent_dir_src
);
7496 TALLOC_FREE(parent_dir_dst
);
7499 /****************************************************************************
7500 Returns an error if the parent directory for a filename is open in an
7502 ****************************************************************************/
7504 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
7505 const struct smb_filename
*smb_fname_dst_in
)
7507 struct smb_filename
*smb_fname_parent
= NULL
;
7509 files_struct
*fsp
= NULL
;
7513 ok
= parent_smb_fname(talloc_tos(),
7518 return NT_STATUS_NO_MEMORY
;
7521 ret
= SMB_VFS_LSTAT(conn
, smb_fname_parent
);
7523 return map_nt_error_from_unix(errno
);
7527 * We're only checking on this smbd here, mostly good
7528 * enough.. and will pass tests.
7531 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
->st
);
7532 for (fsp
= file_find_di_first(conn
->sconn
, id
, true); fsp
;
7533 fsp
= file_find_di_next(fsp
, true)) {
7534 if (fsp
->access_mask
& DELETE_ACCESS
) {
7535 return NT_STATUS_SHARING_VIOLATION
;
7538 return NT_STATUS_OK
;
7541 /****************************************************************************
7542 Rename an open file - given an fsp.
7543 ****************************************************************************/
7545 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
7547 struct smb_filename
*smb_fname_dst_in
,
7548 const char *dst_original_lcomp
,
7550 bool replace_if_exists
)
7552 TALLOC_CTX
*ctx
= talloc_tos();
7553 struct smb_filename
*smb_fname_dst
= NULL
;
7554 NTSTATUS status
= NT_STATUS_OK
;
7555 struct share_mode_lock
*lck
= NULL
;
7556 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
7557 bool dst_exists
, old_is_stream
, new_is_stream
;
7560 status
= check_name(conn
, smb_fname_dst_in
);
7561 if (!NT_STATUS_IS_OK(status
)) {
7565 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
7566 if (!NT_STATUS_IS_OK(status
)) {
7570 if (file_has_open_streams(fsp
)) {
7571 return NT_STATUS_ACCESS_DENIED
;
7574 /* Make a copy of the dst smb_fname structs */
7576 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
7577 if (smb_fname_dst
== NULL
) {
7578 status
= NT_STATUS_NO_MEMORY
;
7583 * Check for special case with case preserving and not
7584 * case sensitive. If the new last component differs from the original
7585 * last component only by case, then we should allow
7586 * the rename (user is trying to change the case of the
7589 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
7590 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
7591 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
7592 char *fname_dst_parent
= NULL
;
7593 const char *fname_dst_lcomp
= NULL
;
7594 char *orig_lcomp_path
= NULL
;
7595 char *orig_lcomp_stream
= NULL
;
7599 * Split off the last component of the processed
7600 * destination name. We will compare this to
7601 * the split components of dst_original_lcomp.
7603 if (!parent_dirname(ctx
,
7604 smb_fname_dst
->base_name
,
7606 &fname_dst_lcomp
)) {
7607 status
= NT_STATUS_NO_MEMORY
;
7612 * The dst_original_lcomp component contains
7613 * the last_component of the path + stream
7614 * name (if a stream exists).
7616 * Split off the stream name so we
7617 * can check them separately.
7620 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
7621 /* POSIX - no stream component. */
7622 orig_lcomp_path
= talloc_strdup(ctx
,
7623 dst_original_lcomp
);
7624 if (orig_lcomp_path
== NULL
) {
7628 ok
= split_stream_filename(ctx
,
7631 &orig_lcomp_stream
);
7635 TALLOC_FREE(fname_dst_parent
);
7636 status
= NT_STATUS_NO_MEMORY
;
7640 /* If the base names only differ by case, use original. */
7641 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
7644 * Replace the modified last component with the
7647 if (!ISDOT(fname_dst_parent
)) {
7648 tmp
= talloc_asprintf(smb_fname_dst
,
7653 tmp
= talloc_strdup(smb_fname_dst
,
7657 status
= NT_STATUS_NO_MEMORY
;
7658 TALLOC_FREE(fname_dst_parent
);
7659 TALLOC_FREE(orig_lcomp_path
);
7660 TALLOC_FREE(orig_lcomp_stream
);
7663 TALLOC_FREE(smb_fname_dst
->base_name
);
7664 smb_fname_dst
->base_name
= tmp
;
7667 /* If the stream_names only differ by case, use original. */
7668 if(!strcsequal(smb_fname_dst
->stream_name
,
7669 orig_lcomp_stream
)) {
7670 /* Use the original stream. */
7671 char *tmp
= talloc_strdup(smb_fname_dst
,
7674 status
= NT_STATUS_NO_MEMORY
;
7675 TALLOC_FREE(fname_dst_parent
);
7676 TALLOC_FREE(orig_lcomp_path
);
7677 TALLOC_FREE(orig_lcomp_stream
);
7680 TALLOC_FREE(smb_fname_dst
->stream_name
);
7681 smb_fname_dst
->stream_name
= tmp
;
7683 TALLOC_FREE(fname_dst_parent
);
7684 TALLOC_FREE(orig_lcomp_path
);
7685 TALLOC_FREE(orig_lcomp_stream
);
7689 * If the src and dest names are identical - including case,
7690 * don't do the rename, just return success.
7693 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
7694 strcsequal(fsp
->fsp_name
->stream_name
,
7695 smb_fname_dst
->stream_name
)) {
7696 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7697 "- returning success\n",
7698 smb_fname_str_dbg(smb_fname_dst
)));
7699 status
= NT_STATUS_OK
;
7703 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
7704 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
7706 /* Return the correct error code if both names aren't streams. */
7707 if (!old_is_stream
&& new_is_stream
) {
7708 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7712 if (old_is_stream
&& !new_is_stream
) {
7713 status
= NT_STATUS_INVALID_PARAMETER
;
7717 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
7719 if(!replace_if_exists
&& dst_exists
) {
7720 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7721 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
7722 smb_fname_str_dbg(smb_fname_dst
)));
7723 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
7728 * Drop the pathref fsp on the destination otherwise we trip upon in in
7729 * the below check for open files check.
7731 if (smb_fname_dst_in
->fsp
!= NULL
) {
7732 fd_close(smb_fname_dst_in
->fsp
);
7733 file_free(NULL
, smb_fname_dst_in
->fsp
);
7734 SMB_ASSERT(smb_fname_dst_in
->fsp
== NULL
);
7738 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
7739 &smb_fname_dst
->st
);
7740 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
7742 /* The file can be open when renaming a stream */
7743 if (dst_fsp
&& !new_is_stream
) {
7744 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7745 status
= NT_STATUS_ACCESS_DENIED
;
7750 /* Ensure we have a valid stat struct for the source. */
7751 status
= vfs_stat_fsp(fsp
);
7752 if (!NT_STATUS_IS_OK(status
)) {
7756 status
= can_rename(conn
, fsp
, attrs
);
7758 if (!NT_STATUS_IS_OK(status
)) {
7759 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7760 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
7761 smb_fname_str_dbg(smb_fname_dst
)));
7762 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
7763 status
= NT_STATUS_ACCESS_DENIED
;
7767 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
7768 status
= NT_STATUS_ACCESS_DENIED
;
7772 /* Do we have rights to move into the destination ? */
7773 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
7774 /* We're moving a directory. */
7775 access_mask
= SEC_DIR_ADD_SUBDIR
;
7777 status
= check_parent_access(conn
,
7781 if (!NT_STATUS_IS_OK(status
)) {
7782 DBG_INFO("check_parent_access on "
7783 "dst %s returned %s\n",
7784 smb_fname_str_dbg(smb_fname_dst
),
7789 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7792 * We have the file open ourselves, so not being able to get the
7793 * corresponding share mode lock is a fatal error.
7796 SMB_ASSERT(lck
!= NULL
);
7798 ret
= SMB_VFS_RENAMEAT(conn
,
7804 uint32_t create_options
= fh_get_private_options(fsp
->fh
);
7806 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7807 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
7808 smb_fname_str_dbg(smb_fname_dst
)));
7810 if (!fsp
->fsp_flags
.is_directory
&&
7811 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
7812 (lp_map_archive(SNUM(conn
)) ||
7813 lp_store_dos_attributes(SNUM(conn
)))) {
7814 /* We must set the archive bit on the newly
7816 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
7817 uint32_t old_dosmode
= dos_mode(conn
,
7819 file_set_dosmode(conn
,
7821 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
7828 fsp
->fsp_flags
.is_directory
,
7832 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
7836 * A rename acts as a new file create w.r.t. allowing an initial delete
7837 * on close, probably because in Windows there is a new handle to the
7838 * new file. If initial delete on close was requested but not
7839 * originally set, we need to set it here. This is probably not 100% correct,
7840 * but will work for the CIFSFS client which in non-posix mode
7841 * depends on these semantics. JRA.
7844 if (create_options
& FILE_DELETE_ON_CLOSE
) {
7845 status
= can_set_delete_on_close(fsp
, 0);
7847 if (NT_STATUS_IS_OK(status
)) {
7848 /* Note that here we set the *initial* delete on close flag,
7849 * not the regular one. The magic gets handled in close. */
7850 fsp
->fsp_flags
.initial_delete_on_close
= true;
7854 status
= NT_STATUS_OK
;
7860 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
7861 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
7863 status
= map_nt_error_from_unix(errno
);
7866 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7867 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
7868 smb_fname_str_dbg(smb_fname_dst
)));
7871 TALLOC_FREE(smb_fname_dst
);
7876 /****************************************************************************
7877 The guts of the rename command, split out so it may be called by the NT SMB
7879 ****************************************************************************/
7881 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
7882 connection_struct
*conn
,
7883 struct smb_request
*req
,
7884 struct smb_filename
*smb_fname_src
,
7885 const char *src_original_lcomp
,
7886 struct smb_filename
*smb_fname_dst
,
7887 const char *dst_original_lcomp
,
7889 bool replace_if_exists
,
7890 uint32_t access_mask
)
7892 char *fname_src_dir
= NULL
;
7893 struct smb_filename
*smb_fname_src_dir
= NULL
;
7894 char *fname_src_mask
= NULL
;
7896 NTSTATUS status
= NT_STATUS_OK
;
7897 struct smb_Dir
*dir_hnd
= NULL
;
7898 const char *dname
= NULL
;
7899 char *talloced
= NULL
;
7901 int create_options
= 0;
7902 struct smb2_create_blobs
*posx
= NULL
;
7904 bool src_has_wild
= false;
7905 bool dest_has_wild
= false;
7908 * Split the old name into directory and last component
7909 * strings. Note that unix_convert may have stripped off a
7910 * leading ./ from both name and newname if the rename is
7911 * at the root of the share. We need to make sure either both
7912 * name and newname contain a / character or neither of them do
7913 * as this is checked in resolve_wildcards().
7916 /* Split up the directory from the filename/mask. */
7917 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7918 &fname_src_dir
, &fname_src_mask
);
7919 if (!NT_STATUS_IS_OK(status
)) {
7920 status
= NT_STATUS_NO_MEMORY
;
7924 if (!(smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
)) {
7926 * Check the wildcard mask *before*
7927 * unmangling. As mangling is done
7928 * for names that can't be returned
7929 * to Windows the unmangled name may
7930 * contain Windows wildcard characters.
7932 if (src_original_lcomp
!= NULL
) {
7933 src_has_wild
= ms_has_wild(src_original_lcomp
);
7935 dest_has_wild
= ms_has_wild(dst_original_lcomp
);
7939 * We should only check the mangled cache
7940 * here if unix_convert failed. This means
7941 * that the path in 'mask' doesn't exist
7942 * on the file system and so we need to look
7943 * for a possible mangle. This patch from
7944 * Tine Smukavec <valentin.smukavec@hermes.si>.
7947 if (!VALID_STAT(smb_fname_src
->st
) &&
7948 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7949 char *new_mask
= NULL
;
7950 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
7953 TALLOC_FREE(fname_src_mask
);
7954 fname_src_mask
= new_mask
;
7958 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
7959 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
7960 if (!NT_STATUS_IS_OK(status
)) {
7961 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
7967 if (!src_has_wild
) {
7971 * Only one file needs to be renamed. Append the mask back
7972 * onto the directory.
7974 TALLOC_FREE(smb_fname_src
->base_name
);
7975 if (ISDOT(fname_src_dir
)) {
7976 /* Ensure we use canonical names on open. */
7977 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7981 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7986 if (!smb_fname_src
->base_name
) {
7987 status
= NT_STATUS_NO_MEMORY
;
7991 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7992 "case_preserve = %d, short case preserve = %d, "
7993 "directory = %s, newname = %s, "
7994 "last_component_dest = %s\n",
7995 conn
->case_sensitive
, conn
->case_preserve
,
7996 conn
->short_case_preserve
,
7997 smb_fname_str_dbg(smb_fname_src
),
7998 smb_fname_str_dbg(smb_fname_dst
),
7999 dst_original_lcomp
));
8001 /* The dest name still may have wildcards. */
8002 if (dest_has_wild
) {
8003 char *fname_dst_mod
= NULL
;
8004 if (!resolve_wildcards(smb_fname_dst
,
8005 smb_fname_src
->base_name
,
8006 smb_fname_dst
->base_name
,
8008 DEBUG(6, ("rename_internals: resolve_wildcards "
8010 smb_fname_src
->base_name
,
8011 smb_fname_dst
->base_name
));
8012 status
= NT_STATUS_NO_MEMORY
;
8015 TALLOC_FREE(smb_fname_dst
->base_name
);
8016 smb_fname_dst
->base_name
= fname_dst_mod
;
8019 ZERO_STRUCT(smb_fname_src
->st
);
8021 rc
= vfs_stat(conn
, smb_fname_src
);
8023 status
= map_nt_error_from_unix_common(errno
);
8027 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_src
);
8028 if (NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
8029 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8031 if (!NT_STATUS_IS_OK(status
)) {
8035 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
8036 create_options
|= FILE_DIRECTORY_FILE
;
8039 status
= SMB_VFS_CREATE_FILE(
8042 smb_fname_src
, /* fname */
8043 access_mask
, /* access_mask */
8044 (FILE_SHARE_READ
| /* share_access */
8046 FILE_OPEN
, /* create_disposition*/
8047 create_options
, /* create_options */
8048 0, /* file_attributes */
8049 0, /* oplock_request */
8051 0, /* allocation_size */
8052 0, /* private_flags */
8057 posx
, /* in_context_blobs */
8058 NULL
); /* out_context_blobs */
8060 if (!NT_STATUS_IS_OK(status
)) {
8061 DEBUG(3, ("Could not open rename source %s: %s\n",
8062 smb_fname_str_dbg(smb_fname_src
),
8063 nt_errstr(status
)));
8067 status
= rename_internals_fsp(conn
,
8074 close_file(req
, fsp
, NORMAL_CLOSE
);
8076 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8077 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
8078 smb_fname_str_dbg(smb_fname_dst
)));
8084 * Wildcards - process each file that matches.
8086 if (strequal(fname_src_mask
, "????????.???")) {
8087 TALLOC_FREE(fname_src_mask
);
8088 fname_src_mask
= talloc_strdup(ctx
, "*");
8089 if (!fname_src_mask
) {
8090 status
= NT_STATUS_NO_MEMORY
;
8095 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
8099 smb_fname_src
->twrp
,
8100 smb_fname_src
->flags
);
8101 if (smb_fname_src_dir
== NULL
) {
8102 status
= NT_STATUS_NO_MEMORY
;
8106 status
= check_name(conn
, smb_fname_src_dir
);
8107 if (!NT_STATUS_IS_OK(status
)) {
8111 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
8113 if (dir_hnd
== NULL
) {
8114 status
= map_nt_error_from_unix(errno
);
8118 status
= NT_STATUS_NO_SUCH_FILE
;
8120 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8121 * - gentest fix. JRA
8124 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
8126 files_struct
*fsp
= NULL
;
8127 char *destname
= NULL
;
8128 bool sysdir_entry
= False
;
8130 /* Quick check for "." and ".." */
8131 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
8132 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
8133 sysdir_entry
= True
;
8135 TALLOC_FREE(talloced
);
8140 if (!is_visible_file(conn
,
8145 TALLOC_FREE(talloced
);
8149 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
8150 TALLOC_FREE(talloced
);
8155 status
= NT_STATUS_OBJECT_NAME_INVALID
;
8159 TALLOC_FREE(smb_fname_src
->base_name
);
8160 if (ISDOT(fname_src_dir
)) {
8161 /* Ensure we use canonical names on open. */
8162 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8166 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8171 if (!smb_fname_src
->base_name
) {
8172 status
= NT_STATUS_NO_MEMORY
;
8176 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
8177 smb_fname_dst
->base_name
,
8179 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8180 smb_fname_src
->base_name
, destname
));
8181 TALLOC_FREE(talloced
);
8185 status
= NT_STATUS_NO_MEMORY
;
8189 TALLOC_FREE(smb_fname_dst
->base_name
);
8190 smb_fname_dst
->base_name
= destname
;
8192 ZERO_STRUCT(smb_fname_src
->st
);
8193 vfs_stat(conn
, smb_fname_src
);
8195 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_src
);
8196 if (NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
8197 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8199 if (!NT_STATUS_IS_OK(status
)) {
8200 DBG_INFO("openat_pathref_fsp [%s] failed: %s\n",
8201 smb_fname_str_dbg(smb_fname_src
),
8208 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
8209 create_options
|= FILE_DIRECTORY_FILE
;
8212 status
= SMB_VFS_CREATE_FILE(
8215 smb_fname_src
, /* fname */
8216 access_mask
, /* access_mask */
8217 (FILE_SHARE_READ
| /* share_access */
8219 FILE_OPEN
, /* create_disposition*/
8220 create_options
, /* create_options */
8221 0, /* file_attributes */
8222 0, /* oplock_request */
8224 0, /* allocation_size */
8225 0, /* private_flags */
8230 posx
, /* in_context_blobs */
8231 NULL
); /* out_context_blobs */
8233 if (!NT_STATUS_IS_OK(status
)) {
8234 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8235 "returned %s rename %s -> %s\n",
8237 smb_fname_str_dbg(smb_fname_src
),
8238 smb_fname_str_dbg(smb_fname_dst
)));
8242 dst_original_lcomp
= talloc_strdup(smb_fname_dst
, dname
);
8243 if (dst_original_lcomp
== NULL
) {
8244 status
= NT_STATUS_NO_MEMORY
;
8248 status
= rename_internals_fsp(conn
,
8255 close_file(req
, fsp
, NORMAL_CLOSE
);
8257 if (!NT_STATUS_IS_OK(status
)) {
8258 DEBUG(3, ("rename_internals_fsp returned %s for "
8259 "rename %s -> %s\n", nt_errstr(status
),
8260 smb_fname_str_dbg(smb_fname_src
),
8261 smb_fname_str_dbg(smb_fname_dst
)));
8267 DEBUG(3,("rename_internals: doing rename on %s -> "
8268 "%s\n", smb_fname_str_dbg(smb_fname_src
),
8269 smb_fname_str_dbg(smb_fname_src
)));
8270 TALLOC_FREE(talloced
);
8272 TALLOC_FREE(dir_hnd
);
8274 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
8275 status
= map_nt_error_from_unix(errno
);
8280 TALLOC_FREE(talloced
);
8281 TALLOC_FREE(smb_fname_src_dir
);
8282 TALLOC_FREE(fname_src_dir
);
8283 TALLOC_FREE(fname_src_mask
);
8287 /****************************************************************************
8289 ****************************************************************************/
8291 void reply_mv(struct smb_request
*req
)
8293 connection_struct
*conn
= req
->conn
;
8295 char *newname
= NULL
;
8299 TALLOC_CTX
*ctx
= talloc_tos();
8300 struct smb_filename
*smb_fname_src
= NULL
;
8301 const char *src_original_lcomp
= NULL
;
8302 struct smb_filename
*smb_fname_dst
= NULL
;
8303 const char *dst_original_lcomp
= NULL
;
8304 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
) |
8305 (!req
->posix_pathnames
? UCF_ALWAYS_ALLOW_WCARD_LCOMP
: 0);
8306 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
) |
8307 (!req
->posix_pathnames
? UCF_ALWAYS_ALLOW_WCARD_LCOMP
: 0);
8308 bool stream_rename
= false;
8310 START_PROFILE(SMBmv
);
8313 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8317 attrs
= SVAL(req
->vwv
+0, 0);
8319 p
= (const char *)req
->buf
+ 1;
8320 p
+= srvstr_get_path_req(ctx
, req
, &name
, p
, STR_TERMINATE
,
8322 if (!NT_STATUS_IS_OK(status
)) {
8323 reply_nterror(req
, status
);
8327 p
+= srvstr_get_path_req(ctx
, req
, &newname
, p
, STR_TERMINATE
,
8329 if (!NT_STATUS_IS_OK(status
)) {
8330 reply_nterror(req
, status
);
8334 if (!req
->posix_pathnames
) {
8335 /* The newname must begin with a ':' if the
8336 name contains a ':'. */
8337 if (strchr_m(name
, ':')) {
8338 if (newname
[0] != ':') {
8339 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8342 stream_rename
= true;
8346 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 /* Get the last component of the source for rename_internals(). */
8364 src_original_lcomp
= get_original_lcomp(ctx
,
8368 if (src_original_lcomp
== NULL
) {
8369 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8373 status
= filename_convert(ctx
,
8380 if (!NT_STATUS_IS_OK(status
)) {
8381 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8382 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8383 ERRSRV
, ERRbadpath
);
8386 reply_nterror(req
, status
);
8390 /* Get the last component of the destination for rename_internals(). */
8391 dst_original_lcomp
= get_original_lcomp(ctx
,
8395 if (dst_original_lcomp
== NULL
) {
8396 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8400 if (stream_rename
) {
8401 /* smb_fname_dst->base_name must be the same as
8402 smb_fname_src->base_name. */
8403 TALLOC_FREE(smb_fname_dst
->base_name
);
8404 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
8405 smb_fname_src
->base_name
);
8406 if (!smb_fname_dst
->base_name
) {
8407 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8412 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
8413 smb_fname_str_dbg(smb_fname_dst
)));
8415 status
= rename_internals(ctx
,
8425 if (!NT_STATUS_IS_OK(status
)) {
8426 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8427 /* We have re-scheduled this call. */
8430 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
8431 bool ok
= defer_smb1_sharing_violation(req
);
8436 reply_nterror(req
, status
);
8440 reply_outbuf(req
, 0, 0);
8442 TALLOC_FREE(smb_fname_src
);
8443 TALLOC_FREE(smb_fname_dst
);
8448 /*******************************************************************
8449 Copy a file as part of a reply_copy.
8450 ******************************************************************/
8453 * TODO: check error codes on all callers
8456 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
8457 connection_struct
*conn
,
8458 struct smb_filename
*smb_fname_src
,
8459 struct smb_filename
*smb_fname_dst
,
8462 bool target_is_directory
)
8464 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
8466 files_struct
*fsp1
,*fsp2
;
8468 uint32_t new_create_disposition
;
8472 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
8473 if (smb_fname_dst_tmp
== NULL
) {
8474 return NT_STATUS_NO_MEMORY
;
8478 * If the target is a directory, extract the last component from the
8479 * src filename and append it to the dst filename
8481 if (target_is_directory
) {
8484 /* dest/target can't be a stream if it's a directory. */
8485 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
8487 p
= strrchr_m(smb_fname_src
->base_name
,'/');
8491 p
= smb_fname_src
->base_name
;
8493 smb_fname_dst_tmp
->base_name
=
8494 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
8496 if (!smb_fname_dst_tmp
->base_name
) {
8497 status
= NT_STATUS_NO_MEMORY
;
8502 status
= vfs_file_exist(conn
, smb_fname_src
);
8503 if (!NT_STATUS_IS_OK(status
)) {
8507 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_src
);
8508 if (NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
8509 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8511 if (!NT_STATUS_IS_OK(status
)) {
8515 if (!target_is_directory
&& count
) {
8516 new_create_disposition
= FILE_OPEN
;
8518 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
8521 &new_create_disposition
,
8524 status
= NT_STATUS_INVALID_PARAMETER
;
8529 /* Open the src file for reading. */
8530 status
= SMB_VFS_CREATE_FILE(
8533 smb_fname_src
, /* fname */
8534 FILE_GENERIC_READ
, /* access_mask */
8535 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
8536 FILE_OPEN
, /* create_disposition*/
8537 0, /* create_options */
8538 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
8539 INTERNAL_OPEN_ONLY
, /* oplock_request */
8541 0, /* allocation_size */
8542 0, /* private_flags */
8547 NULL
, NULL
); /* create context */
8549 if (!NT_STATUS_IS_OK(status
)) {
8553 dosattrs
= dos_mode(conn
, smb_fname_src
);
8555 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
8556 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
8559 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_dst
);
8560 if (NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
8561 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8564 if (!NT_STATUS_IS_OK(status
) &&
8565 !NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
))
8570 /* Open the dst file for writing. */
8571 status
= SMB_VFS_CREATE_FILE(
8574 smb_fname_dst
, /* fname */
8575 FILE_GENERIC_WRITE
, /* access_mask */
8576 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
8577 new_create_disposition
, /* create_disposition*/
8578 0, /* create_options */
8579 dosattrs
, /* file_attributes */
8580 INTERNAL_OPEN_ONLY
, /* oplock_request */
8582 0, /* allocation_size */
8583 0, /* private_flags */
8588 NULL
, NULL
); /* create context */
8590 if (!NT_STATUS_IS_OK(status
)) {
8591 close_file(NULL
, fsp1
, ERROR_CLOSE
);
8595 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
8596 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
8598 DEBUG(0, ("error - vfs lseek returned error %s\n",
8600 status
= map_nt_error_from_unix(errno
);
8601 close_file(NULL
, fsp1
, ERROR_CLOSE
);
8602 close_file(NULL
, fsp2
, ERROR_CLOSE
);
8607 /* Do the actual copy. */
8608 if (smb_fname_src
->st
.st_ex_size
) {
8609 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
8614 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
8616 /* Ensure the modtime is set correctly on the destination file. */
8617 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
8620 * As we are opening fsp1 read-only we only expect
8621 * an error on close on fsp2 if we are out of space.
8622 * Thus we don't look at the error return from the
8625 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
8627 if (!NT_STATUS_IS_OK(status
)) {
8631 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
8632 status
= NT_STATUS_DISK_FULL
;
8636 status
= NT_STATUS_OK
;
8639 TALLOC_FREE(smb_fname_dst_tmp
);
8643 /****************************************************************************
8644 Reply to a file copy.
8645 ****************************************************************************/
8647 void reply_copy(struct smb_request
*req
)
8649 connection_struct
*conn
= req
->conn
;
8650 struct smb_filename
*smb_fname_src
= NULL
;
8651 struct smb_filename
*smb_fname_src_dir
= NULL
;
8652 struct smb_filename
*smb_fname_dst
= NULL
;
8653 char *fname_src
= NULL
;
8654 char *fname_dst
= NULL
;
8655 char *fname_src_mask
= NULL
;
8656 char *fname_src_dir
= NULL
;
8659 int error
= ERRnoaccess
;
8663 bool target_is_directory
=False
;
8664 bool source_has_wild
= False
;
8665 bool dest_has_wild
= False
;
8667 uint32_t ucf_flags_src
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
8668 ucf_flags_from_smb_request(req
);
8669 uint32_t ucf_flags_dst
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
8670 ucf_flags_from_smb_request(req
);
8671 TALLOC_CTX
*ctx
= talloc_tos();
8673 START_PROFILE(SMBcopy
);
8676 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8680 tid2
= SVAL(req
->vwv
+0, 0);
8681 ofun
= SVAL(req
->vwv
+1, 0);
8682 flags
= SVAL(req
->vwv
+2, 0);
8684 p
= (const char *)req
->buf
;
8685 p
+= srvstr_get_path_req(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
8687 if (!NT_STATUS_IS_OK(status
)) {
8688 reply_nterror(req
, status
);
8691 p
+= srvstr_get_path_req(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
8693 if (!NT_STATUS_IS_OK(status
)) {
8694 reply_nterror(req
, status
);
8698 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
8700 if (tid2
!= conn
->cnum
) {
8701 /* can't currently handle inter share copies XXXX */
8702 DEBUG(3,("Rejecting inter-share copy\n"));
8703 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
8707 status
= filename_convert(ctx
, conn
,
8712 if (!NT_STATUS_IS_OK(status
)) {
8713 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8714 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8715 ERRSRV
, ERRbadpath
);
8718 reply_nterror(req
, status
);
8722 status
= filename_convert(ctx
, conn
,
8727 if (!NT_STATUS_IS_OK(status
)) {
8728 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8729 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8730 ERRSRV
, ERRbadpath
);
8733 reply_nterror(req
, status
);
8737 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
8739 if ((flags
&1) && target_is_directory
) {
8740 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
8744 if ((flags
&2) && !target_is_directory
) {
8745 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8749 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
8750 /* wants a tree copy! XXXX */
8751 DEBUG(3,("Rejecting tree copy\n"));
8752 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8756 /* Split up the directory from the filename/mask. */
8757 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
8758 &fname_src_dir
, &fname_src_mask
);
8759 if (!NT_STATUS_IS_OK(status
)) {
8760 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8764 if (!req
->posix_pathnames
) {
8765 char *orig_src_lcomp
= NULL
;
8766 char *orig_dst_lcomp
= NULL
;
8768 * Check the wildcard mask *before*
8769 * unmangling. As mangling is done
8770 * for names that can't be returned
8771 * to Windows the unmangled name may
8772 * contain Windows wildcard characters.
8774 orig_src_lcomp
= get_original_lcomp(ctx
,
8778 if (orig_src_lcomp
== NULL
) {
8779 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8782 orig_dst_lcomp
= get_original_lcomp(ctx
,
8786 if (orig_dst_lcomp
== NULL
) {
8787 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8790 source_has_wild
= ms_has_wild(orig_src_lcomp
);
8791 dest_has_wild
= ms_has_wild(orig_dst_lcomp
);
8792 TALLOC_FREE(orig_src_lcomp
);
8793 TALLOC_FREE(orig_dst_lcomp
);
8797 * We should only check the mangled cache
8798 * here if unix_convert failed. This means
8799 * that the path in 'mask' doesn't exist
8800 * on the file system and so we need to look
8801 * for a possible mangle. This patch from
8802 * Tine Smukavec <valentin.smukavec@hermes.si>.
8804 if (!VALID_STAT(smb_fname_src
->st
) &&
8805 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
8806 char *new_mask
= NULL
;
8807 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
8808 &new_mask
, conn
->params
);
8810 /* Use demangled name if one was successfully found. */
8812 TALLOC_FREE(fname_src_mask
);
8813 fname_src_mask
= new_mask
;
8817 if (!source_has_wild
) {
8820 * Only one file needs to be copied. Append the mask back onto
8823 TALLOC_FREE(smb_fname_src
->base_name
);
8824 if (ISDOT(fname_src_dir
)) {
8825 /* Ensure we use canonical names on open. */
8826 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8830 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8835 if (!smb_fname_src
->base_name
) {
8836 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8840 if (dest_has_wild
) {
8841 char *fname_dst_mod
= NULL
;
8842 if (!resolve_wildcards(smb_fname_dst
,
8843 smb_fname_src
->base_name
,
8844 smb_fname_dst
->base_name
,
8846 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8849 TALLOC_FREE(smb_fname_dst
->base_name
);
8850 smb_fname_dst
->base_name
= fname_dst_mod
;
8853 status
= check_name(conn
, smb_fname_src
);
8854 if (!NT_STATUS_IS_OK(status
)) {
8855 reply_nterror(req
, status
);
8859 status
= check_name(conn
, smb_fname_dst
);
8860 if (!NT_STATUS_IS_OK(status
)) {
8861 reply_nterror(req
, status
);
8865 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
8866 ofun
, count
, target_is_directory
);
8868 if(!NT_STATUS_IS_OK(status
)) {
8869 reply_nterror(req
, status
);
8875 struct smb_Dir
*dir_hnd
= NULL
;
8876 const char *dname
= NULL
;
8877 char *talloced
= NULL
;
8881 * There is a wildcard that requires us to actually read the
8882 * src dir and copy each file matching the mask to the dst.
8883 * Right now streams won't be copied, but this could
8884 * presumably be added with a nested loop for reach dir entry.
8886 SMB_ASSERT(!smb_fname_src
->stream_name
);
8887 SMB_ASSERT(!smb_fname_dst
->stream_name
);
8889 smb_fname_src
->stream_name
= NULL
;
8890 smb_fname_dst
->stream_name
= NULL
;
8892 if (strequal(fname_src_mask
,"????????.???")) {
8893 TALLOC_FREE(fname_src_mask
);
8894 fname_src_mask
= talloc_strdup(ctx
, "*");
8895 if (!fname_src_mask
) {
8896 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8901 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
8905 smb_fname_src
->twrp
,
8906 smb_fname_src
->flags
);
8907 if (smb_fname_src_dir
== NULL
) {
8908 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8912 status
= check_name(conn
, smb_fname_src_dir
);
8913 if (!NT_STATUS_IS_OK(status
)) {
8914 reply_nterror(req
, status
);
8918 dir_hnd
= OpenDir(ctx
,
8923 if (dir_hnd
== NULL
) {
8924 status
= map_nt_error_from_unix(errno
);
8925 reply_nterror(req
, status
);
8931 /* Iterate over the src dir copying each entry to the dst. */
8932 while ((dname
= ReadDirName(dir_hnd
, &offset
,
8933 &smb_fname_src
->st
, &talloced
))) {
8934 char *destname
= NULL
;
8936 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
8937 TALLOC_FREE(talloced
);
8941 if (!is_visible_file(conn
,
8946 TALLOC_FREE(talloced
);
8950 if(!mask_match(dname
, fname_src_mask
,
8951 conn
->case_sensitive
)) {
8952 TALLOC_FREE(talloced
);
8956 error
= ERRnoaccess
;
8958 /* Get the src smb_fname struct setup. */
8959 TALLOC_FREE(smb_fname_src
->base_name
);
8960 if (ISDOT(fname_src_dir
)) {
8961 /* Ensure we use canonical names on open. */
8962 smb_fname_src
->base_name
=
8963 talloc_asprintf(smb_fname_src
, "%s",
8966 smb_fname_src
->base_name
=
8967 talloc_asprintf(smb_fname_src
, "%s/%s",
8968 fname_src_dir
, dname
);
8971 if (!smb_fname_src
->base_name
) {
8972 TALLOC_FREE(dir_hnd
);
8973 TALLOC_FREE(talloced
);
8974 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8978 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
8979 smb_fname_dst
->base_name
,
8981 TALLOC_FREE(talloced
);
8985 TALLOC_FREE(dir_hnd
);
8986 TALLOC_FREE(talloced
);
8987 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8991 TALLOC_FREE(smb_fname_dst
->base_name
);
8992 smb_fname_dst
->base_name
= destname
;
8994 status
= check_name(conn
, smb_fname_src
);
8995 if (!NT_STATUS_IS_OK(status
)) {
8996 TALLOC_FREE(dir_hnd
);
8997 TALLOC_FREE(talloced
);
8998 reply_nterror(req
, status
);
9002 status
= check_name(conn
, smb_fname_dst
);
9003 if (!NT_STATUS_IS_OK(status
)) {
9004 TALLOC_FREE(dir_hnd
);
9005 TALLOC_FREE(talloced
);
9006 reply_nterror(req
, status
);
9010 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
9011 smb_fname_src
->base_name
,
9012 smb_fname_dst
->base_name
));
9014 status
= copy_file(ctx
, conn
, smb_fname_src
,
9015 smb_fname_dst
, ofun
, count
,
9016 target_is_directory
);
9017 if (NT_STATUS_IS_OK(status
)) {
9021 TALLOC_FREE(talloced
);
9023 TALLOC_FREE(dir_hnd
);
9027 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
9031 reply_outbuf(req
, 1, 0);
9032 SSVAL(req
->outbuf
,smb_vwv0
,count
);
9034 TALLOC_FREE(smb_fname_src
);
9035 TALLOC_FREE(smb_fname_src_dir
);
9036 TALLOC_FREE(smb_fname_dst
);
9037 TALLOC_FREE(fname_src
);
9038 TALLOC_FREE(fname_dst
);
9039 TALLOC_FREE(fname_src_mask
);
9040 TALLOC_FREE(fname_src_dir
);
9042 END_PROFILE(SMBcopy
);
9047 #define DBGC_CLASS DBGC_LOCKING
9049 /****************************************************************************
9050 Get a lock pid, dealing with large count requests.
9051 ****************************************************************************/
9053 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
9054 bool large_file_format
)
9056 if(!large_file_format
)
9057 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
9059 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
9062 /****************************************************************************
9063 Get a lock count, dealing with large count requests.
9064 ****************************************************************************/
9066 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
9067 bool large_file_format
)
9071 if(!large_file_format
) {
9072 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
9075 * No BVAL, this is reversed!
9077 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
9078 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
9084 /****************************************************************************
9085 Get a lock offset, dealing with large offset requests.
9086 ****************************************************************************/
9088 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
9089 bool large_file_format
)
9091 uint64_t offset
= 0;
9093 if(!large_file_format
) {
9094 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
9097 * No BVAL, this is reversed!
9099 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
9100 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
9106 struct smbd_do_unlocking_state
{
9107 struct files_struct
*fsp
;
9108 uint16_t num_ulocks
;
9109 struct smbd_lock_element
*ulocks
;
9110 enum brl_flavour lock_flav
;
9114 static void smbd_do_unlocking_fn(
9117 bool *pmodified_dependent
,
9120 struct smbd_do_unlocking_state
*state
= private_data
;
9121 struct files_struct
*fsp
= state
->fsp
;
9122 enum brl_flavour lock_flav
= state
->lock_flav
;
9125 for (i
= 0; i
< state
->num_ulocks
; i
++) {
9126 struct smbd_lock_element
*e
= &state
->ulocks
[i
];
9128 DBG_DEBUG("unlock start=%"PRIu64
", len=%"PRIu64
" for "
9129 "pid %"PRIu64
", file %s\n",
9135 if (e
->brltype
!= UNLOCK_LOCK
) {
9136 /* this can only happen with SMB2 */
9137 state
->status
= NT_STATUS_INVALID_PARAMETER
;
9141 state
->status
= do_unlock(
9142 fsp
, e
->smblctx
, e
->count
, e
->offset
, lock_flav
);
9144 DBG_DEBUG("do_unlock returned %s\n",
9145 nt_errstr(state
->status
));
9147 if (!NT_STATUS_IS_OK(state
->status
)) {
9152 *pmodified_dependent
= true;
9155 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
9157 uint16_t num_ulocks
,
9158 struct smbd_lock_element
*ulocks
,
9159 enum brl_flavour lock_flav
)
9161 struct smbd_do_unlocking_state state
= {
9163 .num_ulocks
= num_ulocks
,
9165 .lock_flav
= lock_flav
,
9169 DBG_NOTICE("%s num_ulocks=%"PRIu16
"\n", fsp_fnum_dbg(fsp
), num_ulocks
);
9171 status
= share_mode_do_locked(
9172 fsp
->file_id
, smbd_do_unlocking_fn
, &state
);
9174 if (!NT_STATUS_IS_OK(status
)) {
9175 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9179 if (!NT_STATUS_IS_OK(state
.status
)) {
9180 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9182 return state
.status
;
9185 return NT_STATUS_OK
;
9188 /****************************************************************************
9189 Reply to a lockingX request.
9190 ****************************************************************************/
9192 static void reply_lockingx_done(struct tevent_req
*subreq
);
9194 void reply_lockingX(struct smb_request
*req
)
9196 connection_struct
*conn
= req
->conn
;
9198 unsigned char locktype
;
9199 enum brl_type brltype
;
9200 unsigned char oplocklevel
;
9201 uint16_t num_ulocks
;
9203 int32_t lock_timeout
;
9205 const uint8_t *data
;
9206 bool large_file_format
;
9207 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
9208 struct smbd_lock_element
*locks
= NULL
;
9209 struct tevent_req
*subreq
= NULL
;
9211 START_PROFILE(SMBlockingX
);
9214 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9215 END_PROFILE(SMBlockingX
);
9219 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
9220 locktype
= CVAL(req
->vwv
+3, 0);
9221 oplocklevel
= CVAL(req
->vwv
+3, 1);
9222 num_ulocks
= SVAL(req
->vwv
+6, 0);
9223 num_locks
= SVAL(req
->vwv
+7, 0);
9224 lock_timeout
= IVAL(req
->vwv
+4, 0);
9225 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
9227 if (!check_fsp(conn
, req
, fsp
)) {
9228 END_PROFILE(SMBlockingX
);
9234 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
9235 /* we don't support these - and CANCEL_LOCK makes w2k
9236 and XP reboot so I don't really want to be
9237 compatible! (tridge) */
9238 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
9239 END_PROFILE(SMBlockingX
);
9243 /* Check if this is an oplock break on a file
9244 we have granted an oplock on.
9246 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
9247 /* Client can insist on breaking to none. */
9248 bool break_to_none
= (oplocklevel
== 0);
9251 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9252 "for %s\n", (unsigned int)oplocklevel
,
9253 fsp_fnum_dbg(fsp
)));
9256 * Make sure we have granted an exclusive or batch oplock on
9260 if (fsp
->oplock_type
== 0) {
9262 /* The Samba4 nbench simulator doesn't understand
9263 the difference between break to level2 and break
9264 to none from level2 - it sends oplock break
9265 replies in both cases. Don't keep logging an error
9266 message here - just ignore it. JRA. */
9268 DEBUG(5,("reply_lockingX: Error : oplock break from "
9269 "client for %s (oplock=%d) and no "
9270 "oplock granted on this file (%s).\n",
9271 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
9274 /* if this is a pure oplock break request then don't
9276 if (num_locks
== 0 && num_ulocks
== 0) {
9277 END_PROFILE(SMBlockingX
);
9281 END_PROFILE(SMBlockingX
);
9282 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
9286 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
9288 result
= remove_oplock(fsp
);
9290 result
= downgrade_oplock(fsp
);
9294 DEBUG(0, ("reply_lockingX: error in removing "
9295 "oplock on file %s\n", fsp_str_dbg(fsp
)));
9296 /* Hmmm. Is this panic justified? */
9297 smb_panic("internal tdb error");
9300 /* if this is a pure oplock break request then don't send a
9302 if (num_locks
== 0 && num_ulocks
== 0) {
9303 /* Sanity check - ensure a pure oplock break is not a
9305 if (CVAL(req
->vwv
+0, 0) != 0xff) {
9306 DEBUG(0,("reply_lockingX: Error : pure oplock "
9307 "break is a chained %d request !\n",
9308 (unsigned int)CVAL(req
->vwv
+0, 0)));
9310 END_PROFILE(SMBlockingX
);
9316 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
9317 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9318 END_PROFILE(SMBlockingX
);
9322 if (num_ulocks
!= 0) {
9323 struct smbd_lock_element
*ulocks
= NULL
;
9326 ulocks
= talloc_array(
9327 req
, struct smbd_lock_element
, num_ulocks
);
9328 if (ulocks
== NULL
) {
9329 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9330 END_PROFILE(SMBlockingX
);
9335 * Data now points at the beginning of the list of
9336 * smb_unlkrng structs
9338 for (i
= 0; i
< num_ulocks
; i
++) {
9339 ulocks
[i
].req_guid
= smbd_request_guid(req
,
9341 ulocks
[i
].smblctx
= get_lock_pid(
9342 data
, i
, large_file_format
);
9343 ulocks
[i
].count
= get_lock_count(
9344 data
, i
, large_file_format
);
9345 ulocks
[i
].offset
= get_lock_offset(
9346 data
, i
, large_file_format
);
9347 ulocks
[i
].brltype
= UNLOCK_LOCK
;
9351 * Unlock cancels pending locks
9354 ok
= smbd_smb1_brl_finish_by_lock(
9361 reply_outbuf(req
, 2, 0);
9362 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
9363 SSVAL(req
->outbuf
, smb_vwv1
, 0);
9364 END_PROFILE(SMBlockingX
);
9368 status
= smbd_do_unlocking(
9369 req
, fsp
, num_ulocks
, ulocks
, WINDOWS_LOCK
);
9370 TALLOC_FREE(ulocks
);
9371 if (!NT_STATUS_IS_OK(status
)) {
9372 END_PROFILE(SMBlockingX
);
9373 reply_nterror(req
, status
);
9378 /* Now do any requested locks */
9379 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
9381 /* Data now points at the beginning of the list
9382 of smb_lkrng structs */
9384 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
9385 brltype
= READ_LOCK
;
9387 brltype
= WRITE_LOCK
;
9390 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
9391 if (locks
== NULL
) {
9392 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9393 END_PROFILE(SMBlockingX
);
9397 for (i
= 0; i
< num_locks
; i
++) {
9398 locks
[i
].req_guid
= smbd_request_guid(req
, i
),
9399 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
9400 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
9401 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
9402 locks
[i
].brltype
= brltype
;
9405 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
9409 if (num_locks
== 0) {
9410 /* See smbtorture3 lock11 test */
9411 reply_outbuf(req
, 2, 0);
9412 /* andx chain ends */
9413 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
9414 SSVAL(req
->outbuf
, smb_vwv1
, 0);
9415 END_PROFILE(SMBlockingX
);
9419 ok
= smbd_smb1_brl_finish_by_lock(
9423 locks
[0], /* Windows only cancels the first lock */
9424 NT_STATUS_FILE_LOCK_CONFLICT
);
9427 reply_force_doserror(req
, ERRDOS
, ERRcancelviolation
);
9428 END_PROFILE(SMBlockingX
);
9432 reply_outbuf(req
, 2, 0);
9433 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
9434 SSVAL(req
->outbuf
, smb_vwv1
, 0);
9435 END_PROFILE(SMBlockingX
);
9439 subreq
= smbd_smb1_do_locks_send(
9449 if (subreq
== NULL
) {
9450 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9451 END_PROFILE(SMBlockingX
);
9454 tevent_req_set_callback(subreq
, reply_lockingx_done
, NULL
);
9455 END_PROFILE(SMBlockingX
);
9458 static void reply_lockingx_done(struct tevent_req
*subreq
)
9460 struct smb_request
*req
= NULL
;
9464 START_PROFILE(SMBlockingX
);
9466 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
9469 status
= smbd_smb1_do_locks_recv(subreq
);
9470 TALLOC_FREE(subreq
);
9472 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status
));
9474 if (NT_STATUS_IS_OK(status
)) {
9475 reply_outbuf(req
, 2, 0);
9476 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
9477 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
9479 reply_nterror(req
, status
);
9482 ok
= srv_send_smb(req
->xconn
,
9483 (char *)req
->outbuf
,
9486 IS_CONN_ENCRYPTED(req
->conn
),
9489 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9492 END_PROFILE(SMBlockingX
);
9496 #define DBGC_CLASS DBGC_ALL
9498 /****************************************************************************
9499 Reply to a SMBreadbmpx (read block multiplex) request.
9500 Always reply with an error, if someone has a platform really needs this,
9501 please contact vl@samba.org
9502 ****************************************************************************/
9504 void reply_readbmpx(struct smb_request
*req
)
9506 START_PROFILE(SMBreadBmpx
);
9507 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
9508 END_PROFILE(SMBreadBmpx
);
9512 /****************************************************************************
9513 Reply to a SMBreadbs (read block multiplex secondary) request.
9514 Always reply with an error, if someone has a platform really needs this,
9515 please contact vl@samba.org
9516 ****************************************************************************/
9518 void reply_readbs(struct smb_request
*req
)
9520 START_PROFILE(SMBreadBs
);
9521 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
9522 END_PROFILE(SMBreadBs
);
9526 /****************************************************************************
9527 Reply to a SMBsetattrE.
9528 ****************************************************************************/
9530 void reply_setattrE(struct smb_request
*req
)
9532 connection_struct
*conn
= req
->conn
;
9533 struct smb_file_time ft
;
9537 START_PROFILE(SMBsetattrE
);
9538 init_smb_file_time(&ft
);
9541 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9545 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
9547 if(!fsp
|| (fsp
->conn
!= conn
)) {
9548 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
9553 * Convert the DOS times into unix times.
9556 ft
.atime
= time_t_to_full_timespec(
9557 srv_make_unix_date2(req
->vwv
+3));
9558 ft
.mtime
= time_t_to_full_timespec(
9559 srv_make_unix_date2(req
->vwv
+5));
9560 ft
.create_time
= time_t_to_full_timespec(
9561 srv_make_unix_date2(req
->vwv
+1));
9563 reply_outbuf(req
, 0, 0);
9566 * Patch from Ray Frush <frush@engr.colostate.edu>
9567 * Sometimes times are sent as zero - ignore them.
9570 /* Ensure we have a valid stat struct for the source. */
9571 status
= vfs_stat_fsp(fsp
);
9572 if (!NT_STATUS_IS_OK(status
)) {
9573 reply_nterror(req
, status
);
9577 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
9578 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9582 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
9583 if (!NT_STATUS_IS_OK(status
)) {
9584 reply_nterror(req
, status
);
9588 if (fsp
->fsp_flags
.modified
) {
9589 trigger_write_time_update_immediate(fsp
);
9592 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9595 (unsigned int)ft
.atime
.tv_sec
,
9596 (unsigned int)ft
.mtime
.tv_sec
,
9597 (unsigned int)ft
.create_time
.tv_sec
9600 END_PROFILE(SMBsetattrE
);
9605 /* Back from the dead for OS/2..... JRA. */
9607 /****************************************************************************
9608 Reply to a SMBwritebmpx (write block multiplex primary) request.
9609 Always reply with an error, if someone has a platform really needs this,
9610 please contact vl@samba.org
9611 ****************************************************************************/
9613 void reply_writebmpx(struct smb_request
*req
)
9615 START_PROFILE(SMBwriteBmpx
);
9616 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
9617 END_PROFILE(SMBwriteBmpx
);
9621 /****************************************************************************
9622 Reply to a SMBwritebs (write block multiplex secondary) request.
9623 Always reply with an error, if someone has a platform really needs this,
9624 please contact vl@samba.org
9625 ****************************************************************************/
9627 void reply_writebs(struct smb_request
*req
)
9629 START_PROFILE(SMBwriteBs
);
9630 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
9631 END_PROFILE(SMBwriteBs
);
9635 /****************************************************************************
9636 Reply to a SMBgetattrE.
9637 ****************************************************************************/
9639 void reply_getattrE(struct smb_request
*req
)
9641 connection_struct
*conn
= req
->conn
;
9644 struct timespec create_ts
;
9647 START_PROFILE(SMBgetattrE
);
9650 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9651 END_PROFILE(SMBgetattrE
);
9655 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
9657 if(!fsp
|| (fsp
->conn
!= conn
)) {
9658 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
9659 END_PROFILE(SMBgetattrE
);
9663 /* Do an fstat on this file */
9664 status
= vfs_stat_fsp(fsp
);
9665 if (!NT_STATUS_IS_OK(status
)) {
9666 reply_nterror(req
, status
);
9667 END_PROFILE(SMBgetattrE
);
9671 mode
= dos_mode(conn
, fsp
->fsp_name
);
9674 * Convert the times into dos times. Set create
9675 * date to be last modify date as UNIX doesn't save
9679 reply_outbuf(req
, 11, 0);
9681 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
9682 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
9683 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
9684 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
9685 /* Should we check pending modtime here ? JRA */
9686 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
9687 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
9689 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
9690 SIVAL(req
->outbuf
, smb_vwv6
, 0);
9691 SIVAL(req
->outbuf
, smb_vwv8
, 0);
9693 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
9694 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
9695 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
9697 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
9699 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
9701 END_PROFILE(SMBgetattrE
);