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. */
3799 TALLOC_FREE(br_lck
);
3801 if (NT_STATUS_V(status
)) {
3802 reply_nterror(req
, status
);
3803 END_PROFILE(SMBlockread
);
3808 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3810 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3812 if (numtoread
> maxtoread
) {
3813 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3814 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3815 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3816 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3817 numtoread
= maxtoread
;
3820 reply_outbuf(req
, 5, numtoread
+ 3);
3822 data
= smb_buf(req
->outbuf
) + 3;
3824 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3827 reply_nterror(req
, map_nt_error_from_unix(errno
));
3828 END_PROFILE(SMBlockread
);
3832 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3834 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3835 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3836 p
= smb_buf(req
->outbuf
);
3837 SCVAL(p
,0,0); /* pad byte. */
3840 DEBUG(3,("lockread %s num=%d nread=%d\n",
3841 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3843 END_PROFILE(SMBlockread
);
3848 #define DBGC_CLASS DBGC_ALL
3850 /****************************************************************************
3852 ****************************************************************************/
3854 void reply_read(struct smb_request
*req
)
3856 connection_struct
*conn
= req
->conn
;
3863 struct lock_struct lock
;
3864 struct smbXsrv_connection
*xconn
= req
->xconn
;
3866 START_PROFILE(SMBread
);
3869 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3870 END_PROFILE(SMBread
);
3874 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3876 if (!check_fsp(conn
, req
, fsp
)) {
3877 END_PROFILE(SMBread
);
3881 if (!CHECK_READ(fsp
,req
)) {
3882 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3883 END_PROFILE(SMBread
);
3887 numtoread
= SVAL(req
->vwv
+1, 0);
3888 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3891 * The requested read size cannot be greater than max_send. JRA.
3893 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3895 if (numtoread
> maxtoread
) {
3896 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3897 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3898 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3899 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3900 numtoread
= maxtoread
;
3903 reply_outbuf(req
, 5, numtoread
+3);
3905 data
= smb_buf(req
->outbuf
) + 3;
3907 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3908 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3911 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3912 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3913 END_PROFILE(SMBread
);
3918 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3921 reply_nterror(req
, map_nt_error_from_unix(errno
));
3925 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3927 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3928 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3929 SCVAL(smb_buf(req
->outbuf
),0,1);
3930 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3932 DEBUG(3, ("read %s num=%d nread=%d\n",
3933 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3936 END_PROFILE(SMBread
);
3940 /****************************************************************************
3942 ****************************************************************************/
3944 size_t setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3948 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3951 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3953 SCVAL(outbuf
,smb_vwv0
,0xFF);
3954 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3955 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3956 SSVAL(outbuf
,smb_vwv6
,
3957 (smb_wct
- 4) /* offset from smb header to wct */
3958 + 1 /* the wct field */
3959 + 12 * sizeof(uint16_t) /* vwv */
3960 + 2 /* the buflen field */
3961 + 1); /* padding byte */
3962 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3963 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3964 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3965 _smb_setlen_large(outbuf
,
3966 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3970 /****************************************************************************
3971 Reply to a read and X - possibly using sendfile.
3972 ****************************************************************************/
3974 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3975 files_struct
*fsp
, off_t startpos
,
3978 struct smbXsrv_connection
*xconn
= req
->xconn
;
3980 struct lock_struct lock
;
3981 int saved_errno
= 0;
3983 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3984 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3987 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3988 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3993 * We can only use sendfile on a non-chained packet
3994 * but we can use on a non-oplocked file. tridge proved this
3995 * on a train in Germany :-). JRA.
3998 if (!req_is_in_chain(req
) &&
4000 (fsp
->base_fsp
== NULL
) &&
4001 (fsp
->wcp
== NULL
) &&
4002 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
4003 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
4006 if(fsp_stat(fsp
) == -1) {
4007 reply_nterror(req
, map_nt_error_from_unix(errno
));
4011 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4012 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4013 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4015 * We already know that we would do a short read, so don't
4016 * try the sendfile() path.
4018 goto nosendfile_read
;
4022 * Set up the packet header before send. We
4023 * assume here the sendfile will work (get the
4024 * correct amount of data).
4027 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4029 construct_reply_common_req(req
, (char *)headerbuf
);
4030 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4032 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4033 startpos
, smb_maxcnt
);
4035 saved_errno
= errno
;
4037 /* Returning ENOSYS means no data at all was sent.
4038 Do this as a normal read. */
4039 if (errno
== ENOSYS
) {
4044 * Special hack for broken Linux with no working sendfile. If we
4045 * return EINTR we sent the header but not the rest of the data.
4046 * Fake this up by doing read/write calls.
4049 if (errno
== EINTR
) {
4050 /* Ensure we don't do this again. */
4051 set_use_sendfile(SNUM(conn
), False
);
4052 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4053 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4056 saved_errno
= errno
;
4057 DEBUG(0,("send_file_readX: "
4058 "fake_sendfile failed for "
4059 "file %s (%s) for client %s. "
4062 smbXsrv_connection_dbg(xconn
),
4063 strerror(saved_errno
)));
4064 errno
= saved_errno
;
4065 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4067 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4068 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4069 /* No outbuf here means successful sendfile. */
4073 DEBUG(0,("send_file_readX: sendfile failed for file "
4074 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4076 exit_server_cleanly("send_file_readX sendfile failed");
4077 } else if (nread
== 0) {
4079 * Some sendfile implementations return 0 to indicate
4080 * that there was a short read, but nothing was
4081 * actually written to the socket. In this case,
4082 * fallback to the normal read path so the header gets
4083 * the correct byte count.
4085 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4086 "falling back to the normal read: %s\n",
4091 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4092 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4094 /* Deal with possible short send. */
4095 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4098 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4099 sizeof(headerbuf
), smb_maxcnt
);
4102 r
= "send_file_readX: sendfile_short_send failed";
4103 DEBUG(0,("%s for file %s (%s).\n",
4104 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4105 exit_server_cleanly(r
);
4108 /* No outbuf here means successful sendfile. */
4109 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4110 SMB_PERFCOUNT_END(&req
->pcd
);
4116 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4117 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4120 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4121 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4122 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4124 * We already know that we would do a short
4125 * read, so don't try the sendfile() path.
4127 goto nosendfile_read
;
4130 construct_reply_common_req(req
, (char *)headerbuf
);
4131 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4133 /* Send out the header. */
4134 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4136 if (ret
!= sizeof(headerbuf
)) {
4137 saved_errno
= errno
;
4139 * Try and give an error message saying what
4142 DEBUG(0,("send_file_readX: write_data failed for file "
4143 "%s (%s) for client %s. Terminating\n",
4145 smbXsrv_connection_dbg(xconn
),
4146 strerror(saved_errno
)));
4147 errno
= saved_errno
;
4148 exit_server_cleanly("send_file_readX sendfile failed");
4150 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4152 saved_errno
= errno
;
4153 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4154 "%s (%s) for client %s. Terminating\n",
4156 smbXsrv_connection_dbg(xconn
),
4157 strerror(saved_errno
)));
4158 errno
= saved_errno
;
4159 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4166 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4167 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4168 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4170 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4171 startpos
, smb_maxcnt
);
4172 saved_errno
= errno
;
4175 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4179 setup_readX_header((char *)req
->outbuf
, nread
);
4181 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4182 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4186 TALLOC_FREE(req
->outbuf
);
4190 /****************************************************************************
4191 Work out how much space we have for a read return.
4192 ****************************************************************************/
4194 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4196 struct smbXsrv_connection
*xconn
= req
->xconn
;
4198 if (xconn
->protocol
< PROTOCOL_NT1
) {
4199 return xconn
->smb1
.sessions
.max_send
;
4202 if (!lp_large_readwrite()) {
4203 return xconn
->smb1
.sessions
.max_send
;
4206 if (req_is_in_chain(req
)) {
4207 return xconn
->smb1
.sessions
.max_send
;
4210 if (req
->encrypted
) {
4212 * Don't take encrypted traffic up to the
4213 * limit. There are padding considerations
4214 * that make that tricky.
4216 return xconn
->smb1
.sessions
.max_send
;
4219 if (srv_is_signing_active(xconn
)) {
4223 if (!lp_unix_extensions()) {
4228 * We can do ultra-large POSIX reads.
4233 /****************************************************************************
4234 Calculate how big a read can be. Copes with all clients. It's always
4235 safe to return a short read - Windows does this.
4236 ****************************************************************************/
4238 static size_t calc_read_size(const struct smb_request
*req
,
4242 struct smbXsrv_connection
*xconn
= req
->xconn
;
4243 size_t max_pdu
= calc_max_read_pdu(req
);
4244 size_t total_size
= 0;
4245 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4246 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4249 * Windows explicitly ignores upper size of 0xFFFF.
4250 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4251 * We must do the same as these will never fit even in
4252 * an extended size NetBIOS packet.
4254 if (upper_size
== 0xFFFF) {
4258 if (xconn
->protocol
< PROTOCOL_NT1
) {
4262 total_size
= ((upper_size
<<16) | lower_size
);
4265 * LARGE_READX test shows it's always safe to return
4266 * a short read. Windows does so.
4268 return MIN(total_size
, max_len
);
4271 /****************************************************************************
4272 Reply to a read and X.
4273 ****************************************************************************/
4275 void reply_read_and_X(struct smb_request
*req
)
4277 connection_struct
*conn
= req
->conn
;
4282 bool big_readX
= False
;
4284 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4287 START_PROFILE(SMBreadX
);
4289 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4290 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4294 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4295 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4296 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4298 /* If it's an IPC, pass off the pipe handler. */
4300 reply_pipe_read_and_X(req
);
4301 END_PROFILE(SMBreadX
);
4305 if (!check_fsp(conn
, req
, fsp
)) {
4306 END_PROFILE(SMBreadX
);
4310 if (!CHECK_READ(fsp
,req
)) {
4311 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4312 END_PROFILE(SMBreadX
);
4316 upper_size
= SVAL(req
->vwv
+7, 0);
4317 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4318 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4320 * This is a heuristic to avoid keeping large
4321 * outgoing buffers around over long-lived aio
4327 if (req
->wct
== 12) {
4329 * This is a large offset (64 bit) read.
4331 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4336 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4341 if (NT_STATUS_IS_OK(status
)) {
4342 /* Read scheduled - we're done. */
4345 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4346 /* Real error - report to client. */
4347 END_PROFILE(SMBreadX
);
4348 reply_nterror(req
, status
);
4351 /* NT_STATUS_RETRY - fall back to sync read. */
4354 smbd_lock_socket(req
->xconn
);
4355 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4356 smbd_unlock_socket(req
->xconn
);
4359 END_PROFILE(SMBreadX
);
4363 /****************************************************************************
4364 Error replies to writebraw must have smb_wct == 1. Fix this up.
4365 ****************************************************************************/
4367 void error_to_writebrawerr(struct smb_request
*req
)
4369 uint8_t *old_outbuf
= req
->outbuf
;
4371 reply_outbuf(req
, 1, 0);
4373 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4374 TALLOC_FREE(old_outbuf
);
4377 /****************************************************************************
4378 Read 4 bytes of a smb packet and return the smb length of the packet.
4379 Store the result in the buffer. This version of the function will
4380 never return a session keepalive (length of zero).
4381 Timeout is in milliseconds.
4382 ****************************************************************************/
4384 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4387 uint8_t msgtype
= NBSSkeepalive
;
4389 while (msgtype
== NBSSkeepalive
) {
4392 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4394 if (!NT_STATUS_IS_OK(status
)) {
4395 char addr
[INET6_ADDRSTRLEN
];
4396 /* Try and give an error message
4397 * saying what client failed. */
4398 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4399 "client %s read error = %s.\n",
4400 get_peer_addr(fd
,addr
,sizeof(addr
)),
4401 nt_errstr(status
)));
4405 msgtype
= CVAL(inbuf
, 0);
4408 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4409 (unsigned long)len
));
4411 return NT_STATUS_OK
;
4414 /****************************************************************************
4415 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4416 ****************************************************************************/
4418 void reply_writebraw(struct smb_request
*req
)
4420 connection_struct
*conn
= req
->conn
;
4421 struct smbXsrv_connection
*xconn
= req
->xconn
;
4424 ssize_t total_written
=0;
4425 size_t numtowrite
=0;
4428 const char *data
=NULL
;
4431 struct lock_struct lock
;
4434 START_PROFILE(SMBwritebraw
);
4437 * If we ever reply with an error, it must have the SMB command
4438 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4441 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4443 if (srv_is_signing_active(xconn
)) {
4444 END_PROFILE(SMBwritebraw
);
4445 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4446 "raw reads/writes are disallowed.");
4449 if (req
->wct
< 12) {
4450 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4451 error_to_writebrawerr(req
);
4452 END_PROFILE(SMBwritebraw
);
4456 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4457 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4458 "'async smb echo handler = yes'\n"));
4459 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4460 error_to_writebrawerr(req
);
4461 END_PROFILE(SMBwritebraw
);
4465 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4466 if (!check_fsp(conn
, req
, fsp
)) {
4467 error_to_writebrawerr(req
);
4468 END_PROFILE(SMBwritebraw
);
4472 if (!CHECK_WRITE(fsp
)) {
4473 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4474 error_to_writebrawerr(req
);
4475 END_PROFILE(SMBwritebraw
);
4479 tcount
= IVAL(req
->vwv
+1, 0);
4480 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4481 write_through
= BITSETW(req
->vwv
+7,0);
4483 /* We have to deal with slightly different formats depending
4484 on whether we are using the core+ or lanman1.0 protocol */
4486 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4487 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4488 data
= smb_buf_const(req
->inbuf
);
4490 numtowrite
= SVAL(req
->vwv
+10, 0);
4491 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4494 /* Ensure we don't write bytes past the end of this packet. */
4496 * This already protects us against CVE-2017-12163.
4498 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4499 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4500 error_to_writebrawerr(req
);
4501 END_PROFILE(SMBwritebraw
);
4505 if (!fsp
->print_file
) {
4506 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4507 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4510 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4511 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4512 error_to_writebrawerr(req
);
4513 END_PROFILE(SMBwritebraw
);
4519 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4522 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4523 "wrote=%d sync=%d\n",
4524 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4525 (int)nwritten
, (int)write_through
));
4527 if (nwritten
< (ssize_t
)numtowrite
) {
4528 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4529 error_to_writebrawerr(req
);
4533 total_written
= nwritten
;
4535 /* Allocate a buffer of 64k + length. */
4536 buf
= talloc_array(NULL
, char, 65540);
4538 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4539 error_to_writebrawerr(req
);
4543 /* Return a SMBwritebraw message to the redirector to tell
4544 * it to send more bytes */
4546 memcpy(buf
, req
->inbuf
, smb_size
);
4547 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4548 SCVAL(buf
,smb_com
,SMBwritebraw
);
4549 SSVALS(buf
,smb_vwv0
,0xFFFF);
4551 if (!srv_send_smb(req
->xconn
,
4553 false, 0, /* no signing */
4554 IS_CONN_ENCRYPTED(conn
),
4556 exit_server_cleanly("reply_writebraw: srv_send_smb "
4560 /* Now read the raw data into the buffer and write it */
4561 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4563 if (!NT_STATUS_IS_OK(status
)) {
4564 exit_server_cleanly("secondary writebraw failed");
4567 /* Set up outbuf to return the correct size */
4568 reply_outbuf(req
, 1, 0);
4570 if (numtowrite
!= 0) {
4572 if (numtowrite
> 0xFFFF) {
4573 DEBUG(0,("reply_writebraw: Oversize secondary write "
4574 "raw requested (%u). Terminating\n",
4575 (unsigned int)numtowrite
));
4576 exit_server_cleanly("secondary writebraw failed");
4579 if (tcount
> nwritten
+numtowrite
) {
4580 DEBUG(3,("reply_writebraw: Client overestimated the "
4582 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4585 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4588 if (!NT_STATUS_IS_OK(status
)) {
4589 /* Try and give an error message
4590 * saying what client failed. */
4591 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4592 "raw read failed (%s) for client %s. "
4593 "Terminating\n", nt_errstr(status
),
4594 smbXsrv_connection_dbg(xconn
)));
4595 exit_server_cleanly("secondary writebraw failed");
4599 * We are not vulnerable to CVE-2017-12163
4600 * here as we are guaranteed to have numtowrite
4601 * bytes available - we just read from the client.
4603 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4604 if (nwritten
== -1) {
4606 reply_nterror(req
, map_nt_error_from_unix(errno
));
4607 error_to_writebrawerr(req
);
4611 if (nwritten
< (ssize_t
)numtowrite
) {
4612 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4613 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4617 total_written
+= nwritten
;
4622 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4624 status
= sync_file(conn
, fsp
, write_through
);
4625 if (!NT_STATUS_IS_OK(status
)) {
4626 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4627 fsp_str_dbg(fsp
), nt_errstr(status
)));
4628 reply_nterror(req
, status
);
4629 error_to_writebrawerr(req
);
4633 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4635 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4636 (int)total_written
));
4638 /* We won't return a status if write through is not selected - this
4639 * follows what WfWg does */
4640 END_PROFILE(SMBwritebraw
);
4642 if (!write_through
&& total_written
==tcount
) {
4644 #if RABBIT_PELLET_FIX
4646 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4647 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4650 if (!send_keepalive(xconn
->transport
.sock
)) {
4651 exit_server_cleanly("reply_writebraw: send of "
4652 "keepalive failed");
4655 TALLOC_FREE(req
->outbuf
);
4660 END_PROFILE(SMBwritebraw
);
4665 #define DBGC_CLASS DBGC_LOCKING
4667 /****************************************************************************
4668 Reply to a writeunlock (core+).
4669 ****************************************************************************/
4671 void reply_writeunlock(struct smb_request
*req
)
4673 connection_struct
*conn
= req
->conn
;
4674 ssize_t nwritten
= -1;
4679 NTSTATUS status
= NT_STATUS_OK
;
4681 struct lock_struct lock
;
4682 int saved_errno
= 0;
4684 START_PROFILE(SMBwriteunlock
);
4687 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4688 END_PROFILE(SMBwriteunlock
);
4692 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4694 if (!check_fsp(conn
, req
, fsp
)) {
4695 END_PROFILE(SMBwriteunlock
);
4699 if (!CHECK_WRITE(fsp
)) {
4700 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4701 END_PROFILE(SMBwriteunlock
);
4705 numtowrite
= SVAL(req
->vwv
+1, 0);
4706 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4707 data
= (const char *)req
->buf
+ 3;
4710 * Ensure client isn't asking us to write more than
4711 * they sent. CVE-2017-12163.
4713 remaining
= smbreq_bufrem(req
, data
);
4714 if (numtowrite
> remaining
) {
4715 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4716 END_PROFILE(SMBwriteunlock
);
4720 if (!fsp
->print_file
&& numtowrite
> 0) {
4721 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4722 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4725 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4726 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4727 END_PROFILE(SMBwriteunlock
);
4732 /* The special X/Open SMB protocol handling of
4733 zero length writes is *NOT* done for
4735 if(numtowrite
== 0) {
4738 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4739 saved_errno
= errno
;
4742 status
= sync_file(conn
, fsp
, False
/* write through */);
4743 if (!NT_STATUS_IS_OK(status
)) {
4744 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4745 fsp_str_dbg(fsp
), nt_errstr(status
)));
4746 reply_nterror(req
, status
);
4751 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4755 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4756 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4760 if (numtowrite
&& !fsp
->print_file
) {
4761 status
= do_unlock(req
->sconn
->msg_ctx
,
4763 (uint64_t)req
->smbpid
,
4764 (uint64_t)numtowrite
,
4768 if (NT_STATUS_V(status
)) {
4769 reply_nterror(req
, status
);
4774 reply_outbuf(req
, 1, 0);
4776 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4778 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4779 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4782 END_PROFILE(SMBwriteunlock
);
4787 #define DBGC_CLASS DBGC_ALL
4789 /****************************************************************************
4791 ****************************************************************************/
4793 void reply_write(struct smb_request
*req
)
4795 connection_struct
*conn
= req
->conn
;
4798 ssize_t nwritten
= -1;
4802 struct lock_struct lock
;
4804 int saved_errno
= 0;
4806 START_PROFILE(SMBwrite
);
4809 END_PROFILE(SMBwrite
);
4810 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4814 /* If it's an IPC, pass off the pipe handler. */
4816 reply_pipe_write(req
);
4817 END_PROFILE(SMBwrite
);
4821 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4823 if (!check_fsp(conn
, req
, fsp
)) {
4824 END_PROFILE(SMBwrite
);
4828 if (!CHECK_WRITE(fsp
)) {
4829 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4830 END_PROFILE(SMBwrite
);
4834 numtowrite
= SVAL(req
->vwv
+1, 0);
4835 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4836 data
= (const char *)req
->buf
+ 3;
4839 * Ensure client isn't asking us to write more than
4840 * they sent. CVE-2017-12163.
4842 remaining
= smbreq_bufrem(req
, data
);
4843 if (numtowrite
> remaining
) {
4844 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4845 END_PROFILE(SMBwrite
);
4849 if (!fsp
->print_file
) {
4850 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4851 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4854 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4855 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4856 END_PROFILE(SMBwrite
);
4862 * X/Open SMB protocol says that if smb_vwv1 is
4863 * zero then the file size should be extended or
4864 * truncated to the size given in smb_vwv[2-3].
4867 if(numtowrite
== 0) {
4869 * This is actually an allocate call, and set EOF. JRA.
4871 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4873 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4876 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4878 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4881 trigger_write_time_update_immediate(fsp
);
4883 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4886 status
= sync_file(conn
, fsp
, False
);
4887 if (!NT_STATUS_IS_OK(status
)) {
4888 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4889 fsp_str_dbg(fsp
), nt_errstr(status
)));
4890 reply_nterror(req
, status
);
4895 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4899 if((nwritten
== 0) && (numtowrite
!= 0)) {
4900 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4904 reply_outbuf(req
, 1, 0);
4906 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4908 if (nwritten
< (ssize_t
)numtowrite
) {
4909 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4910 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4913 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4916 END_PROFILE(SMBwrite
);
4920 /****************************************************************************
4921 Ensure a buffer is a valid writeX for recvfile purposes.
4922 ****************************************************************************/
4924 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4925 (2*14) + /* word count (including bcc) */ \
4928 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4929 const uint8_t *inbuf
)
4932 unsigned int doff
= 0;
4933 size_t len
= smb_len_large(inbuf
);
4935 struct smbXsrv_open
*op
= NULL
;
4936 struct files_struct
*fsp
= NULL
;
4939 if (is_encrypted_packet(inbuf
)) {
4940 /* Can't do this on encrypted
4945 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4949 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4950 CVAL(inbuf
,smb_wct
) != 14) {
4951 DEBUG(10,("is_valid_writeX_buffer: chained or "
4952 "invalid word length.\n"));
4956 fnum
= SVAL(inbuf
, smb_vwv2
);
4957 status
= smb1srv_open_lookup(xconn
,
4961 if (!NT_STATUS_IS_OK(status
)) {
4962 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4967 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4970 if (fsp
->conn
== NULL
) {
4971 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4975 if (IS_IPC(fsp
->conn
)) {
4976 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4979 if (IS_PRINT(fsp
->conn
)) {
4980 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4983 if (fsp
->base_fsp
!= NULL
) {
4984 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4987 doff
= SVAL(inbuf
,smb_vwv11
);
4989 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4991 if (len
> doff
&& len
- doff
> 0xFFFF) {
4992 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4995 if (numtowrite
== 0) {
4996 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5000 /* Ensure the sizes match up. */
5001 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
5002 /* no pad byte...old smbclient :-( */
5003 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5005 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
5009 if (len
- doff
!= numtowrite
) {
5010 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5011 "len = %u, doff = %u, numtowrite = %u\n",
5014 (unsigned int)numtowrite
));
5018 DEBUG(10,("is_valid_writeX_buffer: true "
5019 "len = %u, doff = %u, numtowrite = %u\n",
5022 (unsigned int)numtowrite
));
5027 /****************************************************************************
5028 Reply to a write and X.
5029 ****************************************************************************/
5031 void reply_write_and_X(struct smb_request
*req
)
5033 connection_struct
*conn
= req
->conn
;
5034 struct smbXsrv_connection
*xconn
= req
->xconn
;
5036 struct lock_struct lock
;
5041 unsigned int smb_doff
;
5042 unsigned int smblen
;
5045 int saved_errno
= 0;
5047 START_PROFILE(SMBwriteX
);
5049 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5050 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5054 numtowrite
= SVAL(req
->vwv
+10, 0);
5055 smb_doff
= SVAL(req
->vwv
+11, 0);
5056 smblen
= smb_len(req
->inbuf
);
5058 if (req
->unread_bytes
> 0xFFFF ||
5059 (smblen
> smb_doff
&&
5060 smblen
- smb_doff
> 0xFFFF)) {
5061 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5064 if (req
->unread_bytes
) {
5065 /* Can't do a recvfile write on IPC$ */
5067 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5070 if (numtowrite
!= req
->unread_bytes
) {
5071 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5076 * This already protects us against CVE-2017-12163.
5078 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5079 smb_doff
+ numtowrite
> smblen
) {
5080 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5085 /* If it's an IPC, pass off the pipe handler. */
5087 if (req
->unread_bytes
) {
5088 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5091 reply_pipe_write_and_X(req
);
5095 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5096 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5097 write_through
= BITSETW(req
->vwv
+7,0);
5099 if (!check_fsp(conn
, req
, fsp
)) {
5103 if (!CHECK_WRITE(fsp
)) {
5104 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5108 data
= smb_base(req
->inbuf
) + smb_doff
;
5110 if(req
->wct
== 14) {
5112 * This is a large offset (64 bit) write.
5114 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5118 /* X/Open SMB protocol says that, unlike SMBwrite
5119 if the length is zero then NO truncation is
5120 done, just a write of zero. To truncate a file,
5123 if(numtowrite
== 0) {
5126 if (req
->unread_bytes
== 0) {
5127 status
= schedule_aio_write_and_X(conn
,
5134 if (NT_STATUS_IS_OK(status
)) {
5135 /* write scheduled - we're done. */
5138 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5139 /* Real error - report to client. */
5140 reply_nterror(req
, status
);
5143 /* NT_STATUS_RETRY - fall through to sync write. */
5146 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5147 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5150 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5151 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5155 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5156 saved_errno
= errno
;
5160 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5164 if((nwritten
== 0) && (numtowrite
!= 0)) {
5165 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5169 reply_outbuf(req
, 6, 0);
5170 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5171 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5172 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5173 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5175 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5176 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5178 status
= sync_file(conn
, fsp
, write_through
);
5179 if (!NT_STATUS_IS_OK(status
)) {
5180 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5181 fsp_str_dbg(fsp
), nt_errstr(status
)));
5182 reply_nterror(req
, status
);
5186 END_PROFILE(SMBwriteX
);
5190 if (req
->unread_bytes
) {
5191 /* writeX failed. drain socket. */
5192 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5193 req
->unread_bytes
) {
5194 smb_panic("failed to drain pending bytes");
5196 req
->unread_bytes
= 0;
5199 END_PROFILE(SMBwriteX
);
5203 /****************************************************************************
5205 ****************************************************************************/
5207 void reply_lseek(struct smb_request
*req
)
5209 connection_struct
*conn
= req
->conn
;
5215 START_PROFILE(SMBlseek
);
5218 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5219 END_PROFILE(SMBlseek
);
5223 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5225 if (!check_fsp(conn
, req
, fsp
)) {
5229 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5231 mode
= SVAL(req
->vwv
+1, 0) & 3;
5232 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5233 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5242 res
= fsp
->fh
->pos
+ startpos
;
5253 if (umode
== SEEK_END
) {
5254 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5255 if(errno
== EINVAL
) {
5256 off_t current_pos
= startpos
;
5258 if(fsp_stat(fsp
) == -1) {
5260 map_nt_error_from_unix(errno
));
5261 END_PROFILE(SMBlseek
);
5265 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5267 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5272 reply_nterror(req
, map_nt_error_from_unix(errno
));
5273 END_PROFILE(SMBlseek
);
5280 reply_outbuf(req
, 2, 0);
5281 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5283 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5284 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5286 END_PROFILE(SMBlseek
);
5290 static struct files_struct
*file_sync_one_fn(struct files_struct
*fsp
,
5293 connection_struct
*conn
= talloc_get_type_abort(
5294 private_data
, connection_struct
);
5296 if (conn
!= fsp
->conn
) {
5299 if (fsp
->fh
->fd
== -1) {
5302 sync_file(conn
, fsp
, True
/* write through */);
5307 /****************************************************************************
5309 ****************************************************************************/
5311 void reply_flush(struct smb_request
*req
)
5313 connection_struct
*conn
= req
->conn
;
5317 START_PROFILE(SMBflush
);
5320 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5324 fnum
= SVAL(req
->vwv
+0, 0);
5325 fsp
= file_fsp(req
, fnum
);
5327 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5332 files_forall(req
->sconn
, file_sync_one_fn
, conn
);
5334 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5335 if (!NT_STATUS_IS_OK(status
)) {
5336 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5337 fsp_str_dbg(fsp
), nt_errstr(status
)));
5338 reply_nterror(req
, status
);
5339 END_PROFILE(SMBflush
);
5344 reply_outbuf(req
, 0, 0);
5346 DEBUG(3,("flush\n"));
5347 END_PROFILE(SMBflush
);
5351 /****************************************************************************
5353 conn POINTER CAN BE NULL HERE !
5354 ****************************************************************************/
5356 void reply_exit(struct smb_request
*req
)
5358 START_PROFILE(SMBexit
);
5360 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5362 reply_outbuf(req
, 0, 0);
5364 DEBUG(3,("exit\n"));
5366 END_PROFILE(SMBexit
);
5370 struct reply_close_state
{
5372 struct smb_request
*smbreq
;
5375 static void do_smb1_close(struct tevent_req
*req
);
5377 void reply_close(struct smb_request
*req
)
5379 connection_struct
*conn
= req
->conn
;
5380 NTSTATUS status
= NT_STATUS_OK
;
5381 files_struct
*fsp
= NULL
;
5382 START_PROFILE(SMBclose
);
5385 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5386 END_PROFILE(SMBclose
);
5390 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5393 * We can only use check_fsp if we know it's not a directory.
5396 if (!check_fsp_open(conn
, req
, fsp
)) {
5397 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5398 END_PROFILE(SMBclose
);
5402 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5403 fsp
->is_directory
? "directory" : "file",
5404 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5405 conn
->num_files_open
));
5407 if (!fsp
->is_directory
) {
5411 * Take care of any time sent in the close.
5414 t
= srv_make_unix_date3(req
->vwv
+1);
5415 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5418 if (fsp
->num_aio_requests
!= 0) {
5420 struct reply_close_state
*state
;
5422 DEBUG(10, ("closing with aio %u requests pending\n",
5423 fsp
->num_aio_requests
));
5426 * We depend on the aio_extra destructor to take care of this
5427 * close request once fsp->num_aio_request drops to 0.
5430 fsp
->deferred_close
= tevent_wait_send(
5431 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5432 if (fsp
->deferred_close
== NULL
) {
5433 status
= NT_STATUS_NO_MEMORY
;
5437 state
= talloc(fsp
, struct reply_close_state
);
5438 if (state
== NULL
) {
5439 TALLOC_FREE(fsp
->deferred_close
);
5440 status
= NT_STATUS_NO_MEMORY
;
5444 state
->smbreq
= talloc_move(fsp
, &req
);
5445 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5447 END_PROFILE(SMBclose
);
5452 * close_file() returns the unix errno if an error was detected on
5453 * close - normally this is due to a disk full error. If not then it
5454 * was probably an I/O error.
5457 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5459 if (!NT_STATUS_IS_OK(status
)) {
5460 reply_nterror(req
, status
);
5461 END_PROFILE(SMBclose
);
5465 reply_outbuf(req
, 0, 0);
5466 END_PROFILE(SMBclose
);
5470 static void do_smb1_close(struct tevent_req
*req
)
5472 struct reply_close_state
*state
= tevent_req_callback_data(
5473 req
, struct reply_close_state
);
5474 struct smb_request
*smbreq
;
5478 ret
= tevent_wait_recv(req
);
5481 DEBUG(10, ("tevent_wait_recv returned %s\n",
5484 * Continue anyway, this should never happen
5489 * fsp->smb2_close_request right now is a talloc grandchild of
5490 * fsp. When we close_file(fsp), it would go with it. No chance to
5493 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5495 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5496 if (NT_STATUS_IS_OK(status
)) {
5497 reply_outbuf(smbreq
, 0, 0);
5499 reply_nterror(smbreq
, status
);
5501 if (!srv_send_smb(smbreq
->xconn
,
5502 (char *)smbreq
->outbuf
,
5505 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5507 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5510 TALLOC_FREE(smbreq
);
5513 /****************************************************************************
5514 Reply to a writeclose (Core+ protocol).
5515 ****************************************************************************/
5517 void reply_writeclose(struct smb_request
*req
)
5519 connection_struct
*conn
= req
->conn
;
5522 ssize_t nwritten
= -1;
5523 NTSTATUS close_status
= NT_STATUS_OK
;
5526 struct timespec mtime
;
5528 struct lock_struct lock
;
5530 START_PROFILE(SMBwriteclose
);
5533 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5534 END_PROFILE(SMBwriteclose
);
5538 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5540 if (!check_fsp(conn
, req
, fsp
)) {
5541 END_PROFILE(SMBwriteclose
);
5544 if (!CHECK_WRITE(fsp
)) {
5545 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5546 END_PROFILE(SMBwriteclose
);
5550 numtowrite
= SVAL(req
->vwv
+1, 0);
5551 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5552 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5553 data
= (const char *)req
->buf
+ 1;
5556 * Ensure client isn't asking us to write more than
5557 * they sent. CVE-2017-12163.
5559 remaining
= smbreq_bufrem(req
, data
);
5560 if (numtowrite
> remaining
) {
5561 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5562 END_PROFILE(SMBwriteclose
);
5566 if (fsp
->print_file
== NULL
) {
5567 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5568 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5571 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5572 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5573 END_PROFILE(SMBwriteclose
);
5578 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5580 set_close_write_time(fsp
, mtime
);
5583 * More insanity. W2K only closes the file if writelen > 0.
5587 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5588 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5589 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5592 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5593 "file %s\n", fsp_str_dbg(fsp
)));
5594 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5598 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5599 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5603 if(!NT_STATUS_IS_OK(close_status
)) {
5604 reply_nterror(req
, close_status
);
5608 reply_outbuf(req
, 1, 0);
5610 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5614 END_PROFILE(SMBwriteclose
);
5619 #define DBGC_CLASS DBGC_LOCKING
5621 /****************************************************************************
5623 ****************************************************************************/
5625 void reply_lock(struct smb_request
*req
)
5627 connection_struct
*conn
= req
->conn
;
5628 uint64_t count
,offset
;
5631 struct byte_range_lock
*br_lck
= NULL
;
5633 START_PROFILE(SMBlock
);
5636 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5637 END_PROFILE(SMBlock
);
5641 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5643 if (!check_fsp(conn
, req
, fsp
)) {
5644 END_PROFILE(SMBlock
);
5648 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5649 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5651 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5652 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5654 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5656 (uint64_t)req
->smbpid
,
5661 False
, /* Non-blocking lock. */
5665 TALLOC_FREE(br_lck
);
5667 if (NT_STATUS_V(status
)) {
5668 reply_nterror(req
, status
);
5669 END_PROFILE(SMBlock
);
5673 reply_outbuf(req
, 0, 0);
5675 END_PROFILE(SMBlock
);
5679 /****************************************************************************
5681 ****************************************************************************/
5683 void reply_unlock(struct smb_request
*req
)
5685 connection_struct
*conn
= req
->conn
;
5686 uint64_t count
,offset
;
5690 START_PROFILE(SMBunlock
);
5693 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5694 END_PROFILE(SMBunlock
);
5698 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5700 if (!check_fsp(conn
, req
, fsp
)) {
5701 END_PROFILE(SMBunlock
);
5705 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5706 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5708 status
= do_unlock(req
->sconn
->msg_ctx
,
5710 (uint64_t)req
->smbpid
,
5715 if (NT_STATUS_V(status
)) {
5716 reply_nterror(req
, status
);
5717 END_PROFILE(SMBunlock
);
5721 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5722 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5724 reply_outbuf(req
, 0, 0);
5726 END_PROFILE(SMBunlock
);
5731 #define DBGC_CLASS DBGC_ALL
5733 /****************************************************************************
5735 conn POINTER CAN BE NULL HERE !
5736 ****************************************************************************/
5738 void reply_tdis(struct smb_request
*req
)
5741 connection_struct
*conn
= req
->conn
;
5742 struct smbXsrv_tcon
*tcon
;
5744 START_PROFILE(SMBtdis
);
5747 DEBUG(4,("Invalid connection in tdis\n"));
5748 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5749 END_PROFILE(SMBtdis
);
5757 * TODO: cancel all outstanding requests on the tcon
5759 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5760 if (!NT_STATUS_IS_OK(status
)) {
5761 DEBUG(0, ("reply_tdis: "
5762 "smbXsrv_tcon_disconnect() failed: %s\n",
5763 nt_errstr(status
)));
5765 * If we hit this case, there is something completely
5766 * wrong, so we better disconnect the transport connection.
5768 END_PROFILE(SMBtdis
);
5769 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5775 reply_outbuf(req
, 0, 0);
5776 END_PROFILE(SMBtdis
);
5780 /****************************************************************************
5782 conn POINTER CAN BE NULL HERE !
5783 ****************************************************************************/
5785 void reply_echo(struct smb_request
*req
)
5787 connection_struct
*conn
= req
->conn
;
5788 struct smb_perfcount_data local_pcd
;
5789 struct smb_perfcount_data
*cur_pcd
;
5793 START_PROFILE(SMBecho
);
5795 smb_init_perfcount_data(&local_pcd
);
5798 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5799 END_PROFILE(SMBecho
);
5803 smb_reverb
= SVAL(req
->vwv
+0, 0);
5805 reply_outbuf(req
, 1, req
->buflen
);
5807 /* copy any incoming data back out */
5808 if (req
->buflen
> 0) {
5809 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5812 if (smb_reverb
> 100) {
5813 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5817 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5819 /* this makes sure we catch the request pcd */
5820 if (seq_num
== smb_reverb
) {
5821 cur_pcd
= &req
->pcd
;
5823 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5824 cur_pcd
= &local_pcd
;
5827 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5829 show_msg((char *)req
->outbuf
);
5830 if (!srv_send_smb(req
->xconn
,
5831 (char *)req
->outbuf
,
5832 true, req
->seqnum
+1,
5833 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5835 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5838 DEBUG(3,("echo %d times\n", smb_reverb
));
5840 TALLOC_FREE(req
->outbuf
);
5842 END_PROFILE(SMBecho
);
5846 /****************************************************************************
5847 Reply to a printopen.
5848 ****************************************************************************/
5850 void reply_printopen(struct smb_request
*req
)
5852 connection_struct
*conn
= req
->conn
;
5856 START_PROFILE(SMBsplopen
);
5859 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5860 END_PROFILE(SMBsplopen
);
5864 if (!CAN_PRINT(conn
)) {
5865 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5866 END_PROFILE(SMBsplopen
);
5870 status
= file_new(req
, conn
, &fsp
);
5871 if(!NT_STATUS_IS_OK(status
)) {
5872 reply_nterror(req
, status
);
5873 END_PROFILE(SMBsplopen
);
5877 /* Open for exclusive use, write only. */
5878 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5880 if (!NT_STATUS_IS_OK(status
)) {
5881 file_free(req
, fsp
);
5882 reply_nterror(req
, status
);
5883 END_PROFILE(SMBsplopen
);
5887 reply_outbuf(req
, 1, 0);
5888 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5890 DEBUG(3,("openprint fd=%d %s\n",
5891 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5893 END_PROFILE(SMBsplopen
);
5897 /****************************************************************************
5898 Reply to a printclose.
5899 ****************************************************************************/
5901 void reply_printclose(struct smb_request
*req
)
5903 connection_struct
*conn
= req
->conn
;
5907 START_PROFILE(SMBsplclose
);
5910 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5911 END_PROFILE(SMBsplclose
);
5915 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5917 if (!check_fsp(conn
, req
, fsp
)) {
5918 END_PROFILE(SMBsplclose
);
5922 if (!CAN_PRINT(conn
)) {
5923 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5924 END_PROFILE(SMBsplclose
);
5928 DEBUG(3,("printclose fd=%d %s\n",
5929 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5931 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5933 if(!NT_STATUS_IS_OK(status
)) {
5934 reply_nterror(req
, status
);
5935 END_PROFILE(SMBsplclose
);
5939 reply_outbuf(req
, 0, 0);
5941 END_PROFILE(SMBsplclose
);
5945 /****************************************************************************
5946 Reply to a printqueue.
5947 ****************************************************************************/
5949 void reply_printqueue(struct smb_request
*req
)
5951 connection_struct
*conn
= req
->conn
;
5955 START_PROFILE(SMBsplretq
);
5958 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5959 END_PROFILE(SMBsplretq
);
5963 max_count
= SVAL(req
->vwv
+0, 0);
5964 start_index
= SVAL(req
->vwv
+1, 0);
5966 /* we used to allow the client to get the cnum wrong, but that
5967 is really quite gross and only worked when there was only
5968 one printer - I think we should now only accept it if they
5969 get it right (tridge) */
5970 if (!CAN_PRINT(conn
)) {
5971 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5972 END_PROFILE(SMBsplretq
);
5976 reply_outbuf(req
, 2, 3);
5977 SSVAL(req
->outbuf
,smb_vwv0
,0);
5978 SSVAL(req
->outbuf
,smb_vwv1
,0);
5979 SCVAL(smb_buf(req
->outbuf
),0,1);
5980 SSVAL(smb_buf(req
->outbuf
),1,0);
5982 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5983 start_index
, max_count
));
5986 TALLOC_CTX
*mem_ctx
= talloc_tos();
5989 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5990 struct rpc_pipe_client
*cli
= NULL
;
5991 struct dcerpc_binding_handle
*b
= NULL
;
5992 struct policy_handle handle
;
5993 struct spoolss_DevmodeContainer devmode_ctr
;
5994 union spoolss_JobInfo
*info
;
5996 uint32_t num_to_get
;
6000 ZERO_STRUCT(handle
);
6002 status
= rpc_pipe_open_interface(mem_ctx
,
6005 conn
->sconn
->remote_address
,
6006 conn
->sconn
->local_address
,
6007 conn
->sconn
->msg_ctx
,
6009 if (!NT_STATUS_IS_OK(status
)) {
6010 DEBUG(0, ("reply_printqueue: "
6011 "could not connect to spoolss: %s\n",
6012 nt_errstr(status
)));
6013 reply_nterror(req
, status
);
6016 b
= cli
->binding_handle
;
6018 ZERO_STRUCT(devmode_ctr
);
6020 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
6023 SEC_FLAG_MAXIMUM_ALLOWED
,
6026 if (!NT_STATUS_IS_OK(status
)) {
6027 reply_nterror(req
, status
);
6030 if (!W_ERROR_IS_OK(werr
)) {
6031 reply_nterror(req
, werror_to_ntstatus(werr
));
6035 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
6043 if (!W_ERROR_IS_OK(werr
)) {
6044 reply_nterror(req
, werror_to_ntstatus(werr
));
6048 if (max_count
> 0) {
6049 first
= start_index
;
6051 first
= start_index
+ max_count
+ 1;
6054 if (first
>= count
) {
6057 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6060 for (i
= first
; i
< num_to_get
; i
++) {
6063 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6066 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6067 info
[i
].info2
.job_id
);
6069 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6075 srv_put_dos_date2(p
, 0, qtime
);
6076 SCVAL(p
, 4, qstatus
);
6077 SSVAL(p
, 5, qrapjobid
);
6078 SIVAL(p
, 7, info
[i
].info2
.size
);
6080 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6081 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6082 if (!NT_STATUS_IS_OK(status
)) {
6083 reply_nterror(req
, status
);
6086 if (message_push_blob(
6089 blob
, sizeof(blob
))) == -1) {
6090 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6096 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6097 SSVAL(req
->outbuf
,smb_vwv1
,
6098 (max_count
>0?first
+count
:first
-1));
6099 SCVAL(smb_buf(req
->outbuf
),0,1);
6100 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6104 DEBUG(3, ("%u entries returned in queue\n",
6108 if (b
&& is_valid_policy_hnd(&handle
)) {
6109 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6114 END_PROFILE(SMBsplretq
);
6118 /****************************************************************************
6119 Reply to a printwrite.
6120 ****************************************************************************/
6122 void reply_printwrite(struct smb_request
*req
)
6124 connection_struct
*conn
= req
->conn
;
6129 START_PROFILE(SMBsplwr
);
6132 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6133 END_PROFILE(SMBsplwr
);
6137 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6139 if (!check_fsp(conn
, req
, fsp
)) {
6140 END_PROFILE(SMBsplwr
);
6144 if (!fsp
->print_file
) {
6145 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6146 END_PROFILE(SMBsplwr
);
6150 if (!CHECK_WRITE(fsp
)) {
6151 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6152 END_PROFILE(SMBsplwr
);
6156 numtowrite
= SVAL(req
->buf
, 1);
6159 * This already protects us against CVE-2017-12163.
6161 if (req
->buflen
< numtowrite
+ 3) {
6162 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6163 END_PROFILE(SMBsplwr
);
6167 data
= (const char *)req
->buf
+ 3;
6169 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6170 reply_nterror(req
, map_nt_error_from_unix(errno
));
6171 END_PROFILE(SMBsplwr
);
6175 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6177 END_PROFILE(SMBsplwr
);
6181 /****************************************************************************
6183 ****************************************************************************/
6185 void reply_mkdir(struct smb_request
*req
)
6187 connection_struct
*conn
= req
->conn
;
6188 struct smb_filename
*smb_dname
= NULL
;
6189 char *directory
= NULL
;
6192 TALLOC_CTX
*ctx
= talloc_tos();
6194 START_PROFILE(SMBmkdir
);
6196 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6197 STR_TERMINATE
, &status
);
6198 if (!NT_STATUS_IS_OK(status
)) {
6199 reply_nterror(req
, status
);
6203 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
6204 status
= filename_convert(ctx
, conn
,
6210 if (!NT_STATUS_IS_OK(status
)) {
6211 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6212 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6213 ERRSRV
, ERRbadpath
);
6216 reply_nterror(req
, status
);
6220 status
= create_directory(conn
, req
, smb_dname
);
6222 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6224 if (!NT_STATUS_IS_OK(status
)) {
6226 if (!use_nt_status()
6227 && NT_STATUS_EQUAL(status
,
6228 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6230 * Yes, in the DOS error code case we get a
6231 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6232 * samba4 torture test.
6234 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6237 reply_nterror(req
, status
);
6241 reply_outbuf(req
, 0, 0);
6243 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6245 TALLOC_FREE(smb_dname
);
6246 END_PROFILE(SMBmkdir
);
6250 /****************************************************************************
6252 ****************************************************************************/
6254 void reply_rmdir(struct smb_request
*req
)
6256 connection_struct
*conn
= req
->conn
;
6257 struct smb_filename
*smb_dname
= NULL
;
6258 char *directory
= NULL
;
6260 TALLOC_CTX
*ctx
= talloc_tos();
6261 files_struct
*fsp
= NULL
;
6263 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6264 struct smbd_server_connection
*sconn
= req
->sconn
;
6266 START_PROFILE(SMBrmdir
);
6268 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6269 STR_TERMINATE
, &status
);
6270 if (!NT_STATUS_IS_OK(status
)) {
6271 reply_nterror(req
, status
);
6275 status
= filename_convert(ctx
, conn
,
6281 if (!NT_STATUS_IS_OK(status
)) {
6282 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6283 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6284 ERRSRV
, ERRbadpath
);
6287 reply_nterror(req
, status
);
6291 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6292 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6296 status
= SMB_VFS_CREATE_FILE(
6299 0, /* root_dir_fid */
6300 smb_dname
, /* fname */
6301 DELETE_ACCESS
, /* access_mask */
6302 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6304 FILE_OPEN
, /* create_disposition*/
6305 FILE_DIRECTORY_FILE
, /* create_options */
6306 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6307 0, /* oplock_request */
6309 0, /* allocation_size */
6310 0, /* private_flags */
6315 NULL
, NULL
); /* create context */
6317 if (!NT_STATUS_IS_OK(status
)) {
6318 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6319 /* We have re-scheduled this call. */
6322 reply_nterror(req
, status
);
6326 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6327 if (!NT_STATUS_IS_OK(status
)) {
6328 close_file(req
, fsp
, ERROR_CLOSE
);
6329 reply_nterror(req
, status
);
6333 if (!set_delete_on_close(fsp
, true,
6334 conn
->session_info
->security_token
,
6335 conn
->session_info
->unix_token
)) {
6336 close_file(req
, fsp
, ERROR_CLOSE
);
6337 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6341 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6342 if (!NT_STATUS_IS_OK(status
)) {
6343 reply_nterror(req
, status
);
6345 reply_outbuf(req
, 0, 0);
6348 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6350 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6352 TALLOC_FREE(smb_dname
);
6353 END_PROFILE(SMBrmdir
);
6357 /*******************************************************************
6358 Resolve wildcards in a filename rename.
6359 ********************************************************************/
6361 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6366 char *name2_copy
= NULL
;
6371 char *p
,*p2
, *pname1
, *pname2
;
6373 name2_copy
= talloc_strdup(ctx
, name2
);
6378 pname1
= strrchr_m(name1
,'/');
6379 pname2
= strrchr_m(name2_copy
,'/');
6381 if (!pname1
|| !pname2
) {
6385 /* Truncate the copy of name2 at the last '/' */
6388 /* Now go past the '/' */
6392 root1
= talloc_strdup(ctx
, pname1
);
6393 root2
= talloc_strdup(ctx
, pname2
);
6395 if (!root1
|| !root2
) {
6399 p
= strrchr_m(root1
,'.');
6402 ext1
= talloc_strdup(ctx
, p
+1);
6404 ext1
= talloc_strdup(ctx
, "");
6406 p
= strrchr_m(root2
,'.');
6409 ext2
= talloc_strdup(ctx
, p
+1);
6411 ext2
= talloc_strdup(ctx
, "");
6414 if (!ext1
|| !ext2
) {
6422 /* Hmmm. Should this be mb-aware ? */
6425 } else if (*p2
== '*') {
6427 root2
= talloc_asprintf(ctx
, "%s%s",
6446 /* Hmmm. Should this be mb-aware ? */
6449 } else if (*p2
== '*') {
6451 ext2
= talloc_asprintf(ctx
, "%s%s",
6467 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6472 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6484 /****************************************************************************
6485 Ensure open files have their names updated. Updated to notify other smbd's
6487 ****************************************************************************/
6489 static void rename_open_files(connection_struct
*conn
,
6490 struct share_mode_lock
*lck
,
6492 uint32_t orig_name_hash
,
6493 const struct smb_filename
*smb_fname_dst
)
6496 bool did_rename
= False
;
6498 uint32_t new_name_hash
= 0;
6500 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6501 fsp
= file_find_di_next(fsp
)) {
6502 /* fsp_name is a relative path under the fsp. To change this for other
6503 sharepaths we need to manipulate relative paths. */
6504 /* TODO - create the absolute path and manipulate the newname
6505 relative to the sharepath. */
6506 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6509 if (fsp
->name_hash
!= orig_name_hash
) {
6512 DEBUG(10, ("rename_open_files: renaming file %s "
6513 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6514 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6515 smb_fname_str_dbg(smb_fname_dst
)));
6517 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6518 if (NT_STATUS_IS_OK(status
)) {
6520 new_name_hash
= fsp
->name_hash
;
6525 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6526 "for %s\n", file_id_string_tos(&id
),
6527 smb_fname_str_dbg(smb_fname_dst
)));
6530 /* Send messages to all smbd's (not ourself) that the name has changed. */
6531 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6532 orig_name_hash
, new_name_hash
,
6537 /****************************************************************************
6538 We need to check if the source path is a parent directory of the destination
6539 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6540 refuse the rename with a sharing violation. Under UNIX the above call can
6541 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6542 probably need to check that the client is a Windows one before disallowing
6543 this as a UNIX client (one with UNIX extensions) can know the source is a
6544 symlink and make this decision intelligently. Found by an excellent bug
6545 report from <AndyLiebman@aol.com>.
6546 ****************************************************************************/
6548 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6549 const struct smb_filename
*smb_fname_dst
)
6551 const char *psrc
= smb_fname_src
->base_name
;
6552 const char *pdst
= smb_fname_dst
->base_name
;
6555 if (psrc
[0] == '.' && psrc
[1] == '/') {
6558 if (pdst
[0] == '.' && pdst
[1] == '/') {
6561 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6564 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6568 * Do the notify calls from a rename
6571 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6572 const struct smb_filename
*smb_fname_src
,
6573 const struct smb_filename
*smb_fname_dst
)
6575 char *parent_dir_src
= NULL
;
6576 char *parent_dir_dst
= NULL
;
6579 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6580 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6582 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6583 &parent_dir_src
, NULL
) ||
6584 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6585 &parent_dir_dst
, NULL
)) {
6589 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6590 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6591 smb_fname_src
->base_name
);
6592 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6593 smb_fname_dst
->base_name
);
6596 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6597 smb_fname_src
->base_name
);
6598 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6599 smb_fname_dst
->base_name
);
6602 /* this is a strange one. w2k3 gives an additional event for
6603 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6604 files, but not directories */
6606 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6607 FILE_NOTIFY_CHANGE_ATTRIBUTES
6608 |FILE_NOTIFY_CHANGE_CREATION
,
6609 smb_fname_dst
->base_name
);
6612 TALLOC_FREE(parent_dir_src
);
6613 TALLOC_FREE(parent_dir_dst
);
6616 /****************************************************************************
6617 Returns an error if the parent directory for a filename is open in an
6619 ****************************************************************************/
6621 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6622 const struct smb_filename
*smb_fname_dst_in
)
6624 char *parent_dir
= NULL
;
6625 struct smb_filename smb_fname_parent
;
6627 files_struct
*fsp
= NULL
;
6630 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6631 &parent_dir
, NULL
)) {
6632 return NT_STATUS_NO_MEMORY
;
6634 ZERO_STRUCT(smb_fname_parent
);
6635 smb_fname_parent
.base_name
= parent_dir
;
6637 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6639 return map_nt_error_from_unix(errno
);
6643 * We're only checking on this smbd here, mostly good
6644 * enough.. and will pass tests.
6647 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6648 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6649 fsp
= file_find_di_next(fsp
)) {
6650 if (fsp
->access_mask
& DELETE_ACCESS
) {
6651 return NT_STATUS_SHARING_VIOLATION
;
6654 return NT_STATUS_OK
;
6657 /****************************************************************************
6658 Rename an open file - given an fsp.
6659 ****************************************************************************/
6661 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6663 const struct smb_filename
*smb_fname_dst_in
,
6665 bool replace_if_exists
)
6667 TALLOC_CTX
*ctx
= talloc_tos();
6668 struct smb_filename
*smb_fname_dst
= NULL
;
6669 NTSTATUS status
= NT_STATUS_OK
;
6670 struct share_mode_lock
*lck
= NULL
;
6671 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
6672 bool dst_exists
, old_is_stream
, new_is_stream
;
6674 status
= check_name(conn
, smb_fname_dst_in
);
6675 if (!NT_STATUS_IS_OK(status
)) {
6679 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6680 if (!NT_STATUS_IS_OK(status
)) {
6684 if (file_has_open_streams(fsp
)) {
6685 return NT_STATUS_ACCESS_DENIED
;
6688 /* Make a copy of the dst smb_fname structs */
6690 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6691 if (smb_fname_dst
== NULL
) {
6692 status
= NT_STATUS_NO_MEMORY
;
6697 * Check for special case with case preserving and not
6698 * case sensitive. If the new last component differs from the original
6699 * last component only by case, then we should allow
6700 * the rename (user is trying to change the case of the
6703 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
6704 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6705 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6706 char *fname_dst_parent
= NULL
;
6707 const char *fname_dst_lcomp
= NULL
;
6708 char *orig_lcomp_path
= NULL
;
6709 char *orig_lcomp_stream
= NULL
;
6713 * Split off the last component of the processed
6714 * destination name. We will compare this to
6715 * the split components of smb_fname_dst->original_lcomp.
6717 if (!parent_dirname(ctx
,
6718 smb_fname_dst
->base_name
,
6720 &fname_dst_lcomp
)) {
6721 status
= NT_STATUS_NO_MEMORY
;
6726 * The original_lcomp component contains
6727 * the last_component of the path + stream
6728 * name (if a stream exists).
6730 * Split off the stream name so we
6731 * can check them separately.
6734 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
6735 /* POSIX - no stream component. */
6736 orig_lcomp_path
= talloc_strdup(ctx
,
6737 smb_fname_dst
->original_lcomp
);
6738 if (orig_lcomp_path
== NULL
) {
6742 ok
= split_stream_filename(ctx
,
6743 smb_fname_dst
->original_lcomp
,
6745 &orig_lcomp_stream
);
6749 TALLOC_FREE(fname_dst_parent
);
6750 status
= NT_STATUS_NO_MEMORY
;
6754 /* If the base names only differ by case, use original. */
6755 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
6758 * Replace the modified last component with the
6761 if (!ISDOT(fname_dst_parent
)) {
6762 tmp
= talloc_asprintf(smb_fname_dst
,
6767 tmp
= talloc_strdup(smb_fname_dst
,
6771 status
= NT_STATUS_NO_MEMORY
;
6772 TALLOC_FREE(fname_dst_parent
);
6773 TALLOC_FREE(orig_lcomp_path
);
6774 TALLOC_FREE(orig_lcomp_stream
);
6777 TALLOC_FREE(smb_fname_dst
->base_name
);
6778 smb_fname_dst
->base_name
= tmp
;
6781 /* If the stream_names only differ by case, use original. */
6782 if(!strcsequal(smb_fname_dst
->stream_name
,
6783 orig_lcomp_stream
)) {
6784 /* Use the original stream. */
6785 char *tmp
= talloc_strdup(smb_fname_dst
,
6788 status
= NT_STATUS_NO_MEMORY
;
6789 TALLOC_FREE(fname_dst_parent
);
6790 TALLOC_FREE(orig_lcomp_path
);
6791 TALLOC_FREE(orig_lcomp_stream
);
6794 TALLOC_FREE(smb_fname_dst
->stream_name
);
6795 smb_fname_dst
->stream_name
= tmp
;
6797 TALLOC_FREE(fname_dst_parent
);
6798 TALLOC_FREE(orig_lcomp_path
);
6799 TALLOC_FREE(orig_lcomp_stream
);
6803 * If the src and dest names are identical - including case,
6804 * don't do the rename, just return success.
6807 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6808 strcsequal(fsp
->fsp_name
->stream_name
,
6809 smb_fname_dst
->stream_name
)) {
6810 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6811 "- returning success\n",
6812 smb_fname_str_dbg(smb_fname_dst
)));
6813 status
= NT_STATUS_OK
;
6817 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6818 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6820 /* Return the correct error code if both names aren't streams. */
6821 if (!old_is_stream
&& new_is_stream
) {
6822 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6826 if (old_is_stream
&& !new_is_stream
) {
6827 status
= NT_STATUS_INVALID_PARAMETER
;
6831 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6833 if(!replace_if_exists
&& dst_exists
) {
6834 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6835 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6836 smb_fname_str_dbg(smb_fname_dst
)));
6837 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6842 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6843 &smb_fname_dst
->st
);
6844 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6846 /* The file can be open when renaming a stream */
6847 if (dst_fsp
&& !new_is_stream
) {
6848 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6849 status
= NT_STATUS_ACCESS_DENIED
;
6854 /* Ensure we have a valid stat struct for the source. */
6855 status
= vfs_stat_fsp(fsp
);
6856 if (!NT_STATUS_IS_OK(status
)) {
6860 status
= can_rename(conn
, fsp
, attrs
);
6862 if (!NT_STATUS_IS_OK(status
)) {
6863 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6864 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6865 smb_fname_str_dbg(smb_fname_dst
)));
6866 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6867 status
= NT_STATUS_ACCESS_DENIED
;
6871 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6872 status
= NT_STATUS_ACCESS_DENIED
;
6876 /* Do we have rights to move into the destination ? */
6877 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
6878 /* We're moving a directory. */
6879 access_mask
= SEC_DIR_ADD_SUBDIR
;
6881 status
= check_parent_access(conn
,
6884 if (!NT_STATUS_IS_OK(status
)) {
6885 DBG_INFO("check_parent_access on "
6886 "dst %s returned %s\n",
6887 smb_fname_str_dbg(smb_fname_dst
),
6892 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6895 * We have the file open ourselves, so not being able to get the
6896 * corresponding share mode lock is a fatal error.
6899 SMB_ASSERT(lck
!= NULL
);
6901 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6902 uint32_t create_options
= fsp
->fh
->private_options
;
6904 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6905 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6906 smb_fname_str_dbg(smb_fname_dst
)));
6908 if (!fsp
->is_directory
&&
6909 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
6910 (lp_map_archive(SNUM(conn
)) ||
6911 lp_store_dos_attributes(SNUM(conn
)))) {
6912 /* We must set the archive bit on the newly
6914 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6915 uint32_t old_dosmode
= dos_mode(conn
,
6917 file_set_dosmode(conn
,
6919 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6925 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6928 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6932 * A rename acts as a new file create w.r.t. allowing an initial delete
6933 * on close, probably because in Windows there is a new handle to the
6934 * new file. If initial delete on close was requested but not
6935 * originally set, we need to set it here. This is probably not 100% correct,
6936 * but will work for the CIFSFS client which in non-posix mode
6937 * depends on these semantics. JRA.
6940 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6941 status
= can_set_delete_on_close(fsp
, 0);
6943 if (NT_STATUS_IS_OK(status
)) {
6944 /* Note that here we set the *initial* delete on close flag,
6945 * not the regular one. The magic gets handled in close. */
6946 fsp
->initial_delete_on_close
= True
;
6950 status
= NT_STATUS_OK
;
6956 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6957 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6959 status
= map_nt_error_from_unix(errno
);
6962 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6963 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6964 smb_fname_str_dbg(smb_fname_dst
)));
6967 TALLOC_FREE(smb_fname_dst
);
6972 /****************************************************************************
6973 The guts of the rename command, split out so it may be called by the NT SMB
6975 ****************************************************************************/
6977 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6978 connection_struct
*conn
,
6979 struct smb_request
*req
,
6980 struct smb_filename
*smb_fname_src
,
6981 struct smb_filename
*smb_fname_dst
,
6983 bool replace_if_exists
,
6986 uint32_t access_mask
)
6988 char *fname_src_dir
= NULL
;
6989 struct smb_filename
*smb_fname_src_dir
= NULL
;
6990 char *fname_src_mask
= NULL
;
6992 NTSTATUS status
= NT_STATUS_OK
;
6993 struct smb_Dir
*dir_hnd
= NULL
;
6994 const char *dname
= NULL
;
6995 char *talloced
= NULL
;
6997 int create_options
= 0;
6998 bool posix_pathnames
= (req
!= NULL
&& req
->posix_pathnames
);
7002 * Split the old name into directory and last component
7003 * strings. Note that unix_convert may have stripped off a
7004 * leading ./ from both name and newname if the rename is
7005 * at the root of the share. We need to make sure either both
7006 * name and newname contain a / character or neither of them do
7007 * as this is checked in resolve_wildcards().
7010 /* Split up the directory from the filename/mask. */
7011 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7012 &fname_src_dir
, &fname_src_mask
);
7013 if (!NT_STATUS_IS_OK(status
)) {
7014 status
= NT_STATUS_NO_MEMORY
;
7019 * We should only check the mangled cache
7020 * here if unix_convert failed. This means
7021 * that the path in 'mask' doesn't exist
7022 * on the file system and so we need to look
7023 * for a possible mangle. This patch from
7024 * Tine Smukavec <valentin.smukavec@hermes.si>.
7027 if (!VALID_STAT(smb_fname_src
->st
) &&
7028 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7029 char *new_mask
= NULL
;
7030 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
7033 TALLOC_FREE(fname_src_mask
);
7034 fname_src_mask
= new_mask
;
7038 if (!src_has_wild
) {
7042 * Only one file needs to be renamed. Append the mask back
7043 * onto the directory.
7045 TALLOC_FREE(smb_fname_src
->base_name
);
7046 if (ISDOT(fname_src_dir
)) {
7047 /* Ensure we use canonical names on open. */
7048 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7052 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7057 if (!smb_fname_src
->base_name
) {
7058 status
= NT_STATUS_NO_MEMORY
;
7062 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7063 "case_preserve = %d, short case preserve = %d, "
7064 "directory = %s, newname = %s, "
7065 "last_component_dest = %s\n",
7066 conn
->case_sensitive
, conn
->case_preserve
,
7067 conn
->short_case_preserve
,
7068 smb_fname_str_dbg(smb_fname_src
),
7069 smb_fname_str_dbg(smb_fname_dst
),
7070 smb_fname_dst
->original_lcomp
));
7072 /* The dest name still may have wildcards. */
7073 if (dest_has_wild
) {
7074 char *fname_dst_mod
= NULL
;
7075 if (!resolve_wildcards(smb_fname_dst
,
7076 smb_fname_src
->base_name
,
7077 smb_fname_dst
->base_name
,
7079 DEBUG(6, ("rename_internals: resolve_wildcards "
7081 smb_fname_src
->base_name
,
7082 smb_fname_dst
->base_name
));
7083 status
= NT_STATUS_NO_MEMORY
;
7086 TALLOC_FREE(smb_fname_dst
->base_name
);
7087 smb_fname_dst
->base_name
= fname_dst_mod
;
7090 ZERO_STRUCT(smb_fname_src
->st
);
7091 if (posix_pathnames
) {
7092 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
7094 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
7097 status
= map_nt_error_from_unix_common(errno
);
7101 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7102 create_options
|= FILE_DIRECTORY_FILE
;
7105 status
= SMB_VFS_CREATE_FILE(
7108 0, /* root_dir_fid */
7109 smb_fname_src
, /* fname */
7110 access_mask
, /* access_mask */
7111 (FILE_SHARE_READ
| /* share_access */
7113 FILE_OPEN
, /* create_disposition*/
7114 create_options
, /* create_options */
7115 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7116 0, /* oplock_request */
7118 0, /* allocation_size */
7119 0, /* private_flags */
7124 NULL
, NULL
); /* create context */
7126 if (!NT_STATUS_IS_OK(status
)) {
7127 DEBUG(3, ("Could not open rename source %s: %s\n",
7128 smb_fname_str_dbg(smb_fname_src
),
7129 nt_errstr(status
)));
7133 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7134 attrs
, replace_if_exists
);
7136 close_file(req
, fsp
, NORMAL_CLOSE
);
7138 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7139 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
7140 smb_fname_str_dbg(smb_fname_dst
)));
7146 * Wildcards - process each file that matches.
7148 if (strequal(fname_src_mask
, "????????.???")) {
7149 TALLOC_FREE(fname_src_mask
);
7150 fname_src_mask
= talloc_strdup(ctx
, "*");
7151 if (!fname_src_mask
) {
7152 status
= NT_STATUS_NO_MEMORY
;
7157 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7161 smb_fname_src
->flags
);
7162 if (smb_fname_src_dir
== NULL
) {
7163 status
= NT_STATUS_NO_MEMORY
;
7167 status
= check_name(conn
, smb_fname_src_dir
);
7168 if (!NT_STATUS_IS_OK(status
)) {
7172 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
7174 if (dir_hnd
== NULL
) {
7175 status
= map_nt_error_from_unix(errno
);
7179 status
= NT_STATUS_NO_SUCH_FILE
;
7181 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7182 * - gentest fix. JRA
7185 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
7187 files_struct
*fsp
= NULL
;
7188 char *destname
= NULL
;
7189 bool sysdir_entry
= False
;
7191 /* Quick check for "." and ".." */
7192 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7193 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
7194 sysdir_entry
= True
;
7196 TALLOC_FREE(talloced
);
7201 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7202 &smb_fname_src
->st
, false)) {
7203 TALLOC_FREE(talloced
);
7207 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
7208 TALLOC_FREE(talloced
);
7213 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7217 TALLOC_FREE(smb_fname_src
->base_name
);
7218 if (ISDOT(fname_src_dir
)) {
7219 /* Ensure we use canonical names on open. */
7220 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7224 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7229 if (!smb_fname_src
->base_name
) {
7230 status
= NT_STATUS_NO_MEMORY
;
7234 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7235 smb_fname_dst
->base_name
,
7237 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7238 smb_fname_src
->base_name
, destname
));
7239 TALLOC_FREE(talloced
);
7243 status
= NT_STATUS_NO_MEMORY
;
7247 TALLOC_FREE(smb_fname_dst
->base_name
);
7248 smb_fname_dst
->base_name
= destname
;
7250 ZERO_STRUCT(smb_fname_src
->st
);
7251 if (posix_pathnames
) {
7252 SMB_VFS_LSTAT(conn
, smb_fname_src
);
7254 SMB_VFS_STAT(conn
, smb_fname_src
);
7259 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7260 create_options
|= FILE_DIRECTORY_FILE
;
7263 status
= SMB_VFS_CREATE_FILE(
7266 0, /* root_dir_fid */
7267 smb_fname_src
, /* fname */
7268 access_mask
, /* access_mask */
7269 (FILE_SHARE_READ
| /* share_access */
7271 FILE_OPEN
, /* create_disposition*/
7272 create_options
, /* create_options */
7273 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7274 0, /* oplock_request */
7276 0, /* allocation_size */
7277 0, /* private_flags */
7282 NULL
, NULL
); /* create context */
7284 if (!NT_STATUS_IS_OK(status
)) {
7285 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7286 "returned %s rename %s -> %s\n",
7288 smb_fname_str_dbg(smb_fname_src
),
7289 smb_fname_str_dbg(smb_fname_dst
)));
7293 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7295 if (!smb_fname_dst
->original_lcomp
) {
7296 status
= NT_STATUS_NO_MEMORY
;
7300 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7301 attrs
, replace_if_exists
);
7303 close_file(req
, fsp
, NORMAL_CLOSE
);
7305 if (!NT_STATUS_IS_OK(status
)) {
7306 DEBUG(3, ("rename_internals_fsp returned %s for "
7307 "rename %s -> %s\n", nt_errstr(status
),
7308 smb_fname_str_dbg(smb_fname_src
),
7309 smb_fname_str_dbg(smb_fname_dst
)));
7315 DEBUG(3,("rename_internals: doing rename on %s -> "
7316 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7317 smb_fname_str_dbg(smb_fname_src
)));
7318 TALLOC_FREE(talloced
);
7320 TALLOC_FREE(dir_hnd
);
7322 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7323 status
= map_nt_error_from_unix(errno
);
7327 TALLOC_FREE(talloced
);
7328 TALLOC_FREE(smb_fname_src_dir
);
7329 TALLOC_FREE(fname_src_dir
);
7330 TALLOC_FREE(fname_src_mask
);
7334 /****************************************************************************
7336 ****************************************************************************/
7338 void reply_mv(struct smb_request
*req
)
7340 connection_struct
*conn
= req
->conn
;
7342 char *newname
= NULL
;
7346 bool src_has_wcard
= False
;
7347 bool dest_has_wcard
= False
;
7348 TALLOC_CTX
*ctx
= talloc_tos();
7349 struct smb_filename
*smb_fname_src
= NULL
;
7350 struct smb_filename
*smb_fname_dst
= NULL
;
7351 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
) |
7352 (req
->posix_pathnames
?
7353 UCF_UNIX_NAME_LOOKUP
:
7354 UCF_COND_ALLOW_WCARD_LCOMP
);
7355 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
) |
7357 (req
->posix_pathnames
?
7359 UCF_COND_ALLOW_WCARD_LCOMP
);
7360 bool stream_rename
= false;
7362 START_PROFILE(SMBmv
);
7365 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7369 attrs
= SVAL(req
->vwv
+0, 0);
7371 p
= (const char *)req
->buf
+ 1;
7372 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7373 &status
, &src_has_wcard
);
7374 if (!NT_STATUS_IS_OK(status
)) {
7375 reply_nterror(req
, status
);
7379 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7380 &status
, &dest_has_wcard
);
7381 if (!NT_STATUS_IS_OK(status
)) {
7382 reply_nterror(req
, status
);
7386 if (!req
->posix_pathnames
) {
7387 /* The newname must begin with a ':' if the
7388 name contains a ':'. */
7389 if (strchr_m(name
, ':')) {
7390 if (newname
[0] != ':') {
7391 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7394 stream_rename
= true;
7398 status
= filename_convert(ctx
,
7406 if (!NT_STATUS_IS_OK(status
)) {
7407 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7408 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7409 ERRSRV
, ERRbadpath
);
7412 reply_nterror(req
, status
);
7416 status
= filename_convert(ctx
,
7424 if (!NT_STATUS_IS_OK(status
)) {
7425 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7426 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7427 ERRSRV
, ERRbadpath
);
7430 reply_nterror(req
, status
);
7434 if (stream_rename
) {
7435 /* smb_fname_dst->base_name must be the same as
7436 smb_fname_src->base_name. */
7437 TALLOC_FREE(smb_fname_dst
->base_name
);
7438 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7439 smb_fname_src
->base_name
);
7440 if (!smb_fname_dst
->base_name
) {
7441 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7446 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7447 smb_fname_str_dbg(smb_fname_dst
)));
7449 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7450 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7452 if (!NT_STATUS_IS_OK(status
)) {
7453 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7454 /* We have re-scheduled this call. */
7457 reply_nterror(req
, status
);
7461 reply_outbuf(req
, 0, 0);
7463 TALLOC_FREE(smb_fname_src
);
7464 TALLOC_FREE(smb_fname_dst
);
7469 /*******************************************************************
7470 Copy a file as part of a reply_copy.
7471 ******************************************************************/
7474 * TODO: check error codes on all callers
7477 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7478 connection_struct
*conn
,
7479 struct smb_filename
*smb_fname_src
,
7480 struct smb_filename
*smb_fname_dst
,
7483 bool target_is_directory
)
7485 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7487 files_struct
*fsp1
,*fsp2
;
7489 uint32_t new_create_disposition
;
7493 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7494 if (smb_fname_dst_tmp
== NULL
) {
7495 return NT_STATUS_NO_MEMORY
;
7499 * If the target is a directory, extract the last component from the
7500 * src filename and append it to the dst filename
7502 if (target_is_directory
) {
7505 /* dest/target can't be a stream if it's a directory. */
7506 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7508 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7512 p
= smb_fname_src
->base_name
;
7514 smb_fname_dst_tmp
->base_name
=
7515 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7517 if (!smb_fname_dst_tmp
->base_name
) {
7518 status
= NT_STATUS_NO_MEMORY
;
7523 status
= vfs_file_exist(conn
, smb_fname_src
);
7524 if (!NT_STATUS_IS_OK(status
)) {
7528 if (!target_is_directory
&& count
) {
7529 new_create_disposition
= FILE_OPEN
;
7531 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7534 &new_create_disposition
,
7537 status
= NT_STATUS_INVALID_PARAMETER
;
7542 /* Open the src file for reading. */
7543 status
= SMB_VFS_CREATE_FILE(
7546 0, /* root_dir_fid */
7547 smb_fname_src
, /* fname */
7548 FILE_GENERIC_READ
, /* access_mask */
7549 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7550 FILE_OPEN
, /* create_disposition*/
7551 0, /* create_options */
7552 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7553 INTERNAL_OPEN_ONLY
, /* oplock_request */
7555 0, /* allocation_size */
7556 0, /* private_flags */
7561 NULL
, NULL
); /* create context */
7563 if (!NT_STATUS_IS_OK(status
)) {
7567 dosattrs
= dos_mode(conn
, smb_fname_src
);
7569 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7570 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7573 /* Open the dst file for writing. */
7574 status
= SMB_VFS_CREATE_FILE(
7577 0, /* root_dir_fid */
7578 smb_fname_dst
, /* fname */
7579 FILE_GENERIC_WRITE
, /* access_mask */
7580 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7581 new_create_disposition
, /* create_disposition*/
7582 0, /* create_options */
7583 dosattrs
, /* file_attributes */
7584 INTERNAL_OPEN_ONLY
, /* oplock_request */
7586 0, /* allocation_size */
7587 0, /* private_flags */
7592 NULL
, NULL
); /* create context */
7594 if (!NT_STATUS_IS_OK(status
)) {
7595 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7599 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7600 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7602 DEBUG(0, ("error - vfs lseek returned error %s\n",
7604 status
= map_nt_error_from_unix(errno
);
7605 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7606 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7611 /* Do the actual copy. */
7612 if (smb_fname_src
->st
.st_ex_size
) {
7613 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7618 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7620 /* Ensure the modtime is set correctly on the destination file. */
7621 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7624 * As we are opening fsp1 read-only we only expect
7625 * an error on close on fsp2 if we are out of space.
7626 * Thus we don't look at the error return from the
7629 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7631 if (!NT_STATUS_IS_OK(status
)) {
7635 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7636 status
= NT_STATUS_DISK_FULL
;
7640 status
= NT_STATUS_OK
;
7643 TALLOC_FREE(smb_fname_dst_tmp
);
7647 /****************************************************************************
7648 Reply to a file copy.
7649 ****************************************************************************/
7651 void reply_copy(struct smb_request
*req
)
7653 connection_struct
*conn
= req
->conn
;
7654 struct smb_filename
*smb_fname_src
= NULL
;
7655 struct smb_filename
*smb_fname_src_dir
= NULL
;
7656 struct smb_filename
*smb_fname_dst
= NULL
;
7657 char *fname_src
= NULL
;
7658 char *fname_dst
= NULL
;
7659 char *fname_src_mask
= NULL
;
7660 char *fname_src_dir
= NULL
;
7663 int error
= ERRnoaccess
;
7667 bool target_is_directory
=False
;
7668 bool source_has_wild
= False
;
7669 bool dest_has_wild
= False
;
7671 uint32_t ucf_flags_src
= UCF_COND_ALLOW_WCARD_LCOMP
|
7672 ucf_flags_from_smb_request(req
);
7673 uint32_t ucf_flags_dst
= UCF_COND_ALLOW_WCARD_LCOMP
|
7674 ucf_flags_from_smb_request(req
);
7675 TALLOC_CTX
*ctx
= talloc_tos();
7677 START_PROFILE(SMBcopy
);
7680 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7684 tid2
= SVAL(req
->vwv
+0, 0);
7685 ofun
= SVAL(req
->vwv
+1, 0);
7686 flags
= SVAL(req
->vwv
+2, 0);
7688 p
= (const char *)req
->buf
;
7689 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7690 &status
, &source_has_wild
);
7691 if (!NT_STATUS_IS_OK(status
)) {
7692 reply_nterror(req
, status
);
7695 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7696 &status
, &dest_has_wild
);
7697 if (!NT_STATUS_IS_OK(status
)) {
7698 reply_nterror(req
, status
);
7702 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7704 if (tid2
!= conn
->cnum
) {
7705 /* can't currently handle inter share copies XXXX */
7706 DEBUG(3,("Rejecting inter-share copy\n"));
7707 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7711 status
= filename_convert(ctx
, conn
,
7717 if (!NT_STATUS_IS_OK(status
)) {
7718 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7719 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7720 ERRSRV
, ERRbadpath
);
7723 reply_nterror(req
, status
);
7727 status
= filename_convert(ctx
, conn
,
7733 if (!NT_STATUS_IS_OK(status
)) {
7734 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7735 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7736 ERRSRV
, ERRbadpath
);
7739 reply_nterror(req
, status
);
7743 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7745 if ((flags
&1) && target_is_directory
) {
7746 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7750 if ((flags
&2) && !target_is_directory
) {
7751 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7755 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7756 /* wants a tree copy! XXXX */
7757 DEBUG(3,("Rejecting tree copy\n"));
7758 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7762 /* Split up the directory from the filename/mask. */
7763 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7764 &fname_src_dir
, &fname_src_mask
);
7765 if (!NT_STATUS_IS_OK(status
)) {
7766 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7771 * We should only check the mangled cache
7772 * here if unix_convert failed. This means
7773 * that the path in 'mask' doesn't exist
7774 * on the file system and so we need to look
7775 * for a possible mangle. This patch from
7776 * Tine Smukavec <valentin.smukavec@hermes.si>.
7778 if (!VALID_STAT(smb_fname_src
->st
) &&
7779 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7780 char *new_mask
= NULL
;
7781 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7782 &new_mask
, conn
->params
);
7784 /* Use demangled name if one was successfully found. */
7786 TALLOC_FREE(fname_src_mask
);
7787 fname_src_mask
= new_mask
;
7791 if (!source_has_wild
) {
7794 * Only one file needs to be copied. Append the mask back onto
7797 TALLOC_FREE(smb_fname_src
->base_name
);
7798 if (ISDOT(fname_src_dir
)) {
7799 /* Ensure we use canonical names on open. */
7800 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7804 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7809 if (!smb_fname_src
->base_name
) {
7810 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7814 if (dest_has_wild
) {
7815 char *fname_dst_mod
= NULL
;
7816 if (!resolve_wildcards(smb_fname_dst
,
7817 smb_fname_src
->base_name
,
7818 smb_fname_dst
->base_name
,
7820 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7823 TALLOC_FREE(smb_fname_dst
->base_name
);
7824 smb_fname_dst
->base_name
= fname_dst_mod
;
7827 status
= check_name(conn
, smb_fname_src
);
7828 if (!NT_STATUS_IS_OK(status
)) {
7829 reply_nterror(req
, status
);
7833 status
= check_name(conn
, smb_fname_dst
);
7834 if (!NT_STATUS_IS_OK(status
)) {
7835 reply_nterror(req
, status
);
7839 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7840 ofun
, count
, target_is_directory
);
7842 if(!NT_STATUS_IS_OK(status
)) {
7843 reply_nterror(req
, status
);
7849 struct smb_Dir
*dir_hnd
= NULL
;
7850 const char *dname
= NULL
;
7851 char *talloced
= NULL
;
7855 * There is a wildcard that requires us to actually read the
7856 * src dir and copy each file matching the mask to the dst.
7857 * Right now streams won't be copied, but this could
7858 * presumably be added with a nested loop for reach dir entry.
7860 SMB_ASSERT(!smb_fname_src
->stream_name
);
7861 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7863 smb_fname_src
->stream_name
= NULL
;
7864 smb_fname_dst
->stream_name
= NULL
;
7866 if (strequal(fname_src_mask
,"????????.???")) {
7867 TALLOC_FREE(fname_src_mask
);
7868 fname_src_mask
= talloc_strdup(ctx
, "*");
7869 if (!fname_src_mask
) {
7870 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7875 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7879 smb_fname_src
->flags
);
7880 if (smb_fname_src_dir
== NULL
) {
7881 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7885 status
= check_name(conn
, smb_fname_src_dir
);
7886 if (!NT_STATUS_IS_OK(status
)) {
7887 reply_nterror(req
, status
);
7891 dir_hnd
= OpenDir(ctx
,
7896 if (dir_hnd
== NULL
) {
7897 status
= map_nt_error_from_unix(errno
);
7898 reply_nterror(req
, status
);
7904 /* Iterate over the src dir copying each entry to the dst. */
7905 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7906 &smb_fname_src
->st
, &talloced
))) {
7907 char *destname
= NULL
;
7909 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7910 TALLOC_FREE(talloced
);
7914 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7915 &smb_fname_src
->st
, false)) {
7916 TALLOC_FREE(talloced
);
7920 if(!mask_match(dname
, fname_src_mask
,
7921 conn
->case_sensitive
)) {
7922 TALLOC_FREE(talloced
);
7926 error
= ERRnoaccess
;
7928 /* Get the src smb_fname struct setup. */
7929 TALLOC_FREE(smb_fname_src
->base_name
);
7930 if (ISDOT(fname_src_dir
)) {
7931 /* Ensure we use canonical names on open. */
7932 smb_fname_src
->base_name
=
7933 talloc_asprintf(smb_fname_src
, "%s",
7936 smb_fname_src
->base_name
=
7937 talloc_asprintf(smb_fname_src
, "%s/%s",
7938 fname_src_dir
, dname
);
7941 if (!smb_fname_src
->base_name
) {
7942 TALLOC_FREE(dir_hnd
);
7943 TALLOC_FREE(talloced
);
7944 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7948 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7949 smb_fname_dst
->base_name
,
7951 TALLOC_FREE(talloced
);
7955 TALLOC_FREE(dir_hnd
);
7956 TALLOC_FREE(talloced
);
7957 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7961 TALLOC_FREE(smb_fname_dst
->base_name
);
7962 smb_fname_dst
->base_name
= destname
;
7964 status
= check_name(conn
, smb_fname_src
);
7965 if (!NT_STATUS_IS_OK(status
)) {
7966 TALLOC_FREE(dir_hnd
);
7967 TALLOC_FREE(talloced
);
7968 reply_nterror(req
, status
);
7972 status
= check_name(conn
, smb_fname_dst
);
7973 if (!NT_STATUS_IS_OK(status
)) {
7974 TALLOC_FREE(dir_hnd
);
7975 TALLOC_FREE(talloced
);
7976 reply_nterror(req
, status
);
7980 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7981 smb_fname_src
->base_name
,
7982 smb_fname_dst
->base_name
));
7984 status
= copy_file(ctx
, conn
, smb_fname_src
,
7985 smb_fname_dst
, ofun
, count
,
7986 target_is_directory
);
7987 if (NT_STATUS_IS_OK(status
)) {
7991 TALLOC_FREE(talloced
);
7993 TALLOC_FREE(dir_hnd
);
7997 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
8001 reply_outbuf(req
, 1, 0);
8002 SSVAL(req
->outbuf
,smb_vwv0
,count
);
8004 TALLOC_FREE(smb_fname_src
);
8005 TALLOC_FREE(smb_fname_src_dir
);
8006 TALLOC_FREE(smb_fname_dst
);
8007 TALLOC_FREE(fname_src
);
8008 TALLOC_FREE(fname_dst
);
8009 TALLOC_FREE(fname_src_mask
);
8010 TALLOC_FREE(fname_src_dir
);
8012 END_PROFILE(SMBcopy
);
8017 #define DBGC_CLASS DBGC_LOCKING
8019 /****************************************************************************
8020 Get a lock pid, dealing with large count requests.
8021 ****************************************************************************/
8023 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
8024 bool large_file_format
)
8026 if(!large_file_format
)
8027 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
8029 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
8032 /****************************************************************************
8033 Get a lock count, dealing with large count requests.
8034 ****************************************************************************/
8036 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
8037 bool large_file_format
)
8041 if(!large_file_format
) {
8042 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
8045 * No BVAL, this is reversed!
8047 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
8048 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
8054 /****************************************************************************
8055 Get a lock offset, dealing with large offset requests.
8056 ****************************************************************************/
8058 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
8059 bool large_file_format
)
8061 uint64_t offset
= 0;
8063 if(!large_file_format
) {
8064 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
8067 * No BVAL, this is reversed!
8069 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
8070 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
8076 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
8081 struct smbd_lock_element
*locks
,
8084 connection_struct
*conn
= req
->conn
;
8086 NTSTATUS status
= NT_STATUS_OK
;
8090 /* Setup the timeout in seconds. */
8092 if (!lp_blocking_locks(SNUM(conn
))) {
8096 for(i
= 0; i
< (int)num_locks
; i
++) {
8097 struct smbd_lock_element
*e
= &locks
[i
];
8099 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8100 "%llu, file %s timeout = %d\n",
8103 (unsigned long long)e
->smblctx
,
8107 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8108 struct blocking_lock_record
*blr
= NULL
;
8110 if (num_locks
> 1) {
8112 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8113 * if the lock vector contains one entry. When given multiple cancel
8114 * requests in a single PDU we expect the server to return an
8115 * error. Windows servers seem to accept the request but only
8116 * cancel the first lock.
8117 * JRA - Do what Windows does (tm) :-).
8121 /* MS-CIFS (2.2.4.32.1) behavior. */
8122 return NT_STATUS_DOS(ERRDOS
,
8123 ERRcancelviolation
);
8125 /* Windows behavior. */
8127 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8128 "cancel request\n"));
8134 if (lp_blocking_locks(SNUM(conn
))) {
8136 /* Schedule a message to ourselves to
8137 remove the blocking lock record and
8138 return the right error. */
8140 blr
= blocking_lock_cancel_smb1(fsp
,
8146 NT_STATUS_FILE_LOCK_CONFLICT
);
8148 return NT_STATUS_DOS(
8150 ERRcancelviolation
);
8153 /* Remove a matching pending lock. */
8154 status
= do_lock_cancel(fsp
,
8160 bool blocking_lock
= timeout
? true : false;
8161 bool defer_lock
= false;
8162 struct byte_range_lock
*br_lck
;
8163 uint64_t block_smblctx
;
8165 br_lck
= do_lock(req
->sconn
->msg_ctx
,
8176 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
8177 /* Windows internal resolution for blocking locks seems
8178 to be about 200ms... Don't wait for less than that. JRA. */
8179 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
8180 timeout
= lp_lock_spin_time();
8185 /* If a lock sent with timeout of zero would fail, and
8186 * this lock has been requested multiple times,
8187 * according to brl_lock_failed() we convert this
8188 * request to a blocking lock with a timeout of between
8189 * 150 - 300 milliseconds.
8191 * If lp_lock_spin_time() has been set to 0, we skip
8192 * this blocking retry and fail immediately.
8194 * Replacement for do_lock_spin(). JRA. */
8196 if (!req
->sconn
->using_smb2
&&
8197 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
8198 lp_lock_spin_time() && !blocking_lock
&&
8199 NT_STATUS_EQUAL((status
),
8200 NT_STATUS_FILE_LOCK_CONFLICT
))
8203 timeout
= lp_lock_spin_time();
8206 if (br_lck
&& defer_lock
) {
8208 * A blocking lock was requested. Package up
8209 * this smb into a queued request and push it
8210 * onto the blocking lock queue.
8212 if(push_blocking_lock_request(br_lck
,
8223 TALLOC_FREE(br_lck
);
8225 return NT_STATUS_OK
;
8229 TALLOC_FREE(br_lck
);
8232 if (!NT_STATUS_IS_OK(status
)) {
8237 /* If any of the above locks failed, then we must unlock
8238 all of the previous locks (X/Open spec). */
8240 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
8242 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8243 i
= -1; /* we want to skip the for loop */
8247 * Ensure we don't do a remove on the lock that just failed,
8248 * as under POSIX rules, if we have a lock already there, we
8249 * will delete it (and we shouldn't) .....
8251 for(i
--; i
>= 0; i
--) {
8252 struct smbd_lock_element
*e
= &locks
[i
];
8254 do_unlock(req
->sconn
->msg_ctx
,
8264 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8265 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
8267 return NT_STATUS_OK
;
8270 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
8272 uint16_t num_ulocks
,
8273 struct smbd_lock_element
*ulocks
)
8277 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8278 struct smbd_lock_element
*e
= &ulocks
[i
];
8281 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8282 "pid %u, file %s\n", __func__
,
8285 (unsigned int)e
->smblctx
,
8288 if (e
->brltype
!= UNLOCK_LOCK
) {
8289 /* this can only happen with SMB2 */
8290 return NT_STATUS_INVALID_PARAMETER
;
8293 status
= do_unlock(req
->sconn
->msg_ctx
,
8300 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
8301 nt_errstr(status
)));
8303 if (!NT_STATUS_IS_OK(status
)) {
8308 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
8311 return NT_STATUS_OK
;
8314 /****************************************************************************
8315 Reply to a lockingX request.
8316 ****************************************************************************/
8318 void reply_lockingX(struct smb_request
*req
)
8320 connection_struct
*conn
= req
->conn
;
8322 unsigned char locktype
;
8323 unsigned char oplocklevel
;
8324 uint16_t num_ulocks
;
8326 int32_t lock_timeout
;
8328 const uint8_t *data
;
8329 bool large_file_format
;
8330 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8331 struct smbd_lock_element
*ulocks
;
8332 struct smbd_lock_element
*locks
;
8335 START_PROFILE(SMBlockingX
);
8338 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8339 END_PROFILE(SMBlockingX
);
8343 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8344 locktype
= CVAL(req
->vwv
+3, 0);
8345 oplocklevel
= CVAL(req
->vwv
+3, 1);
8346 num_ulocks
= SVAL(req
->vwv
+6, 0);
8347 num_locks
= SVAL(req
->vwv
+7, 0);
8348 lock_timeout
= IVAL(req
->vwv
+4, 0);
8349 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8351 if (!check_fsp(conn
, req
, fsp
)) {
8352 END_PROFILE(SMBlockingX
);
8358 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8359 /* we don't support these - and CANCEL_LOCK makes w2k
8360 and XP reboot so I don't really want to be
8361 compatible! (tridge) */
8362 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8363 END_PROFILE(SMBlockingX
);
8367 /* Check if this is an oplock break on a file
8368 we have granted an oplock on.
8370 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8371 /* Client can insist on breaking to none. */
8372 bool break_to_none
= (oplocklevel
== 0);
8375 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8376 "for %s\n", (unsigned int)oplocklevel
,
8377 fsp_fnum_dbg(fsp
)));
8380 * Make sure we have granted an exclusive or batch oplock on
8384 if (fsp
->oplock_type
== 0) {
8386 /* The Samba4 nbench simulator doesn't understand
8387 the difference between break to level2 and break
8388 to none from level2 - it sends oplock break
8389 replies in both cases. Don't keep logging an error
8390 message here - just ignore it. JRA. */
8392 DEBUG(5,("reply_lockingX: Error : oplock break from "
8393 "client for %s (oplock=%d) and no "
8394 "oplock granted on this file (%s).\n",
8395 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8398 /* if this is a pure oplock break request then don't
8400 if (num_locks
== 0 && num_ulocks
== 0) {
8401 END_PROFILE(SMBlockingX
);
8404 END_PROFILE(SMBlockingX
);
8405 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8410 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8412 result
= remove_oplock(fsp
);
8414 result
= downgrade_oplock(fsp
);
8418 DEBUG(0, ("reply_lockingX: error in removing "
8419 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8420 /* Hmmm. Is this panic justified? */
8421 smb_panic("internal tdb error");
8424 /* if this is a pure oplock break request then don't send a
8426 if (num_locks
== 0 && num_ulocks
== 0) {
8427 /* Sanity check - ensure a pure oplock break is not a
8429 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8430 DEBUG(0,("reply_lockingX: Error : pure oplock "
8431 "break is a chained %d request !\n",
8432 (unsigned int)CVAL(req
->vwv
+0, 0)));
8434 END_PROFILE(SMBlockingX
);
8440 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8441 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8442 END_PROFILE(SMBlockingX
);
8446 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8447 if (ulocks
== NULL
) {
8448 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8449 END_PROFILE(SMBlockingX
);
8453 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8454 if (locks
== NULL
) {
8455 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8456 END_PROFILE(SMBlockingX
);
8460 /* Data now points at the beginning of the list
8461 of smb_unlkrng structs */
8462 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8463 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8464 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8465 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8466 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8469 /* Now do any requested locks */
8470 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8472 /* Data now points at the beginning of the list
8473 of smb_lkrng structs */
8475 for(i
= 0; i
< (int)num_locks
; i
++) {
8476 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8477 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8478 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8480 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8481 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8482 locks
[i
].brltype
= PENDING_READ_LOCK
;
8484 locks
[i
].brltype
= READ_LOCK
;
8487 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8488 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8490 locks
[i
].brltype
= WRITE_LOCK
;
8495 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8496 if (!NT_STATUS_IS_OK(status
)) {
8497 END_PROFILE(SMBlockingX
);
8498 reply_nterror(req
, status
);
8502 status
= smbd_do_locking(req
, fsp
,
8503 locktype
, lock_timeout
,
8506 if (!NT_STATUS_IS_OK(status
)) {
8507 END_PROFILE(SMBlockingX
);
8508 reply_nterror(req
, status
);
8512 END_PROFILE(SMBlockingX
);
8516 reply_outbuf(req
, 2, 0);
8517 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8518 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8520 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8521 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8523 END_PROFILE(SMBlockingX
);
8527 #define DBGC_CLASS DBGC_ALL
8529 /****************************************************************************
8530 Reply to a SMBreadbmpx (read block multiplex) request.
8531 Always reply with an error, if someone has a platform really needs this,
8532 please contact vl@samba.org
8533 ****************************************************************************/
8535 void reply_readbmpx(struct smb_request
*req
)
8537 START_PROFILE(SMBreadBmpx
);
8538 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8539 END_PROFILE(SMBreadBmpx
);
8543 /****************************************************************************
8544 Reply to a SMBreadbs (read block multiplex secondary) request.
8545 Always reply with an error, if someone has a platform really needs this,
8546 please contact vl@samba.org
8547 ****************************************************************************/
8549 void reply_readbs(struct smb_request
*req
)
8551 START_PROFILE(SMBreadBs
);
8552 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8553 END_PROFILE(SMBreadBs
);
8557 /****************************************************************************
8558 Reply to a SMBsetattrE.
8559 ****************************************************************************/
8561 void reply_setattrE(struct smb_request
*req
)
8563 connection_struct
*conn
= req
->conn
;
8564 struct smb_file_time ft
;
8568 START_PROFILE(SMBsetattrE
);
8572 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8576 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8578 if(!fsp
|| (fsp
->conn
!= conn
)) {
8579 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8584 * Convert the DOS times into unix times.
8587 ft
.atime
= convert_time_t_to_timespec(
8588 srv_make_unix_date2(req
->vwv
+3));
8589 ft
.mtime
= convert_time_t_to_timespec(
8590 srv_make_unix_date2(req
->vwv
+5));
8591 ft
.create_time
= convert_time_t_to_timespec(
8592 srv_make_unix_date2(req
->vwv
+1));
8594 reply_outbuf(req
, 0, 0);
8597 * Patch from Ray Frush <frush@engr.colostate.edu>
8598 * Sometimes times are sent as zero - ignore them.
8601 /* Ensure we have a valid stat struct for the source. */
8602 status
= vfs_stat_fsp(fsp
);
8603 if (!NT_STATUS_IS_OK(status
)) {
8604 reply_nterror(req
, status
);
8608 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8609 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8613 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8614 if (!NT_STATUS_IS_OK(status
)) {
8615 reply_nterror(req
, status
);
8619 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8622 (unsigned int)ft
.atime
.tv_sec
,
8623 (unsigned int)ft
.mtime
.tv_sec
,
8624 (unsigned int)ft
.create_time
.tv_sec
8627 END_PROFILE(SMBsetattrE
);
8632 /* Back from the dead for OS/2..... JRA. */
8634 /****************************************************************************
8635 Reply to a SMBwritebmpx (write block multiplex primary) request.
8636 Always reply with an error, if someone has a platform really needs this,
8637 please contact vl@samba.org
8638 ****************************************************************************/
8640 void reply_writebmpx(struct smb_request
*req
)
8642 START_PROFILE(SMBwriteBmpx
);
8643 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8644 END_PROFILE(SMBwriteBmpx
);
8648 /****************************************************************************
8649 Reply to a SMBwritebs (write block multiplex secondary) request.
8650 Always reply with an error, if someone has a platform really needs this,
8651 please contact vl@samba.org
8652 ****************************************************************************/
8654 void reply_writebs(struct smb_request
*req
)
8656 START_PROFILE(SMBwriteBs
);
8657 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8658 END_PROFILE(SMBwriteBs
);
8662 /****************************************************************************
8663 Reply to a SMBgetattrE.
8664 ****************************************************************************/
8666 void reply_getattrE(struct smb_request
*req
)
8668 connection_struct
*conn
= req
->conn
;
8671 struct timespec create_ts
;
8673 START_PROFILE(SMBgetattrE
);
8676 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8677 END_PROFILE(SMBgetattrE
);
8681 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8683 if(!fsp
|| (fsp
->conn
!= conn
)) {
8684 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8685 END_PROFILE(SMBgetattrE
);
8689 /* Do an fstat on this file */
8691 reply_nterror(req
, map_nt_error_from_unix(errno
));
8692 END_PROFILE(SMBgetattrE
);
8696 mode
= dos_mode(conn
, fsp
->fsp_name
);
8699 * Convert the times into dos times. Set create
8700 * date to be last modify date as UNIX doesn't save
8704 reply_outbuf(req
, 11, 0);
8706 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8707 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8708 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8709 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8710 /* Should we check pending modtime here ? JRA */
8711 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8712 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8714 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8715 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8716 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8718 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8719 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8720 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8722 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8724 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8726 END_PROFILE(SMBgetattrE
);