2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
31 #include "locking/share_mode_lock.h"
32 #include "smbd/smbd.h"
33 #include "smbd/globals.h"
34 #include "fake_file.h"
35 #include "rpc_client/rpc_client.h"
36 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
37 #include "rpc_client/cli_spoolss.h"
38 #include "rpc_client/init_spoolss.h"
39 #include "rpc_server/rpc_ncacn_np.h"
40 #include "libcli/security/security.h"
41 #include "libsmb/nmblib.h"
43 #include "smbprofile.h"
44 #include "../lib/tsocket/tsocket.h"
45 #include "lib/util/tevent_ntstatus.h"
46 #include "libcli/smb/smb_signing.h"
47 #include "lib/util/sys_rw_data.h"
48 #include "librpc/gen_ndr/open_files.h"
49 #include "smb1_utils.h"
50 #include "libcli/smb/smb2_posix.h"
51 #include "lib/util/string_wrappers.h"
52 #include "source3/printing/rap_jobid.h"
54 /****************************************************************************
55 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
56 path or anything including wildcards.
57 We're assuming here that '/' is not the second byte in any multibyte char
58 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
60 ****************************************************************************/
62 /* Custom version for processing POSIX paths. */
63 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
65 static NTSTATUS
check_path_syntax_internal(char *path
,
70 NTSTATUS ret
= NT_STATUS_OK
;
71 bool start_of_name_component
= True
;
72 bool stream_started
= false;
73 bool last_component_contains_wcard
= false;
80 return NT_STATUS_OBJECT_NAME_INVALID
;
83 return NT_STATUS_OBJECT_NAME_INVALID
;
85 if (strchr_m(&s
[1], ':')) {
86 return NT_STATUS_OBJECT_NAME_INVALID
;
92 if ((*s
== ':') && !posix_path
&& !stream_started
) {
93 if (last_component_contains_wcard
) {
94 return NT_STATUS_OBJECT_NAME_INVALID
;
96 /* Stream names allow more characters than file names.
97 We're overloading posix_path here to allow a wider
98 range of characters. If stream_started is true this
99 is still a Windows path even if posix_path is true.
102 stream_started
= true;
103 start_of_name_component
= false;
107 return NT_STATUS_OBJECT_NAME_INVALID
;
111 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
113 * Safe to assume is not the second part of a mb char
114 * as this is handled below.
116 /* Eat multiple '/' or '\\' */
117 while (IS_PATH_SEP(*s
,posix_path
)) {
120 if ((d
!= path
) && (*s
!= '\0')) {
121 /* We only care about non-leading or trailing '/' or '\\' */
125 start_of_name_component
= True
;
127 last_component_contains_wcard
= false;
131 if (start_of_name_component
) {
132 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
133 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
136 * No mb char starts with '.' so we're safe checking the directory separator here.
139 /* If we just added a '/' - delete it */
140 if ((d
> path
) && (*(d
-1) == '/')) {
145 /* Are we at the start ? Can't go back further if so. */
147 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
150 /* Go back one level... */
151 /* We know this is safe as '/' cannot be part of a mb sequence. */
152 /* NOTE - if this assumption is invalid we are not in good shape... */
153 /* Decrement d first as d points to the *next* char to write into. */
154 for (d
--; d
> path
; d
--) {
158 s
+= 2; /* Else go past the .. */
159 /* We're still at the start of a name component, just the previous one. */
162 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
174 if (*s
<= 0x1f || *s
== '|') {
175 return NT_STATUS_OBJECT_NAME_INVALID
;
183 last_component_contains_wcard
= true;
192 /* Get the size of the next MB character. */
193 next_codepoint(s
,&siz
);
211 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
213 return NT_STATUS_INVALID_PARAMETER
;
216 start_of_name_component
= False
;
224 /****************************************************************************
225 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
226 No wildcards allowed.
227 ****************************************************************************/
229 NTSTATUS
check_path_syntax(char *path
)
231 return check_path_syntax_internal(path
, false);
234 /****************************************************************************
235 Check the path for a POSIX client.
236 We're assuming here that '/' is not the second byte in any multibyte char
237 set (a safe assumption).
238 ****************************************************************************/
240 NTSTATUS
check_path_syntax_posix(char *path
)
242 return check_path_syntax_internal(path
, true);
245 /****************************************************************************
246 Pull a string and check the path allowing a wildcard - provide for error return.
247 Passes in posix flag.
248 ****************************************************************************/
250 static size_t srvstr_get_path_internal(TALLOC_CTX
*ctx
,
251 const char *base_ptr
,
257 bool posix_pathnames
,
264 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
268 *err
= NT_STATUS_INVALID_PARAMETER
;
272 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
274 * For a DFS path the function parse_dfs_path()
275 * will do the path processing, just make a copy.
281 if (posix_pathnames
) {
282 *err
= check_path_syntax_posix(*pp_dest
);
284 *err
= check_path_syntax(*pp_dest
);
290 /****************************************************************************
291 Pull a string and check the path - provide for error return.
292 ****************************************************************************/
294 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
295 const char *base_ptr
,
303 return srvstr_get_path_internal(ctx
,
314 /****************************************************************************
315 Pull a string and check the path - provide for error return.
316 posix_pathnames version.
317 ****************************************************************************/
319 size_t srvstr_get_path_posix(TALLOC_CTX
*ctx
,
320 const char *base_ptr
,
328 return srvstr_get_path_internal(ctx
,
340 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
341 char **pp_dest
, const char *src
, int flags
,
344 ssize_t bufrem
= smbreq_bufrem(req
, src
);
347 *err
= NT_STATUS_INVALID_PARAMETER
;
351 if (req
->posix_pathnames
) {
352 return srvstr_get_path_internal(mem_ctx
,
353 (const char *)req
->inbuf
,
362 return srvstr_get_path_internal(mem_ctx
,
363 (const char *)req
->inbuf
,
375 * pull a string from the smb_buf part of a packet. In this case the
376 * string can either be null terminated or it can be terminated by the
377 * end of the smbbuf area
379 size_t srvstr_pull_req_talloc(TALLOC_CTX
*ctx
, struct smb_request
*req
,
380 char **dest
, const uint8_t *src
, int flags
)
382 ssize_t bufrem
= smbreq_bufrem(req
, src
);
388 return pull_string_talloc(ctx
, req
->inbuf
, req
->flags2
, dest
, src
,
392 /****************************************************************************
393 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
394 ****************************************************************************/
396 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
399 if ((fsp
== NULL
) || (conn
== NULL
)) {
400 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
403 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
404 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
410 /****************************************************************************
411 Check if we have a correct fsp pointing to a file.
412 ****************************************************************************/
414 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
417 if (!check_fsp_open(conn
, req
, fsp
)) {
420 if (fsp
->fsp_flags
.is_directory
) {
421 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
424 if (fsp_get_pathref_fd(fsp
) == -1) {
425 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
428 fsp
->num_smb_operations
++;
432 /****************************************************************************
433 Check if we have a correct fsp pointing to a quota fake file. Replacement for
434 the CHECK_NTQUOTA_HANDLE_OK macro.
435 ****************************************************************************/
437 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
440 if (!check_fsp_open(conn
, req
, fsp
)) {
444 if (fsp
->fsp_flags
.is_directory
) {
448 if (fsp
->fake_file_handle
== NULL
) {
452 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
456 if (fsp
->fake_file_handle
->private_data
== NULL
) {
463 /****************************************************************************
464 Return the port number we've bound to on a socket.
465 ****************************************************************************/
467 static int get_socket_port(int fd
)
469 struct samba_sockaddr saddr
= {
470 .sa_socklen
= sizeof(struct sockaddr_storage
),
477 if (getsockname(fd
, &saddr
.u
.sa
, &saddr
.sa_socklen
) < 0) {
478 int level
= (errno
== ENOTCONN
) ? 2 : 0;
479 DEBUG(level
, ("getsockname failed. Error was %s\n",
484 #if defined(HAVE_IPV6)
485 if (saddr
.u
.sa
.sa_family
== AF_INET6
) {
486 return ntohs(saddr
.u
.in6
.sin6_port
);
489 if (saddr
.u
.sa
.sa_family
== AF_INET
) {
490 return ntohs(saddr
.u
.in
.sin_port
);
495 static bool netbios_session_retarget(struct smbXsrv_connection
*xconn
,
496 const char *name
, int name_type
)
499 char *trim_name_type
;
500 const char *retarget_parm
;
503 int retarget_type
= 0x20;
504 int retarget_port
= NBT_SMB_PORT
;
505 struct sockaddr_storage retarget_addr
;
506 struct sockaddr_in
*in_addr
;
510 if (get_socket_port(xconn
->transport
.sock
) != NBT_SMB_PORT
) {
514 trim_name
= talloc_strdup(talloc_tos(), name
);
515 if (trim_name
== NULL
) {
518 trim_char(trim_name
, ' ', ' ');
520 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
522 if (trim_name_type
== NULL
) {
526 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
527 trim_name_type
, NULL
);
528 if (retarget_parm
== NULL
) {
529 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
532 if (retarget_parm
== NULL
) {
536 retarget
= talloc_strdup(trim_name
, retarget_parm
);
537 if (retarget
== NULL
) {
541 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
543 p
= strchr(retarget
, ':');
546 retarget_port
= atoi(p
);
549 p
= strchr_m(retarget
, '#');
552 if (sscanf(p
, "%x", &retarget_type
) != 1) {
557 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
559 DEBUG(10, ("could not resolve %s\n", retarget
));
563 if (retarget_addr
.ss_family
!= AF_INET
) {
564 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
568 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
570 _smb_setlen(outbuf
, 6);
571 SCVAL(outbuf
, 0, 0x84);
572 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
573 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
575 if (!srv_send_smb(xconn
, (char *)outbuf
, false, 0, false,
577 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
583 TALLOC_FREE(trim_name
);
587 static void reply_called_name_not_present(char *outbuf
)
589 smb_setlen(outbuf
, 1);
590 SCVAL(outbuf
, 0, 0x83);
591 SCVAL(outbuf
, 4, 0x82);
594 /****************************************************************************
595 Reply to a (netbios-level) special message.
596 ****************************************************************************/
598 void reply_special(struct smbXsrv_connection
*xconn
, char *inbuf
, size_t inbuf_size
)
600 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
601 int msg_type
= CVAL(inbuf
,0);
602 int msg_flags
= CVAL(inbuf
,1);
604 * We only really use 4 bytes of the outbuf, but for the smb_setlen
605 * calculation & friends (srv_send_smb uses that) we need the full smb
608 char outbuf
[smb_size
];
610 memset(outbuf
, '\0', sizeof(outbuf
));
612 smb_setlen(outbuf
,0);
615 case NBSSrequest
: /* session request */
617 /* inbuf_size is guarenteed to be at least 4. */
619 int name_type1
, name_type2
;
620 int name_len1
, name_len2
;
624 if (xconn
->transport
.nbt
.got_session
) {
625 exit_server_cleanly("multiple session request not permitted");
628 SCVAL(outbuf
,0,NBSSpositive
);
631 /* inbuf_size is guaranteed to be at least 4. */
632 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
633 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
634 DEBUG(0,("Invalid name length in session request\n"));
635 reply_called_name_not_present(outbuf
);
638 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
639 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
640 DEBUG(0,("Invalid name length in session request\n"));
641 reply_called_name_not_present(outbuf
);
645 name_type1
= name_extract((unsigned char *)inbuf
,
646 inbuf_size
,(unsigned int)4,name1
);
647 name_type2
= name_extract((unsigned char *)inbuf
,
648 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
650 if (name_type1
== -1 || name_type2
== -1) {
651 DEBUG(0,("Invalid name type in session request\n"));
652 reply_called_name_not_present(outbuf
);
656 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
657 name1
, name_type1
, name2
, name_type2
));
659 if (netbios_session_retarget(xconn
, name1
, name_type1
)) {
660 exit_server_cleanly("retargeted client");
664 * Windows NT/2k uses "*SMBSERVER" and XP uses
665 * "*SMBSERV" arrggg!!!
667 if (strequal(name1
, "*SMBSERVER ")
668 || strequal(name1
, "*SMBSERV ")) {
671 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
674 exit_server_cleanly("could not allocate raddr");
677 fstrcpy(name1
, raddr
);
680 set_local_machine_name(name1
, True
);
681 set_remote_machine_name(name2
, True
);
683 if (is_ipaddress(sconn
->remote_hostname
)) {
684 char *p
= discard_const_p(char, sconn
->remote_hostname
);
688 sconn
->remote_hostname
= talloc_strdup(sconn
,
689 get_remote_machine_name());
690 if (sconn
->remote_hostname
== NULL
) {
691 exit_server_cleanly("could not copy remote name");
693 xconn
->remote_hostname
= sconn
->remote_hostname
;
696 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
697 get_local_machine_name(), get_remote_machine_name(),
700 if (name_type2
== 'R') {
701 /* We are being asked for a pathworks session ---
703 reply_called_name_not_present(outbuf
);
707 reload_services(sconn
, conn_snum_used
, true);
710 xconn
->transport
.nbt
.got_session
= true;
714 case 0x89: /* session keepalive request
715 (some old clients produce this?) */
716 SCVAL(outbuf
,0,NBSSkeepalive
);
720 case NBSSpositive
: /* positive session response */
721 case NBSSnegative
: /* negative session response */
722 case NBSSretarget
: /* retarget session response */
723 DEBUG(0,("Unexpected session response\n"));
726 case NBSSkeepalive
: /* session keepalive */
731 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
732 msg_type
, msg_flags
));
734 if (!srv_send_smb(xconn
, outbuf
, false, 0, false, NULL
)) {
735 exit_server_cleanly("reply_special: srv_send_smb failed.");
738 if (CVAL(outbuf
, 0) != 0x82) {
739 exit_server_cleanly("invalid netbios session");
744 /****************************************************************************
746 conn POINTER CAN BE NULL HERE !
747 ****************************************************************************/
749 void reply_tcon(struct smb_request
*req
)
751 connection_struct
*conn
= req
->conn
;
753 char *service_buf
= NULL
;
754 char *password
= NULL
;
760 TALLOC_CTX
*ctx
= talloc_tos();
761 struct smbXsrv_connection
*xconn
= req
->xconn
;
762 NTTIME now
= timeval_to_nttime(&req
->request_time
);
764 START_PROFILE(SMBtcon
);
766 if (req
->buflen
< 4) {
767 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
768 END_PROFILE(SMBtcon
);
773 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
775 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
777 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
780 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
781 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
782 END_PROFILE(SMBtcon
);
785 p2
= strrchr_m(service_buf
,'\\');
789 service
= service_buf
;
792 conn
= make_connection(req
, now
, service
, dev
,
793 req
->vuid
,&nt_status
);
797 reply_nterror(req
, nt_status
);
798 END_PROFILE(SMBtcon
);
802 reply_outbuf(req
, 2, 0);
803 SSVAL(req
->outbuf
,smb_vwv0
,xconn
->smb1
.negprot
.max_recv
);
804 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
805 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
807 DEBUG(3,("tcon service=%s cnum=%d\n",
808 service
, conn
->cnum
));
810 END_PROFILE(SMBtcon
);
814 /****************************************************************************
815 Reply to a tcon and X.
816 conn POINTER CAN BE NULL HERE !
817 ****************************************************************************/
819 void reply_tcon_and_X(struct smb_request
*req
)
821 const struct loadparm_substitution
*lp_sub
=
822 loadparm_s3_global_substitution();
823 connection_struct
*conn
= req
->conn
;
824 const char *service
= NULL
;
825 TALLOC_CTX
*ctx
= talloc_tos();
826 /* what the client thinks the device is */
827 char *client_devicetype
= NULL
;
828 /* what the server tells the client the share represents */
829 const char *server_devicetype
;
836 struct smbXsrv_session
*session
= NULL
;
837 NTTIME now
= timeval_to_nttime(&req
->request_time
);
838 bool session_key_updated
= false;
839 uint16_t optional_support
= 0;
840 struct smbXsrv_connection
*xconn
= req
->xconn
;
842 START_PROFILE(SMBtconX
);
845 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
846 END_PROFILE(SMBtconX
);
850 passlen
= SVAL(req
->vwv
+3, 0);
851 tcon_flags
= SVAL(req
->vwv
+2, 0);
853 /* we might have to close an old one */
854 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
855 struct smbXsrv_tcon
*tcon
;
863 * TODO: cancel all outstanding requests on the tcon
865 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
866 if (!NT_STATUS_IS_OK(status
)) {
867 DEBUG(0, ("reply_tcon_and_X: "
868 "smbXsrv_tcon_disconnect() failed: %s\n",
871 * If we hit this case, there is something completely
872 * wrong, so we better disconnect the transport connection.
874 END_PROFILE(SMBtconX
);
875 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
881 * This tree id is gone. Make sure we can't re-use it
887 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
888 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
889 END_PROFILE(SMBtconX
);
893 if (xconn
->smb1
.negprot
.encrypted_passwords
) {
894 p
= req
->buf
+ passlen
;
896 p
= req
->buf
+ passlen
+ 1;
899 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
902 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
903 END_PROFILE(SMBtconX
);
908 * the service name can be either: \\server\share
909 * or share directly like on the DELL PowerVault 705
912 q
= strchr_m(path
+2,'\\');
914 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
915 END_PROFILE(SMBtconX
);
923 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
924 &client_devicetype
, p
,
925 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
927 if (client_devicetype
== NULL
) {
928 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
929 END_PROFILE(SMBtconX
);
933 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
935 nt_status
= smb1srv_session_lookup(xconn
,
936 req
->vuid
, now
, &session
);
937 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
938 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
939 END_PROFILE(SMBtconX
);
942 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
943 reply_nterror(req
, nt_status
);
944 END_PROFILE(SMBtconX
);
947 if (!NT_STATUS_IS_OK(nt_status
)) {
948 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
949 END_PROFILE(SMBtconX
);
953 if (session
->global
->auth_session_info
== NULL
) {
954 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
955 END_PROFILE(SMBtconX
);
960 * If there is no application key defined yet
963 * This means we setup the application key on the
964 * first tcon that happens via the given session.
966 * Once the application key is defined, it does not
969 if (session
->global
->application_key_blob
.length
== 0 &&
970 smb2_signing_key_valid(session
->global
->signing_key
))
972 struct smbXsrv_session
*x
= session
;
973 struct auth_session_info
*session_info
=
974 session
->global
->auth_session_info
;
975 uint8_t session_key
[16];
977 ZERO_STRUCT(session_key
);
978 memcpy(session_key
, x
->global
->signing_key
->blob
.data
,
979 MIN(x
->global
->signing_key
->blob
.length
, sizeof(session_key
)));
982 * The application key is truncated/padded to 16 bytes
984 x
->global
->application_key_blob
= data_blob_talloc(x
->global
,
986 sizeof(session_key
));
987 ZERO_STRUCT(session_key
);
988 if (x
->global
->application_key_blob
.data
== NULL
) {
989 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
990 END_PROFILE(SMBtconX
);
993 talloc_keep_secret(x
->global
->application_key_blob
.data
);
995 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
998 status
= smb_key_derivation(x
->global
->application_key_blob
.data
,
999 x
->global
->application_key_blob
.length
,
1000 x
->global
->application_key_blob
.data
);
1001 if (!NT_STATUS_IS_OK(status
)) {
1002 DBG_ERR("smb_key_derivation failed: %s\n",
1004 END_PROFILE(SMBtconX
);
1007 optional_support
|= SMB_EXTENDED_SIGNATURES
;
1011 * Place the application key into the session_info
1013 data_blob_clear_free(&session_info
->session_key
);
1014 session_info
->session_key
= data_blob_dup_talloc(session_info
,
1015 x
->global
->application_key_blob
);
1016 if (session_info
->session_key
.data
== NULL
) {
1017 data_blob_clear_free(&x
->global
->application_key_blob
);
1018 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1019 END_PROFILE(SMBtconX
);
1022 talloc_keep_secret(session_info
->session_key
.data
);
1023 session_key_updated
= true;
1026 conn
= make_connection(req
, now
, service
, client_devicetype
,
1027 req
->vuid
, &nt_status
);
1031 if (session_key_updated
) {
1032 struct smbXsrv_session
*x
= session
;
1033 struct auth_session_info
*session_info
=
1034 session
->global
->auth_session_info
;
1035 data_blob_clear_free(&x
->global
->application_key_blob
);
1036 data_blob_clear_free(&session_info
->session_key
);
1038 reply_nterror(req
, nt_status
);
1039 END_PROFILE(SMBtconX
);
1044 server_devicetype
= "IPC";
1045 else if ( IS_PRINT(conn
) )
1046 server_devicetype
= "LPT1:";
1048 server_devicetype
= "A:";
1050 if (get_Protocol() < PROTOCOL_NT1
) {
1051 reply_outbuf(req
, 2, 0);
1052 if (message_push_string(&req
->outbuf
, server_devicetype
,
1053 STR_TERMINATE
|STR_ASCII
) == -1) {
1054 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1055 END_PROFILE(SMBtconX
);
1059 /* NT sets the fstype of IPC$ to the null string */
1060 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
1062 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
1063 /* Return permissions. */
1067 reply_outbuf(req
, 7, 0);
1070 perm1
= FILE_ALL_ACCESS
;
1071 perm2
= FILE_ALL_ACCESS
;
1073 perm1
= conn
->share_access
;
1076 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
1077 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
1079 reply_outbuf(req
, 3, 0);
1082 if ((message_push_string(&req
->outbuf
, server_devicetype
,
1083 STR_TERMINATE
|STR_ASCII
) == -1)
1084 || (message_push_string(&req
->outbuf
, fstype
,
1085 STR_TERMINATE
) == -1)) {
1086 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1087 END_PROFILE(SMBtconX
);
1091 /* what does setting this bit do? It is set by NT4 and
1092 may affect the ability to autorun mounted cdroms */
1093 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1095 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1097 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1098 DEBUG(2,("Serving %s as a Dfs root\n",
1099 lp_servicename(ctx
, lp_sub
, SNUM(conn
)) ));
1100 optional_support
|= SMB_SHARE_IN_DFS
;
1103 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1106 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1107 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1109 DEBUG(3,("tconX service=%s \n",
1112 /* set the incoming and outgoing tid to the just created one */
1113 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1114 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1116 END_PROFILE(SMBtconX
);
1118 req
->tid
= conn
->cnum
;
1121 /****************************************************************************
1122 Reply to an unknown type.
1123 ****************************************************************************/
1125 void reply_unknown_new(struct smb_request
*req
, uint8_t type
)
1127 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1128 smb_fn_name(type
), type
, type
));
1129 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1133 /****************************************************************************
1135 conn POINTER CAN BE NULL HERE !
1136 ****************************************************************************/
1138 void reply_ioctl(struct smb_request
*req
)
1140 const struct loadparm_substitution
*lp_sub
=
1141 loadparm_s3_global_substitution();
1142 connection_struct
*conn
= req
->conn
;
1145 uint32_t ioctl_code
;
1149 START_PROFILE(SMBioctl
);
1152 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1153 END_PROFILE(SMBioctl
);
1157 device
= SVAL(req
->vwv
+1, 0);
1158 function
= SVAL(req
->vwv
+2, 0);
1159 ioctl_code
= (device
<< 16) + function
;
1161 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1163 switch (ioctl_code
) {
1164 case IOCTL_QUERY_JOB_INFO
:
1168 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1169 END_PROFILE(SMBioctl
);
1173 reply_outbuf(req
, 8, replysize
+1);
1174 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1175 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1176 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1177 p
= smb_buf(req
->outbuf
);
1178 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1179 p
+= 1; /* Allow for alignment */
1181 switch (ioctl_code
) {
1182 case IOCTL_QUERY_JOB_INFO
:
1186 files_struct
*fsp
= file_fsp(
1187 req
, SVAL(req
->vwv
+0, 0));
1189 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1190 END_PROFILE(SMBioctl
);
1194 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1196 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1197 lp_netbios_name(), 15,
1198 STR_TERMINATE
|STR_ASCII
, &len
);
1199 if (!NT_STATUS_IS_OK(status
)) {
1200 reply_nterror(req
, status
);
1201 END_PROFILE(SMBioctl
);
1205 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
,
1207 lp_servicename(talloc_tos(),
1210 13, STR_TERMINATE
|STR_ASCII
, &len
);
1211 if (!NT_STATUS_IS_OK(status
)) {
1212 reply_nterror(req
, status
);
1213 END_PROFILE(SMBioctl
);
1217 memset(p
+18, 0, 13);
1223 END_PROFILE(SMBioctl
);
1227 /****************************************************************************
1228 Strange checkpath NTSTATUS mapping.
1229 ****************************************************************************/
1231 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1233 /* Strange DOS error code semantics only for checkpath... */
1234 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1235 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1236 /* We need to map to ERRbadpath */
1237 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1243 /****************************************************************************
1244 Reply to a checkpath.
1245 ****************************************************************************/
1247 void reply_checkpath(struct smb_request
*req
)
1249 connection_struct
*conn
= req
->conn
;
1250 struct smb_filename
*smb_fname
= NULL
;
1253 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1254 TALLOC_CTX
*ctx
= talloc_tos();
1256 START_PROFILE(SMBcheckpath
);
1258 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1259 STR_TERMINATE
, &status
);
1261 if (!NT_STATUS_IS_OK(status
)) {
1262 status
= map_checkpath_error(req
->flags2
, status
);
1263 reply_nterror(req
, status
);
1264 END_PROFILE(SMBcheckpath
);
1268 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1270 status
= filename_convert(ctx
,
1277 if (!NT_STATUS_IS_OK(status
)) {
1278 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1279 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1280 ERRSRV
, ERRbadpath
);
1281 END_PROFILE(SMBcheckpath
);
1287 if (!VALID_STAT(smb_fname
->st
) &&
1288 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1289 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1290 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1291 status
= map_nt_error_from_unix(errno
);
1295 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1296 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1297 ERRDOS
, ERRbadpath
);
1301 reply_outbuf(req
, 0, 0);
1304 /* We special case this - as when a Windows machine
1305 is parsing a path is steps through the components
1306 one at a time - if a component fails it expects
1307 ERRbadpath, not ERRbadfile.
1309 status
= map_checkpath_error(req
->flags2
, status
);
1310 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1312 * Windows returns different error codes if
1313 * the parent directory is valid but not the
1314 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1315 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1316 * if the path is invalid.
1318 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1319 ERRDOS
, ERRbadpath
);
1323 reply_nterror(req
, status
);
1326 TALLOC_FREE(smb_fname
);
1327 END_PROFILE(SMBcheckpath
);
1331 /****************************************************************************
1333 ****************************************************************************/
1335 void reply_getatr(struct smb_request
*req
)
1337 connection_struct
*conn
= req
->conn
;
1338 struct smb_filename
*smb_fname
= NULL
;
1345 TALLOC_CTX
*ctx
= talloc_tos();
1346 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
1348 START_PROFILE(SMBgetatr
);
1350 p
= (const char *)req
->buf
+ 1;
1351 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1352 if (!NT_STATUS_IS_OK(status
)) {
1353 reply_nterror(req
, status
);
1357 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1358 under WfWg - weird! */
1359 if (*fname
== '\0') {
1360 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1361 if (!CAN_WRITE(conn
)) {
1362 mode
|= FILE_ATTRIBUTE_READONLY
;
1367 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1368 status
= filename_convert(ctx
,
1374 if (!NT_STATUS_IS_OK(status
)) {
1375 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1376 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1377 ERRSRV
, ERRbadpath
);
1380 reply_nterror(req
, status
);
1383 if (!VALID_STAT(smb_fname
->st
) &&
1384 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1385 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1386 smb_fname_str_dbg(smb_fname
),
1388 reply_nterror(req
, map_nt_error_from_unix(errno
));
1392 mode
= fdos_mode(smb_fname
->fsp
);
1393 size
= smb_fname
->st
.st_ex_size
;
1395 if (ask_sharemode
) {
1396 struct timespec write_time_ts
;
1397 struct file_id fileid
;
1399 ZERO_STRUCT(write_time_ts
);
1400 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1401 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1402 if (!is_omit_timespec(&write_time_ts
)) {
1403 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1407 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1408 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1413 reply_outbuf(req
, 10, 0);
1415 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1416 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1417 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1419 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1421 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
1423 if (get_Protocol() >= PROTOCOL_NT1
) {
1424 SSVAL(req
->outbuf
, smb_flg2
,
1425 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1428 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1429 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1432 TALLOC_FREE(smb_fname
);
1434 END_PROFILE(SMBgetatr
);
1438 /****************************************************************************
1440 ****************************************************************************/
1442 void reply_setatr(struct smb_request
*req
)
1444 struct smb_file_time ft
;
1445 connection_struct
*conn
= req
->conn
;
1446 struct smb_filename
*smb_fname
= NULL
;
1452 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1453 TALLOC_CTX
*ctx
= talloc_tos();
1455 START_PROFILE(SMBsetatr
);
1456 init_smb_file_time(&ft
);
1459 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1463 p
= (const char *)req
->buf
+ 1;
1464 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1465 if (!NT_STATUS_IS_OK(status
)) {
1466 reply_nterror(req
, status
);
1470 status
= filename_convert(ctx
,
1476 if (!NT_STATUS_IS_OK(status
)) {
1477 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1478 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1479 ERRSRV
, ERRbadpath
);
1482 reply_nterror(req
, status
);
1486 if (ISDOT(smb_fname
->base_name
)) {
1488 * Not sure here is the right place to catch this
1489 * condition. Might be moved to somewhere else later -- vl
1491 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1495 if (smb_fname
->fsp
== NULL
) {
1496 /* Can't set access rights on a symlink. */
1497 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1501 mode
= SVAL(req
->vwv
+0, 0);
1502 mtime
= srv_make_unix_date3(req
->vwv
+1);
1504 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1505 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1506 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1508 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1510 status
= smbd_check_access_rights_fsp(conn
->cwd_fsp
,
1513 FILE_WRITE_ATTRIBUTES
);
1514 if (!NT_STATUS_IS_OK(status
)) {
1515 reply_nterror(req
, status
);
1519 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1521 reply_nterror(req
, map_nt_error_from_unix(errno
));
1526 ft
.mtime
= time_t_to_full_timespec(mtime
);
1528 status
= smb_set_file_time(conn
, smb_fname
->fsp
, smb_fname
, &ft
, true);
1529 if (!NT_STATUS_IS_OK(status
)) {
1530 reply_nterror(req
, status
);
1534 reply_outbuf(req
, 0, 0);
1536 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1539 TALLOC_FREE(smb_fname
);
1540 END_PROFILE(SMBsetatr
);
1544 /****************************************************************************
1546 ****************************************************************************/
1548 void reply_dskattr(struct smb_request
*req
)
1550 connection_struct
*conn
= req
->conn
;
1552 uint64_t dfree
,dsize
,bsize
;
1553 struct smb_filename smb_fname
;
1554 START_PROFILE(SMBdskattr
);
1556 ZERO_STRUCT(smb_fname
);
1557 smb_fname
.base_name
= discard_const_p(char, ".");
1559 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
1560 reply_nterror(req
, map_nt_error_from_unix(errno
));
1561 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
1562 END_PROFILE(SMBdskattr
);
1566 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
1567 if (ret
== (uint64_t)-1) {
1568 reply_nterror(req
, map_nt_error_from_unix(errno
));
1569 END_PROFILE(SMBdskattr
);
1574 * Force max to fit in 16 bit fields.
1576 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1580 if (bsize
> (WORDMAX
*512)) {
1581 bsize
= (WORDMAX
*512);
1582 if (dsize
> WORDMAX
)
1584 if (dfree
> WORDMAX
)
1590 reply_outbuf(req
, 5, 0);
1592 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1593 double total_space
, free_space
;
1594 /* we need to scale this to a number that DOS6 can handle. We
1595 use floating point so we can handle large drives on systems
1596 that don't have 64 bit integers
1598 we end up displaying a maximum of 2G to DOS systems
1600 total_space
= dsize
* (double)bsize
;
1601 free_space
= dfree
* (double)bsize
;
1603 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1604 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1606 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1607 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1609 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1610 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1611 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1612 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1614 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1615 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1616 SSVAL(req
->outbuf
,smb_vwv2
,512);
1617 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1620 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1622 END_PROFILE(SMBdskattr
);
1627 * Utility function to split the filename from the directory.
1629 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1630 char **fname_dir_out
,
1631 char **fname_mask_out
)
1633 const char *p
= NULL
;
1634 char *fname_dir
= NULL
;
1635 char *fname_mask
= NULL
;
1637 p
= strrchr_m(fname_in
, '/');
1639 fname_dir
= talloc_strdup(ctx
, ".");
1640 fname_mask
= talloc_strdup(ctx
, fname_in
);
1642 fname_dir
= talloc_strndup(ctx
, fname_in
,
1643 PTR_DIFF(p
, fname_in
));
1644 fname_mask
= talloc_strdup(ctx
, p
+1);
1647 if (!fname_dir
|| !fname_mask
) {
1648 TALLOC_FREE(fname_dir
);
1649 TALLOC_FREE(fname_mask
);
1650 return NT_STATUS_NO_MEMORY
;
1653 *fname_dir_out
= fname_dir
;
1654 *fname_mask_out
= fname_mask
;
1655 return NT_STATUS_OK
;
1658 /****************************************************************************
1660 ****************************************************************************/
1662 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1672 char *mask2
= talloc_strdup(ctx
, mask
);
1678 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1682 memset(buf
+1,' ',11);
1683 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1685 push_ascii(buf
+1,mask2
,8, 0);
1686 push_ascii(buf
+9,p
+1,3, 0);
1689 push_ascii(buf
+1,mask2
,11, 0);
1692 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1694 srv_put_dos_date(buf
,22,date
);
1695 SSVAL(buf
,26,size
& 0xFFFF);
1696 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1697 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1698 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1699 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1700 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1704 /****************************************************************************
1706 Can be called from SMBsearch, SMBffirst or SMBfunique.
1707 ****************************************************************************/
1709 void reply_search(struct smb_request
*req
)
1711 connection_struct
*conn
= req
->conn
;
1714 char *directory
= NULL
;
1715 struct smb_filename
*smb_fname
= NULL
;
1719 struct timespec date
;
1721 unsigned int numentries
= 0;
1722 unsigned int maxentries
= 0;
1723 bool finished
= False
;
1728 bool check_descend
= False
;
1729 bool expect_close
= False
;
1731 bool mask_contains_wcard
= False
;
1732 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1733 TALLOC_CTX
*ctx
= talloc_tos();
1734 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
1735 struct smbXsrv_connection
*xconn
= req
->xconn
;
1736 struct smbd_server_connection
*sconn
= req
->sconn
;
1737 files_struct
*fsp
= NULL
;
1738 const struct loadparm_substitution
*lp_sub
=
1739 loadparm_s3_global_substitution();
1741 START_PROFILE(SMBsearch
);
1744 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1748 if (req
->posix_pathnames
) {
1749 reply_unknown_new(req
, req
->cmd
);
1753 /* If we were called as SMBffirst then we must expect close. */
1754 if(req
->cmd
== SMBffirst
) {
1755 expect_close
= True
;
1758 reply_outbuf(req
, 1, 3);
1759 maxentries
= SVAL(req
->vwv
+0, 0);
1760 dirtype
= SVAL(req
->vwv
+1, 0);
1761 p
= (const char *)req
->buf
+ 1;
1762 p
+= srvstr_get_path_req(ctx
, req
, &path
, p
, STR_TERMINATE
,
1764 if (!NT_STATUS_IS_OK(nt_status
)) {
1765 reply_nterror(req
, nt_status
);
1769 if (smbreq_bufrem(req
, p
) < 3) {
1770 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1775 status_len
= SVAL(p
, 0);
1778 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1780 if (status_len
== 0) {
1782 struct smb_filename
*smb_dname
= NULL
;
1783 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
1784 ucf_flags_from_smb_request(req
);
1785 nt_status
= filename_convert(ctx
, conn
,
1790 if (!NT_STATUS_IS_OK(nt_status
)) {
1791 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1792 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1793 ERRSRV
, ERRbadpath
);
1796 reply_nterror(req
, nt_status
);
1800 directory
= smb_fname
->base_name
;
1802 p
= strrchr_m(directory
,'/');
1803 if ((p
!= NULL
) && (*directory
!= '/')) {
1804 mask
= talloc_strdup(ctx
, p
+ 1);
1805 directory
= talloc_strndup(ctx
, directory
,
1806 PTR_DIFF(p
, directory
));
1808 mask
= talloc_strdup(ctx
, directory
);
1809 directory
= talloc_strdup(ctx
,".");
1813 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1817 memset((char *)status
,'\0',21);
1818 SCVAL(status
,0,(dirtype
& 0x1F));
1820 smb_dname
= synthetic_smb_fname(talloc_tos(),
1826 if (smb_dname
== NULL
) {
1827 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1832 * As we've cut off the last component from
1833 * smb_fname we need to re-stat smb_dname
1834 * so FILE_OPEN disposition knows the directory
1837 ret
= vfs_stat(conn
, smb_dname
);
1839 nt_status
= map_nt_error_from_unix(errno
);
1840 reply_nterror(req
, nt_status
);
1844 nt_status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_dname
);
1845 if (!NT_STATUS_IS_OK(nt_status
)) {
1846 reply_nterror(req
, nt_status
);
1851 * Open an fsp on this directory for the dptr.
1853 nt_status
= SMB_VFS_CREATE_FILE(
1856 smb_dname
, /* dname */
1857 FILE_LIST_DIRECTORY
, /* access_mask */
1859 FILE_SHARE_WRITE
, /* share_access */
1860 FILE_OPEN
, /* create_disposition*/
1861 FILE_DIRECTORY_FILE
, /* create_options */
1862 FILE_ATTRIBUTE_DIRECTORY
,/* file_attributes */
1863 NO_OPLOCK
, /* oplock_request */
1865 0, /* allocation_size */
1866 0, /* private_flags */
1871 NULL
, /* in_context */
1872 NULL
);/* out_context */
1874 if (!NT_STATUS_IS_OK(nt_status
)) {
1875 DBG_ERR("failed to open directory %s\n",
1876 smb_fname_str_dbg(smb_dname
));
1877 reply_nterror(req
, nt_status
);
1881 nt_status
= dptr_create(conn
,
1891 TALLOC_FREE(smb_dname
);
1893 if (!NT_STATUS_IS_OK(nt_status
)) {
1895 * Use NULL here for the first parameter (req)
1896 * as this is not a client visible handle so
1897 * can'tbe part of an SMB1 chain.
1899 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1901 reply_nterror(req
, nt_status
);
1905 dptr_num
= dptr_dnum(fsp
->dptr
);
1909 const char *dirpath
;
1911 if (smbreq_bufrem(req
, p
) < 21) {
1912 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1916 memcpy(status
,p
,21);
1917 status_dirtype
= CVAL(status
,0) & 0x1F;
1918 if (status_dirtype
!= (dirtype
& 0x1F)) {
1919 dirtype
= status_dirtype
;
1922 fsp
= dptr_fetch_fsp(sconn
, status
+12,&dptr_num
);
1926 dirpath
= dptr_path(sconn
, dptr_num
);
1927 directory
= talloc_strdup(ctx
, dirpath
);
1929 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1933 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1937 dirtype
= dptr_attr(sconn
, dptr_num
);
1940 mask_contains_wcard
= dptr_has_wild(fsp
->dptr
);
1942 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1944 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1945 char buf
[DIR_STRUCT_SIZE
];
1946 memcpy(buf
,status
,21);
1947 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1948 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1949 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1952 dptr_fill(sconn
, buf
+12,dptr_num
);
1953 if (dptr_zero(buf
+12) && (status_len
==0)) {
1958 if (message_push_blob(&req
->outbuf
,
1959 data_blob_const(buf
, sizeof(buf
)))
1961 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1966 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1967 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1969 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1971 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1972 directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
))));
1973 if (in_list(directory
, lp_dont_descend(ctx
, lp_sub
, SNUM(conn
)),True
)) {
1974 check_descend
= True
;
1977 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1978 finished
= !get_dir_entry(ctx
,
1989 char buf
[DIR_STRUCT_SIZE
];
1990 memcpy(buf
,status
,21);
1991 if (!make_dir_struct(ctx
,
1997 convert_timespec_to_time_t(date
),
1998 !allow_long_path_components
)) {
1999 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2002 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
2005 if (message_push_blob(&req
->outbuf
,
2006 data_blob_const(buf
, sizeof(buf
)))
2008 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2018 /* If we were called as SMBffirst with smb_search_id == NULL
2019 and no entries were found then return error and close fsp->dptr
2022 if (numentries
== 0) {
2025 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2028 } else if(expect_close
&& status_len
== 0) {
2029 /* Close the dptr - we know it's gone */
2032 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2037 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2038 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
2040 /* fsp may have been closed above. */
2042 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2047 if ((numentries
== 0) && !mask_contains_wcard
) {
2048 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
2052 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
2053 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
2054 SCVAL(smb_buf(req
->outbuf
),0,5);
2055 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
2057 /* The replies here are never long name. */
2058 SSVAL(req
->outbuf
, smb_flg2
,
2059 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
2060 if (!allow_long_path_components
) {
2061 SSVAL(req
->outbuf
, smb_flg2
,
2062 SVAL(req
->outbuf
, smb_flg2
)
2063 & (~FLAGS2_LONG_PATH_COMPONENTS
));
2066 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2067 SSVAL(req
->outbuf
, smb_flg2
,
2068 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
2070 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2071 smb_fn_name(req
->cmd
),
2078 TALLOC_FREE(directory
);
2080 TALLOC_FREE(smb_fname
);
2081 END_PROFILE(SMBsearch
);
2085 /****************************************************************************
2086 Reply to a fclose (stop directory search).
2087 ****************************************************************************/
2089 void reply_fclose(struct smb_request
*req
)
2097 TALLOC_CTX
*ctx
= talloc_tos();
2098 struct smbd_server_connection
*sconn
= req
->sconn
;
2099 files_struct
*fsp
= NULL
;
2101 START_PROFILE(SMBfclose
);
2103 if (req
->posix_pathnames
) {
2104 reply_unknown_new(req
, req
->cmd
);
2105 END_PROFILE(SMBfclose
);
2109 p
= (const char *)req
->buf
+ 1;
2110 p
+= srvstr_get_path_req(ctx
, req
, &path
, p
, STR_TERMINATE
,
2112 if (!NT_STATUS_IS_OK(err
)) {
2113 reply_nterror(req
, err
);
2114 END_PROFILE(SMBfclose
);
2118 if (smbreq_bufrem(req
, p
) < 3) {
2119 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2120 END_PROFILE(SMBfclose
);
2125 status_len
= SVAL(p
,0);
2128 if (status_len
== 0) {
2129 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
2130 END_PROFILE(SMBfclose
);
2134 if (smbreq_bufrem(req
, p
) < 21) {
2135 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2136 END_PROFILE(SMBfclose
);
2140 memcpy(status
,p
,21);
2142 fsp
= dptr_fetch_fsp(sconn
, status
+12,&dptr_num
);
2144 /* Close the file - we know it's gone */
2145 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2150 reply_outbuf(req
, 1, 0);
2151 SSVAL(req
->outbuf
,smb_vwv0
,0);
2153 DEBUG(3,("search close\n"));
2155 END_PROFILE(SMBfclose
);
2159 /****************************************************************************
2161 ****************************************************************************/
2163 void reply_open(struct smb_request
*req
)
2165 connection_struct
*conn
= req
->conn
;
2166 struct smb_filename
*smb_fname
= NULL
;
2176 uint32_t access_mask
;
2177 uint32_t share_mode
;
2178 uint32_t create_disposition
;
2179 uint32_t create_options
= 0;
2180 uint32_t private_flags
= 0;
2183 TALLOC_CTX
*ctx
= talloc_tos();
2185 START_PROFILE(SMBopen
);
2188 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2192 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2193 deny_mode
= SVAL(req
->vwv
+0, 0);
2194 dos_attr
= SVAL(req
->vwv
+1, 0);
2196 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2197 STR_TERMINATE
, &status
);
2198 if (!NT_STATUS_IS_OK(status
)) {
2199 reply_nterror(req
, status
);
2203 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2204 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
2205 &share_mode
, &create_disposition
,
2206 &create_options
, &private_flags
)) {
2207 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2211 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2213 status
= filename_convert(ctx
,
2219 if (!NT_STATUS_IS_OK(status
)) {
2220 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2221 reply_botherror(req
,
2222 NT_STATUS_PATH_NOT_COVERED
,
2223 ERRSRV
, ERRbadpath
);
2226 reply_nterror(req
, status
);
2230 status
= SMB_VFS_CREATE_FILE(
2233 smb_fname
, /* fname */
2234 access_mask
, /* access_mask */
2235 share_mode
, /* share_access */
2236 create_disposition
, /* create_disposition*/
2237 create_options
, /* create_options */
2238 dos_attr
, /* file_attributes */
2239 oplock_request
, /* oplock_request */
2241 0, /* allocation_size */
2247 NULL
, NULL
); /* create context */
2249 if (!NT_STATUS_IS_OK(status
)) {
2250 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2251 /* We have re-scheduled this call. */
2255 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2256 reply_openerror(req
, status
);
2260 fsp
= fcb_or_dos_open(
2267 bool ok
= defer_smb1_sharing_violation(req
);
2271 reply_openerror(req
, status
);
2276 /* Ensure we're pointing at the correct stat struct. */
2277 TALLOC_FREE(smb_fname
);
2278 smb_fname
= fsp
->fsp_name
;
2280 size
= smb_fname
->st
.st_ex_size
;
2281 fattr
= fdos_mode(fsp
);
2283 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2285 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2286 DEBUG(3,("attempt to open a directory %s\n",
2288 close_file(req
, fsp
, ERROR_CLOSE
);
2289 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2290 ERRDOS
, ERRnoaccess
);
2294 reply_outbuf(req
, 7, 0);
2295 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2296 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2297 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2298 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2300 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2302 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2303 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2305 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2306 SCVAL(req
->outbuf
,smb_flg
,
2307 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2310 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2311 SCVAL(req
->outbuf
,smb_flg
,
2312 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2315 END_PROFILE(SMBopen
);
2319 /****************************************************************************
2320 Reply to an open and X.
2321 ****************************************************************************/
2323 void reply_open_and_X(struct smb_request
*req
)
2325 connection_struct
*conn
= req
->conn
;
2326 struct smb_filename
*smb_fname
= NULL
;
2328 uint16_t open_flags
;
2331 /* Breakout the oplock request bits so we can set the
2332 reply bits separately. */
2333 int ex_oplock_request
;
2334 int core_oplock_request
;
2337 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2338 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2346 uint64_t allocation_size
;
2347 ssize_t retval
= -1;
2348 uint32_t access_mask
;
2349 uint32_t share_mode
;
2350 uint32_t create_disposition
;
2351 uint32_t create_options
= 0;
2352 uint32_t private_flags
= 0;
2354 TALLOC_CTX
*ctx
= talloc_tos();
2356 START_PROFILE(SMBopenX
);
2358 if (req
->wct
< 15) {
2359 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2363 open_flags
= SVAL(req
->vwv
+2, 0);
2364 deny_mode
= SVAL(req
->vwv
+3, 0);
2365 smb_attr
= SVAL(req
->vwv
+5, 0);
2366 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2367 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2368 oplock_request
= ex_oplock_request
| core_oplock_request
;
2369 smb_ofun
= SVAL(req
->vwv
+8, 0);
2370 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2372 /* If it's an IPC, pass off the pipe handler. */
2374 if (lp_nt_pipe_support()) {
2375 reply_open_pipe_and_X(conn
, req
);
2377 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2382 /* XXXX we need to handle passed times, sattr and flags */
2383 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2384 STR_TERMINATE
, &status
);
2385 if (!NT_STATUS_IS_OK(status
)) {
2386 reply_nterror(req
, status
);
2390 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2392 &access_mask
, &share_mode
,
2393 &create_disposition
,
2396 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2400 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2402 status
= filename_convert(ctx
,
2408 if (!NT_STATUS_IS_OK(status
)) {
2409 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2410 reply_botherror(req
,
2411 NT_STATUS_PATH_NOT_COVERED
,
2412 ERRSRV
, ERRbadpath
);
2415 reply_nterror(req
, status
);
2419 status
= SMB_VFS_CREATE_FILE(
2422 smb_fname
, /* fname */
2423 access_mask
, /* access_mask */
2424 share_mode
, /* share_access */
2425 create_disposition
, /* create_disposition*/
2426 create_options
, /* create_options */
2427 smb_attr
, /* file_attributes */
2428 oplock_request
, /* oplock_request */
2430 0, /* allocation_size */
2435 &smb_action
, /* pinfo */
2436 NULL
, NULL
); /* create context */
2438 if (!NT_STATUS_IS_OK(status
)) {
2439 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2440 /* We have re-scheduled this call. */
2444 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2445 reply_openerror(req
, status
);
2449 fsp
= fcb_or_dos_open(
2456 bool ok
= defer_smb1_sharing_violation(req
);
2460 reply_openerror(req
, status
);
2465 smb_action
= FILE_WAS_OPENED
;
2468 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2469 if the file is truncated or created. */
2470 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2471 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2472 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2473 close_file(req
, fsp
, ERROR_CLOSE
);
2474 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2477 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2479 close_file(req
, fsp
, ERROR_CLOSE
);
2480 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2483 status
= vfs_stat_fsp(fsp
);
2484 if (!NT_STATUS_IS_OK(status
)) {
2485 close_file(req
, fsp
, ERROR_CLOSE
);
2486 reply_nterror(req
, status
);
2491 fattr
= fdos_mode(fsp
);
2492 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2493 close_file(req
, fsp
, ERROR_CLOSE
);
2494 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2497 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2499 /* If the caller set the extended oplock request bit
2500 and we granted one (by whatever means) - set the
2501 correct bit for extended oplock reply.
2504 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2505 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2508 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2509 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2512 /* If the caller set the core oplock request bit
2513 and we granted one (by whatever means) - set the
2514 correct bit for core oplock reply.
2517 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2518 reply_outbuf(req
, 19, 0);
2520 reply_outbuf(req
, 15, 0);
2523 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2524 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2526 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2527 SCVAL(req
->outbuf
, smb_flg
,
2528 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2531 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2532 SCVAL(req
->outbuf
, smb_flg
,
2533 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2536 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2537 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2538 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2539 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2541 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2543 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2544 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2545 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2547 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2548 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2552 TALLOC_FREE(smb_fname
);
2553 END_PROFILE(SMBopenX
);
2557 /****************************************************************************
2558 Reply to a SMBulogoffX.
2559 ****************************************************************************/
2561 static struct tevent_req
*reply_ulogoffX_send(struct smb_request
*smb1req
,
2562 struct smbXsrv_session
*session
);
2563 static void reply_ulogoffX_done(struct tevent_req
*req
);
2565 void reply_ulogoffX(struct smb_request
*smb1req
)
2567 struct timeval now
= timeval_current();
2568 struct smbXsrv_session
*session
= NULL
;
2569 struct tevent_req
*req
;
2573 * Don't setup the profile charge here, take
2574 * it in reply_ulogoffX_done(). Not strictly correct
2575 * but better than the other SMB1 async
2576 * code that double-charges at the moment.
2579 status
= smb1srv_session_lookup(smb1req
->xconn
,
2581 timeval_to_nttime(&now
),
2583 if (!NT_STATUS_IS_OK(status
)) {
2584 /* Not going async, profile here. */
2585 START_PROFILE(SMBulogoffX
);
2586 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2587 (unsigned long long)smb1req
->vuid
);
2589 smb1req
->vuid
= UID_FIELD_INVALID
;
2590 reply_force_doserror(smb1req
, ERRSRV
, ERRbaduid
);
2591 END_PROFILE(SMBulogoffX
);
2595 req
= reply_ulogoffX_send(smb1req
, session
);
2597 /* Not going async, profile here. */
2598 START_PROFILE(SMBulogoffX
);
2599 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
2600 END_PROFILE(SMBulogoffX
);
2604 /* We're async. This will complete later. */
2605 tevent_req_set_callback(req
, reply_ulogoffX_done
, smb1req
);
2609 struct reply_ulogoffX_state
{
2610 struct tevent_queue
*wait_queue
;
2611 struct smbXsrv_session
*session
;
2614 static void reply_ulogoffX_wait_done(struct tevent_req
*subreq
);
2616 /****************************************************************************
2617 Async SMB1 ulogoffX.
2618 Note, on failure here we deallocate and return NULL to allow the caller to
2619 SMB1 return an error of ERRnomem immediately.
2620 ****************************************************************************/
2622 static struct tevent_req
*reply_ulogoffX_send(struct smb_request
*smb1req
,
2623 struct smbXsrv_session
*session
)
2625 struct tevent_req
*req
;
2626 struct reply_ulogoffX_state
*state
;
2627 struct tevent_req
*subreq
;
2629 struct smbd_server_connection
*sconn
= session
->client
->sconn
;
2630 uint64_t vuid
= session
->global
->session_wire_id
;
2632 req
= tevent_req_create(smb1req
, &state
,
2633 struct reply_ulogoffX_state
);
2637 state
->wait_queue
= tevent_queue_create(state
,
2638 "reply_ulogoffX_wait_queue");
2639 if (tevent_req_nomem(state
->wait_queue
, req
)) {
2643 state
->session
= session
;
2646 * Make sure that no new request will be able to use this session.
2647 * This ensures that once all outstanding fsp->aio_requests
2648 * on this session are done, we are safe to close it.
2650 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
2652 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
) {
2653 if (fsp
->vuid
!= vuid
) {
2657 * Flag the file as close in progress.
2658 * This will prevent any more IO being
2661 fsp
->fsp_flags
.closing
= true;
2663 if (fsp
->num_aio_requests
> 0) {
2665 * Now wait until all aio requests on this fsp are
2668 * We don't set a callback, as we just want to block the
2669 * wait queue and the talloc_free() of fsp->aio_request
2670 * will remove the item from the wait queue.
2672 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
2675 if (tevent_req_nomem(subreq
, req
)) {
2683 * Now we add our own waiter to the end of the queue,
2684 * this way we get notified when all pending requests are finished
2685 * and reply to the outstanding SMB1 request.
2687 subreq
= tevent_queue_wait_send(state
,
2690 if (tevent_req_nomem(subreq
, req
)) {
2696 * We're really going async - move the SMB1 request from
2697 * a talloc stackframe above us to the sconn talloc-context.
2698 * We need this to stick around until the wait_done
2699 * callback is invoked.
2701 smb1req
= talloc_move(sconn
, &smb1req
);
2703 tevent_req_set_callback(subreq
, reply_ulogoffX_wait_done
, req
);
2708 static void reply_ulogoffX_wait_done(struct tevent_req
*subreq
)
2710 struct tevent_req
*req
= tevent_req_callback_data(
2711 subreq
, struct tevent_req
);
2713 tevent_queue_wait_recv(subreq
);
2714 TALLOC_FREE(subreq
);
2715 tevent_req_done(req
);
2718 static NTSTATUS
reply_ulogoffX_recv(struct tevent_req
*req
)
2720 return tevent_req_simple_recv_ntstatus(req
);
2723 static void reply_ulogoffX_done(struct tevent_req
*req
)
2725 struct smb_request
*smb1req
= tevent_req_callback_data(
2726 req
, struct smb_request
);
2727 struct reply_ulogoffX_state
*state
= tevent_req_data(req
,
2728 struct reply_ulogoffX_state
);
2729 struct smbXsrv_session
*session
= state
->session
;
2733 * Take the profile charge here. Not strictly
2734 * correct but better than the other SMB1 async
2735 * code that double-charges at the moment.
2737 START_PROFILE(SMBulogoffX
);
2739 status
= reply_ulogoffX_recv(req
);
2741 if (!NT_STATUS_IS_OK(status
)) {
2742 TALLOC_FREE(smb1req
);
2743 END_PROFILE(SMBulogoffX
);
2744 exit_server(__location__
": reply_ulogoffX_recv failed");
2748 status
= smbXsrv_session_logoff(session
);
2749 if (!NT_STATUS_IS_OK(status
)) {
2750 TALLOC_FREE(smb1req
);
2751 END_PROFILE(SMBulogoffX
);
2752 exit_server(__location__
": smbXsrv_session_logoff failed");
2756 TALLOC_FREE(session
);
2758 reply_outbuf(smb1req
, 2, 0);
2759 SSVAL(smb1req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2760 SSVAL(smb1req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2762 DBG_NOTICE("ulogoffX vuid=%llu\n",
2763 (unsigned long long)smb1req
->vuid
);
2765 smb1req
->vuid
= UID_FIELD_INVALID
;
2767 * The following call is needed to push the
2768 * reply data back out the socket after async
2769 * return. Plus it frees smb1req.
2771 smb_request_done(smb1req
);
2772 END_PROFILE(SMBulogoffX
);
2775 /****************************************************************************
2776 Reply to a mknew or a create.
2777 ****************************************************************************/
2779 void reply_mknew(struct smb_request
*req
)
2781 connection_struct
*conn
= req
->conn
;
2782 struct smb_filename
*smb_fname
= NULL
;
2785 struct smb_file_time ft
;
2787 int oplock_request
= 0;
2789 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2790 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2791 uint32_t create_disposition
;
2792 uint32_t create_options
= 0;
2794 TALLOC_CTX
*ctx
= talloc_tos();
2796 START_PROFILE(SMBcreate
);
2797 init_smb_file_time(&ft
);
2800 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2804 fattr
= SVAL(req
->vwv
+0, 0);
2805 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2807 if (req
->cmd
== SMBmknew
) {
2808 /* We should fail if file exists. */
2809 create_disposition
= FILE_CREATE
;
2811 /* Create if file doesn't exist, truncate if it does. */
2812 create_disposition
= FILE_OVERWRITE_IF
;
2816 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date3(req
->vwv
+1));
2818 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2819 STR_TERMINATE
, &status
);
2820 if (!NT_STATUS_IS_OK(status
)) {
2821 reply_nterror(req
, status
);
2825 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2826 status
= filename_convert(ctx
,
2832 if (!NT_STATUS_IS_OK(status
)) {
2833 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2834 reply_botherror(req
,
2835 NT_STATUS_PATH_NOT_COVERED
,
2836 ERRSRV
, ERRbadpath
);
2839 reply_nterror(req
, status
);
2843 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2844 DEBUG(0,("Attempt to create file (%s) with volid set - "
2845 "please report this\n",
2846 smb_fname_str_dbg(smb_fname
)));
2849 status
= SMB_VFS_CREATE_FILE(
2852 smb_fname
, /* fname */
2853 access_mask
, /* access_mask */
2854 share_mode
, /* share_access */
2855 create_disposition
, /* create_disposition*/
2856 create_options
, /* create_options */
2857 fattr
, /* file_attributes */
2858 oplock_request
, /* oplock_request */
2860 0, /* allocation_size */
2861 0, /* private_flags */
2866 NULL
, NULL
); /* create context */
2868 if (!NT_STATUS_IS_OK(status
)) {
2869 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2870 /* We have re-scheduled this call. */
2873 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2874 bool ok
= defer_smb1_sharing_violation(req
);
2879 reply_openerror(req
, status
);
2883 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2884 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2885 if (!NT_STATUS_IS_OK(status
)) {
2886 END_PROFILE(SMBcreate
);
2890 reply_outbuf(req
, 1, 0);
2891 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2893 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2894 SCVAL(req
->outbuf
,smb_flg
,
2895 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2898 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2899 SCVAL(req
->outbuf
,smb_flg
,
2900 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2903 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2904 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2905 smb_fname_str_dbg(smb_fname
), fsp_get_io_fd(fsp
),
2906 (unsigned int)fattr
));
2909 TALLOC_FREE(smb_fname
);
2910 END_PROFILE(SMBcreate
);
2914 /****************************************************************************
2915 Reply to a create temporary file.
2916 ****************************************************************************/
2918 void reply_ctemp(struct smb_request
*req
)
2920 connection_struct
*conn
= req
->conn
;
2921 struct smb_filename
*smb_fname
= NULL
;
2922 char *wire_name
= NULL
;
2931 TALLOC_CTX
*ctx
= talloc_tos();
2933 START_PROFILE(SMBctemp
);
2936 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2940 fattr
= SVAL(req
->vwv
+0, 0);
2941 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2943 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2944 STR_TERMINATE
, &status
);
2945 if (!NT_STATUS_IS_OK(status
)) {
2946 reply_nterror(req
, status
);
2950 for (i
= 0; i
< 10; i
++) {
2952 fname
= talloc_asprintf(ctx
,
2955 generate_random_str_list(ctx
, 5, "0123456789"));
2957 fname
= talloc_asprintf(ctx
,
2959 generate_random_str_list(ctx
, 5, "0123456789"));
2963 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2967 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2968 status
= filename_convert(ctx
, conn
,
2973 if (!NT_STATUS_IS_OK(status
)) {
2974 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2975 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2976 ERRSRV
, ERRbadpath
);
2979 reply_nterror(req
, status
);
2983 /* Create the file. */
2984 status
= SMB_VFS_CREATE_FILE(
2987 smb_fname
, /* fname */
2988 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2989 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2990 FILE_CREATE
, /* create_disposition*/
2991 0, /* create_options */
2992 fattr
, /* file_attributes */
2993 oplock_request
, /* oplock_request */
2995 0, /* allocation_size */
2996 0, /* private_flags */
3001 NULL
, NULL
); /* create context */
3003 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
3005 TALLOC_FREE(smb_fname
);
3009 if (!NT_STATUS_IS_OK(status
)) {
3010 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3011 /* We have re-scheduled this call. */
3014 if (NT_STATUS_EQUAL(
3015 status
, NT_STATUS_SHARING_VIOLATION
)) {
3016 bool ok
= defer_smb1_sharing_violation(req
);
3021 reply_openerror(req
, status
);
3029 /* Collision after 10 times... */
3030 reply_nterror(req
, status
);
3034 reply_outbuf(req
, 1, 0);
3035 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
3037 /* the returned filename is relative to the directory */
3038 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
3040 s
= fsp
->fsp_name
->base_name
;
3046 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3047 thing in the byte section. JRA */
3048 SSVALS(p
, 0, -1); /* what is this? not in spec */
3050 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
3052 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3056 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
3057 SCVAL(req
->outbuf
, smb_flg
,
3058 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
3061 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
3062 SCVAL(req
->outbuf
, smb_flg
,
3063 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
3066 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
3067 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
3068 fsp_get_io_fd(fsp
), (unsigned int)smb_fname
->st
.st_ex_mode
));
3070 TALLOC_FREE(smb_fname
);
3071 TALLOC_FREE(wire_name
);
3072 END_PROFILE(SMBctemp
);
3076 /*******************************************************************
3077 Check if a user is allowed to rename a file.
3078 ********************************************************************/
3080 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
3083 if (!CAN_WRITE(conn
)) {
3084 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
3087 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
3088 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
3089 /* Only bother to read the DOS attribute if we might deny the
3090 rename on the grounds of attribute mismatch. */
3091 uint32_t fmode
= fdos_mode(fsp
);
3092 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
3093 return NT_STATUS_NO_SUCH_FILE
;
3097 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
3098 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
3099 return NT_STATUS_OK
;
3102 /* If no pathnames are open below this
3103 directory, allow the rename. */
3105 if (lp_strict_rename(SNUM(conn
))) {
3107 * Strict rename, check open file db.
3109 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
3110 return NT_STATUS_ACCESS_DENIED
;
3112 } else if (file_find_subpath(fsp
)) {
3114 * No strict rename, just look in local process.
3116 return NT_STATUS_ACCESS_DENIED
;
3118 return NT_STATUS_OK
;
3121 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
3122 return NT_STATUS_OK
;
3125 return NT_STATUS_ACCESS_DENIED
;
3128 /*******************************************************************
3129 * unlink a file with all relevant access checks
3130 *******************************************************************/
3132 static NTSTATUS
do_unlink(connection_struct
*conn
,
3133 struct smb_request
*req
,
3134 struct smb_filename
*smb_fname
,
3139 uint32_t dirtype_orig
= dirtype
;
3142 struct smb2_create_blobs
*posx
= NULL
;
3144 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3145 smb_fname_str_dbg(smb_fname
),
3148 if (!CAN_WRITE(conn
)) {
3149 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
3152 ret
= vfs_stat(conn
, smb_fname
);
3154 return map_nt_error_from_unix(errno
);
3157 fattr
= fdos_mode(smb_fname
->fsp
);
3159 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
3160 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
3163 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
3165 return NT_STATUS_NO_SUCH_FILE
;
3168 if (!dir_check_ftype(fattr
, dirtype
)) {
3169 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
3170 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3172 return NT_STATUS_NO_SUCH_FILE
;
3175 if (dirtype_orig
& 0x8000) {
3176 /* These will never be set for POSIX. */
3177 return NT_STATUS_NO_SUCH_FILE
;
3181 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
3182 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3185 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
3186 return NT_STATUS_NO_SUCH_FILE
;
3189 if (dirtype
& 0xFF00) {
3190 /* These will never be set for POSIX. */
3191 return NT_STATUS_NO_SUCH_FILE
;
3196 return NT_STATUS_NO_SUCH_FILE
;
3199 /* Can't delete a directory. */
3200 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
3201 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3206 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
3207 return NT_STATUS_OBJECT_NAME_INVALID
;
3208 #endif /* JRATEST */
3210 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
) {
3211 status
= make_smb2_posix_create_ctx(
3212 talloc_tos(), &posx
, 0777);
3213 if (!NT_STATUS_IS_OK(status
)) {
3214 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
3220 /* On open checks the open itself will check the share mode, so
3221 don't do it here as we'll get it wrong. */
3223 status
= SMB_VFS_CREATE_FILE
3226 smb_fname
, /* fname */
3227 DELETE_ACCESS
, /* access_mask */
3228 FILE_SHARE_NONE
, /* share_access */
3229 FILE_OPEN
, /* create_disposition*/
3230 FILE_NON_DIRECTORY_FILE
, /* create_options */
3231 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
3232 0, /* oplock_request */
3234 0, /* allocation_size */
3235 0, /* private_flags */
3240 posx
, /* in_context_blobs */
3241 NULL
); /* out_context_blobs */
3245 if (!NT_STATUS_IS_OK(status
)) {
3246 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3247 nt_errstr(status
)));
3251 status
= can_set_delete_on_close(fsp
, fattr
);
3252 if (!NT_STATUS_IS_OK(status
)) {
3253 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3255 smb_fname_str_dbg(smb_fname
),
3256 nt_errstr(status
)));
3257 close_file(req
, fsp
, NORMAL_CLOSE
);
3261 /* The set is across all open files on this dev/inode pair. */
3262 if (!set_delete_on_close(fsp
, True
,
3263 conn
->session_info
->security_token
,
3264 conn
->session_info
->unix_token
)) {
3265 close_file(req
, fsp
, NORMAL_CLOSE
);
3266 return NT_STATUS_ACCESS_DENIED
;
3269 return close_file(req
, fsp
, NORMAL_CLOSE
);
3272 /****************************************************************************
3273 The guts of the unlink command, split out so it may be called by the NT SMB
3275 ****************************************************************************/
3277 NTSTATUS
unlink_internals(connection_struct
*conn
,
3278 struct smb_request
*req
,
3280 struct smb_filename
*smb_fname
,
3283 char *fname_dir
= NULL
;
3284 char *fname_mask
= NULL
;
3286 NTSTATUS status
= NT_STATUS_OK
;
3287 struct smb_filename
*smb_fname_dir
= NULL
;
3288 TALLOC_CTX
*ctx
= talloc_tos();
3291 /* Split up the directory from the filename/mask. */
3292 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
3293 &fname_dir
, &fname_mask
);
3294 if (!NT_STATUS_IS_OK(status
)) {
3299 * We should only check the mangled cache
3300 * here if unix_convert failed. This means
3301 * that the path in 'mask' doesn't exist
3302 * on the file system and so we need to look
3303 * for a possible mangle. This patch from
3304 * Tine Smukavec <valentin.smukavec@hermes.si>.
3307 if (!VALID_STAT(smb_fname
->st
) &&
3308 mangle_is_mangled(fname_mask
, conn
->params
)) {
3309 char *new_mask
= NULL
;
3310 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
3311 &new_mask
, conn
->params
);
3313 TALLOC_FREE(fname_mask
);
3314 fname_mask
= new_mask
;
3321 * Only one file needs to be unlinked. Append the mask back
3322 * onto the directory.
3324 TALLOC_FREE(smb_fname
->base_name
);
3325 if (ISDOT(fname_dir
)) {
3326 /* Ensure we use canonical names on open. */
3327 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3331 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3336 if (!smb_fname
->base_name
) {
3337 status
= NT_STATUS_NO_MEMORY
;
3341 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3344 status
= check_name(conn
, smb_fname
);
3345 if (!NT_STATUS_IS_OK(status
)) {
3349 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3350 if (!NT_STATUS_IS_OK(status
)) {
3356 struct smb_Dir
*dir_hnd
= NULL
;
3358 const char *dname
= NULL
;
3359 char *talloced
= NULL
;
3361 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
3362 status
= NT_STATUS_OBJECT_NAME_INVALID
;
3366 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3369 if (strequal(fname_mask
,"????????.???")) {
3370 TALLOC_FREE(fname_mask
);
3371 fname_mask
= talloc_strdup(ctx
, "*");
3373 status
= NT_STATUS_NO_MEMORY
;
3378 smb_fname_dir
= synthetic_smb_fname(talloc_tos(),
3384 if (smb_fname_dir
== NULL
) {
3385 status
= NT_STATUS_NO_MEMORY
;
3389 status
= check_name(conn
, smb_fname_dir
);
3390 if (!NT_STATUS_IS_OK(status
)) {
3394 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_dir
, fname_mask
,
3396 if (dir_hnd
== NULL
) {
3397 status
= map_nt_error_from_unix(errno
);
3401 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3402 the pattern matches against the long name, otherwise the short name
3403 We don't implement this yet XXXX
3406 status
= NT_STATUS_NO_SUCH_FILE
;
3408 while ((dname
= ReadDirName(dir_hnd
, &offset
,
3409 &smb_fname
->st
, &talloced
))) {
3410 TALLOC_CTX
*frame
= talloc_stackframe();
3412 struct smb_filename
*f
= NULL
;
3414 /* Quick check for "." and ".." */
3415 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
3417 TALLOC_FREE(talloced
);
3421 if (IS_VETO_PATH(conn
, dname
)) {
3423 TALLOC_FREE(talloced
);
3427 if(!mask_match(dname
, fname_mask
,
3428 conn
->case_sensitive
)) {
3430 TALLOC_FREE(talloced
);
3434 if (ISDOT(fname_dir
)) {
3435 /* Ensure we use canonical names on open. */
3436 p
= talloc_asprintf(smb_fname
, "%s", dname
);
3438 p
= talloc_asprintf(smb_fname
, "%s/%s",
3442 TALLOC_FREE(dir_hnd
);
3443 status
= NT_STATUS_NO_MEMORY
;
3445 TALLOC_FREE(talloced
);
3448 f
= synthetic_smb_fname(frame
,
3455 TALLOC_FREE(dir_hnd
);
3456 status
= NT_STATUS_NO_MEMORY
;
3458 TALLOC_FREE(talloced
);
3462 ret
= vfs_stat(conn
, f
);
3464 status
= map_nt_error_from_unix(errno
);
3465 TALLOC_FREE(dir_hnd
);
3467 TALLOC_FREE(talloced
);
3471 status
= openat_pathref_fsp(conn
->cwd_fsp
, f
);
3472 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
) &&
3473 (f
->flags
& SMB_FILENAME_POSIX_PATH
) &&
3474 S_ISLNK(f
->st
.st_ex_mode
))
3476 status
= NT_STATUS_OK
;
3478 if (!NT_STATUS_IS_OK(status
)) {
3479 TALLOC_FREE(dir_hnd
);
3481 TALLOC_FREE(talloced
);
3485 if (!is_visible_fsp(f
->fsp
)) {
3487 TALLOC_FREE(talloced
);
3491 status
= check_name(conn
, f
);
3492 if (!NT_STATUS_IS_OK(status
)) {
3493 TALLOC_FREE(dir_hnd
);
3495 TALLOC_FREE(talloced
);
3499 status
= do_unlink(conn
, req
, f
, dirtype
);
3500 if (!NT_STATUS_IS_OK(status
)) {
3501 TALLOC_FREE(dir_hnd
);
3503 TALLOC_FREE(talloced
);
3508 DBG_DEBUG("successful unlink [%s]\n",
3509 smb_fname_str_dbg(f
));
3512 TALLOC_FREE(talloced
);
3514 TALLOC_FREE(dir_hnd
);
3517 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3518 status
= map_nt_error_from_unix(errno
);
3522 TALLOC_FREE(smb_fname_dir
);
3523 TALLOC_FREE(fname_dir
);
3524 TALLOC_FREE(fname_mask
);
3528 /****************************************************************************
3530 ****************************************************************************/
3532 void reply_unlink(struct smb_request
*req
)
3534 connection_struct
*conn
= req
->conn
;
3536 struct smb_filename
*smb_fname
= NULL
;
3539 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
3540 ucf_flags_from_smb_request(req
);
3541 TALLOC_CTX
*ctx
= talloc_tos();
3542 bool has_wild
= false;
3544 START_PROFILE(SMBunlink
);
3547 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3551 dirtype
= SVAL(req
->vwv
+0, 0);
3553 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3554 STR_TERMINATE
, &status
);
3555 if (!NT_STATUS_IS_OK(status
)) {
3556 reply_nterror(req
, status
);
3560 status
= filename_convert(ctx
, conn
,
3565 if (!NT_STATUS_IS_OK(status
)) {
3566 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3567 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3568 ERRSRV
, ERRbadpath
);
3571 reply_nterror(req
, status
);
3575 if (!req
->posix_pathnames
) {
3576 char *lcomp
= get_original_lcomp(ctx
,
3580 if (lcomp
== NULL
) {
3581 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3584 has_wild
= ms_has_wild(lcomp
);
3588 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3590 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
, has_wild
);
3591 if (!NT_STATUS_IS_OK(status
)) {
3592 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3593 /* We have re-scheduled this call. */
3596 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
3597 bool ok
= defer_smb1_sharing_violation(req
);
3602 reply_nterror(req
, status
);
3606 reply_outbuf(req
, 0, 0);
3608 TALLOC_FREE(smb_fname
);
3609 END_PROFILE(SMBunlink
);
3613 /****************************************************************************
3615 ****************************************************************************/
3617 static void fail_readraw(void)
3619 const char *errstr
= talloc_asprintf(talloc_tos(),
3620 "FAIL ! reply_readbraw: socket write fail (%s)",
3625 exit_server_cleanly(errstr
);
3628 /****************************************************************************
3629 Fake (read/write) sendfile. Returns -1 on read or write fail.
3630 ****************************************************************************/
3632 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3633 off_t startpos
, size_t nread
)
3636 size_t tosend
= nread
;
3643 bufsize
= MIN(nread
, 65536);
3645 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3649 while (tosend
> 0) {
3653 cur_read
= MIN(tosend
, bufsize
);
3654 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3660 /* If we had a short read, fill with zeros. */
3661 if (ret
< cur_read
) {
3662 memset(buf
+ ret
, '\0', cur_read
- ret
);
3665 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3666 if (ret
!= cur_read
) {
3667 int saved_errno
= errno
;
3669 * Try and give an error message saying what
3672 DEBUG(0, ("write_data failed for client %s. "
3674 smbXsrv_connection_dbg(xconn
),
3675 strerror(saved_errno
)));
3677 errno
= saved_errno
;
3681 startpos
+= cur_read
;
3685 return (ssize_t
)nread
;
3688 /****************************************************************************
3689 Deal with the case of sendfile reading less bytes from the file than
3690 requested. Fill with zeros (all we can do). Returns 0 on success
3691 ****************************************************************************/
3693 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3699 #define SHORT_SEND_BUFSIZE 1024
3700 if (nread
< headersize
) {
3701 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3702 "header for file %s (%s). Terminating\n",
3703 fsp_str_dbg(fsp
), strerror(errno
)));
3707 nread
-= headersize
;
3709 if (nread
< smb_maxcnt
) {
3710 char buf
[SHORT_SEND_BUFSIZE
] = { 0 };
3712 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3713 "with zeros !\n", fsp_str_dbg(fsp
)));
3715 while (nread
< smb_maxcnt
) {
3717 * We asked for the real file size and told sendfile
3718 * to not go beyond the end of the file. But it can
3719 * happen that in between our fstat call and the
3720 * sendfile call the file was truncated. This is very
3721 * bad because we have already announced the larger
3722 * number of bytes to the client.
3724 * The best we can do now is to send 0-bytes, just as
3725 * a read from a hole in a sparse file would do.
3727 * This should happen rarely enough that I don't care
3728 * about efficiency here :-)
3733 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3734 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3735 if (ret
!= to_write
) {
3736 int saved_errno
= errno
;
3738 * Try and give an error message saying what
3741 DEBUG(0, ("write_data failed for client %s. "
3743 smbXsrv_connection_dbg(xconn
),
3744 strerror(saved_errno
)));
3745 errno
= saved_errno
;
3755 /****************************************************************************
3756 Return a readbraw error (4 bytes of zero).
3757 ****************************************************************************/
3759 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3765 smbd_lock_socket(xconn
);
3766 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3767 int saved_errno
= errno
;
3769 * Try and give an error message saying what
3772 DEBUG(0, ("write_data failed for client %s. "
3774 smbXsrv_connection_dbg(xconn
),
3775 strerror(saved_errno
)));
3776 errno
= saved_errno
;
3780 smbd_unlock_socket(xconn
);
3783 /*******************************************************************
3784 Ensure we don't use sendfile if server smb signing is active.
3785 ********************************************************************/
3787 static bool lp_use_sendfile(int snum
, struct smb_signing_state
*signing_state
)
3789 bool sign_active
= false;
3791 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3792 if (get_Protocol() < PROTOCOL_NT1
) {
3795 if (signing_state
) {
3796 sign_active
= smb_signing_is_active(signing_state
);
3798 return (lp__use_sendfile(snum
) &&
3799 (get_remote_arch() != RA_WIN95
) &&
3802 /****************************************************************************
3803 Use sendfile in readbraw.
3804 ****************************************************************************/
3806 static void send_file_readbraw(connection_struct
*conn
,
3807 struct smb_request
*req
,
3813 struct smbXsrv_connection
*xconn
= req
->xconn
;
3814 char *outbuf
= NULL
;
3818 * We can only use sendfile on a non-chained packet
3819 * but we can use on a non-oplocked file. tridge proved this
3820 * on a train in Germany :-). JRA.
3821 * reply_readbraw has already checked the length.
3824 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3825 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3826 ssize_t sendfile_read
= -1;
3828 DATA_BLOB header_blob
;
3830 _smb_setlen(header
,nread
);
3831 header_blob
= data_blob_const(header
, 4);
3833 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3834 &header_blob
, startpos
,
3836 if (sendfile_read
== -1) {
3837 /* Returning ENOSYS means no data at all was sent.
3838 * Do this as a normal read. */
3839 if (errno
== ENOSYS
) {
3840 goto normal_readbraw
;
3844 * Special hack for broken Linux with no working sendfile. If we
3845 * return EINTR we sent the header but not the rest of the data.
3846 * Fake this up by doing read/write calls.
3848 if (errno
== EINTR
) {
3849 /* Ensure we don't do this again. */
3850 set_use_sendfile(SNUM(conn
), False
);
3851 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3853 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3854 DEBUG(0,("send_file_readbraw: "
3855 "fake_sendfile failed for "
3859 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3864 DEBUG(0,("send_file_readbraw: sendfile failed for "
3865 "file %s (%s). Terminating\n",
3866 fsp_str_dbg(fsp
), strerror(errno
)));
3867 exit_server_cleanly("send_file_readbraw sendfile failed");
3868 } else if (sendfile_read
== 0) {
3870 * Some sendfile implementations return 0 to indicate
3871 * that there was a short read, but nothing was
3872 * actually written to the socket. In this case,
3873 * fallback to the normal read path so the header gets
3874 * the correct byte count.
3876 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3877 "bytes falling back to the normal read: "
3878 "%s\n", fsp_str_dbg(fsp
)));
3879 goto normal_readbraw
;
3882 /* Deal with possible short send. */
3883 if (sendfile_read
!= 4+nread
) {
3884 ret
= sendfile_short_send(xconn
, fsp
,
3885 sendfile_read
, 4, nread
);
3895 outbuf
= talloc_array(NULL
, char, nread
+4);
3897 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3898 (unsigned)(nread
+4)));
3899 reply_readbraw_error(xconn
);
3904 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3905 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3914 _smb_setlen(outbuf
,ret
);
3915 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3916 int saved_errno
= errno
;
3918 * Try and give an error message saying what
3921 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3922 smbXsrv_connection_dbg(xconn
),
3923 strerror(saved_errno
)));
3924 errno
= saved_errno
;
3929 TALLOC_FREE(outbuf
);
3932 /****************************************************************************
3933 Reply to a readbraw (core+ protocol).
3934 ****************************************************************************/
3936 void reply_readbraw(struct smb_request
*req
)
3938 connection_struct
*conn
= req
->conn
;
3939 struct smbXsrv_connection
*xconn
= req
->xconn
;
3940 ssize_t maxcount
,mincount
;
3944 struct lock_struct lock
;
3948 START_PROFILE(SMBreadbraw
);
3950 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3951 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3952 "raw reads/writes are disallowed.");
3956 reply_readbraw_error(xconn
);
3957 END_PROFILE(SMBreadbraw
);
3961 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3962 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3963 "'async smb echo handler = yes'\n"));
3964 reply_readbraw_error(xconn
);
3965 END_PROFILE(SMBreadbraw
);
3970 * Special check if an oplock break has been issued
3971 * and the readraw request croses on the wire, we must
3972 * return a zero length response here.
3975 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3978 * We have to do a check_fsp by hand here, as
3979 * we must always return 4 zero bytes on error,
3985 conn
!= fsp
->conn
||
3986 req
->vuid
!= fsp
->vuid
||
3987 fsp
->fsp_flags
.is_directory
||
3988 fsp_get_io_fd(fsp
) == -1)
3991 * fsp could be NULL here so use the value from the packet. JRA.
3993 DEBUG(3,("reply_readbraw: fnum %d not valid "
3995 (int)SVAL(req
->vwv
+0, 0)));
3996 reply_readbraw_error(xconn
);
3997 END_PROFILE(SMBreadbraw
);
4001 /* Do a "by hand" version of CHECK_READ. */
4002 if (!(fsp
->fsp_flags
.can_read
||
4003 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
4004 (fsp
->access_mask
& FILE_EXECUTE
)))) {
4005 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4006 (int)SVAL(req
->vwv
+0, 0)));
4007 reply_readbraw_error(xconn
);
4008 END_PROFILE(SMBreadbraw
);
4012 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
4013 if(req
->wct
== 10) {
4015 * This is a large offset (64 bit) read.
4018 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
4021 DEBUG(0,("reply_readbraw: negative 64 bit "
4022 "readraw offset (%.0f) !\n",
4023 (double)startpos
));
4024 reply_readbraw_error(xconn
);
4025 END_PROFILE(SMBreadbraw
);
4030 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
4031 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
4033 /* ensure we don't overrun the packet size */
4034 maxcount
= MIN(65535,maxcount
);
4036 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4037 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
4040 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4041 reply_readbraw_error(xconn
);
4042 END_PROFILE(SMBreadbraw
);
4046 status
= vfs_stat_fsp(fsp
);
4047 if (NT_STATUS_IS_OK(status
)) {
4048 size
= fsp
->fsp_name
->st
.st_ex_size
;
4051 if (startpos
>= size
) {
4054 nread
= MIN(maxcount
,(size
- startpos
));
4057 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4058 if (nread
< mincount
)
4062 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4063 "min=%lu nread=%lu\n",
4064 fsp_fnum_dbg(fsp
), (double)startpos
,
4065 (unsigned long)maxcount
,
4066 (unsigned long)mincount
,
4067 (unsigned long)nread
) );
4069 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
4071 DEBUG(5,("reply_readbraw finished\n"));
4073 END_PROFILE(SMBreadbraw
);
4078 #define DBGC_CLASS DBGC_LOCKING
4080 /****************************************************************************
4081 Reply to a lockread (core+ protocol).
4082 ****************************************************************************/
4084 static void reply_lockread_locked(struct tevent_req
*subreq
);
4086 void reply_lockread(struct smb_request
*req
)
4088 struct tevent_req
*subreq
= NULL
;
4089 connection_struct
*conn
= req
->conn
;
4091 struct smbd_lock_element
*lck
= NULL
;
4093 START_PROFILE(SMBlockread
);
4096 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4097 END_PROFILE(SMBlockread
);
4101 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4103 if (!check_fsp(conn
, req
, fsp
)) {
4104 END_PROFILE(SMBlockread
);
4108 if (!CHECK_READ(fsp
,req
)) {
4109 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4110 END_PROFILE(SMBlockread
);
4114 lck
= talloc(req
, struct smbd_lock_element
);
4116 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4117 END_PROFILE(SMBlockread
);
4122 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4123 * protocol request that predates the read/write lock concept.
4124 * Thus instead of asking for a read lock here we need to ask
4125 * for a write lock. JRA.
4126 * Note that the requested lock size is unaffected by max_send.
4129 *lck
= (struct smbd_lock_element
) {
4130 .req_guid
= smbd_request_guid(req
, 0),
4131 .smblctx
= req
->smbpid
,
4132 .brltype
= WRITE_LOCK
,
4133 .count
= SVAL(req
->vwv
+1, 0),
4134 .offset
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0),
4137 subreq
= smbd_smb1_do_locks_send(
4143 false, /* large_offset */
4147 if (subreq
== NULL
) {
4148 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4149 END_PROFILE(SMBlockread
);
4152 tevent_req_set_callback(subreq
, reply_lockread_locked
, NULL
);
4153 END_PROFILE(SMBlockread
);
4156 static void reply_lockread_locked(struct tevent_req
*subreq
)
4158 struct smb_request
*req
= NULL
;
4164 size_t numtoread
, maxtoread
;
4165 struct files_struct
*fsp
= NULL
;
4168 START_PROFILE(SMBlockread
);
4170 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
4173 status
= smbd_smb1_do_locks_recv(subreq
);
4174 TALLOC_FREE(subreq
);
4176 if (!NT_STATUS_IS_OK(status
)) {
4177 reply_nterror(req
, status
);
4181 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4183 reply_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
4187 numtoread
= SVAL(req
->vwv
+1, 0);
4188 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4191 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4193 maxtoread
= req
->xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
4195 if (numtoread
> maxtoread
) {
4196 DBG_WARNING("requested read size (%zu) is greater than "
4197 "maximum allowed (%zu/%d). "
4198 "Returning short read of maximum allowed for "
4199 "compatibility with Windows 2000.\n",
4202 req
->xconn
->smb1
.sessions
.max_send
);
4203 numtoread
= maxtoread
;
4206 reply_outbuf(req
, 5, numtoread
+ 3);
4208 data
= smb_buf(req
->outbuf
) + 3;
4210 nread
= read_file(fsp
,data
,startpos
,numtoread
);
4213 reply_nterror(req
, map_nt_error_from_unix(errno
));
4217 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
4219 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
4220 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
4221 p
= smb_buf(req
->outbuf
);
4222 SCVAL(p
,0,0); /* pad byte. */
4225 DEBUG(3,("lockread %s num=%d nread=%d\n",
4226 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
4229 ok
= srv_send_smb(req
->xconn
,
4230 (char *)req
->outbuf
,
4233 IS_CONN_ENCRYPTED(req
->conn
),
4236 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4239 END_PROFILE(SMBlockread
);
4244 #define DBGC_CLASS DBGC_ALL
4246 /****************************************************************************
4248 ****************************************************************************/
4250 void reply_read(struct smb_request
*req
)
4252 connection_struct
*conn
= req
->conn
;
4259 struct lock_struct lock
;
4260 struct smbXsrv_connection
*xconn
= req
->xconn
;
4262 START_PROFILE(SMBread
);
4265 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4266 END_PROFILE(SMBread
);
4270 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4272 if (!check_fsp(conn
, req
, fsp
)) {
4273 END_PROFILE(SMBread
);
4277 if (!CHECK_READ(fsp
,req
)) {
4278 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4279 END_PROFILE(SMBread
);
4283 numtoread
= SVAL(req
->vwv
+1, 0);
4284 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4287 * The requested read size cannot be greater than max_send. JRA.
4289 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
4291 if (numtoread
> maxtoread
) {
4292 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4293 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4294 (unsigned int)numtoread
, (unsigned int)maxtoread
,
4295 (unsigned int)xconn
->smb1
.sessions
.max_send
));
4296 numtoread
= maxtoread
;
4299 reply_outbuf(req
, 5, numtoread
+3);
4301 data
= smb_buf(req
->outbuf
) + 3;
4303 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4304 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
4307 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4308 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4309 END_PROFILE(SMBread
);
4314 nread
= read_file(fsp
,data
,startpos
,numtoread
);
4317 reply_nterror(req
, map_nt_error_from_unix(errno
));
4321 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
4323 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
4324 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
4325 SCVAL(smb_buf(req
->outbuf
),0,1);
4326 SSVAL(smb_buf(req
->outbuf
),1,nread
);
4328 DEBUG(3, ("read %s num=%d nread=%d\n",
4329 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
4332 END_PROFILE(SMBread
);
4336 /****************************************************************************
4338 ****************************************************************************/
4340 size_t setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
4344 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
4347 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
4349 SCVAL(outbuf
,smb_vwv0
,0xFF);
4350 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
4351 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
4352 SSVAL(outbuf
,smb_vwv6
,
4353 (smb_wct
- 4) /* offset from smb header to wct */
4354 + 1 /* the wct field */
4355 + 12 * sizeof(uint16_t) /* vwv */
4356 + 2 /* the buflen field */
4357 + 1); /* padding byte */
4358 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
4359 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
4360 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4361 _smb_setlen_large(outbuf
,
4362 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
4366 /****************************************************************************
4367 Reply to a read and X - possibly using sendfile.
4368 ****************************************************************************/
4370 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
4371 files_struct
*fsp
, off_t startpos
,
4374 struct smbXsrv_connection
*xconn
= req
->xconn
;
4376 struct lock_struct lock
;
4377 int saved_errno
= 0;
4380 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4381 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
4384 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4385 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4390 * We can only use sendfile on a non-chained packet
4391 * but we can use on a non-oplocked file. tridge proved this
4392 * on a train in Germany :-). JRA.
4395 if (!req_is_in_chain(req
) &&
4397 (fsp
->base_fsp
== NULL
) &&
4398 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
4399 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
4402 status
= vfs_stat_fsp(fsp
);
4403 if (!NT_STATUS_IS_OK(status
)) {
4404 reply_nterror(req
, status
);
4408 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4409 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4410 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4412 * We already know that we would do a short read, so don't
4413 * try the sendfile() path.
4415 goto nosendfile_read
;
4419 * Set up the packet header before send. We
4420 * assume here the sendfile will work (get the
4421 * correct amount of data).
4424 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4426 construct_reply_common_req(req
, (char *)headerbuf
);
4427 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4429 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4430 startpos
, smb_maxcnt
);
4432 saved_errno
= errno
;
4434 /* Returning ENOSYS means no data at all was sent.
4435 Do this as a normal read. */
4436 if (errno
== ENOSYS
) {
4441 * Special hack for broken Linux with no working sendfile. If we
4442 * return EINTR we sent the header but not the rest of the data.
4443 * Fake this up by doing read/write calls.
4446 if (errno
== EINTR
) {
4447 /* Ensure we don't do this again. */
4448 set_use_sendfile(SNUM(conn
), False
);
4449 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4450 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4453 saved_errno
= errno
;
4454 DEBUG(0,("send_file_readX: "
4455 "fake_sendfile failed for "
4456 "file %s (%s) for client %s. "
4459 smbXsrv_connection_dbg(xconn
),
4460 strerror(saved_errno
)));
4461 errno
= saved_errno
;
4462 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4464 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4465 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4466 /* No outbuf here means successful sendfile. */
4470 DEBUG(0,("send_file_readX: sendfile failed for file "
4471 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4473 exit_server_cleanly("send_file_readX sendfile failed");
4474 } else if (nread
== 0) {
4476 * Some sendfile implementations return 0 to indicate
4477 * that there was a short read, but nothing was
4478 * actually written to the socket. In this case,
4479 * fallback to the normal read path so the header gets
4480 * the correct byte count.
4482 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4483 "falling back to the normal read: %s\n",
4488 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4489 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4491 /* Deal with possible short send. */
4492 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4495 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4496 sizeof(headerbuf
), smb_maxcnt
);
4499 r
= "send_file_readX: sendfile_short_send failed";
4500 DEBUG(0,("%s for file %s (%s).\n",
4501 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4502 exit_server_cleanly(r
);
4505 /* No outbuf here means successful sendfile. */
4506 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4507 SMB_PERFCOUNT_END(&req
->pcd
);
4513 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4514 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4517 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4518 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4519 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4521 * We already know that we would do a short
4522 * read, so don't try the sendfile() path.
4524 goto nosendfile_read
;
4527 construct_reply_common_req(req
, (char *)headerbuf
);
4528 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4530 /* Send out the header. */
4531 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4533 if (ret
!= sizeof(headerbuf
)) {
4534 saved_errno
= errno
;
4536 * Try and give an error message saying what
4539 DEBUG(0,("send_file_readX: write_data failed for file "
4540 "%s (%s) for client %s. Terminating\n",
4542 smbXsrv_connection_dbg(xconn
),
4543 strerror(saved_errno
)));
4544 errno
= saved_errno
;
4545 exit_server_cleanly("send_file_readX sendfile failed");
4547 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4549 saved_errno
= errno
;
4550 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4551 "%s (%s) for client %s. Terminating\n",
4553 smbXsrv_connection_dbg(xconn
),
4554 strerror(saved_errno
)));
4555 errno
= saved_errno
;
4556 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4563 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4564 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4565 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4567 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4568 startpos
, smb_maxcnt
);
4569 saved_errno
= errno
;
4572 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4576 setup_readX_header((char *)req
->outbuf
, nread
);
4578 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4579 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4583 TALLOC_FREE(req
->outbuf
);
4587 /****************************************************************************
4588 Work out how much space we have for a read return.
4589 ****************************************************************************/
4591 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4593 struct smbXsrv_connection
*xconn
= req
->xconn
;
4595 if (xconn
->protocol
< PROTOCOL_NT1
) {
4596 return xconn
->smb1
.sessions
.max_send
;
4599 if (!lp_large_readwrite()) {
4600 return xconn
->smb1
.sessions
.max_send
;
4603 if (req_is_in_chain(req
)) {
4604 return xconn
->smb1
.sessions
.max_send
;
4607 if (req
->encrypted
) {
4609 * Don't take encrypted traffic up to the
4610 * limit. There are padding considerations
4611 * that make that tricky.
4613 return xconn
->smb1
.sessions
.max_send
;
4616 if (srv_is_signing_active(xconn
)) {
4620 if (!lp_unix_extensions()) {
4625 * We can do ultra-large POSIX reads.
4630 /****************************************************************************
4631 Calculate how big a read can be. Copes with all clients. It's always
4632 safe to return a short read - Windows does this.
4633 ****************************************************************************/
4635 static size_t calc_read_size(const struct smb_request
*req
,
4639 struct smbXsrv_connection
*xconn
= req
->xconn
;
4640 size_t max_pdu
= calc_max_read_pdu(req
);
4641 size_t total_size
= 0;
4642 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4643 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4646 * Windows explicitly ignores upper size of 0xFFFF.
4647 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4648 * We must do the same as these will never fit even in
4649 * an extended size NetBIOS packet.
4651 if (upper_size
== 0xFFFF) {
4655 if (xconn
->protocol
< PROTOCOL_NT1
) {
4659 total_size
= ((upper_size
<<16) | lower_size
);
4662 * LARGE_READX test shows it's always safe to return
4663 * a short read. Windows does so.
4665 return MIN(total_size
, max_len
);
4668 /****************************************************************************
4669 Reply to a read and X.
4670 ****************************************************************************/
4672 void reply_read_and_X(struct smb_request
*req
)
4674 connection_struct
*conn
= req
->conn
;
4679 bool big_readX
= False
;
4681 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4684 START_PROFILE(SMBreadX
);
4686 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4687 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4691 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4692 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4693 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4695 /* If it's an IPC, pass off the pipe handler. */
4697 reply_pipe_read_and_X(req
);
4698 END_PROFILE(SMBreadX
);
4702 if (!check_fsp(conn
, req
, fsp
)) {
4703 END_PROFILE(SMBreadX
);
4707 if (!CHECK_READ(fsp
,req
)) {
4708 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4709 END_PROFILE(SMBreadX
);
4713 upper_size
= SVAL(req
->vwv
+7, 0);
4714 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4715 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4717 * This is a heuristic to avoid keeping large
4718 * outgoing buffers around over long-lived aio
4724 if (req
->wct
== 12) {
4726 * This is a large offset (64 bit) read.
4728 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4733 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4738 if (NT_STATUS_IS_OK(status
)) {
4739 /* Read scheduled - we're done. */
4742 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4743 /* Real error - report to client. */
4744 END_PROFILE(SMBreadX
);
4745 reply_nterror(req
, status
);
4748 /* NT_STATUS_RETRY - fall back to sync read. */
4751 smbd_lock_socket(req
->xconn
);
4752 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4753 smbd_unlock_socket(req
->xconn
);
4756 END_PROFILE(SMBreadX
);
4760 /****************************************************************************
4761 Error replies to writebraw must have smb_wct == 1. Fix this up.
4762 ****************************************************************************/
4764 void error_to_writebrawerr(struct smb_request
*req
)
4766 uint8_t *old_outbuf
= req
->outbuf
;
4768 reply_outbuf(req
, 1, 0);
4770 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4771 TALLOC_FREE(old_outbuf
);
4774 /****************************************************************************
4775 Read 4 bytes of a smb packet and return the smb length of the packet.
4776 Store the result in the buffer. This version of the function will
4777 never return a session keepalive (length of zero).
4778 Timeout is in milliseconds.
4779 ****************************************************************************/
4781 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4784 uint8_t msgtype
= NBSSkeepalive
;
4786 while (msgtype
== NBSSkeepalive
) {
4789 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4791 if (!NT_STATUS_IS_OK(status
)) {
4792 char addr
[INET6_ADDRSTRLEN
];
4793 /* Try and give an error message
4794 * saying what client failed. */
4795 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4796 "client %s read error = %s.\n",
4797 get_peer_addr(fd
,addr
,sizeof(addr
)),
4798 nt_errstr(status
)));
4802 msgtype
= CVAL(inbuf
, 0);
4805 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4806 (unsigned long)len
));
4808 return NT_STATUS_OK
;
4811 /****************************************************************************
4812 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4813 ****************************************************************************/
4815 void reply_writebraw(struct smb_request
*req
)
4817 connection_struct
*conn
= req
->conn
;
4818 struct smbXsrv_connection
*xconn
= req
->xconn
;
4821 ssize_t total_written
=0;
4822 size_t numtowrite
=0;
4825 const char *data
=NULL
;
4828 struct lock_struct lock
;
4831 START_PROFILE(SMBwritebraw
);
4834 * If we ever reply with an error, it must have the SMB command
4835 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4838 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4840 if (srv_is_signing_active(xconn
)) {
4841 END_PROFILE(SMBwritebraw
);
4842 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4843 "raw reads/writes are disallowed.");
4846 if (req
->wct
< 12) {
4847 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4848 error_to_writebrawerr(req
);
4849 END_PROFILE(SMBwritebraw
);
4853 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4854 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4855 "'async smb echo handler = yes'\n"));
4856 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4857 error_to_writebrawerr(req
);
4858 END_PROFILE(SMBwritebraw
);
4862 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4863 if (!check_fsp(conn
, req
, fsp
)) {
4864 error_to_writebrawerr(req
);
4865 END_PROFILE(SMBwritebraw
);
4869 if (!CHECK_WRITE(fsp
)) {
4870 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4871 error_to_writebrawerr(req
);
4872 END_PROFILE(SMBwritebraw
);
4876 tcount
= IVAL(req
->vwv
+1, 0);
4877 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4878 write_through
= BITSETW(req
->vwv
+7,0);
4880 /* We have to deal with slightly different formats depending
4881 on whether we are using the core+ or lanman1.0 protocol */
4883 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4884 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4885 data
= smb_buf_const(req
->inbuf
);
4887 numtowrite
= SVAL(req
->vwv
+10, 0);
4888 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4891 /* Ensure we don't write bytes past the end of this packet. */
4893 * This already protects us against CVE-2017-12163.
4895 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4896 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4897 error_to_writebrawerr(req
);
4898 END_PROFILE(SMBwritebraw
);
4902 if (!fsp
->print_file
) {
4903 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4904 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4907 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4908 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4909 error_to_writebrawerr(req
);
4910 END_PROFILE(SMBwritebraw
);
4916 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4919 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4920 "wrote=%d sync=%d\n",
4921 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4922 (int)nwritten
, (int)write_through
));
4924 if (nwritten
< (ssize_t
)numtowrite
) {
4925 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4926 error_to_writebrawerr(req
);
4930 total_written
= nwritten
;
4932 /* Allocate a buffer of 64k + length. */
4933 buf
= talloc_array(NULL
, char, 65540);
4935 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4936 error_to_writebrawerr(req
);
4940 /* Return a SMBwritebraw message to the redirector to tell
4941 * it to send more bytes */
4943 memcpy(buf
, req
->inbuf
, smb_size
);
4944 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4945 SCVAL(buf
,smb_com
,SMBwritebraw
);
4946 SSVALS(buf
,smb_vwv0
,0xFFFF);
4948 if (!srv_send_smb(req
->xconn
,
4950 false, 0, /* no signing */
4951 IS_CONN_ENCRYPTED(conn
),
4953 exit_server_cleanly("reply_writebraw: srv_send_smb "
4957 /* Now read the raw data into the buffer and write it */
4958 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4960 if (!NT_STATUS_IS_OK(status
)) {
4961 exit_server_cleanly("secondary writebraw failed");
4964 /* Set up outbuf to return the correct size */
4965 reply_outbuf(req
, 1, 0);
4967 if (numtowrite
!= 0) {
4969 if (numtowrite
> 0xFFFF) {
4970 DEBUG(0,("reply_writebraw: Oversize secondary write "
4971 "raw requested (%u). Terminating\n",
4972 (unsigned int)numtowrite
));
4973 exit_server_cleanly("secondary writebraw failed");
4976 if (tcount
> nwritten
+numtowrite
) {
4977 DEBUG(3,("reply_writebraw: Client overestimated the "
4979 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4982 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4985 if (!NT_STATUS_IS_OK(status
)) {
4986 /* Try and give an error message
4987 * saying what client failed. */
4988 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4989 "raw read failed (%s) for client %s. "
4990 "Terminating\n", nt_errstr(status
),
4991 smbXsrv_connection_dbg(xconn
)));
4992 exit_server_cleanly("secondary writebraw failed");
4996 * We are not vulnerable to CVE-2017-12163
4997 * here as we are guaranteed to have numtowrite
4998 * bytes available - we just read from the client.
5000 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
5001 if (nwritten
== -1) {
5003 reply_nterror(req
, map_nt_error_from_unix(errno
));
5004 error_to_writebrawerr(req
);
5008 if (nwritten
< (ssize_t
)numtowrite
) {
5009 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
5010 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
5014 total_written
+= nwritten
;
5019 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
5021 status
= sync_file(conn
, fsp
, write_through
);
5022 if (!NT_STATUS_IS_OK(status
)) {
5023 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5024 fsp_str_dbg(fsp
), nt_errstr(status
)));
5025 reply_nterror(req
, status
);
5026 error_to_writebrawerr(req
);
5030 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5032 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
5033 (int)total_written
));
5035 /* We won't return a status if write through is not selected - this
5036 * follows what WfWg does */
5037 END_PROFILE(SMBwritebraw
);
5039 if (!write_through
&& total_written
==tcount
) {
5041 #if RABBIT_PELLET_FIX
5043 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5044 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5047 if (!send_keepalive(xconn
->transport
.sock
)) {
5048 exit_server_cleanly("reply_writebraw: send of "
5049 "keepalive failed");
5052 TALLOC_FREE(req
->outbuf
);
5057 END_PROFILE(SMBwritebraw
);
5062 #define DBGC_CLASS DBGC_LOCKING
5064 /****************************************************************************
5065 Reply to a writeunlock (core+).
5066 ****************************************************************************/
5068 void reply_writeunlock(struct smb_request
*req
)
5070 connection_struct
*conn
= req
->conn
;
5071 ssize_t nwritten
= -1;
5076 NTSTATUS status
= NT_STATUS_OK
;
5078 struct lock_struct lock
;
5079 int saved_errno
= 0;
5081 START_PROFILE(SMBwriteunlock
);
5084 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5085 END_PROFILE(SMBwriteunlock
);
5089 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5091 if (!check_fsp(conn
, req
, fsp
)) {
5092 END_PROFILE(SMBwriteunlock
);
5096 if (!CHECK_WRITE(fsp
)) {
5097 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5098 END_PROFILE(SMBwriteunlock
);
5102 numtowrite
= SVAL(req
->vwv
+1, 0);
5103 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5104 data
= (const char *)req
->buf
+ 3;
5107 * Ensure client isn't asking us to write more than
5108 * they sent. CVE-2017-12163.
5110 remaining
= smbreq_bufrem(req
, data
);
5111 if (numtowrite
> remaining
) {
5112 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5113 END_PROFILE(SMBwriteunlock
);
5117 if (!fsp
->print_file
&& numtowrite
> 0) {
5118 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5119 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5122 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5123 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5124 END_PROFILE(SMBwriteunlock
);
5129 /* The special X/Open SMB protocol handling of
5130 zero length writes is *NOT* done for
5132 if(numtowrite
== 0) {
5135 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5136 saved_errno
= errno
;
5139 status
= sync_file(conn
, fsp
, False
/* write through */);
5140 if (!NT_STATUS_IS_OK(status
)) {
5141 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5142 fsp_str_dbg(fsp
), nt_errstr(status
)));
5143 reply_nterror(req
, status
);
5148 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5152 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
5153 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5157 if (numtowrite
&& !fsp
->print_file
) {
5158 struct smbd_lock_element l
= {
5159 .req_guid
= smbd_request_guid(req
, 0),
5160 .smblctx
= req
->smbpid
,
5161 .brltype
= UNLOCK_LOCK
,
5163 .count
= numtowrite
,
5165 status
= smbd_do_unlocking(req
, fsp
, 1, &l
, WINDOWS_LOCK
);
5166 if (NT_STATUS_V(status
)) {
5167 reply_nterror(req
, status
);
5172 reply_outbuf(req
, 1, 0);
5174 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5176 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5177 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5180 END_PROFILE(SMBwriteunlock
);
5185 #define DBGC_CLASS DBGC_ALL
5187 /****************************************************************************
5189 ****************************************************************************/
5191 void reply_write(struct smb_request
*req
)
5193 connection_struct
*conn
= req
->conn
;
5196 ssize_t nwritten
= -1;
5200 struct lock_struct lock
;
5202 int saved_errno
= 0;
5204 START_PROFILE(SMBwrite
);
5207 END_PROFILE(SMBwrite
);
5208 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5212 /* If it's an IPC, pass off the pipe handler. */
5214 reply_pipe_write(req
);
5215 END_PROFILE(SMBwrite
);
5219 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5221 if (!check_fsp(conn
, req
, fsp
)) {
5222 END_PROFILE(SMBwrite
);
5226 if (!CHECK_WRITE(fsp
)) {
5227 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5228 END_PROFILE(SMBwrite
);
5232 numtowrite
= SVAL(req
->vwv
+1, 0);
5233 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5234 data
= (const char *)req
->buf
+ 3;
5237 * Ensure client isn't asking us to write more than
5238 * they sent. CVE-2017-12163.
5240 remaining
= smbreq_bufrem(req
, data
);
5241 if (numtowrite
> remaining
) {
5242 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5243 END_PROFILE(SMBwrite
);
5247 if (!fsp
->print_file
) {
5248 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5249 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5252 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5253 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5254 END_PROFILE(SMBwrite
);
5260 * X/Open SMB protocol says that if smb_vwv1 is
5261 * zero then the file size should be extended or
5262 * truncated to the size given in smb_vwv[2-3].
5265 if(numtowrite
== 0) {
5267 * This is actually an allocate call, and set EOF. JRA.
5269 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
5271 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5274 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
5276 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5279 trigger_write_time_update_immediate(fsp
);
5281 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5284 status
= sync_file(conn
, fsp
, False
);
5285 if (!NT_STATUS_IS_OK(status
)) {
5286 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5287 fsp_str_dbg(fsp
), nt_errstr(status
)));
5288 reply_nterror(req
, status
);
5293 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5297 if((nwritten
== 0) && (numtowrite
!= 0)) {
5298 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5302 reply_outbuf(req
, 1, 0);
5304 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5306 if (nwritten
< (ssize_t
)numtowrite
) {
5307 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
5308 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
5311 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5314 END_PROFILE(SMBwrite
);
5318 /****************************************************************************
5319 Ensure a buffer is a valid writeX for recvfile purposes.
5320 ****************************************************************************/
5322 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5323 (2*14) + /* word count (including bcc) */ \
5326 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
5327 const uint8_t *inbuf
)
5330 unsigned int doff
= 0;
5331 size_t len
= smb_len_large(inbuf
);
5333 struct smbXsrv_open
*op
= NULL
;
5334 struct files_struct
*fsp
= NULL
;
5337 if (is_encrypted_packet(inbuf
)) {
5338 /* Can't do this on encrypted
5343 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
5347 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
5348 CVAL(inbuf
,smb_wct
) != 14) {
5349 DEBUG(10,("is_valid_writeX_buffer: chained or "
5350 "invalid word length.\n"));
5354 fnum
= SVAL(inbuf
, smb_vwv2
);
5355 status
= smb1srv_open_lookup(xconn
,
5359 if (!NT_STATUS_IS_OK(status
)) {
5360 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5365 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5368 if (fsp
->conn
== NULL
) {
5369 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5373 if (IS_IPC(fsp
->conn
)) {
5374 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5377 if (IS_PRINT(fsp
->conn
)) {
5378 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5381 if (fsp
->base_fsp
!= NULL
) {
5382 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5385 doff
= SVAL(inbuf
,smb_vwv11
);
5387 numtowrite
= SVAL(inbuf
,smb_vwv10
);
5389 if (len
> doff
&& len
- doff
> 0xFFFF) {
5390 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
5393 if (numtowrite
== 0) {
5394 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5398 /* Ensure the sizes match up. */
5399 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
5400 /* no pad byte...old smbclient :-( */
5401 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5403 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
5407 if (len
- doff
!= numtowrite
) {
5408 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5409 "len = %u, doff = %u, numtowrite = %u\n",
5412 (unsigned int)numtowrite
));
5416 DEBUG(10,("is_valid_writeX_buffer: true "
5417 "len = %u, doff = %u, numtowrite = %u\n",
5420 (unsigned int)numtowrite
));
5425 /****************************************************************************
5426 Reply to a write and X.
5427 ****************************************************************************/
5429 void reply_write_and_X(struct smb_request
*req
)
5431 connection_struct
*conn
= req
->conn
;
5432 struct smbXsrv_connection
*xconn
= req
->xconn
;
5434 struct lock_struct lock
;
5439 unsigned int smb_doff
;
5440 unsigned int smblen
;
5443 int saved_errno
= 0;
5445 START_PROFILE(SMBwriteX
);
5447 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5448 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5452 numtowrite
= SVAL(req
->vwv
+10, 0);
5453 smb_doff
= SVAL(req
->vwv
+11, 0);
5454 smblen
= smb_len(req
->inbuf
);
5456 if (req
->unread_bytes
> 0xFFFF ||
5457 (smblen
> smb_doff
&&
5458 smblen
- smb_doff
> 0xFFFF)) {
5459 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5462 if (req
->unread_bytes
) {
5463 /* Can't do a recvfile write on IPC$ */
5465 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5468 if (numtowrite
!= req
->unread_bytes
) {
5469 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5474 * This already protects us against CVE-2017-12163.
5476 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5477 smb_doff
+ numtowrite
> smblen
) {
5478 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5483 /* If it's an IPC, pass off the pipe handler. */
5485 if (req
->unread_bytes
) {
5486 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5489 reply_pipe_write_and_X(req
);
5493 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5494 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5495 write_through
= BITSETW(req
->vwv
+7,0);
5497 if (!check_fsp(conn
, req
, fsp
)) {
5501 if (!CHECK_WRITE(fsp
)) {
5502 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5506 data
= smb_base(req
->inbuf
) + smb_doff
;
5508 if(req
->wct
== 14) {
5510 * This is a large offset (64 bit) write.
5512 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5516 /* X/Open SMB protocol says that, unlike SMBwrite
5517 if the length is zero then NO truncation is
5518 done, just a write of zero. To truncate a file,
5521 if(numtowrite
== 0) {
5524 if (req
->unread_bytes
== 0) {
5525 status
= schedule_aio_write_and_X(conn
,
5532 if (NT_STATUS_IS_OK(status
)) {
5533 /* write scheduled - we're done. */
5536 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5537 /* Real error - report to client. */
5538 reply_nterror(req
, status
);
5541 /* NT_STATUS_RETRY - fall through to sync write. */
5544 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5545 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5548 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5549 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5553 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5554 saved_errno
= errno
;
5558 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5562 if((nwritten
== 0) && (numtowrite
!= 0)) {
5563 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5567 reply_outbuf(req
, 6, 0);
5568 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5569 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5570 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5571 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5573 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5574 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5576 status
= sync_file(conn
, fsp
, write_through
);
5577 if (!NT_STATUS_IS_OK(status
)) {
5578 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5579 fsp_str_dbg(fsp
), nt_errstr(status
)));
5580 reply_nterror(req
, status
);
5584 END_PROFILE(SMBwriteX
);
5588 if (req
->unread_bytes
) {
5589 /* writeX failed. drain socket. */
5590 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5591 req
->unread_bytes
) {
5592 smb_panic("failed to drain pending bytes");
5594 req
->unread_bytes
= 0;
5597 END_PROFILE(SMBwriteX
);
5601 /****************************************************************************
5603 ****************************************************************************/
5605 void reply_lseek(struct smb_request
*req
)
5607 connection_struct
*conn
= req
->conn
;
5614 START_PROFILE(SMBlseek
);
5617 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5618 END_PROFILE(SMBlseek
);
5622 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5624 if (!check_fsp(conn
, req
, fsp
)) {
5628 mode
= SVAL(req
->vwv
+1, 0) & 3;
5629 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5630 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5639 res
= fh_get_pos(fsp
->fh
) + startpos
;
5650 if (umode
== SEEK_END
) {
5651 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5652 if(errno
== EINVAL
) {
5653 off_t current_pos
= startpos
;
5655 status
= vfs_stat_fsp(fsp
);
5656 if (!NT_STATUS_IS_OK(status
)) {
5657 reply_nterror(req
, status
);
5658 END_PROFILE(SMBlseek
);
5662 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5664 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5669 reply_nterror(req
, map_nt_error_from_unix(errno
));
5670 END_PROFILE(SMBlseek
);
5675 fh_set_pos(fsp
->fh
, res
);
5677 reply_outbuf(req
, 2, 0);
5678 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5680 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5681 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5683 END_PROFILE(SMBlseek
);
5687 static struct files_struct
*file_sync_one_fn(struct files_struct
*fsp
,
5690 connection_struct
*conn
= talloc_get_type_abort(
5691 private_data
, connection_struct
);
5693 if (conn
!= fsp
->conn
) {
5696 if (fsp_get_io_fd(fsp
) == -1) {
5699 sync_file(conn
, fsp
, True
/* write through */);
5701 if (fsp
->fsp_flags
.modified
) {
5702 trigger_write_time_update_immediate(fsp
);
5708 /****************************************************************************
5710 ****************************************************************************/
5712 void reply_flush(struct smb_request
*req
)
5714 connection_struct
*conn
= req
->conn
;
5718 START_PROFILE(SMBflush
);
5721 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5725 fnum
= SVAL(req
->vwv
+0, 0);
5726 fsp
= file_fsp(req
, fnum
);
5728 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5733 files_forall(req
->sconn
, file_sync_one_fn
, conn
);
5735 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5736 if (!NT_STATUS_IS_OK(status
)) {
5737 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5738 fsp_str_dbg(fsp
), nt_errstr(status
)));
5739 reply_nterror(req
, status
);
5740 END_PROFILE(SMBflush
);
5743 if (fsp
->fsp_flags
.modified
) {
5744 trigger_write_time_update_immediate(fsp
);
5748 reply_outbuf(req
, 0, 0);
5750 DEBUG(3,("flush\n"));
5751 END_PROFILE(SMBflush
);
5755 /****************************************************************************
5757 conn POINTER CAN BE NULL HERE !
5758 ****************************************************************************/
5760 static struct tevent_req
*reply_exit_send(struct smb_request
*smb1req
);
5761 static void reply_exit_done(struct tevent_req
*req
);
5763 void reply_exit(struct smb_request
*smb1req
)
5765 struct tevent_req
*req
;
5768 * Don't setup the profile charge here, take
5769 * it in reply_exit_done(). Not strictly correct
5770 * but better than the other SMB1 async
5771 * code that double-charges at the moment.
5773 req
= reply_exit_send(smb1req
);
5775 /* Not going async, profile here. */
5776 START_PROFILE(SMBexit
);
5777 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
5778 END_PROFILE(SMBexit
);
5782 /* We're async. This will complete later. */
5783 tevent_req_set_callback(req
, reply_exit_done
, smb1req
);
5787 struct reply_exit_state
{
5788 struct tevent_queue
*wait_queue
;
5791 static void reply_exit_wait_done(struct tevent_req
*subreq
);
5793 /****************************************************************************
5795 Note, on failure here we deallocate and return NULL to allow the caller to
5796 SMB1 return an error of ERRnomem immediately.
5797 ****************************************************************************/
5799 static struct tevent_req
*reply_exit_send(struct smb_request
*smb1req
)
5801 struct tevent_req
*req
;
5802 struct reply_exit_state
*state
;
5803 struct tevent_req
*subreq
;
5805 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
5807 req
= tevent_req_create(smb1req
, &state
,
5808 struct reply_exit_state
);
5812 state
->wait_queue
= tevent_queue_create(state
,
5813 "reply_exit_wait_queue");
5814 if (tevent_req_nomem(state
->wait_queue
, req
)) {
5819 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
) {
5820 if (fsp
->file_pid
!= smb1req
->smbpid
) {
5823 if (fsp
->vuid
!= smb1req
->vuid
) {
5827 * Flag the file as close in progress.
5828 * This will prevent any more IO being
5831 fsp
->fsp_flags
.closing
= true;
5833 if (fsp
->num_aio_requests
> 0) {
5835 * Now wait until all aio requests on this fsp are
5838 * We don't set a callback, as we just want to block the
5839 * wait queue and the talloc_free() of fsp->aio_request
5840 * will remove the item from the wait queue.
5842 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
5845 if (tevent_req_nomem(subreq
, req
)) {
5853 * Now we add our own waiter to the end of the queue,
5854 * this way we get notified when all pending requests are finished
5855 * and reply to the outstanding SMB1 request.
5857 subreq
= tevent_queue_wait_send(state
,
5860 if (tevent_req_nomem(subreq
, req
)) {
5866 * We're really going async - move the SMB1 request from
5867 * a talloc stackframe above us to the conn talloc-context.
5868 * We need this to stick around until the wait_done
5869 * callback is invoked.
5871 smb1req
= talloc_move(sconn
, &smb1req
);
5873 tevent_req_set_callback(subreq
, reply_exit_wait_done
, req
);
5878 static void reply_exit_wait_done(struct tevent_req
*subreq
)
5880 struct tevent_req
*req
= tevent_req_callback_data(
5881 subreq
, struct tevent_req
);
5883 tevent_queue_wait_recv(subreq
);
5884 TALLOC_FREE(subreq
);
5885 tevent_req_done(req
);
5888 static NTSTATUS
reply_exit_recv(struct tevent_req
*req
)
5890 return tevent_req_simple_recv_ntstatus(req
);
5893 static void reply_exit_done(struct tevent_req
*req
)
5895 struct smb_request
*smb1req
= tevent_req_callback_data(
5896 req
, struct smb_request
);
5897 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
5898 struct smbXsrv_connection
*xconn
= smb1req
->xconn
;
5899 NTTIME now
= timeval_to_nttime(&smb1req
->request_time
);
5900 struct smbXsrv_session
*session
= NULL
;
5901 files_struct
*fsp
, *next
;
5905 * Take the profile charge here. Not strictly
5906 * correct but better than the other SMB1 async
5907 * code that double-charges at the moment.
5909 START_PROFILE(SMBexit
);
5911 status
= reply_exit_recv(req
);
5913 if (!NT_STATUS_IS_OK(status
)) {
5914 TALLOC_FREE(smb1req
);
5915 END_PROFILE(SMBexit
);
5916 exit_server(__location__
": reply_exit_recv failed");
5921 * Ensure the session is still valid.
5923 status
= smb1srv_session_lookup(xconn
,
5927 if (!NT_STATUS_IS_OK(status
)) {
5928 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5929 smb_request_done(smb1req
);
5930 END_PROFILE(SMBexit
);
5934 * Ensure the vuid is still valid - no one
5935 * called reply_ulogoffX() in the meantime.
5936 * reply_exit() doesn't have AS_USER set, so
5937 * use set_current_user_info() directly.
5938 * This is the same logic as in switch_message().
5940 if (session
->global
->auth_session_info
!= NULL
) {
5941 set_current_user_info(
5942 session
->global
->auth_session_info
->unix_info
->sanitized_username
,
5943 session
->global
->auth_session_info
->unix_info
->unix_name
,
5944 session
->global
->auth_session_info
->info
->domain_name
);
5947 /* No more aio - do the actual closes. */
5948 for (fsp
= sconn
->files
; fsp
; fsp
= next
) {
5952 if (fsp
->file_pid
!= smb1req
->smbpid
) {
5955 if (fsp
->vuid
!= smb1req
->vuid
) {
5958 if (!fsp
->fsp_flags
.closing
) {
5963 * reply_exit() has the DO_CHDIR flag set.
5965 ok
= chdir_current_service(fsp
->conn
);
5967 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5968 smb_request_done(smb1req
);
5969 END_PROFILE(SMBexit
);
5971 close_file(NULL
, fsp
, SHUTDOWN_CLOSE
);
5974 reply_outbuf(smb1req
, 0, 0);
5976 * The following call is needed to push the
5977 * reply data back out the socket after async
5978 * return. Plus it frees smb1req.
5980 smb_request_done(smb1req
);
5981 DBG_INFO("reply_exit complete\n");
5982 END_PROFILE(SMBexit
);
5986 static struct tevent_req
*reply_close_send(struct smb_request
*smb1req
,
5988 static void reply_close_done(struct tevent_req
*req
);
5990 void reply_close(struct smb_request
*smb1req
)
5992 connection_struct
*conn
= smb1req
->conn
;
5993 NTSTATUS status
= NT_STATUS_OK
;
5994 files_struct
*fsp
= NULL
;
5995 START_PROFILE(SMBclose
);
5997 if (smb1req
->wct
< 3) {
5998 reply_nterror(smb1req
, NT_STATUS_INVALID_PARAMETER
);
5999 END_PROFILE(SMBclose
);
6003 fsp
= file_fsp(smb1req
, SVAL(smb1req
->vwv
+0, 0));
6006 * We can only use check_fsp if we know it's not a directory.
6009 if (!check_fsp_open(conn
, smb1req
, fsp
)) {
6010 reply_nterror(smb1req
, NT_STATUS_INVALID_HANDLE
);
6011 END_PROFILE(SMBclose
);
6015 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
6016 fsp
->fsp_flags
.is_directory
?
6017 "directory" : "file",
6018 fsp_get_pathref_fd(fsp
), fsp_fnum_dbg(fsp
),
6019 conn
->num_files_open
);
6021 if (!fsp
->fsp_flags
.is_directory
) {
6025 * Take care of any time sent in the close.
6028 t
= srv_make_unix_date3(smb1req
->vwv
+1);
6029 set_close_write_time(fsp
, time_t_to_full_timespec(t
));
6032 if (fsp
->num_aio_requests
!= 0) {
6033 struct tevent_req
*req
;
6035 req
= reply_close_send(smb1req
, fsp
);
6037 status
= NT_STATUS_NO_MEMORY
;
6040 /* We're async. This will complete later. */
6041 tevent_req_set_callback(req
, reply_close_done
, smb1req
);
6042 END_PROFILE(SMBclose
);
6047 * close_file() returns the unix errno if an error was detected on
6048 * close - normally this is due to a disk full error. If not then it
6049 * was probably an I/O error.
6052 status
= close_file(smb1req
, fsp
, NORMAL_CLOSE
);
6054 if (!NT_STATUS_IS_OK(status
)) {
6055 reply_nterror(smb1req
, status
);
6056 END_PROFILE(SMBclose
);
6060 reply_outbuf(smb1req
, 0, 0);
6061 END_PROFILE(SMBclose
);
6065 struct reply_close_state
{
6067 struct tevent_queue
*wait_queue
;
6070 static void reply_close_wait_done(struct tevent_req
*subreq
);
6072 /****************************************************************************
6074 Note, on failure here we deallocate and return NULL to allow the caller to
6075 SMB1 return an error of ERRnomem immediately.
6076 ****************************************************************************/
6078 static struct tevent_req
*reply_close_send(struct smb_request
*smb1req
,
6081 struct tevent_req
*req
;
6082 struct reply_close_state
*state
;
6083 struct tevent_req
*subreq
;
6084 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
6086 req
= tevent_req_create(smb1req
, &state
,
6087 struct reply_close_state
);
6091 state
->wait_queue
= tevent_queue_create(state
,
6092 "reply_close_wait_queue");
6093 if (tevent_req_nomem(state
->wait_queue
, req
)) {
6099 * Flag the file as close in progress.
6100 * This will prevent any more IO being
6103 fsp
->fsp_flags
.closing
= true;
6106 * Now wait until all aio requests on this fsp are
6109 * We don't set a callback, as we just want to block the
6110 * wait queue and the talloc_free() of fsp->aio_request
6111 * will remove the item from the wait queue.
6113 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
6116 if (tevent_req_nomem(subreq
, req
)) {
6122 * Now we add our own waiter to the end of the queue,
6123 * this way we get notified when all pending requests are finished
6124 * and reply to the outstanding SMB1 request.
6126 subreq
= tevent_queue_wait_send(state
,
6129 if (tevent_req_nomem(subreq
, req
)) {
6135 * We're really going async - move the SMB1 request from
6136 * a talloc stackframe above us to the conn talloc-context.
6137 * We need this to stick around until the wait_done
6138 * callback is invoked.
6140 smb1req
= talloc_move(sconn
, &smb1req
);
6142 tevent_req_set_callback(subreq
, reply_close_wait_done
, req
);
6147 static void reply_close_wait_done(struct tevent_req
*subreq
)
6149 struct tevent_req
*req
= tevent_req_callback_data(
6150 subreq
, struct tevent_req
);
6152 tevent_queue_wait_recv(subreq
);
6153 TALLOC_FREE(subreq
);
6154 tevent_req_done(req
);
6157 static NTSTATUS
reply_close_recv(struct tevent_req
*req
)
6159 return tevent_req_simple_recv_ntstatus(req
);
6162 static void reply_close_done(struct tevent_req
*req
)
6164 struct smb_request
*smb1req
= tevent_req_callback_data(
6165 req
, struct smb_request
);
6166 struct reply_close_state
*state
= tevent_req_data(req
,
6167 struct reply_close_state
);
6170 status
= reply_close_recv(req
);
6172 if (!NT_STATUS_IS_OK(status
)) {
6173 TALLOC_FREE(smb1req
);
6174 exit_server(__location__
": reply_close_recv failed");
6178 status
= close_file(smb1req
, state
->fsp
, NORMAL_CLOSE
);
6179 if (NT_STATUS_IS_OK(status
)) {
6180 reply_outbuf(smb1req
, 0, 0);
6182 reply_nterror(smb1req
, status
);
6185 * The following call is needed to push the
6186 * reply data back out the socket after async
6187 * return. Plus it frees smb1req.
6189 smb_request_done(smb1req
);
6192 /****************************************************************************
6193 Reply to a writeclose (Core+ protocol).
6194 ****************************************************************************/
6196 void reply_writeclose(struct smb_request
*req
)
6198 connection_struct
*conn
= req
->conn
;
6201 ssize_t nwritten
= -1;
6202 NTSTATUS close_status
= NT_STATUS_OK
;
6205 struct timespec mtime
;
6207 struct lock_struct lock
;
6209 START_PROFILE(SMBwriteclose
);
6212 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6213 END_PROFILE(SMBwriteclose
);
6217 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6219 if (!check_fsp(conn
, req
, fsp
)) {
6220 END_PROFILE(SMBwriteclose
);
6223 if (!CHECK_WRITE(fsp
)) {
6224 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6225 END_PROFILE(SMBwriteclose
);
6229 numtowrite
= SVAL(req
->vwv
+1, 0);
6230 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
6231 mtime
= time_t_to_full_timespec(srv_make_unix_date3(req
->vwv
+4));
6232 data
= (const char *)req
->buf
+ 1;
6235 * Ensure client isn't asking us to write more than
6236 * they sent. CVE-2017-12163.
6238 remaining
= smbreq_bufrem(req
, data
);
6239 if (numtowrite
> remaining
) {
6240 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6241 END_PROFILE(SMBwriteclose
);
6245 if (fsp
->print_file
== NULL
) {
6246 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
6247 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
6250 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
6251 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
6252 END_PROFILE(SMBwriteclose
);
6257 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
6259 set_close_write_time(fsp
, mtime
);
6262 * More insanity. W2K only closes the file if writelen > 0.
6266 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6267 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
6268 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
6271 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6272 "file %s\n", fsp_str_dbg(fsp
)));
6273 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6277 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
6278 reply_nterror(req
, NT_STATUS_DISK_FULL
);
6282 if(!NT_STATUS_IS_OK(close_status
)) {
6283 reply_nterror(req
, close_status
);
6287 reply_outbuf(req
, 1, 0);
6289 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
6293 END_PROFILE(SMBwriteclose
);
6298 #define DBGC_CLASS DBGC_LOCKING
6300 /****************************************************************************
6302 ****************************************************************************/
6304 static void reply_lock_done(struct tevent_req
*subreq
);
6306 void reply_lock(struct smb_request
*req
)
6308 struct tevent_req
*subreq
= NULL
;
6309 connection_struct
*conn
= req
->conn
;
6311 struct smbd_lock_element
*lck
= NULL
;
6313 START_PROFILE(SMBlock
);
6316 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6317 END_PROFILE(SMBlock
);
6321 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6323 if (!check_fsp(conn
, req
, fsp
)) {
6324 END_PROFILE(SMBlock
);
6328 lck
= talloc(req
, struct smbd_lock_element
);
6330 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6331 END_PROFILE(SMBlock
);
6335 *lck
= (struct smbd_lock_element
) {
6336 .req_guid
= smbd_request_guid(req
, 0),
6337 .smblctx
= req
->smbpid
,
6338 .brltype
= WRITE_LOCK
,
6339 .count
= IVAL(req
->vwv
+1, 0),
6340 .offset
= IVAL(req
->vwv
+3, 0),
6343 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
6349 subreq
= smbd_smb1_do_locks_send(
6355 false, /* large_offset */
6359 if (subreq
== NULL
) {
6360 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6361 END_PROFILE(SMBlock
);
6364 tevent_req_set_callback(subreq
, reply_lock_done
, NULL
);
6365 END_PROFILE(SMBlock
);
6368 static void reply_lock_done(struct tevent_req
*subreq
)
6370 struct smb_request
*req
= NULL
;
6374 START_PROFILE(SMBlock
);
6376 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
6379 status
= smbd_smb1_do_locks_recv(subreq
);
6380 TALLOC_FREE(subreq
);
6382 if (NT_STATUS_IS_OK(status
)) {
6383 reply_outbuf(req
, 0, 0);
6385 reply_nterror(req
, status
);
6388 ok
= srv_send_smb(req
->xconn
,
6389 (char *)req
->outbuf
,
6392 IS_CONN_ENCRYPTED(req
->conn
),
6395 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6398 END_PROFILE(SMBlock
);
6401 /****************************************************************************
6403 ****************************************************************************/
6405 void reply_unlock(struct smb_request
*req
)
6407 connection_struct
*conn
= req
->conn
;
6410 struct smbd_lock_element lck
;
6412 START_PROFILE(SMBunlock
);
6415 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6416 END_PROFILE(SMBunlock
);
6420 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6422 if (!check_fsp(conn
, req
, fsp
)) {
6423 END_PROFILE(SMBunlock
);
6427 lck
= (struct smbd_lock_element
) {
6428 .req_guid
= smbd_request_guid(req
, 0),
6429 .smblctx
= req
->smbpid
,
6430 .brltype
= UNLOCK_LOCK
,
6431 .offset
= IVAL(req
->vwv
+3, 0),
6432 .count
= IVAL(req
->vwv
+1, 0),
6435 status
= smbd_do_unlocking(req
, fsp
, 1, &lck
, WINDOWS_LOCK
);
6437 if (!NT_STATUS_IS_OK(status
)) {
6438 reply_nterror(req
, status
);
6439 END_PROFILE(SMBunlock
);
6443 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
6449 reply_outbuf(req
, 0, 0);
6451 END_PROFILE(SMBunlock
);
6456 #define DBGC_CLASS DBGC_ALL
6458 /****************************************************************************
6460 conn POINTER CAN BE NULL HERE !
6461 ****************************************************************************/
6463 static struct tevent_req
*reply_tdis_send(struct smb_request
*smb1req
);
6464 static void reply_tdis_done(struct tevent_req
*req
);
6466 void reply_tdis(struct smb_request
*smb1req
)
6468 connection_struct
*conn
= smb1req
->conn
;
6469 struct tevent_req
*req
;
6472 * Don't setup the profile charge here, take
6473 * it in reply_tdis_done(). Not strictly correct
6474 * but better than the other SMB1 async
6475 * code that double-charges at the moment.
6479 /* Not going async, profile here. */
6480 START_PROFILE(SMBtdis
);
6481 DBG_INFO("Invalid connection in tdis\n");
6482 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
6483 END_PROFILE(SMBtdis
);
6487 req
= reply_tdis_send(smb1req
);
6489 /* Not going async, profile here. */
6490 START_PROFILE(SMBtdis
);
6491 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
6492 END_PROFILE(SMBtdis
);
6495 /* We're async. This will complete later. */
6496 tevent_req_set_callback(req
, reply_tdis_done
, smb1req
);
6500 struct reply_tdis_state
{
6501 struct tevent_queue
*wait_queue
;
6504 static void reply_tdis_wait_done(struct tevent_req
*subreq
);
6506 /****************************************************************************
6508 Note, on failure here we deallocate and return NULL to allow the caller to
6509 SMB1 return an error of ERRnomem immediately.
6510 ****************************************************************************/
6512 static struct tevent_req
*reply_tdis_send(struct smb_request
*smb1req
)
6514 struct tevent_req
*req
;
6515 struct reply_tdis_state
*state
;
6516 struct tevent_req
*subreq
;
6517 connection_struct
*conn
= smb1req
->conn
;
6520 req
= tevent_req_create(smb1req
, &state
,
6521 struct reply_tdis_state
);
6525 state
->wait_queue
= tevent_queue_create(state
, "reply_tdis_wait_queue");
6526 if (tevent_req_nomem(state
->wait_queue
, req
)) {
6532 * Make sure that no new request will be able to use this tcon.
6533 * This ensures that once all outstanding fsp->aio_requests
6534 * on this tcon are done, we are safe to close it.
6536 conn
->tcon
->status
= NT_STATUS_NETWORK_NAME_DELETED
;
6538 for (fsp
= conn
->sconn
->files
; fsp
; fsp
= fsp
->next
) {
6539 if (fsp
->conn
!= conn
) {
6543 * Flag the file as close in progress.
6544 * This will prevent any more IO being
6545 * done on it. Not strictly needed, but
6546 * doesn't hurt to flag it as closing.
6548 fsp
->fsp_flags
.closing
= true;
6550 if (fsp
->num_aio_requests
> 0) {
6552 * Now wait until all aio requests on this fsp are
6555 * We don't set a callback, as we just want to block the
6556 * wait queue and the talloc_free() of fsp->aio_request
6557 * will remove the item from the wait queue.
6559 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
6560 conn
->sconn
->ev_ctx
,
6562 if (tevent_req_nomem(subreq
, req
)) {
6570 * Now we add our own waiter to the end of the queue,
6571 * this way we get notified when all pending requests are finished
6572 * and reply to the outstanding SMB1 request.
6574 subreq
= tevent_queue_wait_send(state
,
6575 conn
->sconn
->ev_ctx
,
6577 if (tevent_req_nomem(subreq
, req
)) {
6583 * We're really going async - move the SMB1 request from
6584 * a talloc stackframe above us to the sconn talloc-context.
6585 * We need this to stick around until the wait_done
6586 * callback is invoked.
6588 smb1req
= talloc_move(smb1req
->sconn
, &smb1req
);
6590 tevent_req_set_callback(subreq
, reply_tdis_wait_done
, req
);
6595 static void reply_tdis_wait_done(struct tevent_req
*subreq
)
6597 struct tevent_req
*req
= tevent_req_callback_data(
6598 subreq
, struct tevent_req
);
6600 tevent_queue_wait_recv(subreq
);
6601 TALLOC_FREE(subreq
);
6602 tevent_req_done(req
);
6605 static NTSTATUS
reply_tdis_recv(struct tevent_req
*req
)
6607 return tevent_req_simple_recv_ntstatus(req
);
6610 static void reply_tdis_done(struct tevent_req
*req
)
6612 struct smb_request
*smb1req
= tevent_req_callback_data(
6613 req
, struct smb_request
);
6615 struct smbXsrv_tcon
*tcon
= smb1req
->conn
->tcon
;
6619 * Take the profile charge here. Not strictly
6620 * correct but better than the other SMB1 async
6621 * code that double-charges at the moment.
6623 START_PROFILE(SMBtdis
);
6625 status
= reply_tdis_recv(req
);
6627 if (!NT_STATUS_IS_OK(status
)) {
6628 TALLOC_FREE(smb1req
);
6629 END_PROFILE(SMBtdis
);
6630 exit_server(__location__
": reply_tdis_recv failed");
6635 * As we've been awoken, we may have changed
6636 * directory in the meantime.
6637 * reply_tdis() has the DO_CHDIR flag set.
6639 ok
= chdir_current_service(smb1req
->conn
);
6641 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
6642 smb_request_done(smb1req
);
6643 END_PROFILE(SMBtdis
);
6646 status
= smbXsrv_tcon_disconnect(tcon
,
6648 if (!NT_STATUS_IS_OK(status
)) {
6649 TALLOC_FREE(smb1req
);
6650 END_PROFILE(SMBtdis
);
6651 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
6655 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6656 smb1req
->conn
= NULL
;
6660 reply_outbuf(smb1req
, 0, 0);
6662 * The following call is needed to push the
6663 * reply data back out the socket after async
6664 * return. Plus it frees smb1req.
6666 smb_request_done(smb1req
);
6667 END_PROFILE(SMBtdis
);
6670 /****************************************************************************
6672 conn POINTER CAN BE NULL HERE !
6673 ****************************************************************************/
6675 void reply_echo(struct smb_request
*req
)
6677 connection_struct
*conn
= req
->conn
;
6678 struct smb_perfcount_data local_pcd
;
6679 struct smb_perfcount_data
*cur_pcd
;
6683 START_PROFILE(SMBecho
);
6685 smb_init_perfcount_data(&local_pcd
);
6688 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6689 END_PROFILE(SMBecho
);
6693 smb_reverb
= SVAL(req
->vwv
+0, 0);
6695 reply_outbuf(req
, 1, req
->buflen
);
6697 /* copy any incoming data back out */
6698 if (req
->buflen
> 0) {
6699 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
6702 if (smb_reverb
> 100) {
6703 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
6707 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
6709 /* this makes sure we catch the request pcd */
6710 if (seq_num
== smb_reverb
) {
6711 cur_pcd
= &req
->pcd
;
6713 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
6714 cur_pcd
= &local_pcd
;
6717 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
6719 show_msg((char *)req
->outbuf
);
6720 if (!srv_send_smb(req
->xconn
,
6721 (char *)req
->outbuf
,
6722 true, req
->seqnum
+1,
6723 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
6725 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6728 DEBUG(3,("echo %d times\n", smb_reverb
));
6730 TALLOC_FREE(req
->outbuf
);
6732 END_PROFILE(SMBecho
);
6736 /****************************************************************************
6737 Reply to a printopen.
6738 ****************************************************************************/
6740 void reply_printopen(struct smb_request
*req
)
6742 connection_struct
*conn
= req
->conn
;
6746 START_PROFILE(SMBsplopen
);
6749 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6750 END_PROFILE(SMBsplopen
);
6754 if (!CAN_PRINT(conn
)) {
6755 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6756 END_PROFILE(SMBsplopen
);
6760 status
= file_new(req
, conn
, &fsp
);
6761 if(!NT_STATUS_IS_OK(status
)) {
6762 reply_nterror(req
, status
);
6763 END_PROFILE(SMBsplopen
);
6767 /* Open for exclusive use, write only. */
6768 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
6770 if (!NT_STATUS_IS_OK(status
)) {
6771 file_free(req
, fsp
);
6772 reply_nterror(req
, status
);
6773 END_PROFILE(SMBsplopen
);
6777 reply_outbuf(req
, 1, 0);
6778 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
6780 DEBUG(3,("openprint fd=%d %s\n",
6781 fsp_get_io_fd(fsp
), fsp_fnum_dbg(fsp
)));
6783 END_PROFILE(SMBsplopen
);
6787 /****************************************************************************
6788 Reply to a printclose.
6789 ****************************************************************************/
6791 void reply_printclose(struct smb_request
*req
)
6793 connection_struct
*conn
= req
->conn
;
6797 START_PROFILE(SMBsplclose
);
6800 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6801 END_PROFILE(SMBsplclose
);
6805 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6807 if (!check_fsp(conn
, req
, fsp
)) {
6808 END_PROFILE(SMBsplclose
);
6812 if (!CAN_PRINT(conn
)) {
6813 reply_force_doserror(req
, ERRSRV
, ERRerror
);
6814 END_PROFILE(SMBsplclose
);
6818 DEBUG(3,("printclose fd=%d %s\n",
6819 fsp_get_io_fd(fsp
), fsp_fnum_dbg(fsp
)));
6821 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6823 if(!NT_STATUS_IS_OK(status
)) {
6824 reply_nterror(req
, status
);
6825 END_PROFILE(SMBsplclose
);
6829 reply_outbuf(req
, 0, 0);
6831 END_PROFILE(SMBsplclose
);
6835 /****************************************************************************
6836 Reply to a printqueue.
6837 ****************************************************************************/
6839 void reply_printqueue(struct smb_request
*req
)
6841 const struct loadparm_substitution
*lp_sub
=
6842 loadparm_s3_global_substitution();
6843 connection_struct
*conn
= req
->conn
;
6847 START_PROFILE(SMBsplretq
);
6850 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6851 END_PROFILE(SMBsplretq
);
6855 max_count
= SVAL(req
->vwv
+0, 0);
6856 start_index
= SVAL(req
->vwv
+1, 0);
6858 /* we used to allow the client to get the cnum wrong, but that
6859 is really quite gross and only worked when there was only
6860 one printer - I think we should now only accept it if they
6861 get it right (tridge) */
6862 if (!CAN_PRINT(conn
)) {
6863 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6864 END_PROFILE(SMBsplretq
);
6868 reply_outbuf(req
, 2, 3);
6869 SSVAL(req
->outbuf
,smb_vwv0
,0);
6870 SSVAL(req
->outbuf
,smb_vwv1
,0);
6871 SCVAL(smb_buf(req
->outbuf
),0,1);
6872 SSVAL(smb_buf(req
->outbuf
),1,0);
6874 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6875 start_index
, max_count
));
6878 TALLOC_CTX
*mem_ctx
= talloc_tos();
6881 const char *sharename
= lp_servicename(mem_ctx
, lp_sub
, SNUM(conn
));
6882 struct rpc_pipe_client
*cli
= NULL
;
6883 struct dcerpc_binding_handle
*b
= NULL
;
6884 struct policy_handle handle
;
6885 struct spoolss_DevmodeContainer devmode_ctr
;
6886 union spoolss_JobInfo
*info
;
6888 uint32_t num_to_get
;
6892 ZERO_STRUCT(handle
);
6894 status
= rpc_pipe_open_interface(mem_ctx
,
6897 conn
->sconn
->remote_address
,
6898 conn
->sconn
->local_address
,
6899 conn
->sconn
->msg_ctx
,
6901 if (!NT_STATUS_IS_OK(status
)) {
6902 DEBUG(0, ("reply_printqueue: "
6903 "could not connect to spoolss: %s\n",
6904 nt_errstr(status
)));
6905 reply_nterror(req
, status
);
6908 b
= cli
->binding_handle
;
6910 ZERO_STRUCT(devmode_ctr
);
6912 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
6915 SEC_FLAG_MAXIMUM_ALLOWED
,
6918 if (!NT_STATUS_IS_OK(status
)) {
6919 reply_nterror(req
, status
);
6922 if (!W_ERROR_IS_OK(werr
)) {
6923 reply_nterror(req
, werror_to_ntstatus(werr
));
6927 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
6935 if (!W_ERROR_IS_OK(werr
)) {
6936 reply_nterror(req
, werror_to_ntstatus(werr
));
6940 if (max_count
> 0) {
6941 first
= start_index
;
6943 first
= start_index
+ max_count
+ 1;
6946 if (first
>= count
) {
6949 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6952 for (i
= first
; i
< num_to_get
; i
++) {
6955 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6958 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6959 info
[i
].info2
.job_id
);
6961 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6967 srv_put_dos_date2(p
, 0, qtime
);
6968 SCVAL(p
, 4, qstatus
);
6969 SSVAL(p
, 5, qrapjobid
);
6970 SIVAL(p
, 7, info
[i
].info2
.size
);
6972 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6973 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6974 if (!NT_STATUS_IS_OK(status
)) {
6975 reply_nterror(req
, status
);
6978 if (message_push_blob(
6981 blob
, sizeof(blob
))) == -1) {
6982 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6988 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6989 SSVAL(req
->outbuf
,smb_vwv1
,
6990 (max_count
>0?first
+count
:first
-1));
6991 SCVAL(smb_buf(req
->outbuf
),0,1);
6992 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6996 DEBUG(3, ("%u entries returned in queue\n",
7000 if (b
&& is_valid_policy_hnd(&handle
)) {
7001 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
7006 END_PROFILE(SMBsplretq
);
7010 /****************************************************************************
7011 Reply to a printwrite.
7012 ****************************************************************************/
7014 void reply_printwrite(struct smb_request
*req
)
7016 connection_struct
*conn
= req
->conn
;
7021 START_PROFILE(SMBsplwr
);
7024 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7025 END_PROFILE(SMBsplwr
);
7029 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7031 if (!check_fsp(conn
, req
, fsp
)) {
7032 END_PROFILE(SMBsplwr
);
7036 if (!fsp
->print_file
) {
7037 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7038 END_PROFILE(SMBsplwr
);
7042 if (!CHECK_WRITE(fsp
)) {
7043 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7044 END_PROFILE(SMBsplwr
);
7048 numtowrite
= SVAL(req
->buf
, 1);
7051 * This already protects us against CVE-2017-12163.
7053 if (req
->buflen
< numtowrite
+ 3) {
7054 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7055 END_PROFILE(SMBsplwr
);
7059 data
= (const char *)req
->buf
+ 3;
7061 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
7062 reply_nterror(req
, map_nt_error_from_unix(errno
));
7063 END_PROFILE(SMBsplwr
);
7067 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
7069 reply_outbuf(req
, 0, 0);
7071 END_PROFILE(SMBsplwr
);
7075 /****************************************************************************
7077 ****************************************************************************/
7079 void reply_mkdir(struct smb_request
*req
)
7081 connection_struct
*conn
= req
->conn
;
7082 struct smb_filename
*smb_dname
= NULL
;
7083 char *directory
= NULL
;
7086 TALLOC_CTX
*ctx
= talloc_tos();
7088 START_PROFILE(SMBmkdir
);
7090 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
7091 STR_TERMINATE
, &status
);
7092 if (!NT_STATUS_IS_OK(status
)) {
7093 reply_nterror(req
, status
);
7097 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
7098 status
= filename_convert(ctx
, conn
,
7103 if (!NT_STATUS_IS_OK(status
)) {
7104 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7105 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7106 ERRSRV
, ERRbadpath
);
7109 reply_nterror(req
, status
);
7113 status
= create_directory(conn
, req
, smb_dname
);
7115 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
7117 if (!NT_STATUS_IS_OK(status
)) {
7119 if (!use_nt_status()
7120 && NT_STATUS_EQUAL(status
,
7121 NT_STATUS_OBJECT_NAME_COLLISION
)) {
7123 * Yes, in the DOS error code case we get a
7124 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7125 * samba4 torture test.
7127 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
7130 reply_nterror(req
, status
);
7134 reply_outbuf(req
, 0, 0);
7136 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
7138 TALLOC_FREE(smb_dname
);
7139 END_PROFILE(SMBmkdir
);
7143 /****************************************************************************
7145 ****************************************************************************/
7147 void reply_rmdir(struct smb_request
*req
)
7149 connection_struct
*conn
= req
->conn
;
7150 struct smb_filename
*smb_dname
= NULL
;
7151 char *directory
= NULL
;
7153 TALLOC_CTX
*ctx
= talloc_tos();
7154 files_struct
*fsp
= NULL
;
7156 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
7158 START_PROFILE(SMBrmdir
);
7160 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
7161 STR_TERMINATE
, &status
);
7162 if (!NT_STATUS_IS_OK(status
)) {
7163 reply_nterror(req
, status
);
7167 status
= filename_convert(ctx
, conn
,
7172 if (!NT_STATUS_IS_OK(status
)) {
7173 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7174 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7175 ERRSRV
, ERRbadpath
);
7178 reply_nterror(req
, status
);
7182 if (is_ntfs_stream_smb_fname(smb_dname
)) {
7183 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
7187 status
= SMB_VFS_CREATE_FILE(
7190 smb_dname
, /* fname */
7191 DELETE_ACCESS
, /* access_mask */
7192 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7194 FILE_OPEN
, /* create_disposition*/
7195 FILE_DIRECTORY_FILE
, /* create_options */
7196 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
7197 0, /* oplock_request */
7199 0, /* allocation_size */
7200 0, /* private_flags */
7205 NULL
, NULL
); /* create context */
7207 if (!NT_STATUS_IS_OK(status
)) {
7208 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7209 /* We have re-scheduled this call. */
7212 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
7213 bool ok
= defer_smb1_sharing_violation(req
);
7218 reply_nterror(req
, status
);
7222 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
7223 if (!NT_STATUS_IS_OK(status
)) {
7224 close_file(req
, fsp
, ERROR_CLOSE
);
7225 reply_nterror(req
, status
);
7229 if (!set_delete_on_close(fsp
, true,
7230 conn
->session_info
->security_token
,
7231 conn
->session_info
->unix_token
)) {
7232 close_file(req
, fsp
, ERROR_CLOSE
);
7233 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
7237 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
7238 if (!NT_STATUS_IS_OK(status
)) {
7239 reply_nterror(req
, status
);
7241 reply_outbuf(req
, 0, 0);
7244 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
7246 TALLOC_FREE(smb_dname
);
7247 END_PROFILE(SMBrmdir
);
7251 /*******************************************************************
7252 Resolve wildcards in a filename rename.
7253 ********************************************************************/
7255 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
7260 char *name2_copy
= NULL
;
7265 char *p
,*p2
, *pname1
, *pname2
;
7267 name2_copy
= talloc_strdup(ctx
, name2
);
7272 pname1
= strrchr_m(name1
,'/');
7273 pname2
= strrchr_m(name2_copy
,'/');
7275 if (!pname1
|| !pname2
) {
7279 /* Truncate the copy of name2 at the last '/' */
7282 /* Now go past the '/' */
7286 root1
= talloc_strdup(ctx
, pname1
);
7287 root2
= talloc_strdup(ctx
, pname2
);
7289 if (!root1
|| !root2
) {
7293 p
= strrchr_m(root1
,'.');
7296 ext1
= talloc_strdup(ctx
, p
+1);
7298 ext1
= talloc_strdup(ctx
, "");
7300 p
= strrchr_m(root2
,'.');
7303 ext2
= talloc_strdup(ctx
, p
+1);
7305 ext2
= talloc_strdup(ctx
, "");
7308 if (!ext1
|| !ext2
) {
7316 /* Hmmm. Should this be mb-aware ? */
7319 } else if (*p2
== '*') {
7321 root2
= talloc_asprintf(ctx
, "%s%s",
7340 /* Hmmm. Should this be mb-aware ? */
7343 } else if (*p2
== '*') {
7345 ext2
= talloc_asprintf(ctx
, "%s%s",
7361 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
7366 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
7378 /****************************************************************************
7379 Ensure open files have their names updated. Updated to notify other smbd's
7381 ****************************************************************************/
7383 static void rename_open_files(connection_struct
*conn
,
7384 struct share_mode_lock
*lck
,
7386 uint32_t orig_name_hash
,
7387 const struct smb_filename
*smb_fname_dst
)
7390 bool did_rename
= False
;
7392 uint32_t new_name_hash
= 0;
7394 for(fsp
= file_find_di_first(conn
->sconn
, id
, false); fsp
;
7395 fsp
= file_find_di_next(fsp
, false)) {
7396 struct file_id_buf idbuf
;
7397 /* fsp_name is a relative path under the fsp. To change this for other
7398 sharepaths we need to manipulate relative paths. */
7399 /* TODO - create the absolute path and manipulate the newname
7400 relative to the sharepath. */
7401 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
7404 if (fsp
->name_hash
!= orig_name_hash
) {
7407 DBG_DEBUG("renaming file %s "
7408 "(file_id %s) from %s -> %s\n",
7410 file_id_str_buf(fsp
->file_id
, &idbuf
),
7412 smb_fname_str_dbg(smb_fname_dst
));
7414 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
7415 if (NT_STATUS_IS_OK(status
)) {
7417 new_name_hash
= fsp
->name_hash
;
7422 struct file_id_buf idbuf
;
7423 DBG_DEBUG("no open files on file_id %s "
7425 file_id_str_buf(id
, &idbuf
),
7426 smb_fname_str_dbg(smb_fname_dst
));
7429 /* Send messages to all smbd's (not ourself) that the name has changed. */
7430 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
7431 orig_name_hash
, new_name_hash
,
7436 /****************************************************************************
7437 We need to check if the source path is a parent directory of the destination
7438 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7439 refuse the rename with a sharing violation. Under UNIX the above call can
7440 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7441 probably need to check that the client is a Windows one before disallowing
7442 this as a UNIX client (one with UNIX extensions) can know the source is a
7443 symlink and make this decision intelligently. Found by an excellent bug
7444 report from <AndyLiebman@aol.com>.
7445 ****************************************************************************/
7447 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
7448 const struct smb_filename
*smb_fname_dst
)
7450 const char *psrc
= smb_fname_src
->base_name
;
7451 const char *pdst
= smb_fname_dst
->base_name
;
7454 if (psrc
[0] == '.' && psrc
[1] == '/') {
7457 if (pdst
[0] == '.' && pdst
[1] == '/') {
7460 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
7463 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
7467 * Do the notify calls from a rename
7470 static void notify_rename(connection_struct
*conn
, bool is_dir
,
7471 const struct smb_filename
*smb_fname_src
,
7472 const struct smb_filename
*smb_fname_dst
)
7474 char *parent_dir_src
= NULL
;
7475 char *parent_dir_dst
= NULL
;
7478 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
7479 : FILE_NOTIFY_CHANGE_FILE_NAME
;
7481 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
7482 &parent_dir_src
, NULL
) ||
7483 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
7484 &parent_dir_dst
, NULL
)) {
7488 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
7489 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
7490 smb_fname_src
->base_name
);
7491 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
7492 smb_fname_dst
->base_name
);
7495 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
7496 smb_fname_src
->base_name
);
7497 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
7498 smb_fname_dst
->base_name
);
7501 /* this is a strange one. w2k3 gives an additional event for
7502 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7503 files, but not directories */
7505 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7506 FILE_NOTIFY_CHANGE_ATTRIBUTES
7507 |FILE_NOTIFY_CHANGE_CREATION
,
7508 smb_fname_dst
->base_name
);
7511 TALLOC_FREE(parent_dir_src
);
7512 TALLOC_FREE(parent_dir_dst
);
7515 /****************************************************************************
7516 Returns an error if the parent directory for a filename is open in an
7518 ****************************************************************************/
7520 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
7521 const struct smb_filename
*smb_fname_dst_in
)
7523 struct smb_filename
*smb_fname_parent
= NULL
;
7525 files_struct
*fsp
= NULL
;
7529 status
= SMB_VFS_PARENT_PATHNAME(conn
,
7534 if (!NT_STATUS_IS_OK(status
)) {
7538 ret
= SMB_VFS_LSTAT(conn
, smb_fname_parent
);
7540 return map_nt_error_from_unix(errno
);
7544 * We're only checking on this smbd here, mostly good
7545 * enough.. and will pass tests.
7548 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
->st
);
7549 for (fsp
= file_find_di_first(conn
->sconn
, id
, true); fsp
;
7550 fsp
= file_find_di_next(fsp
, true)) {
7551 if (fsp
->access_mask
& DELETE_ACCESS
) {
7552 return NT_STATUS_SHARING_VIOLATION
;
7555 return NT_STATUS_OK
;
7558 /****************************************************************************
7559 Rename an open file - given an fsp.
7560 ****************************************************************************/
7562 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
7564 struct smb_filename
*smb_fname_dst_in
,
7565 const char *dst_original_lcomp
,
7567 bool replace_if_exists
)
7569 TALLOC_CTX
*ctx
= talloc_tos();
7570 struct smb_filename
*parent_dir_fname_dst
= NULL
;
7571 struct smb_filename
*parent_dir_fname_dst_atname
= NULL
;
7572 struct smb_filename
*smb_fname_dst
= NULL
;
7573 NTSTATUS status
= NT_STATUS_OK
;
7574 struct share_mode_lock
*lck
= NULL
;
7575 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
7576 bool dst_exists
, old_is_stream
, new_is_stream
;
7579 status
= check_name(conn
, smb_fname_dst_in
);
7580 if (!NT_STATUS_IS_OK(status
)) {
7584 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
7585 if (!NT_STATUS_IS_OK(status
)) {
7589 if (file_has_open_streams(fsp
)) {
7590 return NT_STATUS_ACCESS_DENIED
;
7593 /* Make a copy of the dst smb_fname structs */
7595 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
7596 if (smb_fname_dst
== NULL
) {
7597 status
= NT_STATUS_NO_MEMORY
;
7602 * Check for special case with case preserving and not
7603 * case sensitive. If the new last component differs from the original
7604 * last component only by case, then we should allow
7605 * the rename (user is trying to change the case of the
7608 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
7609 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
7610 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
7611 char *fname_dst_parent
= NULL
;
7612 const char *fname_dst_lcomp
= NULL
;
7613 char *orig_lcomp_path
= NULL
;
7614 char *orig_lcomp_stream
= NULL
;
7618 * Split off the last component of the processed
7619 * destination name. We will compare this to
7620 * the split components of dst_original_lcomp.
7622 if (!parent_dirname(ctx
,
7623 smb_fname_dst
->base_name
,
7625 &fname_dst_lcomp
)) {
7626 status
= NT_STATUS_NO_MEMORY
;
7631 * The dst_original_lcomp component contains
7632 * the last_component of the path + stream
7633 * name (if a stream exists).
7635 * Split off the stream name so we
7636 * can check them separately.
7639 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
7640 /* POSIX - no stream component. */
7641 orig_lcomp_path
= talloc_strdup(ctx
,
7642 dst_original_lcomp
);
7643 if (orig_lcomp_path
== NULL
) {
7647 ok
= split_stream_filename(ctx
,
7650 &orig_lcomp_stream
);
7654 TALLOC_FREE(fname_dst_parent
);
7655 status
= NT_STATUS_NO_MEMORY
;
7659 /* If the base names only differ by case, use original. */
7660 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
7663 * Replace the modified last component with the
7666 if (!ISDOT(fname_dst_parent
)) {
7667 tmp
= talloc_asprintf(smb_fname_dst
,
7672 tmp
= talloc_strdup(smb_fname_dst
,
7676 status
= NT_STATUS_NO_MEMORY
;
7677 TALLOC_FREE(fname_dst_parent
);
7678 TALLOC_FREE(orig_lcomp_path
);
7679 TALLOC_FREE(orig_lcomp_stream
);
7682 TALLOC_FREE(smb_fname_dst
->base_name
);
7683 smb_fname_dst
->base_name
= tmp
;
7686 /* If the stream_names only differ by case, use original. */
7687 if(!strcsequal(smb_fname_dst
->stream_name
,
7688 orig_lcomp_stream
)) {
7689 /* Use the original stream. */
7690 char *tmp
= talloc_strdup(smb_fname_dst
,
7693 status
= NT_STATUS_NO_MEMORY
;
7694 TALLOC_FREE(fname_dst_parent
);
7695 TALLOC_FREE(orig_lcomp_path
);
7696 TALLOC_FREE(orig_lcomp_stream
);
7699 TALLOC_FREE(smb_fname_dst
->stream_name
);
7700 smb_fname_dst
->stream_name
= tmp
;
7702 TALLOC_FREE(fname_dst_parent
);
7703 TALLOC_FREE(orig_lcomp_path
);
7704 TALLOC_FREE(orig_lcomp_stream
);
7708 * If the src and dest names are identical - including case,
7709 * don't do the rename, just return success.
7712 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
7713 strcsequal(fsp
->fsp_name
->stream_name
,
7714 smb_fname_dst
->stream_name
)) {
7715 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7716 "- returning success\n",
7717 smb_fname_str_dbg(smb_fname_dst
)));
7718 status
= NT_STATUS_OK
;
7722 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
7723 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
7725 /* Return the correct error code if both names aren't streams. */
7726 if (!old_is_stream
&& new_is_stream
) {
7727 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7731 if (old_is_stream
&& !new_is_stream
) {
7732 status
= NT_STATUS_INVALID_PARAMETER
;
7736 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
7738 if(!replace_if_exists
&& dst_exists
) {
7739 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7740 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
7741 smb_fname_str_dbg(smb_fname_dst
)));
7742 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
7747 * Drop the pathref fsp on the destination otherwise we trip upon in in
7748 * the below check for open files check.
7750 if (smb_fname_dst_in
->fsp
!= NULL
) {
7751 fd_close(smb_fname_dst_in
->fsp
);
7752 file_free(NULL
, smb_fname_dst_in
->fsp
);
7753 SMB_ASSERT(smb_fname_dst_in
->fsp
== NULL
);
7757 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
7758 &smb_fname_dst
->st
);
7759 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
7761 /* The file can be open when renaming a stream */
7762 if (dst_fsp
&& !new_is_stream
) {
7763 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7764 status
= NT_STATUS_ACCESS_DENIED
;
7769 /* Ensure we have a valid stat struct for the source. */
7770 status
= vfs_stat_fsp(fsp
);
7771 if (!NT_STATUS_IS_OK(status
)) {
7775 status
= can_rename(conn
, fsp
, attrs
);
7777 if (!NT_STATUS_IS_OK(status
)) {
7778 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7779 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
7780 smb_fname_str_dbg(smb_fname_dst
)));
7781 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
7782 status
= NT_STATUS_ACCESS_DENIED
;
7786 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
7787 status
= NT_STATUS_ACCESS_DENIED
;
7791 /* Do we have rights to move into the destination ? */
7792 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
7793 /* We're moving a directory. */
7794 access_mask
= SEC_DIR_ADD_SUBDIR
;
7798 * Get a pathref on the parent directory, so
7799 * we can call check_parent_access_fsp().
7801 status
= parent_pathref(ctx
,
7804 &parent_dir_fname_dst
,
7805 &parent_dir_fname_dst_atname
);
7806 if (!NT_STATUS_IS_OK(status
)) {
7810 status
= check_parent_access_fsp(parent_dir_fname_dst
->fsp
,
7812 if (!NT_STATUS_IS_OK(status
)) {
7813 DBG_INFO("check_parent_access_fsp on "
7814 "dst %s returned %s\n",
7815 smb_fname_str_dbg(smb_fname_dst
),
7820 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7823 * We have the file open ourselves, so not being able to get the
7824 * corresponding share mode lock is a fatal error.
7827 SMB_ASSERT(lck
!= NULL
);
7829 ret
= SMB_VFS_RENAMEAT(conn
,
7835 uint32_t create_options
= fh_get_private_options(fsp
->fh
);
7837 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7838 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
7839 smb_fname_str_dbg(smb_fname_dst
)));
7842 fsp
->fsp_flags
.is_directory
,
7846 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
7849 if (!fsp
->fsp_flags
.is_directory
&&
7850 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
7851 (lp_map_archive(SNUM(conn
)) ||
7852 lp_store_dos_attributes(SNUM(conn
))))
7855 * We must set the archive bit on the newly renamed
7858 ret
= SMB_VFS_FSTAT(fsp
, &fsp
->fsp_name
->st
);
7860 uint32_t old_dosmode
;
7861 old_dosmode
= fdos_mode(fsp
);
7863 * We can use fsp->fsp_name here as it has
7864 * already been changed to the new name.
7866 SMB_ASSERT(fsp
->fsp_name
->fsp
== fsp
);
7867 file_set_dosmode(conn
,
7869 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
7876 * A rename acts as a new file create w.r.t. allowing an initial delete
7877 * on close, probably because in Windows there is a new handle to the
7878 * new file. If initial delete on close was requested but not
7879 * originally set, we need to set it here. This is probably not 100% correct,
7880 * but will work for the CIFSFS client which in non-posix mode
7881 * depends on these semantics. JRA.
7884 if (create_options
& FILE_DELETE_ON_CLOSE
) {
7885 status
= can_set_delete_on_close(fsp
, 0);
7887 if (NT_STATUS_IS_OK(status
)) {
7888 /* Note that here we set the *initial* delete on close flag,
7889 * not the regular one. The magic gets handled in close. */
7890 fsp
->fsp_flags
.initial_delete_on_close
= true;
7894 status
= NT_STATUS_OK
;
7900 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
7901 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
7903 status
= map_nt_error_from_unix(errno
);
7906 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7907 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
7908 smb_fname_str_dbg(smb_fname_dst
)));
7911 TALLOC_FREE(smb_fname_dst
);
7916 /****************************************************************************
7917 The guts of the rename command, split out so it may be called by the NT SMB
7919 ****************************************************************************/
7921 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
7922 connection_struct
*conn
,
7923 struct smb_request
*req
,
7924 struct smb_filename
*smb_fname_src
,
7925 const char *src_original_lcomp
,
7926 struct smb_filename
*smb_fname_dst
,
7927 const char *dst_original_lcomp
,
7929 bool replace_if_exists
,
7930 uint32_t access_mask
)
7932 char *fname_src_dir
= NULL
;
7933 struct smb_filename
*smb_fname_src_dir
= NULL
;
7934 char *fname_src_mask
= NULL
;
7936 NTSTATUS status
= NT_STATUS_OK
;
7937 struct smb_Dir
*dir_hnd
= NULL
;
7938 const char *dname
= NULL
;
7939 char *talloced
= NULL
;
7941 int create_options
= 0;
7942 struct smb2_create_blobs
*posx
= NULL
;
7944 bool src_has_wild
= false;
7945 bool dest_has_wild
= false;
7948 * Split the old name into directory and last component
7949 * strings. Note that unix_convert may have stripped off a
7950 * leading ./ from both name and newname if the rename is
7951 * at the root of the share. We need to make sure either both
7952 * name and newname contain a / character or neither of them do
7953 * as this is checked in resolve_wildcards().
7956 /* Split up the directory from the filename/mask. */
7957 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7958 &fname_src_dir
, &fname_src_mask
);
7959 if (!NT_STATUS_IS_OK(status
)) {
7960 status
= NT_STATUS_NO_MEMORY
;
7964 if (!(smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
)) {
7966 * Check the wildcard mask *before*
7967 * unmangling. As mangling is done
7968 * for names that can't be returned
7969 * to Windows the unmangled name may
7970 * contain Windows wildcard characters.
7972 if (src_original_lcomp
!= NULL
) {
7973 src_has_wild
= ms_has_wild(src_original_lcomp
);
7975 dest_has_wild
= ms_has_wild(dst_original_lcomp
);
7979 * We should only check the mangled cache
7980 * here if unix_convert failed. This means
7981 * that the path in 'mask' doesn't exist
7982 * on the file system and so we need to look
7983 * for a possible mangle. This patch from
7984 * Tine Smukavec <valentin.smukavec@hermes.si>.
7987 if (!VALID_STAT(smb_fname_src
->st
) &&
7988 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7989 char *new_mask
= NULL
;
7990 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
7993 TALLOC_FREE(fname_src_mask
);
7994 fname_src_mask
= new_mask
;
7998 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
7999 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
8000 if (!NT_STATUS_IS_OK(status
)) {
8001 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8007 if (!src_has_wild
) {
8011 * Only one file needs to be renamed. Append the mask back
8012 * onto the directory.
8014 TALLOC_FREE(smb_fname_src
->base_name
);
8015 if (ISDOT(fname_src_dir
)) {
8016 /* Ensure we use canonical names on open. */
8017 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8021 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8026 if (!smb_fname_src
->base_name
) {
8027 status
= NT_STATUS_NO_MEMORY
;
8031 DEBUG(3, ("rename_internals: case_sensitive = %d, "
8032 "case_preserve = %d, short case preserve = %d, "
8033 "directory = %s, newname = %s, "
8034 "last_component_dest = %s\n",
8035 conn
->case_sensitive
, conn
->case_preserve
,
8036 conn
->short_case_preserve
,
8037 smb_fname_str_dbg(smb_fname_src
),
8038 smb_fname_str_dbg(smb_fname_dst
),
8039 dst_original_lcomp
));
8041 /* The dest name still may have wildcards. */
8042 if (dest_has_wild
) {
8043 char *fname_dst_mod
= NULL
;
8044 if (!resolve_wildcards(smb_fname_dst
,
8045 smb_fname_src
->base_name
,
8046 smb_fname_dst
->base_name
,
8048 DEBUG(6, ("rename_internals: resolve_wildcards "
8050 smb_fname_src
->base_name
,
8051 smb_fname_dst
->base_name
));
8052 status
= NT_STATUS_NO_MEMORY
;
8055 TALLOC_FREE(smb_fname_dst
->base_name
);
8056 smb_fname_dst
->base_name
= fname_dst_mod
;
8059 ZERO_STRUCT(smb_fname_src
->st
);
8061 rc
= vfs_stat(conn
, smb_fname_src
);
8063 status
= map_nt_error_from_unix_common(errno
);
8067 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_src
);
8068 if (!NT_STATUS_IS_OK(status
)) {
8069 if (!NT_STATUS_EQUAL(status
,
8070 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
8074 * Possible symlink src.
8076 if (!(smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
)) {
8079 if (!S_ISLNK(smb_fname_src
->st
.st_ex_mode
)) {
8084 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
8085 create_options
|= FILE_DIRECTORY_FILE
;
8088 status
= SMB_VFS_CREATE_FILE(
8091 smb_fname_src
, /* fname */
8092 access_mask
, /* access_mask */
8093 (FILE_SHARE_READ
| /* share_access */
8095 FILE_OPEN
, /* create_disposition*/
8096 create_options
, /* create_options */
8097 0, /* file_attributes */
8098 0, /* oplock_request */
8100 0, /* allocation_size */
8101 0, /* private_flags */
8106 posx
, /* in_context_blobs */
8107 NULL
); /* out_context_blobs */
8109 if (!NT_STATUS_IS_OK(status
)) {
8110 DEBUG(3, ("Could not open rename source %s: %s\n",
8111 smb_fname_str_dbg(smb_fname_src
),
8112 nt_errstr(status
)));
8116 status
= rename_internals_fsp(conn
,
8123 close_file(req
, fsp
, NORMAL_CLOSE
);
8125 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
8126 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
8127 smb_fname_str_dbg(smb_fname_dst
)));
8133 * Wildcards - process each file that matches.
8135 if (strequal(fname_src_mask
, "????????.???")) {
8136 TALLOC_FREE(fname_src_mask
);
8137 fname_src_mask
= talloc_strdup(ctx
, "*");
8138 if (!fname_src_mask
) {
8139 status
= NT_STATUS_NO_MEMORY
;
8144 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
8148 smb_fname_src
->twrp
,
8149 smb_fname_src
->flags
);
8150 if (smb_fname_src_dir
== NULL
) {
8151 status
= NT_STATUS_NO_MEMORY
;
8155 status
= check_name(conn
, smb_fname_src_dir
);
8156 if (!NT_STATUS_IS_OK(status
)) {
8160 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
8162 if (dir_hnd
== NULL
) {
8163 status
= map_nt_error_from_unix(errno
);
8167 status
= NT_STATUS_NO_SUCH_FILE
;
8169 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8170 * - gentest fix. JRA
8173 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
8175 files_struct
*fsp
= NULL
;
8176 char *destname
= NULL
;
8177 bool sysdir_entry
= False
;
8179 /* Quick check for "." and ".." */
8180 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
8181 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
8182 sysdir_entry
= True
;
8184 TALLOC_FREE(talloced
);
8189 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
8190 TALLOC_FREE(talloced
);
8195 status
= NT_STATUS_OBJECT_NAME_INVALID
;
8199 TALLOC_FREE(smb_fname_src
->base_name
);
8200 if (ISDOT(fname_src_dir
)) {
8201 /* Ensure we use canonical names on open. */
8202 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8206 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8211 if (!smb_fname_src
->base_name
) {
8212 status
= NT_STATUS_NO_MEMORY
;
8216 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
8217 smb_fname_dst
->base_name
,
8219 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8220 smb_fname_src
->base_name
, destname
));
8221 TALLOC_FREE(talloced
);
8225 status
= NT_STATUS_NO_MEMORY
;
8229 TALLOC_FREE(smb_fname_dst
->base_name
);
8230 smb_fname_dst
->base_name
= destname
;
8232 ZERO_STRUCT(smb_fname_src
->st
);
8233 vfs_stat(conn
, smb_fname_src
);
8235 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_src
);
8236 if (!NT_STATUS_IS_OK(status
)) {
8237 DBG_INFO("openat_pathref_fsp [%s] failed: %s\n",
8238 smb_fname_str_dbg(smb_fname_src
),
8243 if (!is_visible_fsp(smb_fname_src
->fsp
)) {
8244 TALLOC_FREE(talloced
);
8250 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
8251 create_options
|= FILE_DIRECTORY_FILE
;
8254 status
= SMB_VFS_CREATE_FILE(
8257 smb_fname_src
, /* fname */
8258 access_mask
, /* access_mask */
8259 (FILE_SHARE_READ
| /* share_access */
8261 FILE_OPEN
, /* create_disposition*/
8262 create_options
, /* create_options */
8263 0, /* file_attributes */
8264 0, /* oplock_request */
8266 0, /* allocation_size */
8267 0, /* private_flags */
8272 posx
, /* in_context_blobs */
8273 NULL
); /* out_context_blobs */
8275 if (!NT_STATUS_IS_OK(status
)) {
8276 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8277 "returned %s rename %s -> %s\n",
8279 smb_fname_str_dbg(smb_fname_src
),
8280 smb_fname_str_dbg(smb_fname_dst
)));
8284 dst_original_lcomp
= talloc_strdup(smb_fname_dst
, dname
);
8285 if (dst_original_lcomp
== NULL
) {
8286 status
= NT_STATUS_NO_MEMORY
;
8290 status
= rename_internals_fsp(conn
,
8297 close_file(req
, fsp
, NORMAL_CLOSE
);
8299 if (!NT_STATUS_IS_OK(status
)) {
8300 DEBUG(3, ("rename_internals_fsp returned %s for "
8301 "rename %s -> %s\n", nt_errstr(status
),
8302 smb_fname_str_dbg(smb_fname_src
),
8303 smb_fname_str_dbg(smb_fname_dst
)));
8309 DEBUG(3,("rename_internals: doing rename on %s -> "
8310 "%s\n", smb_fname_str_dbg(smb_fname_src
),
8311 smb_fname_str_dbg(smb_fname_src
)));
8312 TALLOC_FREE(talloced
);
8314 TALLOC_FREE(dir_hnd
);
8316 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
8317 status
= map_nt_error_from_unix(errno
);
8322 TALLOC_FREE(talloced
);
8323 TALLOC_FREE(smb_fname_src_dir
);
8324 TALLOC_FREE(fname_src_dir
);
8325 TALLOC_FREE(fname_src_mask
);
8329 /****************************************************************************
8331 ****************************************************************************/
8333 void reply_mv(struct smb_request
*req
)
8335 connection_struct
*conn
= req
->conn
;
8337 char *newname
= NULL
;
8341 TALLOC_CTX
*ctx
= talloc_tos();
8342 struct smb_filename
*smb_fname_src
= NULL
;
8343 const char *src_original_lcomp
= NULL
;
8344 struct smb_filename
*smb_fname_dst
= NULL
;
8345 const char *dst_original_lcomp
= NULL
;
8346 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
) |
8347 (!req
->posix_pathnames
? UCF_ALWAYS_ALLOW_WCARD_LCOMP
: 0);
8348 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
) |
8349 (!req
->posix_pathnames
? UCF_ALWAYS_ALLOW_WCARD_LCOMP
: 0);
8350 bool stream_rename
= false;
8352 START_PROFILE(SMBmv
);
8355 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8359 attrs
= SVAL(req
->vwv
+0, 0);
8361 p
= (const char *)req
->buf
+ 1;
8362 p
+= srvstr_get_path_req(ctx
, req
, &name
, p
, STR_TERMINATE
,
8364 if (!NT_STATUS_IS_OK(status
)) {
8365 reply_nterror(req
, status
);
8369 p
+= srvstr_get_path_req(ctx
, req
, &newname
, p
, STR_TERMINATE
,
8371 if (!NT_STATUS_IS_OK(status
)) {
8372 reply_nterror(req
, status
);
8376 if (!req
->posix_pathnames
) {
8377 /* The newname must begin with a ':' if the
8378 name contains a ':'. */
8379 if (strchr_m(name
, ':')) {
8380 if (newname
[0] != ':') {
8381 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8384 stream_rename
= true;
8388 status
= filename_convert(ctx
,
8395 if (!NT_STATUS_IS_OK(status
)) {
8396 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8397 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8398 ERRSRV
, ERRbadpath
);
8401 reply_nterror(req
, status
);
8405 /* Get the last component of the source for rename_internals(). */
8406 src_original_lcomp
= get_original_lcomp(ctx
,
8410 if (src_original_lcomp
== NULL
) {
8411 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8415 status
= filename_convert(ctx
,
8422 if (!NT_STATUS_IS_OK(status
)) {
8423 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8424 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8425 ERRSRV
, ERRbadpath
);
8428 reply_nterror(req
, status
);
8432 /* Get the last component of the destination for rename_internals(). */
8433 dst_original_lcomp
= get_original_lcomp(ctx
,
8437 if (dst_original_lcomp
== NULL
) {
8438 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8442 if (stream_rename
) {
8443 /* smb_fname_dst->base_name must be the same as
8444 smb_fname_src->base_name. */
8445 TALLOC_FREE(smb_fname_dst
->base_name
);
8446 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
8447 smb_fname_src
->base_name
);
8448 if (!smb_fname_dst
->base_name
) {
8449 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8454 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
8455 smb_fname_str_dbg(smb_fname_dst
)));
8457 status
= rename_internals(ctx
,
8467 if (!NT_STATUS_IS_OK(status
)) {
8468 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8469 /* We have re-scheduled this call. */
8472 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
8473 bool ok
= defer_smb1_sharing_violation(req
);
8478 reply_nterror(req
, status
);
8482 reply_outbuf(req
, 0, 0);
8484 TALLOC_FREE(smb_fname_src
);
8485 TALLOC_FREE(smb_fname_dst
);
8490 /*******************************************************************
8491 Copy a file as part of a reply_copy.
8492 ******************************************************************/
8495 * TODO: check error codes on all callers
8498 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
8499 connection_struct
*conn
,
8500 struct smb_filename
*smb_fname_src
,
8501 struct smb_filename
*smb_fname_dst
,
8504 bool target_is_directory
)
8506 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
8508 files_struct
*fsp1
,*fsp2
;
8510 uint32_t new_create_disposition
;
8514 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
8515 if (smb_fname_dst_tmp
== NULL
) {
8516 return NT_STATUS_NO_MEMORY
;
8520 * If the target is a directory, extract the last component from the
8521 * src filename and append it to the dst filename
8523 if (target_is_directory
) {
8526 /* dest/target can't be a stream if it's a directory. */
8527 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
8529 p
= strrchr_m(smb_fname_src
->base_name
,'/');
8533 p
= smb_fname_src
->base_name
;
8535 smb_fname_dst_tmp
->base_name
=
8536 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
8538 if (!smb_fname_dst_tmp
->base_name
) {
8539 status
= NT_STATUS_NO_MEMORY
;
8544 status
= vfs_file_exist(conn
, smb_fname_src
);
8545 if (!NT_STATUS_IS_OK(status
)) {
8549 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_src
);
8550 if (!NT_STATUS_IS_OK(status
)) {
8554 if (!target_is_directory
&& count
) {
8555 new_create_disposition
= FILE_OPEN
;
8557 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
8560 &new_create_disposition
,
8563 status
= NT_STATUS_INVALID_PARAMETER
;
8568 /* Open the src file for reading. */
8569 status
= SMB_VFS_CREATE_FILE(
8572 smb_fname_src
, /* fname */
8573 FILE_GENERIC_READ
, /* access_mask */
8574 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
8575 FILE_OPEN
, /* create_disposition*/
8576 0, /* create_options */
8577 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
8578 INTERNAL_OPEN_ONLY
, /* oplock_request */
8580 0, /* allocation_size */
8581 0, /* private_flags */
8586 NULL
, NULL
); /* create context */
8588 if (!NT_STATUS_IS_OK(status
)) {
8592 dosattrs
= fdos_mode(fsp1
);
8594 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
8595 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
8598 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_dst
);
8599 if (!NT_STATUS_IS_OK(status
) &&
8600 !NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
))
8605 /* Open the dst file for writing. */
8606 status
= SMB_VFS_CREATE_FILE(
8609 smb_fname_dst
, /* fname */
8610 FILE_GENERIC_WRITE
, /* access_mask */
8611 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
8612 new_create_disposition
, /* create_disposition*/
8613 0, /* create_options */
8614 dosattrs
, /* file_attributes */
8615 INTERNAL_OPEN_ONLY
, /* oplock_request */
8617 0, /* allocation_size */
8618 0, /* private_flags */
8623 NULL
, NULL
); /* create context */
8625 if (!NT_STATUS_IS_OK(status
)) {
8626 close_file(NULL
, fsp1
, ERROR_CLOSE
);
8630 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
8631 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
8633 DEBUG(0, ("error - vfs lseek returned error %s\n",
8635 status
= map_nt_error_from_unix(errno
);
8636 close_file(NULL
, fsp1
, ERROR_CLOSE
);
8637 close_file(NULL
, fsp2
, ERROR_CLOSE
);
8642 /* Do the actual copy. */
8643 if (smb_fname_src
->st
.st_ex_size
) {
8644 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
8649 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
8651 /* Ensure the modtime is set correctly on the destination file. */
8652 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
8655 * As we are opening fsp1 read-only we only expect
8656 * an error on close on fsp2 if we are out of space.
8657 * Thus we don't look at the error return from the
8660 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
8662 if (!NT_STATUS_IS_OK(status
)) {
8666 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
8667 status
= NT_STATUS_DISK_FULL
;
8671 status
= NT_STATUS_OK
;
8674 TALLOC_FREE(smb_fname_dst_tmp
);
8678 /****************************************************************************
8679 Reply to a file copy.
8680 ****************************************************************************/
8682 void reply_copy(struct smb_request
*req
)
8684 connection_struct
*conn
= req
->conn
;
8685 struct smb_filename
*smb_fname_src
= NULL
;
8686 struct smb_filename
*smb_fname_src_dir
= NULL
;
8687 struct smb_filename
*smb_fname_dst
= NULL
;
8688 char *fname_src
= NULL
;
8689 char *fname_dst
= NULL
;
8690 char *fname_src_mask
= NULL
;
8691 char *fname_src_dir
= NULL
;
8694 int error
= ERRnoaccess
;
8698 bool target_is_directory
=False
;
8699 bool source_has_wild
= False
;
8700 bool dest_has_wild
= False
;
8702 uint32_t ucf_flags_src
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
8703 ucf_flags_from_smb_request(req
);
8704 uint32_t ucf_flags_dst
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
8705 ucf_flags_from_smb_request(req
);
8706 TALLOC_CTX
*ctx
= talloc_tos();
8708 START_PROFILE(SMBcopy
);
8711 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8715 tid2
= SVAL(req
->vwv
+0, 0);
8716 ofun
= SVAL(req
->vwv
+1, 0);
8717 flags
= SVAL(req
->vwv
+2, 0);
8719 p
= (const char *)req
->buf
;
8720 p
+= srvstr_get_path_req(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
8722 if (!NT_STATUS_IS_OK(status
)) {
8723 reply_nterror(req
, status
);
8726 p
+= srvstr_get_path_req(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
8728 if (!NT_STATUS_IS_OK(status
)) {
8729 reply_nterror(req
, status
);
8733 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
8735 if (tid2
!= conn
->cnum
) {
8736 /* can't currently handle inter share copies XXXX */
8737 DEBUG(3,("Rejecting inter-share copy\n"));
8738 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
8742 status
= filename_convert(ctx
, conn
,
8747 if (!NT_STATUS_IS_OK(status
)) {
8748 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8749 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8750 ERRSRV
, ERRbadpath
);
8753 reply_nterror(req
, status
);
8757 status
= filename_convert(ctx
, conn
,
8762 if (!NT_STATUS_IS_OK(status
)) {
8763 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8764 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8765 ERRSRV
, ERRbadpath
);
8768 reply_nterror(req
, status
);
8772 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
8774 if ((flags
&1) && target_is_directory
) {
8775 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
8779 if ((flags
&2) && !target_is_directory
) {
8780 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8784 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
8785 /* wants a tree copy! XXXX */
8786 DEBUG(3,("Rejecting tree copy\n"));
8787 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8791 /* Split up the directory from the filename/mask. */
8792 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
8793 &fname_src_dir
, &fname_src_mask
);
8794 if (!NT_STATUS_IS_OK(status
)) {
8795 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8799 if (!req
->posix_pathnames
) {
8800 char *orig_src_lcomp
= NULL
;
8801 char *orig_dst_lcomp
= NULL
;
8803 * Check the wildcard mask *before*
8804 * unmangling. As mangling is done
8805 * for names that can't be returned
8806 * to Windows the unmangled name may
8807 * contain Windows wildcard characters.
8809 orig_src_lcomp
= get_original_lcomp(ctx
,
8813 if (orig_src_lcomp
== NULL
) {
8814 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8817 orig_dst_lcomp
= get_original_lcomp(ctx
,
8821 if (orig_dst_lcomp
== NULL
) {
8822 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8825 source_has_wild
= ms_has_wild(orig_src_lcomp
);
8826 dest_has_wild
= ms_has_wild(orig_dst_lcomp
);
8827 TALLOC_FREE(orig_src_lcomp
);
8828 TALLOC_FREE(orig_dst_lcomp
);
8832 * We should only check the mangled cache
8833 * here if unix_convert failed. This means
8834 * that the path in 'mask' doesn't exist
8835 * on the file system and so we need to look
8836 * for a possible mangle. This patch from
8837 * Tine Smukavec <valentin.smukavec@hermes.si>.
8839 if (!VALID_STAT(smb_fname_src
->st
) &&
8840 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
8841 char *new_mask
= NULL
;
8842 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
8843 &new_mask
, conn
->params
);
8845 /* Use demangled name if one was successfully found. */
8847 TALLOC_FREE(fname_src_mask
);
8848 fname_src_mask
= new_mask
;
8852 if (!source_has_wild
) {
8855 * Only one file needs to be copied. Append the mask back onto
8858 TALLOC_FREE(smb_fname_src
->base_name
);
8859 if (ISDOT(fname_src_dir
)) {
8860 /* Ensure we use canonical names on open. */
8861 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8865 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8870 if (!smb_fname_src
->base_name
) {
8871 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8875 if (dest_has_wild
) {
8876 char *fname_dst_mod
= NULL
;
8877 if (!resolve_wildcards(smb_fname_dst
,
8878 smb_fname_src
->base_name
,
8879 smb_fname_dst
->base_name
,
8881 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8884 TALLOC_FREE(smb_fname_dst
->base_name
);
8885 smb_fname_dst
->base_name
= fname_dst_mod
;
8888 status
= check_name(conn
, smb_fname_src
);
8889 if (!NT_STATUS_IS_OK(status
)) {
8890 reply_nterror(req
, status
);
8894 status
= check_name(conn
, smb_fname_dst
);
8895 if (!NT_STATUS_IS_OK(status
)) {
8896 reply_nterror(req
, status
);
8900 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
8901 ofun
, count
, target_is_directory
);
8903 if(!NT_STATUS_IS_OK(status
)) {
8904 reply_nterror(req
, status
);
8910 struct smb_Dir
*dir_hnd
= NULL
;
8911 const char *dname
= NULL
;
8912 char *talloced
= NULL
;
8916 * There is a wildcard that requires us to actually read the
8917 * src dir and copy each file matching the mask to the dst.
8918 * Right now streams won't be copied, but this could
8919 * presumably be added with a nested loop for reach dir entry.
8921 SMB_ASSERT(!smb_fname_src
->stream_name
);
8922 SMB_ASSERT(!smb_fname_dst
->stream_name
);
8924 smb_fname_src
->stream_name
= NULL
;
8925 smb_fname_dst
->stream_name
= NULL
;
8927 if (strequal(fname_src_mask
,"????????.???")) {
8928 TALLOC_FREE(fname_src_mask
);
8929 fname_src_mask
= talloc_strdup(ctx
, "*");
8930 if (!fname_src_mask
) {
8931 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8936 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
8940 smb_fname_src
->twrp
,
8941 smb_fname_src
->flags
);
8942 if (smb_fname_src_dir
== NULL
) {
8943 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8947 status
= check_name(conn
, smb_fname_src_dir
);
8948 if (!NT_STATUS_IS_OK(status
)) {
8949 reply_nterror(req
, status
);
8953 dir_hnd
= OpenDir(ctx
,
8958 if (dir_hnd
== NULL
) {
8959 status
= map_nt_error_from_unix(errno
);
8960 reply_nterror(req
, status
);
8966 /* Iterate over the src dir copying each entry to the dst. */
8967 while ((dname
= ReadDirName(dir_hnd
, &offset
,
8968 &smb_fname_src
->st
, &talloced
))) {
8969 char *destname
= NULL
;
8971 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
8972 TALLOC_FREE(talloced
);
8976 if (IS_VETO_PATH(conn
, dname
)) {
8977 TALLOC_FREE(talloced
);
8981 if(!mask_match(dname
, fname_src_mask
,
8982 conn
->case_sensitive
)) {
8983 TALLOC_FREE(talloced
);
8987 error
= ERRnoaccess
;
8989 /* Get the src smb_fname struct setup. */
8990 TALLOC_FREE(smb_fname_src
->base_name
);
8991 if (ISDOT(fname_src_dir
)) {
8992 /* Ensure we use canonical names on open. */
8993 smb_fname_src
->base_name
=
8994 talloc_asprintf(smb_fname_src
, "%s",
8997 smb_fname_src
->base_name
=
8998 talloc_asprintf(smb_fname_src
, "%s/%s",
8999 fname_src_dir
, dname
);
9002 if (!smb_fname_src
->base_name
) {
9003 TALLOC_FREE(dir_hnd
);
9004 TALLOC_FREE(talloced
);
9005 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9009 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
9010 smb_fname_dst
->base_name
,
9012 TALLOC_FREE(talloced
);
9016 TALLOC_FREE(dir_hnd
);
9017 TALLOC_FREE(talloced
);
9018 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9022 TALLOC_FREE(smb_fname_dst
->base_name
);
9023 smb_fname_dst
->base_name
= destname
;
9025 ZERO_STRUCT(smb_fname_src
->st
);
9026 vfs_stat(conn
, smb_fname_src
);
9028 status
= openat_pathref_fsp(conn
->cwd_fsp
,
9030 if (!NT_STATUS_IS_OK(status
)) {
9031 DBG_INFO("openat_pathref_fsp [%s] failed: %s\n",
9032 smb_fname_str_dbg(smb_fname_src
),
9037 if (!is_visible_fsp(smb_fname_src
->fsp
)) {
9038 TALLOC_FREE(talloced
);
9042 status
= check_name(conn
, smb_fname_src
);
9043 if (!NT_STATUS_IS_OK(status
)) {
9044 TALLOC_FREE(dir_hnd
);
9045 TALLOC_FREE(talloced
);
9046 reply_nterror(req
, status
);
9050 status
= check_name(conn
, smb_fname_dst
);
9051 if (!NT_STATUS_IS_OK(status
)) {
9052 TALLOC_FREE(dir_hnd
);
9053 TALLOC_FREE(talloced
);
9054 reply_nterror(req
, status
);
9058 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
9059 smb_fname_src
->base_name
,
9060 smb_fname_dst
->base_name
));
9062 status
= copy_file(ctx
, conn
, smb_fname_src
,
9063 smb_fname_dst
, ofun
, count
,
9064 target_is_directory
);
9065 if (NT_STATUS_IS_OK(status
)) {
9069 TALLOC_FREE(talloced
);
9071 TALLOC_FREE(dir_hnd
);
9075 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
9079 reply_outbuf(req
, 1, 0);
9080 SSVAL(req
->outbuf
,smb_vwv0
,count
);
9082 TALLOC_FREE(smb_fname_src
);
9083 TALLOC_FREE(smb_fname_src_dir
);
9084 TALLOC_FREE(smb_fname_dst
);
9085 TALLOC_FREE(fname_src
);
9086 TALLOC_FREE(fname_dst
);
9087 TALLOC_FREE(fname_src_mask
);
9088 TALLOC_FREE(fname_src_dir
);
9090 END_PROFILE(SMBcopy
);
9095 #define DBGC_CLASS DBGC_LOCKING
9097 /****************************************************************************
9098 Get a lock pid, dealing with large count requests.
9099 ****************************************************************************/
9101 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
9102 bool large_file_format
)
9104 if(!large_file_format
)
9105 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
9107 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
9110 /****************************************************************************
9111 Get a lock count, dealing with large count requests.
9112 ****************************************************************************/
9114 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
9115 bool large_file_format
)
9119 if(!large_file_format
) {
9120 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
9123 * No BVAL, this is reversed!
9125 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
9126 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
9132 /****************************************************************************
9133 Get a lock offset, dealing with large offset requests.
9134 ****************************************************************************/
9136 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
9137 bool large_file_format
)
9139 uint64_t offset
= 0;
9141 if(!large_file_format
) {
9142 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
9145 * No BVAL, this is reversed!
9147 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
9148 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
9154 struct smbd_do_unlocking_state
{
9155 struct files_struct
*fsp
;
9156 uint16_t num_ulocks
;
9157 struct smbd_lock_element
*ulocks
;
9158 enum brl_flavour lock_flav
;
9162 static void smbd_do_unlocking_fn(
9165 bool *pmodified_dependent
,
9168 struct smbd_do_unlocking_state
*state
= private_data
;
9169 struct files_struct
*fsp
= state
->fsp
;
9170 enum brl_flavour lock_flav
= state
->lock_flav
;
9173 for (i
= 0; i
< state
->num_ulocks
; i
++) {
9174 struct smbd_lock_element
*e
= &state
->ulocks
[i
];
9176 DBG_DEBUG("unlock start=%"PRIu64
", len=%"PRIu64
" for "
9177 "pid %"PRIu64
", file %s\n",
9183 if (e
->brltype
!= UNLOCK_LOCK
) {
9184 /* this can only happen with SMB2 */
9185 state
->status
= NT_STATUS_INVALID_PARAMETER
;
9189 state
->status
= do_unlock(
9190 fsp
, e
->smblctx
, e
->count
, e
->offset
, lock_flav
);
9192 DBG_DEBUG("do_unlock returned %s\n",
9193 nt_errstr(state
->status
));
9195 if (!NT_STATUS_IS_OK(state
->status
)) {
9200 *pmodified_dependent
= true;
9203 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
9205 uint16_t num_ulocks
,
9206 struct smbd_lock_element
*ulocks
,
9207 enum brl_flavour lock_flav
)
9209 struct smbd_do_unlocking_state state
= {
9211 .num_ulocks
= num_ulocks
,
9213 .lock_flav
= lock_flav
,
9217 DBG_NOTICE("%s num_ulocks=%"PRIu16
"\n", fsp_fnum_dbg(fsp
), num_ulocks
);
9219 status
= share_mode_do_locked(
9220 fsp
->file_id
, smbd_do_unlocking_fn
, &state
);
9222 if (!NT_STATUS_IS_OK(status
)) {
9223 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9227 if (!NT_STATUS_IS_OK(state
.status
)) {
9228 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9230 return state
.status
;
9233 return NT_STATUS_OK
;
9236 /****************************************************************************
9237 Reply to a lockingX request.
9238 ****************************************************************************/
9240 static void reply_lockingx_done(struct tevent_req
*subreq
);
9242 void reply_lockingX(struct smb_request
*req
)
9244 connection_struct
*conn
= req
->conn
;
9246 unsigned char locktype
;
9247 enum brl_type brltype
;
9248 unsigned char oplocklevel
;
9249 uint16_t num_ulocks
;
9251 int32_t lock_timeout
;
9253 const uint8_t *data
;
9254 bool large_file_format
;
9255 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
9256 struct smbd_lock_element
*locks
= NULL
;
9257 struct tevent_req
*subreq
= NULL
;
9259 START_PROFILE(SMBlockingX
);
9262 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9263 END_PROFILE(SMBlockingX
);
9267 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
9268 locktype
= CVAL(req
->vwv
+3, 0);
9269 oplocklevel
= CVAL(req
->vwv
+3, 1);
9270 num_ulocks
= SVAL(req
->vwv
+6, 0);
9271 num_locks
= SVAL(req
->vwv
+7, 0);
9272 lock_timeout
= IVAL(req
->vwv
+4, 0);
9273 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
9275 if (!check_fsp(conn
, req
, fsp
)) {
9276 END_PROFILE(SMBlockingX
);
9282 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
9283 /* we don't support these - and CANCEL_LOCK makes w2k
9284 and XP reboot so I don't really want to be
9285 compatible! (tridge) */
9286 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
9287 END_PROFILE(SMBlockingX
);
9291 /* Check if this is an oplock break on a file
9292 we have granted an oplock on.
9294 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
9295 /* Client can insist on breaking to none. */
9296 bool break_to_none
= (oplocklevel
== 0);
9299 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9300 "for %s\n", (unsigned int)oplocklevel
,
9301 fsp_fnum_dbg(fsp
)));
9304 * Make sure we have granted an exclusive or batch oplock on
9308 if (fsp
->oplock_type
== 0) {
9310 /* The Samba4 nbench simulator doesn't understand
9311 the difference between break to level2 and break
9312 to none from level2 - it sends oplock break
9313 replies in both cases. Don't keep logging an error
9314 message here - just ignore it. JRA. */
9316 DEBUG(5,("reply_lockingX: Error : oplock break from "
9317 "client for %s (oplock=%d) and no "
9318 "oplock granted on this file (%s).\n",
9319 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
9322 /* if this is a pure oplock break request then don't
9324 if (num_locks
== 0 && num_ulocks
== 0) {
9325 END_PROFILE(SMBlockingX
);
9329 END_PROFILE(SMBlockingX
);
9330 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
9334 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
9336 result
= remove_oplock(fsp
);
9338 result
= downgrade_oplock(fsp
);
9342 DEBUG(0, ("reply_lockingX: error in removing "
9343 "oplock on file %s\n", fsp_str_dbg(fsp
)));
9344 /* Hmmm. Is this panic justified? */
9345 smb_panic("internal tdb error");
9348 /* if this is a pure oplock break request then don't send a
9350 if (num_locks
== 0 && num_ulocks
== 0) {
9351 /* Sanity check - ensure a pure oplock break is not a
9353 if (CVAL(req
->vwv
+0, 0) != 0xff) {
9354 DEBUG(0,("reply_lockingX: Error : pure oplock "
9355 "break is a chained %d request !\n",
9356 (unsigned int)CVAL(req
->vwv
+0, 0)));
9358 END_PROFILE(SMBlockingX
);
9364 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
9365 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9366 END_PROFILE(SMBlockingX
);
9370 if (num_ulocks
!= 0) {
9371 struct smbd_lock_element
*ulocks
= NULL
;
9374 ulocks
= talloc_array(
9375 req
, struct smbd_lock_element
, num_ulocks
);
9376 if (ulocks
== NULL
) {
9377 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9378 END_PROFILE(SMBlockingX
);
9383 * Data now points at the beginning of the list of
9384 * smb_unlkrng structs
9386 for (i
= 0; i
< num_ulocks
; i
++) {
9387 ulocks
[i
].req_guid
= smbd_request_guid(req
,
9389 ulocks
[i
].smblctx
= get_lock_pid(
9390 data
, i
, large_file_format
);
9391 ulocks
[i
].count
= get_lock_count(
9392 data
, i
, large_file_format
);
9393 ulocks
[i
].offset
= get_lock_offset(
9394 data
, i
, large_file_format
);
9395 ulocks
[i
].brltype
= UNLOCK_LOCK
;
9399 * Unlock cancels pending locks
9402 ok
= smbd_smb1_brl_finish_by_lock(
9409 reply_outbuf(req
, 2, 0);
9410 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
9411 SSVAL(req
->outbuf
, smb_vwv1
, 0);
9412 END_PROFILE(SMBlockingX
);
9416 status
= smbd_do_unlocking(
9417 req
, fsp
, num_ulocks
, ulocks
, WINDOWS_LOCK
);
9418 TALLOC_FREE(ulocks
);
9419 if (!NT_STATUS_IS_OK(status
)) {
9420 END_PROFILE(SMBlockingX
);
9421 reply_nterror(req
, status
);
9426 /* Now do any requested locks */
9427 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
9429 /* Data now points at the beginning of the list
9430 of smb_lkrng structs */
9432 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
9433 brltype
= READ_LOCK
;
9435 brltype
= WRITE_LOCK
;
9438 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
9439 if (locks
== NULL
) {
9440 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9441 END_PROFILE(SMBlockingX
);
9445 for (i
= 0; i
< num_locks
; i
++) {
9446 locks
[i
].req_guid
= smbd_request_guid(req
, i
),
9447 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
9448 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
9449 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
9450 locks
[i
].brltype
= brltype
;
9453 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
9457 if (num_locks
== 0) {
9458 /* See smbtorture3 lock11 test */
9459 reply_outbuf(req
, 2, 0);
9460 /* andx chain ends */
9461 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
9462 SSVAL(req
->outbuf
, smb_vwv1
, 0);
9463 END_PROFILE(SMBlockingX
);
9467 ok
= smbd_smb1_brl_finish_by_lock(
9471 locks
[0], /* Windows only cancels the first lock */
9472 NT_STATUS_FILE_LOCK_CONFLICT
);
9475 reply_force_doserror(req
, ERRDOS
, ERRcancelviolation
);
9476 END_PROFILE(SMBlockingX
);
9480 reply_outbuf(req
, 2, 0);
9481 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
9482 SSVAL(req
->outbuf
, smb_vwv1
, 0);
9483 END_PROFILE(SMBlockingX
);
9487 subreq
= smbd_smb1_do_locks_send(
9497 if (subreq
== NULL
) {
9498 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9499 END_PROFILE(SMBlockingX
);
9502 tevent_req_set_callback(subreq
, reply_lockingx_done
, NULL
);
9503 END_PROFILE(SMBlockingX
);
9506 static void reply_lockingx_done(struct tevent_req
*subreq
)
9508 struct smb_request
*req
= NULL
;
9512 START_PROFILE(SMBlockingX
);
9514 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
9517 status
= smbd_smb1_do_locks_recv(subreq
);
9518 TALLOC_FREE(subreq
);
9520 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status
));
9522 if (NT_STATUS_IS_OK(status
)) {
9523 reply_outbuf(req
, 2, 0);
9524 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
9525 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
9527 reply_nterror(req
, status
);
9530 ok
= srv_send_smb(req
->xconn
,
9531 (char *)req
->outbuf
,
9534 IS_CONN_ENCRYPTED(req
->conn
),
9537 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9540 END_PROFILE(SMBlockingX
);
9544 #define DBGC_CLASS DBGC_ALL
9546 /****************************************************************************
9547 Reply to a SMBreadbmpx (read block multiplex) request.
9548 Always reply with an error, if someone has a platform really needs this,
9549 please contact vl@samba.org
9550 ****************************************************************************/
9552 void reply_readbmpx(struct smb_request
*req
)
9554 START_PROFILE(SMBreadBmpx
);
9555 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
9556 END_PROFILE(SMBreadBmpx
);
9560 /****************************************************************************
9561 Reply to a SMBreadbs (read block multiplex secondary) request.
9562 Always reply with an error, if someone has a platform really needs this,
9563 please contact vl@samba.org
9564 ****************************************************************************/
9566 void reply_readbs(struct smb_request
*req
)
9568 START_PROFILE(SMBreadBs
);
9569 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
9570 END_PROFILE(SMBreadBs
);
9574 /****************************************************************************
9575 Reply to a SMBsetattrE.
9576 ****************************************************************************/
9578 void reply_setattrE(struct smb_request
*req
)
9580 connection_struct
*conn
= req
->conn
;
9581 struct smb_file_time ft
;
9585 START_PROFILE(SMBsetattrE
);
9586 init_smb_file_time(&ft
);
9589 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9593 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
9595 if(!fsp
|| (fsp
->conn
!= conn
)) {
9596 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
9601 * Convert the DOS times into unix times.
9604 ft
.atime
= time_t_to_full_timespec(
9605 srv_make_unix_date2(req
->vwv
+3));
9606 ft
.mtime
= time_t_to_full_timespec(
9607 srv_make_unix_date2(req
->vwv
+5));
9608 ft
.create_time
= time_t_to_full_timespec(
9609 srv_make_unix_date2(req
->vwv
+1));
9611 reply_outbuf(req
, 0, 0);
9614 * Patch from Ray Frush <frush@engr.colostate.edu>
9615 * Sometimes times are sent as zero - ignore them.
9618 /* Ensure we have a valid stat struct for the source. */
9619 status
= vfs_stat_fsp(fsp
);
9620 if (!NT_STATUS_IS_OK(status
)) {
9621 reply_nterror(req
, status
);
9625 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
9626 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9630 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
9631 if (!NT_STATUS_IS_OK(status
)) {
9632 reply_nterror(req
, status
);
9636 if (fsp
->fsp_flags
.modified
) {
9637 trigger_write_time_update_immediate(fsp
);
9640 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9643 (unsigned int)ft
.atime
.tv_sec
,
9644 (unsigned int)ft
.mtime
.tv_sec
,
9645 (unsigned int)ft
.create_time
.tv_sec
9648 END_PROFILE(SMBsetattrE
);
9653 /* Back from the dead for OS/2..... JRA. */
9655 /****************************************************************************
9656 Reply to a SMBwritebmpx (write block multiplex primary) request.
9657 Always reply with an error, if someone has a platform really needs this,
9658 please contact vl@samba.org
9659 ****************************************************************************/
9661 void reply_writebmpx(struct smb_request
*req
)
9663 START_PROFILE(SMBwriteBmpx
);
9664 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
9665 END_PROFILE(SMBwriteBmpx
);
9669 /****************************************************************************
9670 Reply to a SMBwritebs (write block multiplex secondary) request.
9671 Always reply with an error, if someone has a platform really needs this,
9672 please contact vl@samba.org
9673 ****************************************************************************/
9675 void reply_writebs(struct smb_request
*req
)
9677 START_PROFILE(SMBwriteBs
);
9678 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
9679 END_PROFILE(SMBwriteBs
);
9683 /****************************************************************************
9684 Reply to a SMBgetattrE.
9685 ****************************************************************************/
9687 void reply_getattrE(struct smb_request
*req
)
9689 connection_struct
*conn
= req
->conn
;
9692 struct timespec create_ts
;
9695 START_PROFILE(SMBgetattrE
);
9698 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9699 END_PROFILE(SMBgetattrE
);
9703 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
9705 if(!fsp
|| (fsp
->conn
!= conn
)) {
9706 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
9707 END_PROFILE(SMBgetattrE
);
9711 /* Do an fstat on this file */
9712 status
= vfs_stat_fsp(fsp
);
9713 if (!NT_STATUS_IS_OK(status
)) {
9714 reply_nterror(req
, status
);
9715 END_PROFILE(SMBgetattrE
);
9719 mode
= fdos_mode(fsp
);
9722 * Convert the times into dos times. Set create
9723 * date to be last modify date as UNIX doesn't save
9727 reply_outbuf(req
, 11, 0);
9729 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
9730 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
9731 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
9732 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
9733 /* Should we check pending modtime here ? JRA */
9734 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
9735 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
9737 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
9738 SIVAL(req
->outbuf
, smb_vwv6
, 0);
9739 SIVAL(req
->outbuf
, smb_vwv8
, 0);
9741 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
9742 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
9743 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
9745 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
9747 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
9749 END_PROFILE(SMBgetattrE
);