2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
48 /****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
54 ****************************************************************************/
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
59 static NTSTATUS
check_path_syntax_internal(char *path
,
61 bool *p_last_component_contains_wcard
)
65 NTSTATUS ret
= NT_STATUS_OK
;
66 bool start_of_name_component
= True
;
67 bool stream_started
= false;
69 *p_last_component_contains_wcard
= False
;
76 return NT_STATUS_OBJECT_NAME_INVALID
;
79 return NT_STATUS_OBJECT_NAME_INVALID
;
81 if (strchr_m(&s
[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID
;
88 if ((*s
== ':') && !posix_path
&& !stream_started
) {
89 if (*p_last_component_contains_wcard
) {
90 return NT_STATUS_OBJECT_NAME_INVALID
;
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
98 stream_started
= true;
99 start_of_name_component
= false;
103 return NT_STATUS_OBJECT_NAME_INVALID
;
107 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s
,posix_path
)) {
116 if ((d
!= path
) && (*s
!= '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
121 start_of_name_component
= True
;
123 *p_last_component_contains_wcard
= False
;
127 if (start_of_name_component
) {
128 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
132 * No mb char starts with '.' so we're safe checking the directory separator here.
135 /* If we just added a '/' - delete it */
136 if ((d
> path
) && (*(d
-1) == '/')) {
141 /* Are we at the start ? Can't go back further if so. */
143 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d
--; d
> path
; d
--) {
154 s
+= 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
158 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
170 if (*s
<= 0x1f || *s
== '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID
;
179 *p_last_component_contains_wcard
= True
;
188 /* Get the size of the next MB character. */
189 next_codepoint(s
,&siz
);
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
209 return NT_STATUS_INVALID_PARAMETER
;
212 start_of_name_component
= False
;
220 /****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223 ****************************************************************************/
225 NTSTATUS
check_path_syntax(char *path
)
228 return check_path_syntax_internal(path
, False
, &ignore
);
231 /****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
235 ****************************************************************************/
237 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
239 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
242 /****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246 ****************************************************************************/
248 NTSTATUS
check_path_syntax_posix(char *path
)
251 return check_path_syntax_internal(path
, True
, &ignore
);
254 /****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 Passes in posix flag.
257 ****************************************************************************/
259 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX
*ctx
,
260 const char *base_ptr
,
266 bool posix_pathnames
,
268 bool *contains_wcard
)
274 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
278 *err
= NT_STATUS_INVALID_PARAMETER
;
282 *contains_wcard
= False
;
284 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
286 * For a DFS path the function parse_dfs_path()
287 * will do the path processing, just make a copy.
293 if (posix_pathnames
) {
294 *err
= check_path_syntax_posix(*pp_dest
);
296 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
302 /****************************************************************************
303 Pull a string and check the path allowing a wilcard - provide for error return.
304 ****************************************************************************/
306 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
307 const char *base_ptr
,
314 bool *contains_wcard
)
316 return srvstr_get_path_wcard_internal(ctx
,
328 /****************************************************************************
329 Pull a string and check the path allowing a wilcard - provide for error return.
330 posix_pathnames version.
331 ****************************************************************************/
333 size_t srvstr_get_path_wcard_posix(TALLOC_CTX
*ctx
,
334 const char *base_ptr
,
341 bool *contains_wcard
)
343 return srvstr_get_path_wcard_internal(ctx
,
355 /****************************************************************************
356 Pull a string and check the path - provide for error return.
357 ****************************************************************************/
359 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
360 const char *base_ptr
,
369 return srvstr_get_path_wcard_internal(ctx
,
381 /****************************************************************************
382 Pull a string and check the path - provide for error return.
383 posix_pathnames version.
384 ****************************************************************************/
386 size_t srvstr_get_path_posix(TALLOC_CTX
*ctx
,
387 const char *base_ptr
,
396 return srvstr_get_path_wcard_internal(ctx
,
409 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
410 char **pp_dest
, const char *src
, int flags
,
411 NTSTATUS
*err
, bool *contains_wcard
)
413 ssize_t bufrem
= smbreq_bufrem(req
, src
);
416 *err
= NT_STATUS_INVALID_PARAMETER
;
420 if (req
->posix_pathnames
) {
421 return srvstr_get_path_wcard_internal(mem_ctx
,
422 (const char *)req
->inbuf
,
432 return srvstr_get_path_wcard_internal(mem_ctx
,
433 (const char *)req
->inbuf
,
445 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
446 char **pp_dest
, const char *src
, int flags
,
450 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
451 flags
, err
, &ignore
);
455 * pull a string from the smb_buf part of a packet. In this case the
456 * string can either be null terminated or it can be terminated by the
457 * end of the smbbuf area
459 size_t srvstr_pull_req_talloc(TALLOC_CTX
*ctx
, struct smb_request
*req
,
460 char **dest
, const uint8_t *src
, int flags
)
462 ssize_t bufrem
= smbreq_bufrem(req
, src
);
468 return pull_string_talloc(ctx
, req
->inbuf
, req
->flags2
, dest
, src
,
472 /****************************************************************************
473 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
474 ****************************************************************************/
476 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
479 if ((fsp
== NULL
) || (conn
== NULL
)) {
480 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
483 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
484 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
490 /****************************************************************************
491 Check if we have a correct fsp pointing to a file.
492 ****************************************************************************/
494 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
497 if (!check_fsp_open(conn
, req
, fsp
)) {
500 if (fsp
->is_directory
) {
501 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
504 if (fsp
->fh
->fd
== -1) {
505 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
508 fsp
->num_smb_operations
++;
512 /****************************************************************************
513 Check if we have a correct fsp pointing to a quota fake file. Replacement for
514 the CHECK_NTQUOTA_HANDLE_OK macro.
515 ****************************************************************************/
517 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
520 if (!check_fsp_open(conn
, req
, fsp
)) {
524 if (fsp
->is_directory
) {
528 if (fsp
->fake_file_handle
== NULL
) {
532 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
536 if (fsp
->fake_file_handle
->private_data
== NULL
) {
543 static bool netbios_session_retarget(struct smbXsrv_connection
*xconn
,
544 const char *name
, int name_type
)
547 char *trim_name_type
;
548 const char *retarget_parm
;
551 int retarget_type
= 0x20;
552 int retarget_port
= NBT_SMB_PORT
;
553 struct sockaddr_storage retarget_addr
;
554 struct sockaddr_in
*in_addr
;
558 if (get_socket_port(xconn
->transport
.sock
) != NBT_SMB_PORT
) {
562 trim_name
= talloc_strdup(talloc_tos(), name
);
563 if (trim_name
== NULL
) {
566 trim_char(trim_name
, ' ', ' ');
568 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
570 if (trim_name_type
== NULL
) {
574 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
575 trim_name_type
, NULL
);
576 if (retarget_parm
== NULL
) {
577 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
580 if (retarget_parm
== NULL
) {
584 retarget
= talloc_strdup(trim_name
, retarget_parm
);
585 if (retarget
== NULL
) {
589 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
591 p
= strchr(retarget
, ':');
594 retarget_port
= atoi(p
);
597 p
= strchr_m(retarget
, '#');
600 if (sscanf(p
, "%x", &retarget_type
) != 1) {
605 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
607 DEBUG(10, ("could not resolve %s\n", retarget
));
611 if (retarget_addr
.ss_family
!= AF_INET
) {
612 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
616 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
618 _smb_setlen(outbuf
, 6);
619 SCVAL(outbuf
, 0, 0x84);
620 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
621 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
623 if (!srv_send_smb(xconn
, (char *)outbuf
, false, 0, false,
625 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
631 TALLOC_FREE(trim_name
);
635 static void reply_called_name_not_present(char *outbuf
)
637 smb_setlen(outbuf
, 1);
638 SCVAL(outbuf
, 0, 0x83);
639 SCVAL(outbuf
, 4, 0x82);
642 /****************************************************************************
643 Reply to a (netbios-level) special message.
644 ****************************************************************************/
646 void reply_special(struct smbXsrv_connection
*xconn
, char *inbuf
, size_t inbuf_size
)
648 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
649 int msg_type
= CVAL(inbuf
,0);
650 int msg_flags
= CVAL(inbuf
,1);
652 * We only really use 4 bytes of the outbuf, but for the smb_setlen
653 * calculation & friends (srv_send_smb uses that) we need the full smb
656 char outbuf
[smb_size
];
658 memset(outbuf
, '\0', sizeof(outbuf
));
660 smb_setlen(outbuf
,0);
663 case NBSSrequest
: /* session request */
665 /* inbuf_size is guarenteed to be at least 4. */
667 int name_type1
, name_type2
;
668 int name_len1
, name_len2
;
672 if (xconn
->transport
.nbt
.got_session
) {
673 exit_server_cleanly("multiple session request not permitted");
676 SCVAL(outbuf
,0,NBSSpositive
);
679 /* inbuf_size is guaranteed to be at least 4. */
680 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
681 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
682 DEBUG(0,("Invalid name length in session request\n"));
683 reply_called_name_not_present(outbuf
);
686 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
687 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
688 DEBUG(0,("Invalid name length in session request\n"));
689 reply_called_name_not_present(outbuf
);
693 name_type1
= name_extract((unsigned char *)inbuf
,
694 inbuf_size
,(unsigned int)4,name1
);
695 name_type2
= name_extract((unsigned char *)inbuf
,
696 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
698 if (name_type1
== -1 || name_type2
== -1) {
699 DEBUG(0,("Invalid name type in session request\n"));
700 reply_called_name_not_present(outbuf
);
704 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
705 name1
, name_type1
, name2
, name_type2
));
707 if (netbios_session_retarget(xconn
, name1
, name_type1
)) {
708 exit_server_cleanly("retargeted client");
712 * Windows NT/2k uses "*SMBSERVER" and XP uses
713 * "*SMBSERV" arrggg!!!
715 if (strequal(name1
, "*SMBSERVER ")
716 || strequal(name1
, "*SMBSERV ")) {
719 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
722 exit_server_cleanly("could not allocate raddr");
725 fstrcpy(name1
, raddr
);
728 set_local_machine_name(name1
, True
);
729 set_remote_machine_name(name2
, True
);
731 if (is_ipaddress(sconn
->remote_hostname
)) {
732 char *p
= discard_const_p(char, sconn
->remote_hostname
);
736 sconn
->remote_hostname
= talloc_strdup(sconn
,
737 get_remote_machine_name());
738 if (sconn
->remote_hostname
== NULL
) {
739 exit_server_cleanly("could not copy remote name");
741 xconn
->remote_hostname
= sconn
->remote_hostname
;
744 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
745 get_local_machine_name(), get_remote_machine_name(),
748 if (name_type2
== 'R') {
749 /* We are being asked for a pathworks session ---
751 reply_called_name_not_present(outbuf
);
755 reload_services(sconn
, conn_snum_used
, true);
758 xconn
->transport
.nbt
.got_session
= true;
762 case 0x89: /* session keepalive request
763 (some old clients produce this?) */
764 SCVAL(outbuf
,0,NBSSkeepalive
);
768 case NBSSpositive
: /* positive session response */
769 case NBSSnegative
: /* negative session response */
770 case NBSSretarget
: /* retarget session response */
771 DEBUG(0,("Unexpected session response\n"));
774 case NBSSkeepalive
: /* session keepalive */
779 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
780 msg_type
, msg_flags
));
782 if (!srv_send_smb(xconn
, outbuf
, false, 0, false, NULL
)) {
783 exit_server_cleanly("reply_special: srv_send_smb failed.");
786 if (CVAL(outbuf
, 0) != 0x82) {
787 exit_server_cleanly("invalid netbios session");
792 /****************************************************************************
794 conn POINTER CAN BE NULL HERE !
795 ****************************************************************************/
797 void reply_tcon(struct smb_request
*req
)
799 connection_struct
*conn
= req
->conn
;
801 char *service_buf
= NULL
;
802 char *password
= NULL
;
808 TALLOC_CTX
*ctx
= talloc_tos();
809 struct smbXsrv_connection
*xconn
= req
->xconn
;
810 NTTIME now
= timeval_to_nttime(&req
->request_time
);
812 START_PROFILE(SMBtcon
);
814 if (req
->buflen
< 4) {
815 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
816 END_PROFILE(SMBtcon
);
821 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
823 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
825 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
828 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
829 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
830 END_PROFILE(SMBtcon
);
833 p2
= strrchr_m(service_buf
,'\\');
837 service
= service_buf
;
840 conn
= make_connection(req
, now
, service
, dev
,
841 req
->vuid
,&nt_status
);
845 reply_nterror(req
, nt_status
);
846 END_PROFILE(SMBtcon
);
850 reply_outbuf(req
, 2, 0);
851 SSVAL(req
->outbuf
,smb_vwv0
,xconn
->smb1
.negprot
.max_recv
);
852 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
853 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
855 DEBUG(3,("tcon service=%s cnum=%d\n",
856 service
, conn
->cnum
));
858 END_PROFILE(SMBtcon
);
862 /****************************************************************************
863 Reply to a tcon and X.
864 conn POINTER CAN BE NULL HERE !
865 ****************************************************************************/
867 void reply_tcon_and_X(struct smb_request
*req
)
869 connection_struct
*conn
= req
->conn
;
870 const char *service
= NULL
;
871 TALLOC_CTX
*ctx
= talloc_tos();
872 /* what the client thinks the device is */
873 char *client_devicetype
= NULL
;
874 /* what the server tells the client the share represents */
875 const char *server_devicetype
;
882 struct smbXsrv_session
*session
= NULL
;
883 NTTIME now
= timeval_to_nttime(&req
->request_time
);
884 bool session_key_updated
= false;
885 uint16_t optional_support
= 0;
886 struct smbXsrv_connection
*xconn
= req
->xconn
;
888 START_PROFILE(SMBtconX
);
891 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
892 END_PROFILE(SMBtconX
);
896 passlen
= SVAL(req
->vwv
+3, 0);
897 tcon_flags
= SVAL(req
->vwv
+2, 0);
899 /* we might have to close an old one */
900 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
901 struct smbXsrv_tcon
*tcon
;
909 * TODO: cancel all outstanding requests on the tcon
911 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
912 if (!NT_STATUS_IS_OK(status
)) {
913 DEBUG(0, ("reply_tcon_and_X: "
914 "smbXsrv_tcon_disconnect() failed: %s\n",
917 * If we hit this case, there is something completely
918 * wrong, so we better disconnect the transport connection.
920 END_PROFILE(SMBtconX
);
921 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
927 * This tree id is gone. Make sure we can't re-use it
933 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
934 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
935 END_PROFILE(SMBtconX
);
939 if (xconn
->smb1
.negprot
.encrypted_passwords
) {
940 p
= req
->buf
+ passlen
;
942 p
= req
->buf
+ passlen
+ 1;
945 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
948 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
949 END_PROFILE(SMBtconX
);
954 * the service name can be either: \\server\share
955 * or share directly like on the DELL PowerVault 705
958 q
= strchr_m(path
+2,'\\');
960 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
961 END_PROFILE(SMBtconX
);
969 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
970 &client_devicetype
, p
,
971 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
973 if (client_devicetype
== NULL
) {
974 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
975 END_PROFILE(SMBtconX
);
979 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
981 nt_status
= smb1srv_session_lookup(xconn
,
982 req
->vuid
, now
, &session
);
983 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
984 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
985 END_PROFILE(SMBtconX
);
988 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
989 reply_nterror(req
, nt_status
);
990 END_PROFILE(SMBtconX
);
993 if (!NT_STATUS_IS_OK(nt_status
)) {
994 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
995 END_PROFILE(SMBtconX
);
999 if (session
->global
->auth_session_info
== NULL
) {
1000 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1001 END_PROFILE(SMBtconX
);
1006 * If there is no application key defined yet
1009 * This means we setup the application key on the
1010 * first tcon that happens via the given session.
1012 * Once the application key is defined, it does not
1015 if (session
->global
->application_key
.length
== 0 &&
1016 smb2_signing_key_valid(session
->global
->signing_key
))
1018 struct smbXsrv_session
*x
= session
;
1019 struct auth_session_info
*session_info
=
1020 session
->global
->auth_session_info
;
1021 uint8_t session_key
[16];
1023 ZERO_STRUCT(session_key
);
1024 memcpy(session_key
, x
->global
->signing_key
->blob
.data
,
1025 MIN(x
->global
->signing_key
->blob
.length
, sizeof(session_key
)));
1028 * The application key is truncated/padded to 16 bytes
1030 x
->global
->application_key
= data_blob_talloc(x
->global
,
1032 sizeof(session_key
));
1033 ZERO_STRUCT(session_key
);
1034 if (x
->global
->application_key
.data
== NULL
) {
1035 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1036 END_PROFILE(SMBtconX
);
1040 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
1043 status
= smb_key_derivation(x
->global
->application_key
.data
,
1044 x
->global
->application_key
.length
,
1045 x
->global
->application_key
.data
);
1046 if (!NT_STATUS_IS_OK(status
)) {
1047 DBG_ERR("smb_key_derivation failed: %s\n",
1051 optional_support
|= SMB_EXTENDED_SIGNATURES
;
1055 * Place the application key into the session_info
1057 data_blob_clear_free(&session_info
->session_key
);
1058 session_info
->session_key
= data_blob_dup_talloc(session_info
,
1059 x
->global
->application_key
);
1060 if (session_info
->session_key
.data
== NULL
) {
1061 data_blob_clear_free(&x
->global
->application_key
);
1062 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1063 END_PROFILE(SMBtconX
);
1066 session_key_updated
= true;
1069 conn
= make_connection(req
, now
, service
, client_devicetype
,
1070 req
->vuid
, &nt_status
);
1074 if (session_key_updated
) {
1075 struct smbXsrv_session
*x
= session
;
1076 struct auth_session_info
*session_info
=
1077 session
->global
->auth_session_info
;
1078 data_blob_clear_free(&x
->global
->application_key
);
1079 data_blob_clear_free(&session_info
->session_key
);
1081 reply_nterror(req
, nt_status
);
1082 END_PROFILE(SMBtconX
);
1087 server_devicetype
= "IPC";
1088 else if ( IS_PRINT(conn
) )
1089 server_devicetype
= "LPT1:";
1091 server_devicetype
= "A:";
1093 if (get_Protocol() < PROTOCOL_NT1
) {
1094 reply_outbuf(req
, 2, 0);
1095 if (message_push_string(&req
->outbuf
, server_devicetype
,
1096 STR_TERMINATE
|STR_ASCII
) == -1) {
1097 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1098 END_PROFILE(SMBtconX
);
1102 /* NT sets the fstype of IPC$ to the null string */
1103 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
1105 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
1106 /* Return permissions. */
1110 reply_outbuf(req
, 7, 0);
1113 perm1
= FILE_ALL_ACCESS
;
1114 perm2
= FILE_ALL_ACCESS
;
1116 perm1
= conn
->share_access
;
1119 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
1120 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
1122 reply_outbuf(req
, 3, 0);
1125 if ((message_push_string(&req
->outbuf
, server_devicetype
,
1126 STR_TERMINATE
|STR_ASCII
) == -1)
1127 || (message_push_string(&req
->outbuf
, fstype
,
1128 STR_TERMINATE
) == -1)) {
1129 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1130 END_PROFILE(SMBtconX
);
1134 /* what does setting this bit do? It is set by NT4 and
1135 may affect the ability to autorun mounted cdroms */
1136 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1138 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1140 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1141 DEBUG(2,("Serving %s as a Dfs root\n",
1142 lp_servicename(ctx
, SNUM(conn
)) ));
1143 optional_support
|= SMB_SHARE_IN_DFS
;
1146 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1149 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1150 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1152 DEBUG(3,("tconX service=%s \n",
1155 /* set the incoming and outgoing tid to the just created one */
1156 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1157 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1159 END_PROFILE(SMBtconX
);
1161 req
->tid
= conn
->cnum
;
1164 /****************************************************************************
1165 Reply to an unknown type.
1166 ****************************************************************************/
1168 void reply_unknown_new(struct smb_request
*req
, uint8_t type
)
1170 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1171 smb_fn_name(type
), type
, type
));
1172 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1176 /****************************************************************************
1178 conn POINTER CAN BE NULL HERE !
1179 ****************************************************************************/
1181 void reply_ioctl(struct smb_request
*req
)
1183 connection_struct
*conn
= req
->conn
;
1186 uint32_t ioctl_code
;
1190 START_PROFILE(SMBioctl
);
1193 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1194 END_PROFILE(SMBioctl
);
1198 device
= SVAL(req
->vwv
+1, 0);
1199 function
= SVAL(req
->vwv
+2, 0);
1200 ioctl_code
= (device
<< 16) + function
;
1202 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1204 switch (ioctl_code
) {
1205 case IOCTL_QUERY_JOB_INFO
:
1209 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1210 END_PROFILE(SMBioctl
);
1214 reply_outbuf(req
, 8, replysize
+1);
1215 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1216 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1217 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1218 p
= smb_buf(req
->outbuf
);
1219 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1220 p
+= 1; /* Allow for alignment */
1222 switch (ioctl_code
) {
1223 case IOCTL_QUERY_JOB_INFO
:
1227 files_struct
*fsp
= file_fsp(
1228 req
, SVAL(req
->vwv
+0, 0));
1230 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1231 END_PROFILE(SMBioctl
);
1235 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1237 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1238 lp_netbios_name(), 15,
1239 STR_TERMINATE
|STR_ASCII
, &len
);
1240 if (!NT_STATUS_IS_OK(status
)) {
1241 reply_nterror(req
, status
);
1242 END_PROFILE(SMBioctl
);
1246 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
,
1248 lp_servicename(talloc_tos(),
1250 13, STR_TERMINATE
|STR_ASCII
, &len
);
1251 if (!NT_STATUS_IS_OK(status
)) {
1252 reply_nterror(req
, status
);
1253 END_PROFILE(SMBioctl
);
1257 memset(p
+18, 0, 13);
1263 END_PROFILE(SMBioctl
);
1267 /****************************************************************************
1268 Strange checkpath NTSTATUS mapping.
1269 ****************************************************************************/
1271 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1273 /* Strange DOS error code semantics only for checkpath... */
1274 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1275 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1276 /* We need to map to ERRbadpath */
1277 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1283 /****************************************************************************
1284 Reply to a checkpath.
1285 ****************************************************************************/
1287 void reply_checkpath(struct smb_request
*req
)
1289 connection_struct
*conn
= req
->conn
;
1290 struct smb_filename
*smb_fname
= NULL
;
1293 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1294 TALLOC_CTX
*ctx
= talloc_tos();
1296 START_PROFILE(SMBcheckpath
);
1298 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1299 STR_TERMINATE
, &status
);
1301 if (!NT_STATUS_IS_OK(status
)) {
1302 status
= map_checkpath_error(req
->flags2
, status
);
1303 reply_nterror(req
, status
);
1304 END_PROFILE(SMBcheckpath
);
1308 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1310 status
= filename_convert(ctx
,
1318 if (!NT_STATUS_IS_OK(status
)) {
1319 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1320 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1321 ERRSRV
, ERRbadpath
);
1322 END_PROFILE(SMBcheckpath
);
1328 if (!VALID_STAT(smb_fname
->st
) &&
1329 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1330 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1331 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1332 status
= map_nt_error_from_unix(errno
);
1336 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1337 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1338 ERRDOS
, ERRbadpath
);
1342 reply_outbuf(req
, 0, 0);
1345 /* We special case this - as when a Windows machine
1346 is parsing a path is steps through the components
1347 one at a time - if a component fails it expects
1348 ERRbadpath, not ERRbadfile.
1350 status
= map_checkpath_error(req
->flags2
, status
);
1351 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1353 * Windows returns different error codes if
1354 * the parent directory is valid but not the
1355 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1356 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1357 * if the path is invalid.
1359 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1360 ERRDOS
, ERRbadpath
);
1364 reply_nterror(req
, status
);
1367 TALLOC_FREE(smb_fname
);
1368 END_PROFILE(SMBcheckpath
);
1372 /****************************************************************************
1374 ****************************************************************************/
1376 void reply_getatr(struct smb_request
*req
)
1378 connection_struct
*conn
= req
->conn
;
1379 struct smb_filename
*smb_fname
= NULL
;
1386 TALLOC_CTX
*ctx
= talloc_tos();
1387 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1389 START_PROFILE(SMBgetatr
);
1391 p
= (const char *)req
->buf
+ 1;
1392 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1393 if (!NT_STATUS_IS_OK(status
)) {
1394 reply_nterror(req
, status
);
1398 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1399 under WfWg - weird! */
1400 if (*fname
== '\0') {
1401 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1402 if (!CAN_WRITE(conn
)) {
1403 mode
|= FILE_ATTRIBUTE_READONLY
;
1408 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1409 status
= filename_convert(ctx
,
1416 if (!NT_STATUS_IS_OK(status
)) {
1417 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1418 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1419 ERRSRV
, ERRbadpath
);
1422 reply_nterror(req
, status
);
1425 if (!VALID_STAT(smb_fname
->st
) &&
1426 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1427 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1428 smb_fname_str_dbg(smb_fname
),
1430 reply_nterror(req
, map_nt_error_from_unix(errno
));
1434 mode
= dos_mode(conn
, smb_fname
);
1435 size
= smb_fname
->st
.st_ex_size
;
1437 if (ask_sharemode
) {
1438 struct timespec write_time_ts
;
1439 struct file_id fileid
;
1441 ZERO_STRUCT(write_time_ts
);
1442 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1443 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1444 if (!null_timespec(write_time_ts
)) {
1445 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1449 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1450 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1455 reply_outbuf(req
, 10, 0);
1457 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1458 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1459 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1461 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1463 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
1465 if (get_Protocol() >= PROTOCOL_NT1
) {
1466 SSVAL(req
->outbuf
, smb_flg2
,
1467 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1470 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1471 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1474 TALLOC_FREE(smb_fname
);
1476 END_PROFILE(SMBgetatr
);
1480 /****************************************************************************
1482 ****************************************************************************/
1484 void reply_setatr(struct smb_request
*req
)
1486 struct smb_file_time ft
;
1487 connection_struct
*conn
= req
->conn
;
1488 struct smb_filename
*smb_fname
= NULL
;
1494 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1495 TALLOC_CTX
*ctx
= talloc_tos();
1497 START_PROFILE(SMBsetatr
);
1500 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1504 p
= (const char *)req
->buf
+ 1;
1505 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1506 if (!NT_STATUS_IS_OK(status
)) {
1507 reply_nterror(req
, status
);
1511 status
= filename_convert(ctx
,
1518 if (!NT_STATUS_IS_OK(status
)) {
1519 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1520 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1521 ERRSRV
, ERRbadpath
);
1524 reply_nterror(req
, status
);
1528 if (ISDOT(smb_fname
->base_name
)) {
1530 * Not sure here is the right place to catch this
1531 * condition. Might be moved to somewhere else later -- vl
1533 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1537 mode
= SVAL(req
->vwv
+0, 0);
1538 mtime
= srv_make_unix_date3(req
->vwv
+1);
1540 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1541 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1542 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1544 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1546 status
= smbd_check_access_rights(
1547 conn
, smb_fname
, false, FILE_WRITE_ATTRIBUTES
);
1548 if (!NT_STATUS_IS_OK(status
)) {
1549 reply_nterror(req
, status
);
1553 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1555 reply_nterror(req
, map_nt_error_from_unix(errno
));
1560 ft
= (struct smb_file_time
) {
1561 .mtime
= convert_time_t_to_timespec(mtime
)
1564 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1565 if (!NT_STATUS_IS_OK(status
)) {
1566 reply_nterror(req
, status
);
1570 reply_outbuf(req
, 0, 0);
1572 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1575 TALLOC_FREE(smb_fname
);
1576 END_PROFILE(SMBsetatr
);
1580 /****************************************************************************
1582 ****************************************************************************/
1584 void reply_dskattr(struct smb_request
*req
)
1586 connection_struct
*conn
= req
->conn
;
1588 uint64_t dfree
,dsize
,bsize
;
1589 struct smb_filename smb_fname
;
1590 START_PROFILE(SMBdskattr
);
1592 ZERO_STRUCT(smb_fname
);
1593 smb_fname
.base_name
= discard_const_p(char, ".");
1595 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
1596 reply_nterror(req
, map_nt_error_from_unix(errno
));
1597 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
1598 END_PROFILE(SMBdskattr
);
1602 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
1603 if (ret
== (uint64_t)-1) {
1604 reply_nterror(req
, map_nt_error_from_unix(errno
));
1605 END_PROFILE(SMBdskattr
);
1610 * Force max to fit in 16 bit fields.
1612 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1616 if (bsize
> (WORDMAX
*512)) {
1617 bsize
= (WORDMAX
*512);
1618 if (dsize
> WORDMAX
)
1620 if (dfree
> WORDMAX
)
1626 reply_outbuf(req
, 5, 0);
1628 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1629 double total_space
, free_space
;
1630 /* we need to scale this to a number that DOS6 can handle. We
1631 use floating point so we can handle large drives on systems
1632 that don't have 64 bit integers
1634 we end up displaying a maximum of 2G to DOS systems
1636 total_space
= dsize
* (double)bsize
;
1637 free_space
= dfree
* (double)bsize
;
1639 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1640 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1642 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1643 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1645 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1646 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1647 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1648 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1650 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1651 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1652 SSVAL(req
->outbuf
,smb_vwv2
,512);
1653 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1656 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1658 END_PROFILE(SMBdskattr
);
1663 * Utility function to split the filename from the directory.
1665 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1666 char **fname_dir_out
,
1667 char **fname_mask_out
)
1669 const char *p
= NULL
;
1670 char *fname_dir
= NULL
;
1671 char *fname_mask
= NULL
;
1673 p
= strrchr_m(fname_in
, '/');
1675 fname_dir
= talloc_strdup(ctx
, ".");
1676 fname_mask
= talloc_strdup(ctx
, fname_in
);
1678 fname_dir
= talloc_strndup(ctx
, fname_in
,
1679 PTR_DIFF(p
, fname_in
));
1680 fname_mask
= talloc_strdup(ctx
, p
+1);
1683 if (!fname_dir
|| !fname_mask
) {
1684 TALLOC_FREE(fname_dir
);
1685 TALLOC_FREE(fname_mask
);
1686 return NT_STATUS_NO_MEMORY
;
1689 *fname_dir_out
= fname_dir
;
1690 *fname_mask_out
= fname_mask
;
1691 return NT_STATUS_OK
;
1694 /****************************************************************************
1696 ****************************************************************************/
1698 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1708 char *mask2
= talloc_strdup(ctx
, mask
);
1714 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1718 memset(buf
+1,' ',11);
1719 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1721 push_ascii(buf
+1,mask2
,8, 0);
1722 push_ascii(buf
+9,p
+1,3, 0);
1725 push_ascii(buf
+1,mask2
,11, 0);
1728 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1730 srv_put_dos_date(buf
,22,date
);
1731 SSVAL(buf
,26,size
& 0xFFFF);
1732 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1733 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1734 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1735 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1736 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1740 /****************************************************************************
1742 Can be called from SMBsearch, SMBffirst or SMBfunique.
1743 ****************************************************************************/
1745 void reply_search(struct smb_request
*req
)
1747 connection_struct
*conn
= req
->conn
;
1750 char *directory
= NULL
;
1751 struct smb_filename
*smb_fname
= NULL
;
1755 struct timespec date
;
1757 unsigned int numentries
= 0;
1758 unsigned int maxentries
= 0;
1759 bool finished
= False
;
1764 bool check_descend
= False
;
1765 bool expect_close
= False
;
1767 bool mask_contains_wcard
= False
;
1768 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1769 TALLOC_CTX
*ctx
= talloc_tos();
1770 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1771 struct dptr_struct
*dirptr
= NULL
;
1772 struct smbXsrv_connection
*xconn
= req
->xconn
;
1773 struct smbd_server_connection
*sconn
= req
->sconn
;
1775 START_PROFILE(SMBsearch
);
1778 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1782 if (req
->posix_pathnames
) {
1783 reply_unknown_new(req
, req
->cmd
);
1787 /* If we were called as SMBffirst then we must expect close. */
1788 if(req
->cmd
== SMBffirst
) {
1789 expect_close
= True
;
1792 reply_outbuf(req
, 1, 3);
1793 maxentries
= SVAL(req
->vwv
+0, 0);
1794 dirtype
= SVAL(req
->vwv
+1, 0);
1795 p
= (const char *)req
->buf
+ 1;
1796 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1797 &nt_status
, &mask_contains_wcard
);
1798 if (!NT_STATUS_IS_OK(nt_status
)) {
1799 reply_nterror(req
, nt_status
);
1804 status_len
= SVAL(p
, 0);
1807 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1809 if (status_len
== 0) {
1810 struct smb_filename
*smb_dname
= NULL
;
1811 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
1812 ucf_flags_from_smb_request(req
);
1813 nt_status
= filename_convert(ctx
, conn
,
1817 &mask_contains_wcard
,
1819 if (!NT_STATUS_IS_OK(nt_status
)) {
1820 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1821 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1822 ERRSRV
, ERRbadpath
);
1825 reply_nterror(req
, nt_status
);
1829 directory
= smb_fname
->base_name
;
1831 p
= strrchr_m(directory
,'/');
1832 if ((p
!= NULL
) && (*directory
!= '/')) {
1833 mask
= talloc_strdup(ctx
, p
+ 1);
1834 directory
= talloc_strndup(ctx
, directory
,
1835 PTR_DIFF(p
, directory
));
1837 mask
= talloc_strdup(ctx
, directory
);
1838 directory
= talloc_strdup(ctx
,".");
1842 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1846 memset((char *)status
,'\0',21);
1847 SCVAL(status
,0,(dirtype
& 0x1F));
1849 smb_dname
= synthetic_smb_fname(talloc_tos(),
1854 if (smb_dname
== NULL
) {
1855 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1859 nt_status
= dptr_create(conn
,
1867 mask_contains_wcard
,
1871 TALLOC_FREE(smb_dname
);
1873 if (!NT_STATUS_IS_OK(nt_status
)) {
1874 reply_nterror(req
, nt_status
);
1877 dptr_num
= dptr_dnum(dirptr
);
1880 const char *dirpath
;
1882 memcpy(status
,p
,21);
1883 status_dirtype
= CVAL(status
,0) & 0x1F;
1884 if (status_dirtype
!= (dirtype
& 0x1F)) {
1885 dirtype
= status_dirtype
;
1888 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1892 dirpath
= dptr_path(sconn
, dptr_num
);
1893 directory
= talloc_strdup(ctx
, dirpath
);
1895 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1899 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1904 * For a 'continue' search we have no string. So
1905 * check from the initial saved string.
1907 if (!req
->posix_pathnames
) {
1908 mask_contains_wcard
= ms_has_wild(mask
);
1910 dirtype
= dptr_attr(sconn
, dptr_num
);
1913 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1915 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1916 char buf
[DIR_STRUCT_SIZE
];
1917 memcpy(buf
,status
,21);
1918 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1919 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1920 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1923 dptr_fill(sconn
, buf
+12,dptr_num
);
1924 if (dptr_zero(buf
+12) && (status_len
==0)) {
1929 if (message_push_blob(&req
->outbuf
,
1930 data_blob_const(buf
, sizeof(buf
)))
1932 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1937 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1938 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1940 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1942 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1943 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
1944 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
1945 check_descend
= True
;
1948 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1949 finished
= !get_dir_entry(ctx
,
1960 char buf
[DIR_STRUCT_SIZE
];
1961 memcpy(buf
,status
,21);
1962 if (!make_dir_struct(ctx
,
1968 convert_timespec_to_time_t(date
),
1969 !allow_long_path_components
)) {
1970 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1973 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1976 if (message_push_blob(&req
->outbuf
,
1977 data_blob_const(buf
, sizeof(buf
)))
1979 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1989 /* If we were called as SMBffirst with smb_search_id == NULL
1990 and no entries were found then return error and close dirptr
1993 if (numentries
== 0) {
1994 dptr_close(sconn
, &dptr_num
);
1995 } else if(expect_close
&& status_len
== 0) {
1996 /* Close the dptr - we know it's gone */
1997 dptr_close(sconn
, &dptr_num
);
2000 /* If we were called as SMBfunique, then we can close the dirptr now ! */
2001 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
2002 dptr_close(sconn
, &dptr_num
);
2005 if ((numentries
== 0) && !mask_contains_wcard
) {
2006 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
2010 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
2011 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
2012 SCVAL(smb_buf(req
->outbuf
),0,5);
2013 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
2015 /* The replies here are never long name. */
2016 SSVAL(req
->outbuf
, smb_flg2
,
2017 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
2018 if (!allow_long_path_components
) {
2019 SSVAL(req
->outbuf
, smb_flg2
,
2020 SVAL(req
->outbuf
, smb_flg2
)
2021 & (~FLAGS2_LONG_PATH_COMPONENTS
));
2024 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2025 SSVAL(req
->outbuf
, smb_flg2
,
2026 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
2028 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2029 smb_fn_name(req
->cmd
),
2036 TALLOC_FREE(directory
);
2038 TALLOC_FREE(smb_fname
);
2039 END_PROFILE(SMBsearch
);
2043 /****************************************************************************
2044 Reply to a fclose (stop directory search).
2045 ****************************************************************************/
2047 void reply_fclose(struct smb_request
*req
)
2055 bool path_contains_wcard
= False
;
2056 TALLOC_CTX
*ctx
= talloc_tos();
2057 struct smbd_server_connection
*sconn
= req
->sconn
;
2059 START_PROFILE(SMBfclose
);
2061 if (req
->posix_pathnames
) {
2062 reply_unknown_new(req
, req
->cmd
);
2063 END_PROFILE(SMBfclose
);
2067 p
= (const char *)req
->buf
+ 1;
2068 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
2069 &err
, &path_contains_wcard
);
2070 if (!NT_STATUS_IS_OK(err
)) {
2071 reply_nterror(req
, err
);
2072 END_PROFILE(SMBfclose
);
2076 status_len
= SVAL(p
,0);
2079 if (status_len
== 0) {
2080 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
2081 END_PROFILE(SMBfclose
);
2085 memcpy(status
,p
,21);
2087 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
2088 /* Close the dptr - we know it's gone */
2089 dptr_close(sconn
, &dptr_num
);
2092 reply_outbuf(req
, 1, 0);
2093 SSVAL(req
->outbuf
,smb_vwv0
,0);
2095 DEBUG(3,("search close\n"));
2097 END_PROFILE(SMBfclose
);
2101 /****************************************************************************
2103 ****************************************************************************/
2105 void reply_open(struct smb_request
*req
)
2107 connection_struct
*conn
= req
->conn
;
2108 struct smb_filename
*smb_fname
= NULL
;
2118 uint32_t access_mask
;
2119 uint32_t share_mode
;
2120 uint32_t create_disposition
;
2121 uint32_t create_options
= 0;
2122 uint32_t private_flags
= 0;
2125 TALLOC_CTX
*ctx
= talloc_tos();
2127 START_PROFILE(SMBopen
);
2130 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2134 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2135 deny_mode
= SVAL(req
->vwv
+0, 0);
2136 dos_attr
= SVAL(req
->vwv
+1, 0);
2138 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2139 STR_TERMINATE
, &status
);
2140 if (!NT_STATUS_IS_OK(status
)) {
2141 reply_nterror(req
, status
);
2145 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2146 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
2147 &share_mode
, &create_disposition
,
2148 &create_options
, &private_flags
)) {
2149 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2153 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2155 status
= filename_convert(ctx
,
2162 if (!NT_STATUS_IS_OK(status
)) {
2163 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2164 reply_botherror(req
,
2165 NT_STATUS_PATH_NOT_COVERED
,
2166 ERRSRV
, ERRbadpath
);
2169 reply_nterror(req
, status
);
2173 status
= SMB_VFS_CREATE_FILE(
2176 0, /* root_dir_fid */
2177 smb_fname
, /* fname */
2178 access_mask
, /* access_mask */
2179 share_mode
, /* share_access */
2180 create_disposition
, /* create_disposition*/
2181 create_options
, /* create_options */
2182 dos_attr
, /* file_attributes */
2183 oplock_request
, /* oplock_request */
2185 0, /* allocation_size */
2191 NULL
, NULL
); /* create context */
2193 if (!NT_STATUS_IS_OK(status
)) {
2194 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2195 /* We have re-scheduled this call. */
2198 reply_openerror(req
, status
);
2202 /* Ensure we're pointing at the correct stat struct. */
2203 TALLOC_FREE(smb_fname
);
2204 smb_fname
= fsp
->fsp_name
;
2206 size
= smb_fname
->st
.st_ex_size
;
2207 fattr
= dos_mode(conn
, smb_fname
);
2209 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2211 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2212 DEBUG(3,("attempt to open a directory %s\n",
2214 close_file(req
, fsp
, ERROR_CLOSE
);
2215 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2216 ERRDOS
, ERRnoaccess
);
2220 reply_outbuf(req
, 7, 0);
2221 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2222 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2223 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2224 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2226 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2228 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2229 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2231 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2232 SCVAL(req
->outbuf
,smb_flg
,
2233 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2236 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2237 SCVAL(req
->outbuf
,smb_flg
,
2238 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2241 END_PROFILE(SMBopen
);
2245 /****************************************************************************
2246 Reply to an open and X.
2247 ****************************************************************************/
2249 void reply_open_and_X(struct smb_request
*req
)
2251 connection_struct
*conn
= req
->conn
;
2252 struct smb_filename
*smb_fname
= NULL
;
2254 uint16_t open_flags
;
2257 /* Breakout the oplock request bits so we can set the
2258 reply bits separately. */
2259 int ex_oplock_request
;
2260 int core_oplock_request
;
2263 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2264 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2272 uint64_t allocation_size
;
2273 ssize_t retval
= -1;
2274 uint32_t access_mask
;
2275 uint32_t share_mode
;
2276 uint32_t create_disposition
;
2277 uint32_t create_options
= 0;
2278 uint32_t private_flags
= 0;
2280 TALLOC_CTX
*ctx
= talloc_tos();
2282 START_PROFILE(SMBopenX
);
2284 if (req
->wct
< 15) {
2285 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2289 open_flags
= SVAL(req
->vwv
+2, 0);
2290 deny_mode
= SVAL(req
->vwv
+3, 0);
2291 smb_attr
= SVAL(req
->vwv
+5, 0);
2292 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2293 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2294 oplock_request
= ex_oplock_request
| core_oplock_request
;
2295 smb_ofun
= SVAL(req
->vwv
+8, 0);
2296 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2298 /* If it's an IPC, pass off the pipe handler. */
2300 if (lp_nt_pipe_support()) {
2301 reply_open_pipe_and_X(conn
, req
);
2303 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2308 /* XXXX we need to handle passed times, sattr and flags */
2309 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2310 STR_TERMINATE
, &status
);
2311 if (!NT_STATUS_IS_OK(status
)) {
2312 reply_nterror(req
, status
);
2316 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2318 &access_mask
, &share_mode
,
2319 &create_disposition
,
2322 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2326 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2328 status
= filename_convert(ctx
,
2335 if (!NT_STATUS_IS_OK(status
)) {
2336 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2337 reply_botherror(req
,
2338 NT_STATUS_PATH_NOT_COVERED
,
2339 ERRSRV
, ERRbadpath
);
2342 reply_nterror(req
, status
);
2346 status
= SMB_VFS_CREATE_FILE(
2349 0, /* root_dir_fid */
2350 smb_fname
, /* fname */
2351 access_mask
, /* access_mask */
2352 share_mode
, /* share_access */
2353 create_disposition
, /* create_disposition*/
2354 create_options
, /* create_options */
2355 smb_attr
, /* file_attributes */
2356 oplock_request
, /* oplock_request */
2358 0, /* allocation_size */
2363 &smb_action
, /* pinfo */
2364 NULL
, NULL
); /* create context */
2366 if (!NT_STATUS_IS_OK(status
)) {
2367 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2368 /* We have re-scheduled this call. */
2371 reply_openerror(req
, status
);
2375 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2376 if the file is truncated or created. */
2377 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2378 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2379 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2380 close_file(req
, fsp
, ERROR_CLOSE
);
2381 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2384 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2386 close_file(req
, fsp
, ERROR_CLOSE
);
2387 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2390 status
= vfs_stat_fsp(fsp
);
2391 if (!NT_STATUS_IS_OK(status
)) {
2392 close_file(req
, fsp
, ERROR_CLOSE
);
2393 reply_nterror(req
, status
);
2398 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2399 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2400 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2401 close_file(req
, fsp
, ERROR_CLOSE
);
2402 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2406 /* If the caller set the extended oplock request bit
2407 and we granted one (by whatever means) - set the
2408 correct bit for extended oplock reply.
2411 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2412 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2415 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2416 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2419 /* If the caller set the core oplock request bit
2420 and we granted one (by whatever means) - set the
2421 correct bit for core oplock reply.
2424 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2425 reply_outbuf(req
, 19, 0);
2427 reply_outbuf(req
, 15, 0);
2430 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2431 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2433 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2434 SCVAL(req
->outbuf
, smb_flg
,
2435 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2438 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2439 SCVAL(req
->outbuf
, smb_flg
,
2440 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2443 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2444 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2445 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2446 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2448 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2450 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2451 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2452 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2454 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2455 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2459 TALLOC_FREE(smb_fname
);
2460 END_PROFILE(SMBopenX
);
2464 /****************************************************************************
2465 Reply to a SMBulogoffX.
2466 ****************************************************************************/
2468 void reply_ulogoffX(struct smb_request
*req
)
2470 struct smbd_server_connection
*sconn
= req
->sconn
;
2471 struct user_struct
*vuser
;
2472 struct smbXsrv_session
*session
= NULL
;
2475 START_PROFILE(SMBulogoffX
);
2477 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2480 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2481 (unsigned long long)req
->vuid
));
2483 req
->vuid
= UID_FIELD_INVALID
;
2484 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2485 END_PROFILE(SMBulogoffX
);
2489 session
= vuser
->session
;
2493 * TODO: cancel all outstanding requests on the session
2495 status
= smbXsrv_session_logoff(session
);
2496 if (!NT_STATUS_IS_OK(status
)) {
2497 DEBUG(0, ("reply_ulogoff: "
2498 "smbXsrv_session_logoff() failed: %s\n",
2499 nt_errstr(status
)));
2501 * If we hit this case, there is something completely
2502 * wrong, so we better disconnect the transport connection.
2504 END_PROFILE(SMBulogoffX
);
2505 exit_server(__location__
": smbXsrv_session_logoff failed");
2509 TALLOC_FREE(session
);
2511 reply_outbuf(req
, 2, 0);
2512 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2513 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2515 DEBUG(3, ("ulogoffX vuid=%llu\n",
2516 (unsigned long long)req
->vuid
));
2518 END_PROFILE(SMBulogoffX
);
2519 req
->vuid
= UID_FIELD_INVALID
;
2522 /****************************************************************************
2523 Reply to a mknew or a create.
2524 ****************************************************************************/
2526 void reply_mknew(struct smb_request
*req
)
2528 connection_struct
*conn
= req
->conn
;
2529 struct smb_filename
*smb_fname
= NULL
;
2532 struct smb_file_time ft
;
2534 int oplock_request
= 0;
2536 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2537 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2538 uint32_t create_disposition
;
2539 uint32_t create_options
= 0;
2541 TALLOC_CTX
*ctx
= talloc_tos();
2543 START_PROFILE(SMBcreate
);
2547 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2551 fattr
= SVAL(req
->vwv
+0, 0);
2552 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2554 if (req
->cmd
== SMBmknew
) {
2555 /* We should fail if file exists. */
2556 create_disposition
= FILE_CREATE
;
2558 /* Create if file doesn't exist, truncate if it does. */
2559 create_disposition
= FILE_OVERWRITE_IF
;
2563 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2565 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2566 STR_TERMINATE
, &status
);
2567 if (!NT_STATUS_IS_OK(status
)) {
2568 reply_nterror(req
, status
);
2572 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2573 status
= filename_convert(ctx
,
2580 if (!NT_STATUS_IS_OK(status
)) {
2581 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2582 reply_botherror(req
,
2583 NT_STATUS_PATH_NOT_COVERED
,
2584 ERRSRV
, ERRbadpath
);
2587 reply_nterror(req
, status
);
2591 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2592 DEBUG(0,("Attempt to create file (%s) with volid set - "
2593 "please report this\n",
2594 smb_fname_str_dbg(smb_fname
)));
2597 status
= SMB_VFS_CREATE_FILE(
2600 0, /* root_dir_fid */
2601 smb_fname
, /* fname */
2602 access_mask
, /* access_mask */
2603 share_mode
, /* share_access */
2604 create_disposition
, /* create_disposition*/
2605 create_options
, /* create_options */
2606 fattr
, /* file_attributes */
2607 oplock_request
, /* oplock_request */
2609 0, /* allocation_size */
2610 0, /* private_flags */
2615 NULL
, NULL
); /* create context */
2617 if (!NT_STATUS_IS_OK(status
)) {
2618 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2619 /* We have re-scheduled this call. */
2622 reply_openerror(req
, status
);
2626 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2627 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2628 if (!NT_STATUS_IS_OK(status
)) {
2629 END_PROFILE(SMBcreate
);
2633 reply_outbuf(req
, 1, 0);
2634 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2636 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2637 SCVAL(req
->outbuf
,smb_flg
,
2638 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2641 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2642 SCVAL(req
->outbuf
,smb_flg
,
2643 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2646 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2647 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2648 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2649 (unsigned int)fattr
));
2652 TALLOC_FREE(smb_fname
);
2653 END_PROFILE(SMBcreate
);
2657 /****************************************************************************
2658 Reply to a create temporary file.
2659 ****************************************************************************/
2661 void reply_ctemp(struct smb_request
*req
)
2663 connection_struct
*conn
= req
->conn
;
2664 struct smb_filename
*smb_fname
= NULL
;
2665 char *wire_name
= NULL
;
2674 TALLOC_CTX
*ctx
= talloc_tos();
2676 START_PROFILE(SMBctemp
);
2679 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2683 fattr
= SVAL(req
->vwv
+0, 0);
2684 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2686 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2687 STR_TERMINATE
, &status
);
2688 if (!NT_STATUS_IS_OK(status
)) {
2689 reply_nterror(req
, status
);
2693 for (i
= 0; i
< 10; i
++) {
2695 fname
= talloc_asprintf(ctx
,
2698 generate_random_str_list(ctx
, 5, "0123456789"));
2700 fname
= talloc_asprintf(ctx
,
2702 generate_random_str_list(ctx
, 5, "0123456789"));
2706 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2710 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2711 status
= filename_convert(ctx
, conn
,
2717 if (!NT_STATUS_IS_OK(status
)) {
2718 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2719 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2720 ERRSRV
, ERRbadpath
);
2723 reply_nterror(req
, status
);
2727 /* Create the file. */
2728 status
= SMB_VFS_CREATE_FILE(
2731 0, /* root_dir_fid */
2732 smb_fname
, /* fname */
2733 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2734 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2735 FILE_CREATE
, /* create_disposition*/
2736 0, /* create_options */
2737 fattr
, /* file_attributes */
2738 oplock_request
, /* oplock_request */
2740 0, /* allocation_size */
2741 0, /* private_flags */
2746 NULL
, NULL
); /* create context */
2748 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2750 TALLOC_FREE(smb_fname
);
2754 if (!NT_STATUS_IS_OK(status
)) {
2755 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2756 /* We have re-scheduled this call. */
2759 reply_openerror(req
, status
);
2767 /* Collision after 10 times... */
2768 reply_nterror(req
, status
);
2772 reply_outbuf(req
, 1, 0);
2773 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2775 /* the returned filename is relative to the directory */
2776 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2778 s
= fsp
->fsp_name
->base_name
;
2784 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2785 thing in the byte section. JRA */
2786 SSVALS(p
, 0, -1); /* what is this? not in spec */
2788 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2790 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2794 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2795 SCVAL(req
->outbuf
, smb_flg
,
2796 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2799 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2800 SCVAL(req
->outbuf
, smb_flg
,
2801 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2804 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2805 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2806 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2808 TALLOC_FREE(smb_fname
);
2809 TALLOC_FREE(wire_name
);
2810 END_PROFILE(SMBctemp
);
2814 /*******************************************************************
2815 Check if a user is allowed to rename a file.
2816 ********************************************************************/
2818 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2821 if (!CAN_WRITE(conn
)) {
2822 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2825 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2826 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2827 /* Only bother to read the DOS attribute if we might deny the
2828 rename on the grounds of attribute mismatch. */
2829 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2830 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2831 return NT_STATUS_NO_SUCH_FILE
;
2835 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2836 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
2837 return NT_STATUS_OK
;
2840 /* If no pathnames are open below this
2841 directory, allow the rename. */
2843 if (lp_strict_rename(SNUM(conn
))) {
2845 * Strict rename, check open file db.
2847 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
2848 return NT_STATUS_ACCESS_DENIED
;
2850 } else if (file_find_subpath(fsp
)) {
2852 * No strict rename, just look in local process.
2854 return NT_STATUS_ACCESS_DENIED
;
2856 return NT_STATUS_OK
;
2859 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2860 return NT_STATUS_OK
;
2863 return NT_STATUS_ACCESS_DENIED
;
2866 /*******************************************************************
2867 * unlink a file with all relevant access checks
2868 *******************************************************************/
2870 static NTSTATUS
do_unlink(connection_struct
*conn
,
2871 struct smb_request
*req
,
2872 struct smb_filename
*smb_fname
,
2877 uint32_t dirtype_orig
= dirtype
;
2880 bool posix_paths
= (req
!= NULL
&& req
->posix_pathnames
);
2882 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2883 smb_fname_str_dbg(smb_fname
),
2886 if (!CAN_WRITE(conn
)) {
2887 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2891 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2893 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2896 return map_nt_error_from_unix(errno
);
2899 fattr
= dos_mode(conn
, smb_fname
);
2901 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2902 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2905 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2907 return NT_STATUS_NO_SUCH_FILE
;
2910 if (!dir_check_ftype(fattr
, dirtype
)) {
2911 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2912 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2914 return NT_STATUS_NO_SUCH_FILE
;
2917 if (dirtype_orig
& 0x8000) {
2918 /* These will never be set for POSIX. */
2919 return NT_STATUS_NO_SUCH_FILE
;
2923 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2924 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2927 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2928 return NT_STATUS_NO_SUCH_FILE
;
2931 if (dirtype
& 0xFF00) {
2932 /* These will never be set for POSIX. */
2933 return NT_STATUS_NO_SUCH_FILE
;
2938 return NT_STATUS_NO_SUCH_FILE
;
2941 /* Can't delete a directory. */
2942 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2943 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2948 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2949 return NT_STATUS_OBJECT_NAME_INVALID
;
2950 #endif /* JRATEST */
2952 /* On open checks the open itself will check the share mode, so
2953 don't do it here as we'll get it wrong. */
2955 status
= SMB_VFS_CREATE_FILE
2958 0, /* root_dir_fid */
2959 smb_fname
, /* fname */
2960 DELETE_ACCESS
, /* access_mask */
2961 FILE_SHARE_NONE
, /* share_access */
2962 FILE_OPEN
, /* create_disposition*/
2963 FILE_NON_DIRECTORY_FILE
, /* create_options */
2964 /* file_attributes */
2965 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2966 FILE_ATTRIBUTE_NORMAL
,
2967 0, /* oplock_request */
2969 0, /* allocation_size */
2970 0, /* private_flags */
2975 NULL
, NULL
); /* create context */
2977 if (!NT_STATUS_IS_OK(status
)) {
2978 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2979 nt_errstr(status
)));
2983 status
= can_set_delete_on_close(fsp
, fattr
);
2984 if (!NT_STATUS_IS_OK(status
)) {
2985 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2987 smb_fname_str_dbg(smb_fname
),
2988 nt_errstr(status
)));
2989 close_file(req
, fsp
, NORMAL_CLOSE
);
2993 /* The set is across all open files on this dev/inode pair. */
2994 if (!set_delete_on_close(fsp
, True
,
2995 conn
->session_info
->security_token
,
2996 conn
->session_info
->unix_token
)) {
2997 close_file(req
, fsp
, NORMAL_CLOSE
);
2998 return NT_STATUS_ACCESS_DENIED
;
3001 return close_file(req
, fsp
, NORMAL_CLOSE
);
3004 /****************************************************************************
3005 The guts of the unlink command, split out so it may be called by the NT SMB
3007 ****************************************************************************/
3009 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
3010 uint32_t dirtype
, struct smb_filename
*smb_fname
,
3013 char *fname_dir
= NULL
;
3014 char *fname_mask
= NULL
;
3016 NTSTATUS status
= NT_STATUS_OK
;
3017 struct smb_filename
*smb_fname_dir
= NULL
;
3018 TALLOC_CTX
*ctx
= talloc_tos();
3020 /* Split up the directory from the filename/mask. */
3021 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
3022 &fname_dir
, &fname_mask
);
3023 if (!NT_STATUS_IS_OK(status
)) {
3028 * We should only check the mangled cache
3029 * here if unix_convert failed. This means
3030 * that the path in 'mask' doesn't exist
3031 * on the file system and so we need to look
3032 * for a possible mangle. This patch from
3033 * Tine Smukavec <valentin.smukavec@hermes.si>.
3036 if (!VALID_STAT(smb_fname
->st
) &&
3037 mangle_is_mangled(fname_mask
, conn
->params
)) {
3038 char *new_mask
= NULL
;
3039 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
3040 &new_mask
, conn
->params
);
3042 TALLOC_FREE(fname_mask
);
3043 fname_mask
= new_mask
;
3050 * Only one file needs to be unlinked. Append the mask back
3051 * onto the directory.
3053 TALLOC_FREE(smb_fname
->base_name
);
3054 if (ISDOT(fname_dir
)) {
3055 /* Ensure we use canonical names on open. */
3056 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3060 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3065 if (!smb_fname
->base_name
) {
3066 status
= NT_STATUS_NO_MEMORY
;
3070 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3073 status
= check_name(conn
, smb_fname
);
3074 if (!NT_STATUS_IS_OK(status
)) {
3078 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3079 if (!NT_STATUS_IS_OK(status
)) {
3085 struct smb_Dir
*dir_hnd
= NULL
;
3087 const char *dname
= NULL
;
3088 char *talloced
= NULL
;
3090 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
3091 status
= NT_STATUS_OBJECT_NAME_INVALID
;
3095 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3098 if (strequal(fname_mask
,"????????.???")) {
3099 TALLOC_FREE(fname_mask
);
3100 fname_mask
= talloc_strdup(ctx
, "*");
3102 status
= NT_STATUS_NO_MEMORY
;
3107 smb_fname_dir
= synthetic_smb_fname(talloc_tos(),
3112 if (smb_fname_dir
== NULL
) {
3113 status
= NT_STATUS_NO_MEMORY
;
3117 status
= check_name(conn
, smb_fname_dir
);
3118 if (!NT_STATUS_IS_OK(status
)) {
3122 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_dir
, fname_mask
,
3124 if (dir_hnd
== NULL
) {
3125 status
= map_nt_error_from_unix(errno
);
3129 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3130 the pattern matches against the long name, otherwise the short name
3131 We don't implement this yet XXXX
3134 status
= NT_STATUS_NO_SUCH_FILE
;
3136 while ((dname
= ReadDirName(dir_hnd
, &offset
,
3137 &smb_fname
->st
, &talloced
))) {
3138 TALLOC_CTX
*frame
= talloc_stackframe();
3140 if (!is_visible_file(conn
, fname_dir
, dname
,
3141 &smb_fname
->st
, true)) {
3143 TALLOC_FREE(talloced
);
3147 /* Quick check for "." and ".." */
3148 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
3150 TALLOC_FREE(talloced
);
3154 if(!mask_match(dname
, fname_mask
,
3155 conn
->case_sensitive
)) {
3157 TALLOC_FREE(talloced
);
3161 TALLOC_FREE(smb_fname
->base_name
);
3162 if (ISDOT(fname_dir
)) {
3163 /* Ensure we use canonical names on open. */
3164 smb_fname
->base_name
=
3165 talloc_asprintf(smb_fname
, "%s",
3168 smb_fname
->base_name
=
3169 talloc_asprintf(smb_fname
, "%s/%s",
3173 if (!smb_fname
->base_name
) {
3174 TALLOC_FREE(dir_hnd
);
3175 status
= NT_STATUS_NO_MEMORY
;
3177 TALLOC_FREE(talloced
);
3181 status
= check_name(conn
, smb_fname
);
3182 if (!NT_STATUS_IS_OK(status
)) {
3183 TALLOC_FREE(dir_hnd
);
3185 TALLOC_FREE(talloced
);
3189 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3190 if (!NT_STATUS_IS_OK(status
)) {
3191 TALLOC_FREE(dir_hnd
);
3193 TALLOC_FREE(talloced
);
3198 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3199 smb_fname
->base_name
));
3202 TALLOC_FREE(talloced
);
3204 TALLOC_FREE(dir_hnd
);
3207 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3208 status
= map_nt_error_from_unix(errno
);
3212 TALLOC_FREE(smb_fname_dir
);
3213 TALLOC_FREE(fname_dir
);
3214 TALLOC_FREE(fname_mask
);
3218 /****************************************************************************
3220 ****************************************************************************/
3222 void reply_unlink(struct smb_request
*req
)
3224 connection_struct
*conn
= req
->conn
;
3226 struct smb_filename
*smb_fname
= NULL
;
3229 bool path_contains_wcard
= False
;
3230 uint32_t ucf_flags
= UCF_COND_ALLOW_WCARD_LCOMP
|
3231 ucf_flags_from_smb_request(req
);
3232 TALLOC_CTX
*ctx
= talloc_tos();
3234 START_PROFILE(SMBunlink
);
3237 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3241 dirtype
= SVAL(req
->vwv
+0, 0);
3243 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3244 STR_TERMINATE
, &status
,
3245 &path_contains_wcard
);
3246 if (!NT_STATUS_IS_OK(status
)) {
3247 reply_nterror(req
, status
);
3251 status
= filename_convert(ctx
, conn
,
3255 &path_contains_wcard
,
3257 if (!NT_STATUS_IS_OK(status
)) {
3258 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3259 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3260 ERRSRV
, ERRbadpath
);
3263 reply_nterror(req
, status
);
3267 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3269 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
3270 path_contains_wcard
);
3271 if (!NT_STATUS_IS_OK(status
)) {
3272 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3273 /* We have re-scheduled this call. */
3276 reply_nterror(req
, status
);
3280 reply_outbuf(req
, 0, 0);
3282 TALLOC_FREE(smb_fname
);
3283 END_PROFILE(SMBunlink
);
3287 /****************************************************************************
3289 ****************************************************************************/
3291 static void fail_readraw(void)
3293 const char *errstr
= talloc_asprintf(talloc_tos(),
3294 "FAIL ! reply_readbraw: socket write fail (%s)",
3299 exit_server_cleanly(errstr
);
3302 /****************************************************************************
3303 Fake (read/write) sendfile. Returns -1 on read or write fail.
3304 ****************************************************************************/
3306 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3307 off_t startpos
, size_t nread
)
3310 size_t tosend
= nread
;
3317 bufsize
= MIN(nread
, 65536);
3319 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3323 while (tosend
> 0) {
3327 cur_read
= MIN(tosend
, bufsize
);
3328 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3334 /* If we had a short read, fill with zeros. */
3335 if (ret
< cur_read
) {
3336 memset(buf
+ ret
, '\0', cur_read
- ret
);
3339 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3340 if (ret
!= cur_read
) {
3341 int saved_errno
= errno
;
3343 * Try and give an error message saying what
3346 DEBUG(0, ("write_data failed for client %s. "
3348 smbXsrv_connection_dbg(xconn
),
3349 strerror(saved_errno
)));
3351 errno
= saved_errno
;
3355 startpos
+= cur_read
;
3359 return (ssize_t
)nread
;
3362 /****************************************************************************
3363 Deal with the case of sendfile reading less bytes from the file than
3364 requested. Fill with zeros (all we can do). Returns 0 on success
3365 ****************************************************************************/
3367 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3373 #define SHORT_SEND_BUFSIZE 1024
3374 if (nread
< headersize
) {
3375 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3376 "header for file %s (%s). Terminating\n",
3377 fsp_str_dbg(fsp
), strerror(errno
)));
3381 nread
-= headersize
;
3383 if (nread
< smb_maxcnt
) {
3384 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3386 DEBUG(0,("sendfile_short_send: malloc failed "
3387 "for file %s (%s). Terminating\n",
3388 fsp_str_dbg(fsp
), strerror(errno
)));
3392 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3393 "with zeros !\n", fsp_str_dbg(fsp
)));
3395 while (nread
< smb_maxcnt
) {
3397 * We asked for the real file size and told sendfile
3398 * to not go beyond the end of the file. But it can
3399 * happen that in between our fstat call and the
3400 * sendfile call the file was truncated. This is very
3401 * bad because we have already announced the larger
3402 * number of bytes to the client.
3404 * The best we can do now is to send 0-bytes, just as
3405 * a read from a hole in a sparse file would do.
3407 * This should happen rarely enough that I don't care
3408 * about efficiency here :-)
3413 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3414 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3415 if (ret
!= to_write
) {
3416 int saved_errno
= errno
;
3418 * Try and give an error message saying what
3421 DEBUG(0, ("write_data failed for client %s. "
3423 smbXsrv_connection_dbg(xconn
),
3424 strerror(saved_errno
)));
3425 errno
= saved_errno
;
3436 /****************************************************************************
3437 Return a readbraw error (4 bytes of zero).
3438 ****************************************************************************/
3440 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3446 smbd_lock_socket(xconn
);
3447 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3448 int saved_errno
= errno
;
3450 * Try and give an error message saying what
3453 DEBUG(0, ("write_data failed for client %s. "
3455 smbXsrv_connection_dbg(xconn
),
3456 strerror(saved_errno
)));
3457 errno
= saved_errno
;
3461 smbd_unlock_socket(xconn
);
3464 /****************************************************************************
3465 Use sendfile in readbraw.
3466 ****************************************************************************/
3468 static void send_file_readbraw(connection_struct
*conn
,
3469 struct smb_request
*req
,
3475 struct smbXsrv_connection
*xconn
= req
->xconn
;
3476 char *outbuf
= NULL
;
3480 * We can only use sendfile on a non-chained packet
3481 * but we can use on a non-oplocked file. tridge proved this
3482 * on a train in Germany :-). JRA.
3483 * reply_readbraw has already checked the length.
3486 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3487 (fsp
->wcp
== NULL
) &&
3488 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3489 ssize_t sendfile_read
= -1;
3491 DATA_BLOB header_blob
;
3493 _smb_setlen(header
,nread
);
3494 header_blob
= data_blob_const(header
, 4);
3496 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3497 &header_blob
, startpos
,
3499 if (sendfile_read
== -1) {
3500 /* Returning ENOSYS means no data at all was sent.
3501 * Do this as a normal read. */
3502 if (errno
== ENOSYS
) {
3503 goto normal_readbraw
;
3507 * Special hack for broken Linux with no working sendfile. If we
3508 * return EINTR we sent the header but not the rest of the data.
3509 * Fake this up by doing read/write calls.
3511 if (errno
== EINTR
) {
3512 /* Ensure we don't do this again. */
3513 set_use_sendfile(SNUM(conn
), False
);
3514 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3516 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3517 DEBUG(0,("send_file_readbraw: "
3518 "fake_sendfile failed for "
3522 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3527 DEBUG(0,("send_file_readbraw: sendfile failed for "
3528 "file %s (%s). Terminating\n",
3529 fsp_str_dbg(fsp
), strerror(errno
)));
3530 exit_server_cleanly("send_file_readbraw sendfile failed");
3531 } else if (sendfile_read
== 0) {
3533 * Some sendfile implementations return 0 to indicate
3534 * that there was a short read, but nothing was
3535 * actually written to the socket. In this case,
3536 * fallback to the normal read path so the header gets
3537 * the correct byte count.
3539 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3540 "bytes falling back to the normal read: "
3541 "%s\n", fsp_str_dbg(fsp
)));
3542 goto normal_readbraw
;
3545 /* Deal with possible short send. */
3546 if (sendfile_read
!= 4+nread
) {
3547 ret
= sendfile_short_send(xconn
, fsp
,
3548 sendfile_read
, 4, nread
);
3558 outbuf
= talloc_array(NULL
, char, nread
+4);
3560 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3561 (unsigned)(nread
+4)));
3562 reply_readbraw_error(xconn
);
3567 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3568 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3577 _smb_setlen(outbuf
,ret
);
3578 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3579 int saved_errno
= errno
;
3581 * Try and give an error message saying what
3584 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3585 smbXsrv_connection_dbg(xconn
),
3586 strerror(saved_errno
)));
3587 errno
= saved_errno
;
3592 TALLOC_FREE(outbuf
);
3595 /****************************************************************************
3596 Reply to a readbraw (core+ protocol).
3597 ****************************************************************************/
3599 void reply_readbraw(struct smb_request
*req
)
3601 connection_struct
*conn
= req
->conn
;
3602 struct smbXsrv_connection
*xconn
= req
->xconn
;
3603 ssize_t maxcount
,mincount
;
3607 struct lock_struct lock
;
3610 START_PROFILE(SMBreadbraw
);
3612 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3613 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3614 "raw reads/writes are disallowed.");
3618 reply_readbraw_error(xconn
);
3619 END_PROFILE(SMBreadbraw
);
3623 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3624 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3625 "'async smb echo handler = yes'\n"));
3626 reply_readbraw_error(xconn
);
3627 END_PROFILE(SMBreadbraw
);
3632 * Special check if an oplock break has been issued
3633 * and the readraw request croses on the wire, we must
3634 * return a zero length response here.
3637 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3640 * We have to do a check_fsp by hand here, as
3641 * we must always return 4 zero bytes on error,
3645 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3646 req
->vuid
!= fsp
->vuid
||
3647 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3649 * fsp could be NULL here so use the value from the packet. JRA.
3651 DEBUG(3,("reply_readbraw: fnum %d not valid "
3653 (int)SVAL(req
->vwv
+0, 0)));
3654 reply_readbraw_error(xconn
);
3655 END_PROFILE(SMBreadbraw
);
3659 /* Do a "by hand" version of CHECK_READ. */
3660 if (!(fsp
->can_read
||
3661 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3662 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3663 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3664 (int)SVAL(req
->vwv
+0, 0)));
3665 reply_readbraw_error(xconn
);
3666 END_PROFILE(SMBreadbraw
);
3670 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3672 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3673 if(req
->wct
== 10) {
3675 * This is a large offset (64 bit) read.
3678 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3681 DEBUG(0,("reply_readbraw: negative 64 bit "
3682 "readraw offset (%.0f) !\n",
3683 (double)startpos
));
3684 reply_readbraw_error(xconn
);
3685 END_PROFILE(SMBreadbraw
);
3690 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3691 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3693 /* ensure we don't overrun the packet size */
3694 maxcount
= MIN(65535,maxcount
);
3696 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3697 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3700 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3701 reply_readbraw_error(xconn
);
3702 END_PROFILE(SMBreadbraw
);
3706 if (fsp_stat(fsp
) == 0) {
3707 size
= fsp
->fsp_name
->st
.st_ex_size
;
3710 if (startpos
>= size
) {
3713 nread
= MIN(maxcount
,(size
- startpos
));
3716 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3717 if (nread
< mincount
)
3721 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3722 "min=%lu nread=%lu\n",
3723 fsp_fnum_dbg(fsp
), (double)startpos
,
3724 (unsigned long)maxcount
,
3725 (unsigned long)mincount
,
3726 (unsigned long)nread
) );
3728 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3730 DEBUG(5,("reply_readbraw finished\n"));
3732 END_PROFILE(SMBreadbraw
);
3737 #define DBGC_CLASS DBGC_LOCKING
3739 /****************************************************************************
3740 Reply to a lockread (core+ protocol).
3741 ****************************************************************************/
3743 void reply_lockread(struct smb_request
*req
)
3745 connection_struct
*conn
= req
->conn
;
3753 struct byte_range_lock
*br_lck
= NULL
;
3755 struct smbXsrv_connection
*xconn
= req
->xconn
;
3757 START_PROFILE(SMBlockread
);
3760 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3761 END_PROFILE(SMBlockread
);
3765 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3767 if (!check_fsp(conn
, req
, fsp
)) {
3768 END_PROFILE(SMBlockread
);
3772 if (!CHECK_READ(fsp
,req
)) {
3773 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3774 END_PROFILE(SMBlockread
);
3778 numtoread
= SVAL(req
->vwv
+1, 0);
3779 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3782 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3783 * protocol request that predates the read/write lock concept.
3784 * Thus instead of asking for a read lock here we need to ask
3785 * for a write lock. JRA.
3786 * Note that the requested lock size is unaffected by max_send.
3789 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3791 (uint64_t)req
->smbpid
,
3792 (uint64_t)numtoread
,
3796 False
, /* Non-blocking lock. */
3800 TALLOC_FREE(br_lck
);
3802 if (NT_STATUS_V(status
)) {
3803 reply_nterror(req
, status
);
3804 END_PROFILE(SMBlockread
);
3809 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3811 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3813 if (numtoread
> maxtoread
) {
3814 DBG_WARNING("requested read size (%zu) is greater than "
3815 "maximum allowed (%zu/%d). "
3816 "Returning short read of maximum allowed for "
3817 "compatibility with Windows 2000.\n",
3820 xconn
->smb1
.sessions
.max_send
);
3821 numtoread
= maxtoread
;
3824 reply_outbuf(req
, 5, numtoread
+ 3);
3826 data
= smb_buf(req
->outbuf
) + 3;
3828 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3831 reply_nterror(req
, map_nt_error_from_unix(errno
));
3832 END_PROFILE(SMBlockread
);
3836 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3838 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3839 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3840 p
= smb_buf(req
->outbuf
);
3841 SCVAL(p
,0,0); /* pad byte. */
3844 DEBUG(3,("lockread %s num=%d nread=%d\n",
3845 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3847 END_PROFILE(SMBlockread
);
3852 #define DBGC_CLASS DBGC_ALL
3854 /****************************************************************************
3856 ****************************************************************************/
3858 void reply_read(struct smb_request
*req
)
3860 connection_struct
*conn
= req
->conn
;
3867 struct lock_struct lock
;
3868 struct smbXsrv_connection
*xconn
= req
->xconn
;
3870 START_PROFILE(SMBread
);
3873 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3874 END_PROFILE(SMBread
);
3878 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3880 if (!check_fsp(conn
, req
, fsp
)) {
3881 END_PROFILE(SMBread
);
3885 if (!CHECK_READ(fsp
,req
)) {
3886 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3887 END_PROFILE(SMBread
);
3891 numtoread
= SVAL(req
->vwv
+1, 0);
3892 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3895 * The requested read size cannot be greater than max_send. JRA.
3897 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3899 if (numtoread
> maxtoread
) {
3900 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3901 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3902 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3903 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3904 numtoread
= maxtoread
;
3907 reply_outbuf(req
, 5, numtoread
+3);
3909 data
= smb_buf(req
->outbuf
) + 3;
3911 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3912 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3915 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3916 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3917 END_PROFILE(SMBread
);
3922 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3925 reply_nterror(req
, map_nt_error_from_unix(errno
));
3929 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3931 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3932 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3933 SCVAL(smb_buf(req
->outbuf
),0,1);
3934 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3936 DEBUG(3, ("read %s num=%d nread=%d\n",
3937 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3940 END_PROFILE(SMBread
);
3944 /****************************************************************************
3946 ****************************************************************************/
3948 size_t setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3952 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3955 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3957 SCVAL(outbuf
,smb_vwv0
,0xFF);
3958 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3959 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3960 SSVAL(outbuf
,smb_vwv6
,
3961 (smb_wct
- 4) /* offset from smb header to wct */
3962 + 1 /* the wct field */
3963 + 12 * sizeof(uint16_t) /* vwv */
3964 + 2 /* the buflen field */
3965 + 1); /* padding byte */
3966 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3967 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3968 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3969 _smb_setlen_large(outbuf
,
3970 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3974 /****************************************************************************
3975 Reply to a read and X - possibly using sendfile.
3976 ****************************************************************************/
3978 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3979 files_struct
*fsp
, off_t startpos
,
3982 struct smbXsrv_connection
*xconn
= req
->xconn
;
3984 struct lock_struct lock
;
3985 int saved_errno
= 0;
3987 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3988 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3991 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3992 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3997 * We can only use sendfile on a non-chained packet
3998 * but we can use on a non-oplocked file. tridge proved this
3999 * on a train in Germany :-). JRA.
4002 if (!req_is_in_chain(req
) &&
4004 (fsp
->base_fsp
== NULL
) &&
4005 (fsp
->wcp
== NULL
) &&
4006 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
4007 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
4010 if(fsp_stat(fsp
) == -1) {
4011 reply_nterror(req
, map_nt_error_from_unix(errno
));
4015 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4016 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4017 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4019 * We already know that we would do a short read, so don't
4020 * try the sendfile() path.
4022 goto nosendfile_read
;
4026 * Set up the packet header before send. We
4027 * assume here the sendfile will work (get the
4028 * correct amount of data).
4031 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4033 construct_reply_common_req(req
, (char *)headerbuf
);
4034 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4036 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4037 startpos
, smb_maxcnt
);
4039 saved_errno
= errno
;
4041 /* Returning ENOSYS means no data at all was sent.
4042 Do this as a normal read. */
4043 if (errno
== ENOSYS
) {
4048 * Special hack for broken Linux with no working sendfile. If we
4049 * return EINTR we sent the header but not the rest of the data.
4050 * Fake this up by doing read/write calls.
4053 if (errno
== EINTR
) {
4054 /* Ensure we don't do this again. */
4055 set_use_sendfile(SNUM(conn
), False
);
4056 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4057 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4060 saved_errno
= errno
;
4061 DEBUG(0,("send_file_readX: "
4062 "fake_sendfile failed for "
4063 "file %s (%s) for client %s. "
4066 smbXsrv_connection_dbg(xconn
),
4067 strerror(saved_errno
)));
4068 errno
= saved_errno
;
4069 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4071 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4072 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4073 /* No outbuf here means successful sendfile. */
4077 DEBUG(0,("send_file_readX: sendfile failed for file "
4078 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4080 exit_server_cleanly("send_file_readX sendfile failed");
4081 } else if (nread
== 0) {
4083 * Some sendfile implementations return 0 to indicate
4084 * that there was a short read, but nothing was
4085 * actually written to the socket. In this case,
4086 * fallback to the normal read path so the header gets
4087 * the correct byte count.
4089 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4090 "falling back to the normal read: %s\n",
4095 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4096 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4098 /* Deal with possible short send. */
4099 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4102 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4103 sizeof(headerbuf
), smb_maxcnt
);
4106 r
= "send_file_readX: sendfile_short_send failed";
4107 DEBUG(0,("%s for file %s (%s).\n",
4108 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4109 exit_server_cleanly(r
);
4112 /* No outbuf here means successful sendfile. */
4113 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4114 SMB_PERFCOUNT_END(&req
->pcd
);
4120 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4121 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4124 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4125 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4126 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4128 * We already know that we would do a short
4129 * read, so don't try the sendfile() path.
4131 goto nosendfile_read
;
4134 construct_reply_common_req(req
, (char *)headerbuf
);
4135 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4137 /* Send out the header. */
4138 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4140 if (ret
!= sizeof(headerbuf
)) {
4141 saved_errno
= errno
;
4143 * Try and give an error message saying what
4146 DEBUG(0,("send_file_readX: write_data failed for file "
4147 "%s (%s) for client %s. Terminating\n",
4149 smbXsrv_connection_dbg(xconn
),
4150 strerror(saved_errno
)));
4151 errno
= saved_errno
;
4152 exit_server_cleanly("send_file_readX sendfile failed");
4154 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4156 saved_errno
= errno
;
4157 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4158 "%s (%s) for client %s. Terminating\n",
4160 smbXsrv_connection_dbg(xconn
),
4161 strerror(saved_errno
)));
4162 errno
= saved_errno
;
4163 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4170 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4171 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4172 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4174 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4175 startpos
, smb_maxcnt
);
4176 saved_errno
= errno
;
4179 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4183 setup_readX_header((char *)req
->outbuf
, nread
);
4185 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4186 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4190 TALLOC_FREE(req
->outbuf
);
4194 /****************************************************************************
4195 Work out how much space we have for a read return.
4196 ****************************************************************************/
4198 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4200 struct smbXsrv_connection
*xconn
= req
->xconn
;
4202 if (xconn
->protocol
< PROTOCOL_NT1
) {
4203 return xconn
->smb1
.sessions
.max_send
;
4206 if (!lp_large_readwrite()) {
4207 return xconn
->smb1
.sessions
.max_send
;
4210 if (req_is_in_chain(req
)) {
4211 return xconn
->smb1
.sessions
.max_send
;
4214 if (req
->encrypted
) {
4216 * Don't take encrypted traffic up to the
4217 * limit. There are padding considerations
4218 * that make that tricky.
4220 return xconn
->smb1
.sessions
.max_send
;
4223 if (srv_is_signing_active(xconn
)) {
4227 if (!lp_unix_extensions()) {
4232 * We can do ultra-large POSIX reads.
4237 /****************************************************************************
4238 Calculate how big a read can be. Copes with all clients. It's always
4239 safe to return a short read - Windows does this.
4240 ****************************************************************************/
4242 static size_t calc_read_size(const struct smb_request
*req
,
4246 struct smbXsrv_connection
*xconn
= req
->xconn
;
4247 size_t max_pdu
= calc_max_read_pdu(req
);
4248 size_t total_size
= 0;
4249 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4250 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4253 * Windows explicitly ignores upper size of 0xFFFF.
4254 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4255 * We must do the same as these will never fit even in
4256 * an extended size NetBIOS packet.
4258 if (upper_size
== 0xFFFF) {
4262 if (xconn
->protocol
< PROTOCOL_NT1
) {
4266 total_size
= ((upper_size
<<16) | lower_size
);
4269 * LARGE_READX test shows it's always safe to return
4270 * a short read. Windows does so.
4272 return MIN(total_size
, max_len
);
4275 /****************************************************************************
4276 Reply to a read and X.
4277 ****************************************************************************/
4279 void reply_read_and_X(struct smb_request
*req
)
4281 connection_struct
*conn
= req
->conn
;
4286 bool big_readX
= False
;
4288 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4291 START_PROFILE(SMBreadX
);
4293 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4294 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4298 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4299 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4300 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4302 /* If it's an IPC, pass off the pipe handler. */
4304 reply_pipe_read_and_X(req
);
4305 END_PROFILE(SMBreadX
);
4309 if (!check_fsp(conn
, req
, fsp
)) {
4310 END_PROFILE(SMBreadX
);
4314 if (!CHECK_READ(fsp
,req
)) {
4315 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4316 END_PROFILE(SMBreadX
);
4320 upper_size
= SVAL(req
->vwv
+7, 0);
4321 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4322 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4324 * This is a heuristic to avoid keeping large
4325 * outgoing buffers around over long-lived aio
4331 if (req
->wct
== 12) {
4333 * This is a large offset (64 bit) read.
4335 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4340 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4345 if (NT_STATUS_IS_OK(status
)) {
4346 /* Read scheduled - we're done. */
4349 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4350 /* Real error - report to client. */
4351 END_PROFILE(SMBreadX
);
4352 reply_nterror(req
, status
);
4355 /* NT_STATUS_RETRY - fall back to sync read. */
4358 smbd_lock_socket(req
->xconn
);
4359 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4360 smbd_unlock_socket(req
->xconn
);
4363 END_PROFILE(SMBreadX
);
4367 /****************************************************************************
4368 Error replies to writebraw must have smb_wct == 1. Fix this up.
4369 ****************************************************************************/
4371 void error_to_writebrawerr(struct smb_request
*req
)
4373 uint8_t *old_outbuf
= req
->outbuf
;
4375 reply_outbuf(req
, 1, 0);
4377 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4378 TALLOC_FREE(old_outbuf
);
4381 /****************************************************************************
4382 Read 4 bytes of a smb packet and return the smb length of the packet.
4383 Store the result in the buffer. This version of the function will
4384 never return a session keepalive (length of zero).
4385 Timeout is in milliseconds.
4386 ****************************************************************************/
4388 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4391 uint8_t msgtype
= NBSSkeepalive
;
4393 while (msgtype
== NBSSkeepalive
) {
4396 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4398 if (!NT_STATUS_IS_OK(status
)) {
4399 char addr
[INET6_ADDRSTRLEN
];
4400 /* Try and give an error message
4401 * saying what client failed. */
4402 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4403 "client %s read error = %s.\n",
4404 get_peer_addr(fd
,addr
,sizeof(addr
)),
4405 nt_errstr(status
)));
4409 msgtype
= CVAL(inbuf
, 0);
4412 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4413 (unsigned long)len
));
4415 return NT_STATUS_OK
;
4418 /****************************************************************************
4419 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4420 ****************************************************************************/
4422 void reply_writebraw(struct smb_request
*req
)
4424 connection_struct
*conn
= req
->conn
;
4425 struct smbXsrv_connection
*xconn
= req
->xconn
;
4428 ssize_t total_written
=0;
4429 size_t numtowrite
=0;
4432 const char *data
=NULL
;
4435 struct lock_struct lock
;
4438 START_PROFILE(SMBwritebraw
);
4441 * If we ever reply with an error, it must have the SMB command
4442 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4445 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4447 if (srv_is_signing_active(xconn
)) {
4448 END_PROFILE(SMBwritebraw
);
4449 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4450 "raw reads/writes are disallowed.");
4453 if (req
->wct
< 12) {
4454 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4455 error_to_writebrawerr(req
);
4456 END_PROFILE(SMBwritebraw
);
4460 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4461 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4462 "'async smb echo handler = yes'\n"));
4463 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4464 error_to_writebrawerr(req
);
4465 END_PROFILE(SMBwritebraw
);
4469 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4470 if (!check_fsp(conn
, req
, fsp
)) {
4471 error_to_writebrawerr(req
);
4472 END_PROFILE(SMBwritebraw
);
4476 if (!CHECK_WRITE(fsp
)) {
4477 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4478 error_to_writebrawerr(req
);
4479 END_PROFILE(SMBwritebraw
);
4483 tcount
= IVAL(req
->vwv
+1, 0);
4484 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4485 write_through
= BITSETW(req
->vwv
+7,0);
4487 /* We have to deal with slightly different formats depending
4488 on whether we are using the core+ or lanman1.0 protocol */
4490 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4491 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4492 data
= smb_buf_const(req
->inbuf
);
4494 numtowrite
= SVAL(req
->vwv
+10, 0);
4495 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4498 /* Ensure we don't write bytes past the end of this packet. */
4500 * This already protects us against CVE-2017-12163.
4502 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4503 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4504 error_to_writebrawerr(req
);
4505 END_PROFILE(SMBwritebraw
);
4509 if (!fsp
->print_file
) {
4510 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4511 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4514 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4515 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4516 error_to_writebrawerr(req
);
4517 END_PROFILE(SMBwritebraw
);
4523 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4526 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4527 "wrote=%d sync=%d\n",
4528 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4529 (int)nwritten
, (int)write_through
));
4531 if (nwritten
< (ssize_t
)numtowrite
) {
4532 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4533 error_to_writebrawerr(req
);
4537 total_written
= nwritten
;
4539 /* Allocate a buffer of 64k + length. */
4540 buf
= talloc_array(NULL
, char, 65540);
4542 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4543 error_to_writebrawerr(req
);
4547 /* Return a SMBwritebraw message to the redirector to tell
4548 * it to send more bytes */
4550 memcpy(buf
, req
->inbuf
, smb_size
);
4551 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4552 SCVAL(buf
,smb_com
,SMBwritebraw
);
4553 SSVALS(buf
,smb_vwv0
,0xFFFF);
4555 if (!srv_send_smb(req
->xconn
,
4557 false, 0, /* no signing */
4558 IS_CONN_ENCRYPTED(conn
),
4560 exit_server_cleanly("reply_writebraw: srv_send_smb "
4564 /* Now read the raw data into the buffer and write it */
4565 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4567 if (!NT_STATUS_IS_OK(status
)) {
4568 exit_server_cleanly("secondary writebraw failed");
4571 /* Set up outbuf to return the correct size */
4572 reply_outbuf(req
, 1, 0);
4574 if (numtowrite
!= 0) {
4576 if (numtowrite
> 0xFFFF) {
4577 DEBUG(0,("reply_writebraw: Oversize secondary write "
4578 "raw requested (%u). Terminating\n",
4579 (unsigned int)numtowrite
));
4580 exit_server_cleanly("secondary writebraw failed");
4583 if (tcount
> nwritten
+numtowrite
) {
4584 DEBUG(3,("reply_writebraw: Client overestimated the "
4586 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4589 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4592 if (!NT_STATUS_IS_OK(status
)) {
4593 /* Try and give an error message
4594 * saying what client failed. */
4595 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4596 "raw read failed (%s) for client %s. "
4597 "Terminating\n", nt_errstr(status
),
4598 smbXsrv_connection_dbg(xconn
)));
4599 exit_server_cleanly("secondary writebraw failed");
4603 * We are not vulnerable to CVE-2017-12163
4604 * here as we are guaranteed to have numtowrite
4605 * bytes available - we just read from the client.
4607 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4608 if (nwritten
== -1) {
4610 reply_nterror(req
, map_nt_error_from_unix(errno
));
4611 error_to_writebrawerr(req
);
4615 if (nwritten
< (ssize_t
)numtowrite
) {
4616 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4617 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4621 total_written
+= nwritten
;
4626 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4628 status
= sync_file(conn
, fsp
, write_through
);
4629 if (!NT_STATUS_IS_OK(status
)) {
4630 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4631 fsp_str_dbg(fsp
), nt_errstr(status
)));
4632 reply_nterror(req
, status
);
4633 error_to_writebrawerr(req
);
4637 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4639 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4640 (int)total_written
));
4642 /* We won't return a status if write through is not selected - this
4643 * follows what WfWg does */
4644 END_PROFILE(SMBwritebraw
);
4646 if (!write_through
&& total_written
==tcount
) {
4648 #if RABBIT_PELLET_FIX
4650 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4651 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4654 if (!send_keepalive(xconn
->transport
.sock
)) {
4655 exit_server_cleanly("reply_writebraw: send of "
4656 "keepalive failed");
4659 TALLOC_FREE(req
->outbuf
);
4664 END_PROFILE(SMBwritebraw
);
4669 #define DBGC_CLASS DBGC_LOCKING
4671 /****************************************************************************
4672 Reply to a writeunlock (core+).
4673 ****************************************************************************/
4675 void reply_writeunlock(struct smb_request
*req
)
4677 connection_struct
*conn
= req
->conn
;
4678 ssize_t nwritten
= -1;
4683 NTSTATUS status
= NT_STATUS_OK
;
4685 struct lock_struct lock
;
4686 int saved_errno
= 0;
4688 START_PROFILE(SMBwriteunlock
);
4691 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4692 END_PROFILE(SMBwriteunlock
);
4696 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4698 if (!check_fsp(conn
, req
, fsp
)) {
4699 END_PROFILE(SMBwriteunlock
);
4703 if (!CHECK_WRITE(fsp
)) {
4704 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4705 END_PROFILE(SMBwriteunlock
);
4709 numtowrite
= SVAL(req
->vwv
+1, 0);
4710 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4711 data
= (const char *)req
->buf
+ 3;
4714 * Ensure client isn't asking us to write more than
4715 * they sent. CVE-2017-12163.
4717 remaining
= smbreq_bufrem(req
, data
);
4718 if (numtowrite
> remaining
) {
4719 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4720 END_PROFILE(SMBwriteunlock
);
4724 if (!fsp
->print_file
&& numtowrite
> 0) {
4725 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4726 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4729 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4730 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4731 END_PROFILE(SMBwriteunlock
);
4736 /* The special X/Open SMB protocol handling of
4737 zero length writes is *NOT* done for
4739 if(numtowrite
== 0) {
4742 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4743 saved_errno
= errno
;
4746 status
= sync_file(conn
, fsp
, False
/* write through */);
4747 if (!NT_STATUS_IS_OK(status
)) {
4748 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4749 fsp_str_dbg(fsp
), nt_errstr(status
)));
4750 reply_nterror(req
, status
);
4755 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4759 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4760 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4764 if (numtowrite
&& !fsp
->print_file
) {
4765 struct smbd_lock_element l
= {
4766 .smblctx
= req
->smbpid
,
4767 .brltype
= UNLOCK_LOCK
,
4769 .count
= numtowrite
,
4771 status
= smbd_do_unlocking(req
, fsp
, 1, &l
, WINDOWS_LOCK
);
4772 if (NT_STATUS_V(status
)) {
4773 reply_nterror(req
, status
);
4778 reply_outbuf(req
, 1, 0);
4780 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4782 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4783 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4786 END_PROFILE(SMBwriteunlock
);
4791 #define DBGC_CLASS DBGC_ALL
4793 /****************************************************************************
4795 ****************************************************************************/
4797 void reply_write(struct smb_request
*req
)
4799 connection_struct
*conn
= req
->conn
;
4802 ssize_t nwritten
= -1;
4806 struct lock_struct lock
;
4808 int saved_errno
= 0;
4810 START_PROFILE(SMBwrite
);
4813 END_PROFILE(SMBwrite
);
4814 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4818 /* If it's an IPC, pass off the pipe handler. */
4820 reply_pipe_write(req
);
4821 END_PROFILE(SMBwrite
);
4825 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4827 if (!check_fsp(conn
, req
, fsp
)) {
4828 END_PROFILE(SMBwrite
);
4832 if (!CHECK_WRITE(fsp
)) {
4833 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4834 END_PROFILE(SMBwrite
);
4838 numtowrite
= SVAL(req
->vwv
+1, 0);
4839 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4840 data
= (const char *)req
->buf
+ 3;
4843 * Ensure client isn't asking us to write more than
4844 * they sent. CVE-2017-12163.
4846 remaining
= smbreq_bufrem(req
, data
);
4847 if (numtowrite
> remaining
) {
4848 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4849 END_PROFILE(SMBwrite
);
4853 if (!fsp
->print_file
) {
4854 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4855 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4858 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4859 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4860 END_PROFILE(SMBwrite
);
4866 * X/Open SMB protocol says that if smb_vwv1 is
4867 * zero then the file size should be extended or
4868 * truncated to the size given in smb_vwv[2-3].
4871 if(numtowrite
== 0) {
4873 * This is actually an allocate call, and set EOF. JRA.
4875 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4877 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4880 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4882 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4885 trigger_write_time_update_immediate(fsp
);
4887 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4890 status
= sync_file(conn
, fsp
, False
);
4891 if (!NT_STATUS_IS_OK(status
)) {
4892 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4893 fsp_str_dbg(fsp
), nt_errstr(status
)));
4894 reply_nterror(req
, status
);
4899 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4903 if((nwritten
== 0) && (numtowrite
!= 0)) {
4904 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4908 reply_outbuf(req
, 1, 0);
4910 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4912 if (nwritten
< (ssize_t
)numtowrite
) {
4913 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4914 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4917 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4920 END_PROFILE(SMBwrite
);
4924 /****************************************************************************
4925 Ensure a buffer is a valid writeX for recvfile purposes.
4926 ****************************************************************************/
4928 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4929 (2*14) + /* word count (including bcc) */ \
4932 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4933 const uint8_t *inbuf
)
4936 unsigned int doff
= 0;
4937 size_t len
= smb_len_large(inbuf
);
4939 struct smbXsrv_open
*op
= NULL
;
4940 struct files_struct
*fsp
= NULL
;
4943 if (is_encrypted_packet(inbuf
)) {
4944 /* Can't do this on encrypted
4949 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4953 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4954 CVAL(inbuf
,smb_wct
) != 14) {
4955 DEBUG(10,("is_valid_writeX_buffer: chained or "
4956 "invalid word length.\n"));
4960 fnum
= SVAL(inbuf
, smb_vwv2
);
4961 status
= smb1srv_open_lookup(xconn
,
4965 if (!NT_STATUS_IS_OK(status
)) {
4966 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4971 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4974 if (fsp
->conn
== NULL
) {
4975 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4979 if (IS_IPC(fsp
->conn
)) {
4980 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4983 if (IS_PRINT(fsp
->conn
)) {
4984 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4987 if (fsp
->base_fsp
!= NULL
) {
4988 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4991 doff
= SVAL(inbuf
,smb_vwv11
);
4993 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4995 if (len
> doff
&& len
- doff
> 0xFFFF) {
4996 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4999 if (numtowrite
== 0) {
5000 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5004 /* Ensure the sizes match up. */
5005 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
5006 /* no pad byte...old smbclient :-( */
5007 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5009 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
5013 if (len
- doff
!= numtowrite
) {
5014 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5015 "len = %u, doff = %u, numtowrite = %u\n",
5018 (unsigned int)numtowrite
));
5022 DEBUG(10,("is_valid_writeX_buffer: true "
5023 "len = %u, doff = %u, numtowrite = %u\n",
5026 (unsigned int)numtowrite
));
5031 /****************************************************************************
5032 Reply to a write and X.
5033 ****************************************************************************/
5035 void reply_write_and_X(struct smb_request
*req
)
5037 connection_struct
*conn
= req
->conn
;
5038 struct smbXsrv_connection
*xconn
= req
->xconn
;
5040 struct lock_struct lock
;
5045 unsigned int smb_doff
;
5046 unsigned int smblen
;
5049 int saved_errno
= 0;
5051 START_PROFILE(SMBwriteX
);
5053 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5054 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5058 numtowrite
= SVAL(req
->vwv
+10, 0);
5059 smb_doff
= SVAL(req
->vwv
+11, 0);
5060 smblen
= smb_len(req
->inbuf
);
5062 if (req
->unread_bytes
> 0xFFFF ||
5063 (smblen
> smb_doff
&&
5064 smblen
- smb_doff
> 0xFFFF)) {
5065 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5068 if (req
->unread_bytes
) {
5069 /* Can't do a recvfile write on IPC$ */
5071 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5074 if (numtowrite
!= req
->unread_bytes
) {
5075 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5080 * This already protects us against CVE-2017-12163.
5082 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5083 smb_doff
+ numtowrite
> smblen
) {
5084 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5089 /* If it's an IPC, pass off the pipe handler. */
5091 if (req
->unread_bytes
) {
5092 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5095 reply_pipe_write_and_X(req
);
5099 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5100 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5101 write_through
= BITSETW(req
->vwv
+7,0);
5103 if (!check_fsp(conn
, req
, fsp
)) {
5107 if (!CHECK_WRITE(fsp
)) {
5108 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5112 data
= smb_base(req
->inbuf
) + smb_doff
;
5114 if(req
->wct
== 14) {
5116 * This is a large offset (64 bit) write.
5118 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5122 /* X/Open SMB protocol says that, unlike SMBwrite
5123 if the length is zero then NO truncation is
5124 done, just a write of zero. To truncate a file,
5127 if(numtowrite
== 0) {
5130 if (req
->unread_bytes
== 0) {
5131 status
= schedule_aio_write_and_X(conn
,
5138 if (NT_STATUS_IS_OK(status
)) {
5139 /* write scheduled - we're done. */
5142 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5143 /* Real error - report to client. */
5144 reply_nterror(req
, status
);
5147 /* NT_STATUS_RETRY - fall through to sync write. */
5150 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5151 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5154 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5155 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5159 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5160 saved_errno
= errno
;
5164 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5168 if((nwritten
== 0) && (numtowrite
!= 0)) {
5169 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5173 reply_outbuf(req
, 6, 0);
5174 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5175 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5176 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5177 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5179 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5180 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5182 status
= sync_file(conn
, fsp
, write_through
);
5183 if (!NT_STATUS_IS_OK(status
)) {
5184 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5185 fsp_str_dbg(fsp
), nt_errstr(status
)));
5186 reply_nterror(req
, status
);
5190 END_PROFILE(SMBwriteX
);
5194 if (req
->unread_bytes
) {
5195 /* writeX failed. drain socket. */
5196 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5197 req
->unread_bytes
) {
5198 smb_panic("failed to drain pending bytes");
5200 req
->unread_bytes
= 0;
5203 END_PROFILE(SMBwriteX
);
5207 /****************************************************************************
5209 ****************************************************************************/
5211 void reply_lseek(struct smb_request
*req
)
5213 connection_struct
*conn
= req
->conn
;
5219 START_PROFILE(SMBlseek
);
5222 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5223 END_PROFILE(SMBlseek
);
5227 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5229 if (!check_fsp(conn
, req
, fsp
)) {
5233 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5235 mode
= SVAL(req
->vwv
+1, 0) & 3;
5236 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5237 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5246 res
= fsp
->fh
->pos
+ startpos
;
5257 if (umode
== SEEK_END
) {
5258 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5259 if(errno
== EINVAL
) {
5260 off_t current_pos
= startpos
;
5262 if(fsp_stat(fsp
) == -1) {
5264 map_nt_error_from_unix(errno
));
5265 END_PROFILE(SMBlseek
);
5269 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5271 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5276 reply_nterror(req
, map_nt_error_from_unix(errno
));
5277 END_PROFILE(SMBlseek
);
5284 reply_outbuf(req
, 2, 0);
5285 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5287 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5288 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5290 END_PROFILE(SMBlseek
);
5294 static struct files_struct
*file_sync_one_fn(struct files_struct
*fsp
,
5297 connection_struct
*conn
= talloc_get_type_abort(
5298 private_data
, connection_struct
);
5300 if (conn
!= fsp
->conn
) {
5303 if (fsp
->fh
->fd
== -1) {
5306 sync_file(conn
, fsp
, True
/* write through */);
5311 /****************************************************************************
5313 ****************************************************************************/
5315 void reply_flush(struct smb_request
*req
)
5317 connection_struct
*conn
= req
->conn
;
5321 START_PROFILE(SMBflush
);
5324 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5328 fnum
= SVAL(req
->vwv
+0, 0);
5329 fsp
= file_fsp(req
, fnum
);
5331 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5336 files_forall(req
->sconn
, file_sync_one_fn
, conn
);
5338 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5339 if (!NT_STATUS_IS_OK(status
)) {
5340 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5341 fsp_str_dbg(fsp
), nt_errstr(status
)));
5342 reply_nterror(req
, status
);
5343 END_PROFILE(SMBflush
);
5348 reply_outbuf(req
, 0, 0);
5350 DEBUG(3,("flush\n"));
5351 END_PROFILE(SMBflush
);
5355 /****************************************************************************
5357 conn POINTER CAN BE NULL HERE !
5358 ****************************************************************************/
5360 void reply_exit(struct smb_request
*req
)
5362 START_PROFILE(SMBexit
);
5364 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5366 reply_outbuf(req
, 0, 0);
5368 DEBUG(3,("exit\n"));
5370 END_PROFILE(SMBexit
);
5374 struct reply_close_state
{
5376 struct smb_request
*smbreq
;
5379 static void do_smb1_close(struct tevent_req
*req
);
5381 void reply_close(struct smb_request
*req
)
5383 connection_struct
*conn
= req
->conn
;
5384 NTSTATUS status
= NT_STATUS_OK
;
5385 files_struct
*fsp
= NULL
;
5386 START_PROFILE(SMBclose
);
5389 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5390 END_PROFILE(SMBclose
);
5394 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5397 * We can only use check_fsp if we know it's not a directory.
5400 if (!check_fsp_open(conn
, req
, fsp
)) {
5401 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5402 END_PROFILE(SMBclose
);
5406 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5407 fsp
->is_directory
? "directory" : "file",
5408 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5409 conn
->num_files_open
));
5411 if (!fsp
->is_directory
) {
5415 * Take care of any time sent in the close.
5418 t
= srv_make_unix_date3(req
->vwv
+1);
5419 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5422 if (fsp
->num_aio_requests
!= 0) {
5424 struct reply_close_state
*state
;
5426 DEBUG(10, ("closing with aio %u requests pending\n",
5427 fsp
->num_aio_requests
));
5430 * We depend on the aio_extra destructor to take care of this
5431 * close request once fsp->num_aio_request drops to 0.
5434 fsp
->deferred_close
= tevent_wait_send(
5435 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5436 if (fsp
->deferred_close
== NULL
) {
5437 status
= NT_STATUS_NO_MEMORY
;
5441 state
= talloc(fsp
, struct reply_close_state
);
5442 if (state
== NULL
) {
5443 TALLOC_FREE(fsp
->deferred_close
);
5444 status
= NT_STATUS_NO_MEMORY
;
5448 state
->smbreq
= talloc_move(fsp
, &req
);
5449 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5451 END_PROFILE(SMBclose
);
5456 * close_file() returns the unix errno if an error was detected on
5457 * close - normally this is due to a disk full error. If not then it
5458 * was probably an I/O error.
5461 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5463 if (!NT_STATUS_IS_OK(status
)) {
5464 reply_nterror(req
, status
);
5465 END_PROFILE(SMBclose
);
5469 reply_outbuf(req
, 0, 0);
5470 END_PROFILE(SMBclose
);
5474 static void do_smb1_close(struct tevent_req
*req
)
5476 struct reply_close_state
*state
= tevent_req_callback_data(
5477 req
, struct reply_close_state
);
5478 struct smb_request
*smbreq
;
5482 ret
= tevent_wait_recv(req
);
5485 DEBUG(10, ("tevent_wait_recv returned %s\n",
5488 * Continue anyway, this should never happen
5493 * fsp->smb2_close_request right now is a talloc grandchild of
5494 * fsp. When we close_file(fsp), it would go with it. No chance to
5497 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5499 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5500 if (NT_STATUS_IS_OK(status
)) {
5501 reply_outbuf(smbreq
, 0, 0);
5503 reply_nterror(smbreq
, status
);
5505 if (!srv_send_smb(smbreq
->xconn
,
5506 (char *)smbreq
->outbuf
,
5509 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5511 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5514 TALLOC_FREE(smbreq
);
5517 /****************************************************************************
5518 Reply to a writeclose (Core+ protocol).
5519 ****************************************************************************/
5521 void reply_writeclose(struct smb_request
*req
)
5523 connection_struct
*conn
= req
->conn
;
5526 ssize_t nwritten
= -1;
5527 NTSTATUS close_status
= NT_STATUS_OK
;
5530 struct timespec mtime
;
5532 struct lock_struct lock
;
5534 START_PROFILE(SMBwriteclose
);
5537 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5538 END_PROFILE(SMBwriteclose
);
5542 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5544 if (!check_fsp(conn
, req
, fsp
)) {
5545 END_PROFILE(SMBwriteclose
);
5548 if (!CHECK_WRITE(fsp
)) {
5549 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5550 END_PROFILE(SMBwriteclose
);
5554 numtowrite
= SVAL(req
->vwv
+1, 0);
5555 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5556 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5557 data
= (const char *)req
->buf
+ 1;
5560 * Ensure client isn't asking us to write more than
5561 * they sent. CVE-2017-12163.
5563 remaining
= smbreq_bufrem(req
, data
);
5564 if (numtowrite
> remaining
) {
5565 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5566 END_PROFILE(SMBwriteclose
);
5570 if (fsp
->print_file
== NULL
) {
5571 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5572 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5575 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5576 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5577 END_PROFILE(SMBwriteclose
);
5582 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5584 set_close_write_time(fsp
, mtime
);
5587 * More insanity. W2K only closes the file if writelen > 0.
5591 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5592 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5593 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5596 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5597 "file %s\n", fsp_str_dbg(fsp
)));
5598 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5602 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5603 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5607 if(!NT_STATUS_IS_OK(close_status
)) {
5608 reply_nterror(req
, close_status
);
5612 reply_outbuf(req
, 1, 0);
5614 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5618 END_PROFILE(SMBwriteclose
);
5623 #define DBGC_CLASS DBGC_LOCKING
5625 /****************************************************************************
5627 ****************************************************************************/
5629 void reply_lock(struct smb_request
*req
)
5631 connection_struct
*conn
= req
->conn
;
5632 uint64_t count
,offset
;
5635 struct byte_range_lock
*br_lck
= NULL
;
5637 START_PROFILE(SMBlock
);
5640 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5641 END_PROFILE(SMBlock
);
5645 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5647 if (!check_fsp(conn
, req
, fsp
)) {
5648 END_PROFILE(SMBlock
);
5652 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5653 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5655 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5656 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5658 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5660 (uint64_t)req
->smbpid
,
5665 False
, /* Non-blocking lock. */
5670 TALLOC_FREE(br_lck
);
5672 if (NT_STATUS_V(status
)) {
5673 reply_nterror(req
, status
);
5674 END_PROFILE(SMBlock
);
5678 reply_outbuf(req
, 0, 0);
5680 END_PROFILE(SMBlock
);
5684 /****************************************************************************
5686 ****************************************************************************/
5688 void reply_unlock(struct smb_request
*req
)
5690 connection_struct
*conn
= req
->conn
;
5693 struct smbd_lock_element lck
;
5695 START_PROFILE(SMBunlock
);
5698 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5699 END_PROFILE(SMBunlock
);
5703 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5705 if (!check_fsp(conn
, req
, fsp
)) {
5706 END_PROFILE(SMBunlock
);
5710 lck
= (struct smbd_lock_element
) {
5711 .smblctx
= req
->smbpid
,
5712 .brltype
= UNLOCK_LOCK
,
5713 .offset
= IVAL(req
->vwv
+3, 0),
5714 .count
= IVAL(req
->vwv
+1, 0),
5717 status
= smbd_do_unlocking(req
, fsp
, 1, &lck
, WINDOWS_LOCK
);
5719 if (!NT_STATUS_IS_OK(status
)) {
5720 reply_nterror(req
, status
);
5721 END_PROFILE(SMBunlock
);
5725 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
5731 reply_outbuf(req
, 0, 0);
5733 END_PROFILE(SMBunlock
);
5738 #define DBGC_CLASS DBGC_ALL
5740 /****************************************************************************
5742 conn POINTER CAN BE NULL HERE !
5743 ****************************************************************************/
5745 void reply_tdis(struct smb_request
*req
)
5748 connection_struct
*conn
= req
->conn
;
5749 struct smbXsrv_tcon
*tcon
;
5751 START_PROFILE(SMBtdis
);
5754 DEBUG(4,("Invalid connection in tdis\n"));
5755 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5756 END_PROFILE(SMBtdis
);
5764 * TODO: cancel all outstanding requests on the tcon
5766 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5767 if (!NT_STATUS_IS_OK(status
)) {
5768 DEBUG(0, ("reply_tdis: "
5769 "smbXsrv_tcon_disconnect() failed: %s\n",
5770 nt_errstr(status
)));
5772 * If we hit this case, there is something completely
5773 * wrong, so we better disconnect the transport connection.
5775 END_PROFILE(SMBtdis
);
5776 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5782 reply_outbuf(req
, 0, 0);
5783 END_PROFILE(SMBtdis
);
5787 /****************************************************************************
5789 conn POINTER CAN BE NULL HERE !
5790 ****************************************************************************/
5792 void reply_echo(struct smb_request
*req
)
5794 connection_struct
*conn
= req
->conn
;
5795 struct smb_perfcount_data local_pcd
;
5796 struct smb_perfcount_data
*cur_pcd
;
5800 START_PROFILE(SMBecho
);
5802 smb_init_perfcount_data(&local_pcd
);
5805 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5806 END_PROFILE(SMBecho
);
5810 smb_reverb
= SVAL(req
->vwv
+0, 0);
5812 reply_outbuf(req
, 1, req
->buflen
);
5814 /* copy any incoming data back out */
5815 if (req
->buflen
> 0) {
5816 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5819 if (smb_reverb
> 100) {
5820 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5824 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5826 /* this makes sure we catch the request pcd */
5827 if (seq_num
== smb_reverb
) {
5828 cur_pcd
= &req
->pcd
;
5830 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5831 cur_pcd
= &local_pcd
;
5834 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5836 show_msg((char *)req
->outbuf
);
5837 if (!srv_send_smb(req
->xconn
,
5838 (char *)req
->outbuf
,
5839 true, req
->seqnum
+1,
5840 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5842 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5845 DEBUG(3,("echo %d times\n", smb_reverb
));
5847 TALLOC_FREE(req
->outbuf
);
5849 END_PROFILE(SMBecho
);
5853 /****************************************************************************
5854 Reply to a printopen.
5855 ****************************************************************************/
5857 void reply_printopen(struct smb_request
*req
)
5859 connection_struct
*conn
= req
->conn
;
5863 START_PROFILE(SMBsplopen
);
5866 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5867 END_PROFILE(SMBsplopen
);
5871 if (!CAN_PRINT(conn
)) {
5872 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5873 END_PROFILE(SMBsplopen
);
5877 status
= file_new(req
, conn
, &fsp
);
5878 if(!NT_STATUS_IS_OK(status
)) {
5879 reply_nterror(req
, status
);
5880 END_PROFILE(SMBsplopen
);
5884 /* Open for exclusive use, write only. */
5885 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5887 if (!NT_STATUS_IS_OK(status
)) {
5888 file_free(req
, fsp
);
5889 reply_nterror(req
, status
);
5890 END_PROFILE(SMBsplopen
);
5894 reply_outbuf(req
, 1, 0);
5895 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5897 DEBUG(3,("openprint fd=%d %s\n",
5898 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5900 END_PROFILE(SMBsplopen
);
5904 /****************************************************************************
5905 Reply to a printclose.
5906 ****************************************************************************/
5908 void reply_printclose(struct smb_request
*req
)
5910 connection_struct
*conn
= req
->conn
;
5914 START_PROFILE(SMBsplclose
);
5917 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5918 END_PROFILE(SMBsplclose
);
5922 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5924 if (!check_fsp(conn
, req
, fsp
)) {
5925 END_PROFILE(SMBsplclose
);
5929 if (!CAN_PRINT(conn
)) {
5930 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5931 END_PROFILE(SMBsplclose
);
5935 DEBUG(3,("printclose fd=%d %s\n",
5936 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5938 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5940 if(!NT_STATUS_IS_OK(status
)) {
5941 reply_nterror(req
, status
);
5942 END_PROFILE(SMBsplclose
);
5946 reply_outbuf(req
, 0, 0);
5948 END_PROFILE(SMBsplclose
);
5952 /****************************************************************************
5953 Reply to a printqueue.
5954 ****************************************************************************/
5956 void reply_printqueue(struct smb_request
*req
)
5958 connection_struct
*conn
= req
->conn
;
5962 START_PROFILE(SMBsplretq
);
5965 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5966 END_PROFILE(SMBsplretq
);
5970 max_count
= SVAL(req
->vwv
+0, 0);
5971 start_index
= SVAL(req
->vwv
+1, 0);
5973 /* we used to allow the client to get the cnum wrong, but that
5974 is really quite gross and only worked when there was only
5975 one printer - I think we should now only accept it if they
5976 get it right (tridge) */
5977 if (!CAN_PRINT(conn
)) {
5978 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5979 END_PROFILE(SMBsplretq
);
5983 reply_outbuf(req
, 2, 3);
5984 SSVAL(req
->outbuf
,smb_vwv0
,0);
5985 SSVAL(req
->outbuf
,smb_vwv1
,0);
5986 SCVAL(smb_buf(req
->outbuf
),0,1);
5987 SSVAL(smb_buf(req
->outbuf
),1,0);
5989 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5990 start_index
, max_count
));
5993 TALLOC_CTX
*mem_ctx
= talloc_tos();
5996 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5997 struct rpc_pipe_client
*cli
= NULL
;
5998 struct dcerpc_binding_handle
*b
= NULL
;
5999 struct policy_handle handle
;
6000 struct spoolss_DevmodeContainer devmode_ctr
;
6001 union spoolss_JobInfo
*info
;
6003 uint32_t num_to_get
;
6007 ZERO_STRUCT(handle
);
6009 status
= rpc_pipe_open_interface(mem_ctx
,
6012 conn
->sconn
->remote_address
,
6013 conn
->sconn
->local_address
,
6014 conn
->sconn
->msg_ctx
,
6016 if (!NT_STATUS_IS_OK(status
)) {
6017 DEBUG(0, ("reply_printqueue: "
6018 "could not connect to spoolss: %s\n",
6019 nt_errstr(status
)));
6020 reply_nterror(req
, status
);
6023 b
= cli
->binding_handle
;
6025 ZERO_STRUCT(devmode_ctr
);
6027 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
6030 SEC_FLAG_MAXIMUM_ALLOWED
,
6033 if (!NT_STATUS_IS_OK(status
)) {
6034 reply_nterror(req
, status
);
6037 if (!W_ERROR_IS_OK(werr
)) {
6038 reply_nterror(req
, werror_to_ntstatus(werr
));
6042 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
6050 if (!W_ERROR_IS_OK(werr
)) {
6051 reply_nterror(req
, werror_to_ntstatus(werr
));
6055 if (max_count
> 0) {
6056 first
= start_index
;
6058 first
= start_index
+ max_count
+ 1;
6061 if (first
>= count
) {
6064 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6067 for (i
= first
; i
< num_to_get
; i
++) {
6070 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6073 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6074 info
[i
].info2
.job_id
);
6076 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6082 srv_put_dos_date2(p
, 0, qtime
);
6083 SCVAL(p
, 4, qstatus
);
6084 SSVAL(p
, 5, qrapjobid
);
6085 SIVAL(p
, 7, info
[i
].info2
.size
);
6087 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6088 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6089 if (!NT_STATUS_IS_OK(status
)) {
6090 reply_nterror(req
, status
);
6093 if (message_push_blob(
6096 blob
, sizeof(blob
))) == -1) {
6097 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6103 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6104 SSVAL(req
->outbuf
,smb_vwv1
,
6105 (max_count
>0?first
+count
:first
-1));
6106 SCVAL(smb_buf(req
->outbuf
),0,1);
6107 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6111 DEBUG(3, ("%u entries returned in queue\n",
6115 if (b
&& is_valid_policy_hnd(&handle
)) {
6116 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6121 END_PROFILE(SMBsplretq
);
6125 /****************************************************************************
6126 Reply to a printwrite.
6127 ****************************************************************************/
6129 void reply_printwrite(struct smb_request
*req
)
6131 connection_struct
*conn
= req
->conn
;
6136 START_PROFILE(SMBsplwr
);
6139 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6140 END_PROFILE(SMBsplwr
);
6144 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6146 if (!check_fsp(conn
, req
, fsp
)) {
6147 END_PROFILE(SMBsplwr
);
6151 if (!fsp
->print_file
) {
6152 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6153 END_PROFILE(SMBsplwr
);
6157 if (!CHECK_WRITE(fsp
)) {
6158 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6159 END_PROFILE(SMBsplwr
);
6163 numtowrite
= SVAL(req
->buf
, 1);
6166 * This already protects us against CVE-2017-12163.
6168 if (req
->buflen
< numtowrite
+ 3) {
6169 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6170 END_PROFILE(SMBsplwr
);
6174 data
= (const char *)req
->buf
+ 3;
6176 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6177 reply_nterror(req
, map_nt_error_from_unix(errno
));
6178 END_PROFILE(SMBsplwr
);
6182 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6184 END_PROFILE(SMBsplwr
);
6188 /****************************************************************************
6190 ****************************************************************************/
6192 void reply_mkdir(struct smb_request
*req
)
6194 connection_struct
*conn
= req
->conn
;
6195 struct smb_filename
*smb_dname
= NULL
;
6196 char *directory
= NULL
;
6199 TALLOC_CTX
*ctx
= talloc_tos();
6201 START_PROFILE(SMBmkdir
);
6203 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6204 STR_TERMINATE
, &status
);
6205 if (!NT_STATUS_IS_OK(status
)) {
6206 reply_nterror(req
, status
);
6210 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
6211 status
= filename_convert(ctx
, conn
,
6217 if (!NT_STATUS_IS_OK(status
)) {
6218 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6219 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6220 ERRSRV
, ERRbadpath
);
6223 reply_nterror(req
, status
);
6227 status
= create_directory(conn
, req
, smb_dname
);
6229 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6231 if (!NT_STATUS_IS_OK(status
)) {
6233 if (!use_nt_status()
6234 && NT_STATUS_EQUAL(status
,
6235 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6237 * Yes, in the DOS error code case we get a
6238 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6239 * samba4 torture test.
6241 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6244 reply_nterror(req
, status
);
6248 reply_outbuf(req
, 0, 0);
6250 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6252 TALLOC_FREE(smb_dname
);
6253 END_PROFILE(SMBmkdir
);
6257 /****************************************************************************
6259 ****************************************************************************/
6261 void reply_rmdir(struct smb_request
*req
)
6263 connection_struct
*conn
= req
->conn
;
6264 struct smb_filename
*smb_dname
= NULL
;
6265 char *directory
= NULL
;
6267 TALLOC_CTX
*ctx
= talloc_tos();
6268 files_struct
*fsp
= NULL
;
6270 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6271 struct smbd_server_connection
*sconn
= req
->sconn
;
6273 START_PROFILE(SMBrmdir
);
6275 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6276 STR_TERMINATE
, &status
);
6277 if (!NT_STATUS_IS_OK(status
)) {
6278 reply_nterror(req
, status
);
6282 status
= filename_convert(ctx
, conn
,
6288 if (!NT_STATUS_IS_OK(status
)) {
6289 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6290 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6291 ERRSRV
, ERRbadpath
);
6294 reply_nterror(req
, status
);
6298 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6299 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6303 status
= SMB_VFS_CREATE_FILE(
6306 0, /* root_dir_fid */
6307 smb_dname
, /* fname */
6308 DELETE_ACCESS
, /* access_mask */
6309 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6311 FILE_OPEN
, /* create_disposition*/
6312 FILE_DIRECTORY_FILE
, /* create_options */
6313 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6314 0, /* oplock_request */
6316 0, /* allocation_size */
6317 0, /* private_flags */
6322 NULL
, NULL
); /* create context */
6324 if (!NT_STATUS_IS_OK(status
)) {
6325 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6326 /* We have re-scheduled this call. */
6329 reply_nterror(req
, status
);
6333 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6334 if (!NT_STATUS_IS_OK(status
)) {
6335 close_file(req
, fsp
, ERROR_CLOSE
);
6336 reply_nterror(req
, status
);
6340 if (!set_delete_on_close(fsp
, true,
6341 conn
->session_info
->security_token
,
6342 conn
->session_info
->unix_token
)) {
6343 close_file(req
, fsp
, ERROR_CLOSE
);
6344 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6348 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6349 if (!NT_STATUS_IS_OK(status
)) {
6350 reply_nterror(req
, status
);
6352 reply_outbuf(req
, 0, 0);
6355 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6357 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6359 TALLOC_FREE(smb_dname
);
6360 END_PROFILE(SMBrmdir
);
6364 /*******************************************************************
6365 Resolve wildcards in a filename rename.
6366 ********************************************************************/
6368 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6373 char *name2_copy
= NULL
;
6378 char *p
,*p2
, *pname1
, *pname2
;
6380 name2_copy
= talloc_strdup(ctx
, name2
);
6385 pname1
= strrchr_m(name1
,'/');
6386 pname2
= strrchr_m(name2_copy
,'/');
6388 if (!pname1
|| !pname2
) {
6392 /* Truncate the copy of name2 at the last '/' */
6395 /* Now go past the '/' */
6399 root1
= talloc_strdup(ctx
, pname1
);
6400 root2
= talloc_strdup(ctx
, pname2
);
6402 if (!root1
|| !root2
) {
6406 p
= strrchr_m(root1
,'.');
6409 ext1
= talloc_strdup(ctx
, p
+1);
6411 ext1
= talloc_strdup(ctx
, "");
6413 p
= strrchr_m(root2
,'.');
6416 ext2
= talloc_strdup(ctx
, p
+1);
6418 ext2
= talloc_strdup(ctx
, "");
6421 if (!ext1
|| !ext2
) {
6429 /* Hmmm. Should this be mb-aware ? */
6432 } else if (*p2
== '*') {
6434 root2
= talloc_asprintf(ctx
, "%s%s",
6453 /* Hmmm. Should this be mb-aware ? */
6456 } else if (*p2
== '*') {
6458 ext2
= talloc_asprintf(ctx
, "%s%s",
6474 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6479 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6491 /****************************************************************************
6492 Ensure open files have their names updated. Updated to notify other smbd's
6494 ****************************************************************************/
6496 static void rename_open_files(connection_struct
*conn
,
6497 struct share_mode_lock
*lck
,
6499 uint32_t orig_name_hash
,
6500 const struct smb_filename
*smb_fname_dst
)
6503 bool did_rename
= False
;
6505 uint32_t new_name_hash
= 0;
6507 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6508 fsp
= file_find_di_next(fsp
)) {
6509 /* fsp_name is a relative path under the fsp. To change this for other
6510 sharepaths we need to manipulate relative paths. */
6511 /* TODO - create the absolute path and manipulate the newname
6512 relative to the sharepath. */
6513 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6516 if (fsp
->name_hash
!= orig_name_hash
) {
6519 DEBUG(10, ("rename_open_files: renaming file %s "
6520 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6521 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6522 smb_fname_str_dbg(smb_fname_dst
)));
6524 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6525 if (NT_STATUS_IS_OK(status
)) {
6527 new_name_hash
= fsp
->name_hash
;
6532 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6533 "for %s\n", file_id_string_tos(&id
),
6534 smb_fname_str_dbg(smb_fname_dst
)));
6537 /* Send messages to all smbd's (not ourself) that the name has changed. */
6538 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6539 orig_name_hash
, new_name_hash
,
6544 /****************************************************************************
6545 We need to check if the source path is a parent directory of the destination
6546 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6547 refuse the rename with a sharing violation. Under UNIX the above call can
6548 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6549 probably need to check that the client is a Windows one before disallowing
6550 this as a UNIX client (one with UNIX extensions) can know the source is a
6551 symlink and make this decision intelligently. Found by an excellent bug
6552 report from <AndyLiebman@aol.com>.
6553 ****************************************************************************/
6555 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6556 const struct smb_filename
*smb_fname_dst
)
6558 const char *psrc
= smb_fname_src
->base_name
;
6559 const char *pdst
= smb_fname_dst
->base_name
;
6562 if (psrc
[0] == '.' && psrc
[1] == '/') {
6565 if (pdst
[0] == '.' && pdst
[1] == '/') {
6568 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6571 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6575 * Do the notify calls from a rename
6578 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6579 const struct smb_filename
*smb_fname_src
,
6580 const struct smb_filename
*smb_fname_dst
)
6582 char *parent_dir_src
= NULL
;
6583 char *parent_dir_dst
= NULL
;
6586 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6587 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6589 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6590 &parent_dir_src
, NULL
) ||
6591 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6592 &parent_dir_dst
, NULL
)) {
6596 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6597 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6598 smb_fname_src
->base_name
);
6599 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6600 smb_fname_dst
->base_name
);
6603 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6604 smb_fname_src
->base_name
);
6605 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6606 smb_fname_dst
->base_name
);
6609 /* this is a strange one. w2k3 gives an additional event for
6610 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6611 files, but not directories */
6613 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6614 FILE_NOTIFY_CHANGE_ATTRIBUTES
6615 |FILE_NOTIFY_CHANGE_CREATION
,
6616 smb_fname_dst
->base_name
);
6619 TALLOC_FREE(parent_dir_src
);
6620 TALLOC_FREE(parent_dir_dst
);
6623 /****************************************************************************
6624 Returns an error if the parent directory for a filename is open in an
6626 ****************************************************************************/
6628 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6629 const struct smb_filename
*smb_fname_dst_in
)
6631 char *parent_dir
= NULL
;
6632 struct smb_filename smb_fname_parent
;
6634 files_struct
*fsp
= NULL
;
6637 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6638 &parent_dir
, NULL
)) {
6639 return NT_STATUS_NO_MEMORY
;
6641 ZERO_STRUCT(smb_fname_parent
);
6642 smb_fname_parent
.base_name
= parent_dir
;
6644 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6646 return map_nt_error_from_unix(errno
);
6650 * We're only checking on this smbd here, mostly good
6651 * enough.. and will pass tests.
6654 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6655 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6656 fsp
= file_find_di_next(fsp
)) {
6657 if (fsp
->access_mask
& DELETE_ACCESS
) {
6658 return NT_STATUS_SHARING_VIOLATION
;
6661 return NT_STATUS_OK
;
6664 /****************************************************************************
6665 Rename an open file - given an fsp.
6666 ****************************************************************************/
6668 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6670 const struct smb_filename
*smb_fname_dst_in
,
6672 bool replace_if_exists
)
6674 TALLOC_CTX
*ctx
= talloc_tos();
6675 struct smb_filename
*smb_fname_dst
= NULL
;
6676 NTSTATUS status
= NT_STATUS_OK
;
6677 struct share_mode_lock
*lck
= NULL
;
6678 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
6679 bool dst_exists
, old_is_stream
, new_is_stream
;
6681 status
= check_name(conn
, smb_fname_dst_in
);
6682 if (!NT_STATUS_IS_OK(status
)) {
6686 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6687 if (!NT_STATUS_IS_OK(status
)) {
6691 if (file_has_open_streams(fsp
)) {
6692 return NT_STATUS_ACCESS_DENIED
;
6695 /* Make a copy of the dst smb_fname structs */
6697 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6698 if (smb_fname_dst
== NULL
) {
6699 status
= NT_STATUS_NO_MEMORY
;
6704 * Check for special case with case preserving and not
6705 * case sensitive. If the new last component differs from the original
6706 * last component only by case, then we should allow
6707 * the rename (user is trying to change the case of the
6710 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
6711 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6712 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6713 char *fname_dst_parent
= NULL
;
6714 const char *fname_dst_lcomp
= NULL
;
6715 char *orig_lcomp_path
= NULL
;
6716 char *orig_lcomp_stream
= NULL
;
6720 * Split off the last component of the processed
6721 * destination name. We will compare this to
6722 * the split components of smb_fname_dst->original_lcomp.
6724 if (!parent_dirname(ctx
,
6725 smb_fname_dst
->base_name
,
6727 &fname_dst_lcomp
)) {
6728 status
= NT_STATUS_NO_MEMORY
;
6733 * The original_lcomp component contains
6734 * the last_component of the path + stream
6735 * name (if a stream exists).
6737 * Split off the stream name so we
6738 * can check them separately.
6741 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
6742 /* POSIX - no stream component. */
6743 orig_lcomp_path
= talloc_strdup(ctx
,
6744 smb_fname_dst
->original_lcomp
);
6745 if (orig_lcomp_path
== NULL
) {
6749 ok
= split_stream_filename(ctx
,
6750 smb_fname_dst
->original_lcomp
,
6752 &orig_lcomp_stream
);
6756 TALLOC_FREE(fname_dst_parent
);
6757 status
= NT_STATUS_NO_MEMORY
;
6761 /* If the base names only differ by case, use original. */
6762 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
6765 * Replace the modified last component with the
6768 if (!ISDOT(fname_dst_parent
)) {
6769 tmp
= talloc_asprintf(smb_fname_dst
,
6774 tmp
= talloc_strdup(smb_fname_dst
,
6778 status
= NT_STATUS_NO_MEMORY
;
6779 TALLOC_FREE(fname_dst_parent
);
6780 TALLOC_FREE(orig_lcomp_path
);
6781 TALLOC_FREE(orig_lcomp_stream
);
6784 TALLOC_FREE(smb_fname_dst
->base_name
);
6785 smb_fname_dst
->base_name
= tmp
;
6788 /* If the stream_names only differ by case, use original. */
6789 if(!strcsequal(smb_fname_dst
->stream_name
,
6790 orig_lcomp_stream
)) {
6791 /* Use the original stream. */
6792 char *tmp
= talloc_strdup(smb_fname_dst
,
6795 status
= NT_STATUS_NO_MEMORY
;
6796 TALLOC_FREE(fname_dst_parent
);
6797 TALLOC_FREE(orig_lcomp_path
);
6798 TALLOC_FREE(orig_lcomp_stream
);
6801 TALLOC_FREE(smb_fname_dst
->stream_name
);
6802 smb_fname_dst
->stream_name
= tmp
;
6804 TALLOC_FREE(fname_dst_parent
);
6805 TALLOC_FREE(orig_lcomp_path
);
6806 TALLOC_FREE(orig_lcomp_stream
);
6810 * If the src and dest names are identical - including case,
6811 * don't do the rename, just return success.
6814 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6815 strcsequal(fsp
->fsp_name
->stream_name
,
6816 smb_fname_dst
->stream_name
)) {
6817 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6818 "- returning success\n",
6819 smb_fname_str_dbg(smb_fname_dst
)));
6820 status
= NT_STATUS_OK
;
6824 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6825 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6827 /* Return the correct error code if both names aren't streams. */
6828 if (!old_is_stream
&& new_is_stream
) {
6829 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6833 if (old_is_stream
&& !new_is_stream
) {
6834 status
= NT_STATUS_INVALID_PARAMETER
;
6838 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6840 if(!replace_if_exists
&& dst_exists
) {
6841 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6842 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6843 smb_fname_str_dbg(smb_fname_dst
)));
6844 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6849 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6850 &smb_fname_dst
->st
);
6851 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6853 /* The file can be open when renaming a stream */
6854 if (dst_fsp
&& !new_is_stream
) {
6855 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6856 status
= NT_STATUS_ACCESS_DENIED
;
6861 /* Ensure we have a valid stat struct for the source. */
6862 status
= vfs_stat_fsp(fsp
);
6863 if (!NT_STATUS_IS_OK(status
)) {
6867 status
= can_rename(conn
, fsp
, attrs
);
6869 if (!NT_STATUS_IS_OK(status
)) {
6870 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6871 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6872 smb_fname_str_dbg(smb_fname_dst
)));
6873 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6874 status
= NT_STATUS_ACCESS_DENIED
;
6878 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6879 status
= NT_STATUS_ACCESS_DENIED
;
6883 /* Do we have rights to move into the destination ? */
6884 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
6885 /* We're moving a directory. */
6886 access_mask
= SEC_DIR_ADD_SUBDIR
;
6888 status
= check_parent_access(conn
,
6891 if (!NT_STATUS_IS_OK(status
)) {
6892 DBG_INFO("check_parent_access on "
6893 "dst %s returned %s\n",
6894 smb_fname_str_dbg(smb_fname_dst
),
6899 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6902 * We have the file open ourselves, so not being able to get the
6903 * corresponding share mode lock is a fatal error.
6906 SMB_ASSERT(lck
!= NULL
);
6908 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6909 uint32_t create_options
= fsp
->fh
->private_options
;
6911 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6912 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6913 smb_fname_str_dbg(smb_fname_dst
)));
6915 if (!fsp
->is_directory
&&
6916 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
6917 (lp_map_archive(SNUM(conn
)) ||
6918 lp_store_dos_attributes(SNUM(conn
)))) {
6919 /* We must set the archive bit on the newly
6921 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6922 uint32_t old_dosmode
= dos_mode(conn
,
6924 file_set_dosmode(conn
,
6926 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6932 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6935 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6939 * A rename acts as a new file create w.r.t. allowing an initial delete
6940 * on close, probably because in Windows there is a new handle to the
6941 * new file. If initial delete on close was requested but not
6942 * originally set, we need to set it here. This is probably not 100% correct,
6943 * but will work for the CIFSFS client which in non-posix mode
6944 * depends on these semantics. JRA.
6947 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6948 status
= can_set_delete_on_close(fsp
, 0);
6950 if (NT_STATUS_IS_OK(status
)) {
6951 /* Note that here we set the *initial* delete on close flag,
6952 * not the regular one. The magic gets handled in close. */
6953 fsp
->initial_delete_on_close
= True
;
6957 status
= NT_STATUS_OK
;
6963 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6964 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6966 status
= map_nt_error_from_unix(errno
);
6969 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6970 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6971 smb_fname_str_dbg(smb_fname_dst
)));
6974 TALLOC_FREE(smb_fname_dst
);
6979 /****************************************************************************
6980 The guts of the rename command, split out so it may be called by the NT SMB
6982 ****************************************************************************/
6984 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6985 connection_struct
*conn
,
6986 struct smb_request
*req
,
6987 struct smb_filename
*smb_fname_src
,
6988 struct smb_filename
*smb_fname_dst
,
6990 bool replace_if_exists
,
6993 uint32_t access_mask
)
6995 char *fname_src_dir
= NULL
;
6996 struct smb_filename
*smb_fname_src_dir
= NULL
;
6997 char *fname_src_mask
= NULL
;
6999 NTSTATUS status
= NT_STATUS_OK
;
7000 struct smb_Dir
*dir_hnd
= NULL
;
7001 const char *dname
= NULL
;
7002 char *talloced
= NULL
;
7004 int create_options
= 0;
7005 bool posix_pathnames
= (req
!= NULL
&& req
->posix_pathnames
);
7009 * Split the old name into directory and last component
7010 * strings. Note that unix_convert may have stripped off a
7011 * leading ./ from both name and newname if the rename is
7012 * at the root of the share. We need to make sure either both
7013 * name and newname contain a / character or neither of them do
7014 * as this is checked in resolve_wildcards().
7017 /* Split up the directory from the filename/mask. */
7018 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7019 &fname_src_dir
, &fname_src_mask
);
7020 if (!NT_STATUS_IS_OK(status
)) {
7021 status
= NT_STATUS_NO_MEMORY
;
7026 * We should only check the mangled cache
7027 * here if unix_convert failed. This means
7028 * that the path in 'mask' doesn't exist
7029 * on the file system and so we need to look
7030 * for a possible mangle. This patch from
7031 * Tine Smukavec <valentin.smukavec@hermes.si>.
7034 if (!VALID_STAT(smb_fname_src
->st
) &&
7035 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7036 char *new_mask
= NULL
;
7037 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
7040 TALLOC_FREE(fname_src_mask
);
7041 fname_src_mask
= new_mask
;
7045 if (!src_has_wild
) {
7049 * Only one file needs to be renamed. Append the mask back
7050 * onto the directory.
7052 TALLOC_FREE(smb_fname_src
->base_name
);
7053 if (ISDOT(fname_src_dir
)) {
7054 /* Ensure we use canonical names on open. */
7055 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7059 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7064 if (!smb_fname_src
->base_name
) {
7065 status
= NT_STATUS_NO_MEMORY
;
7069 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7070 "case_preserve = %d, short case preserve = %d, "
7071 "directory = %s, newname = %s, "
7072 "last_component_dest = %s\n",
7073 conn
->case_sensitive
, conn
->case_preserve
,
7074 conn
->short_case_preserve
,
7075 smb_fname_str_dbg(smb_fname_src
),
7076 smb_fname_str_dbg(smb_fname_dst
),
7077 smb_fname_dst
->original_lcomp
));
7079 /* The dest name still may have wildcards. */
7080 if (dest_has_wild
) {
7081 char *fname_dst_mod
= NULL
;
7082 if (!resolve_wildcards(smb_fname_dst
,
7083 smb_fname_src
->base_name
,
7084 smb_fname_dst
->base_name
,
7086 DEBUG(6, ("rename_internals: resolve_wildcards "
7088 smb_fname_src
->base_name
,
7089 smb_fname_dst
->base_name
));
7090 status
= NT_STATUS_NO_MEMORY
;
7093 TALLOC_FREE(smb_fname_dst
->base_name
);
7094 smb_fname_dst
->base_name
= fname_dst_mod
;
7097 ZERO_STRUCT(smb_fname_src
->st
);
7098 if (posix_pathnames
) {
7099 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
7101 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
7104 status
= map_nt_error_from_unix_common(errno
);
7108 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7109 create_options
|= FILE_DIRECTORY_FILE
;
7112 status
= SMB_VFS_CREATE_FILE(
7115 0, /* root_dir_fid */
7116 smb_fname_src
, /* fname */
7117 access_mask
, /* access_mask */
7118 (FILE_SHARE_READ
| /* share_access */
7120 FILE_OPEN
, /* create_disposition*/
7121 create_options
, /* create_options */
7122 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7123 0, /* oplock_request */
7125 0, /* allocation_size */
7126 0, /* private_flags */
7131 NULL
, NULL
); /* create context */
7133 if (!NT_STATUS_IS_OK(status
)) {
7134 DEBUG(3, ("Could not open rename source %s: %s\n",
7135 smb_fname_str_dbg(smb_fname_src
),
7136 nt_errstr(status
)));
7140 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7141 attrs
, replace_if_exists
);
7143 close_file(req
, fsp
, NORMAL_CLOSE
);
7145 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7146 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
7147 smb_fname_str_dbg(smb_fname_dst
)));
7153 * Wildcards - process each file that matches.
7155 if (strequal(fname_src_mask
, "????????.???")) {
7156 TALLOC_FREE(fname_src_mask
);
7157 fname_src_mask
= talloc_strdup(ctx
, "*");
7158 if (!fname_src_mask
) {
7159 status
= NT_STATUS_NO_MEMORY
;
7164 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7168 smb_fname_src
->flags
);
7169 if (smb_fname_src_dir
== NULL
) {
7170 status
= NT_STATUS_NO_MEMORY
;
7174 status
= check_name(conn
, smb_fname_src_dir
);
7175 if (!NT_STATUS_IS_OK(status
)) {
7179 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
7181 if (dir_hnd
== NULL
) {
7182 status
= map_nt_error_from_unix(errno
);
7186 status
= NT_STATUS_NO_SUCH_FILE
;
7188 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7189 * - gentest fix. JRA
7192 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
7194 files_struct
*fsp
= NULL
;
7195 char *destname
= NULL
;
7196 bool sysdir_entry
= False
;
7198 /* Quick check for "." and ".." */
7199 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7200 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
7201 sysdir_entry
= True
;
7203 TALLOC_FREE(talloced
);
7208 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7209 &smb_fname_src
->st
, false)) {
7210 TALLOC_FREE(talloced
);
7214 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
7215 TALLOC_FREE(talloced
);
7220 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7224 TALLOC_FREE(smb_fname_src
->base_name
);
7225 if (ISDOT(fname_src_dir
)) {
7226 /* Ensure we use canonical names on open. */
7227 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7231 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7236 if (!smb_fname_src
->base_name
) {
7237 status
= NT_STATUS_NO_MEMORY
;
7241 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7242 smb_fname_dst
->base_name
,
7244 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7245 smb_fname_src
->base_name
, destname
));
7246 TALLOC_FREE(talloced
);
7250 status
= NT_STATUS_NO_MEMORY
;
7254 TALLOC_FREE(smb_fname_dst
->base_name
);
7255 smb_fname_dst
->base_name
= destname
;
7257 ZERO_STRUCT(smb_fname_src
->st
);
7258 if (posix_pathnames
) {
7259 SMB_VFS_LSTAT(conn
, smb_fname_src
);
7261 SMB_VFS_STAT(conn
, smb_fname_src
);
7266 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7267 create_options
|= FILE_DIRECTORY_FILE
;
7270 status
= SMB_VFS_CREATE_FILE(
7273 0, /* root_dir_fid */
7274 smb_fname_src
, /* fname */
7275 access_mask
, /* access_mask */
7276 (FILE_SHARE_READ
| /* share_access */
7278 FILE_OPEN
, /* create_disposition*/
7279 create_options
, /* create_options */
7280 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7281 0, /* oplock_request */
7283 0, /* allocation_size */
7284 0, /* private_flags */
7289 NULL
, NULL
); /* create context */
7291 if (!NT_STATUS_IS_OK(status
)) {
7292 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7293 "returned %s rename %s -> %s\n",
7295 smb_fname_str_dbg(smb_fname_src
),
7296 smb_fname_str_dbg(smb_fname_dst
)));
7300 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7302 if (!smb_fname_dst
->original_lcomp
) {
7303 status
= NT_STATUS_NO_MEMORY
;
7307 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7308 attrs
, replace_if_exists
);
7310 close_file(req
, fsp
, NORMAL_CLOSE
);
7312 if (!NT_STATUS_IS_OK(status
)) {
7313 DEBUG(3, ("rename_internals_fsp returned %s for "
7314 "rename %s -> %s\n", nt_errstr(status
),
7315 smb_fname_str_dbg(smb_fname_src
),
7316 smb_fname_str_dbg(smb_fname_dst
)));
7322 DEBUG(3,("rename_internals: doing rename on %s -> "
7323 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7324 smb_fname_str_dbg(smb_fname_src
)));
7325 TALLOC_FREE(talloced
);
7327 TALLOC_FREE(dir_hnd
);
7329 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7330 status
= map_nt_error_from_unix(errno
);
7334 TALLOC_FREE(talloced
);
7335 TALLOC_FREE(smb_fname_src_dir
);
7336 TALLOC_FREE(fname_src_dir
);
7337 TALLOC_FREE(fname_src_mask
);
7341 /****************************************************************************
7343 ****************************************************************************/
7345 void reply_mv(struct smb_request
*req
)
7347 connection_struct
*conn
= req
->conn
;
7349 char *newname
= NULL
;
7353 bool src_has_wcard
= False
;
7354 bool dest_has_wcard
= False
;
7355 TALLOC_CTX
*ctx
= talloc_tos();
7356 struct smb_filename
*smb_fname_src
= NULL
;
7357 struct smb_filename
*smb_fname_dst
= NULL
;
7358 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
) |
7359 (req
->posix_pathnames
?
7360 UCF_UNIX_NAME_LOOKUP
:
7361 UCF_COND_ALLOW_WCARD_LCOMP
);
7362 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
) |
7364 (req
->posix_pathnames
?
7366 UCF_COND_ALLOW_WCARD_LCOMP
);
7367 bool stream_rename
= false;
7369 START_PROFILE(SMBmv
);
7372 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7376 attrs
= SVAL(req
->vwv
+0, 0);
7378 p
= (const char *)req
->buf
+ 1;
7379 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7380 &status
, &src_has_wcard
);
7381 if (!NT_STATUS_IS_OK(status
)) {
7382 reply_nterror(req
, status
);
7386 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7387 &status
, &dest_has_wcard
);
7388 if (!NT_STATUS_IS_OK(status
)) {
7389 reply_nterror(req
, status
);
7393 if (!req
->posix_pathnames
) {
7394 /* The newname must begin with a ':' if the
7395 name contains a ':'. */
7396 if (strchr_m(name
, ':')) {
7397 if (newname
[0] != ':') {
7398 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7401 stream_rename
= true;
7405 status
= filename_convert(ctx
,
7413 if (!NT_STATUS_IS_OK(status
)) {
7414 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7415 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7416 ERRSRV
, ERRbadpath
);
7419 reply_nterror(req
, status
);
7423 status
= filename_convert(ctx
,
7431 if (!NT_STATUS_IS_OK(status
)) {
7432 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7433 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7434 ERRSRV
, ERRbadpath
);
7437 reply_nterror(req
, status
);
7441 if (stream_rename
) {
7442 /* smb_fname_dst->base_name must be the same as
7443 smb_fname_src->base_name. */
7444 TALLOC_FREE(smb_fname_dst
->base_name
);
7445 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7446 smb_fname_src
->base_name
);
7447 if (!smb_fname_dst
->base_name
) {
7448 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7453 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7454 smb_fname_str_dbg(smb_fname_dst
)));
7456 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7457 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7459 if (!NT_STATUS_IS_OK(status
)) {
7460 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7461 /* We have re-scheduled this call. */
7464 reply_nterror(req
, status
);
7468 reply_outbuf(req
, 0, 0);
7470 TALLOC_FREE(smb_fname_src
);
7471 TALLOC_FREE(smb_fname_dst
);
7476 /*******************************************************************
7477 Copy a file as part of a reply_copy.
7478 ******************************************************************/
7481 * TODO: check error codes on all callers
7484 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7485 connection_struct
*conn
,
7486 struct smb_filename
*smb_fname_src
,
7487 struct smb_filename
*smb_fname_dst
,
7490 bool target_is_directory
)
7492 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7494 files_struct
*fsp1
,*fsp2
;
7496 uint32_t new_create_disposition
;
7500 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7501 if (smb_fname_dst_tmp
== NULL
) {
7502 return NT_STATUS_NO_MEMORY
;
7506 * If the target is a directory, extract the last component from the
7507 * src filename and append it to the dst filename
7509 if (target_is_directory
) {
7512 /* dest/target can't be a stream if it's a directory. */
7513 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7515 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7519 p
= smb_fname_src
->base_name
;
7521 smb_fname_dst_tmp
->base_name
=
7522 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7524 if (!smb_fname_dst_tmp
->base_name
) {
7525 status
= NT_STATUS_NO_MEMORY
;
7530 status
= vfs_file_exist(conn
, smb_fname_src
);
7531 if (!NT_STATUS_IS_OK(status
)) {
7535 if (!target_is_directory
&& count
) {
7536 new_create_disposition
= FILE_OPEN
;
7538 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7541 &new_create_disposition
,
7544 status
= NT_STATUS_INVALID_PARAMETER
;
7549 /* Open the src file for reading. */
7550 status
= SMB_VFS_CREATE_FILE(
7553 0, /* root_dir_fid */
7554 smb_fname_src
, /* fname */
7555 FILE_GENERIC_READ
, /* access_mask */
7556 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7557 FILE_OPEN
, /* create_disposition*/
7558 0, /* create_options */
7559 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7560 INTERNAL_OPEN_ONLY
, /* oplock_request */
7562 0, /* allocation_size */
7563 0, /* private_flags */
7568 NULL
, NULL
); /* create context */
7570 if (!NT_STATUS_IS_OK(status
)) {
7574 dosattrs
= dos_mode(conn
, smb_fname_src
);
7576 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7577 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7580 /* Open the dst file for writing. */
7581 status
= SMB_VFS_CREATE_FILE(
7584 0, /* root_dir_fid */
7585 smb_fname_dst
, /* fname */
7586 FILE_GENERIC_WRITE
, /* access_mask */
7587 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7588 new_create_disposition
, /* create_disposition*/
7589 0, /* create_options */
7590 dosattrs
, /* file_attributes */
7591 INTERNAL_OPEN_ONLY
, /* oplock_request */
7593 0, /* allocation_size */
7594 0, /* private_flags */
7599 NULL
, NULL
); /* create context */
7601 if (!NT_STATUS_IS_OK(status
)) {
7602 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7606 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7607 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7609 DEBUG(0, ("error - vfs lseek returned error %s\n",
7611 status
= map_nt_error_from_unix(errno
);
7612 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7613 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7618 /* Do the actual copy. */
7619 if (smb_fname_src
->st
.st_ex_size
) {
7620 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7625 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7627 /* Ensure the modtime is set correctly on the destination file. */
7628 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7631 * As we are opening fsp1 read-only we only expect
7632 * an error on close on fsp2 if we are out of space.
7633 * Thus we don't look at the error return from the
7636 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7638 if (!NT_STATUS_IS_OK(status
)) {
7642 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7643 status
= NT_STATUS_DISK_FULL
;
7647 status
= NT_STATUS_OK
;
7650 TALLOC_FREE(smb_fname_dst_tmp
);
7654 /****************************************************************************
7655 Reply to a file copy.
7656 ****************************************************************************/
7658 void reply_copy(struct smb_request
*req
)
7660 connection_struct
*conn
= req
->conn
;
7661 struct smb_filename
*smb_fname_src
= NULL
;
7662 struct smb_filename
*smb_fname_src_dir
= NULL
;
7663 struct smb_filename
*smb_fname_dst
= NULL
;
7664 char *fname_src
= NULL
;
7665 char *fname_dst
= NULL
;
7666 char *fname_src_mask
= NULL
;
7667 char *fname_src_dir
= NULL
;
7670 int error
= ERRnoaccess
;
7674 bool target_is_directory
=False
;
7675 bool source_has_wild
= False
;
7676 bool dest_has_wild
= False
;
7678 uint32_t ucf_flags_src
= UCF_COND_ALLOW_WCARD_LCOMP
|
7679 ucf_flags_from_smb_request(req
);
7680 uint32_t ucf_flags_dst
= UCF_COND_ALLOW_WCARD_LCOMP
|
7681 ucf_flags_from_smb_request(req
);
7682 TALLOC_CTX
*ctx
= talloc_tos();
7684 START_PROFILE(SMBcopy
);
7687 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7691 tid2
= SVAL(req
->vwv
+0, 0);
7692 ofun
= SVAL(req
->vwv
+1, 0);
7693 flags
= SVAL(req
->vwv
+2, 0);
7695 p
= (const char *)req
->buf
;
7696 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7697 &status
, &source_has_wild
);
7698 if (!NT_STATUS_IS_OK(status
)) {
7699 reply_nterror(req
, status
);
7702 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7703 &status
, &dest_has_wild
);
7704 if (!NT_STATUS_IS_OK(status
)) {
7705 reply_nterror(req
, status
);
7709 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7711 if (tid2
!= conn
->cnum
) {
7712 /* can't currently handle inter share copies XXXX */
7713 DEBUG(3,("Rejecting inter-share copy\n"));
7714 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7718 status
= filename_convert(ctx
, conn
,
7724 if (!NT_STATUS_IS_OK(status
)) {
7725 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7726 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7727 ERRSRV
, ERRbadpath
);
7730 reply_nterror(req
, status
);
7734 status
= filename_convert(ctx
, conn
,
7740 if (!NT_STATUS_IS_OK(status
)) {
7741 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7742 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7743 ERRSRV
, ERRbadpath
);
7746 reply_nterror(req
, status
);
7750 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7752 if ((flags
&1) && target_is_directory
) {
7753 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7757 if ((flags
&2) && !target_is_directory
) {
7758 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7762 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7763 /* wants a tree copy! XXXX */
7764 DEBUG(3,("Rejecting tree copy\n"));
7765 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7769 /* Split up the directory from the filename/mask. */
7770 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7771 &fname_src_dir
, &fname_src_mask
);
7772 if (!NT_STATUS_IS_OK(status
)) {
7773 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7778 * We should only check the mangled cache
7779 * here if unix_convert failed. This means
7780 * that the path in 'mask' doesn't exist
7781 * on the file system and so we need to look
7782 * for a possible mangle. This patch from
7783 * Tine Smukavec <valentin.smukavec@hermes.si>.
7785 if (!VALID_STAT(smb_fname_src
->st
) &&
7786 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7787 char *new_mask
= NULL
;
7788 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7789 &new_mask
, conn
->params
);
7791 /* Use demangled name if one was successfully found. */
7793 TALLOC_FREE(fname_src_mask
);
7794 fname_src_mask
= new_mask
;
7798 if (!source_has_wild
) {
7801 * Only one file needs to be copied. Append the mask back onto
7804 TALLOC_FREE(smb_fname_src
->base_name
);
7805 if (ISDOT(fname_src_dir
)) {
7806 /* Ensure we use canonical names on open. */
7807 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7811 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7816 if (!smb_fname_src
->base_name
) {
7817 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7821 if (dest_has_wild
) {
7822 char *fname_dst_mod
= NULL
;
7823 if (!resolve_wildcards(smb_fname_dst
,
7824 smb_fname_src
->base_name
,
7825 smb_fname_dst
->base_name
,
7827 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7830 TALLOC_FREE(smb_fname_dst
->base_name
);
7831 smb_fname_dst
->base_name
= fname_dst_mod
;
7834 status
= check_name(conn
, smb_fname_src
);
7835 if (!NT_STATUS_IS_OK(status
)) {
7836 reply_nterror(req
, status
);
7840 status
= check_name(conn
, smb_fname_dst
);
7841 if (!NT_STATUS_IS_OK(status
)) {
7842 reply_nterror(req
, status
);
7846 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7847 ofun
, count
, target_is_directory
);
7849 if(!NT_STATUS_IS_OK(status
)) {
7850 reply_nterror(req
, status
);
7856 struct smb_Dir
*dir_hnd
= NULL
;
7857 const char *dname
= NULL
;
7858 char *talloced
= NULL
;
7862 * There is a wildcard that requires us to actually read the
7863 * src dir and copy each file matching the mask to the dst.
7864 * Right now streams won't be copied, but this could
7865 * presumably be added with a nested loop for reach dir entry.
7867 SMB_ASSERT(!smb_fname_src
->stream_name
);
7868 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7870 smb_fname_src
->stream_name
= NULL
;
7871 smb_fname_dst
->stream_name
= NULL
;
7873 if (strequal(fname_src_mask
,"????????.???")) {
7874 TALLOC_FREE(fname_src_mask
);
7875 fname_src_mask
= talloc_strdup(ctx
, "*");
7876 if (!fname_src_mask
) {
7877 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7882 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7886 smb_fname_src
->flags
);
7887 if (smb_fname_src_dir
== NULL
) {
7888 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7892 status
= check_name(conn
, smb_fname_src_dir
);
7893 if (!NT_STATUS_IS_OK(status
)) {
7894 reply_nterror(req
, status
);
7898 dir_hnd
= OpenDir(ctx
,
7903 if (dir_hnd
== NULL
) {
7904 status
= map_nt_error_from_unix(errno
);
7905 reply_nterror(req
, status
);
7911 /* Iterate over the src dir copying each entry to the dst. */
7912 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7913 &smb_fname_src
->st
, &talloced
))) {
7914 char *destname
= NULL
;
7916 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7917 TALLOC_FREE(talloced
);
7921 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7922 &smb_fname_src
->st
, false)) {
7923 TALLOC_FREE(talloced
);
7927 if(!mask_match(dname
, fname_src_mask
,
7928 conn
->case_sensitive
)) {
7929 TALLOC_FREE(talloced
);
7933 error
= ERRnoaccess
;
7935 /* Get the src smb_fname struct setup. */
7936 TALLOC_FREE(smb_fname_src
->base_name
);
7937 if (ISDOT(fname_src_dir
)) {
7938 /* Ensure we use canonical names on open. */
7939 smb_fname_src
->base_name
=
7940 talloc_asprintf(smb_fname_src
, "%s",
7943 smb_fname_src
->base_name
=
7944 talloc_asprintf(smb_fname_src
, "%s/%s",
7945 fname_src_dir
, dname
);
7948 if (!smb_fname_src
->base_name
) {
7949 TALLOC_FREE(dir_hnd
);
7950 TALLOC_FREE(talloced
);
7951 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7955 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7956 smb_fname_dst
->base_name
,
7958 TALLOC_FREE(talloced
);
7962 TALLOC_FREE(dir_hnd
);
7963 TALLOC_FREE(talloced
);
7964 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7968 TALLOC_FREE(smb_fname_dst
->base_name
);
7969 smb_fname_dst
->base_name
= destname
;
7971 status
= check_name(conn
, smb_fname_src
);
7972 if (!NT_STATUS_IS_OK(status
)) {
7973 TALLOC_FREE(dir_hnd
);
7974 TALLOC_FREE(talloced
);
7975 reply_nterror(req
, status
);
7979 status
= check_name(conn
, smb_fname_dst
);
7980 if (!NT_STATUS_IS_OK(status
)) {
7981 TALLOC_FREE(dir_hnd
);
7982 TALLOC_FREE(talloced
);
7983 reply_nterror(req
, status
);
7987 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7988 smb_fname_src
->base_name
,
7989 smb_fname_dst
->base_name
));
7991 status
= copy_file(ctx
, conn
, smb_fname_src
,
7992 smb_fname_dst
, ofun
, count
,
7993 target_is_directory
);
7994 if (NT_STATUS_IS_OK(status
)) {
7998 TALLOC_FREE(talloced
);
8000 TALLOC_FREE(dir_hnd
);
8004 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
8008 reply_outbuf(req
, 1, 0);
8009 SSVAL(req
->outbuf
,smb_vwv0
,count
);
8011 TALLOC_FREE(smb_fname_src
);
8012 TALLOC_FREE(smb_fname_src_dir
);
8013 TALLOC_FREE(smb_fname_dst
);
8014 TALLOC_FREE(fname_src
);
8015 TALLOC_FREE(fname_dst
);
8016 TALLOC_FREE(fname_src_mask
);
8017 TALLOC_FREE(fname_src_dir
);
8019 END_PROFILE(SMBcopy
);
8024 #define DBGC_CLASS DBGC_LOCKING
8026 /****************************************************************************
8027 Get a lock pid, dealing with large count requests.
8028 ****************************************************************************/
8030 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
8031 bool large_file_format
)
8033 if(!large_file_format
)
8034 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
8036 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
8039 /****************************************************************************
8040 Get a lock count, dealing with large count requests.
8041 ****************************************************************************/
8043 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
8044 bool large_file_format
)
8048 if(!large_file_format
) {
8049 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
8052 * No BVAL, this is reversed!
8054 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
8055 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
8061 /****************************************************************************
8062 Get a lock offset, dealing with large offset requests.
8063 ****************************************************************************/
8065 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
8066 bool large_file_format
)
8068 uint64_t offset
= 0;
8070 if(!large_file_format
) {
8071 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
8074 * No BVAL, this is reversed!
8076 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
8077 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
8083 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
8087 struct smbd_lock_element
*locks
,
8090 connection_struct
*conn
= req
->conn
;
8092 NTSTATUS status
= NT_STATUS_OK
;
8096 /* Setup the timeout in seconds. */
8098 if (!lp_blocking_locks(SNUM(conn
))) {
8102 for(i
= 0; i
< (int)num_locks
; i
++) {
8103 struct smbd_lock_element
*e
= &locks
[i
];
8105 DBG_DEBUG("lock start=%"PRIu64
", len=%"PRIu64
" for smblctx "
8106 "%"PRIu64
", file %s timeout = %"PRIi32
"\n",
8114 bool blocking_lock
= (timeout
!= 0);
8115 bool defer_lock
= false;
8116 struct byte_range_lock
*br_lck
;
8117 struct server_id blocker_pid
;
8118 uint64_t block_smblctx
;
8120 br_lck
= do_lock(req
->sconn
->msg_ctx
,
8132 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
8133 /* Windows internal resolution for blocking locks seems
8134 to be about 200ms... Don't wait for less than that. JRA. */
8135 if (timeout
!= -1) {
8136 timeout
= MAX(timeout
, lp_lock_spin_time());
8141 /* If a lock sent with timeout of zero would fail, and
8142 * this lock has been requested multiple times,
8143 * according to brl_lock_failed() we convert this
8144 * request to a blocking lock with a timeout of between
8145 * 150 - 300 milliseconds.
8147 * If lp_lock_spin_time() has been set to 0, we skip
8148 * this blocking retry and fail immediately.
8150 * Replacement for do_lock_spin(). JRA. */
8152 if (!req
->sconn
->using_smb2
&&
8153 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
8154 lp_lock_spin_time() && !blocking_lock
&&
8155 NT_STATUS_EQUAL((status
),
8156 NT_STATUS_FILE_LOCK_CONFLICT
))
8159 timeout
= lp_lock_spin_time();
8162 if (br_lck
&& defer_lock
) {
8164 * A blocking lock was requested. Package up
8165 * this smb into a queued request and push it
8166 * onto the blocking lock queue.
8168 if(push_blocking_lock_request(br_lck
,
8179 TALLOC_FREE(br_lck
);
8181 return NT_STATUS_OK
;
8185 TALLOC_FREE(br_lck
);
8188 if (!NT_STATUS_IS_OK(status
)) {
8193 /* If any of the above locks failed, then we must unlock
8194 all of the previous locks (X/Open spec). */
8196 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
8199 * Ensure we don't do a remove on the lock that just failed,
8200 * as under POSIX rules, if we have a lock already there, we
8201 * will delete it (and we shouldn't) .....
8203 for(i
--; i
>= 0; i
--) {
8204 struct smbd_lock_element
*e
= &locks
[i
];
8206 do_unlock(req
->sconn
->msg_ctx
,
8216 DBG_NOTICE("%s num_locks=%"PRIu16
"\n",
8220 return NT_STATUS_OK
;
8223 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
8225 uint16_t num_ulocks
,
8226 struct smbd_lock_element
*ulocks
,
8227 enum brl_flavour lock_flav
)
8231 for(i
= 0; i
< num_ulocks
; i
++) {
8232 struct smbd_lock_element
*e
= &ulocks
[i
];
8235 DBG_DEBUG("unlock start=%"PRIu64
", len=%"PRIu64
" for "
8236 "pid %"PRIu64
", file %s\n",
8242 if (e
->brltype
!= UNLOCK_LOCK
) {
8243 /* this can only happen with SMB2 */
8244 return NT_STATUS_INVALID_PARAMETER
;
8247 status
= do_unlock(req
->sconn
->msg_ctx
,
8254 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
8255 nt_errstr(status
)));
8257 if (!NT_STATUS_IS_OK(status
)) {
8262 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
8265 return NT_STATUS_OK
;
8268 /****************************************************************************
8269 Reply to a lockingX request.
8270 ****************************************************************************/
8272 void reply_lockingX(struct smb_request
*req
)
8274 connection_struct
*conn
= req
->conn
;
8276 unsigned char locktype
;
8277 enum brl_type brltype
;
8278 unsigned char oplocklevel
;
8279 uint16_t num_ulocks
;
8281 int32_t lock_timeout
;
8283 const uint8_t *data
;
8284 bool large_file_format
;
8285 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8286 struct smbd_lock_element
*ulocks
= NULL
;
8287 struct smbd_lock_element
*locks
= NULL
;
8290 START_PROFILE(SMBlockingX
);
8293 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8294 END_PROFILE(SMBlockingX
);
8298 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8299 locktype
= CVAL(req
->vwv
+3, 0);
8300 oplocklevel
= CVAL(req
->vwv
+3, 1);
8301 num_ulocks
= SVAL(req
->vwv
+6, 0);
8302 num_locks
= SVAL(req
->vwv
+7, 0);
8303 lock_timeout
= IVAL(req
->vwv
+4, 0);
8304 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8306 if (!check_fsp(conn
, req
, fsp
)) {
8307 END_PROFILE(SMBlockingX
);
8313 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8314 /* we don't support these - and CANCEL_LOCK makes w2k
8315 and XP reboot so I don't really want to be
8316 compatible! (tridge) */
8317 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8318 END_PROFILE(SMBlockingX
);
8322 /* Check if this is an oplock break on a file
8323 we have granted an oplock on.
8325 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8326 /* Client can insist on breaking to none. */
8327 bool break_to_none
= (oplocklevel
== 0);
8330 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8331 "for %s\n", (unsigned int)oplocklevel
,
8332 fsp_fnum_dbg(fsp
)));
8335 * Make sure we have granted an exclusive or batch oplock on
8339 if (fsp
->oplock_type
== 0) {
8341 /* The Samba4 nbench simulator doesn't understand
8342 the difference between break to level2 and break
8343 to none from level2 - it sends oplock break
8344 replies in both cases. Don't keep logging an error
8345 message here - just ignore it. JRA. */
8347 DEBUG(5,("reply_lockingX: Error : oplock break from "
8348 "client for %s (oplock=%d) and no "
8349 "oplock granted on this file (%s).\n",
8350 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8353 /* if this is a pure oplock break request then don't
8355 if (num_locks
== 0 && num_ulocks
== 0) {
8356 END_PROFILE(SMBlockingX
);
8360 END_PROFILE(SMBlockingX
);
8361 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8365 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8367 result
= remove_oplock(fsp
);
8369 result
= downgrade_oplock(fsp
);
8373 DEBUG(0, ("reply_lockingX: error in removing "
8374 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8375 /* Hmmm. Is this panic justified? */
8376 smb_panic("internal tdb error");
8379 /* if this is a pure oplock break request then don't send a
8381 if (num_locks
== 0 && num_ulocks
== 0) {
8382 /* Sanity check - ensure a pure oplock break is not a
8384 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8385 DEBUG(0,("reply_lockingX: Error : pure oplock "
8386 "break is a chained %d request !\n",
8387 (unsigned int)CVAL(req
->vwv
+0, 0)));
8389 END_PROFILE(SMBlockingX
);
8395 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8396 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8397 END_PROFILE(SMBlockingX
);
8401 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8402 if (ulocks
== NULL
) {
8403 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8404 END_PROFILE(SMBlockingX
);
8408 /* Data now points at the beginning of the list
8409 of smb_unlkrng structs */
8410 for (i
= 0; i
< num_ulocks
; i
++) {
8411 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8412 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8413 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8414 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8417 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
, WINDOWS_LOCK
);
8418 TALLOC_FREE(ulocks
);
8419 if (!NT_STATUS_IS_OK(status
)) {
8420 END_PROFILE(SMBlockingX
);
8421 reply_nterror(req
, status
);
8425 /* Now do any requested locks */
8426 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8428 /* Data now points at the beginning of the list
8429 of smb_lkrng structs */
8431 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8432 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8433 brltype
= PENDING_READ_LOCK
;
8435 brltype
= READ_LOCK
;
8438 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8439 brltype
= PENDING_WRITE_LOCK
;
8441 brltype
= WRITE_LOCK
;
8445 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8446 if (locks
== NULL
) {
8447 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8448 END_PROFILE(SMBlockingX
);
8452 for (i
= 0; i
< num_locks
; i
++) {
8453 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8454 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8455 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8456 locks
[i
].brltype
= brltype
;
8459 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8460 struct smbd_lock_element
*e
= NULL
;
8462 if (num_locks
== 0) {
8463 /* See smbtorture3 lock11 test */
8470 * MS-CIFS (2.2.4.32.1) states that a cancel is
8471 * honored if and only if the lock vector contains one
8472 * entry. When given multiple cancel requests in a
8473 * single PDU we expect the server to return an
8474 * error. Windows servers seem to accept the request
8475 * but only cancel the first lock.
8477 * JRA - Do what Windows does (tm) :-).
8480 if (lp_blocking_locks(SNUM(conn
))) {
8481 struct blocking_lock_record
*blr
= NULL
;
8483 /* Schedule a message to ourselves to
8484 remove the blocking lock record and
8485 return the right error. */
8487 blr
= blocking_lock_cancel_smb1(
8494 NT_STATUS_FILE_LOCK_CONFLICT
);
8496 reply_force_doserror(
8497 req
, ERRDOS
, ERRcancelviolation
);
8498 END_PROFILE(SMBlockingX
);
8503 /* Remove a matching pending lock. */
8504 status
= do_lock_cancel(fsp
,
8509 END_PROFILE(SMBlockingX
);
8510 reply_nterror(req
, status
);
8514 status
= smbd_do_locking(
8515 req
, fsp
, lock_timeout
, num_locks
, locks
, &async
);
8517 if (!NT_STATUS_IS_OK(status
)) {
8518 END_PROFILE(SMBlockingX
);
8519 reply_nterror(req
, status
);
8523 END_PROFILE(SMBlockingX
);
8528 reply_outbuf(req
, 2, 0);
8529 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8530 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8532 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8533 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8535 END_PROFILE(SMBlockingX
);
8539 #define DBGC_CLASS DBGC_ALL
8541 /****************************************************************************
8542 Reply to a SMBreadbmpx (read block multiplex) request.
8543 Always reply with an error, if someone has a platform really needs this,
8544 please contact vl@samba.org
8545 ****************************************************************************/
8547 void reply_readbmpx(struct smb_request
*req
)
8549 START_PROFILE(SMBreadBmpx
);
8550 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8551 END_PROFILE(SMBreadBmpx
);
8555 /****************************************************************************
8556 Reply to a SMBreadbs (read block multiplex secondary) request.
8557 Always reply with an error, if someone has a platform really needs this,
8558 please contact vl@samba.org
8559 ****************************************************************************/
8561 void reply_readbs(struct smb_request
*req
)
8563 START_PROFILE(SMBreadBs
);
8564 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8565 END_PROFILE(SMBreadBs
);
8569 /****************************************************************************
8570 Reply to a SMBsetattrE.
8571 ****************************************************************************/
8573 void reply_setattrE(struct smb_request
*req
)
8575 connection_struct
*conn
= req
->conn
;
8576 struct smb_file_time ft
;
8580 START_PROFILE(SMBsetattrE
);
8584 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8588 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8590 if(!fsp
|| (fsp
->conn
!= conn
)) {
8591 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8596 * Convert the DOS times into unix times.
8599 ft
.atime
= convert_time_t_to_timespec(
8600 srv_make_unix_date2(req
->vwv
+3));
8601 ft
.mtime
= convert_time_t_to_timespec(
8602 srv_make_unix_date2(req
->vwv
+5));
8603 ft
.create_time
= convert_time_t_to_timespec(
8604 srv_make_unix_date2(req
->vwv
+1));
8606 reply_outbuf(req
, 0, 0);
8609 * Patch from Ray Frush <frush@engr.colostate.edu>
8610 * Sometimes times are sent as zero - ignore them.
8613 /* Ensure we have a valid stat struct for the source. */
8614 status
= vfs_stat_fsp(fsp
);
8615 if (!NT_STATUS_IS_OK(status
)) {
8616 reply_nterror(req
, status
);
8620 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8621 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8625 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8626 if (!NT_STATUS_IS_OK(status
)) {
8627 reply_nterror(req
, status
);
8631 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8634 (unsigned int)ft
.atime
.tv_sec
,
8635 (unsigned int)ft
.mtime
.tv_sec
,
8636 (unsigned int)ft
.create_time
.tv_sec
8639 END_PROFILE(SMBsetattrE
);
8644 /* Back from the dead for OS/2..... JRA. */
8646 /****************************************************************************
8647 Reply to a SMBwritebmpx (write block multiplex primary) request.
8648 Always reply with an error, if someone has a platform really needs this,
8649 please contact vl@samba.org
8650 ****************************************************************************/
8652 void reply_writebmpx(struct smb_request
*req
)
8654 START_PROFILE(SMBwriteBmpx
);
8655 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8656 END_PROFILE(SMBwriteBmpx
);
8660 /****************************************************************************
8661 Reply to a SMBwritebs (write block multiplex secondary) request.
8662 Always reply with an error, if someone has a platform really needs this,
8663 please contact vl@samba.org
8664 ****************************************************************************/
8666 void reply_writebs(struct smb_request
*req
)
8668 START_PROFILE(SMBwriteBs
);
8669 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8670 END_PROFILE(SMBwriteBs
);
8674 /****************************************************************************
8675 Reply to a SMBgetattrE.
8676 ****************************************************************************/
8678 void reply_getattrE(struct smb_request
*req
)
8680 connection_struct
*conn
= req
->conn
;
8683 struct timespec create_ts
;
8685 START_PROFILE(SMBgetattrE
);
8688 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8689 END_PROFILE(SMBgetattrE
);
8693 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8695 if(!fsp
|| (fsp
->conn
!= conn
)) {
8696 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8697 END_PROFILE(SMBgetattrE
);
8701 /* Do an fstat on this file */
8703 reply_nterror(req
, map_nt_error_from_unix(errno
));
8704 END_PROFILE(SMBgetattrE
);
8708 mode
= dos_mode(conn
, fsp
->fsp_name
);
8711 * Convert the times into dos times. Set create
8712 * date to be last modify date as UNIX doesn't save
8716 reply_outbuf(req
, 11, 0);
8718 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8719 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8720 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8721 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8722 /* Should we check pending modtime here ? JRA */
8723 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8724 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8726 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8727 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8728 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8730 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8731 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8732 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8734 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8736 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8738 END_PROFILE(SMBgetattrE
);