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 "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.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 session
->global
->signing_key
.length
> 0)
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
.data
,
1025 MIN(x
->global
->signing_key
.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
) {
1041 smb_key_derivation(x
->global
->application_key
.data
,
1042 x
->global
->application_key
.length
,
1043 x
->global
->application_key
.data
);
1044 optional_support
|= SMB_EXTENDED_SIGNATURES
;
1048 * Place the application key into the session_info
1050 data_blob_clear_free(&session_info
->session_key
);
1051 session_info
->session_key
= data_blob_dup_talloc(session_info
,
1052 x
->global
->application_key
);
1053 if (session_info
->session_key
.data
== NULL
) {
1054 data_blob_clear_free(&x
->global
->application_key
);
1055 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1056 END_PROFILE(SMBtconX
);
1059 session_key_updated
= true;
1062 conn
= make_connection(req
, now
, service
, client_devicetype
,
1063 req
->vuid
, &nt_status
);
1067 if (session_key_updated
) {
1068 struct smbXsrv_session
*x
= session
;
1069 struct auth_session_info
*session_info
=
1070 session
->global
->auth_session_info
;
1071 data_blob_clear_free(&x
->global
->application_key
);
1072 data_blob_clear_free(&session_info
->session_key
);
1074 reply_nterror(req
, nt_status
);
1075 END_PROFILE(SMBtconX
);
1080 server_devicetype
= "IPC";
1081 else if ( IS_PRINT(conn
) )
1082 server_devicetype
= "LPT1:";
1084 server_devicetype
= "A:";
1086 if (get_Protocol() < PROTOCOL_NT1
) {
1087 reply_outbuf(req
, 2, 0);
1088 if (message_push_string(&req
->outbuf
, server_devicetype
,
1089 STR_TERMINATE
|STR_ASCII
) == -1) {
1090 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1091 END_PROFILE(SMBtconX
);
1095 /* NT sets the fstype of IPC$ to the null string */
1096 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
1098 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
1099 /* Return permissions. */
1103 reply_outbuf(req
, 7, 0);
1106 perm1
= FILE_ALL_ACCESS
;
1107 perm2
= FILE_ALL_ACCESS
;
1109 perm1
= conn
->share_access
;
1112 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
1113 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
1115 reply_outbuf(req
, 3, 0);
1118 if ((message_push_string(&req
->outbuf
, server_devicetype
,
1119 STR_TERMINATE
|STR_ASCII
) == -1)
1120 || (message_push_string(&req
->outbuf
, fstype
,
1121 STR_TERMINATE
) == -1)) {
1122 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1123 END_PROFILE(SMBtconX
);
1127 /* what does setting this bit do? It is set by NT4 and
1128 may affect the ability to autorun mounted cdroms */
1129 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1131 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1133 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1134 DEBUG(2,("Serving %s as a Dfs root\n",
1135 lp_servicename(ctx
, SNUM(conn
)) ));
1136 optional_support
|= SMB_SHARE_IN_DFS
;
1139 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1142 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1143 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1145 DEBUG(3,("tconX service=%s \n",
1148 /* set the incoming and outgoing tid to the just created one */
1149 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1150 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1152 END_PROFILE(SMBtconX
);
1154 req
->tid
= conn
->cnum
;
1157 /****************************************************************************
1158 Reply to an unknown type.
1159 ****************************************************************************/
1161 void reply_unknown_new(struct smb_request
*req
, uint8_t type
)
1163 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1164 smb_fn_name(type
), type
, type
));
1165 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1169 /****************************************************************************
1171 conn POINTER CAN BE NULL HERE !
1172 ****************************************************************************/
1174 void reply_ioctl(struct smb_request
*req
)
1176 connection_struct
*conn
= req
->conn
;
1179 uint32_t ioctl_code
;
1183 START_PROFILE(SMBioctl
);
1186 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1187 END_PROFILE(SMBioctl
);
1191 device
= SVAL(req
->vwv
+1, 0);
1192 function
= SVAL(req
->vwv
+2, 0);
1193 ioctl_code
= (device
<< 16) + function
;
1195 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1197 switch (ioctl_code
) {
1198 case IOCTL_QUERY_JOB_INFO
:
1202 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1203 END_PROFILE(SMBioctl
);
1207 reply_outbuf(req
, 8, replysize
+1);
1208 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1209 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1210 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1211 p
= smb_buf(req
->outbuf
);
1212 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1213 p
+= 1; /* Allow for alignment */
1215 switch (ioctl_code
) {
1216 case IOCTL_QUERY_JOB_INFO
:
1220 files_struct
*fsp
= file_fsp(
1221 req
, SVAL(req
->vwv
+0, 0));
1223 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1224 END_PROFILE(SMBioctl
);
1228 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1230 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1231 lp_netbios_name(), 15,
1232 STR_TERMINATE
|STR_ASCII
, &len
);
1233 if (!NT_STATUS_IS_OK(status
)) {
1234 reply_nterror(req
, status
);
1235 END_PROFILE(SMBioctl
);
1239 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
,
1241 lp_servicename(talloc_tos(),
1243 13, STR_TERMINATE
|STR_ASCII
, &len
);
1244 if (!NT_STATUS_IS_OK(status
)) {
1245 reply_nterror(req
, status
);
1246 END_PROFILE(SMBioctl
);
1250 memset(p
+18, 0, 13);
1256 END_PROFILE(SMBioctl
);
1260 /****************************************************************************
1261 Strange checkpath NTSTATUS mapping.
1262 ****************************************************************************/
1264 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1266 /* Strange DOS error code semantics only for checkpath... */
1267 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1268 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1269 /* We need to map to ERRbadpath */
1270 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1276 /****************************************************************************
1277 Reply to a checkpath.
1278 ****************************************************************************/
1280 void reply_checkpath(struct smb_request
*req
)
1282 connection_struct
*conn
= req
->conn
;
1283 struct smb_filename
*smb_fname
= NULL
;
1286 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1287 TALLOC_CTX
*ctx
= talloc_tos();
1289 START_PROFILE(SMBcheckpath
);
1291 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1292 STR_TERMINATE
, &status
);
1294 if (!NT_STATUS_IS_OK(status
)) {
1295 status
= map_checkpath_error(req
->flags2
, status
);
1296 reply_nterror(req
, status
);
1297 END_PROFILE(SMBcheckpath
);
1301 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1303 status
= filename_convert(ctx
,
1310 if (!NT_STATUS_IS_OK(status
)) {
1311 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1312 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1313 ERRSRV
, ERRbadpath
);
1314 END_PROFILE(SMBcheckpath
);
1320 if (!VALID_STAT(smb_fname
->st
) &&
1321 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1322 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1323 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1324 status
= map_nt_error_from_unix(errno
);
1328 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1329 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1330 ERRDOS
, ERRbadpath
);
1334 reply_outbuf(req
, 0, 0);
1337 /* We special case this - as when a Windows machine
1338 is parsing a path is steps through the components
1339 one at a time - if a component fails it expects
1340 ERRbadpath, not ERRbadfile.
1342 status
= map_checkpath_error(req
->flags2
, status
);
1343 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1345 * Windows returns different error codes if
1346 * the parent directory is valid but not the
1347 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1348 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1349 * if the path is invalid.
1351 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1352 ERRDOS
, ERRbadpath
);
1356 reply_nterror(req
, status
);
1359 TALLOC_FREE(smb_fname
);
1360 END_PROFILE(SMBcheckpath
);
1364 /****************************************************************************
1366 ****************************************************************************/
1368 void reply_getatr(struct smb_request
*req
)
1370 connection_struct
*conn
= req
->conn
;
1371 struct smb_filename
*smb_fname
= NULL
;
1378 TALLOC_CTX
*ctx
= talloc_tos();
1379 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1381 START_PROFILE(SMBgetatr
);
1383 p
= (const char *)req
->buf
+ 1;
1384 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1385 if (!NT_STATUS_IS_OK(status
)) {
1386 reply_nterror(req
, status
);
1390 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1391 under WfWg - weird! */
1392 if (*fname
== '\0') {
1393 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1394 if (!CAN_WRITE(conn
)) {
1395 mode
|= FILE_ATTRIBUTE_READONLY
;
1400 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1401 status
= filename_convert(ctx
,
1407 if (!NT_STATUS_IS_OK(status
)) {
1408 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1409 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1410 ERRSRV
, ERRbadpath
);
1413 reply_nterror(req
, status
);
1416 if (!VALID_STAT(smb_fname
->st
) &&
1417 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1418 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1419 smb_fname_str_dbg(smb_fname
),
1421 reply_nterror(req
, map_nt_error_from_unix(errno
));
1425 mode
= dos_mode(conn
, smb_fname
);
1426 size
= smb_fname
->st
.st_ex_size
;
1428 if (ask_sharemode
) {
1429 struct timespec write_time_ts
;
1430 struct file_id fileid
;
1432 ZERO_STRUCT(write_time_ts
);
1433 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1434 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1435 if (!null_timespec(write_time_ts
)) {
1436 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1440 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1441 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1446 reply_outbuf(req
, 10, 0);
1448 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1449 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1450 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1452 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1454 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
1456 if (get_Protocol() >= PROTOCOL_NT1
) {
1457 SSVAL(req
->outbuf
, smb_flg2
,
1458 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1461 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1462 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1465 TALLOC_FREE(smb_fname
);
1467 END_PROFILE(SMBgetatr
);
1471 /****************************************************************************
1473 ****************************************************************************/
1475 void reply_setatr(struct smb_request
*req
)
1477 struct smb_file_time ft
;
1478 connection_struct
*conn
= req
->conn
;
1479 struct smb_filename
*smb_fname
= NULL
;
1485 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1486 TALLOC_CTX
*ctx
= talloc_tos();
1488 START_PROFILE(SMBsetatr
);
1493 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1497 p
= (const char *)req
->buf
+ 1;
1498 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1499 if (!NT_STATUS_IS_OK(status
)) {
1500 reply_nterror(req
, status
);
1504 status
= filename_convert(ctx
,
1510 if (!NT_STATUS_IS_OK(status
)) {
1511 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1512 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1513 ERRSRV
, ERRbadpath
);
1516 reply_nterror(req
, status
);
1520 if (smb_fname
->base_name
[0] == '.' &&
1521 smb_fname
->base_name
[1] == '\0') {
1523 * Not sure here is the right place to catch this
1524 * condition. Might be moved to somewhere else later -- vl
1526 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1530 mode
= SVAL(req
->vwv
+0, 0);
1531 mtime
= srv_make_unix_date3(req
->vwv
+1);
1533 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1534 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1535 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1537 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1539 status
= check_access(conn
, NULL
, smb_fname
,
1540 FILE_WRITE_ATTRIBUTES
);
1541 if (!NT_STATUS_IS_OK(status
)) {
1542 reply_nterror(req
, status
);
1546 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1548 reply_nterror(req
, map_nt_error_from_unix(errno
));
1553 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1554 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1555 if (!NT_STATUS_IS_OK(status
)) {
1556 reply_nterror(req
, status
);
1560 reply_outbuf(req
, 0, 0);
1562 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1565 TALLOC_FREE(smb_fname
);
1566 END_PROFILE(SMBsetatr
);
1570 /****************************************************************************
1572 ****************************************************************************/
1574 void reply_dskattr(struct smb_request
*req
)
1576 connection_struct
*conn
= req
->conn
;
1578 uint64_t dfree
,dsize
,bsize
;
1579 struct smb_filename smb_fname
;
1580 START_PROFILE(SMBdskattr
);
1582 ZERO_STRUCT(smb_fname
);
1583 smb_fname
.base_name
= discard_const_p(char, ".");
1585 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
1586 reply_nterror(req
, map_nt_error_from_unix(errno
));
1587 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
1588 END_PROFILE(SMBdskattr
);
1592 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
1593 if (ret
== (uint64_t)-1) {
1594 reply_nterror(req
, map_nt_error_from_unix(errno
));
1595 END_PROFILE(SMBdskattr
);
1600 * Force max to fit in 16 bit fields.
1602 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1606 if (bsize
> (WORDMAX
*512)) {
1607 bsize
= (WORDMAX
*512);
1608 if (dsize
> WORDMAX
)
1610 if (dfree
> WORDMAX
)
1616 reply_outbuf(req
, 5, 0);
1618 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1619 double total_space
, free_space
;
1620 /* we need to scale this to a number that DOS6 can handle. We
1621 use floating point so we can handle large drives on systems
1622 that don't have 64 bit integers
1624 we end up displaying a maximum of 2G to DOS systems
1626 total_space
= dsize
* (double)bsize
;
1627 free_space
= dfree
* (double)bsize
;
1629 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1630 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1632 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1633 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1635 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1636 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1637 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1638 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1640 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1641 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1642 SSVAL(req
->outbuf
,smb_vwv2
,512);
1643 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1646 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1648 END_PROFILE(SMBdskattr
);
1653 * Utility function to split the filename from the directory.
1655 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1656 char **fname_dir_out
,
1657 char **fname_mask_out
)
1659 const char *p
= NULL
;
1660 char *fname_dir
= NULL
;
1661 char *fname_mask
= NULL
;
1663 p
= strrchr_m(fname_in
, '/');
1665 fname_dir
= talloc_strdup(ctx
, ".");
1666 fname_mask
= talloc_strdup(ctx
, fname_in
);
1668 fname_dir
= talloc_strndup(ctx
, fname_in
,
1669 PTR_DIFF(p
, fname_in
));
1670 fname_mask
= talloc_strdup(ctx
, p
+1);
1673 if (!fname_dir
|| !fname_mask
) {
1674 TALLOC_FREE(fname_dir
);
1675 TALLOC_FREE(fname_mask
);
1676 return NT_STATUS_NO_MEMORY
;
1679 *fname_dir_out
= fname_dir
;
1680 *fname_mask_out
= fname_mask
;
1681 return NT_STATUS_OK
;
1684 /****************************************************************************
1686 ****************************************************************************/
1688 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1698 char *mask2
= talloc_strdup(ctx
, mask
);
1704 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1708 memset(buf
+1,' ',11);
1709 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1711 push_ascii(buf
+1,mask2
,8, 0);
1712 push_ascii(buf
+9,p
+1,3, 0);
1715 push_ascii(buf
+1,mask2
,11, 0);
1718 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1720 srv_put_dos_date(buf
,22,date
);
1721 SSVAL(buf
,26,size
& 0xFFFF);
1722 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1723 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1724 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1725 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1726 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1730 /****************************************************************************
1732 Can be called from SMBsearch, SMBffirst or SMBfunique.
1733 ****************************************************************************/
1735 void reply_search(struct smb_request
*req
)
1737 connection_struct
*conn
= req
->conn
;
1740 char *directory
= NULL
;
1741 struct smb_filename
*smb_fname
= NULL
;
1745 struct timespec date
;
1747 unsigned int numentries
= 0;
1748 unsigned int maxentries
= 0;
1749 bool finished
= False
;
1754 bool check_descend
= False
;
1755 bool expect_close
= False
;
1757 bool mask_contains_wcard
= False
;
1758 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1759 TALLOC_CTX
*ctx
= talloc_tos();
1760 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1761 struct dptr_struct
*dirptr
= NULL
;
1762 struct smbXsrv_connection
*xconn
= req
->xconn
;
1763 struct smbd_server_connection
*sconn
= req
->sconn
;
1765 START_PROFILE(SMBsearch
);
1768 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1772 if (req
->posix_pathnames
) {
1773 reply_unknown_new(req
, req
->cmd
);
1777 /* If we were called as SMBffirst then we must expect close. */
1778 if(req
->cmd
== SMBffirst
) {
1779 expect_close
= True
;
1782 reply_outbuf(req
, 1, 3);
1783 maxentries
= SVAL(req
->vwv
+0, 0);
1784 dirtype
= SVAL(req
->vwv
+1, 0);
1785 p
= (const char *)req
->buf
+ 1;
1786 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1787 &nt_status
, &mask_contains_wcard
);
1788 if (!NT_STATUS_IS_OK(nt_status
)) {
1789 reply_nterror(req
, nt_status
);
1794 status_len
= SVAL(p
, 0);
1797 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1799 if (status_len
== 0) {
1800 struct smb_filename
*smb_dname
= NULL
;
1801 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
1802 ucf_flags_from_smb_request(req
);
1803 nt_status
= filename_convert(ctx
, conn
,
1806 &mask_contains_wcard
,
1808 if (!NT_STATUS_IS_OK(nt_status
)) {
1809 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1810 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1811 ERRSRV
, ERRbadpath
);
1814 reply_nterror(req
, nt_status
);
1818 directory
= smb_fname
->base_name
;
1820 p
= strrchr_m(directory
,'/');
1821 if ((p
!= NULL
) && (*directory
!= '/')) {
1822 mask
= talloc_strdup(ctx
, p
+ 1);
1823 directory
= talloc_strndup(ctx
, directory
,
1824 PTR_DIFF(p
, directory
));
1826 mask
= talloc_strdup(ctx
, directory
);
1827 directory
= talloc_strdup(ctx
,".");
1831 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1835 memset((char *)status
,'\0',21);
1836 SCVAL(status
,0,(dirtype
& 0x1F));
1838 smb_dname
= synthetic_smb_fname(talloc_tos(),
1843 if (smb_dname
== NULL
) {
1844 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1848 nt_status
= dptr_create(conn
,
1856 mask_contains_wcard
,
1860 TALLOC_FREE(smb_dname
);
1862 if (!NT_STATUS_IS_OK(nt_status
)) {
1863 reply_nterror(req
, nt_status
);
1866 dptr_num
= dptr_dnum(dirptr
);
1869 const char *dirpath
;
1871 memcpy(status
,p
,21);
1872 status_dirtype
= CVAL(status
,0) & 0x1F;
1873 if (status_dirtype
!= (dirtype
& 0x1F)) {
1874 dirtype
= status_dirtype
;
1877 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1881 dirpath
= dptr_path(sconn
, dptr_num
);
1882 directory
= talloc_strdup(ctx
, dirpath
);
1884 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1888 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1893 * For a 'continue' search we have no string. So
1894 * check from the initial saved string.
1896 if (!req
->posix_pathnames
) {
1897 mask_contains_wcard
= ms_has_wild(mask
);
1899 dirtype
= dptr_attr(sconn
, dptr_num
);
1902 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1904 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1905 char buf
[DIR_STRUCT_SIZE
];
1906 memcpy(buf
,status
,21);
1907 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1908 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1909 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1912 dptr_fill(sconn
, buf
+12,dptr_num
);
1913 if (dptr_zero(buf
+12) && (status_len
==0)) {
1918 if (message_push_blob(&req
->outbuf
,
1919 data_blob_const(buf
, sizeof(buf
)))
1921 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1926 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1927 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1929 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1931 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1932 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
1933 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
1934 check_descend
= True
;
1937 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1938 finished
= !get_dir_entry(ctx
,
1949 char buf
[DIR_STRUCT_SIZE
];
1950 memcpy(buf
,status
,21);
1951 if (!make_dir_struct(ctx
,
1957 convert_timespec_to_time_t(date
),
1958 !allow_long_path_components
)) {
1959 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1962 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1965 if (message_push_blob(&req
->outbuf
,
1966 data_blob_const(buf
, sizeof(buf
)))
1968 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1978 /* If we were called as SMBffirst with smb_search_id == NULL
1979 and no entries were found then return error and close dirptr
1982 if (numentries
== 0) {
1983 dptr_close(sconn
, &dptr_num
);
1984 } else if(expect_close
&& status_len
== 0) {
1985 /* Close the dptr - we know it's gone */
1986 dptr_close(sconn
, &dptr_num
);
1989 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1990 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1991 dptr_close(sconn
, &dptr_num
);
1994 if ((numentries
== 0) && !mask_contains_wcard
) {
1995 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1999 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
2000 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
2001 SCVAL(smb_buf(req
->outbuf
),0,5);
2002 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
2004 /* The replies here are never long name. */
2005 SSVAL(req
->outbuf
, smb_flg2
,
2006 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
2007 if (!allow_long_path_components
) {
2008 SSVAL(req
->outbuf
, smb_flg2
,
2009 SVAL(req
->outbuf
, smb_flg2
)
2010 & (~FLAGS2_LONG_PATH_COMPONENTS
));
2013 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2014 SSVAL(req
->outbuf
, smb_flg2
,
2015 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
2017 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2018 smb_fn_name(req
->cmd
),
2025 TALLOC_FREE(directory
);
2027 TALLOC_FREE(smb_fname
);
2028 END_PROFILE(SMBsearch
);
2032 /****************************************************************************
2033 Reply to a fclose (stop directory search).
2034 ****************************************************************************/
2036 void reply_fclose(struct smb_request
*req
)
2044 bool path_contains_wcard
= False
;
2045 TALLOC_CTX
*ctx
= talloc_tos();
2046 struct smbd_server_connection
*sconn
= req
->sconn
;
2048 START_PROFILE(SMBfclose
);
2050 if (req
->posix_pathnames
) {
2051 reply_unknown_new(req
, req
->cmd
);
2052 END_PROFILE(SMBfclose
);
2056 p
= (const char *)req
->buf
+ 1;
2057 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
2058 &err
, &path_contains_wcard
);
2059 if (!NT_STATUS_IS_OK(err
)) {
2060 reply_nterror(req
, err
);
2061 END_PROFILE(SMBfclose
);
2065 status_len
= SVAL(p
,0);
2068 if (status_len
== 0) {
2069 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
2070 END_PROFILE(SMBfclose
);
2074 memcpy(status
,p
,21);
2076 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
2077 /* Close the dptr - we know it's gone */
2078 dptr_close(sconn
, &dptr_num
);
2081 reply_outbuf(req
, 1, 0);
2082 SSVAL(req
->outbuf
,smb_vwv0
,0);
2084 DEBUG(3,("search close\n"));
2086 END_PROFILE(SMBfclose
);
2090 /****************************************************************************
2092 ****************************************************************************/
2094 void reply_open(struct smb_request
*req
)
2096 connection_struct
*conn
= req
->conn
;
2097 struct smb_filename
*smb_fname
= NULL
;
2107 uint32_t access_mask
;
2108 uint32_t share_mode
;
2109 uint32_t create_disposition
;
2110 uint32_t create_options
= 0;
2111 uint32_t private_flags
= 0;
2114 TALLOC_CTX
*ctx
= talloc_tos();
2116 START_PROFILE(SMBopen
);
2119 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2123 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2124 deny_mode
= SVAL(req
->vwv
+0, 0);
2125 dos_attr
= SVAL(req
->vwv
+1, 0);
2127 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2128 STR_TERMINATE
, &status
);
2129 if (!NT_STATUS_IS_OK(status
)) {
2130 reply_nterror(req
, status
);
2134 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2135 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
2136 &share_mode
, &create_disposition
,
2137 &create_options
, &private_flags
)) {
2138 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2142 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2144 status
= filename_convert(ctx
,
2150 if (!NT_STATUS_IS_OK(status
)) {
2151 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2152 reply_botherror(req
,
2153 NT_STATUS_PATH_NOT_COVERED
,
2154 ERRSRV
, ERRbadpath
);
2157 reply_nterror(req
, status
);
2161 status
= SMB_VFS_CREATE_FILE(
2164 0, /* root_dir_fid */
2165 smb_fname
, /* fname */
2166 access_mask
, /* access_mask */
2167 share_mode
, /* share_access */
2168 create_disposition
, /* create_disposition*/
2169 create_options
, /* create_options */
2170 dos_attr
, /* file_attributes */
2171 oplock_request
, /* oplock_request */
2173 0, /* allocation_size */
2179 NULL
, NULL
); /* create context */
2181 if (!NT_STATUS_IS_OK(status
)) {
2182 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2183 /* We have re-scheduled this call. */
2186 reply_openerror(req
, status
);
2190 /* Ensure we're pointing at the correct stat struct. */
2191 TALLOC_FREE(smb_fname
);
2192 smb_fname
= fsp
->fsp_name
;
2194 size
= smb_fname
->st
.st_ex_size
;
2195 fattr
= dos_mode(conn
, smb_fname
);
2197 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2199 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2200 DEBUG(3,("attempt to open a directory %s\n",
2202 close_file(req
, fsp
, ERROR_CLOSE
);
2203 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2204 ERRDOS
, ERRnoaccess
);
2208 reply_outbuf(req
, 7, 0);
2209 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2210 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2211 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2212 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2214 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2216 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2217 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2219 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2220 SCVAL(req
->outbuf
,smb_flg
,
2221 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2224 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2225 SCVAL(req
->outbuf
,smb_flg
,
2226 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2229 END_PROFILE(SMBopen
);
2233 /****************************************************************************
2234 Reply to an open and X.
2235 ****************************************************************************/
2237 void reply_open_and_X(struct smb_request
*req
)
2239 connection_struct
*conn
= req
->conn
;
2240 struct smb_filename
*smb_fname
= NULL
;
2242 uint16_t open_flags
;
2245 /* Breakout the oplock request bits so we can set the
2246 reply bits separately. */
2247 int ex_oplock_request
;
2248 int core_oplock_request
;
2251 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2252 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2260 uint64_t allocation_size
;
2261 ssize_t retval
= -1;
2262 uint32_t access_mask
;
2263 uint32_t share_mode
;
2264 uint32_t create_disposition
;
2265 uint32_t create_options
= 0;
2266 uint32_t private_flags
= 0;
2268 TALLOC_CTX
*ctx
= talloc_tos();
2270 START_PROFILE(SMBopenX
);
2272 if (req
->wct
< 15) {
2273 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2277 open_flags
= SVAL(req
->vwv
+2, 0);
2278 deny_mode
= SVAL(req
->vwv
+3, 0);
2279 smb_attr
= SVAL(req
->vwv
+5, 0);
2280 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2281 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2282 oplock_request
= ex_oplock_request
| core_oplock_request
;
2283 smb_ofun
= SVAL(req
->vwv
+8, 0);
2284 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2286 /* If it's an IPC, pass off the pipe handler. */
2288 if (lp_nt_pipe_support()) {
2289 reply_open_pipe_and_X(conn
, req
);
2291 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2296 /* XXXX we need to handle passed times, sattr and flags */
2297 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2298 STR_TERMINATE
, &status
);
2299 if (!NT_STATUS_IS_OK(status
)) {
2300 reply_nterror(req
, status
);
2304 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2306 &access_mask
, &share_mode
,
2307 &create_disposition
,
2310 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2314 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2316 status
= filename_convert(ctx
,
2322 if (!NT_STATUS_IS_OK(status
)) {
2323 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2324 reply_botherror(req
,
2325 NT_STATUS_PATH_NOT_COVERED
,
2326 ERRSRV
, ERRbadpath
);
2329 reply_nterror(req
, status
);
2333 status
= SMB_VFS_CREATE_FILE(
2336 0, /* root_dir_fid */
2337 smb_fname
, /* fname */
2338 access_mask
, /* access_mask */
2339 share_mode
, /* share_access */
2340 create_disposition
, /* create_disposition*/
2341 create_options
, /* create_options */
2342 smb_attr
, /* file_attributes */
2343 oplock_request
, /* oplock_request */
2345 0, /* allocation_size */
2350 &smb_action
, /* pinfo */
2351 NULL
, NULL
); /* create context */
2353 if (!NT_STATUS_IS_OK(status
)) {
2354 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2355 /* We have re-scheduled this call. */
2358 reply_openerror(req
, status
);
2362 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2363 if the file is truncated or created. */
2364 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2365 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2366 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2367 close_file(req
, fsp
, ERROR_CLOSE
);
2368 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2371 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2373 close_file(req
, fsp
, ERROR_CLOSE
);
2374 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2377 status
= vfs_stat_fsp(fsp
);
2378 if (!NT_STATUS_IS_OK(status
)) {
2379 close_file(req
, fsp
, ERROR_CLOSE
);
2380 reply_nterror(req
, status
);
2385 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2386 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2387 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2388 close_file(req
, fsp
, ERROR_CLOSE
);
2389 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2393 /* If the caller set the extended oplock request bit
2394 and we granted one (by whatever means) - set the
2395 correct bit for extended oplock reply.
2398 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2399 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2402 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2403 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2406 /* If the caller set the core oplock request bit
2407 and we granted one (by whatever means) - set the
2408 correct bit for core oplock reply.
2411 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2412 reply_outbuf(req
, 19, 0);
2414 reply_outbuf(req
, 15, 0);
2417 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2418 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2420 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2421 SCVAL(req
->outbuf
, smb_flg
,
2422 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2425 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2426 SCVAL(req
->outbuf
, smb_flg
,
2427 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2430 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2431 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2432 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2433 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2435 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2437 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2438 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2439 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2441 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2442 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2446 TALLOC_FREE(smb_fname
);
2447 END_PROFILE(SMBopenX
);
2451 /****************************************************************************
2452 Reply to a SMBulogoffX.
2453 ****************************************************************************/
2455 void reply_ulogoffX(struct smb_request
*req
)
2457 struct smbd_server_connection
*sconn
= req
->sconn
;
2458 struct user_struct
*vuser
;
2459 struct smbXsrv_session
*session
= NULL
;
2462 START_PROFILE(SMBulogoffX
);
2464 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2467 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2468 (unsigned long long)req
->vuid
));
2470 req
->vuid
= UID_FIELD_INVALID
;
2471 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2472 END_PROFILE(SMBulogoffX
);
2476 session
= vuser
->session
;
2480 * TODO: cancel all outstanding requests on the session
2482 status
= smbXsrv_session_logoff(session
);
2483 if (!NT_STATUS_IS_OK(status
)) {
2484 DEBUG(0, ("reply_ulogoff: "
2485 "smbXsrv_session_logoff() failed: %s\n",
2486 nt_errstr(status
)));
2488 * If we hit this case, there is something completely
2489 * wrong, so we better disconnect the transport connection.
2491 END_PROFILE(SMBulogoffX
);
2492 exit_server(__location__
": smbXsrv_session_logoff failed");
2496 TALLOC_FREE(session
);
2498 reply_outbuf(req
, 2, 0);
2499 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2500 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2502 DEBUG(3, ("ulogoffX vuid=%llu\n",
2503 (unsigned long long)req
->vuid
));
2505 END_PROFILE(SMBulogoffX
);
2506 req
->vuid
= UID_FIELD_INVALID
;
2509 /****************************************************************************
2510 Reply to a mknew or a create.
2511 ****************************************************************************/
2513 void reply_mknew(struct smb_request
*req
)
2515 connection_struct
*conn
= req
->conn
;
2516 struct smb_filename
*smb_fname
= NULL
;
2519 struct smb_file_time ft
;
2521 int oplock_request
= 0;
2523 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2524 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2525 uint32_t create_disposition
;
2526 uint32_t create_options
= 0;
2528 TALLOC_CTX
*ctx
= talloc_tos();
2530 START_PROFILE(SMBcreate
);
2534 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2538 fattr
= SVAL(req
->vwv
+0, 0);
2539 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2541 if (req
->cmd
== SMBmknew
) {
2542 /* We should fail if file exists. */
2543 create_disposition
= FILE_CREATE
;
2545 /* Create if file doesn't exist, truncate if it does. */
2546 create_disposition
= FILE_OVERWRITE_IF
;
2550 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2552 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2553 STR_TERMINATE
, &status
);
2554 if (!NT_STATUS_IS_OK(status
)) {
2555 reply_nterror(req
, status
);
2559 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2560 status
= filename_convert(ctx
,
2566 if (!NT_STATUS_IS_OK(status
)) {
2567 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2568 reply_botherror(req
,
2569 NT_STATUS_PATH_NOT_COVERED
,
2570 ERRSRV
, ERRbadpath
);
2573 reply_nterror(req
, status
);
2577 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2578 DEBUG(0,("Attempt to create file (%s) with volid set - "
2579 "please report this\n",
2580 smb_fname_str_dbg(smb_fname
)));
2583 status
= SMB_VFS_CREATE_FILE(
2586 0, /* root_dir_fid */
2587 smb_fname
, /* fname */
2588 access_mask
, /* access_mask */
2589 share_mode
, /* share_access */
2590 create_disposition
, /* create_disposition*/
2591 create_options
, /* create_options */
2592 fattr
, /* file_attributes */
2593 oplock_request
, /* oplock_request */
2595 0, /* allocation_size */
2596 0, /* private_flags */
2601 NULL
, NULL
); /* create context */
2603 if (!NT_STATUS_IS_OK(status
)) {
2604 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2605 /* We have re-scheduled this call. */
2608 reply_openerror(req
, status
);
2612 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2613 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2614 if (!NT_STATUS_IS_OK(status
)) {
2615 END_PROFILE(SMBcreate
);
2619 reply_outbuf(req
, 1, 0);
2620 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2622 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2623 SCVAL(req
->outbuf
,smb_flg
,
2624 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2627 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2628 SCVAL(req
->outbuf
,smb_flg
,
2629 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2632 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2633 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2634 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2635 (unsigned int)fattr
));
2638 TALLOC_FREE(smb_fname
);
2639 END_PROFILE(SMBcreate
);
2643 /****************************************************************************
2644 Reply to a create temporary file.
2645 ****************************************************************************/
2647 void reply_ctemp(struct smb_request
*req
)
2649 connection_struct
*conn
= req
->conn
;
2650 struct smb_filename
*smb_fname
= NULL
;
2651 char *wire_name
= NULL
;
2660 TALLOC_CTX
*ctx
= talloc_tos();
2662 START_PROFILE(SMBctemp
);
2665 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2669 fattr
= SVAL(req
->vwv
+0, 0);
2670 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2672 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2673 STR_TERMINATE
, &status
);
2674 if (!NT_STATUS_IS_OK(status
)) {
2675 reply_nterror(req
, status
);
2679 for (i
= 0; i
< 10; i
++) {
2681 fname
= talloc_asprintf(ctx
,
2684 generate_random_str_list(ctx
, 5, "0123456789"));
2686 fname
= talloc_asprintf(ctx
,
2688 generate_random_str_list(ctx
, 5, "0123456789"));
2692 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2696 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2697 status
= filename_convert(ctx
, conn
,
2702 if (!NT_STATUS_IS_OK(status
)) {
2703 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2704 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2705 ERRSRV
, ERRbadpath
);
2708 reply_nterror(req
, status
);
2712 /* Create the file. */
2713 status
= SMB_VFS_CREATE_FILE(
2716 0, /* root_dir_fid */
2717 smb_fname
, /* fname */
2718 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2719 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2720 FILE_CREATE
, /* create_disposition*/
2721 0, /* create_options */
2722 fattr
, /* file_attributes */
2723 oplock_request
, /* oplock_request */
2725 0, /* allocation_size */
2726 0, /* private_flags */
2731 NULL
, NULL
); /* create context */
2733 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2735 TALLOC_FREE(smb_fname
);
2739 if (!NT_STATUS_IS_OK(status
)) {
2740 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2741 /* We have re-scheduled this call. */
2744 reply_openerror(req
, status
);
2752 /* Collision after 10 times... */
2753 reply_nterror(req
, status
);
2757 reply_outbuf(req
, 1, 0);
2758 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2760 /* the returned filename is relative to the directory */
2761 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2763 s
= fsp
->fsp_name
->base_name
;
2769 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2770 thing in the byte section. JRA */
2771 SSVALS(p
, 0, -1); /* what is this? not in spec */
2773 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2775 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2779 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2780 SCVAL(req
->outbuf
, smb_flg
,
2781 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2784 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2785 SCVAL(req
->outbuf
, smb_flg
,
2786 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2789 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2790 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2791 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2793 TALLOC_FREE(smb_fname
);
2794 TALLOC_FREE(wire_name
);
2795 END_PROFILE(SMBctemp
);
2799 /*******************************************************************
2800 Check if a user is allowed to rename a file.
2801 ********************************************************************/
2803 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2806 if (!CAN_WRITE(conn
)) {
2807 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2810 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2811 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2812 /* Only bother to read the DOS attribute if we might deny the
2813 rename on the grounds of attribute mismatch. */
2814 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2815 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2816 return NT_STATUS_NO_SUCH_FILE
;
2820 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2821 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
2822 return NT_STATUS_OK
;
2825 /* If no pathnames are open below this
2826 directory, allow the rename. */
2828 if (lp_strict_rename(SNUM(conn
))) {
2830 * Strict rename, check open file db.
2832 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
2833 return NT_STATUS_ACCESS_DENIED
;
2835 } else if (file_find_subpath(fsp
)) {
2837 * No strict rename, just look in local process.
2839 return NT_STATUS_ACCESS_DENIED
;
2841 return NT_STATUS_OK
;
2844 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2845 return NT_STATUS_OK
;
2848 return NT_STATUS_ACCESS_DENIED
;
2851 /*******************************************************************
2852 * unlink a file with all relevant access checks
2853 *******************************************************************/
2855 static NTSTATUS
do_unlink(connection_struct
*conn
,
2856 struct smb_request
*req
,
2857 struct smb_filename
*smb_fname
,
2862 uint32_t dirtype_orig
= dirtype
;
2865 bool posix_paths
= (req
!= NULL
&& req
->posix_pathnames
);
2867 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2868 smb_fname_str_dbg(smb_fname
),
2871 if (!CAN_WRITE(conn
)) {
2872 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2876 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2878 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2881 return map_nt_error_from_unix(errno
);
2884 fattr
= dos_mode(conn
, smb_fname
);
2886 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2887 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2890 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2892 return NT_STATUS_NO_SUCH_FILE
;
2895 if (!dir_check_ftype(fattr
, dirtype
)) {
2896 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2897 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2899 return NT_STATUS_NO_SUCH_FILE
;
2902 if (dirtype_orig
& 0x8000) {
2903 /* These will never be set for POSIX. */
2904 return NT_STATUS_NO_SUCH_FILE
;
2908 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2909 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2912 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2913 return NT_STATUS_NO_SUCH_FILE
;
2916 if (dirtype
& 0xFF00) {
2917 /* These will never be set for POSIX. */
2918 return NT_STATUS_NO_SUCH_FILE
;
2923 return NT_STATUS_NO_SUCH_FILE
;
2926 /* Can't delete a directory. */
2927 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2928 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2933 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2934 return NT_STATUS_OBJECT_NAME_INVALID
;
2935 #endif /* JRATEST */
2937 /* On open checks the open itself will check the share mode, so
2938 don't do it here as we'll get it wrong. */
2940 status
= SMB_VFS_CREATE_FILE
2943 0, /* root_dir_fid */
2944 smb_fname
, /* fname */
2945 DELETE_ACCESS
, /* access_mask */
2946 FILE_SHARE_NONE
, /* share_access */
2947 FILE_OPEN
, /* create_disposition*/
2948 FILE_NON_DIRECTORY_FILE
, /* create_options */
2949 /* file_attributes */
2950 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2951 FILE_ATTRIBUTE_NORMAL
,
2952 0, /* oplock_request */
2954 0, /* allocation_size */
2955 0, /* private_flags */
2960 NULL
, NULL
); /* create context */
2962 if (!NT_STATUS_IS_OK(status
)) {
2963 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2964 nt_errstr(status
)));
2968 status
= can_set_delete_on_close(fsp
, fattr
);
2969 if (!NT_STATUS_IS_OK(status
)) {
2970 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2972 smb_fname_str_dbg(smb_fname
),
2973 nt_errstr(status
)));
2974 close_file(req
, fsp
, NORMAL_CLOSE
);
2978 /* The set is across all open files on this dev/inode pair. */
2979 if (!set_delete_on_close(fsp
, True
,
2980 conn
->session_info
->security_token
,
2981 conn
->session_info
->unix_token
)) {
2982 close_file(req
, fsp
, NORMAL_CLOSE
);
2983 return NT_STATUS_ACCESS_DENIED
;
2986 return close_file(req
, fsp
, NORMAL_CLOSE
);
2989 /****************************************************************************
2990 The guts of the unlink command, split out so it may be called by the NT SMB
2992 ****************************************************************************/
2994 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2995 uint32_t dirtype
, struct smb_filename
*smb_fname
,
2998 char *fname_dir
= NULL
;
2999 char *fname_mask
= NULL
;
3001 NTSTATUS status
= NT_STATUS_OK
;
3002 struct smb_filename
*smb_fname_dir
= NULL
;
3003 TALLOC_CTX
*ctx
= talloc_tos();
3005 /* Split up the directory from the filename/mask. */
3006 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
3007 &fname_dir
, &fname_mask
);
3008 if (!NT_STATUS_IS_OK(status
)) {
3013 * We should only check the mangled cache
3014 * here if unix_convert failed. This means
3015 * that the path in 'mask' doesn't exist
3016 * on the file system and so we need to look
3017 * for a possible mangle. This patch from
3018 * Tine Smukavec <valentin.smukavec@hermes.si>.
3021 if (!VALID_STAT(smb_fname
->st
) &&
3022 mangle_is_mangled(fname_mask
, conn
->params
)) {
3023 char *new_mask
= NULL
;
3024 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
3025 &new_mask
, conn
->params
);
3027 TALLOC_FREE(fname_mask
);
3028 fname_mask
= new_mask
;
3035 * Only one file needs to be unlinked. Append the mask back
3036 * onto the directory.
3038 TALLOC_FREE(smb_fname
->base_name
);
3039 if (ISDOT(fname_dir
)) {
3040 /* Ensure we use canonical names on open. */
3041 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3045 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3050 if (!smb_fname
->base_name
) {
3051 status
= NT_STATUS_NO_MEMORY
;
3055 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3058 status
= check_name(conn
, smb_fname
);
3059 if (!NT_STATUS_IS_OK(status
)) {
3063 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3064 if (!NT_STATUS_IS_OK(status
)) {
3070 struct smb_Dir
*dir_hnd
= NULL
;
3072 const char *dname
= NULL
;
3073 char *talloced
= NULL
;
3075 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
3076 status
= NT_STATUS_OBJECT_NAME_INVALID
;
3080 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3083 if (strequal(fname_mask
,"????????.???")) {
3084 TALLOC_FREE(fname_mask
);
3085 fname_mask
= talloc_strdup(ctx
, "*");
3087 status
= NT_STATUS_NO_MEMORY
;
3092 smb_fname_dir
= synthetic_smb_fname(talloc_tos(),
3097 if (smb_fname_dir
== NULL
) {
3098 status
= NT_STATUS_NO_MEMORY
;
3102 status
= check_name(conn
, smb_fname_dir
);
3103 if (!NT_STATUS_IS_OK(status
)) {
3107 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_dir
, fname_mask
,
3109 if (dir_hnd
== NULL
) {
3110 status
= map_nt_error_from_unix(errno
);
3114 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3115 the pattern matches against the long name, otherwise the short name
3116 We don't implement this yet XXXX
3119 status
= NT_STATUS_NO_SUCH_FILE
;
3121 while ((dname
= ReadDirName(dir_hnd
, &offset
,
3122 &smb_fname
->st
, &talloced
))) {
3123 TALLOC_CTX
*frame
= talloc_stackframe();
3125 if (!is_visible_file(conn
, fname_dir
, dname
,
3126 &smb_fname
->st
, true)) {
3128 TALLOC_FREE(talloced
);
3132 /* Quick check for "." and ".." */
3133 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
3135 TALLOC_FREE(talloced
);
3139 if(!mask_match(dname
, fname_mask
,
3140 conn
->case_sensitive
)) {
3142 TALLOC_FREE(talloced
);
3146 TALLOC_FREE(smb_fname
->base_name
);
3147 if (ISDOT(fname_dir
)) {
3148 /* Ensure we use canonical names on open. */
3149 smb_fname
->base_name
=
3150 talloc_asprintf(smb_fname
, "%s",
3153 smb_fname
->base_name
=
3154 talloc_asprintf(smb_fname
, "%s/%s",
3158 if (!smb_fname
->base_name
) {
3159 TALLOC_FREE(dir_hnd
);
3160 status
= NT_STATUS_NO_MEMORY
;
3162 TALLOC_FREE(talloced
);
3166 status
= check_name(conn
, smb_fname
);
3167 if (!NT_STATUS_IS_OK(status
)) {
3168 TALLOC_FREE(dir_hnd
);
3170 TALLOC_FREE(talloced
);
3174 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3175 if (!NT_STATUS_IS_OK(status
)) {
3176 TALLOC_FREE(dir_hnd
);
3178 TALLOC_FREE(talloced
);
3183 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3184 smb_fname
->base_name
));
3187 TALLOC_FREE(talloced
);
3189 TALLOC_FREE(dir_hnd
);
3192 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3193 status
= map_nt_error_from_unix(errno
);
3197 TALLOC_FREE(smb_fname_dir
);
3198 TALLOC_FREE(fname_dir
);
3199 TALLOC_FREE(fname_mask
);
3203 /****************************************************************************
3205 ****************************************************************************/
3207 void reply_unlink(struct smb_request
*req
)
3209 connection_struct
*conn
= req
->conn
;
3211 struct smb_filename
*smb_fname
= NULL
;
3214 bool path_contains_wcard
= False
;
3215 uint32_t ucf_flags
= UCF_COND_ALLOW_WCARD_LCOMP
|
3216 ucf_flags_from_smb_request(req
);
3217 TALLOC_CTX
*ctx
= talloc_tos();
3219 START_PROFILE(SMBunlink
);
3222 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3226 dirtype
= SVAL(req
->vwv
+0, 0);
3228 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3229 STR_TERMINATE
, &status
,
3230 &path_contains_wcard
);
3231 if (!NT_STATUS_IS_OK(status
)) {
3232 reply_nterror(req
, status
);
3236 status
= filename_convert(ctx
, conn
,
3239 &path_contains_wcard
,
3241 if (!NT_STATUS_IS_OK(status
)) {
3242 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3243 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3244 ERRSRV
, ERRbadpath
);
3247 reply_nterror(req
, status
);
3251 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3253 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
3254 path_contains_wcard
);
3255 if (!NT_STATUS_IS_OK(status
)) {
3256 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3257 /* We have re-scheduled this call. */
3260 reply_nterror(req
, status
);
3264 reply_outbuf(req
, 0, 0);
3266 TALLOC_FREE(smb_fname
);
3267 END_PROFILE(SMBunlink
);
3271 /****************************************************************************
3273 ****************************************************************************/
3275 static void fail_readraw(void)
3277 const char *errstr
= talloc_asprintf(talloc_tos(),
3278 "FAIL ! reply_readbraw: socket write fail (%s)",
3283 exit_server_cleanly(errstr
);
3286 /****************************************************************************
3287 Fake (read/write) sendfile. Returns -1 on read or write fail.
3288 ****************************************************************************/
3290 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3291 off_t startpos
, size_t nread
)
3294 size_t tosend
= nread
;
3301 bufsize
= MIN(nread
, 65536);
3303 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3307 while (tosend
> 0) {
3311 cur_read
= MIN(tosend
, bufsize
);
3312 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3318 /* If we had a short read, fill with zeros. */
3319 if (ret
< cur_read
) {
3320 memset(buf
+ ret
, '\0', cur_read
- ret
);
3323 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3324 if (ret
!= cur_read
) {
3325 int saved_errno
= errno
;
3327 * Try and give an error message saying what
3330 DEBUG(0, ("write_data failed for client %s. "
3332 smbXsrv_connection_dbg(xconn
),
3333 strerror(saved_errno
)));
3335 errno
= saved_errno
;
3339 startpos
+= cur_read
;
3343 return (ssize_t
)nread
;
3346 /****************************************************************************
3347 Deal with the case of sendfile reading less bytes from the file than
3348 requested. Fill with zeros (all we can do). Returns 0 on success
3349 ****************************************************************************/
3351 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3357 #define SHORT_SEND_BUFSIZE 1024
3358 if (nread
< headersize
) {
3359 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3360 "header for file %s (%s). Terminating\n",
3361 fsp_str_dbg(fsp
), strerror(errno
)));
3365 nread
-= headersize
;
3367 if (nread
< smb_maxcnt
) {
3368 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3370 DEBUG(0,("sendfile_short_send: malloc failed "
3371 "for file %s (%s). Terminating\n",
3372 fsp_str_dbg(fsp
), strerror(errno
)));
3376 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3377 "with zeros !\n", fsp_str_dbg(fsp
)));
3379 while (nread
< smb_maxcnt
) {
3381 * We asked for the real file size and told sendfile
3382 * to not go beyond the end of the file. But it can
3383 * happen that in between our fstat call and the
3384 * sendfile call the file was truncated. This is very
3385 * bad because we have already announced the larger
3386 * number of bytes to the client.
3388 * The best we can do now is to send 0-bytes, just as
3389 * a read from a hole in a sparse file would do.
3391 * This should happen rarely enough that I don't care
3392 * about efficiency here :-)
3397 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3398 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3399 if (ret
!= to_write
) {
3400 int saved_errno
= errno
;
3402 * Try and give an error message saying what
3405 DEBUG(0, ("write_data failed for client %s. "
3407 smbXsrv_connection_dbg(xconn
),
3408 strerror(saved_errno
)));
3409 errno
= saved_errno
;
3420 /****************************************************************************
3421 Return a readbraw error (4 bytes of zero).
3422 ****************************************************************************/
3424 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3430 smbd_lock_socket(xconn
);
3431 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3432 int saved_errno
= errno
;
3434 * Try and give an error message saying what
3437 DEBUG(0, ("write_data failed for client %s. "
3439 smbXsrv_connection_dbg(xconn
),
3440 strerror(saved_errno
)));
3441 errno
= saved_errno
;
3445 smbd_unlock_socket(xconn
);
3448 /****************************************************************************
3449 Use sendfile in readbraw.
3450 ****************************************************************************/
3452 static void send_file_readbraw(connection_struct
*conn
,
3453 struct smb_request
*req
,
3459 struct smbXsrv_connection
*xconn
= req
->xconn
;
3460 char *outbuf
= NULL
;
3464 * We can only use sendfile on a non-chained packet
3465 * but we can use on a non-oplocked file. tridge proved this
3466 * on a train in Germany :-). JRA.
3467 * reply_readbraw has already checked the length.
3470 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3471 (fsp
->wcp
== NULL
) &&
3472 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3473 ssize_t sendfile_read
= -1;
3475 DATA_BLOB header_blob
;
3477 _smb_setlen(header
,nread
);
3478 header_blob
= data_blob_const(header
, 4);
3480 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3481 &header_blob
, startpos
,
3483 if (sendfile_read
== -1) {
3484 /* Returning ENOSYS means no data at all was sent.
3485 * Do this as a normal read. */
3486 if (errno
== ENOSYS
) {
3487 goto normal_readbraw
;
3491 * Special hack for broken Linux with no working sendfile. If we
3492 * return EINTR we sent the header but not the rest of the data.
3493 * Fake this up by doing read/write calls.
3495 if (errno
== EINTR
) {
3496 /* Ensure we don't do this again. */
3497 set_use_sendfile(SNUM(conn
), False
);
3498 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3500 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3501 DEBUG(0,("send_file_readbraw: "
3502 "fake_sendfile failed for "
3506 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3511 DEBUG(0,("send_file_readbraw: sendfile failed for "
3512 "file %s (%s). Terminating\n",
3513 fsp_str_dbg(fsp
), strerror(errno
)));
3514 exit_server_cleanly("send_file_readbraw sendfile failed");
3515 } else if (sendfile_read
== 0) {
3517 * Some sendfile implementations return 0 to indicate
3518 * that there was a short read, but nothing was
3519 * actually written to the socket. In this case,
3520 * fallback to the normal read path so the header gets
3521 * the correct byte count.
3523 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3524 "bytes falling back to the normal read: "
3525 "%s\n", fsp_str_dbg(fsp
)));
3526 goto normal_readbraw
;
3529 /* Deal with possible short send. */
3530 if (sendfile_read
!= 4+nread
) {
3531 ret
= sendfile_short_send(xconn
, fsp
,
3532 sendfile_read
, 4, nread
);
3542 outbuf
= talloc_array(NULL
, char, nread
+4);
3544 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3545 (unsigned)(nread
+4)));
3546 reply_readbraw_error(xconn
);
3551 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3552 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3561 _smb_setlen(outbuf
,ret
);
3562 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3563 int saved_errno
= errno
;
3565 * Try and give an error message saying what
3568 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3569 smbXsrv_connection_dbg(xconn
),
3570 strerror(saved_errno
)));
3571 errno
= saved_errno
;
3576 TALLOC_FREE(outbuf
);
3579 /****************************************************************************
3580 Reply to a readbraw (core+ protocol).
3581 ****************************************************************************/
3583 void reply_readbraw(struct smb_request
*req
)
3585 connection_struct
*conn
= req
->conn
;
3586 struct smbXsrv_connection
*xconn
= req
->xconn
;
3587 ssize_t maxcount
,mincount
;
3591 struct lock_struct lock
;
3594 START_PROFILE(SMBreadbraw
);
3596 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3597 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3598 "raw reads/writes are disallowed.");
3602 reply_readbraw_error(xconn
);
3603 END_PROFILE(SMBreadbraw
);
3607 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3608 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3609 "'async smb echo handler = yes'\n"));
3610 reply_readbraw_error(xconn
);
3611 END_PROFILE(SMBreadbraw
);
3616 * Special check if an oplock break has been issued
3617 * and the readraw request croses on the wire, we must
3618 * return a zero length response here.
3621 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3624 * We have to do a check_fsp by hand here, as
3625 * we must always return 4 zero bytes on error,
3629 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3630 req
->vuid
!= fsp
->vuid
||
3631 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3633 * fsp could be NULL here so use the value from the packet. JRA.
3635 DEBUG(3,("reply_readbraw: fnum %d not valid "
3637 (int)SVAL(req
->vwv
+0, 0)));
3638 reply_readbraw_error(xconn
);
3639 END_PROFILE(SMBreadbraw
);
3643 /* Do a "by hand" version of CHECK_READ. */
3644 if (!(fsp
->can_read
||
3645 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3646 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3647 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3648 (int)SVAL(req
->vwv
+0, 0)));
3649 reply_readbraw_error(xconn
);
3650 END_PROFILE(SMBreadbraw
);
3654 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3656 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3657 if(req
->wct
== 10) {
3659 * This is a large offset (64 bit) read.
3662 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3665 DEBUG(0,("reply_readbraw: negative 64 bit "
3666 "readraw offset (%.0f) !\n",
3667 (double)startpos
));
3668 reply_readbraw_error(xconn
);
3669 END_PROFILE(SMBreadbraw
);
3674 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3675 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3677 /* ensure we don't overrun the packet size */
3678 maxcount
= MIN(65535,maxcount
);
3680 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3681 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3684 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3685 reply_readbraw_error(xconn
);
3686 END_PROFILE(SMBreadbraw
);
3690 if (fsp_stat(fsp
) == 0) {
3691 size
= fsp
->fsp_name
->st
.st_ex_size
;
3694 if (startpos
>= size
) {
3697 nread
= MIN(maxcount
,(size
- startpos
));
3700 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3701 if (nread
< mincount
)
3705 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3706 "min=%lu nread=%lu\n",
3707 fsp_fnum_dbg(fsp
), (double)startpos
,
3708 (unsigned long)maxcount
,
3709 (unsigned long)mincount
,
3710 (unsigned long)nread
) );
3712 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3714 DEBUG(5,("reply_readbraw finished\n"));
3716 END_PROFILE(SMBreadbraw
);
3721 #define DBGC_CLASS DBGC_LOCKING
3723 /****************************************************************************
3724 Reply to a lockread (core+ protocol).
3725 ****************************************************************************/
3727 void reply_lockread(struct smb_request
*req
)
3729 connection_struct
*conn
= req
->conn
;
3737 struct byte_range_lock
*br_lck
= NULL
;
3739 struct smbXsrv_connection
*xconn
= req
->xconn
;
3741 START_PROFILE(SMBlockread
);
3744 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3745 END_PROFILE(SMBlockread
);
3749 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3751 if (!check_fsp(conn
, req
, fsp
)) {
3752 END_PROFILE(SMBlockread
);
3756 if (!CHECK_READ(fsp
,req
)) {
3757 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3758 END_PROFILE(SMBlockread
);
3762 numtoread
= SVAL(req
->vwv
+1, 0);
3763 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3766 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3767 * protocol request that predates the read/write lock concept.
3768 * Thus instead of asking for a read lock here we need to ask
3769 * for a write lock. JRA.
3770 * Note that the requested lock size is unaffected by max_send.
3773 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3775 (uint64_t)req
->smbpid
,
3776 (uint64_t)numtoread
,
3780 False
, /* Non-blocking lock. */
3783 TALLOC_FREE(br_lck
);
3785 if (NT_STATUS_V(status
)) {
3786 reply_nterror(req
, status
);
3787 END_PROFILE(SMBlockread
);
3792 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3794 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3796 if (numtoread
> maxtoread
) {
3797 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3798 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3799 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3800 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3801 numtoread
= maxtoread
;
3804 reply_outbuf(req
, 5, numtoread
+ 3);
3806 data
= smb_buf(req
->outbuf
) + 3;
3808 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3811 reply_nterror(req
, map_nt_error_from_unix(errno
));
3812 END_PROFILE(SMBlockread
);
3816 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3818 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3819 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3820 p
= smb_buf(req
->outbuf
);
3821 SCVAL(p
,0,0); /* pad byte. */
3824 DEBUG(3,("lockread %s num=%d nread=%d\n",
3825 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3827 END_PROFILE(SMBlockread
);
3832 #define DBGC_CLASS DBGC_ALL
3834 /****************************************************************************
3836 ****************************************************************************/
3838 void reply_read(struct smb_request
*req
)
3840 connection_struct
*conn
= req
->conn
;
3847 struct lock_struct lock
;
3848 struct smbXsrv_connection
*xconn
= req
->xconn
;
3850 START_PROFILE(SMBread
);
3853 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3854 END_PROFILE(SMBread
);
3858 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3860 if (!check_fsp(conn
, req
, fsp
)) {
3861 END_PROFILE(SMBread
);
3865 if (!CHECK_READ(fsp
,req
)) {
3866 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3867 END_PROFILE(SMBread
);
3871 numtoread
= SVAL(req
->vwv
+1, 0);
3872 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3875 * The requested read size cannot be greater than max_send. JRA.
3877 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3879 if (numtoread
> maxtoread
) {
3880 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3881 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3882 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3883 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3884 numtoread
= maxtoread
;
3887 reply_outbuf(req
, 5, numtoread
+3);
3889 data
= smb_buf(req
->outbuf
) + 3;
3891 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3892 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3895 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3896 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3897 END_PROFILE(SMBread
);
3902 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3905 reply_nterror(req
, map_nt_error_from_unix(errno
));
3909 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3911 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3912 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3913 SCVAL(smb_buf(req
->outbuf
),0,1);
3914 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3916 DEBUG(3, ("read %s num=%d nread=%d\n",
3917 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3920 END_PROFILE(SMBread
);
3924 /****************************************************************************
3926 ****************************************************************************/
3928 int setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3932 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3935 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3937 SCVAL(outbuf
,smb_vwv0
,0xFF);
3938 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3939 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3940 SSVAL(outbuf
,smb_vwv6
,
3941 (smb_wct
- 4) /* offset from smb header to wct */
3942 + 1 /* the wct field */
3943 + 12 * sizeof(uint16_t) /* vwv */
3944 + 2 /* the buflen field */
3945 + 1); /* padding byte */
3946 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3947 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3948 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3949 _smb_setlen_large(outbuf
,
3950 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3954 /****************************************************************************
3955 Reply to a read and X - possibly using sendfile.
3956 ****************************************************************************/
3958 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3959 files_struct
*fsp
, off_t startpos
,
3962 struct smbXsrv_connection
*xconn
= req
->xconn
;
3964 struct lock_struct lock
;
3965 int saved_errno
= 0;
3967 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3968 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3971 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3972 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3977 * We can only use sendfile on a non-chained packet
3978 * but we can use on a non-oplocked file. tridge proved this
3979 * on a train in Germany :-). JRA.
3982 if (!req_is_in_chain(req
) &&
3984 (fsp
->base_fsp
== NULL
) &&
3985 (fsp
->wcp
== NULL
) &&
3986 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3987 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3990 if(fsp_stat(fsp
) == -1) {
3991 reply_nterror(req
, map_nt_error_from_unix(errno
));
3995 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3996 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3997 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3999 * We already know that we would do a short read, so don't
4000 * try the sendfile() path.
4002 goto nosendfile_read
;
4006 * Set up the packet header before send. We
4007 * assume here the sendfile will work (get the
4008 * correct amount of data).
4011 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4013 construct_reply_common_req(req
, (char *)headerbuf
);
4014 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4016 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4017 startpos
, smb_maxcnt
);
4019 saved_errno
= errno
;
4021 /* Returning ENOSYS means no data at all was sent.
4022 Do this as a normal read. */
4023 if (errno
== ENOSYS
) {
4028 * Special hack for broken Linux with no working sendfile. If we
4029 * return EINTR we sent the header but not the rest of the data.
4030 * Fake this up by doing read/write calls.
4033 if (errno
== EINTR
) {
4034 /* Ensure we don't do this again. */
4035 set_use_sendfile(SNUM(conn
), False
);
4036 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4037 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4040 saved_errno
= errno
;
4041 DEBUG(0,("send_file_readX: "
4042 "fake_sendfile failed for "
4043 "file %s (%s) for client %s. "
4046 smbXsrv_connection_dbg(xconn
),
4047 strerror(saved_errno
)));
4048 errno
= saved_errno
;
4049 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4051 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4052 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4053 /* No outbuf here means successful sendfile. */
4057 DEBUG(0,("send_file_readX: sendfile failed for file "
4058 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4060 exit_server_cleanly("send_file_readX sendfile failed");
4061 } else if (nread
== 0) {
4063 * Some sendfile implementations return 0 to indicate
4064 * that there was a short read, but nothing was
4065 * actually written to the socket. In this case,
4066 * fallback to the normal read path so the header gets
4067 * the correct byte count.
4069 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4070 "falling back to the normal read: %s\n",
4075 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4076 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4078 /* Deal with possible short send. */
4079 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4082 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4083 sizeof(headerbuf
), smb_maxcnt
);
4086 r
= "send_file_readX: sendfile_short_send failed";
4087 DEBUG(0,("%s for file %s (%s).\n",
4088 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4089 exit_server_cleanly(r
);
4092 /* No outbuf here means successful sendfile. */
4093 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4094 SMB_PERFCOUNT_END(&req
->pcd
);
4100 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4101 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4104 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4105 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4106 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4108 * We already know that we would do a short
4109 * read, so don't try the sendfile() path.
4111 goto nosendfile_read
;
4114 construct_reply_common_req(req
, (char *)headerbuf
);
4115 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4117 /* Send out the header. */
4118 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4120 if (ret
!= sizeof(headerbuf
)) {
4121 saved_errno
= errno
;
4123 * Try and give an error message saying what
4126 DEBUG(0,("send_file_readX: write_data failed for file "
4127 "%s (%s) for client %s. Terminating\n",
4129 smbXsrv_connection_dbg(xconn
),
4130 strerror(saved_errno
)));
4131 errno
= saved_errno
;
4132 exit_server_cleanly("send_file_readX sendfile failed");
4134 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4136 saved_errno
= errno
;
4137 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4138 "%s (%s) for client %s. Terminating\n",
4140 smbXsrv_connection_dbg(xconn
),
4141 strerror(saved_errno
)));
4142 errno
= saved_errno
;
4143 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4150 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4151 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4152 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4154 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4155 startpos
, smb_maxcnt
);
4156 saved_errno
= errno
;
4159 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4163 setup_readX_header((char *)req
->outbuf
, nread
);
4165 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4166 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4170 TALLOC_FREE(req
->outbuf
);
4174 /****************************************************************************
4175 Work out how much space we have for a read return.
4176 ****************************************************************************/
4178 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4180 struct smbXsrv_connection
*xconn
= req
->xconn
;
4182 if (xconn
->protocol
< PROTOCOL_NT1
) {
4183 return xconn
->smb1
.sessions
.max_send
;
4186 if (!lp_large_readwrite()) {
4187 return xconn
->smb1
.sessions
.max_send
;
4190 if (req_is_in_chain(req
)) {
4191 return xconn
->smb1
.sessions
.max_send
;
4194 if (req
->encrypted
) {
4196 * Don't take encrypted traffic up to the
4197 * limit. There are padding considerations
4198 * that make that tricky.
4200 return xconn
->smb1
.sessions
.max_send
;
4203 if (srv_is_signing_active(xconn
)) {
4207 if (!lp_unix_extensions()) {
4212 * We can do ultra-large POSIX reads.
4217 /****************************************************************************
4218 Calculate how big a read can be. Copes with all clients. It's always
4219 safe to return a short read - Windows does this.
4220 ****************************************************************************/
4222 static size_t calc_read_size(const struct smb_request
*req
,
4226 struct smbXsrv_connection
*xconn
= req
->xconn
;
4227 size_t max_pdu
= calc_max_read_pdu(req
);
4228 size_t total_size
= 0;
4229 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4230 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4233 * Windows explicitly ignores upper size of 0xFFFF.
4234 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4235 * We must do the same as these will never fit even in
4236 * an extended size NetBIOS packet.
4238 if (upper_size
== 0xFFFF) {
4242 if (xconn
->protocol
< PROTOCOL_NT1
) {
4246 total_size
= ((upper_size
<<16) | lower_size
);
4249 * LARGE_READX test shows it's always safe to return
4250 * a short read. Windows does so.
4252 return MIN(total_size
, max_len
);
4255 /****************************************************************************
4256 Reply to a read and X.
4257 ****************************************************************************/
4259 void reply_read_and_X(struct smb_request
*req
)
4261 connection_struct
*conn
= req
->conn
;
4266 bool big_readX
= False
;
4268 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4271 START_PROFILE(SMBreadX
);
4273 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4274 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4278 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4279 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4280 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4282 /* If it's an IPC, pass off the pipe handler. */
4284 reply_pipe_read_and_X(req
);
4285 END_PROFILE(SMBreadX
);
4289 if (!check_fsp(conn
, req
, fsp
)) {
4290 END_PROFILE(SMBreadX
);
4294 if (!CHECK_READ(fsp
,req
)) {
4295 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4296 END_PROFILE(SMBreadX
);
4300 upper_size
= SVAL(req
->vwv
+7, 0);
4301 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4302 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4304 * This is a heuristic to avoid keeping large
4305 * outgoing buffers around over long-lived aio
4311 if (req
->wct
== 12) {
4313 * This is a large offset (64 bit) read.
4315 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4320 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4325 if (NT_STATUS_IS_OK(status
)) {
4326 /* Read scheduled - we're done. */
4329 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4330 /* Real error - report to client. */
4331 END_PROFILE(SMBreadX
);
4332 reply_nterror(req
, status
);
4335 /* NT_STATUS_RETRY - fall back to sync read. */
4338 smbd_lock_socket(req
->xconn
);
4339 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4340 smbd_unlock_socket(req
->xconn
);
4343 END_PROFILE(SMBreadX
);
4347 /****************************************************************************
4348 Error replies to writebraw must have smb_wct == 1. Fix this up.
4349 ****************************************************************************/
4351 void error_to_writebrawerr(struct smb_request
*req
)
4353 uint8_t *old_outbuf
= req
->outbuf
;
4355 reply_outbuf(req
, 1, 0);
4357 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4358 TALLOC_FREE(old_outbuf
);
4361 /****************************************************************************
4362 Read 4 bytes of a smb packet and return the smb length of the packet.
4363 Store the result in the buffer. This version of the function will
4364 never return a session keepalive (length of zero).
4365 Timeout is in milliseconds.
4366 ****************************************************************************/
4368 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4371 uint8_t msgtype
= NBSSkeepalive
;
4373 while (msgtype
== NBSSkeepalive
) {
4376 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4378 if (!NT_STATUS_IS_OK(status
)) {
4379 char addr
[INET6_ADDRSTRLEN
];
4380 /* Try and give an error message
4381 * saying what client failed. */
4382 DEBUG(0, ("read_fd_with_timeout failed for "
4383 "client %s read error = %s.\n",
4384 get_peer_addr(fd
,addr
,sizeof(addr
)),
4385 nt_errstr(status
)));
4389 msgtype
= CVAL(inbuf
, 0);
4392 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4393 (unsigned long)len
));
4395 return NT_STATUS_OK
;
4398 /****************************************************************************
4399 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4400 ****************************************************************************/
4402 void reply_writebraw(struct smb_request
*req
)
4404 connection_struct
*conn
= req
->conn
;
4405 struct smbXsrv_connection
*xconn
= req
->xconn
;
4408 ssize_t total_written
=0;
4409 size_t numtowrite
=0;
4412 const char *data
=NULL
;
4415 struct lock_struct lock
;
4418 START_PROFILE(SMBwritebraw
);
4421 * If we ever reply with an error, it must have the SMB command
4422 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4425 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4427 if (srv_is_signing_active(xconn
)) {
4428 END_PROFILE(SMBwritebraw
);
4429 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4430 "raw reads/writes are disallowed.");
4433 if (req
->wct
< 12) {
4434 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4435 error_to_writebrawerr(req
);
4436 END_PROFILE(SMBwritebraw
);
4440 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4441 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4442 "'async smb echo handler = yes'\n"));
4443 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4444 error_to_writebrawerr(req
);
4445 END_PROFILE(SMBwritebraw
);
4449 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4450 if (!check_fsp(conn
, req
, fsp
)) {
4451 error_to_writebrawerr(req
);
4452 END_PROFILE(SMBwritebraw
);
4456 if (!CHECK_WRITE(fsp
)) {
4457 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4458 error_to_writebrawerr(req
);
4459 END_PROFILE(SMBwritebraw
);
4463 tcount
= IVAL(req
->vwv
+1, 0);
4464 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4465 write_through
= BITSETW(req
->vwv
+7,0);
4467 /* We have to deal with slightly different formats depending
4468 on whether we are using the core+ or lanman1.0 protocol */
4470 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4471 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4472 data
= smb_buf_const(req
->inbuf
);
4474 numtowrite
= SVAL(req
->vwv
+10, 0);
4475 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4478 /* Ensure we don't write bytes past the end of this packet. */
4480 * This already protects us against CVE-2017-12163.
4482 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4483 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4484 error_to_writebrawerr(req
);
4485 END_PROFILE(SMBwritebraw
);
4489 if (!fsp
->print_file
) {
4490 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4491 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4494 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4495 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4496 error_to_writebrawerr(req
);
4497 END_PROFILE(SMBwritebraw
);
4503 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4506 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4507 "wrote=%d sync=%d\n",
4508 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4509 (int)nwritten
, (int)write_through
));
4511 if (nwritten
< (ssize_t
)numtowrite
) {
4512 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4513 error_to_writebrawerr(req
);
4517 total_written
= nwritten
;
4519 /* Allocate a buffer of 64k + length. */
4520 buf
= talloc_array(NULL
, char, 65540);
4522 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4523 error_to_writebrawerr(req
);
4527 /* Return a SMBwritebraw message to the redirector to tell
4528 * it to send more bytes */
4530 memcpy(buf
, req
->inbuf
, smb_size
);
4531 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4532 SCVAL(buf
,smb_com
,SMBwritebraw
);
4533 SSVALS(buf
,smb_vwv0
,0xFFFF);
4535 if (!srv_send_smb(req
->xconn
,
4537 false, 0, /* no signing */
4538 IS_CONN_ENCRYPTED(conn
),
4540 exit_server_cleanly("reply_writebraw: srv_send_smb "
4544 /* Now read the raw data into the buffer and write it */
4545 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4547 if (!NT_STATUS_IS_OK(status
)) {
4548 exit_server_cleanly("secondary writebraw failed");
4551 /* Set up outbuf to return the correct size */
4552 reply_outbuf(req
, 1, 0);
4554 if (numtowrite
!= 0) {
4556 if (numtowrite
> 0xFFFF) {
4557 DEBUG(0,("reply_writebraw: Oversize secondary write "
4558 "raw requested (%u). Terminating\n",
4559 (unsigned int)numtowrite
));
4560 exit_server_cleanly("secondary writebraw failed");
4563 if (tcount
> nwritten
+numtowrite
) {
4564 DEBUG(3,("reply_writebraw: Client overestimated the "
4566 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4569 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4572 if (!NT_STATUS_IS_OK(status
)) {
4573 /* Try and give an error message
4574 * saying what client failed. */
4575 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4576 "raw read failed (%s) for client %s. "
4577 "Terminating\n", nt_errstr(status
),
4578 smbXsrv_connection_dbg(xconn
)));
4579 exit_server_cleanly("secondary writebraw failed");
4583 * We are not vulnerable to CVE-2017-12163
4584 * here as we are guarenteed to have numtowrite
4585 * bytes available - we just read from the client.
4587 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4588 if (nwritten
== -1) {
4590 reply_nterror(req
, map_nt_error_from_unix(errno
));
4591 error_to_writebrawerr(req
);
4595 if (nwritten
< (ssize_t
)numtowrite
) {
4596 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4597 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4601 total_written
+= nwritten
;
4606 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4608 status
= sync_file(conn
, fsp
, write_through
);
4609 if (!NT_STATUS_IS_OK(status
)) {
4610 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4611 fsp_str_dbg(fsp
), nt_errstr(status
)));
4612 reply_nterror(req
, status
);
4613 error_to_writebrawerr(req
);
4617 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4619 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4620 (int)total_written
));
4622 /* We won't return a status if write through is not selected - this
4623 * follows what WfWg does */
4624 END_PROFILE(SMBwritebraw
);
4626 if (!write_through
&& total_written
==tcount
) {
4628 #if RABBIT_PELLET_FIX
4630 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4631 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4634 if (!send_keepalive(xconn
->transport
.sock
)) {
4635 exit_server_cleanly("reply_writebraw: send of "
4636 "keepalive failed");
4639 TALLOC_FREE(req
->outbuf
);
4644 END_PROFILE(SMBwritebraw
);
4649 #define DBGC_CLASS DBGC_LOCKING
4651 /****************************************************************************
4652 Reply to a writeunlock (core+).
4653 ****************************************************************************/
4655 void reply_writeunlock(struct smb_request
*req
)
4657 connection_struct
*conn
= req
->conn
;
4658 ssize_t nwritten
= -1;
4663 NTSTATUS status
= NT_STATUS_OK
;
4665 struct lock_struct lock
;
4666 int saved_errno
= 0;
4668 START_PROFILE(SMBwriteunlock
);
4671 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4672 END_PROFILE(SMBwriteunlock
);
4676 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4678 if (!check_fsp(conn
, req
, fsp
)) {
4679 END_PROFILE(SMBwriteunlock
);
4683 if (!CHECK_WRITE(fsp
)) {
4684 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4685 END_PROFILE(SMBwriteunlock
);
4689 numtowrite
= SVAL(req
->vwv
+1, 0);
4690 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4691 data
= (const char *)req
->buf
+ 3;
4694 * Ensure client isn't asking us to write more than
4695 * they sent. CVE-2017-12163.
4697 remaining
= smbreq_bufrem(req
, data
);
4698 if (numtowrite
> remaining
) {
4699 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4700 END_PROFILE(SMBwriteunlock
);
4704 if (!fsp
->print_file
&& numtowrite
> 0) {
4705 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4706 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4709 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4710 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4711 END_PROFILE(SMBwriteunlock
);
4716 /* The special X/Open SMB protocol handling of
4717 zero length writes is *NOT* done for
4719 if(numtowrite
== 0) {
4722 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4723 saved_errno
= errno
;
4726 status
= sync_file(conn
, fsp
, False
/* write through */);
4727 if (!NT_STATUS_IS_OK(status
)) {
4728 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4729 fsp_str_dbg(fsp
), nt_errstr(status
)));
4730 reply_nterror(req
, status
);
4735 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4739 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4740 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4744 if (numtowrite
&& !fsp
->print_file
) {
4745 status
= do_unlock(req
->sconn
->msg_ctx
,
4747 (uint64_t)req
->smbpid
,
4748 (uint64_t)numtowrite
,
4752 if (NT_STATUS_V(status
)) {
4753 reply_nterror(req
, status
);
4758 reply_outbuf(req
, 1, 0);
4760 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4762 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4763 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4766 END_PROFILE(SMBwriteunlock
);
4771 #define DBGC_CLASS DBGC_ALL
4773 /****************************************************************************
4775 ****************************************************************************/
4777 void reply_write(struct smb_request
*req
)
4779 connection_struct
*conn
= req
->conn
;
4782 ssize_t nwritten
= -1;
4786 struct lock_struct lock
;
4788 int saved_errno
= 0;
4790 START_PROFILE(SMBwrite
);
4793 END_PROFILE(SMBwrite
);
4794 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4798 /* If it's an IPC, pass off the pipe handler. */
4800 reply_pipe_write(req
);
4801 END_PROFILE(SMBwrite
);
4805 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4807 if (!check_fsp(conn
, req
, fsp
)) {
4808 END_PROFILE(SMBwrite
);
4812 if (!CHECK_WRITE(fsp
)) {
4813 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4814 END_PROFILE(SMBwrite
);
4818 numtowrite
= SVAL(req
->vwv
+1, 0);
4819 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4820 data
= (const char *)req
->buf
+ 3;
4823 * Ensure client isn't asking us to write more than
4824 * they sent. CVE-2017-12163.
4826 remaining
= smbreq_bufrem(req
, data
);
4827 if (numtowrite
> remaining
) {
4828 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4829 END_PROFILE(SMBwrite
);
4833 if (!fsp
->print_file
) {
4834 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4835 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4838 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4839 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4840 END_PROFILE(SMBwrite
);
4846 * X/Open SMB protocol says that if smb_vwv1 is
4847 * zero then the file size should be extended or
4848 * truncated to the size given in smb_vwv[2-3].
4851 if(numtowrite
== 0) {
4853 * This is actually an allocate call, and set EOF. JRA.
4855 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4857 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4860 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4862 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4865 trigger_write_time_update_immediate(fsp
);
4867 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4870 status
= sync_file(conn
, fsp
, False
);
4871 if (!NT_STATUS_IS_OK(status
)) {
4872 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4873 fsp_str_dbg(fsp
), nt_errstr(status
)));
4874 reply_nterror(req
, status
);
4879 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4883 if((nwritten
== 0) && (numtowrite
!= 0)) {
4884 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4888 reply_outbuf(req
, 1, 0);
4890 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4892 if (nwritten
< (ssize_t
)numtowrite
) {
4893 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4894 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4897 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4900 END_PROFILE(SMBwrite
);
4904 /****************************************************************************
4905 Ensure a buffer is a valid writeX for recvfile purposes.
4906 ****************************************************************************/
4908 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4909 (2*14) + /* word count (including bcc) */ \
4912 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4913 const uint8_t *inbuf
)
4916 unsigned int doff
= 0;
4917 size_t len
= smb_len_large(inbuf
);
4919 struct smbXsrv_open
*op
= NULL
;
4920 struct files_struct
*fsp
= NULL
;
4923 if (is_encrypted_packet(inbuf
)) {
4924 /* Can't do this on encrypted
4929 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4933 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4934 CVAL(inbuf
,smb_wct
) != 14) {
4935 DEBUG(10,("is_valid_writeX_buffer: chained or "
4936 "invalid word length.\n"));
4940 fnum
= SVAL(inbuf
, smb_vwv2
);
4941 status
= smb1srv_open_lookup(xconn
,
4945 if (!NT_STATUS_IS_OK(status
)) {
4946 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4951 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4954 if (fsp
->conn
== NULL
) {
4955 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4959 if (IS_IPC(fsp
->conn
)) {
4960 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4963 if (IS_PRINT(fsp
->conn
)) {
4964 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4967 doff
= SVAL(inbuf
,smb_vwv11
);
4969 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4971 if (len
> doff
&& len
- doff
> 0xFFFF) {
4972 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4975 if (numtowrite
== 0) {
4976 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4980 /* Ensure the sizes match up. */
4981 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4982 /* no pad byte...old smbclient :-( */
4983 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4985 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4989 if (len
- doff
!= numtowrite
) {
4990 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4991 "len = %u, doff = %u, numtowrite = %u\n",
4994 (unsigned int)numtowrite
));
4998 DEBUG(10,("is_valid_writeX_buffer: true "
4999 "len = %u, doff = %u, numtowrite = %u\n",
5002 (unsigned int)numtowrite
));
5007 /****************************************************************************
5008 Reply to a write and X.
5009 ****************************************************************************/
5011 void reply_write_and_X(struct smb_request
*req
)
5013 connection_struct
*conn
= req
->conn
;
5014 struct smbXsrv_connection
*xconn
= req
->xconn
;
5016 struct lock_struct lock
;
5021 unsigned int smb_doff
;
5022 unsigned int smblen
;
5025 int saved_errno
= 0;
5027 START_PROFILE(SMBwriteX
);
5029 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5030 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5034 numtowrite
= SVAL(req
->vwv
+10, 0);
5035 smb_doff
= SVAL(req
->vwv
+11, 0);
5036 smblen
= smb_len(req
->inbuf
);
5038 if (req
->unread_bytes
> 0xFFFF ||
5039 (smblen
> smb_doff
&&
5040 smblen
- smb_doff
> 0xFFFF)) {
5041 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5044 if (req
->unread_bytes
) {
5045 /* Can't do a recvfile write on IPC$ */
5047 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5050 if (numtowrite
!= req
->unread_bytes
) {
5051 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5056 * This already protects us against CVE-2017-12163.
5058 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5059 smb_doff
+ numtowrite
> smblen
) {
5060 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5065 /* If it's an IPC, pass off the pipe handler. */
5067 if (req
->unread_bytes
) {
5068 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5071 reply_pipe_write_and_X(req
);
5075 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5076 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5077 write_through
= BITSETW(req
->vwv
+7,0);
5079 if (!check_fsp(conn
, req
, fsp
)) {
5083 if (!CHECK_WRITE(fsp
)) {
5084 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5088 data
= smb_base(req
->inbuf
) + smb_doff
;
5090 if(req
->wct
== 14) {
5092 * This is a large offset (64 bit) write.
5094 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5098 /* X/Open SMB protocol says that, unlike SMBwrite
5099 if the length is zero then NO truncation is
5100 done, just a write of zero. To truncate a file,
5103 if(numtowrite
== 0) {
5106 if (req
->unread_bytes
== 0) {
5107 status
= schedule_aio_write_and_X(conn
,
5114 if (NT_STATUS_IS_OK(status
)) {
5115 /* write scheduled - we're done. */
5118 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5119 /* Real error - report to client. */
5120 reply_nterror(req
, status
);
5123 /* NT_STATUS_RETRY - fall through to sync write. */
5126 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5127 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5130 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5131 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5135 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5136 saved_errno
= errno
;
5140 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5144 if((nwritten
== 0) && (numtowrite
!= 0)) {
5145 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5149 reply_outbuf(req
, 6, 0);
5150 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5151 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5152 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5153 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5155 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5156 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5158 status
= sync_file(conn
, fsp
, write_through
);
5159 if (!NT_STATUS_IS_OK(status
)) {
5160 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5161 fsp_str_dbg(fsp
), nt_errstr(status
)));
5162 reply_nterror(req
, status
);
5166 END_PROFILE(SMBwriteX
);
5170 if (req
->unread_bytes
) {
5171 /* writeX failed. drain socket. */
5172 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5173 req
->unread_bytes
) {
5174 smb_panic("failed to drain pending bytes");
5176 req
->unread_bytes
= 0;
5179 END_PROFILE(SMBwriteX
);
5183 /****************************************************************************
5185 ****************************************************************************/
5187 void reply_lseek(struct smb_request
*req
)
5189 connection_struct
*conn
= req
->conn
;
5195 START_PROFILE(SMBlseek
);
5198 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5199 END_PROFILE(SMBlseek
);
5203 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5205 if (!check_fsp(conn
, req
, fsp
)) {
5209 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5211 mode
= SVAL(req
->vwv
+1, 0) & 3;
5212 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5213 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5222 res
= fsp
->fh
->pos
+ startpos
;
5233 if (umode
== SEEK_END
) {
5234 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5235 if(errno
== EINVAL
) {
5236 off_t current_pos
= startpos
;
5238 if(fsp_stat(fsp
) == -1) {
5240 map_nt_error_from_unix(errno
));
5241 END_PROFILE(SMBlseek
);
5245 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5247 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5252 reply_nterror(req
, map_nt_error_from_unix(errno
));
5253 END_PROFILE(SMBlseek
);
5260 reply_outbuf(req
, 2, 0);
5261 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5263 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5264 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5266 END_PROFILE(SMBlseek
);
5270 /****************************************************************************
5272 ****************************************************************************/
5274 void reply_flush(struct smb_request
*req
)
5276 connection_struct
*conn
= req
->conn
;
5280 START_PROFILE(SMBflush
);
5283 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5287 fnum
= SVAL(req
->vwv
+0, 0);
5288 fsp
= file_fsp(req
, fnum
);
5290 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5295 file_sync_all(conn
);
5297 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5298 if (!NT_STATUS_IS_OK(status
)) {
5299 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5300 fsp_str_dbg(fsp
), nt_errstr(status
)));
5301 reply_nterror(req
, status
);
5302 END_PROFILE(SMBflush
);
5307 reply_outbuf(req
, 0, 0);
5309 DEBUG(3,("flush\n"));
5310 END_PROFILE(SMBflush
);
5314 /****************************************************************************
5316 conn POINTER CAN BE NULL HERE !
5317 ****************************************************************************/
5319 void reply_exit(struct smb_request
*req
)
5321 START_PROFILE(SMBexit
);
5323 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5325 reply_outbuf(req
, 0, 0);
5327 DEBUG(3,("exit\n"));
5329 END_PROFILE(SMBexit
);
5333 struct reply_close_state
{
5335 struct smb_request
*smbreq
;
5338 static void do_smb1_close(struct tevent_req
*req
);
5340 void reply_close(struct smb_request
*req
)
5342 connection_struct
*conn
= req
->conn
;
5343 NTSTATUS status
= NT_STATUS_OK
;
5344 files_struct
*fsp
= NULL
;
5345 START_PROFILE(SMBclose
);
5348 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5349 END_PROFILE(SMBclose
);
5353 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5356 * We can only use check_fsp if we know it's not a directory.
5359 if (!check_fsp_open(conn
, req
, fsp
)) {
5360 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5361 END_PROFILE(SMBclose
);
5365 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5366 fsp
->is_directory
? "directory" : "file",
5367 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5368 conn
->num_files_open
));
5370 if (!fsp
->is_directory
) {
5374 * Take care of any time sent in the close.
5377 t
= srv_make_unix_date3(req
->vwv
+1);
5378 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5381 if (fsp
->num_aio_requests
!= 0) {
5383 struct reply_close_state
*state
;
5385 DEBUG(10, ("closing with aio %u requests pending\n",
5386 fsp
->num_aio_requests
));
5389 * We depend on the aio_extra destructor to take care of this
5390 * close request once fsp->num_aio_request drops to 0.
5393 fsp
->deferred_close
= tevent_wait_send(
5394 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5395 if (fsp
->deferred_close
== NULL
) {
5396 status
= NT_STATUS_NO_MEMORY
;
5400 state
= talloc(fsp
, struct reply_close_state
);
5401 if (state
== NULL
) {
5402 TALLOC_FREE(fsp
->deferred_close
);
5403 status
= NT_STATUS_NO_MEMORY
;
5407 state
->smbreq
= talloc_move(fsp
, &req
);
5408 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5410 END_PROFILE(SMBclose
);
5415 * close_file() returns the unix errno if an error was detected on
5416 * close - normally this is due to a disk full error. If not then it
5417 * was probably an I/O error.
5420 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5422 if (!NT_STATUS_IS_OK(status
)) {
5423 reply_nterror(req
, status
);
5424 END_PROFILE(SMBclose
);
5428 reply_outbuf(req
, 0, 0);
5429 END_PROFILE(SMBclose
);
5433 static void do_smb1_close(struct tevent_req
*req
)
5435 struct reply_close_state
*state
= tevent_req_callback_data(
5436 req
, struct reply_close_state
);
5437 struct smb_request
*smbreq
;
5441 ret
= tevent_wait_recv(req
);
5444 DEBUG(10, ("tevent_wait_recv returned %s\n",
5447 * Continue anyway, this should never happen
5452 * fsp->smb2_close_request right now is a talloc grandchild of
5453 * fsp. When we close_file(fsp), it would go with it. No chance to
5456 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5458 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5459 if (NT_STATUS_IS_OK(status
)) {
5460 reply_outbuf(smbreq
, 0, 0);
5462 reply_nterror(smbreq
, status
);
5464 if (!srv_send_smb(smbreq
->xconn
,
5465 (char *)smbreq
->outbuf
,
5468 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5470 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5473 TALLOC_FREE(smbreq
);
5476 /****************************************************************************
5477 Reply to a writeclose (Core+ protocol).
5478 ****************************************************************************/
5480 void reply_writeclose(struct smb_request
*req
)
5482 connection_struct
*conn
= req
->conn
;
5485 ssize_t nwritten
= -1;
5486 NTSTATUS close_status
= NT_STATUS_OK
;
5489 struct timespec mtime
;
5491 struct lock_struct lock
;
5493 START_PROFILE(SMBwriteclose
);
5496 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5497 END_PROFILE(SMBwriteclose
);
5501 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5503 if (!check_fsp(conn
, req
, fsp
)) {
5504 END_PROFILE(SMBwriteclose
);
5507 if (!CHECK_WRITE(fsp
)) {
5508 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5509 END_PROFILE(SMBwriteclose
);
5513 numtowrite
= SVAL(req
->vwv
+1, 0);
5514 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5515 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5516 data
= (const char *)req
->buf
+ 1;
5519 * Ensure client isn't asking us to write more than
5520 * they sent. CVE-2017-12163.
5522 remaining
= smbreq_bufrem(req
, data
);
5523 if (numtowrite
> remaining
) {
5524 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5525 END_PROFILE(SMBwriteclose
);
5529 if (fsp
->print_file
== NULL
) {
5530 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5531 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5534 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5535 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5536 END_PROFILE(SMBwriteclose
);
5541 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5543 set_close_write_time(fsp
, mtime
);
5546 * More insanity. W2K only closes the file if writelen > 0.
5550 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5551 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5552 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5555 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5556 "file %s\n", fsp_str_dbg(fsp
)));
5557 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5561 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5562 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5566 if(!NT_STATUS_IS_OK(close_status
)) {
5567 reply_nterror(req
, close_status
);
5571 reply_outbuf(req
, 1, 0);
5573 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5577 END_PROFILE(SMBwriteclose
);
5582 #define DBGC_CLASS DBGC_LOCKING
5584 /****************************************************************************
5586 ****************************************************************************/
5588 void reply_lock(struct smb_request
*req
)
5590 connection_struct
*conn
= req
->conn
;
5591 uint64_t count
,offset
;
5594 struct byte_range_lock
*br_lck
= NULL
;
5596 START_PROFILE(SMBlock
);
5599 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5600 END_PROFILE(SMBlock
);
5604 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5606 if (!check_fsp(conn
, req
, fsp
)) {
5607 END_PROFILE(SMBlock
);
5611 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5612 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5614 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5615 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5617 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5619 (uint64_t)req
->smbpid
,
5624 False
, /* Non-blocking lock. */
5628 TALLOC_FREE(br_lck
);
5630 if (NT_STATUS_V(status
)) {
5631 reply_nterror(req
, status
);
5632 END_PROFILE(SMBlock
);
5636 reply_outbuf(req
, 0, 0);
5638 END_PROFILE(SMBlock
);
5642 /****************************************************************************
5644 ****************************************************************************/
5646 void reply_unlock(struct smb_request
*req
)
5648 connection_struct
*conn
= req
->conn
;
5649 uint64_t count
,offset
;
5653 START_PROFILE(SMBunlock
);
5656 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5657 END_PROFILE(SMBunlock
);
5661 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5663 if (!check_fsp(conn
, req
, fsp
)) {
5664 END_PROFILE(SMBunlock
);
5668 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5669 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5671 status
= do_unlock(req
->sconn
->msg_ctx
,
5673 (uint64_t)req
->smbpid
,
5678 if (NT_STATUS_V(status
)) {
5679 reply_nterror(req
, status
);
5680 END_PROFILE(SMBunlock
);
5684 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5685 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5687 reply_outbuf(req
, 0, 0);
5689 END_PROFILE(SMBunlock
);
5694 #define DBGC_CLASS DBGC_ALL
5696 /****************************************************************************
5698 conn POINTER CAN BE NULL HERE !
5699 ****************************************************************************/
5701 void reply_tdis(struct smb_request
*req
)
5704 connection_struct
*conn
= req
->conn
;
5705 struct smbXsrv_tcon
*tcon
;
5707 START_PROFILE(SMBtdis
);
5710 DEBUG(4,("Invalid connection in tdis\n"));
5711 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5712 END_PROFILE(SMBtdis
);
5720 * TODO: cancel all outstanding requests on the tcon
5722 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5723 if (!NT_STATUS_IS_OK(status
)) {
5724 DEBUG(0, ("reply_tdis: "
5725 "smbXsrv_tcon_disconnect() failed: %s\n",
5726 nt_errstr(status
)));
5728 * If we hit this case, there is something completely
5729 * wrong, so we better disconnect the transport connection.
5731 END_PROFILE(SMBtdis
);
5732 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5738 reply_outbuf(req
, 0, 0);
5739 END_PROFILE(SMBtdis
);
5743 /****************************************************************************
5745 conn POINTER CAN BE NULL HERE !
5746 ****************************************************************************/
5748 void reply_echo(struct smb_request
*req
)
5750 connection_struct
*conn
= req
->conn
;
5751 struct smb_perfcount_data local_pcd
;
5752 struct smb_perfcount_data
*cur_pcd
;
5756 START_PROFILE(SMBecho
);
5758 smb_init_perfcount_data(&local_pcd
);
5761 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5762 END_PROFILE(SMBecho
);
5766 smb_reverb
= SVAL(req
->vwv
+0, 0);
5768 reply_outbuf(req
, 1, req
->buflen
);
5770 /* copy any incoming data back out */
5771 if (req
->buflen
> 0) {
5772 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5775 if (smb_reverb
> 100) {
5776 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5780 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5782 /* this makes sure we catch the request pcd */
5783 if (seq_num
== smb_reverb
) {
5784 cur_pcd
= &req
->pcd
;
5786 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5787 cur_pcd
= &local_pcd
;
5790 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5792 show_msg((char *)req
->outbuf
);
5793 if (!srv_send_smb(req
->xconn
,
5794 (char *)req
->outbuf
,
5795 true, req
->seqnum
+1,
5796 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5798 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5801 DEBUG(3,("echo %d times\n", smb_reverb
));
5803 TALLOC_FREE(req
->outbuf
);
5805 END_PROFILE(SMBecho
);
5809 /****************************************************************************
5810 Reply to a printopen.
5811 ****************************************************************************/
5813 void reply_printopen(struct smb_request
*req
)
5815 connection_struct
*conn
= req
->conn
;
5819 START_PROFILE(SMBsplopen
);
5822 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5823 END_PROFILE(SMBsplopen
);
5827 if (!CAN_PRINT(conn
)) {
5828 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5829 END_PROFILE(SMBsplopen
);
5833 status
= file_new(req
, conn
, &fsp
);
5834 if(!NT_STATUS_IS_OK(status
)) {
5835 reply_nterror(req
, status
);
5836 END_PROFILE(SMBsplopen
);
5840 /* Open for exclusive use, write only. */
5841 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5843 if (!NT_STATUS_IS_OK(status
)) {
5844 file_free(req
, fsp
);
5845 reply_nterror(req
, status
);
5846 END_PROFILE(SMBsplopen
);
5850 reply_outbuf(req
, 1, 0);
5851 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5853 DEBUG(3,("openprint fd=%d %s\n",
5854 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5856 END_PROFILE(SMBsplopen
);
5860 /****************************************************************************
5861 Reply to a printclose.
5862 ****************************************************************************/
5864 void reply_printclose(struct smb_request
*req
)
5866 connection_struct
*conn
= req
->conn
;
5870 START_PROFILE(SMBsplclose
);
5873 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5874 END_PROFILE(SMBsplclose
);
5878 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5880 if (!check_fsp(conn
, req
, fsp
)) {
5881 END_PROFILE(SMBsplclose
);
5885 if (!CAN_PRINT(conn
)) {
5886 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5887 END_PROFILE(SMBsplclose
);
5891 DEBUG(3,("printclose fd=%d %s\n",
5892 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5894 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5896 if(!NT_STATUS_IS_OK(status
)) {
5897 reply_nterror(req
, status
);
5898 END_PROFILE(SMBsplclose
);
5902 reply_outbuf(req
, 0, 0);
5904 END_PROFILE(SMBsplclose
);
5908 /****************************************************************************
5909 Reply to a printqueue.
5910 ****************************************************************************/
5912 void reply_printqueue(struct smb_request
*req
)
5914 connection_struct
*conn
= req
->conn
;
5918 START_PROFILE(SMBsplretq
);
5921 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5922 END_PROFILE(SMBsplretq
);
5926 max_count
= SVAL(req
->vwv
+0, 0);
5927 start_index
= SVAL(req
->vwv
+1, 0);
5929 /* we used to allow the client to get the cnum wrong, but that
5930 is really quite gross and only worked when there was only
5931 one printer - I think we should now only accept it if they
5932 get it right (tridge) */
5933 if (!CAN_PRINT(conn
)) {
5934 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5935 END_PROFILE(SMBsplretq
);
5939 reply_outbuf(req
, 2, 3);
5940 SSVAL(req
->outbuf
,smb_vwv0
,0);
5941 SSVAL(req
->outbuf
,smb_vwv1
,0);
5942 SCVAL(smb_buf(req
->outbuf
),0,1);
5943 SSVAL(smb_buf(req
->outbuf
),1,0);
5945 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5946 start_index
, max_count
));
5949 TALLOC_CTX
*mem_ctx
= talloc_tos();
5952 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5953 struct rpc_pipe_client
*cli
= NULL
;
5954 struct dcerpc_binding_handle
*b
= NULL
;
5955 struct policy_handle handle
;
5956 struct spoolss_DevmodeContainer devmode_ctr
;
5957 union spoolss_JobInfo
*info
;
5959 uint32_t num_to_get
;
5963 ZERO_STRUCT(handle
);
5965 status
= rpc_pipe_open_interface(mem_ctx
,
5968 conn
->sconn
->remote_address
,
5969 conn
->sconn
->local_address
,
5970 conn
->sconn
->msg_ctx
,
5972 if (!NT_STATUS_IS_OK(status
)) {
5973 DEBUG(0, ("reply_printqueue: "
5974 "could not connect to spoolss: %s\n",
5975 nt_errstr(status
)));
5976 reply_nterror(req
, status
);
5979 b
= cli
->binding_handle
;
5981 ZERO_STRUCT(devmode_ctr
);
5983 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5986 SEC_FLAG_MAXIMUM_ALLOWED
,
5989 if (!NT_STATUS_IS_OK(status
)) {
5990 reply_nterror(req
, status
);
5993 if (!W_ERROR_IS_OK(werr
)) {
5994 reply_nterror(req
, werror_to_ntstatus(werr
));
5998 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
6006 if (!W_ERROR_IS_OK(werr
)) {
6007 reply_nterror(req
, werror_to_ntstatus(werr
));
6011 if (max_count
> 0) {
6012 first
= start_index
;
6014 first
= start_index
+ max_count
+ 1;
6017 if (first
>= count
) {
6020 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6023 for (i
= first
; i
< num_to_get
; i
++) {
6026 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6029 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6030 info
[i
].info2
.job_id
);
6032 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6038 srv_put_dos_date2(p
, 0, qtime
);
6039 SCVAL(p
, 4, qstatus
);
6040 SSVAL(p
, 5, qrapjobid
);
6041 SIVAL(p
, 7, info
[i
].info2
.size
);
6043 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6044 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6045 if (!NT_STATUS_IS_OK(status
)) {
6046 reply_nterror(req
, status
);
6049 if (message_push_blob(
6052 blob
, sizeof(blob
))) == -1) {
6053 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6059 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6060 SSVAL(req
->outbuf
,smb_vwv1
,
6061 (max_count
>0?first
+count
:first
-1));
6062 SCVAL(smb_buf(req
->outbuf
),0,1);
6063 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6067 DEBUG(3, ("%u entries returned in queue\n",
6071 if (b
&& is_valid_policy_hnd(&handle
)) {
6072 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6077 END_PROFILE(SMBsplretq
);
6081 /****************************************************************************
6082 Reply to a printwrite.
6083 ****************************************************************************/
6085 void reply_printwrite(struct smb_request
*req
)
6087 connection_struct
*conn
= req
->conn
;
6092 START_PROFILE(SMBsplwr
);
6095 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6096 END_PROFILE(SMBsplwr
);
6100 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6102 if (!check_fsp(conn
, req
, fsp
)) {
6103 END_PROFILE(SMBsplwr
);
6107 if (!fsp
->print_file
) {
6108 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6109 END_PROFILE(SMBsplwr
);
6113 if (!CHECK_WRITE(fsp
)) {
6114 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6115 END_PROFILE(SMBsplwr
);
6119 numtowrite
= SVAL(req
->buf
, 1);
6122 * This already protects us against CVE-2017-12163.
6124 if (req
->buflen
< numtowrite
+ 3) {
6125 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6126 END_PROFILE(SMBsplwr
);
6130 data
= (const char *)req
->buf
+ 3;
6132 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6133 reply_nterror(req
, map_nt_error_from_unix(errno
));
6134 END_PROFILE(SMBsplwr
);
6138 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6140 END_PROFILE(SMBsplwr
);
6144 /****************************************************************************
6146 ****************************************************************************/
6148 void reply_mkdir(struct smb_request
*req
)
6150 connection_struct
*conn
= req
->conn
;
6151 struct smb_filename
*smb_dname
= NULL
;
6152 char *directory
= NULL
;
6155 TALLOC_CTX
*ctx
= talloc_tos();
6157 START_PROFILE(SMBmkdir
);
6159 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6160 STR_TERMINATE
, &status
);
6161 if (!NT_STATUS_IS_OK(status
)) {
6162 reply_nterror(req
, status
);
6166 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
6167 status
= filename_convert(ctx
, conn
,
6172 if (!NT_STATUS_IS_OK(status
)) {
6173 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6174 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6175 ERRSRV
, ERRbadpath
);
6178 reply_nterror(req
, status
);
6182 status
= create_directory(conn
, req
, smb_dname
);
6184 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6186 if (!NT_STATUS_IS_OK(status
)) {
6188 if (!use_nt_status()
6189 && NT_STATUS_EQUAL(status
,
6190 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6192 * Yes, in the DOS error code case we get a
6193 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6194 * samba4 torture test.
6196 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6199 reply_nterror(req
, status
);
6203 reply_outbuf(req
, 0, 0);
6205 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6207 TALLOC_FREE(smb_dname
);
6208 END_PROFILE(SMBmkdir
);
6212 /****************************************************************************
6214 ****************************************************************************/
6216 void reply_rmdir(struct smb_request
*req
)
6218 connection_struct
*conn
= req
->conn
;
6219 struct smb_filename
*smb_dname
= NULL
;
6220 char *directory
= NULL
;
6222 TALLOC_CTX
*ctx
= talloc_tos();
6223 files_struct
*fsp
= NULL
;
6225 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6226 struct smbd_server_connection
*sconn
= req
->sconn
;
6228 START_PROFILE(SMBrmdir
);
6230 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6231 STR_TERMINATE
, &status
);
6232 if (!NT_STATUS_IS_OK(status
)) {
6233 reply_nterror(req
, status
);
6237 status
= filename_convert(ctx
, conn
,
6242 if (!NT_STATUS_IS_OK(status
)) {
6243 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6244 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6245 ERRSRV
, ERRbadpath
);
6248 reply_nterror(req
, status
);
6252 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6253 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6257 status
= SMB_VFS_CREATE_FILE(
6260 0, /* root_dir_fid */
6261 smb_dname
, /* fname */
6262 DELETE_ACCESS
, /* access_mask */
6263 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6265 FILE_OPEN
, /* create_disposition*/
6266 FILE_DIRECTORY_FILE
, /* create_options */
6267 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6268 0, /* oplock_request */
6270 0, /* allocation_size */
6271 0, /* private_flags */
6276 NULL
, NULL
); /* create context */
6278 if (!NT_STATUS_IS_OK(status
)) {
6279 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6280 /* We have re-scheduled this call. */
6283 reply_nterror(req
, status
);
6287 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6288 if (!NT_STATUS_IS_OK(status
)) {
6289 close_file(req
, fsp
, ERROR_CLOSE
);
6290 reply_nterror(req
, status
);
6294 if (!set_delete_on_close(fsp
, true,
6295 conn
->session_info
->security_token
,
6296 conn
->session_info
->unix_token
)) {
6297 close_file(req
, fsp
, ERROR_CLOSE
);
6298 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6302 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6303 if (!NT_STATUS_IS_OK(status
)) {
6304 reply_nterror(req
, status
);
6306 reply_outbuf(req
, 0, 0);
6309 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6311 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6313 TALLOC_FREE(smb_dname
);
6314 END_PROFILE(SMBrmdir
);
6318 /*******************************************************************
6319 Resolve wildcards in a filename rename.
6320 ********************************************************************/
6322 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6327 char *name2_copy
= NULL
;
6332 char *p
,*p2
, *pname1
, *pname2
;
6334 name2_copy
= talloc_strdup(ctx
, name2
);
6339 pname1
= strrchr_m(name1
,'/');
6340 pname2
= strrchr_m(name2_copy
,'/');
6342 if (!pname1
|| !pname2
) {
6346 /* Truncate the copy of name2 at the last '/' */
6349 /* Now go past the '/' */
6353 root1
= talloc_strdup(ctx
, pname1
);
6354 root2
= talloc_strdup(ctx
, pname2
);
6356 if (!root1
|| !root2
) {
6360 p
= strrchr_m(root1
,'.');
6363 ext1
= talloc_strdup(ctx
, p
+1);
6365 ext1
= talloc_strdup(ctx
, "");
6367 p
= strrchr_m(root2
,'.');
6370 ext2
= talloc_strdup(ctx
, p
+1);
6372 ext2
= talloc_strdup(ctx
, "");
6375 if (!ext1
|| !ext2
) {
6383 /* Hmmm. Should this be mb-aware ? */
6386 } else if (*p2
== '*') {
6388 root2
= talloc_asprintf(ctx
, "%s%s",
6407 /* Hmmm. Should this be mb-aware ? */
6410 } else if (*p2
== '*') {
6412 ext2
= talloc_asprintf(ctx
, "%s%s",
6428 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6433 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6445 /****************************************************************************
6446 Ensure open files have their names updated. Updated to notify other smbd's
6448 ****************************************************************************/
6450 static void rename_open_files(connection_struct
*conn
,
6451 struct share_mode_lock
*lck
,
6453 uint32_t orig_name_hash
,
6454 const struct smb_filename
*smb_fname_dst
)
6457 bool did_rename
= False
;
6459 uint32_t new_name_hash
= 0;
6461 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6462 fsp
= file_find_di_next(fsp
)) {
6463 /* fsp_name is a relative path under the fsp. To change this for other
6464 sharepaths we need to manipulate relative paths. */
6465 /* TODO - create the absolute path and manipulate the newname
6466 relative to the sharepath. */
6467 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6470 if (fsp
->name_hash
!= orig_name_hash
) {
6473 DEBUG(10, ("rename_open_files: renaming file %s "
6474 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6475 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6476 smb_fname_str_dbg(smb_fname_dst
)));
6478 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6479 if (NT_STATUS_IS_OK(status
)) {
6481 new_name_hash
= fsp
->name_hash
;
6486 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6487 "for %s\n", file_id_string_tos(&id
),
6488 smb_fname_str_dbg(smb_fname_dst
)));
6491 /* Send messages to all smbd's (not ourself) that the name has changed. */
6492 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6493 orig_name_hash
, new_name_hash
,
6498 /****************************************************************************
6499 We need to check if the source path is a parent directory of the destination
6500 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6501 refuse the rename with a sharing violation. Under UNIX the above call can
6502 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6503 probably need to check that the client is a Windows one before disallowing
6504 this as a UNIX client (one with UNIX extensions) can know the source is a
6505 symlink and make this decision intelligently. Found by an excellent bug
6506 report from <AndyLiebman@aol.com>.
6507 ****************************************************************************/
6509 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6510 const struct smb_filename
*smb_fname_dst
)
6512 const char *psrc
= smb_fname_src
->base_name
;
6513 const char *pdst
= smb_fname_dst
->base_name
;
6516 if (psrc
[0] == '.' && psrc
[1] == '/') {
6519 if (pdst
[0] == '.' && pdst
[1] == '/') {
6522 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6525 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6529 * Do the notify calls from a rename
6532 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6533 const struct smb_filename
*smb_fname_src
,
6534 const struct smb_filename
*smb_fname_dst
)
6536 char *parent_dir_src
= NULL
;
6537 char *parent_dir_dst
= NULL
;
6540 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6541 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6543 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6544 &parent_dir_src
, NULL
) ||
6545 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6546 &parent_dir_dst
, NULL
)) {
6550 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6551 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6552 smb_fname_src
->base_name
);
6553 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6554 smb_fname_dst
->base_name
);
6557 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6558 smb_fname_src
->base_name
);
6559 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6560 smb_fname_dst
->base_name
);
6563 /* this is a strange one. w2k3 gives an additional event for
6564 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6565 files, but not directories */
6567 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6568 FILE_NOTIFY_CHANGE_ATTRIBUTES
6569 |FILE_NOTIFY_CHANGE_CREATION
,
6570 smb_fname_dst
->base_name
);
6573 TALLOC_FREE(parent_dir_src
);
6574 TALLOC_FREE(parent_dir_dst
);
6577 /****************************************************************************
6578 Returns an error if the parent directory for a filename is open in an
6580 ****************************************************************************/
6582 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6583 const struct smb_filename
*smb_fname_dst_in
)
6585 char *parent_dir
= NULL
;
6586 struct smb_filename smb_fname_parent
;
6588 files_struct
*fsp
= NULL
;
6591 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6592 &parent_dir
, NULL
)) {
6593 return NT_STATUS_NO_MEMORY
;
6595 ZERO_STRUCT(smb_fname_parent
);
6596 smb_fname_parent
.base_name
= parent_dir
;
6598 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6600 return map_nt_error_from_unix(errno
);
6604 * We're only checking on this smbd here, mostly good
6605 * enough.. and will pass tests.
6608 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6609 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6610 fsp
= file_find_di_next(fsp
)) {
6611 if (fsp
->access_mask
& DELETE_ACCESS
) {
6612 return NT_STATUS_SHARING_VIOLATION
;
6615 return NT_STATUS_OK
;
6618 /****************************************************************************
6619 Rename an open file - given an fsp.
6620 ****************************************************************************/
6622 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6624 const struct smb_filename
*smb_fname_dst_in
,
6626 bool replace_if_exists
)
6628 TALLOC_CTX
*ctx
= talloc_tos();
6629 struct smb_filename
*smb_fname_dst
= NULL
;
6630 NTSTATUS status
= NT_STATUS_OK
;
6631 struct share_mode_lock
*lck
= NULL
;
6632 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
6633 bool dst_exists
, old_is_stream
, new_is_stream
;
6635 status
= check_name(conn
, smb_fname_dst_in
);
6636 if (!NT_STATUS_IS_OK(status
)) {
6640 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6641 if (!NT_STATUS_IS_OK(status
)) {
6645 /* Make a copy of the dst smb_fname structs */
6647 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6648 if (smb_fname_dst
== NULL
) {
6649 status
= NT_STATUS_NO_MEMORY
;
6654 * Check for special case with case preserving and not
6655 * case sensitive. If the new last component differs from the original
6656 * last component only by case, then we should allow
6657 * the rename (user is trying to change the case of the
6660 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
6661 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6662 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6663 char *fname_dst_parent
= NULL
;
6664 const char *fname_dst_lcomp
= NULL
;
6665 char *orig_lcomp_path
= NULL
;
6666 char *orig_lcomp_stream
= NULL
;
6670 * Split off the last component of the processed
6671 * destination name. We will compare this to
6672 * the split components of smb_fname_dst->original_lcomp.
6674 if (!parent_dirname(ctx
,
6675 smb_fname_dst
->base_name
,
6677 &fname_dst_lcomp
)) {
6678 status
= NT_STATUS_NO_MEMORY
;
6683 * The original_lcomp component contains
6684 * the last_component of the path + stream
6685 * name (if a stream exists).
6687 * Split off the stream name so we
6688 * can check them separately.
6691 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
6692 /* POSIX - no stream component. */
6693 orig_lcomp_path
= talloc_strdup(ctx
,
6694 smb_fname_dst
->original_lcomp
);
6695 if (orig_lcomp_path
== NULL
) {
6699 ok
= split_stream_filename(ctx
,
6700 smb_fname_dst
->original_lcomp
,
6702 &orig_lcomp_stream
);
6706 TALLOC_FREE(fname_dst_parent
);
6707 status
= NT_STATUS_NO_MEMORY
;
6711 /* If the base names only differ by case, use original. */
6712 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
6715 * Replace the modified last component with the
6718 if (!ISDOT(fname_dst_parent
)) {
6719 tmp
= talloc_asprintf(smb_fname_dst
,
6724 tmp
= talloc_strdup(smb_fname_dst
,
6728 status
= NT_STATUS_NO_MEMORY
;
6729 TALLOC_FREE(fname_dst_parent
);
6730 TALLOC_FREE(orig_lcomp_path
);
6731 TALLOC_FREE(orig_lcomp_stream
);
6734 TALLOC_FREE(smb_fname_dst
->base_name
);
6735 smb_fname_dst
->base_name
= tmp
;
6738 /* If the stream_names only differ by case, use original. */
6739 if(!strcsequal(smb_fname_dst
->stream_name
,
6740 orig_lcomp_stream
)) {
6741 /* Use the original stream. */
6742 char *tmp
= talloc_strdup(smb_fname_dst
,
6745 status
= NT_STATUS_NO_MEMORY
;
6746 TALLOC_FREE(fname_dst_parent
);
6747 TALLOC_FREE(orig_lcomp_path
);
6748 TALLOC_FREE(orig_lcomp_stream
);
6751 TALLOC_FREE(smb_fname_dst
->stream_name
);
6752 smb_fname_dst
->stream_name
= tmp
;
6754 TALLOC_FREE(fname_dst_parent
);
6755 TALLOC_FREE(orig_lcomp_path
);
6756 TALLOC_FREE(orig_lcomp_stream
);
6760 * If the src and dest names are identical - including case,
6761 * don't do the rename, just return success.
6764 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6765 strcsequal(fsp
->fsp_name
->stream_name
,
6766 smb_fname_dst
->stream_name
)) {
6767 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6768 "- returning success\n",
6769 smb_fname_str_dbg(smb_fname_dst
)));
6770 status
= NT_STATUS_OK
;
6774 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6775 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6777 /* Return the correct error code if both names aren't streams. */
6778 if (!old_is_stream
&& new_is_stream
) {
6779 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6783 if (old_is_stream
&& !new_is_stream
) {
6784 status
= NT_STATUS_INVALID_PARAMETER
;
6788 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6790 if(!replace_if_exists
&& dst_exists
) {
6791 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6792 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6793 smb_fname_str_dbg(smb_fname_dst
)));
6794 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6799 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6800 &smb_fname_dst
->st
);
6801 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6803 /* The file can be open when renaming a stream */
6804 if (dst_fsp
&& !new_is_stream
) {
6805 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6806 status
= NT_STATUS_ACCESS_DENIED
;
6811 /* Ensure we have a valid stat struct for the source. */
6812 status
= vfs_stat_fsp(fsp
);
6813 if (!NT_STATUS_IS_OK(status
)) {
6817 status
= can_rename(conn
, fsp
, attrs
);
6819 if (!NT_STATUS_IS_OK(status
)) {
6820 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6821 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6822 smb_fname_str_dbg(smb_fname_dst
)));
6823 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6824 status
= NT_STATUS_ACCESS_DENIED
;
6828 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6829 status
= NT_STATUS_ACCESS_DENIED
;
6833 /* Do we have rights to move into the destination ? */
6834 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
6835 /* We're moving a directory. */
6836 access_mask
= SEC_DIR_ADD_SUBDIR
;
6838 status
= check_parent_access(conn
,
6841 if (!NT_STATUS_IS_OK(status
)) {
6842 DBG_INFO("check_parent_access on "
6843 "dst %s returned %s\n",
6844 smb_fname_str_dbg(smb_fname_dst
),
6849 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6852 * We have the file open ourselves, so not being able to get the
6853 * corresponding share mode lock is a fatal error.
6856 SMB_ASSERT(lck
!= NULL
);
6858 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6859 uint32_t create_options
= fsp
->fh
->private_options
;
6861 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6862 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6863 smb_fname_str_dbg(smb_fname_dst
)));
6865 if (!fsp
->is_directory
&&
6866 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
6867 (lp_map_archive(SNUM(conn
)) ||
6868 lp_store_dos_attributes(SNUM(conn
)))) {
6869 /* We must set the archive bit on the newly
6871 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6872 uint32_t old_dosmode
= dos_mode(conn
,
6874 file_set_dosmode(conn
,
6876 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6882 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6885 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6889 * A rename acts as a new file create w.r.t. allowing an initial delete
6890 * on close, probably because in Windows there is a new handle to the
6891 * new file. If initial delete on close was requested but not
6892 * originally set, we need to set it here. This is probably not 100% correct,
6893 * but will work for the CIFSFS client which in non-posix mode
6894 * depends on these semantics. JRA.
6897 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6898 status
= can_set_delete_on_close(fsp
, 0);
6900 if (NT_STATUS_IS_OK(status
)) {
6901 /* Note that here we set the *inital* delete on close flag,
6902 * not the regular one. The magic gets handled in close. */
6903 fsp
->initial_delete_on_close
= True
;
6907 status
= NT_STATUS_OK
;
6913 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6914 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6916 status
= map_nt_error_from_unix(errno
);
6919 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6920 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6921 smb_fname_str_dbg(smb_fname_dst
)));
6924 TALLOC_FREE(smb_fname_dst
);
6929 /****************************************************************************
6930 The guts of the rename command, split out so it may be called by the NT SMB
6932 ****************************************************************************/
6934 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6935 connection_struct
*conn
,
6936 struct smb_request
*req
,
6937 struct smb_filename
*smb_fname_src
,
6938 struct smb_filename
*smb_fname_dst
,
6940 bool replace_if_exists
,
6943 uint32_t access_mask
)
6945 char *fname_src_dir
= NULL
;
6946 struct smb_filename
*smb_fname_src_dir
= NULL
;
6947 char *fname_src_mask
= NULL
;
6949 NTSTATUS status
= NT_STATUS_OK
;
6950 struct smb_Dir
*dir_hnd
= NULL
;
6951 const char *dname
= NULL
;
6952 char *talloced
= NULL
;
6954 int create_options
= 0;
6955 bool posix_pathnames
= (req
!= NULL
&& req
->posix_pathnames
);
6959 * Split the old name into directory and last component
6960 * strings. Note that unix_convert may have stripped off a
6961 * leading ./ from both name and newname if the rename is
6962 * at the root of the share. We need to make sure either both
6963 * name and newname contain a / character or neither of them do
6964 * as this is checked in resolve_wildcards().
6967 /* Split up the directory from the filename/mask. */
6968 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6969 &fname_src_dir
, &fname_src_mask
);
6970 if (!NT_STATUS_IS_OK(status
)) {
6971 status
= NT_STATUS_NO_MEMORY
;
6976 * We should only check the mangled cache
6977 * here if unix_convert failed. This means
6978 * that the path in 'mask' doesn't exist
6979 * on the file system and so we need to look
6980 * for a possible mangle. This patch from
6981 * Tine Smukavec <valentin.smukavec@hermes.si>.
6984 if (!VALID_STAT(smb_fname_src
->st
) &&
6985 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6986 char *new_mask
= NULL
;
6987 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6990 TALLOC_FREE(fname_src_mask
);
6991 fname_src_mask
= new_mask
;
6995 if (!src_has_wild
) {
6999 * Only one file needs to be renamed. Append the mask back
7000 * onto the directory.
7002 TALLOC_FREE(smb_fname_src
->base_name
);
7003 if (ISDOT(fname_src_dir
)) {
7004 /* Ensure we use canonical names on open. */
7005 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7009 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7014 if (!smb_fname_src
->base_name
) {
7015 status
= NT_STATUS_NO_MEMORY
;
7019 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7020 "case_preserve = %d, short case preserve = %d, "
7021 "directory = %s, newname = %s, "
7022 "last_component_dest = %s\n",
7023 conn
->case_sensitive
, conn
->case_preserve
,
7024 conn
->short_case_preserve
,
7025 smb_fname_str_dbg(smb_fname_src
),
7026 smb_fname_str_dbg(smb_fname_dst
),
7027 smb_fname_dst
->original_lcomp
));
7029 /* The dest name still may have wildcards. */
7030 if (dest_has_wild
) {
7031 char *fname_dst_mod
= NULL
;
7032 if (!resolve_wildcards(smb_fname_dst
,
7033 smb_fname_src
->base_name
,
7034 smb_fname_dst
->base_name
,
7036 DEBUG(6, ("rename_internals: resolve_wildcards "
7038 smb_fname_src
->base_name
,
7039 smb_fname_dst
->base_name
));
7040 status
= NT_STATUS_NO_MEMORY
;
7043 TALLOC_FREE(smb_fname_dst
->base_name
);
7044 smb_fname_dst
->base_name
= fname_dst_mod
;
7047 ZERO_STRUCT(smb_fname_src
->st
);
7048 if (posix_pathnames
) {
7049 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
7051 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
7054 status
= map_nt_error_from_unix_common(errno
);
7058 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7059 create_options
|= FILE_DIRECTORY_FILE
;
7062 status
= SMB_VFS_CREATE_FILE(
7065 0, /* root_dir_fid */
7066 smb_fname_src
, /* fname */
7067 access_mask
, /* access_mask */
7068 (FILE_SHARE_READ
| /* share_access */
7070 FILE_OPEN
, /* create_disposition*/
7071 create_options
, /* create_options */
7072 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7073 0, /* oplock_request */
7075 0, /* allocation_size */
7076 0, /* private_flags */
7081 NULL
, NULL
); /* create context */
7083 if (!NT_STATUS_IS_OK(status
)) {
7084 DEBUG(3, ("Could not open rename source %s: %s\n",
7085 smb_fname_str_dbg(smb_fname_src
),
7086 nt_errstr(status
)));
7090 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7091 attrs
, replace_if_exists
);
7093 close_file(req
, fsp
, NORMAL_CLOSE
);
7095 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7096 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
7097 smb_fname_str_dbg(smb_fname_dst
)));
7103 * Wildcards - process each file that matches.
7105 if (strequal(fname_src_mask
, "????????.???")) {
7106 TALLOC_FREE(fname_src_mask
);
7107 fname_src_mask
= talloc_strdup(ctx
, "*");
7108 if (!fname_src_mask
) {
7109 status
= NT_STATUS_NO_MEMORY
;
7114 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7118 smb_fname_src
->flags
);
7119 if (smb_fname_src_dir
== NULL
) {
7120 status
= NT_STATUS_NO_MEMORY
;
7124 status
= check_name(conn
, smb_fname_src_dir
);
7125 if (!NT_STATUS_IS_OK(status
)) {
7129 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
7131 if (dir_hnd
== NULL
) {
7132 status
= map_nt_error_from_unix(errno
);
7136 status
= NT_STATUS_NO_SUCH_FILE
;
7138 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7139 * - gentest fix. JRA
7142 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
7144 files_struct
*fsp
= NULL
;
7145 char *destname
= NULL
;
7146 bool sysdir_entry
= False
;
7148 /* Quick check for "." and ".." */
7149 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7150 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
7151 sysdir_entry
= True
;
7153 TALLOC_FREE(talloced
);
7158 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7159 &smb_fname_src
->st
, false)) {
7160 TALLOC_FREE(talloced
);
7164 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
7165 TALLOC_FREE(talloced
);
7170 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7174 TALLOC_FREE(smb_fname_src
->base_name
);
7175 if (ISDOT(fname_src_dir
)) {
7176 /* Ensure we use canonical names on open. */
7177 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7181 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7186 if (!smb_fname_src
->base_name
) {
7187 status
= NT_STATUS_NO_MEMORY
;
7191 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7192 smb_fname_dst
->base_name
,
7194 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7195 smb_fname_src
->base_name
, destname
));
7196 TALLOC_FREE(talloced
);
7200 status
= NT_STATUS_NO_MEMORY
;
7204 TALLOC_FREE(smb_fname_dst
->base_name
);
7205 smb_fname_dst
->base_name
= destname
;
7207 ZERO_STRUCT(smb_fname_src
->st
);
7208 if (posix_pathnames
) {
7209 SMB_VFS_LSTAT(conn
, smb_fname_src
);
7211 SMB_VFS_STAT(conn
, smb_fname_src
);
7216 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7217 create_options
|= FILE_DIRECTORY_FILE
;
7220 status
= SMB_VFS_CREATE_FILE(
7223 0, /* root_dir_fid */
7224 smb_fname_src
, /* fname */
7225 access_mask
, /* access_mask */
7226 (FILE_SHARE_READ
| /* share_access */
7228 FILE_OPEN
, /* create_disposition*/
7229 create_options
, /* create_options */
7230 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7231 0, /* oplock_request */
7233 0, /* allocation_size */
7234 0, /* private_flags */
7239 NULL
, NULL
); /* create context */
7241 if (!NT_STATUS_IS_OK(status
)) {
7242 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7243 "returned %s rename %s -> %s\n",
7245 smb_fname_str_dbg(smb_fname_src
),
7246 smb_fname_str_dbg(smb_fname_dst
)));
7250 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7252 if (!smb_fname_dst
->original_lcomp
) {
7253 status
= NT_STATUS_NO_MEMORY
;
7257 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7258 attrs
, replace_if_exists
);
7260 close_file(req
, fsp
, NORMAL_CLOSE
);
7262 if (!NT_STATUS_IS_OK(status
)) {
7263 DEBUG(3, ("rename_internals_fsp returned %s for "
7264 "rename %s -> %s\n", nt_errstr(status
),
7265 smb_fname_str_dbg(smb_fname_src
),
7266 smb_fname_str_dbg(smb_fname_dst
)));
7272 DEBUG(3,("rename_internals: doing rename on %s -> "
7273 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7274 smb_fname_str_dbg(smb_fname_src
)));
7275 TALLOC_FREE(talloced
);
7277 TALLOC_FREE(dir_hnd
);
7279 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7280 status
= map_nt_error_from_unix(errno
);
7284 TALLOC_FREE(talloced
);
7285 TALLOC_FREE(smb_fname_src_dir
);
7286 TALLOC_FREE(fname_src_dir
);
7287 TALLOC_FREE(fname_src_mask
);
7291 /****************************************************************************
7293 ****************************************************************************/
7295 void reply_mv(struct smb_request
*req
)
7297 connection_struct
*conn
= req
->conn
;
7299 char *newname
= NULL
;
7303 bool src_has_wcard
= False
;
7304 bool dest_has_wcard
= False
;
7305 TALLOC_CTX
*ctx
= talloc_tos();
7306 struct smb_filename
*smb_fname_src
= NULL
;
7307 struct smb_filename
*smb_fname_dst
= NULL
;
7308 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
) |
7309 (req
->posix_pathnames
?
7310 UCF_UNIX_NAME_LOOKUP
:
7311 UCF_COND_ALLOW_WCARD_LCOMP
);
7312 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
) |
7314 (req
->posix_pathnames
?
7316 UCF_COND_ALLOW_WCARD_LCOMP
);
7317 bool stream_rename
= false;
7319 START_PROFILE(SMBmv
);
7322 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7326 attrs
= SVAL(req
->vwv
+0, 0);
7328 p
= (const char *)req
->buf
+ 1;
7329 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7330 &status
, &src_has_wcard
);
7331 if (!NT_STATUS_IS_OK(status
)) {
7332 reply_nterror(req
, status
);
7336 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7337 &status
, &dest_has_wcard
);
7338 if (!NT_STATUS_IS_OK(status
)) {
7339 reply_nterror(req
, status
);
7343 if (!req
->posix_pathnames
) {
7344 /* The newname must begin with a ':' if the
7345 name contains a ':'. */
7346 if (strchr_m(name
, ':')) {
7347 if (newname
[0] != ':') {
7348 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7351 stream_rename
= true;
7355 status
= filename_convert(ctx
,
7362 if (!NT_STATUS_IS_OK(status
)) {
7363 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7364 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7365 ERRSRV
, ERRbadpath
);
7368 reply_nterror(req
, status
);
7372 status
= filename_convert(ctx
,
7379 if (!NT_STATUS_IS_OK(status
)) {
7380 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7381 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7382 ERRSRV
, ERRbadpath
);
7385 reply_nterror(req
, status
);
7389 if (stream_rename
) {
7390 /* smb_fname_dst->base_name must be the same as
7391 smb_fname_src->base_name. */
7392 TALLOC_FREE(smb_fname_dst
->base_name
);
7393 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7394 smb_fname_src
->base_name
);
7395 if (!smb_fname_dst
->base_name
) {
7396 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7401 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7402 smb_fname_str_dbg(smb_fname_dst
)));
7404 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7405 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7407 if (!NT_STATUS_IS_OK(status
)) {
7408 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7409 /* We have re-scheduled this call. */
7412 reply_nterror(req
, status
);
7416 reply_outbuf(req
, 0, 0);
7418 TALLOC_FREE(smb_fname_src
);
7419 TALLOC_FREE(smb_fname_dst
);
7424 /*******************************************************************
7425 Copy a file as part of a reply_copy.
7426 ******************************************************************/
7429 * TODO: check error codes on all callers
7432 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7433 connection_struct
*conn
,
7434 struct smb_filename
*smb_fname_src
,
7435 struct smb_filename
*smb_fname_dst
,
7438 bool target_is_directory
)
7440 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7442 files_struct
*fsp1
,*fsp2
;
7444 uint32_t new_create_disposition
;
7448 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7449 if (smb_fname_dst_tmp
== NULL
) {
7450 return NT_STATUS_NO_MEMORY
;
7454 * If the target is a directory, extract the last component from the
7455 * src filename and append it to the dst filename
7457 if (target_is_directory
) {
7460 /* dest/target can't be a stream if it's a directory. */
7461 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7463 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7467 p
= smb_fname_src
->base_name
;
7469 smb_fname_dst_tmp
->base_name
=
7470 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7472 if (!smb_fname_dst_tmp
->base_name
) {
7473 status
= NT_STATUS_NO_MEMORY
;
7478 status
= vfs_file_exist(conn
, smb_fname_src
);
7479 if (!NT_STATUS_IS_OK(status
)) {
7483 if (!target_is_directory
&& count
) {
7484 new_create_disposition
= FILE_OPEN
;
7486 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7489 &new_create_disposition
,
7492 status
= NT_STATUS_INVALID_PARAMETER
;
7497 /* Open the src file for reading. */
7498 status
= SMB_VFS_CREATE_FILE(
7501 0, /* root_dir_fid */
7502 smb_fname_src
, /* fname */
7503 FILE_GENERIC_READ
, /* access_mask */
7504 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7505 FILE_OPEN
, /* create_disposition*/
7506 0, /* create_options */
7507 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7508 INTERNAL_OPEN_ONLY
, /* oplock_request */
7510 0, /* allocation_size */
7511 0, /* private_flags */
7516 NULL
, NULL
); /* create context */
7518 if (!NT_STATUS_IS_OK(status
)) {
7522 dosattrs
= dos_mode(conn
, smb_fname_src
);
7524 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7525 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7528 /* Open the dst file for writing. */
7529 status
= SMB_VFS_CREATE_FILE(
7532 0, /* root_dir_fid */
7533 smb_fname_dst
, /* fname */
7534 FILE_GENERIC_WRITE
, /* access_mask */
7535 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7536 new_create_disposition
, /* create_disposition*/
7537 0, /* create_options */
7538 dosattrs
, /* file_attributes */
7539 INTERNAL_OPEN_ONLY
, /* oplock_request */
7541 0, /* allocation_size */
7542 0, /* private_flags */
7547 NULL
, NULL
); /* create context */
7549 if (!NT_STATUS_IS_OK(status
)) {
7550 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7554 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7555 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7557 DEBUG(0, ("error - vfs lseek returned error %s\n",
7559 status
= map_nt_error_from_unix(errno
);
7560 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7561 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7566 /* Do the actual copy. */
7567 if (smb_fname_src
->st
.st_ex_size
) {
7568 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7573 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7575 /* Ensure the modtime is set correctly on the destination file. */
7576 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7579 * As we are opening fsp1 read-only we only expect
7580 * an error on close on fsp2 if we are out of space.
7581 * Thus we don't look at the error return from the
7584 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7586 if (!NT_STATUS_IS_OK(status
)) {
7590 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7591 status
= NT_STATUS_DISK_FULL
;
7595 status
= NT_STATUS_OK
;
7598 TALLOC_FREE(smb_fname_dst_tmp
);
7602 /****************************************************************************
7603 Reply to a file copy.
7604 ****************************************************************************/
7606 void reply_copy(struct smb_request
*req
)
7608 connection_struct
*conn
= req
->conn
;
7609 struct smb_filename
*smb_fname_src
= NULL
;
7610 struct smb_filename
*smb_fname_src_dir
= NULL
;
7611 struct smb_filename
*smb_fname_dst
= NULL
;
7612 char *fname_src
= NULL
;
7613 char *fname_dst
= NULL
;
7614 char *fname_src_mask
= NULL
;
7615 char *fname_src_dir
= NULL
;
7618 int error
= ERRnoaccess
;
7622 bool target_is_directory
=False
;
7623 bool source_has_wild
= False
;
7624 bool dest_has_wild
= False
;
7626 uint32_t ucf_flags_src
= UCF_COND_ALLOW_WCARD_LCOMP
|
7627 ucf_flags_from_smb_request(req
);
7628 uint32_t ucf_flags_dst
= UCF_COND_ALLOW_WCARD_LCOMP
|
7629 ucf_flags_from_smb_request(req
);
7630 TALLOC_CTX
*ctx
= talloc_tos();
7632 START_PROFILE(SMBcopy
);
7635 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7639 tid2
= SVAL(req
->vwv
+0, 0);
7640 ofun
= SVAL(req
->vwv
+1, 0);
7641 flags
= SVAL(req
->vwv
+2, 0);
7643 p
= (const char *)req
->buf
;
7644 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7645 &status
, &source_has_wild
);
7646 if (!NT_STATUS_IS_OK(status
)) {
7647 reply_nterror(req
, status
);
7650 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7651 &status
, &dest_has_wild
);
7652 if (!NT_STATUS_IS_OK(status
)) {
7653 reply_nterror(req
, status
);
7657 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7659 if (tid2
!= conn
->cnum
) {
7660 /* can't currently handle inter share copies XXXX */
7661 DEBUG(3,("Rejecting inter-share copy\n"));
7662 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7666 status
= filename_convert(ctx
, conn
,
7671 if (!NT_STATUS_IS_OK(status
)) {
7672 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7673 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7674 ERRSRV
, ERRbadpath
);
7677 reply_nterror(req
, status
);
7681 status
= filename_convert(ctx
, conn
,
7686 if (!NT_STATUS_IS_OK(status
)) {
7687 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7688 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7689 ERRSRV
, ERRbadpath
);
7692 reply_nterror(req
, status
);
7696 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7698 if ((flags
&1) && target_is_directory
) {
7699 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7703 if ((flags
&2) && !target_is_directory
) {
7704 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7708 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7709 /* wants a tree copy! XXXX */
7710 DEBUG(3,("Rejecting tree copy\n"));
7711 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7715 /* Split up the directory from the filename/mask. */
7716 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7717 &fname_src_dir
, &fname_src_mask
);
7718 if (!NT_STATUS_IS_OK(status
)) {
7719 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7724 * We should only check the mangled cache
7725 * here if unix_convert failed. This means
7726 * that the path in 'mask' doesn't exist
7727 * on the file system and so we need to look
7728 * for a possible mangle. This patch from
7729 * Tine Smukavec <valentin.smukavec@hermes.si>.
7731 if (!VALID_STAT(smb_fname_src
->st
) &&
7732 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7733 char *new_mask
= NULL
;
7734 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7735 &new_mask
, conn
->params
);
7737 /* Use demangled name if one was successfully found. */
7739 TALLOC_FREE(fname_src_mask
);
7740 fname_src_mask
= new_mask
;
7744 if (!source_has_wild
) {
7747 * Only one file needs to be copied. Append the mask back onto
7750 TALLOC_FREE(smb_fname_src
->base_name
);
7751 if (ISDOT(fname_src_dir
)) {
7752 /* Ensure we use canonical names on open. */
7753 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7757 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7762 if (!smb_fname_src
->base_name
) {
7763 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7767 if (dest_has_wild
) {
7768 char *fname_dst_mod
= NULL
;
7769 if (!resolve_wildcards(smb_fname_dst
,
7770 smb_fname_src
->base_name
,
7771 smb_fname_dst
->base_name
,
7773 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7776 TALLOC_FREE(smb_fname_dst
->base_name
);
7777 smb_fname_dst
->base_name
= fname_dst_mod
;
7780 status
= check_name(conn
, smb_fname_src
);
7781 if (!NT_STATUS_IS_OK(status
)) {
7782 reply_nterror(req
, status
);
7786 status
= check_name(conn
, smb_fname_dst
);
7787 if (!NT_STATUS_IS_OK(status
)) {
7788 reply_nterror(req
, status
);
7792 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7793 ofun
, count
, target_is_directory
);
7795 if(!NT_STATUS_IS_OK(status
)) {
7796 reply_nterror(req
, status
);
7802 struct smb_Dir
*dir_hnd
= NULL
;
7803 const char *dname
= NULL
;
7804 char *talloced
= NULL
;
7808 * There is a wildcard that requires us to actually read the
7809 * src dir and copy each file matching the mask to the dst.
7810 * Right now streams won't be copied, but this could
7811 * presumably be added with a nested loop for reach dir entry.
7813 SMB_ASSERT(!smb_fname_src
->stream_name
);
7814 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7816 smb_fname_src
->stream_name
= NULL
;
7817 smb_fname_dst
->stream_name
= NULL
;
7819 if (strequal(fname_src_mask
,"????????.???")) {
7820 TALLOC_FREE(fname_src_mask
);
7821 fname_src_mask
= talloc_strdup(ctx
, "*");
7822 if (!fname_src_mask
) {
7823 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7828 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7832 smb_fname_src
->flags
);
7833 if (smb_fname_src_dir
== NULL
) {
7834 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7838 status
= check_name(conn
, smb_fname_src_dir
);
7839 if (!NT_STATUS_IS_OK(status
)) {
7840 reply_nterror(req
, status
);
7844 dir_hnd
= OpenDir(ctx
,
7849 if (dir_hnd
== NULL
) {
7850 status
= map_nt_error_from_unix(errno
);
7851 reply_nterror(req
, status
);
7857 /* Iterate over the src dir copying each entry to the dst. */
7858 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7859 &smb_fname_src
->st
, &talloced
))) {
7860 char *destname
= NULL
;
7862 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7863 TALLOC_FREE(talloced
);
7867 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7868 &smb_fname_src
->st
, false)) {
7869 TALLOC_FREE(talloced
);
7873 if(!mask_match(dname
, fname_src_mask
,
7874 conn
->case_sensitive
)) {
7875 TALLOC_FREE(talloced
);
7879 error
= ERRnoaccess
;
7881 /* Get the src smb_fname struct setup. */
7882 TALLOC_FREE(smb_fname_src
->base_name
);
7883 if (ISDOT(fname_src_dir
)) {
7884 /* Ensure we use canonical names on open. */
7885 smb_fname_src
->base_name
=
7886 talloc_asprintf(smb_fname_src
, "%s",
7889 smb_fname_src
->base_name
=
7890 talloc_asprintf(smb_fname_src
, "%s/%s",
7891 fname_src_dir
, dname
);
7894 if (!smb_fname_src
->base_name
) {
7895 TALLOC_FREE(dir_hnd
);
7896 TALLOC_FREE(talloced
);
7897 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7901 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7902 smb_fname_dst
->base_name
,
7904 TALLOC_FREE(talloced
);
7908 TALLOC_FREE(dir_hnd
);
7909 TALLOC_FREE(talloced
);
7910 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7914 TALLOC_FREE(smb_fname_dst
->base_name
);
7915 smb_fname_dst
->base_name
= destname
;
7917 status
= check_name(conn
, smb_fname_src
);
7918 if (!NT_STATUS_IS_OK(status
)) {
7919 TALLOC_FREE(dir_hnd
);
7920 TALLOC_FREE(talloced
);
7921 reply_nterror(req
, status
);
7925 status
= check_name(conn
, smb_fname_dst
);
7926 if (!NT_STATUS_IS_OK(status
)) {
7927 TALLOC_FREE(dir_hnd
);
7928 TALLOC_FREE(talloced
);
7929 reply_nterror(req
, status
);
7933 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7934 smb_fname_src
->base_name
,
7935 smb_fname_dst
->base_name
));
7937 status
= copy_file(ctx
, conn
, smb_fname_src
,
7938 smb_fname_dst
, ofun
, count
,
7939 target_is_directory
);
7940 if (NT_STATUS_IS_OK(status
)) {
7944 TALLOC_FREE(talloced
);
7946 TALLOC_FREE(dir_hnd
);
7950 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7954 reply_outbuf(req
, 1, 0);
7955 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7957 TALLOC_FREE(smb_fname_src
);
7958 TALLOC_FREE(smb_fname_src_dir
);
7959 TALLOC_FREE(smb_fname_dst
);
7960 TALLOC_FREE(fname_src
);
7961 TALLOC_FREE(fname_dst
);
7962 TALLOC_FREE(fname_src_mask
);
7963 TALLOC_FREE(fname_src_dir
);
7965 END_PROFILE(SMBcopy
);
7970 #define DBGC_CLASS DBGC_LOCKING
7972 /****************************************************************************
7973 Get a lock pid, dealing with large count requests.
7974 ****************************************************************************/
7976 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7977 bool large_file_format
)
7979 if(!large_file_format
)
7980 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7982 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7985 /****************************************************************************
7986 Get a lock count, dealing with large count requests.
7987 ****************************************************************************/
7989 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7990 bool large_file_format
)
7994 if(!large_file_format
) {
7995 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7998 * No BVAL, this is reversed!
8000 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
8001 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
8007 /****************************************************************************
8008 Get a lock offset, dealing with large offset requests.
8009 ****************************************************************************/
8011 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
8012 bool large_file_format
)
8014 uint64_t offset
= 0;
8016 if(!large_file_format
) {
8017 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
8020 * No BVAL, this is reversed!
8022 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
8023 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
8029 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
8034 struct smbd_lock_element
*locks
,
8037 connection_struct
*conn
= req
->conn
;
8039 NTSTATUS status
= NT_STATUS_OK
;
8043 /* Setup the timeout in seconds. */
8045 if (!lp_blocking_locks(SNUM(conn
))) {
8049 for(i
= 0; i
< (int)num_locks
; i
++) {
8050 struct smbd_lock_element
*e
= &locks
[i
];
8052 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8053 "%llu, file %s timeout = %d\n",
8056 (unsigned long long)e
->smblctx
,
8060 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8061 struct blocking_lock_record
*blr
= NULL
;
8063 if (num_locks
> 1) {
8065 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8066 * if the lock vector contains one entry. When given multiple cancel
8067 * requests in a single PDU we expect the server to return an
8068 * error. Windows servers seem to accept the request but only
8069 * cancel the first lock.
8070 * JRA - Do what Windows does (tm) :-).
8074 /* MS-CIFS (2.2.4.32.1) behavior. */
8075 return NT_STATUS_DOS(ERRDOS
,
8076 ERRcancelviolation
);
8078 /* Windows behavior. */
8080 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8081 "cancel request\n"));
8087 if (lp_blocking_locks(SNUM(conn
))) {
8089 /* Schedule a message to ourselves to
8090 remove the blocking lock record and
8091 return the right error. */
8093 blr
= blocking_lock_cancel_smb1(fsp
,
8099 NT_STATUS_FILE_LOCK_CONFLICT
);
8101 return NT_STATUS_DOS(
8103 ERRcancelviolation
);
8106 /* Remove a matching pending lock. */
8107 status
= do_lock_cancel(fsp
,
8113 bool blocking_lock
= timeout
? true : false;
8114 bool defer_lock
= false;
8115 struct byte_range_lock
*br_lck
;
8116 uint64_t block_smblctx
;
8118 br_lck
= do_lock(req
->sconn
->msg_ctx
,
8129 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
8130 /* Windows internal resolution for blocking locks seems
8131 to be about 200ms... Don't wait for less than that. JRA. */
8132 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
8133 timeout
= lp_lock_spin_time();
8138 /* If a lock sent with timeout of zero would fail, and
8139 * this lock has been requested multiple times,
8140 * according to brl_lock_failed() we convert this
8141 * request to a blocking lock with a timeout of between
8142 * 150 - 300 milliseconds.
8144 * If lp_lock_spin_time() has been set to 0, we skip
8145 * this blocking retry and fail immediately.
8147 * Replacement for do_lock_spin(). JRA. */
8149 if (!req
->sconn
->using_smb2
&&
8150 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
8151 lp_lock_spin_time() && !blocking_lock
&&
8152 NT_STATUS_EQUAL((status
),
8153 NT_STATUS_FILE_LOCK_CONFLICT
))
8156 timeout
= lp_lock_spin_time();
8159 if (br_lck
&& defer_lock
) {
8161 * A blocking lock was requested. Package up
8162 * this smb into a queued request and push it
8163 * onto the blocking lock queue.
8165 if(push_blocking_lock_request(br_lck
,
8176 TALLOC_FREE(br_lck
);
8178 return NT_STATUS_OK
;
8182 TALLOC_FREE(br_lck
);
8185 if (!NT_STATUS_IS_OK(status
)) {
8190 /* If any of the above locks failed, then we must unlock
8191 all of the previous locks (X/Open spec). */
8193 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
8195 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8196 i
= -1; /* we want to skip the for loop */
8200 * Ensure we don't do a remove on the lock that just failed,
8201 * as under POSIX rules, if we have a lock already there, we
8202 * will delete it (and we shouldn't) .....
8204 for(i
--; i
>= 0; i
--) {
8205 struct smbd_lock_element
*e
= &locks
[i
];
8207 do_unlock(req
->sconn
->msg_ctx
,
8217 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8218 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
8220 return NT_STATUS_OK
;
8223 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
8225 uint16_t num_ulocks
,
8226 struct smbd_lock_element
*ulocks
)
8230 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8231 struct smbd_lock_element
*e
= &ulocks
[i
];
8234 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8235 "pid %u, file %s\n", __func__
,
8238 (unsigned int)e
->smblctx
,
8241 if (e
->brltype
!= UNLOCK_LOCK
) {
8242 /* this can only happen with SMB2 */
8243 return NT_STATUS_INVALID_PARAMETER
;
8246 status
= do_unlock(req
->sconn
->msg_ctx
,
8253 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
8254 nt_errstr(status
)));
8256 if (!NT_STATUS_IS_OK(status
)) {
8261 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
8264 return NT_STATUS_OK
;
8267 /****************************************************************************
8268 Reply to a lockingX request.
8269 ****************************************************************************/
8271 void reply_lockingX(struct smb_request
*req
)
8273 connection_struct
*conn
= req
->conn
;
8275 unsigned char locktype
;
8276 unsigned char oplocklevel
;
8277 uint16_t num_ulocks
;
8279 int32_t lock_timeout
;
8281 const uint8_t *data
;
8282 bool large_file_format
;
8283 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8284 struct smbd_lock_element
*ulocks
;
8285 struct smbd_lock_element
*locks
;
8288 START_PROFILE(SMBlockingX
);
8291 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8292 END_PROFILE(SMBlockingX
);
8296 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8297 locktype
= CVAL(req
->vwv
+3, 0);
8298 oplocklevel
= CVAL(req
->vwv
+3, 1);
8299 num_ulocks
= SVAL(req
->vwv
+6, 0);
8300 num_locks
= SVAL(req
->vwv
+7, 0);
8301 lock_timeout
= IVAL(req
->vwv
+4, 0);
8302 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8304 if (!check_fsp(conn
, req
, fsp
)) {
8305 END_PROFILE(SMBlockingX
);
8311 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8312 /* we don't support these - and CANCEL_LOCK makes w2k
8313 and XP reboot so I don't really want to be
8314 compatible! (tridge) */
8315 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8316 END_PROFILE(SMBlockingX
);
8320 /* Check if this is an oplock break on a file
8321 we have granted an oplock on.
8323 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8324 /* Client can insist on breaking to none. */
8325 bool break_to_none
= (oplocklevel
== 0);
8328 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8329 "for %s\n", (unsigned int)oplocklevel
,
8330 fsp_fnum_dbg(fsp
)));
8333 * Make sure we have granted an exclusive or batch oplock on
8337 if (fsp
->oplock_type
== 0) {
8339 /* The Samba4 nbench simulator doesn't understand
8340 the difference between break to level2 and break
8341 to none from level2 - it sends oplock break
8342 replies in both cases. Don't keep logging an error
8343 message here - just ignore it. JRA. */
8345 DEBUG(5,("reply_lockingX: Error : oplock break from "
8346 "client for %s (oplock=%d) and no "
8347 "oplock granted on this file (%s).\n",
8348 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8351 /* if this is a pure oplock break request then don't
8353 if (num_locks
== 0 && num_ulocks
== 0) {
8354 END_PROFILE(SMBlockingX
);
8357 END_PROFILE(SMBlockingX
);
8358 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8363 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8365 result
= remove_oplock(fsp
);
8367 result
= downgrade_oplock(fsp
);
8371 DEBUG(0, ("reply_lockingX: error in removing "
8372 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8373 /* Hmmm. Is this panic justified? */
8374 smb_panic("internal tdb error");
8377 /* if this is a pure oplock break request then don't send a
8379 if (num_locks
== 0 && num_ulocks
== 0) {
8380 /* Sanity check - ensure a pure oplock break is not a
8382 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8383 DEBUG(0,("reply_lockingX: Error : pure oplock "
8384 "break is a chained %d request !\n",
8385 (unsigned int)CVAL(req
->vwv
+0, 0)));
8387 END_PROFILE(SMBlockingX
);
8393 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8394 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8395 END_PROFILE(SMBlockingX
);
8399 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8400 if (ulocks
== NULL
) {
8401 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8402 END_PROFILE(SMBlockingX
);
8406 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8407 if (locks
== NULL
) {
8408 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8409 END_PROFILE(SMBlockingX
);
8413 /* Data now points at the beginning of the list
8414 of smb_unlkrng structs */
8415 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8416 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8417 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8418 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8419 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8422 /* Now do any requested locks */
8423 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8425 /* Data now points at the beginning of the list
8426 of smb_lkrng structs */
8428 for(i
= 0; i
< (int)num_locks
; i
++) {
8429 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8430 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8431 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8433 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8434 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8435 locks
[i
].brltype
= PENDING_READ_LOCK
;
8437 locks
[i
].brltype
= READ_LOCK
;
8440 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8441 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8443 locks
[i
].brltype
= WRITE_LOCK
;
8448 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8449 if (!NT_STATUS_IS_OK(status
)) {
8450 END_PROFILE(SMBlockingX
);
8451 reply_nterror(req
, status
);
8455 status
= smbd_do_locking(req
, fsp
,
8456 locktype
, lock_timeout
,
8459 if (!NT_STATUS_IS_OK(status
)) {
8460 END_PROFILE(SMBlockingX
);
8461 reply_nterror(req
, status
);
8465 END_PROFILE(SMBlockingX
);
8469 reply_outbuf(req
, 2, 0);
8470 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8471 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8473 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8474 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8476 END_PROFILE(SMBlockingX
);
8480 #define DBGC_CLASS DBGC_ALL
8482 /****************************************************************************
8483 Reply to a SMBreadbmpx (read block multiplex) request.
8484 Always reply with an error, if someone has a platform really needs this,
8485 please contact vl@samba.org
8486 ****************************************************************************/
8488 void reply_readbmpx(struct smb_request
*req
)
8490 START_PROFILE(SMBreadBmpx
);
8491 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8492 END_PROFILE(SMBreadBmpx
);
8496 /****************************************************************************
8497 Reply to a SMBreadbs (read block multiplex secondary) request.
8498 Always reply with an error, if someone has a platform really needs this,
8499 please contact vl@samba.org
8500 ****************************************************************************/
8502 void reply_readbs(struct smb_request
*req
)
8504 START_PROFILE(SMBreadBs
);
8505 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8506 END_PROFILE(SMBreadBs
);
8510 /****************************************************************************
8511 Reply to a SMBsetattrE.
8512 ****************************************************************************/
8514 void reply_setattrE(struct smb_request
*req
)
8516 connection_struct
*conn
= req
->conn
;
8517 struct smb_file_time ft
;
8521 START_PROFILE(SMBsetattrE
);
8525 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8529 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8531 if(!fsp
|| (fsp
->conn
!= conn
)) {
8532 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8537 * Convert the DOS times into unix times.
8540 ft
.atime
= convert_time_t_to_timespec(
8541 srv_make_unix_date2(req
->vwv
+3));
8542 ft
.mtime
= convert_time_t_to_timespec(
8543 srv_make_unix_date2(req
->vwv
+5));
8544 ft
.create_time
= convert_time_t_to_timespec(
8545 srv_make_unix_date2(req
->vwv
+1));
8547 reply_outbuf(req
, 0, 0);
8550 * Patch from Ray Frush <frush@engr.colostate.edu>
8551 * Sometimes times are sent as zero - ignore them.
8554 /* Ensure we have a valid stat struct for the source. */
8555 status
= vfs_stat_fsp(fsp
);
8556 if (!NT_STATUS_IS_OK(status
)) {
8557 reply_nterror(req
, status
);
8561 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8562 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8566 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8567 if (!NT_STATUS_IS_OK(status
)) {
8568 reply_nterror(req
, status
);
8572 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8575 (unsigned int)ft
.atime
.tv_sec
,
8576 (unsigned int)ft
.mtime
.tv_sec
,
8577 (unsigned int)ft
.create_time
.tv_sec
8580 END_PROFILE(SMBsetattrE
);
8585 /* Back from the dead for OS/2..... JRA. */
8587 /****************************************************************************
8588 Reply to a SMBwritebmpx (write block multiplex primary) request.
8589 Always reply with an error, if someone has a platform really needs this,
8590 please contact vl@samba.org
8591 ****************************************************************************/
8593 void reply_writebmpx(struct smb_request
*req
)
8595 START_PROFILE(SMBwriteBmpx
);
8596 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8597 END_PROFILE(SMBwriteBmpx
);
8601 /****************************************************************************
8602 Reply to a SMBwritebs (write block multiplex secondary) request.
8603 Always reply with an error, if someone has a platform really needs this,
8604 please contact vl@samba.org
8605 ****************************************************************************/
8607 void reply_writebs(struct smb_request
*req
)
8609 START_PROFILE(SMBwriteBs
);
8610 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8611 END_PROFILE(SMBwriteBs
);
8615 /****************************************************************************
8616 Reply to a SMBgetattrE.
8617 ****************************************************************************/
8619 void reply_getattrE(struct smb_request
*req
)
8621 connection_struct
*conn
= req
->conn
;
8624 struct timespec create_ts
;
8626 START_PROFILE(SMBgetattrE
);
8629 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8630 END_PROFILE(SMBgetattrE
);
8634 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8636 if(!fsp
|| (fsp
->conn
!= conn
)) {
8637 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8638 END_PROFILE(SMBgetattrE
);
8642 /* Do an fstat on this file */
8644 reply_nterror(req
, map_nt_error_from_unix(errno
));
8645 END_PROFILE(SMBgetattrE
);
8649 mode
= dos_mode(conn
, fsp
->fsp_name
);
8652 * Convert the times into dos times. Set create
8653 * date to be last modify date as UNIX doesn't save
8657 reply_outbuf(req
, 11, 0);
8659 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8660 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8661 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8662 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8663 /* Should we check pending modtime here ? JRA */
8664 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8665 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8667 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8668 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8669 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8671 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8672 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8673 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8675 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8677 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8679 END_PROFILE(SMBgetattrE
);