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 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1905 dptr_init_search_op(dirptr
);
1907 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1908 char buf
[DIR_STRUCT_SIZE
];
1909 memcpy(buf
,status
,21);
1910 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1911 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1912 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1915 dptr_fill(sconn
, buf
+12,dptr_num
);
1916 if (dptr_zero(buf
+12) && (status_len
==0)) {
1921 if (message_push_blob(&req
->outbuf
,
1922 data_blob_const(buf
, sizeof(buf
)))
1924 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1929 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1930 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1932 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1934 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1935 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
1936 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
1937 check_descend
= True
;
1940 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1941 finished
= !get_dir_entry(ctx
,
1952 char buf
[DIR_STRUCT_SIZE
];
1953 memcpy(buf
,status
,21);
1954 if (!make_dir_struct(ctx
,
1960 convert_timespec_to_time_t(date
),
1961 !allow_long_path_components
)) {
1962 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1965 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1968 if (message_push_blob(&req
->outbuf
,
1969 data_blob_const(buf
, sizeof(buf
)))
1971 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1981 /* If we were called as SMBffirst with smb_search_id == NULL
1982 and no entries were found then return error and close dirptr
1985 if (numentries
== 0) {
1986 dptr_close(sconn
, &dptr_num
);
1987 } else if(expect_close
&& status_len
== 0) {
1988 /* Close the dptr - we know it's gone */
1989 dptr_close(sconn
, &dptr_num
);
1992 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1993 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1994 dptr_close(sconn
, &dptr_num
);
1997 if ((numentries
== 0) && !mask_contains_wcard
) {
1998 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
2002 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
2003 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
2004 SCVAL(smb_buf(req
->outbuf
),0,5);
2005 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
2007 /* The replies here are never long name. */
2008 SSVAL(req
->outbuf
, smb_flg2
,
2009 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
2010 if (!allow_long_path_components
) {
2011 SSVAL(req
->outbuf
, smb_flg2
,
2012 SVAL(req
->outbuf
, smb_flg2
)
2013 & (~FLAGS2_LONG_PATH_COMPONENTS
));
2016 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2017 SSVAL(req
->outbuf
, smb_flg2
,
2018 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
2020 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2021 smb_fn_name(req
->cmd
),
2028 TALLOC_FREE(directory
);
2030 TALLOC_FREE(smb_fname
);
2031 END_PROFILE(SMBsearch
);
2035 /****************************************************************************
2036 Reply to a fclose (stop directory search).
2037 ****************************************************************************/
2039 void reply_fclose(struct smb_request
*req
)
2047 bool path_contains_wcard
= False
;
2048 TALLOC_CTX
*ctx
= talloc_tos();
2049 struct smbd_server_connection
*sconn
= req
->sconn
;
2051 START_PROFILE(SMBfclose
);
2053 if (req
->posix_pathnames
) {
2054 reply_unknown_new(req
, req
->cmd
);
2055 END_PROFILE(SMBfclose
);
2059 p
= (const char *)req
->buf
+ 1;
2060 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
2061 &err
, &path_contains_wcard
);
2062 if (!NT_STATUS_IS_OK(err
)) {
2063 reply_nterror(req
, err
);
2064 END_PROFILE(SMBfclose
);
2068 status_len
= SVAL(p
,0);
2071 if (status_len
== 0) {
2072 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
2073 END_PROFILE(SMBfclose
);
2077 memcpy(status
,p
,21);
2079 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
2080 /* Close the dptr - we know it's gone */
2081 dptr_close(sconn
, &dptr_num
);
2084 reply_outbuf(req
, 1, 0);
2085 SSVAL(req
->outbuf
,smb_vwv0
,0);
2087 DEBUG(3,("search close\n"));
2089 END_PROFILE(SMBfclose
);
2093 /****************************************************************************
2095 ****************************************************************************/
2097 void reply_open(struct smb_request
*req
)
2099 connection_struct
*conn
= req
->conn
;
2100 struct smb_filename
*smb_fname
= NULL
;
2110 uint32_t access_mask
;
2111 uint32_t share_mode
;
2112 uint32_t create_disposition
;
2113 uint32_t create_options
= 0;
2114 uint32_t private_flags
= 0;
2117 TALLOC_CTX
*ctx
= talloc_tos();
2119 START_PROFILE(SMBopen
);
2122 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2126 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2127 deny_mode
= SVAL(req
->vwv
+0, 0);
2128 dos_attr
= SVAL(req
->vwv
+1, 0);
2130 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2131 STR_TERMINATE
, &status
);
2132 if (!NT_STATUS_IS_OK(status
)) {
2133 reply_nterror(req
, status
);
2137 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2138 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
2139 &share_mode
, &create_disposition
,
2140 &create_options
, &private_flags
)) {
2141 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2145 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2147 status
= filename_convert(ctx
,
2153 if (!NT_STATUS_IS_OK(status
)) {
2154 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2155 reply_botherror(req
,
2156 NT_STATUS_PATH_NOT_COVERED
,
2157 ERRSRV
, ERRbadpath
);
2160 reply_nterror(req
, status
);
2164 status
= SMB_VFS_CREATE_FILE(
2167 0, /* root_dir_fid */
2168 smb_fname
, /* fname */
2169 access_mask
, /* access_mask */
2170 share_mode
, /* share_access */
2171 create_disposition
, /* create_disposition*/
2172 create_options
, /* create_options */
2173 dos_attr
, /* file_attributes */
2174 oplock_request
, /* oplock_request */
2176 0, /* allocation_size */
2182 NULL
, NULL
); /* create context */
2184 if (!NT_STATUS_IS_OK(status
)) {
2185 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2186 /* We have re-scheduled this call. */
2189 reply_openerror(req
, status
);
2193 /* Ensure we're pointing at the correct stat struct. */
2194 TALLOC_FREE(smb_fname
);
2195 smb_fname
= fsp
->fsp_name
;
2197 size
= smb_fname
->st
.st_ex_size
;
2198 fattr
= dos_mode(conn
, smb_fname
);
2200 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2202 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2203 DEBUG(3,("attempt to open a directory %s\n",
2205 close_file(req
, fsp
, ERROR_CLOSE
);
2206 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2207 ERRDOS
, ERRnoaccess
);
2211 reply_outbuf(req
, 7, 0);
2212 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2213 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2214 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2215 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2217 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2219 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2220 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2222 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2223 SCVAL(req
->outbuf
,smb_flg
,
2224 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2227 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2228 SCVAL(req
->outbuf
,smb_flg
,
2229 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2232 END_PROFILE(SMBopen
);
2236 /****************************************************************************
2237 Reply to an open and X.
2238 ****************************************************************************/
2240 void reply_open_and_X(struct smb_request
*req
)
2242 connection_struct
*conn
= req
->conn
;
2243 struct smb_filename
*smb_fname
= NULL
;
2245 uint16_t open_flags
;
2248 /* Breakout the oplock request bits so we can set the
2249 reply bits separately. */
2250 int ex_oplock_request
;
2251 int core_oplock_request
;
2254 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2255 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2263 uint64_t allocation_size
;
2264 ssize_t retval
= -1;
2265 uint32_t access_mask
;
2266 uint32_t share_mode
;
2267 uint32_t create_disposition
;
2268 uint32_t create_options
= 0;
2269 uint32_t private_flags
= 0;
2271 TALLOC_CTX
*ctx
= talloc_tos();
2273 START_PROFILE(SMBopenX
);
2275 if (req
->wct
< 15) {
2276 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2280 open_flags
= SVAL(req
->vwv
+2, 0);
2281 deny_mode
= SVAL(req
->vwv
+3, 0);
2282 smb_attr
= SVAL(req
->vwv
+5, 0);
2283 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2284 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2285 oplock_request
= ex_oplock_request
| core_oplock_request
;
2286 smb_ofun
= SVAL(req
->vwv
+8, 0);
2287 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2289 /* If it's an IPC, pass off the pipe handler. */
2291 if (lp_nt_pipe_support()) {
2292 reply_open_pipe_and_X(conn
, req
);
2294 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2299 /* XXXX we need to handle passed times, sattr and flags */
2300 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2301 STR_TERMINATE
, &status
);
2302 if (!NT_STATUS_IS_OK(status
)) {
2303 reply_nterror(req
, status
);
2307 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2309 &access_mask
, &share_mode
,
2310 &create_disposition
,
2313 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2317 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2319 status
= filename_convert(ctx
,
2325 if (!NT_STATUS_IS_OK(status
)) {
2326 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2327 reply_botherror(req
,
2328 NT_STATUS_PATH_NOT_COVERED
,
2329 ERRSRV
, ERRbadpath
);
2332 reply_nterror(req
, status
);
2336 status
= SMB_VFS_CREATE_FILE(
2339 0, /* root_dir_fid */
2340 smb_fname
, /* fname */
2341 access_mask
, /* access_mask */
2342 share_mode
, /* share_access */
2343 create_disposition
, /* create_disposition*/
2344 create_options
, /* create_options */
2345 smb_attr
, /* file_attributes */
2346 oplock_request
, /* oplock_request */
2348 0, /* allocation_size */
2353 &smb_action
, /* pinfo */
2354 NULL
, NULL
); /* create context */
2356 if (!NT_STATUS_IS_OK(status
)) {
2357 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2358 /* We have re-scheduled this call. */
2361 reply_openerror(req
, status
);
2365 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2366 if the file is truncated or created. */
2367 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2368 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2369 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2370 close_file(req
, fsp
, ERROR_CLOSE
);
2371 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2374 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2376 close_file(req
, fsp
, ERROR_CLOSE
);
2377 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2380 status
= vfs_stat_fsp(fsp
);
2381 if (!NT_STATUS_IS_OK(status
)) {
2382 close_file(req
, fsp
, ERROR_CLOSE
);
2383 reply_nterror(req
, status
);
2388 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2389 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2390 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2391 close_file(req
, fsp
, ERROR_CLOSE
);
2392 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2396 /* If the caller set the extended oplock request bit
2397 and we granted one (by whatever means) - set the
2398 correct bit for extended oplock reply.
2401 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2402 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2405 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2406 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2409 /* If the caller set the core oplock request bit
2410 and we granted one (by whatever means) - set the
2411 correct bit for core oplock reply.
2414 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2415 reply_outbuf(req
, 19, 0);
2417 reply_outbuf(req
, 15, 0);
2420 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2421 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2423 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2424 SCVAL(req
->outbuf
, smb_flg
,
2425 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2428 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2429 SCVAL(req
->outbuf
, smb_flg
,
2430 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2433 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2434 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2435 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2436 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2438 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2440 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2441 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2442 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2444 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2445 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2449 TALLOC_FREE(smb_fname
);
2450 END_PROFILE(SMBopenX
);
2454 /****************************************************************************
2455 Reply to a SMBulogoffX.
2456 ****************************************************************************/
2458 void reply_ulogoffX(struct smb_request
*req
)
2460 struct smbd_server_connection
*sconn
= req
->sconn
;
2461 struct user_struct
*vuser
;
2462 struct smbXsrv_session
*session
= NULL
;
2465 START_PROFILE(SMBulogoffX
);
2467 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2470 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2471 (unsigned long long)req
->vuid
));
2473 req
->vuid
= UID_FIELD_INVALID
;
2474 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2475 END_PROFILE(SMBulogoffX
);
2479 session
= vuser
->session
;
2483 * TODO: cancel all outstanding requests on the session
2485 status
= smbXsrv_session_logoff(session
);
2486 if (!NT_STATUS_IS_OK(status
)) {
2487 DEBUG(0, ("reply_ulogoff: "
2488 "smbXsrv_session_logoff() failed: %s\n",
2489 nt_errstr(status
)));
2491 * If we hit this case, there is something completely
2492 * wrong, so we better disconnect the transport connection.
2494 END_PROFILE(SMBulogoffX
);
2495 exit_server(__location__
": smbXsrv_session_logoff failed");
2499 TALLOC_FREE(session
);
2501 reply_outbuf(req
, 2, 0);
2502 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2503 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2505 DEBUG(3, ("ulogoffX vuid=%llu\n",
2506 (unsigned long long)req
->vuid
));
2508 END_PROFILE(SMBulogoffX
);
2509 req
->vuid
= UID_FIELD_INVALID
;
2512 /****************************************************************************
2513 Reply to a mknew or a create.
2514 ****************************************************************************/
2516 void reply_mknew(struct smb_request
*req
)
2518 connection_struct
*conn
= req
->conn
;
2519 struct smb_filename
*smb_fname
= NULL
;
2522 struct smb_file_time ft
;
2524 int oplock_request
= 0;
2526 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2527 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2528 uint32_t create_disposition
;
2529 uint32_t create_options
= 0;
2531 TALLOC_CTX
*ctx
= talloc_tos();
2533 START_PROFILE(SMBcreate
);
2537 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2541 fattr
= SVAL(req
->vwv
+0, 0);
2542 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2544 if (req
->cmd
== SMBmknew
) {
2545 /* We should fail if file exists. */
2546 create_disposition
= FILE_CREATE
;
2548 /* Create if file doesn't exist, truncate if it does. */
2549 create_disposition
= FILE_OVERWRITE_IF
;
2553 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2555 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2556 STR_TERMINATE
, &status
);
2557 if (!NT_STATUS_IS_OK(status
)) {
2558 reply_nterror(req
, status
);
2562 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2563 status
= filename_convert(ctx
,
2569 if (!NT_STATUS_IS_OK(status
)) {
2570 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2571 reply_botherror(req
,
2572 NT_STATUS_PATH_NOT_COVERED
,
2573 ERRSRV
, ERRbadpath
);
2576 reply_nterror(req
, status
);
2580 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2581 DEBUG(0,("Attempt to create file (%s) with volid set - "
2582 "please report this\n",
2583 smb_fname_str_dbg(smb_fname
)));
2586 status
= SMB_VFS_CREATE_FILE(
2589 0, /* root_dir_fid */
2590 smb_fname
, /* fname */
2591 access_mask
, /* access_mask */
2592 share_mode
, /* share_access */
2593 create_disposition
, /* create_disposition*/
2594 create_options
, /* create_options */
2595 fattr
, /* file_attributes */
2596 oplock_request
, /* oplock_request */
2598 0, /* allocation_size */
2599 0, /* private_flags */
2604 NULL
, NULL
); /* create context */
2606 if (!NT_STATUS_IS_OK(status
)) {
2607 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2608 /* We have re-scheduled this call. */
2611 reply_openerror(req
, status
);
2615 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2616 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2617 if (!NT_STATUS_IS_OK(status
)) {
2618 END_PROFILE(SMBcreate
);
2622 reply_outbuf(req
, 1, 0);
2623 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2625 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2626 SCVAL(req
->outbuf
,smb_flg
,
2627 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2630 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2631 SCVAL(req
->outbuf
,smb_flg
,
2632 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2635 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2636 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2637 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2638 (unsigned int)fattr
));
2641 TALLOC_FREE(smb_fname
);
2642 END_PROFILE(SMBcreate
);
2646 /****************************************************************************
2647 Reply to a create temporary file.
2648 ****************************************************************************/
2650 void reply_ctemp(struct smb_request
*req
)
2652 connection_struct
*conn
= req
->conn
;
2653 struct smb_filename
*smb_fname
= NULL
;
2654 char *wire_name
= NULL
;
2663 TALLOC_CTX
*ctx
= talloc_tos();
2665 START_PROFILE(SMBctemp
);
2668 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2672 fattr
= SVAL(req
->vwv
+0, 0);
2673 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2675 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2676 STR_TERMINATE
, &status
);
2677 if (!NT_STATUS_IS_OK(status
)) {
2678 reply_nterror(req
, status
);
2682 for (i
= 0; i
< 10; i
++) {
2684 fname
= talloc_asprintf(ctx
,
2687 generate_random_str_list(ctx
, 5, "0123456789"));
2689 fname
= talloc_asprintf(ctx
,
2691 generate_random_str_list(ctx
, 5, "0123456789"));
2695 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2699 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2700 status
= filename_convert(ctx
, conn
,
2705 if (!NT_STATUS_IS_OK(status
)) {
2706 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2707 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2708 ERRSRV
, ERRbadpath
);
2711 reply_nterror(req
, status
);
2715 /* Create the file. */
2716 status
= SMB_VFS_CREATE_FILE(
2719 0, /* root_dir_fid */
2720 smb_fname
, /* fname */
2721 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2722 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2723 FILE_CREATE
, /* create_disposition*/
2724 0, /* create_options */
2725 fattr
, /* file_attributes */
2726 oplock_request
, /* oplock_request */
2728 0, /* allocation_size */
2729 0, /* private_flags */
2734 NULL
, NULL
); /* create context */
2736 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2738 TALLOC_FREE(smb_fname
);
2742 if (!NT_STATUS_IS_OK(status
)) {
2743 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2744 /* We have re-scheduled this call. */
2747 reply_openerror(req
, status
);
2755 /* Collision after 10 times... */
2756 reply_nterror(req
, status
);
2760 reply_outbuf(req
, 1, 0);
2761 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2763 /* the returned filename is relative to the directory */
2764 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2766 s
= fsp
->fsp_name
->base_name
;
2772 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2773 thing in the byte section. JRA */
2774 SSVALS(p
, 0, -1); /* what is this? not in spec */
2776 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2778 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2782 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2783 SCVAL(req
->outbuf
, smb_flg
,
2784 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2787 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2788 SCVAL(req
->outbuf
, smb_flg
,
2789 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2792 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2793 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2794 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2796 TALLOC_FREE(smb_fname
);
2797 TALLOC_FREE(wire_name
);
2798 END_PROFILE(SMBctemp
);
2802 /*******************************************************************
2803 Check if a user is allowed to rename a file.
2804 ********************************************************************/
2806 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2809 if (!CAN_WRITE(conn
)) {
2810 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2813 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2814 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2815 /* Only bother to read the DOS attribute if we might deny the
2816 rename on the grounds of attribute mismatch. */
2817 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2818 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2819 return NT_STATUS_NO_SUCH_FILE
;
2823 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2824 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
2825 return NT_STATUS_OK
;
2828 /* If no pathnames are open below this
2829 directory, allow the rename. */
2831 if (lp_strict_rename(SNUM(conn
))) {
2833 * Strict rename, check open file db.
2835 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
2836 return NT_STATUS_ACCESS_DENIED
;
2838 } else if (file_find_subpath(fsp
)) {
2840 * No strict rename, just look in local process.
2842 return NT_STATUS_ACCESS_DENIED
;
2844 return NT_STATUS_OK
;
2847 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2848 return NT_STATUS_OK
;
2851 return NT_STATUS_ACCESS_DENIED
;
2854 /*******************************************************************
2855 * unlink a file with all relevant access checks
2856 *******************************************************************/
2858 static NTSTATUS
do_unlink(connection_struct
*conn
,
2859 struct smb_request
*req
,
2860 struct smb_filename
*smb_fname
,
2865 uint32_t dirtype_orig
= dirtype
;
2868 bool posix_paths
= (req
!= NULL
&& req
->posix_pathnames
);
2870 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2871 smb_fname_str_dbg(smb_fname
),
2874 if (!CAN_WRITE(conn
)) {
2875 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2879 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2881 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2884 return map_nt_error_from_unix(errno
);
2887 fattr
= dos_mode(conn
, smb_fname
);
2889 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2890 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2893 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2895 return NT_STATUS_NO_SUCH_FILE
;
2898 if (!dir_check_ftype(fattr
, dirtype
)) {
2899 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2900 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2902 return NT_STATUS_NO_SUCH_FILE
;
2905 if (dirtype_orig
& 0x8000) {
2906 /* These will never be set for POSIX. */
2907 return NT_STATUS_NO_SUCH_FILE
;
2911 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2912 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2915 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2916 return NT_STATUS_NO_SUCH_FILE
;
2919 if (dirtype
& 0xFF00) {
2920 /* These will never be set for POSIX. */
2921 return NT_STATUS_NO_SUCH_FILE
;
2926 return NT_STATUS_NO_SUCH_FILE
;
2929 /* Can't delete a directory. */
2930 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2931 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2936 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2937 return NT_STATUS_OBJECT_NAME_INVALID
;
2938 #endif /* JRATEST */
2940 /* On open checks the open itself will check the share mode, so
2941 don't do it here as we'll get it wrong. */
2943 status
= SMB_VFS_CREATE_FILE
2946 0, /* root_dir_fid */
2947 smb_fname
, /* fname */
2948 DELETE_ACCESS
, /* access_mask */
2949 FILE_SHARE_NONE
, /* share_access */
2950 FILE_OPEN
, /* create_disposition*/
2951 FILE_NON_DIRECTORY_FILE
, /* create_options */
2952 /* file_attributes */
2953 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2954 FILE_ATTRIBUTE_NORMAL
,
2955 0, /* oplock_request */
2957 0, /* allocation_size */
2958 0, /* private_flags */
2963 NULL
, NULL
); /* create context */
2965 if (!NT_STATUS_IS_OK(status
)) {
2966 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2967 nt_errstr(status
)));
2971 status
= can_set_delete_on_close(fsp
, fattr
);
2972 if (!NT_STATUS_IS_OK(status
)) {
2973 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2975 smb_fname_str_dbg(smb_fname
),
2976 nt_errstr(status
)));
2977 close_file(req
, fsp
, NORMAL_CLOSE
);
2981 /* The set is across all open files on this dev/inode pair. */
2982 if (!set_delete_on_close(fsp
, True
,
2983 conn
->session_info
->security_token
,
2984 conn
->session_info
->unix_token
)) {
2985 close_file(req
, fsp
, NORMAL_CLOSE
);
2986 return NT_STATUS_ACCESS_DENIED
;
2989 return close_file(req
, fsp
, NORMAL_CLOSE
);
2992 /****************************************************************************
2993 The guts of the unlink command, split out so it may be called by the NT SMB
2995 ****************************************************************************/
2997 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2998 uint32_t dirtype
, struct smb_filename
*smb_fname
,
3001 char *fname_dir
= NULL
;
3002 char *fname_mask
= NULL
;
3004 NTSTATUS status
= NT_STATUS_OK
;
3005 struct smb_filename
*smb_fname_dir
= NULL
;
3006 TALLOC_CTX
*ctx
= talloc_tos();
3008 /* Split up the directory from the filename/mask. */
3009 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
3010 &fname_dir
, &fname_mask
);
3011 if (!NT_STATUS_IS_OK(status
)) {
3016 * We should only check the mangled cache
3017 * here if unix_convert failed. This means
3018 * that the path in 'mask' doesn't exist
3019 * on the file system and so we need to look
3020 * for a possible mangle. This patch from
3021 * Tine Smukavec <valentin.smukavec@hermes.si>.
3024 if (!VALID_STAT(smb_fname
->st
) &&
3025 mangle_is_mangled(fname_mask
, conn
->params
)) {
3026 char *new_mask
= NULL
;
3027 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
3028 &new_mask
, conn
->params
);
3030 TALLOC_FREE(fname_mask
);
3031 fname_mask
= new_mask
;
3038 * Only one file needs to be unlinked. Append the mask back
3039 * onto the directory.
3041 TALLOC_FREE(smb_fname
->base_name
);
3042 if (ISDOT(fname_dir
)) {
3043 /* Ensure we use canonical names on open. */
3044 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3048 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3053 if (!smb_fname
->base_name
) {
3054 status
= NT_STATUS_NO_MEMORY
;
3058 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3061 status
= check_name(conn
, smb_fname
);
3062 if (!NT_STATUS_IS_OK(status
)) {
3066 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3067 if (!NT_STATUS_IS_OK(status
)) {
3073 struct smb_Dir
*dir_hnd
= NULL
;
3075 const char *dname
= NULL
;
3076 char *talloced
= NULL
;
3078 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
3079 status
= NT_STATUS_OBJECT_NAME_INVALID
;
3083 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3086 if (strequal(fname_mask
,"????????.???")) {
3087 TALLOC_FREE(fname_mask
);
3088 fname_mask
= talloc_strdup(ctx
, "*");
3090 status
= NT_STATUS_NO_MEMORY
;
3095 smb_fname_dir
= synthetic_smb_fname(talloc_tos(),
3100 if (smb_fname_dir
== NULL
) {
3101 status
= NT_STATUS_NO_MEMORY
;
3105 status
= check_name(conn
, smb_fname_dir
);
3106 if (!NT_STATUS_IS_OK(status
)) {
3110 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_dir
, fname_mask
,
3112 if (dir_hnd
== NULL
) {
3113 status
= map_nt_error_from_unix(errno
);
3117 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3118 the pattern matches against the long name, otherwise the short name
3119 We don't implement this yet XXXX
3122 status
= NT_STATUS_NO_SUCH_FILE
;
3124 while ((dname
= ReadDirName(dir_hnd
, &offset
,
3125 &smb_fname
->st
, &talloced
))) {
3126 TALLOC_CTX
*frame
= talloc_stackframe();
3128 if (!is_visible_file(conn
, fname_dir
, dname
,
3129 &smb_fname
->st
, true)) {
3131 TALLOC_FREE(talloced
);
3135 /* Quick check for "." and ".." */
3136 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
3138 TALLOC_FREE(talloced
);
3142 if(!mask_match(dname
, fname_mask
,
3143 conn
->case_sensitive
)) {
3145 TALLOC_FREE(talloced
);
3149 TALLOC_FREE(smb_fname
->base_name
);
3150 if (ISDOT(fname_dir
)) {
3151 /* Ensure we use canonical names on open. */
3152 smb_fname
->base_name
=
3153 talloc_asprintf(smb_fname
, "%s",
3156 smb_fname
->base_name
=
3157 talloc_asprintf(smb_fname
, "%s/%s",
3161 if (!smb_fname
->base_name
) {
3162 TALLOC_FREE(dir_hnd
);
3163 status
= NT_STATUS_NO_MEMORY
;
3165 TALLOC_FREE(talloced
);
3169 status
= check_name(conn
, smb_fname
);
3170 if (!NT_STATUS_IS_OK(status
)) {
3171 TALLOC_FREE(dir_hnd
);
3173 TALLOC_FREE(talloced
);
3177 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3178 if (!NT_STATUS_IS_OK(status
)) {
3179 TALLOC_FREE(dir_hnd
);
3181 TALLOC_FREE(talloced
);
3186 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3187 smb_fname
->base_name
));
3190 TALLOC_FREE(talloced
);
3192 TALLOC_FREE(dir_hnd
);
3195 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3196 status
= map_nt_error_from_unix(errno
);
3200 TALLOC_FREE(smb_fname_dir
);
3201 TALLOC_FREE(fname_dir
);
3202 TALLOC_FREE(fname_mask
);
3206 /****************************************************************************
3208 ****************************************************************************/
3210 void reply_unlink(struct smb_request
*req
)
3212 connection_struct
*conn
= req
->conn
;
3214 struct smb_filename
*smb_fname
= NULL
;
3217 bool path_contains_wcard
= False
;
3218 uint32_t ucf_flags
= UCF_COND_ALLOW_WCARD_LCOMP
|
3219 ucf_flags_from_smb_request(req
);
3220 TALLOC_CTX
*ctx
= talloc_tos();
3222 START_PROFILE(SMBunlink
);
3225 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3229 dirtype
= SVAL(req
->vwv
+0, 0);
3231 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3232 STR_TERMINATE
, &status
,
3233 &path_contains_wcard
);
3234 if (!NT_STATUS_IS_OK(status
)) {
3235 reply_nterror(req
, status
);
3239 status
= filename_convert(ctx
, conn
,
3242 &path_contains_wcard
,
3244 if (!NT_STATUS_IS_OK(status
)) {
3245 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3246 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3247 ERRSRV
, ERRbadpath
);
3250 reply_nterror(req
, status
);
3254 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3256 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
3257 path_contains_wcard
);
3258 if (!NT_STATUS_IS_OK(status
)) {
3259 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3260 /* We have re-scheduled this call. */
3263 reply_nterror(req
, status
);
3267 reply_outbuf(req
, 0, 0);
3269 TALLOC_FREE(smb_fname
);
3270 END_PROFILE(SMBunlink
);
3274 /****************************************************************************
3276 ****************************************************************************/
3278 static void fail_readraw(void)
3280 const char *errstr
= talloc_asprintf(talloc_tos(),
3281 "FAIL ! reply_readbraw: socket write fail (%s)",
3286 exit_server_cleanly(errstr
);
3289 /****************************************************************************
3290 Fake (read/write) sendfile. Returns -1 on read or write fail.
3291 ****************************************************************************/
3293 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3294 off_t startpos
, size_t nread
)
3297 size_t tosend
= nread
;
3304 bufsize
= MIN(nread
, 65536);
3306 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3310 while (tosend
> 0) {
3314 cur_read
= MIN(tosend
, bufsize
);
3315 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3321 /* If we had a short read, fill with zeros. */
3322 if (ret
< cur_read
) {
3323 memset(buf
+ ret
, '\0', cur_read
- ret
);
3326 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3327 if (ret
!= cur_read
) {
3328 int saved_errno
= errno
;
3330 * Try and give an error message saying what
3333 DEBUG(0, ("write_data failed for client %s. "
3335 smbXsrv_connection_dbg(xconn
),
3336 strerror(saved_errno
)));
3338 errno
= saved_errno
;
3342 startpos
+= cur_read
;
3346 return (ssize_t
)nread
;
3349 /****************************************************************************
3350 Deal with the case of sendfile reading less bytes from the file than
3351 requested. Fill with zeros (all we can do). Returns 0 on success
3352 ****************************************************************************/
3354 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3360 #define SHORT_SEND_BUFSIZE 1024
3361 if (nread
< headersize
) {
3362 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3363 "header for file %s (%s). Terminating\n",
3364 fsp_str_dbg(fsp
), strerror(errno
)));
3368 nread
-= headersize
;
3370 if (nread
< smb_maxcnt
) {
3371 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3373 DEBUG(0,("sendfile_short_send: malloc failed "
3374 "for file %s (%s). Terminating\n",
3375 fsp_str_dbg(fsp
), strerror(errno
)));
3379 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3380 "with zeros !\n", fsp_str_dbg(fsp
)));
3382 while (nread
< smb_maxcnt
) {
3384 * We asked for the real file size and told sendfile
3385 * to not go beyond the end of the file. But it can
3386 * happen that in between our fstat call and the
3387 * sendfile call the file was truncated. This is very
3388 * bad because we have already announced the larger
3389 * number of bytes to the client.
3391 * The best we can do now is to send 0-bytes, just as
3392 * a read from a hole in a sparse file would do.
3394 * This should happen rarely enough that I don't care
3395 * about efficiency here :-)
3400 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3401 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3402 if (ret
!= to_write
) {
3403 int saved_errno
= errno
;
3405 * Try and give an error message saying what
3408 DEBUG(0, ("write_data failed for client %s. "
3410 smbXsrv_connection_dbg(xconn
),
3411 strerror(saved_errno
)));
3412 errno
= saved_errno
;
3423 /****************************************************************************
3424 Return a readbraw error (4 bytes of zero).
3425 ****************************************************************************/
3427 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3433 smbd_lock_socket(xconn
);
3434 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3435 int saved_errno
= errno
;
3437 * Try and give an error message saying what
3440 DEBUG(0, ("write_data failed for client %s. "
3442 smbXsrv_connection_dbg(xconn
),
3443 strerror(saved_errno
)));
3444 errno
= saved_errno
;
3448 smbd_unlock_socket(xconn
);
3451 /****************************************************************************
3452 Use sendfile in readbraw.
3453 ****************************************************************************/
3455 static void send_file_readbraw(connection_struct
*conn
,
3456 struct smb_request
*req
,
3462 struct smbXsrv_connection
*xconn
= req
->xconn
;
3463 char *outbuf
= NULL
;
3467 * We can only use sendfile on a non-chained packet
3468 * but we can use on a non-oplocked file. tridge proved this
3469 * on a train in Germany :-). JRA.
3470 * reply_readbraw has already checked the length.
3473 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3474 (fsp
->wcp
== NULL
) &&
3475 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3476 ssize_t sendfile_read
= -1;
3478 DATA_BLOB header_blob
;
3480 _smb_setlen(header
,nread
);
3481 header_blob
= data_blob_const(header
, 4);
3483 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3484 &header_blob
, startpos
,
3486 if (sendfile_read
== -1) {
3487 /* Returning ENOSYS means no data at all was sent.
3488 * Do this as a normal read. */
3489 if (errno
== ENOSYS
) {
3490 goto normal_readbraw
;
3494 * Special hack for broken Linux with no working sendfile. If we
3495 * return EINTR we sent the header but not the rest of the data.
3496 * Fake this up by doing read/write calls.
3498 if (errno
== EINTR
) {
3499 /* Ensure we don't do this again. */
3500 set_use_sendfile(SNUM(conn
), False
);
3501 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3503 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3504 DEBUG(0,("send_file_readbraw: "
3505 "fake_sendfile failed for "
3509 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3514 DEBUG(0,("send_file_readbraw: sendfile failed for "
3515 "file %s (%s). Terminating\n",
3516 fsp_str_dbg(fsp
), strerror(errno
)));
3517 exit_server_cleanly("send_file_readbraw sendfile failed");
3518 } else if (sendfile_read
== 0) {
3520 * Some sendfile implementations return 0 to indicate
3521 * that there was a short read, but nothing was
3522 * actually written to the socket. In this case,
3523 * fallback to the normal read path so the header gets
3524 * the correct byte count.
3526 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3527 "bytes falling back to the normal read: "
3528 "%s\n", fsp_str_dbg(fsp
)));
3529 goto normal_readbraw
;
3532 /* Deal with possible short send. */
3533 if (sendfile_read
!= 4+nread
) {
3534 ret
= sendfile_short_send(xconn
, fsp
,
3535 sendfile_read
, 4, nread
);
3545 outbuf
= talloc_array(NULL
, char, nread
+4);
3547 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3548 (unsigned)(nread
+4)));
3549 reply_readbraw_error(xconn
);
3554 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3555 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3564 _smb_setlen(outbuf
,ret
);
3565 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3566 int saved_errno
= errno
;
3568 * Try and give an error message saying what
3571 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3572 smbXsrv_connection_dbg(xconn
),
3573 strerror(saved_errno
)));
3574 errno
= saved_errno
;
3579 TALLOC_FREE(outbuf
);
3582 /****************************************************************************
3583 Reply to a readbraw (core+ protocol).
3584 ****************************************************************************/
3586 void reply_readbraw(struct smb_request
*req
)
3588 connection_struct
*conn
= req
->conn
;
3589 struct smbXsrv_connection
*xconn
= req
->xconn
;
3590 ssize_t maxcount
,mincount
;
3594 struct lock_struct lock
;
3597 START_PROFILE(SMBreadbraw
);
3599 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3600 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3601 "raw reads/writes are disallowed.");
3605 reply_readbraw_error(xconn
);
3606 END_PROFILE(SMBreadbraw
);
3610 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3611 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3612 "'async smb echo handler = yes'\n"));
3613 reply_readbraw_error(xconn
);
3614 END_PROFILE(SMBreadbraw
);
3619 * Special check if an oplock break has been issued
3620 * and the readraw request croses on the wire, we must
3621 * return a zero length response here.
3624 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3627 * We have to do a check_fsp by hand here, as
3628 * we must always return 4 zero bytes on error,
3632 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3633 req
->vuid
!= fsp
->vuid
||
3634 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3636 * fsp could be NULL here so use the value from the packet. JRA.
3638 DEBUG(3,("reply_readbraw: fnum %d not valid "
3640 (int)SVAL(req
->vwv
+0, 0)));
3641 reply_readbraw_error(xconn
);
3642 END_PROFILE(SMBreadbraw
);
3646 /* Do a "by hand" version of CHECK_READ. */
3647 if (!(fsp
->can_read
||
3648 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3649 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3650 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3651 (int)SVAL(req
->vwv
+0, 0)));
3652 reply_readbraw_error(xconn
);
3653 END_PROFILE(SMBreadbraw
);
3657 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3659 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3660 if(req
->wct
== 10) {
3662 * This is a large offset (64 bit) read.
3665 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3668 DEBUG(0,("reply_readbraw: negative 64 bit "
3669 "readraw offset (%.0f) !\n",
3670 (double)startpos
));
3671 reply_readbraw_error(xconn
);
3672 END_PROFILE(SMBreadbraw
);
3677 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3678 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3680 /* ensure we don't overrun the packet size */
3681 maxcount
= MIN(65535,maxcount
);
3683 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3684 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3687 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3688 reply_readbraw_error(xconn
);
3689 END_PROFILE(SMBreadbraw
);
3693 if (fsp_stat(fsp
) == 0) {
3694 size
= fsp
->fsp_name
->st
.st_ex_size
;
3697 if (startpos
>= size
) {
3700 nread
= MIN(maxcount
,(size
- startpos
));
3703 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3704 if (nread
< mincount
)
3708 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3709 "min=%lu nread=%lu\n",
3710 fsp_fnum_dbg(fsp
), (double)startpos
,
3711 (unsigned long)maxcount
,
3712 (unsigned long)mincount
,
3713 (unsigned long)nread
) );
3715 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3717 DEBUG(5,("reply_readbraw finished\n"));
3719 END_PROFILE(SMBreadbraw
);
3724 #define DBGC_CLASS DBGC_LOCKING
3726 /****************************************************************************
3727 Reply to a lockread (core+ protocol).
3728 ****************************************************************************/
3730 void reply_lockread(struct smb_request
*req
)
3732 connection_struct
*conn
= req
->conn
;
3740 struct byte_range_lock
*br_lck
= NULL
;
3742 struct smbXsrv_connection
*xconn
= req
->xconn
;
3744 START_PROFILE(SMBlockread
);
3747 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3748 END_PROFILE(SMBlockread
);
3752 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3754 if (!check_fsp(conn
, req
, fsp
)) {
3755 END_PROFILE(SMBlockread
);
3759 if (!CHECK_READ(fsp
,req
)) {
3760 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3761 END_PROFILE(SMBlockread
);
3765 numtoread
= SVAL(req
->vwv
+1, 0);
3766 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3769 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3770 * protocol request that predates the read/write lock concept.
3771 * Thus instead of asking for a read lock here we need to ask
3772 * for a write lock. JRA.
3773 * Note that the requested lock size is unaffected by max_send.
3776 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3778 (uint64_t)req
->smbpid
,
3779 (uint64_t)numtoread
,
3783 False
, /* Non-blocking lock. */
3786 TALLOC_FREE(br_lck
);
3788 if (NT_STATUS_V(status
)) {
3789 reply_nterror(req
, status
);
3790 END_PROFILE(SMBlockread
);
3795 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3797 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3799 if (numtoread
> maxtoread
) {
3800 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3801 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3802 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3803 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3804 numtoread
= maxtoread
;
3807 reply_outbuf(req
, 5, numtoread
+ 3);
3809 data
= smb_buf(req
->outbuf
) + 3;
3811 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3814 reply_nterror(req
, map_nt_error_from_unix(errno
));
3815 END_PROFILE(SMBlockread
);
3819 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3821 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3822 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3823 p
= smb_buf(req
->outbuf
);
3824 SCVAL(p
,0,0); /* pad byte. */
3827 DEBUG(3,("lockread %s num=%d nread=%d\n",
3828 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3830 END_PROFILE(SMBlockread
);
3835 #define DBGC_CLASS DBGC_ALL
3837 /****************************************************************************
3839 ****************************************************************************/
3841 void reply_read(struct smb_request
*req
)
3843 connection_struct
*conn
= req
->conn
;
3850 struct lock_struct lock
;
3851 struct smbXsrv_connection
*xconn
= req
->xconn
;
3853 START_PROFILE(SMBread
);
3856 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3857 END_PROFILE(SMBread
);
3861 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3863 if (!check_fsp(conn
, req
, fsp
)) {
3864 END_PROFILE(SMBread
);
3868 if (!CHECK_READ(fsp
,req
)) {
3869 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3870 END_PROFILE(SMBread
);
3874 numtoread
= SVAL(req
->vwv
+1, 0);
3875 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3878 * The requested read size cannot be greater than max_send. JRA.
3880 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3882 if (numtoread
> maxtoread
) {
3883 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3884 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3885 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3886 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3887 numtoread
= maxtoread
;
3890 reply_outbuf(req
, 5, numtoread
+3);
3892 data
= smb_buf(req
->outbuf
) + 3;
3894 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3895 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3898 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3899 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3900 END_PROFILE(SMBread
);
3905 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3908 reply_nterror(req
, map_nt_error_from_unix(errno
));
3912 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3914 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3915 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3916 SCVAL(smb_buf(req
->outbuf
),0,1);
3917 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3919 DEBUG(3, ("read %s num=%d nread=%d\n",
3920 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3923 END_PROFILE(SMBread
);
3927 /****************************************************************************
3929 ****************************************************************************/
3931 int setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3935 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3938 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3940 SCVAL(outbuf
,smb_vwv0
,0xFF);
3941 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3942 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3943 SSVAL(outbuf
,smb_vwv6
,
3944 (smb_wct
- 4) /* offset from smb header to wct */
3945 + 1 /* the wct field */
3946 + 12 * sizeof(uint16_t) /* vwv */
3947 + 2 /* the buflen field */
3948 + 1); /* padding byte */
3949 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3950 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3951 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3952 _smb_setlen_large(outbuf
,
3953 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3957 /****************************************************************************
3958 Reply to a read and X - possibly using sendfile.
3959 ****************************************************************************/
3961 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3962 files_struct
*fsp
, off_t startpos
,
3965 struct smbXsrv_connection
*xconn
= req
->xconn
;
3967 struct lock_struct lock
;
3968 int saved_errno
= 0;
3970 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3971 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3974 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3975 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3980 * We can only use sendfile on a non-chained packet
3981 * but we can use on a non-oplocked file. tridge proved this
3982 * on a train in Germany :-). JRA.
3985 if (!req_is_in_chain(req
) &&
3987 (fsp
->base_fsp
== NULL
) &&
3988 (fsp
->wcp
== NULL
) &&
3989 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3990 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3993 if(fsp_stat(fsp
) == -1) {
3994 reply_nterror(req
, map_nt_error_from_unix(errno
));
3998 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3999 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4000 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4002 * We already know that we would do a short read, so don't
4003 * try the sendfile() path.
4005 goto nosendfile_read
;
4009 * Set up the packet header before send. We
4010 * assume here the sendfile will work (get the
4011 * correct amount of data).
4014 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4016 construct_reply_common_req(req
, (char *)headerbuf
);
4017 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4019 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4020 startpos
, smb_maxcnt
);
4022 saved_errno
= errno
;
4024 /* Returning ENOSYS means no data at all was sent.
4025 Do this as a normal read. */
4026 if (errno
== ENOSYS
) {
4031 * Special hack for broken Linux with no working sendfile. If we
4032 * return EINTR we sent the header but not the rest of the data.
4033 * Fake this up by doing read/write calls.
4036 if (errno
== EINTR
) {
4037 /* Ensure we don't do this again. */
4038 set_use_sendfile(SNUM(conn
), False
);
4039 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4040 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4043 saved_errno
= errno
;
4044 DEBUG(0,("send_file_readX: "
4045 "fake_sendfile failed for "
4046 "file %s (%s) for client %s. "
4049 smbXsrv_connection_dbg(xconn
),
4050 strerror(saved_errno
)));
4051 errno
= saved_errno
;
4052 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4054 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4055 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4056 /* No outbuf here means successful sendfile. */
4060 DEBUG(0,("send_file_readX: sendfile failed for file "
4061 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4063 exit_server_cleanly("send_file_readX sendfile failed");
4064 } else if (nread
== 0) {
4066 * Some sendfile implementations return 0 to indicate
4067 * that there was a short read, but nothing was
4068 * actually written to the socket. In this case,
4069 * fallback to the normal read path so the header gets
4070 * the correct byte count.
4072 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4073 "falling back to the normal read: %s\n",
4078 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4079 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4081 /* Deal with possible short send. */
4082 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4085 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4086 sizeof(headerbuf
), smb_maxcnt
);
4089 r
= "send_file_readX: sendfile_short_send failed";
4090 DEBUG(0,("%s for file %s (%s).\n",
4091 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4092 exit_server_cleanly(r
);
4095 /* No outbuf here means successful sendfile. */
4096 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4097 SMB_PERFCOUNT_END(&req
->pcd
);
4103 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4104 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4107 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4108 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4109 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4111 * We already know that we would do a short
4112 * read, so don't try the sendfile() path.
4114 goto nosendfile_read
;
4117 construct_reply_common_req(req
, (char *)headerbuf
);
4118 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4120 /* Send out the header. */
4121 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4123 if (ret
!= sizeof(headerbuf
)) {
4124 saved_errno
= errno
;
4126 * Try and give an error message saying what
4129 DEBUG(0,("send_file_readX: write_data failed for file "
4130 "%s (%s) for client %s. Terminating\n",
4132 smbXsrv_connection_dbg(xconn
),
4133 strerror(saved_errno
)));
4134 errno
= saved_errno
;
4135 exit_server_cleanly("send_file_readX sendfile failed");
4137 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4139 saved_errno
= errno
;
4140 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4141 "%s (%s) for client %s. Terminating\n",
4143 smbXsrv_connection_dbg(xconn
),
4144 strerror(saved_errno
)));
4145 errno
= saved_errno
;
4146 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4153 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4154 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4155 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4157 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4158 startpos
, smb_maxcnt
);
4159 saved_errno
= errno
;
4162 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4166 setup_readX_header((char *)req
->outbuf
, nread
);
4168 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4169 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4173 TALLOC_FREE(req
->outbuf
);
4177 /****************************************************************************
4178 Work out how much space we have for a read return.
4179 ****************************************************************************/
4181 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4183 struct smbXsrv_connection
*xconn
= req
->xconn
;
4185 if (xconn
->protocol
< PROTOCOL_NT1
) {
4186 return xconn
->smb1
.sessions
.max_send
;
4189 if (!lp_large_readwrite()) {
4190 return xconn
->smb1
.sessions
.max_send
;
4193 if (req_is_in_chain(req
)) {
4194 return xconn
->smb1
.sessions
.max_send
;
4197 if (req
->encrypted
) {
4199 * Don't take encrypted traffic up to the
4200 * limit. There are padding considerations
4201 * that make that tricky.
4203 return xconn
->smb1
.sessions
.max_send
;
4206 if (srv_is_signing_active(xconn
)) {
4210 if (!lp_unix_extensions()) {
4215 * We can do ultra-large POSIX reads.
4220 /****************************************************************************
4221 Calculate how big a read can be. Copes with all clients. It's always
4222 safe to return a short read - Windows does this.
4223 ****************************************************************************/
4225 static size_t calc_read_size(const struct smb_request
*req
,
4229 struct smbXsrv_connection
*xconn
= req
->xconn
;
4230 size_t max_pdu
= calc_max_read_pdu(req
);
4231 size_t total_size
= 0;
4232 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4233 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4236 * Windows explicitly ignores upper size of 0xFFFF.
4237 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4238 * We must do the same as these will never fit even in
4239 * an extended size NetBIOS packet.
4241 if (upper_size
== 0xFFFF) {
4245 if (xconn
->protocol
< PROTOCOL_NT1
) {
4249 total_size
= ((upper_size
<<16) | lower_size
);
4252 * LARGE_READX test shows it's always safe to return
4253 * a short read. Windows does so.
4255 return MIN(total_size
, max_len
);
4258 /****************************************************************************
4259 Reply to a read and X.
4260 ****************************************************************************/
4262 void reply_read_and_X(struct smb_request
*req
)
4264 connection_struct
*conn
= req
->conn
;
4269 bool big_readX
= False
;
4271 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4274 START_PROFILE(SMBreadX
);
4276 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4277 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4281 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4282 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4283 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4285 /* If it's an IPC, pass off the pipe handler. */
4287 reply_pipe_read_and_X(req
);
4288 END_PROFILE(SMBreadX
);
4292 if (!check_fsp(conn
, req
, fsp
)) {
4293 END_PROFILE(SMBreadX
);
4297 if (!CHECK_READ(fsp
,req
)) {
4298 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4299 END_PROFILE(SMBreadX
);
4303 upper_size
= SVAL(req
->vwv
+7, 0);
4304 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4305 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4307 * This is a heuristic to avoid keeping large
4308 * outgoing buffers around over long-lived aio
4314 if (req
->wct
== 12) {
4316 * This is a large offset (64 bit) read.
4318 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4323 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4328 if (NT_STATUS_IS_OK(status
)) {
4329 /* Read scheduled - we're done. */
4332 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4333 /* Real error - report to client. */
4334 END_PROFILE(SMBreadX
);
4335 reply_nterror(req
, status
);
4338 /* NT_STATUS_RETRY - fall back to sync read. */
4341 smbd_lock_socket(req
->xconn
);
4342 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4343 smbd_unlock_socket(req
->xconn
);
4346 END_PROFILE(SMBreadX
);
4350 /****************************************************************************
4351 Error replies to writebraw must have smb_wct == 1. Fix this up.
4352 ****************************************************************************/
4354 void error_to_writebrawerr(struct smb_request
*req
)
4356 uint8_t *old_outbuf
= req
->outbuf
;
4358 reply_outbuf(req
, 1, 0);
4360 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4361 TALLOC_FREE(old_outbuf
);
4364 /****************************************************************************
4365 Read 4 bytes of a smb packet and return the smb length of the packet.
4366 Store the result in the buffer. This version of the function will
4367 never return a session keepalive (length of zero).
4368 Timeout is in milliseconds.
4369 ****************************************************************************/
4371 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4374 uint8_t msgtype
= NBSSkeepalive
;
4376 while (msgtype
== NBSSkeepalive
) {
4379 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4381 if (!NT_STATUS_IS_OK(status
)) {
4382 char addr
[INET6_ADDRSTRLEN
];
4383 /* Try and give an error message
4384 * saying what client failed. */
4385 DEBUG(0, ("read_fd_with_timeout failed for "
4386 "client %s read error = %s.\n",
4387 get_peer_addr(fd
,addr
,sizeof(addr
)),
4388 nt_errstr(status
)));
4392 msgtype
= CVAL(inbuf
, 0);
4395 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4396 (unsigned long)len
));
4398 return NT_STATUS_OK
;
4401 /****************************************************************************
4402 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4403 ****************************************************************************/
4405 void reply_writebraw(struct smb_request
*req
)
4407 connection_struct
*conn
= req
->conn
;
4408 struct smbXsrv_connection
*xconn
= req
->xconn
;
4411 ssize_t total_written
=0;
4412 size_t numtowrite
=0;
4415 const char *data
=NULL
;
4418 struct lock_struct lock
;
4421 START_PROFILE(SMBwritebraw
);
4424 * If we ever reply with an error, it must have the SMB command
4425 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4428 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4430 if (srv_is_signing_active(xconn
)) {
4431 END_PROFILE(SMBwritebraw
);
4432 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4433 "raw reads/writes are disallowed.");
4436 if (req
->wct
< 12) {
4437 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4438 error_to_writebrawerr(req
);
4439 END_PROFILE(SMBwritebraw
);
4443 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4444 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4445 "'async smb echo handler = yes'\n"));
4446 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4447 error_to_writebrawerr(req
);
4448 END_PROFILE(SMBwritebraw
);
4452 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4453 if (!check_fsp(conn
, req
, fsp
)) {
4454 error_to_writebrawerr(req
);
4455 END_PROFILE(SMBwritebraw
);
4459 if (!CHECK_WRITE(fsp
)) {
4460 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4461 error_to_writebrawerr(req
);
4462 END_PROFILE(SMBwritebraw
);
4466 tcount
= IVAL(req
->vwv
+1, 0);
4467 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4468 write_through
= BITSETW(req
->vwv
+7,0);
4470 /* We have to deal with slightly different formats depending
4471 on whether we are using the core+ or lanman1.0 protocol */
4473 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4474 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4475 data
= smb_buf_const(req
->inbuf
);
4477 numtowrite
= SVAL(req
->vwv
+10, 0);
4478 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4481 /* Ensure we don't write bytes past the end of this packet. */
4483 * This already protects us against CVE-2017-12163.
4485 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4486 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4487 error_to_writebrawerr(req
);
4488 END_PROFILE(SMBwritebraw
);
4492 if (!fsp
->print_file
) {
4493 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4494 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4497 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4498 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4499 error_to_writebrawerr(req
);
4500 END_PROFILE(SMBwritebraw
);
4506 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4509 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4510 "wrote=%d sync=%d\n",
4511 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4512 (int)nwritten
, (int)write_through
));
4514 if (nwritten
< (ssize_t
)numtowrite
) {
4515 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4516 error_to_writebrawerr(req
);
4520 total_written
= nwritten
;
4522 /* Allocate a buffer of 64k + length. */
4523 buf
= talloc_array(NULL
, char, 65540);
4525 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4526 error_to_writebrawerr(req
);
4530 /* Return a SMBwritebraw message to the redirector to tell
4531 * it to send more bytes */
4533 memcpy(buf
, req
->inbuf
, smb_size
);
4534 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4535 SCVAL(buf
,smb_com
,SMBwritebraw
);
4536 SSVALS(buf
,smb_vwv0
,0xFFFF);
4538 if (!srv_send_smb(req
->xconn
,
4540 false, 0, /* no signing */
4541 IS_CONN_ENCRYPTED(conn
),
4543 exit_server_cleanly("reply_writebraw: srv_send_smb "
4547 /* Now read the raw data into the buffer and write it */
4548 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4550 if (!NT_STATUS_IS_OK(status
)) {
4551 exit_server_cleanly("secondary writebraw failed");
4554 /* Set up outbuf to return the correct size */
4555 reply_outbuf(req
, 1, 0);
4557 if (numtowrite
!= 0) {
4559 if (numtowrite
> 0xFFFF) {
4560 DEBUG(0,("reply_writebraw: Oversize secondary write "
4561 "raw requested (%u). Terminating\n",
4562 (unsigned int)numtowrite
));
4563 exit_server_cleanly("secondary writebraw failed");
4566 if (tcount
> nwritten
+numtowrite
) {
4567 DEBUG(3,("reply_writebraw: Client overestimated the "
4569 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4572 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4575 if (!NT_STATUS_IS_OK(status
)) {
4576 /* Try and give an error message
4577 * saying what client failed. */
4578 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4579 "raw read failed (%s) for client %s. "
4580 "Terminating\n", nt_errstr(status
),
4581 smbXsrv_connection_dbg(xconn
)));
4582 exit_server_cleanly("secondary writebraw failed");
4586 * We are not vulnerable to CVE-2017-12163
4587 * here as we are guarenteed to have numtowrite
4588 * bytes available - we just read from the client.
4590 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4591 if (nwritten
== -1) {
4593 reply_nterror(req
, map_nt_error_from_unix(errno
));
4594 error_to_writebrawerr(req
);
4598 if (nwritten
< (ssize_t
)numtowrite
) {
4599 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4600 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4604 total_written
+= nwritten
;
4609 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4611 status
= sync_file(conn
, fsp
, write_through
);
4612 if (!NT_STATUS_IS_OK(status
)) {
4613 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4614 fsp_str_dbg(fsp
), nt_errstr(status
)));
4615 reply_nterror(req
, status
);
4616 error_to_writebrawerr(req
);
4620 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4622 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4623 (int)total_written
));
4625 /* We won't return a status if write through is not selected - this
4626 * follows what WfWg does */
4627 END_PROFILE(SMBwritebraw
);
4629 if (!write_through
&& total_written
==tcount
) {
4631 #if RABBIT_PELLET_FIX
4633 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4634 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4637 if (!send_keepalive(xconn
->transport
.sock
)) {
4638 exit_server_cleanly("reply_writebraw: send of "
4639 "keepalive failed");
4642 TALLOC_FREE(req
->outbuf
);
4647 END_PROFILE(SMBwritebraw
);
4652 #define DBGC_CLASS DBGC_LOCKING
4654 /****************************************************************************
4655 Reply to a writeunlock (core+).
4656 ****************************************************************************/
4658 void reply_writeunlock(struct smb_request
*req
)
4660 connection_struct
*conn
= req
->conn
;
4661 ssize_t nwritten
= -1;
4666 NTSTATUS status
= NT_STATUS_OK
;
4668 struct lock_struct lock
;
4669 int saved_errno
= 0;
4671 START_PROFILE(SMBwriteunlock
);
4674 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4675 END_PROFILE(SMBwriteunlock
);
4679 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4681 if (!check_fsp(conn
, req
, fsp
)) {
4682 END_PROFILE(SMBwriteunlock
);
4686 if (!CHECK_WRITE(fsp
)) {
4687 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4688 END_PROFILE(SMBwriteunlock
);
4692 numtowrite
= SVAL(req
->vwv
+1, 0);
4693 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4694 data
= (const char *)req
->buf
+ 3;
4697 * Ensure client isn't asking us to write more than
4698 * they sent. CVE-2017-12163.
4700 remaining
= smbreq_bufrem(req
, data
);
4701 if (numtowrite
> remaining
) {
4702 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4703 END_PROFILE(SMBwriteunlock
);
4707 if (!fsp
->print_file
&& numtowrite
> 0) {
4708 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4709 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4712 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4713 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4714 END_PROFILE(SMBwriteunlock
);
4719 /* The special X/Open SMB protocol handling of
4720 zero length writes is *NOT* done for
4722 if(numtowrite
== 0) {
4725 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4726 saved_errno
= errno
;
4729 status
= sync_file(conn
, fsp
, False
/* write through */);
4730 if (!NT_STATUS_IS_OK(status
)) {
4731 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4732 fsp_str_dbg(fsp
), nt_errstr(status
)));
4733 reply_nterror(req
, status
);
4738 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4742 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4743 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4747 if (numtowrite
&& !fsp
->print_file
) {
4748 status
= do_unlock(req
->sconn
->msg_ctx
,
4750 (uint64_t)req
->smbpid
,
4751 (uint64_t)numtowrite
,
4755 if (NT_STATUS_V(status
)) {
4756 reply_nterror(req
, status
);
4761 reply_outbuf(req
, 1, 0);
4763 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4765 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4766 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4769 END_PROFILE(SMBwriteunlock
);
4774 #define DBGC_CLASS DBGC_ALL
4776 /****************************************************************************
4778 ****************************************************************************/
4780 void reply_write(struct smb_request
*req
)
4782 connection_struct
*conn
= req
->conn
;
4785 ssize_t nwritten
= -1;
4789 struct lock_struct lock
;
4791 int saved_errno
= 0;
4793 START_PROFILE(SMBwrite
);
4796 END_PROFILE(SMBwrite
);
4797 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4801 /* If it's an IPC, pass off the pipe handler. */
4803 reply_pipe_write(req
);
4804 END_PROFILE(SMBwrite
);
4808 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4810 if (!check_fsp(conn
, req
, fsp
)) {
4811 END_PROFILE(SMBwrite
);
4815 if (!CHECK_WRITE(fsp
)) {
4816 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4817 END_PROFILE(SMBwrite
);
4821 numtowrite
= SVAL(req
->vwv
+1, 0);
4822 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4823 data
= (const char *)req
->buf
+ 3;
4826 * Ensure client isn't asking us to write more than
4827 * they sent. CVE-2017-12163.
4829 remaining
= smbreq_bufrem(req
, data
);
4830 if (numtowrite
> remaining
) {
4831 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4832 END_PROFILE(SMBwrite
);
4836 if (!fsp
->print_file
) {
4837 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4838 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4841 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4842 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4843 END_PROFILE(SMBwrite
);
4849 * X/Open SMB protocol says that if smb_vwv1 is
4850 * zero then the file size should be extended or
4851 * truncated to the size given in smb_vwv[2-3].
4854 if(numtowrite
== 0) {
4856 * This is actually an allocate call, and set EOF. JRA.
4858 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4860 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4863 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4865 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4868 trigger_write_time_update_immediate(fsp
);
4870 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4873 status
= sync_file(conn
, fsp
, False
);
4874 if (!NT_STATUS_IS_OK(status
)) {
4875 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4876 fsp_str_dbg(fsp
), nt_errstr(status
)));
4877 reply_nterror(req
, status
);
4882 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4886 if((nwritten
== 0) && (numtowrite
!= 0)) {
4887 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4891 reply_outbuf(req
, 1, 0);
4893 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4895 if (nwritten
< (ssize_t
)numtowrite
) {
4896 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4897 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4900 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4903 END_PROFILE(SMBwrite
);
4907 /****************************************************************************
4908 Ensure a buffer is a valid writeX for recvfile purposes.
4909 ****************************************************************************/
4911 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4912 (2*14) + /* word count (including bcc) */ \
4915 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4916 const uint8_t *inbuf
)
4919 unsigned int doff
= 0;
4920 size_t len
= smb_len_large(inbuf
);
4922 struct smbXsrv_open
*op
= NULL
;
4923 struct files_struct
*fsp
= NULL
;
4926 if (is_encrypted_packet(inbuf
)) {
4927 /* Can't do this on encrypted
4932 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4936 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4937 CVAL(inbuf
,smb_wct
) != 14) {
4938 DEBUG(10,("is_valid_writeX_buffer: chained or "
4939 "invalid word length.\n"));
4943 fnum
= SVAL(inbuf
, smb_vwv2
);
4944 status
= smb1srv_open_lookup(xconn
,
4948 if (!NT_STATUS_IS_OK(status
)) {
4949 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4954 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4957 if (fsp
->conn
== NULL
) {
4958 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4962 if (IS_IPC(fsp
->conn
)) {
4963 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4966 if (IS_PRINT(fsp
->conn
)) {
4967 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4970 doff
= SVAL(inbuf
,smb_vwv11
);
4972 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4974 if (len
> doff
&& len
- doff
> 0xFFFF) {
4975 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4978 if (numtowrite
== 0) {
4979 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4983 /* Ensure the sizes match up. */
4984 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4985 /* no pad byte...old smbclient :-( */
4986 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4988 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4992 if (len
- doff
!= numtowrite
) {
4993 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4994 "len = %u, doff = %u, numtowrite = %u\n",
4997 (unsigned int)numtowrite
));
5001 DEBUG(10,("is_valid_writeX_buffer: true "
5002 "len = %u, doff = %u, numtowrite = %u\n",
5005 (unsigned int)numtowrite
));
5010 /****************************************************************************
5011 Reply to a write and X.
5012 ****************************************************************************/
5014 void reply_write_and_X(struct smb_request
*req
)
5016 connection_struct
*conn
= req
->conn
;
5017 struct smbXsrv_connection
*xconn
= req
->xconn
;
5019 struct lock_struct lock
;
5024 unsigned int smb_doff
;
5025 unsigned int smblen
;
5028 int saved_errno
= 0;
5030 START_PROFILE(SMBwriteX
);
5032 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5033 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5037 numtowrite
= SVAL(req
->vwv
+10, 0);
5038 smb_doff
= SVAL(req
->vwv
+11, 0);
5039 smblen
= smb_len(req
->inbuf
);
5041 if (req
->unread_bytes
> 0xFFFF ||
5042 (smblen
> smb_doff
&&
5043 smblen
- smb_doff
> 0xFFFF)) {
5044 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5047 if (req
->unread_bytes
) {
5048 /* Can't do a recvfile write on IPC$ */
5050 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5053 if (numtowrite
!= req
->unread_bytes
) {
5054 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5059 * This already protects us against CVE-2017-12163.
5061 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5062 smb_doff
+ numtowrite
> smblen
) {
5063 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5068 /* If it's an IPC, pass off the pipe handler. */
5070 if (req
->unread_bytes
) {
5071 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5074 reply_pipe_write_and_X(req
);
5078 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5079 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5080 write_through
= BITSETW(req
->vwv
+7,0);
5082 if (!check_fsp(conn
, req
, fsp
)) {
5086 if (!CHECK_WRITE(fsp
)) {
5087 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5091 data
= smb_base(req
->inbuf
) + smb_doff
;
5093 if(req
->wct
== 14) {
5095 * This is a large offset (64 bit) write.
5097 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5101 /* X/Open SMB protocol says that, unlike SMBwrite
5102 if the length is zero then NO truncation is
5103 done, just a write of zero. To truncate a file,
5106 if(numtowrite
== 0) {
5109 if (req
->unread_bytes
== 0) {
5110 status
= schedule_aio_write_and_X(conn
,
5117 if (NT_STATUS_IS_OK(status
)) {
5118 /* write scheduled - we're done. */
5121 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5122 /* Real error - report to client. */
5123 reply_nterror(req
, status
);
5126 /* NT_STATUS_RETRY - fall through to sync write. */
5129 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5130 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5133 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5134 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5138 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5139 saved_errno
= errno
;
5143 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5147 if((nwritten
== 0) && (numtowrite
!= 0)) {
5148 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5152 reply_outbuf(req
, 6, 0);
5153 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5154 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5155 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5156 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5158 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5159 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5161 status
= sync_file(conn
, fsp
, write_through
);
5162 if (!NT_STATUS_IS_OK(status
)) {
5163 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5164 fsp_str_dbg(fsp
), nt_errstr(status
)));
5165 reply_nterror(req
, status
);
5169 END_PROFILE(SMBwriteX
);
5173 if (req
->unread_bytes
) {
5174 /* writeX failed. drain socket. */
5175 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5176 req
->unread_bytes
) {
5177 smb_panic("failed to drain pending bytes");
5179 req
->unread_bytes
= 0;
5182 END_PROFILE(SMBwriteX
);
5186 /****************************************************************************
5188 ****************************************************************************/
5190 void reply_lseek(struct smb_request
*req
)
5192 connection_struct
*conn
= req
->conn
;
5198 START_PROFILE(SMBlseek
);
5201 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5202 END_PROFILE(SMBlseek
);
5206 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5208 if (!check_fsp(conn
, req
, fsp
)) {
5212 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5214 mode
= SVAL(req
->vwv
+1, 0) & 3;
5215 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5216 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5225 res
= fsp
->fh
->pos
+ startpos
;
5236 if (umode
== SEEK_END
) {
5237 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5238 if(errno
== EINVAL
) {
5239 off_t current_pos
= startpos
;
5241 if(fsp_stat(fsp
) == -1) {
5243 map_nt_error_from_unix(errno
));
5244 END_PROFILE(SMBlseek
);
5248 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5250 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5255 reply_nterror(req
, map_nt_error_from_unix(errno
));
5256 END_PROFILE(SMBlseek
);
5263 reply_outbuf(req
, 2, 0);
5264 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5266 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5267 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5269 END_PROFILE(SMBlseek
);
5273 /****************************************************************************
5275 ****************************************************************************/
5277 void reply_flush(struct smb_request
*req
)
5279 connection_struct
*conn
= req
->conn
;
5283 START_PROFILE(SMBflush
);
5286 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5290 fnum
= SVAL(req
->vwv
+0, 0);
5291 fsp
= file_fsp(req
, fnum
);
5293 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5298 file_sync_all(conn
);
5300 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5301 if (!NT_STATUS_IS_OK(status
)) {
5302 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5303 fsp_str_dbg(fsp
), nt_errstr(status
)));
5304 reply_nterror(req
, status
);
5305 END_PROFILE(SMBflush
);
5310 reply_outbuf(req
, 0, 0);
5312 DEBUG(3,("flush\n"));
5313 END_PROFILE(SMBflush
);
5317 /****************************************************************************
5319 conn POINTER CAN BE NULL HERE !
5320 ****************************************************************************/
5322 void reply_exit(struct smb_request
*req
)
5324 START_PROFILE(SMBexit
);
5326 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5328 reply_outbuf(req
, 0, 0);
5330 DEBUG(3,("exit\n"));
5332 END_PROFILE(SMBexit
);
5336 struct reply_close_state
{
5338 struct smb_request
*smbreq
;
5341 static void do_smb1_close(struct tevent_req
*req
);
5343 void reply_close(struct smb_request
*req
)
5345 connection_struct
*conn
= req
->conn
;
5346 NTSTATUS status
= NT_STATUS_OK
;
5347 files_struct
*fsp
= NULL
;
5348 START_PROFILE(SMBclose
);
5351 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5352 END_PROFILE(SMBclose
);
5356 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5359 * We can only use check_fsp if we know it's not a directory.
5362 if (!check_fsp_open(conn
, req
, fsp
)) {
5363 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5364 END_PROFILE(SMBclose
);
5368 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5369 fsp
->is_directory
? "directory" : "file",
5370 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5371 conn
->num_files_open
));
5373 if (!fsp
->is_directory
) {
5377 * Take care of any time sent in the close.
5380 t
= srv_make_unix_date3(req
->vwv
+1);
5381 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5384 if (fsp
->num_aio_requests
!= 0) {
5386 struct reply_close_state
*state
;
5388 DEBUG(10, ("closing with aio %u requests pending\n",
5389 fsp
->num_aio_requests
));
5392 * We depend on the aio_extra destructor to take care of this
5393 * close request once fsp->num_aio_request drops to 0.
5396 fsp
->deferred_close
= tevent_wait_send(
5397 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5398 if (fsp
->deferred_close
== NULL
) {
5399 status
= NT_STATUS_NO_MEMORY
;
5403 state
= talloc(fsp
, struct reply_close_state
);
5404 if (state
== NULL
) {
5405 TALLOC_FREE(fsp
->deferred_close
);
5406 status
= NT_STATUS_NO_MEMORY
;
5410 state
->smbreq
= talloc_move(fsp
, &req
);
5411 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5413 END_PROFILE(SMBclose
);
5418 * close_file() returns the unix errno if an error was detected on
5419 * close - normally this is due to a disk full error. If not then it
5420 * was probably an I/O error.
5423 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5425 if (!NT_STATUS_IS_OK(status
)) {
5426 reply_nterror(req
, status
);
5427 END_PROFILE(SMBclose
);
5431 reply_outbuf(req
, 0, 0);
5432 END_PROFILE(SMBclose
);
5436 static void do_smb1_close(struct tevent_req
*req
)
5438 struct reply_close_state
*state
= tevent_req_callback_data(
5439 req
, struct reply_close_state
);
5440 struct smb_request
*smbreq
;
5444 ret
= tevent_wait_recv(req
);
5447 DEBUG(10, ("tevent_wait_recv returned %s\n",
5450 * Continue anyway, this should never happen
5455 * fsp->smb2_close_request right now is a talloc grandchild of
5456 * fsp. When we close_file(fsp), it would go with it. No chance to
5459 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5461 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5462 if (NT_STATUS_IS_OK(status
)) {
5463 reply_outbuf(smbreq
, 0, 0);
5465 reply_nterror(smbreq
, status
);
5467 if (!srv_send_smb(smbreq
->xconn
,
5468 (char *)smbreq
->outbuf
,
5471 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5473 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5476 TALLOC_FREE(smbreq
);
5479 /****************************************************************************
5480 Reply to a writeclose (Core+ protocol).
5481 ****************************************************************************/
5483 void reply_writeclose(struct smb_request
*req
)
5485 connection_struct
*conn
= req
->conn
;
5488 ssize_t nwritten
= -1;
5489 NTSTATUS close_status
= NT_STATUS_OK
;
5492 struct timespec mtime
;
5494 struct lock_struct lock
;
5496 START_PROFILE(SMBwriteclose
);
5499 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5500 END_PROFILE(SMBwriteclose
);
5504 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5506 if (!check_fsp(conn
, req
, fsp
)) {
5507 END_PROFILE(SMBwriteclose
);
5510 if (!CHECK_WRITE(fsp
)) {
5511 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5512 END_PROFILE(SMBwriteclose
);
5516 numtowrite
= SVAL(req
->vwv
+1, 0);
5517 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5518 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5519 data
= (const char *)req
->buf
+ 1;
5522 * Ensure client isn't asking us to write more than
5523 * they sent. CVE-2017-12163.
5525 remaining
= smbreq_bufrem(req
, data
);
5526 if (numtowrite
> remaining
) {
5527 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5528 END_PROFILE(SMBwriteclose
);
5532 if (fsp
->print_file
== NULL
) {
5533 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5534 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5537 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5538 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5539 END_PROFILE(SMBwriteclose
);
5544 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5546 set_close_write_time(fsp
, mtime
);
5549 * More insanity. W2K only closes the file if writelen > 0.
5553 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5554 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5555 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5558 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5559 "file %s\n", fsp_str_dbg(fsp
)));
5560 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5564 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5565 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5569 if(!NT_STATUS_IS_OK(close_status
)) {
5570 reply_nterror(req
, close_status
);
5574 reply_outbuf(req
, 1, 0);
5576 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5580 END_PROFILE(SMBwriteclose
);
5585 #define DBGC_CLASS DBGC_LOCKING
5587 /****************************************************************************
5589 ****************************************************************************/
5591 void reply_lock(struct smb_request
*req
)
5593 connection_struct
*conn
= req
->conn
;
5594 uint64_t count
,offset
;
5597 struct byte_range_lock
*br_lck
= NULL
;
5599 START_PROFILE(SMBlock
);
5602 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5603 END_PROFILE(SMBlock
);
5607 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5609 if (!check_fsp(conn
, req
, fsp
)) {
5610 END_PROFILE(SMBlock
);
5614 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5615 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5617 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5618 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5620 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5622 (uint64_t)req
->smbpid
,
5627 False
, /* Non-blocking lock. */
5631 TALLOC_FREE(br_lck
);
5633 if (NT_STATUS_V(status
)) {
5634 reply_nterror(req
, status
);
5635 END_PROFILE(SMBlock
);
5639 reply_outbuf(req
, 0, 0);
5641 END_PROFILE(SMBlock
);
5645 /****************************************************************************
5647 ****************************************************************************/
5649 void reply_unlock(struct smb_request
*req
)
5651 connection_struct
*conn
= req
->conn
;
5652 uint64_t count
,offset
;
5656 START_PROFILE(SMBunlock
);
5659 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5660 END_PROFILE(SMBunlock
);
5664 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5666 if (!check_fsp(conn
, req
, fsp
)) {
5667 END_PROFILE(SMBunlock
);
5671 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5672 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5674 status
= do_unlock(req
->sconn
->msg_ctx
,
5676 (uint64_t)req
->smbpid
,
5681 if (NT_STATUS_V(status
)) {
5682 reply_nterror(req
, status
);
5683 END_PROFILE(SMBunlock
);
5687 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5688 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5690 reply_outbuf(req
, 0, 0);
5692 END_PROFILE(SMBunlock
);
5697 #define DBGC_CLASS DBGC_ALL
5699 /****************************************************************************
5701 conn POINTER CAN BE NULL HERE !
5702 ****************************************************************************/
5704 void reply_tdis(struct smb_request
*req
)
5707 connection_struct
*conn
= req
->conn
;
5708 struct smbXsrv_tcon
*tcon
;
5710 START_PROFILE(SMBtdis
);
5713 DEBUG(4,("Invalid connection in tdis\n"));
5714 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5715 END_PROFILE(SMBtdis
);
5723 * TODO: cancel all outstanding requests on the tcon
5725 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5726 if (!NT_STATUS_IS_OK(status
)) {
5727 DEBUG(0, ("reply_tdis: "
5728 "smbXsrv_tcon_disconnect() failed: %s\n",
5729 nt_errstr(status
)));
5731 * If we hit this case, there is something completely
5732 * wrong, so we better disconnect the transport connection.
5734 END_PROFILE(SMBtdis
);
5735 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5741 reply_outbuf(req
, 0, 0);
5742 END_PROFILE(SMBtdis
);
5746 /****************************************************************************
5748 conn POINTER CAN BE NULL HERE !
5749 ****************************************************************************/
5751 void reply_echo(struct smb_request
*req
)
5753 connection_struct
*conn
= req
->conn
;
5754 struct smb_perfcount_data local_pcd
;
5755 struct smb_perfcount_data
*cur_pcd
;
5759 START_PROFILE(SMBecho
);
5761 smb_init_perfcount_data(&local_pcd
);
5764 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5765 END_PROFILE(SMBecho
);
5769 smb_reverb
= SVAL(req
->vwv
+0, 0);
5771 reply_outbuf(req
, 1, req
->buflen
);
5773 /* copy any incoming data back out */
5774 if (req
->buflen
> 0) {
5775 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5778 if (smb_reverb
> 100) {
5779 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5783 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5785 /* this makes sure we catch the request pcd */
5786 if (seq_num
== smb_reverb
) {
5787 cur_pcd
= &req
->pcd
;
5789 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5790 cur_pcd
= &local_pcd
;
5793 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5795 show_msg((char *)req
->outbuf
);
5796 if (!srv_send_smb(req
->xconn
,
5797 (char *)req
->outbuf
,
5798 true, req
->seqnum
+1,
5799 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5801 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5804 DEBUG(3,("echo %d times\n", smb_reverb
));
5806 TALLOC_FREE(req
->outbuf
);
5808 END_PROFILE(SMBecho
);
5812 /****************************************************************************
5813 Reply to a printopen.
5814 ****************************************************************************/
5816 void reply_printopen(struct smb_request
*req
)
5818 connection_struct
*conn
= req
->conn
;
5822 START_PROFILE(SMBsplopen
);
5825 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5826 END_PROFILE(SMBsplopen
);
5830 if (!CAN_PRINT(conn
)) {
5831 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5832 END_PROFILE(SMBsplopen
);
5836 status
= file_new(req
, conn
, &fsp
);
5837 if(!NT_STATUS_IS_OK(status
)) {
5838 reply_nterror(req
, status
);
5839 END_PROFILE(SMBsplopen
);
5843 /* Open for exclusive use, write only. */
5844 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5846 if (!NT_STATUS_IS_OK(status
)) {
5847 file_free(req
, fsp
);
5848 reply_nterror(req
, status
);
5849 END_PROFILE(SMBsplopen
);
5853 reply_outbuf(req
, 1, 0);
5854 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5856 DEBUG(3,("openprint fd=%d %s\n",
5857 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5859 END_PROFILE(SMBsplopen
);
5863 /****************************************************************************
5864 Reply to a printclose.
5865 ****************************************************************************/
5867 void reply_printclose(struct smb_request
*req
)
5869 connection_struct
*conn
= req
->conn
;
5873 START_PROFILE(SMBsplclose
);
5876 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5877 END_PROFILE(SMBsplclose
);
5881 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5883 if (!check_fsp(conn
, req
, fsp
)) {
5884 END_PROFILE(SMBsplclose
);
5888 if (!CAN_PRINT(conn
)) {
5889 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5890 END_PROFILE(SMBsplclose
);
5894 DEBUG(3,("printclose fd=%d %s\n",
5895 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5897 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5899 if(!NT_STATUS_IS_OK(status
)) {
5900 reply_nterror(req
, status
);
5901 END_PROFILE(SMBsplclose
);
5905 reply_outbuf(req
, 0, 0);
5907 END_PROFILE(SMBsplclose
);
5911 /****************************************************************************
5912 Reply to a printqueue.
5913 ****************************************************************************/
5915 void reply_printqueue(struct smb_request
*req
)
5917 connection_struct
*conn
= req
->conn
;
5921 START_PROFILE(SMBsplretq
);
5924 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5925 END_PROFILE(SMBsplretq
);
5929 max_count
= SVAL(req
->vwv
+0, 0);
5930 start_index
= SVAL(req
->vwv
+1, 0);
5932 /* we used to allow the client to get the cnum wrong, but that
5933 is really quite gross and only worked when there was only
5934 one printer - I think we should now only accept it if they
5935 get it right (tridge) */
5936 if (!CAN_PRINT(conn
)) {
5937 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5938 END_PROFILE(SMBsplretq
);
5942 reply_outbuf(req
, 2, 3);
5943 SSVAL(req
->outbuf
,smb_vwv0
,0);
5944 SSVAL(req
->outbuf
,smb_vwv1
,0);
5945 SCVAL(smb_buf(req
->outbuf
),0,1);
5946 SSVAL(smb_buf(req
->outbuf
),1,0);
5948 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5949 start_index
, max_count
));
5952 TALLOC_CTX
*mem_ctx
= talloc_tos();
5955 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5956 struct rpc_pipe_client
*cli
= NULL
;
5957 struct dcerpc_binding_handle
*b
= NULL
;
5958 struct policy_handle handle
;
5959 struct spoolss_DevmodeContainer devmode_ctr
;
5960 union spoolss_JobInfo
*info
;
5962 uint32_t num_to_get
;
5966 ZERO_STRUCT(handle
);
5968 status
= rpc_pipe_open_interface(mem_ctx
,
5971 conn
->sconn
->remote_address
,
5972 conn
->sconn
->local_address
,
5973 conn
->sconn
->msg_ctx
,
5975 if (!NT_STATUS_IS_OK(status
)) {
5976 DEBUG(0, ("reply_printqueue: "
5977 "could not connect to spoolss: %s\n",
5978 nt_errstr(status
)));
5979 reply_nterror(req
, status
);
5982 b
= cli
->binding_handle
;
5984 ZERO_STRUCT(devmode_ctr
);
5986 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5989 SEC_FLAG_MAXIMUM_ALLOWED
,
5992 if (!NT_STATUS_IS_OK(status
)) {
5993 reply_nterror(req
, status
);
5996 if (!W_ERROR_IS_OK(werr
)) {
5997 reply_nterror(req
, werror_to_ntstatus(werr
));
6001 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
6009 if (!W_ERROR_IS_OK(werr
)) {
6010 reply_nterror(req
, werror_to_ntstatus(werr
));
6014 if (max_count
> 0) {
6015 first
= start_index
;
6017 first
= start_index
+ max_count
+ 1;
6020 if (first
>= count
) {
6023 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6026 for (i
= first
; i
< num_to_get
; i
++) {
6029 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6032 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6033 info
[i
].info2
.job_id
);
6035 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6041 srv_put_dos_date2(p
, 0, qtime
);
6042 SCVAL(p
, 4, qstatus
);
6043 SSVAL(p
, 5, qrapjobid
);
6044 SIVAL(p
, 7, info
[i
].info2
.size
);
6046 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6047 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6048 if (!NT_STATUS_IS_OK(status
)) {
6049 reply_nterror(req
, status
);
6052 if (message_push_blob(
6055 blob
, sizeof(blob
))) == -1) {
6056 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6062 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6063 SSVAL(req
->outbuf
,smb_vwv1
,
6064 (max_count
>0?first
+count
:first
-1));
6065 SCVAL(smb_buf(req
->outbuf
),0,1);
6066 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6070 DEBUG(3, ("%u entries returned in queue\n",
6074 if (b
&& is_valid_policy_hnd(&handle
)) {
6075 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6080 END_PROFILE(SMBsplretq
);
6084 /****************************************************************************
6085 Reply to a printwrite.
6086 ****************************************************************************/
6088 void reply_printwrite(struct smb_request
*req
)
6090 connection_struct
*conn
= req
->conn
;
6095 START_PROFILE(SMBsplwr
);
6098 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6099 END_PROFILE(SMBsplwr
);
6103 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6105 if (!check_fsp(conn
, req
, fsp
)) {
6106 END_PROFILE(SMBsplwr
);
6110 if (!fsp
->print_file
) {
6111 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6112 END_PROFILE(SMBsplwr
);
6116 if (!CHECK_WRITE(fsp
)) {
6117 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6118 END_PROFILE(SMBsplwr
);
6122 numtowrite
= SVAL(req
->buf
, 1);
6125 * This already protects us against CVE-2017-12163.
6127 if (req
->buflen
< numtowrite
+ 3) {
6128 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6129 END_PROFILE(SMBsplwr
);
6133 data
= (const char *)req
->buf
+ 3;
6135 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6136 reply_nterror(req
, map_nt_error_from_unix(errno
));
6137 END_PROFILE(SMBsplwr
);
6141 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6143 END_PROFILE(SMBsplwr
);
6147 /****************************************************************************
6149 ****************************************************************************/
6151 void reply_mkdir(struct smb_request
*req
)
6153 connection_struct
*conn
= req
->conn
;
6154 struct smb_filename
*smb_dname
= NULL
;
6155 char *directory
= NULL
;
6158 TALLOC_CTX
*ctx
= talloc_tos();
6160 START_PROFILE(SMBmkdir
);
6162 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6163 STR_TERMINATE
, &status
);
6164 if (!NT_STATUS_IS_OK(status
)) {
6165 reply_nterror(req
, status
);
6169 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
6170 status
= filename_convert(ctx
, conn
,
6175 if (!NT_STATUS_IS_OK(status
)) {
6176 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6177 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6178 ERRSRV
, ERRbadpath
);
6181 reply_nterror(req
, status
);
6185 status
= create_directory(conn
, req
, smb_dname
);
6187 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6189 if (!NT_STATUS_IS_OK(status
)) {
6191 if (!use_nt_status()
6192 && NT_STATUS_EQUAL(status
,
6193 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6195 * Yes, in the DOS error code case we get a
6196 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6197 * samba4 torture test.
6199 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6202 reply_nterror(req
, status
);
6206 reply_outbuf(req
, 0, 0);
6208 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6210 TALLOC_FREE(smb_dname
);
6211 END_PROFILE(SMBmkdir
);
6215 /****************************************************************************
6217 ****************************************************************************/
6219 void reply_rmdir(struct smb_request
*req
)
6221 connection_struct
*conn
= req
->conn
;
6222 struct smb_filename
*smb_dname
= NULL
;
6223 char *directory
= NULL
;
6225 TALLOC_CTX
*ctx
= talloc_tos();
6226 files_struct
*fsp
= NULL
;
6228 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6229 struct smbd_server_connection
*sconn
= req
->sconn
;
6231 START_PROFILE(SMBrmdir
);
6233 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6234 STR_TERMINATE
, &status
);
6235 if (!NT_STATUS_IS_OK(status
)) {
6236 reply_nterror(req
, status
);
6240 status
= filename_convert(ctx
, conn
,
6245 if (!NT_STATUS_IS_OK(status
)) {
6246 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6247 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6248 ERRSRV
, ERRbadpath
);
6251 reply_nterror(req
, status
);
6255 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6256 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6260 status
= SMB_VFS_CREATE_FILE(
6263 0, /* root_dir_fid */
6264 smb_dname
, /* fname */
6265 DELETE_ACCESS
, /* access_mask */
6266 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6268 FILE_OPEN
, /* create_disposition*/
6269 FILE_DIRECTORY_FILE
, /* create_options */
6270 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6271 0, /* oplock_request */
6273 0, /* allocation_size */
6274 0, /* private_flags */
6279 NULL
, NULL
); /* create context */
6281 if (!NT_STATUS_IS_OK(status
)) {
6282 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6283 /* We have re-scheduled this call. */
6286 reply_nterror(req
, status
);
6290 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6291 if (!NT_STATUS_IS_OK(status
)) {
6292 close_file(req
, fsp
, ERROR_CLOSE
);
6293 reply_nterror(req
, status
);
6297 if (!set_delete_on_close(fsp
, true,
6298 conn
->session_info
->security_token
,
6299 conn
->session_info
->unix_token
)) {
6300 close_file(req
, fsp
, ERROR_CLOSE
);
6301 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6305 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6306 if (!NT_STATUS_IS_OK(status
)) {
6307 reply_nterror(req
, status
);
6309 reply_outbuf(req
, 0, 0);
6312 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6314 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6316 TALLOC_FREE(smb_dname
);
6317 END_PROFILE(SMBrmdir
);
6321 /*******************************************************************
6322 Resolve wildcards in a filename rename.
6323 ********************************************************************/
6325 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6330 char *name2_copy
= NULL
;
6335 char *p
,*p2
, *pname1
, *pname2
;
6337 name2_copy
= talloc_strdup(ctx
, name2
);
6342 pname1
= strrchr_m(name1
,'/');
6343 pname2
= strrchr_m(name2_copy
,'/');
6345 if (!pname1
|| !pname2
) {
6349 /* Truncate the copy of name2 at the last '/' */
6352 /* Now go past the '/' */
6356 root1
= talloc_strdup(ctx
, pname1
);
6357 root2
= talloc_strdup(ctx
, pname2
);
6359 if (!root1
|| !root2
) {
6363 p
= strrchr_m(root1
,'.');
6366 ext1
= talloc_strdup(ctx
, p
+1);
6368 ext1
= talloc_strdup(ctx
, "");
6370 p
= strrchr_m(root2
,'.');
6373 ext2
= talloc_strdup(ctx
, p
+1);
6375 ext2
= talloc_strdup(ctx
, "");
6378 if (!ext1
|| !ext2
) {
6386 /* Hmmm. Should this be mb-aware ? */
6389 } else if (*p2
== '*') {
6391 root2
= talloc_asprintf(ctx
, "%s%s",
6410 /* Hmmm. Should this be mb-aware ? */
6413 } else if (*p2
== '*') {
6415 ext2
= talloc_asprintf(ctx
, "%s%s",
6431 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6436 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6448 /****************************************************************************
6449 Ensure open files have their names updated. Updated to notify other smbd's
6451 ****************************************************************************/
6453 static void rename_open_files(connection_struct
*conn
,
6454 struct share_mode_lock
*lck
,
6456 uint32_t orig_name_hash
,
6457 const struct smb_filename
*smb_fname_dst
)
6460 bool did_rename
= False
;
6462 uint32_t new_name_hash
= 0;
6464 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6465 fsp
= file_find_di_next(fsp
)) {
6466 /* fsp_name is a relative path under the fsp. To change this for other
6467 sharepaths we need to manipulate relative paths. */
6468 /* TODO - create the absolute path and manipulate the newname
6469 relative to the sharepath. */
6470 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6473 if (fsp
->name_hash
!= orig_name_hash
) {
6476 DEBUG(10, ("rename_open_files: renaming file %s "
6477 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6478 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6479 smb_fname_str_dbg(smb_fname_dst
)));
6481 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6482 if (NT_STATUS_IS_OK(status
)) {
6484 new_name_hash
= fsp
->name_hash
;
6489 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6490 "for %s\n", file_id_string_tos(&id
),
6491 smb_fname_str_dbg(smb_fname_dst
)));
6494 /* Send messages to all smbd's (not ourself) that the name has changed. */
6495 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6496 orig_name_hash
, new_name_hash
,
6501 /****************************************************************************
6502 We need to check if the source path is a parent directory of the destination
6503 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6504 refuse the rename with a sharing violation. Under UNIX the above call can
6505 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6506 probably need to check that the client is a Windows one before disallowing
6507 this as a UNIX client (one with UNIX extensions) can know the source is a
6508 symlink and make this decision intelligently. Found by an excellent bug
6509 report from <AndyLiebman@aol.com>.
6510 ****************************************************************************/
6512 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6513 const struct smb_filename
*smb_fname_dst
)
6515 const char *psrc
= smb_fname_src
->base_name
;
6516 const char *pdst
= smb_fname_dst
->base_name
;
6519 if (psrc
[0] == '.' && psrc
[1] == '/') {
6522 if (pdst
[0] == '.' && pdst
[1] == '/') {
6525 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6528 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6532 * Do the notify calls from a rename
6535 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6536 const struct smb_filename
*smb_fname_src
,
6537 const struct smb_filename
*smb_fname_dst
)
6539 char *parent_dir_src
= NULL
;
6540 char *parent_dir_dst
= NULL
;
6543 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6544 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6546 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6547 &parent_dir_src
, NULL
) ||
6548 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6549 &parent_dir_dst
, NULL
)) {
6553 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6554 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6555 smb_fname_src
->base_name
);
6556 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6557 smb_fname_dst
->base_name
);
6560 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6561 smb_fname_src
->base_name
);
6562 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6563 smb_fname_dst
->base_name
);
6566 /* this is a strange one. w2k3 gives an additional event for
6567 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6568 files, but not directories */
6570 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6571 FILE_NOTIFY_CHANGE_ATTRIBUTES
6572 |FILE_NOTIFY_CHANGE_CREATION
,
6573 smb_fname_dst
->base_name
);
6576 TALLOC_FREE(parent_dir_src
);
6577 TALLOC_FREE(parent_dir_dst
);
6580 /****************************************************************************
6581 Returns an error if the parent directory for a filename is open in an
6583 ****************************************************************************/
6585 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6586 const struct smb_filename
*smb_fname_dst_in
)
6588 char *parent_dir
= NULL
;
6589 struct smb_filename smb_fname_parent
;
6591 files_struct
*fsp
= NULL
;
6594 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6595 &parent_dir
, NULL
)) {
6596 return NT_STATUS_NO_MEMORY
;
6598 ZERO_STRUCT(smb_fname_parent
);
6599 smb_fname_parent
.base_name
= parent_dir
;
6601 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6603 return map_nt_error_from_unix(errno
);
6607 * We're only checking on this smbd here, mostly good
6608 * enough.. and will pass tests.
6611 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6612 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6613 fsp
= file_find_di_next(fsp
)) {
6614 if (fsp
->access_mask
& DELETE_ACCESS
) {
6615 return NT_STATUS_SHARING_VIOLATION
;
6618 return NT_STATUS_OK
;
6621 /****************************************************************************
6622 Rename an open file - given an fsp.
6623 ****************************************************************************/
6625 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6627 const struct smb_filename
*smb_fname_dst_in
,
6629 bool replace_if_exists
)
6631 TALLOC_CTX
*ctx
= talloc_tos();
6632 struct smb_filename
*smb_fname_dst
= NULL
;
6633 NTSTATUS status
= NT_STATUS_OK
;
6634 struct share_mode_lock
*lck
= NULL
;
6635 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
6636 bool dst_exists
, old_is_stream
, new_is_stream
;
6638 status
= check_name(conn
, smb_fname_dst_in
);
6639 if (!NT_STATUS_IS_OK(status
)) {
6643 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6644 if (!NT_STATUS_IS_OK(status
)) {
6648 if (file_has_open_streams(fsp
)) {
6649 return NT_STATUS_ACCESS_DENIED
;
6652 /* Make a copy of the dst smb_fname structs */
6654 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6655 if (smb_fname_dst
== NULL
) {
6656 status
= NT_STATUS_NO_MEMORY
;
6661 * Check for special case with case preserving and not
6662 * case sensitive. If the new last component differs from the original
6663 * last component only by case, then we should allow
6664 * the rename (user is trying to change the case of the
6667 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
6668 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6669 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6670 char *fname_dst_parent
= NULL
;
6671 const char *fname_dst_lcomp
= NULL
;
6672 char *orig_lcomp_path
= NULL
;
6673 char *orig_lcomp_stream
= NULL
;
6677 * Split off the last component of the processed
6678 * destination name. We will compare this to
6679 * the split components of smb_fname_dst->original_lcomp.
6681 if (!parent_dirname(ctx
,
6682 smb_fname_dst
->base_name
,
6684 &fname_dst_lcomp
)) {
6685 status
= NT_STATUS_NO_MEMORY
;
6690 * The original_lcomp component contains
6691 * the last_component of the path + stream
6692 * name (if a stream exists).
6694 * Split off the stream name so we
6695 * can check them separately.
6698 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
6699 /* POSIX - no stream component. */
6700 orig_lcomp_path
= talloc_strdup(ctx
,
6701 smb_fname_dst
->original_lcomp
);
6702 if (orig_lcomp_path
== NULL
) {
6706 ok
= split_stream_filename(ctx
,
6707 smb_fname_dst
->original_lcomp
,
6709 &orig_lcomp_stream
);
6713 TALLOC_FREE(fname_dst_parent
);
6714 status
= NT_STATUS_NO_MEMORY
;
6718 /* If the base names only differ by case, use original. */
6719 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
6722 * Replace the modified last component with the
6725 if (!ISDOT(fname_dst_parent
)) {
6726 tmp
= talloc_asprintf(smb_fname_dst
,
6731 tmp
= talloc_strdup(smb_fname_dst
,
6735 status
= NT_STATUS_NO_MEMORY
;
6736 TALLOC_FREE(fname_dst_parent
);
6737 TALLOC_FREE(orig_lcomp_path
);
6738 TALLOC_FREE(orig_lcomp_stream
);
6741 TALLOC_FREE(smb_fname_dst
->base_name
);
6742 smb_fname_dst
->base_name
= tmp
;
6745 /* If the stream_names only differ by case, use original. */
6746 if(!strcsequal(smb_fname_dst
->stream_name
,
6747 orig_lcomp_stream
)) {
6748 /* Use the original stream. */
6749 char *tmp
= talloc_strdup(smb_fname_dst
,
6752 status
= NT_STATUS_NO_MEMORY
;
6753 TALLOC_FREE(fname_dst_parent
);
6754 TALLOC_FREE(orig_lcomp_path
);
6755 TALLOC_FREE(orig_lcomp_stream
);
6758 TALLOC_FREE(smb_fname_dst
->stream_name
);
6759 smb_fname_dst
->stream_name
= tmp
;
6761 TALLOC_FREE(fname_dst_parent
);
6762 TALLOC_FREE(orig_lcomp_path
);
6763 TALLOC_FREE(orig_lcomp_stream
);
6767 * If the src and dest names are identical - including case,
6768 * don't do the rename, just return success.
6771 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6772 strcsequal(fsp
->fsp_name
->stream_name
,
6773 smb_fname_dst
->stream_name
)) {
6774 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6775 "- returning success\n",
6776 smb_fname_str_dbg(smb_fname_dst
)));
6777 status
= NT_STATUS_OK
;
6781 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6782 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6784 /* Return the correct error code if both names aren't streams. */
6785 if (!old_is_stream
&& new_is_stream
) {
6786 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6790 if (old_is_stream
&& !new_is_stream
) {
6791 status
= NT_STATUS_INVALID_PARAMETER
;
6795 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6797 if(!replace_if_exists
&& dst_exists
) {
6798 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6799 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6800 smb_fname_str_dbg(smb_fname_dst
)));
6801 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6806 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6807 &smb_fname_dst
->st
);
6808 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6810 /* The file can be open when renaming a stream */
6811 if (dst_fsp
&& !new_is_stream
) {
6812 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6813 status
= NT_STATUS_ACCESS_DENIED
;
6818 /* Ensure we have a valid stat struct for the source. */
6819 status
= vfs_stat_fsp(fsp
);
6820 if (!NT_STATUS_IS_OK(status
)) {
6824 status
= can_rename(conn
, fsp
, attrs
);
6826 if (!NT_STATUS_IS_OK(status
)) {
6827 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6828 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6829 smb_fname_str_dbg(smb_fname_dst
)));
6830 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6831 status
= NT_STATUS_ACCESS_DENIED
;
6835 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6836 status
= NT_STATUS_ACCESS_DENIED
;
6840 /* Do we have rights to move into the destination ? */
6841 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
6842 /* We're moving a directory. */
6843 access_mask
= SEC_DIR_ADD_SUBDIR
;
6845 status
= check_parent_access(conn
,
6848 if (!NT_STATUS_IS_OK(status
)) {
6849 DBG_INFO("check_parent_access on "
6850 "dst %s returned %s\n",
6851 smb_fname_str_dbg(smb_fname_dst
),
6856 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6859 * We have the file open ourselves, so not being able to get the
6860 * corresponding share mode lock is a fatal error.
6863 SMB_ASSERT(lck
!= NULL
);
6865 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6866 uint32_t create_options
= fsp
->fh
->private_options
;
6868 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6869 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6870 smb_fname_str_dbg(smb_fname_dst
)));
6872 if (!fsp
->is_directory
&&
6873 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
6874 (lp_map_archive(SNUM(conn
)) ||
6875 lp_store_dos_attributes(SNUM(conn
)))) {
6876 /* We must set the archive bit on the newly
6878 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6879 uint32_t old_dosmode
= dos_mode(conn
,
6881 file_set_dosmode(conn
,
6883 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6889 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6892 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6896 * A rename acts as a new file create w.r.t. allowing an initial delete
6897 * on close, probably because in Windows there is a new handle to the
6898 * new file. If initial delete on close was requested but not
6899 * originally set, we need to set it here. This is probably not 100% correct,
6900 * but will work for the CIFSFS client which in non-posix mode
6901 * depends on these semantics. JRA.
6904 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6905 status
= can_set_delete_on_close(fsp
, 0);
6907 if (NT_STATUS_IS_OK(status
)) {
6908 /* Note that here we set the *inital* delete on close flag,
6909 * not the regular one. The magic gets handled in close. */
6910 fsp
->initial_delete_on_close
= True
;
6914 status
= NT_STATUS_OK
;
6920 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6921 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6923 status
= map_nt_error_from_unix(errno
);
6926 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6927 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6928 smb_fname_str_dbg(smb_fname_dst
)));
6931 TALLOC_FREE(smb_fname_dst
);
6936 /****************************************************************************
6937 The guts of the rename command, split out so it may be called by the NT SMB
6939 ****************************************************************************/
6941 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6942 connection_struct
*conn
,
6943 struct smb_request
*req
,
6944 struct smb_filename
*smb_fname_src
,
6945 struct smb_filename
*smb_fname_dst
,
6947 bool replace_if_exists
,
6950 uint32_t access_mask
)
6952 char *fname_src_dir
= NULL
;
6953 struct smb_filename
*smb_fname_src_dir
= NULL
;
6954 char *fname_src_mask
= NULL
;
6956 NTSTATUS status
= NT_STATUS_OK
;
6957 struct smb_Dir
*dir_hnd
= NULL
;
6958 const char *dname
= NULL
;
6959 char *talloced
= NULL
;
6961 int create_options
= 0;
6962 bool posix_pathnames
= (req
!= NULL
&& req
->posix_pathnames
);
6966 * Split the old name into directory and last component
6967 * strings. Note that unix_convert may have stripped off a
6968 * leading ./ from both name and newname if the rename is
6969 * at the root of the share. We need to make sure either both
6970 * name and newname contain a / character or neither of them do
6971 * as this is checked in resolve_wildcards().
6974 /* Split up the directory from the filename/mask. */
6975 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6976 &fname_src_dir
, &fname_src_mask
);
6977 if (!NT_STATUS_IS_OK(status
)) {
6978 status
= NT_STATUS_NO_MEMORY
;
6983 * We should only check the mangled cache
6984 * here if unix_convert failed. This means
6985 * that the path in 'mask' doesn't exist
6986 * on the file system and so we need to look
6987 * for a possible mangle. This patch from
6988 * Tine Smukavec <valentin.smukavec@hermes.si>.
6991 if (!VALID_STAT(smb_fname_src
->st
) &&
6992 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6993 char *new_mask
= NULL
;
6994 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6997 TALLOC_FREE(fname_src_mask
);
6998 fname_src_mask
= new_mask
;
7002 if (!src_has_wild
) {
7006 * Only one file needs to be renamed. Append the mask back
7007 * onto the directory.
7009 TALLOC_FREE(smb_fname_src
->base_name
);
7010 if (ISDOT(fname_src_dir
)) {
7011 /* Ensure we use canonical names on open. */
7012 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7016 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7021 if (!smb_fname_src
->base_name
) {
7022 status
= NT_STATUS_NO_MEMORY
;
7026 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7027 "case_preserve = %d, short case preserve = %d, "
7028 "directory = %s, newname = %s, "
7029 "last_component_dest = %s\n",
7030 conn
->case_sensitive
, conn
->case_preserve
,
7031 conn
->short_case_preserve
,
7032 smb_fname_str_dbg(smb_fname_src
),
7033 smb_fname_str_dbg(smb_fname_dst
),
7034 smb_fname_dst
->original_lcomp
));
7036 /* The dest name still may have wildcards. */
7037 if (dest_has_wild
) {
7038 char *fname_dst_mod
= NULL
;
7039 if (!resolve_wildcards(smb_fname_dst
,
7040 smb_fname_src
->base_name
,
7041 smb_fname_dst
->base_name
,
7043 DEBUG(6, ("rename_internals: resolve_wildcards "
7045 smb_fname_src
->base_name
,
7046 smb_fname_dst
->base_name
));
7047 status
= NT_STATUS_NO_MEMORY
;
7050 TALLOC_FREE(smb_fname_dst
->base_name
);
7051 smb_fname_dst
->base_name
= fname_dst_mod
;
7054 ZERO_STRUCT(smb_fname_src
->st
);
7055 if (posix_pathnames
) {
7056 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
7058 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
7061 status
= map_nt_error_from_unix_common(errno
);
7065 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7066 create_options
|= FILE_DIRECTORY_FILE
;
7069 status
= SMB_VFS_CREATE_FILE(
7072 0, /* root_dir_fid */
7073 smb_fname_src
, /* fname */
7074 access_mask
, /* access_mask */
7075 (FILE_SHARE_READ
| /* share_access */
7077 FILE_OPEN
, /* create_disposition*/
7078 create_options
, /* create_options */
7079 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7080 0, /* oplock_request */
7082 0, /* allocation_size */
7083 0, /* private_flags */
7088 NULL
, NULL
); /* create context */
7090 if (!NT_STATUS_IS_OK(status
)) {
7091 DEBUG(3, ("Could not open rename source %s: %s\n",
7092 smb_fname_str_dbg(smb_fname_src
),
7093 nt_errstr(status
)));
7097 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7098 attrs
, replace_if_exists
);
7100 close_file(req
, fsp
, NORMAL_CLOSE
);
7102 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7103 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
7104 smb_fname_str_dbg(smb_fname_dst
)));
7110 * Wildcards - process each file that matches.
7112 if (strequal(fname_src_mask
, "????????.???")) {
7113 TALLOC_FREE(fname_src_mask
);
7114 fname_src_mask
= talloc_strdup(ctx
, "*");
7115 if (!fname_src_mask
) {
7116 status
= NT_STATUS_NO_MEMORY
;
7121 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7125 smb_fname_src
->flags
);
7126 if (smb_fname_src_dir
== NULL
) {
7127 status
= NT_STATUS_NO_MEMORY
;
7131 status
= check_name(conn
, smb_fname_src_dir
);
7132 if (!NT_STATUS_IS_OK(status
)) {
7136 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
7138 if (dir_hnd
== NULL
) {
7139 status
= map_nt_error_from_unix(errno
);
7143 status
= NT_STATUS_NO_SUCH_FILE
;
7145 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7146 * - gentest fix. JRA
7149 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
7151 files_struct
*fsp
= NULL
;
7152 char *destname
= NULL
;
7153 bool sysdir_entry
= False
;
7155 /* Quick check for "." and ".." */
7156 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7157 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
7158 sysdir_entry
= True
;
7160 TALLOC_FREE(talloced
);
7165 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7166 &smb_fname_src
->st
, false)) {
7167 TALLOC_FREE(talloced
);
7171 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
7172 TALLOC_FREE(talloced
);
7177 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7181 TALLOC_FREE(smb_fname_src
->base_name
);
7182 if (ISDOT(fname_src_dir
)) {
7183 /* Ensure we use canonical names on open. */
7184 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7188 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7193 if (!smb_fname_src
->base_name
) {
7194 status
= NT_STATUS_NO_MEMORY
;
7198 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7199 smb_fname_dst
->base_name
,
7201 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7202 smb_fname_src
->base_name
, destname
));
7203 TALLOC_FREE(talloced
);
7207 status
= NT_STATUS_NO_MEMORY
;
7211 TALLOC_FREE(smb_fname_dst
->base_name
);
7212 smb_fname_dst
->base_name
= destname
;
7214 ZERO_STRUCT(smb_fname_src
->st
);
7215 if (posix_pathnames
) {
7216 SMB_VFS_LSTAT(conn
, smb_fname_src
);
7218 SMB_VFS_STAT(conn
, smb_fname_src
);
7223 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7224 create_options
|= FILE_DIRECTORY_FILE
;
7227 status
= SMB_VFS_CREATE_FILE(
7230 0, /* root_dir_fid */
7231 smb_fname_src
, /* fname */
7232 access_mask
, /* access_mask */
7233 (FILE_SHARE_READ
| /* share_access */
7235 FILE_OPEN
, /* create_disposition*/
7236 create_options
, /* create_options */
7237 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7238 0, /* oplock_request */
7240 0, /* allocation_size */
7241 0, /* private_flags */
7246 NULL
, NULL
); /* create context */
7248 if (!NT_STATUS_IS_OK(status
)) {
7249 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7250 "returned %s rename %s -> %s\n",
7252 smb_fname_str_dbg(smb_fname_src
),
7253 smb_fname_str_dbg(smb_fname_dst
)));
7257 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7259 if (!smb_fname_dst
->original_lcomp
) {
7260 status
= NT_STATUS_NO_MEMORY
;
7264 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7265 attrs
, replace_if_exists
);
7267 close_file(req
, fsp
, NORMAL_CLOSE
);
7269 if (!NT_STATUS_IS_OK(status
)) {
7270 DEBUG(3, ("rename_internals_fsp returned %s for "
7271 "rename %s -> %s\n", nt_errstr(status
),
7272 smb_fname_str_dbg(smb_fname_src
),
7273 smb_fname_str_dbg(smb_fname_dst
)));
7279 DEBUG(3,("rename_internals: doing rename on %s -> "
7280 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7281 smb_fname_str_dbg(smb_fname_src
)));
7282 TALLOC_FREE(talloced
);
7284 TALLOC_FREE(dir_hnd
);
7286 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7287 status
= map_nt_error_from_unix(errno
);
7291 TALLOC_FREE(talloced
);
7292 TALLOC_FREE(smb_fname_src_dir
);
7293 TALLOC_FREE(fname_src_dir
);
7294 TALLOC_FREE(fname_src_mask
);
7298 /****************************************************************************
7300 ****************************************************************************/
7302 void reply_mv(struct smb_request
*req
)
7304 connection_struct
*conn
= req
->conn
;
7306 char *newname
= NULL
;
7310 bool src_has_wcard
= False
;
7311 bool dest_has_wcard
= False
;
7312 TALLOC_CTX
*ctx
= talloc_tos();
7313 struct smb_filename
*smb_fname_src
= NULL
;
7314 struct smb_filename
*smb_fname_dst
= NULL
;
7315 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
) |
7316 (req
->posix_pathnames
?
7317 UCF_UNIX_NAME_LOOKUP
:
7318 UCF_COND_ALLOW_WCARD_LCOMP
);
7319 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
) |
7321 (req
->posix_pathnames
?
7323 UCF_COND_ALLOW_WCARD_LCOMP
);
7324 bool stream_rename
= false;
7326 START_PROFILE(SMBmv
);
7329 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7333 attrs
= SVAL(req
->vwv
+0, 0);
7335 p
= (const char *)req
->buf
+ 1;
7336 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7337 &status
, &src_has_wcard
);
7338 if (!NT_STATUS_IS_OK(status
)) {
7339 reply_nterror(req
, status
);
7343 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7344 &status
, &dest_has_wcard
);
7345 if (!NT_STATUS_IS_OK(status
)) {
7346 reply_nterror(req
, status
);
7350 if (!req
->posix_pathnames
) {
7351 /* The newname must begin with a ':' if the
7352 name contains a ':'. */
7353 if (strchr_m(name
, ':')) {
7354 if (newname
[0] != ':') {
7355 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7358 stream_rename
= true;
7362 status
= filename_convert(ctx
,
7369 if (!NT_STATUS_IS_OK(status
)) {
7370 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7371 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7372 ERRSRV
, ERRbadpath
);
7375 reply_nterror(req
, status
);
7379 status
= filename_convert(ctx
,
7386 if (!NT_STATUS_IS_OK(status
)) {
7387 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7388 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7389 ERRSRV
, ERRbadpath
);
7392 reply_nterror(req
, status
);
7396 if (stream_rename
) {
7397 /* smb_fname_dst->base_name must be the same as
7398 smb_fname_src->base_name. */
7399 TALLOC_FREE(smb_fname_dst
->base_name
);
7400 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7401 smb_fname_src
->base_name
);
7402 if (!smb_fname_dst
->base_name
) {
7403 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7408 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7409 smb_fname_str_dbg(smb_fname_dst
)));
7411 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7412 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7414 if (!NT_STATUS_IS_OK(status
)) {
7415 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7416 /* We have re-scheduled this call. */
7419 reply_nterror(req
, status
);
7423 reply_outbuf(req
, 0, 0);
7425 TALLOC_FREE(smb_fname_src
);
7426 TALLOC_FREE(smb_fname_dst
);
7431 /*******************************************************************
7432 Copy a file as part of a reply_copy.
7433 ******************************************************************/
7436 * TODO: check error codes on all callers
7439 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7440 connection_struct
*conn
,
7441 struct smb_filename
*smb_fname_src
,
7442 struct smb_filename
*smb_fname_dst
,
7445 bool target_is_directory
)
7447 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7449 files_struct
*fsp1
,*fsp2
;
7451 uint32_t new_create_disposition
;
7455 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7456 if (smb_fname_dst_tmp
== NULL
) {
7457 return NT_STATUS_NO_MEMORY
;
7461 * If the target is a directory, extract the last component from the
7462 * src filename and append it to the dst filename
7464 if (target_is_directory
) {
7467 /* dest/target can't be a stream if it's a directory. */
7468 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7470 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7474 p
= smb_fname_src
->base_name
;
7476 smb_fname_dst_tmp
->base_name
=
7477 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7479 if (!smb_fname_dst_tmp
->base_name
) {
7480 status
= NT_STATUS_NO_MEMORY
;
7485 status
= vfs_file_exist(conn
, smb_fname_src
);
7486 if (!NT_STATUS_IS_OK(status
)) {
7490 if (!target_is_directory
&& count
) {
7491 new_create_disposition
= FILE_OPEN
;
7493 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7496 &new_create_disposition
,
7499 status
= NT_STATUS_INVALID_PARAMETER
;
7504 /* Open the src file for reading. */
7505 status
= SMB_VFS_CREATE_FILE(
7508 0, /* root_dir_fid */
7509 smb_fname_src
, /* fname */
7510 FILE_GENERIC_READ
, /* access_mask */
7511 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7512 FILE_OPEN
, /* create_disposition*/
7513 0, /* create_options */
7514 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7515 INTERNAL_OPEN_ONLY
, /* oplock_request */
7517 0, /* allocation_size */
7518 0, /* private_flags */
7523 NULL
, NULL
); /* create context */
7525 if (!NT_STATUS_IS_OK(status
)) {
7529 dosattrs
= dos_mode(conn
, smb_fname_src
);
7531 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7532 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7535 /* Open the dst file for writing. */
7536 status
= SMB_VFS_CREATE_FILE(
7539 0, /* root_dir_fid */
7540 smb_fname_dst
, /* fname */
7541 FILE_GENERIC_WRITE
, /* access_mask */
7542 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7543 new_create_disposition
, /* create_disposition*/
7544 0, /* create_options */
7545 dosattrs
, /* file_attributes */
7546 INTERNAL_OPEN_ONLY
, /* oplock_request */
7548 0, /* allocation_size */
7549 0, /* private_flags */
7554 NULL
, NULL
); /* create context */
7556 if (!NT_STATUS_IS_OK(status
)) {
7557 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7561 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7562 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7564 DEBUG(0, ("error - vfs lseek returned error %s\n",
7566 status
= map_nt_error_from_unix(errno
);
7567 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7568 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7573 /* Do the actual copy. */
7574 if (smb_fname_src
->st
.st_ex_size
) {
7575 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7580 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7582 /* Ensure the modtime is set correctly on the destination file. */
7583 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7586 * As we are opening fsp1 read-only we only expect
7587 * an error on close on fsp2 if we are out of space.
7588 * Thus we don't look at the error return from the
7591 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7593 if (!NT_STATUS_IS_OK(status
)) {
7597 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7598 status
= NT_STATUS_DISK_FULL
;
7602 status
= NT_STATUS_OK
;
7605 TALLOC_FREE(smb_fname_dst_tmp
);
7609 /****************************************************************************
7610 Reply to a file copy.
7611 ****************************************************************************/
7613 void reply_copy(struct smb_request
*req
)
7615 connection_struct
*conn
= req
->conn
;
7616 struct smb_filename
*smb_fname_src
= NULL
;
7617 struct smb_filename
*smb_fname_src_dir
= NULL
;
7618 struct smb_filename
*smb_fname_dst
= NULL
;
7619 char *fname_src
= NULL
;
7620 char *fname_dst
= NULL
;
7621 char *fname_src_mask
= NULL
;
7622 char *fname_src_dir
= NULL
;
7625 int error
= ERRnoaccess
;
7629 bool target_is_directory
=False
;
7630 bool source_has_wild
= False
;
7631 bool dest_has_wild
= False
;
7633 uint32_t ucf_flags_src
= UCF_COND_ALLOW_WCARD_LCOMP
|
7634 ucf_flags_from_smb_request(req
);
7635 uint32_t ucf_flags_dst
= UCF_COND_ALLOW_WCARD_LCOMP
|
7636 ucf_flags_from_smb_request(req
);
7637 TALLOC_CTX
*ctx
= talloc_tos();
7639 START_PROFILE(SMBcopy
);
7642 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7646 tid2
= SVAL(req
->vwv
+0, 0);
7647 ofun
= SVAL(req
->vwv
+1, 0);
7648 flags
= SVAL(req
->vwv
+2, 0);
7650 p
= (const char *)req
->buf
;
7651 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7652 &status
, &source_has_wild
);
7653 if (!NT_STATUS_IS_OK(status
)) {
7654 reply_nterror(req
, status
);
7657 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7658 &status
, &dest_has_wild
);
7659 if (!NT_STATUS_IS_OK(status
)) {
7660 reply_nterror(req
, status
);
7664 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7666 if (tid2
!= conn
->cnum
) {
7667 /* can't currently handle inter share copies XXXX */
7668 DEBUG(3,("Rejecting inter-share copy\n"));
7669 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7673 status
= filename_convert(ctx
, conn
,
7678 if (!NT_STATUS_IS_OK(status
)) {
7679 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7680 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7681 ERRSRV
, ERRbadpath
);
7684 reply_nterror(req
, status
);
7688 status
= filename_convert(ctx
, conn
,
7693 if (!NT_STATUS_IS_OK(status
)) {
7694 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7695 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7696 ERRSRV
, ERRbadpath
);
7699 reply_nterror(req
, status
);
7703 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7705 if ((flags
&1) && target_is_directory
) {
7706 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7710 if ((flags
&2) && !target_is_directory
) {
7711 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7715 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7716 /* wants a tree copy! XXXX */
7717 DEBUG(3,("Rejecting tree copy\n"));
7718 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7722 /* Split up the directory from the filename/mask. */
7723 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7724 &fname_src_dir
, &fname_src_mask
);
7725 if (!NT_STATUS_IS_OK(status
)) {
7726 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7731 * We should only check the mangled cache
7732 * here if unix_convert failed. This means
7733 * that the path in 'mask' doesn't exist
7734 * on the file system and so we need to look
7735 * for a possible mangle. This patch from
7736 * Tine Smukavec <valentin.smukavec@hermes.si>.
7738 if (!VALID_STAT(smb_fname_src
->st
) &&
7739 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7740 char *new_mask
= NULL
;
7741 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7742 &new_mask
, conn
->params
);
7744 /* Use demangled name if one was successfully found. */
7746 TALLOC_FREE(fname_src_mask
);
7747 fname_src_mask
= new_mask
;
7751 if (!source_has_wild
) {
7754 * Only one file needs to be copied. Append the mask back onto
7757 TALLOC_FREE(smb_fname_src
->base_name
);
7758 if (ISDOT(fname_src_dir
)) {
7759 /* Ensure we use canonical names on open. */
7760 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7764 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7769 if (!smb_fname_src
->base_name
) {
7770 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7774 if (dest_has_wild
) {
7775 char *fname_dst_mod
= NULL
;
7776 if (!resolve_wildcards(smb_fname_dst
,
7777 smb_fname_src
->base_name
,
7778 smb_fname_dst
->base_name
,
7780 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7783 TALLOC_FREE(smb_fname_dst
->base_name
);
7784 smb_fname_dst
->base_name
= fname_dst_mod
;
7787 status
= check_name(conn
, smb_fname_src
);
7788 if (!NT_STATUS_IS_OK(status
)) {
7789 reply_nterror(req
, status
);
7793 status
= check_name(conn
, smb_fname_dst
);
7794 if (!NT_STATUS_IS_OK(status
)) {
7795 reply_nterror(req
, status
);
7799 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7800 ofun
, count
, target_is_directory
);
7802 if(!NT_STATUS_IS_OK(status
)) {
7803 reply_nterror(req
, status
);
7809 struct smb_Dir
*dir_hnd
= NULL
;
7810 const char *dname
= NULL
;
7811 char *talloced
= NULL
;
7815 * There is a wildcard that requires us to actually read the
7816 * src dir and copy each file matching the mask to the dst.
7817 * Right now streams won't be copied, but this could
7818 * presumably be added with a nested loop for reach dir entry.
7820 SMB_ASSERT(!smb_fname_src
->stream_name
);
7821 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7823 smb_fname_src
->stream_name
= NULL
;
7824 smb_fname_dst
->stream_name
= NULL
;
7826 if (strequal(fname_src_mask
,"????????.???")) {
7827 TALLOC_FREE(fname_src_mask
);
7828 fname_src_mask
= talloc_strdup(ctx
, "*");
7829 if (!fname_src_mask
) {
7830 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7835 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7839 smb_fname_src
->flags
);
7840 if (smb_fname_src_dir
== NULL
) {
7841 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7845 status
= check_name(conn
, smb_fname_src_dir
);
7846 if (!NT_STATUS_IS_OK(status
)) {
7847 reply_nterror(req
, status
);
7851 dir_hnd
= OpenDir(ctx
,
7856 if (dir_hnd
== NULL
) {
7857 status
= map_nt_error_from_unix(errno
);
7858 reply_nterror(req
, status
);
7864 /* Iterate over the src dir copying each entry to the dst. */
7865 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7866 &smb_fname_src
->st
, &talloced
))) {
7867 char *destname
= NULL
;
7869 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7870 TALLOC_FREE(talloced
);
7874 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7875 &smb_fname_src
->st
, false)) {
7876 TALLOC_FREE(talloced
);
7880 if(!mask_match(dname
, fname_src_mask
,
7881 conn
->case_sensitive
)) {
7882 TALLOC_FREE(talloced
);
7886 error
= ERRnoaccess
;
7888 /* Get the src smb_fname struct setup. */
7889 TALLOC_FREE(smb_fname_src
->base_name
);
7890 if (ISDOT(fname_src_dir
)) {
7891 /* Ensure we use canonical names on open. */
7892 smb_fname_src
->base_name
=
7893 talloc_asprintf(smb_fname_src
, "%s",
7896 smb_fname_src
->base_name
=
7897 talloc_asprintf(smb_fname_src
, "%s/%s",
7898 fname_src_dir
, dname
);
7901 if (!smb_fname_src
->base_name
) {
7902 TALLOC_FREE(dir_hnd
);
7903 TALLOC_FREE(talloced
);
7904 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7908 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7909 smb_fname_dst
->base_name
,
7911 TALLOC_FREE(talloced
);
7915 TALLOC_FREE(dir_hnd
);
7916 TALLOC_FREE(talloced
);
7917 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7921 TALLOC_FREE(smb_fname_dst
->base_name
);
7922 smb_fname_dst
->base_name
= destname
;
7924 status
= check_name(conn
, smb_fname_src
);
7925 if (!NT_STATUS_IS_OK(status
)) {
7926 TALLOC_FREE(dir_hnd
);
7927 TALLOC_FREE(talloced
);
7928 reply_nterror(req
, status
);
7932 status
= check_name(conn
, smb_fname_dst
);
7933 if (!NT_STATUS_IS_OK(status
)) {
7934 TALLOC_FREE(dir_hnd
);
7935 TALLOC_FREE(talloced
);
7936 reply_nterror(req
, status
);
7940 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7941 smb_fname_src
->base_name
,
7942 smb_fname_dst
->base_name
));
7944 status
= copy_file(ctx
, conn
, smb_fname_src
,
7945 smb_fname_dst
, ofun
, count
,
7946 target_is_directory
);
7947 if (NT_STATUS_IS_OK(status
)) {
7951 TALLOC_FREE(talloced
);
7953 TALLOC_FREE(dir_hnd
);
7957 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7961 reply_outbuf(req
, 1, 0);
7962 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7964 TALLOC_FREE(smb_fname_src
);
7965 TALLOC_FREE(smb_fname_src_dir
);
7966 TALLOC_FREE(smb_fname_dst
);
7967 TALLOC_FREE(fname_src
);
7968 TALLOC_FREE(fname_dst
);
7969 TALLOC_FREE(fname_src_mask
);
7970 TALLOC_FREE(fname_src_dir
);
7972 END_PROFILE(SMBcopy
);
7977 #define DBGC_CLASS DBGC_LOCKING
7979 /****************************************************************************
7980 Get a lock pid, dealing with large count requests.
7981 ****************************************************************************/
7983 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7984 bool large_file_format
)
7986 if(!large_file_format
)
7987 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7989 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7992 /****************************************************************************
7993 Get a lock count, dealing with large count requests.
7994 ****************************************************************************/
7996 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7997 bool large_file_format
)
8001 if(!large_file_format
) {
8002 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
8005 * No BVAL, this is reversed!
8007 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
8008 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
8014 /****************************************************************************
8015 Get a lock offset, dealing with large offset requests.
8016 ****************************************************************************/
8018 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
8019 bool large_file_format
)
8021 uint64_t offset
= 0;
8023 if(!large_file_format
) {
8024 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
8027 * No BVAL, this is reversed!
8029 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
8030 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
8036 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
8041 struct smbd_lock_element
*locks
,
8044 connection_struct
*conn
= req
->conn
;
8046 NTSTATUS status
= NT_STATUS_OK
;
8050 /* Setup the timeout in seconds. */
8052 if (!lp_blocking_locks(SNUM(conn
))) {
8056 for(i
= 0; i
< (int)num_locks
; i
++) {
8057 struct smbd_lock_element
*e
= &locks
[i
];
8059 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8060 "%llu, file %s timeout = %d\n",
8063 (unsigned long long)e
->smblctx
,
8067 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8068 struct blocking_lock_record
*blr
= NULL
;
8070 if (num_locks
> 1) {
8072 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8073 * if the lock vector contains one entry. When given multiple cancel
8074 * requests in a single PDU we expect the server to return an
8075 * error. Windows servers seem to accept the request but only
8076 * cancel the first lock.
8077 * JRA - Do what Windows does (tm) :-).
8081 /* MS-CIFS (2.2.4.32.1) behavior. */
8082 return NT_STATUS_DOS(ERRDOS
,
8083 ERRcancelviolation
);
8085 /* Windows behavior. */
8087 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8088 "cancel request\n"));
8094 if (lp_blocking_locks(SNUM(conn
))) {
8096 /* Schedule a message to ourselves to
8097 remove the blocking lock record and
8098 return the right error. */
8100 blr
= blocking_lock_cancel_smb1(fsp
,
8106 NT_STATUS_FILE_LOCK_CONFLICT
);
8108 return NT_STATUS_DOS(
8110 ERRcancelviolation
);
8113 /* Remove a matching pending lock. */
8114 status
= do_lock_cancel(fsp
,
8120 bool blocking_lock
= timeout
? true : false;
8121 bool defer_lock
= false;
8122 struct byte_range_lock
*br_lck
;
8123 uint64_t block_smblctx
;
8125 br_lck
= do_lock(req
->sconn
->msg_ctx
,
8136 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
8137 /* Windows internal resolution for blocking locks seems
8138 to be about 200ms... Don't wait for less than that. JRA. */
8139 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
8140 timeout
= lp_lock_spin_time();
8145 /* If a lock sent with timeout of zero would fail, and
8146 * this lock has been requested multiple times,
8147 * according to brl_lock_failed() we convert this
8148 * request to a blocking lock with a timeout of between
8149 * 150 - 300 milliseconds.
8151 * If lp_lock_spin_time() has been set to 0, we skip
8152 * this blocking retry and fail immediately.
8154 * Replacement for do_lock_spin(). JRA. */
8156 if (!req
->sconn
->using_smb2
&&
8157 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
8158 lp_lock_spin_time() && !blocking_lock
&&
8159 NT_STATUS_EQUAL((status
),
8160 NT_STATUS_FILE_LOCK_CONFLICT
))
8163 timeout
= lp_lock_spin_time();
8166 if (br_lck
&& defer_lock
) {
8168 * A blocking lock was requested. Package up
8169 * this smb into a queued request and push it
8170 * onto the blocking lock queue.
8172 if(push_blocking_lock_request(br_lck
,
8183 TALLOC_FREE(br_lck
);
8185 return NT_STATUS_OK
;
8189 TALLOC_FREE(br_lck
);
8192 if (!NT_STATUS_IS_OK(status
)) {
8197 /* If any of the above locks failed, then we must unlock
8198 all of the previous locks (X/Open spec). */
8200 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
8202 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8203 i
= -1; /* we want to skip the for loop */
8207 * Ensure we don't do a remove on the lock that just failed,
8208 * as under POSIX rules, if we have a lock already there, we
8209 * will delete it (and we shouldn't) .....
8211 for(i
--; i
>= 0; i
--) {
8212 struct smbd_lock_element
*e
= &locks
[i
];
8214 do_unlock(req
->sconn
->msg_ctx
,
8224 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8225 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
8227 return NT_STATUS_OK
;
8230 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
8232 uint16_t num_ulocks
,
8233 struct smbd_lock_element
*ulocks
)
8237 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8238 struct smbd_lock_element
*e
= &ulocks
[i
];
8241 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8242 "pid %u, file %s\n", __func__
,
8245 (unsigned int)e
->smblctx
,
8248 if (e
->brltype
!= UNLOCK_LOCK
) {
8249 /* this can only happen with SMB2 */
8250 return NT_STATUS_INVALID_PARAMETER
;
8253 status
= do_unlock(req
->sconn
->msg_ctx
,
8260 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
8261 nt_errstr(status
)));
8263 if (!NT_STATUS_IS_OK(status
)) {
8268 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
8271 return NT_STATUS_OK
;
8274 /****************************************************************************
8275 Reply to a lockingX request.
8276 ****************************************************************************/
8278 void reply_lockingX(struct smb_request
*req
)
8280 connection_struct
*conn
= req
->conn
;
8282 unsigned char locktype
;
8283 unsigned char oplocklevel
;
8284 uint16_t num_ulocks
;
8286 int32_t lock_timeout
;
8288 const uint8_t *data
;
8289 bool large_file_format
;
8290 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8291 struct smbd_lock_element
*ulocks
;
8292 struct smbd_lock_element
*locks
;
8295 START_PROFILE(SMBlockingX
);
8298 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8299 END_PROFILE(SMBlockingX
);
8303 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8304 locktype
= CVAL(req
->vwv
+3, 0);
8305 oplocklevel
= CVAL(req
->vwv
+3, 1);
8306 num_ulocks
= SVAL(req
->vwv
+6, 0);
8307 num_locks
= SVAL(req
->vwv
+7, 0);
8308 lock_timeout
= IVAL(req
->vwv
+4, 0);
8309 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8311 if (!check_fsp(conn
, req
, fsp
)) {
8312 END_PROFILE(SMBlockingX
);
8318 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8319 /* we don't support these - and CANCEL_LOCK makes w2k
8320 and XP reboot so I don't really want to be
8321 compatible! (tridge) */
8322 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8323 END_PROFILE(SMBlockingX
);
8327 /* Check if this is an oplock break on a file
8328 we have granted an oplock on.
8330 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8331 /* Client can insist on breaking to none. */
8332 bool break_to_none
= (oplocklevel
== 0);
8335 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8336 "for %s\n", (unsigned int)oplocklevel
,
8337 fsp_fnum_dbg(fsp
)));
8340 * Make sure we have granted an exclusive or batch oplock on
8344 if (fsp
->oplock_type
== 0) {
8346 /* The Samba4 nbench simulator doesn't understand
8347 the difference between break to level2 and break
8348 to none from level2 - it sends oplock break
8349 replies in both cases. Don't keep logging an error
8350 message here - just ignore it. JRA. */
8352 DEBUG(5,("reply_lockingX: Error : oplock break from "
8353 "client for %s (oplock=%d) and no "
8354 "oplock granted on this file (%s).\n",
8355 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8358 /* if this is a pure oplock break request then don't
8360 if (num_locks
== 0 && num_ulocks
== 0) {
8361 END_PROFILE(SMBlockingX
);
8364 END_PROFILE(SMBlockingX
);
8365 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8370 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8372 result
= remove_oplock(fsp
);
8374 result
= downgrade_oplock(fsp
);
8378 DEBUG(0, ("reply_lockingX: error in removing "
8379 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8380 /* Hmmm. Is this panic justified? */
8381 smb_panic("internal tdb error");
8384 /* if this is a pure oplock break request then don't send a
8386 if (num_locks
== 0 && num_ulocks
== 0) {
8387 /* Sanity check - ensure a pure oplock break is not a
8389 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8390 DEBUG(0,("reply_lockingX: Error : pure oplock "
8391 "break is a chained %d request !\n",
8392 (unsigned int)CVAL(req
->vwv
+0, 0)));
8394 END_PROFILE(SMBlockingX
);
8400 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8401 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8402 END_PROFILE(SMBlockingX
);
8406 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8407 if (ulocks
== NULL
) {
8408 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8409 END_PROFILE(SMBlockingX
);
8413 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8414 if (locks
== NULL
) {
8415 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8416 END_PROFILE(SMBlockingX
);
8420 /* Data now points at the beginning of the list
8421 of smb_unlkrng structs */
8422 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8423 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8424 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8425 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8426 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8429 /* Now do any requested locks */
8430 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8432 /* Data now points at the beginning of the list
8433 of smb_lkrng structs */
8435 for(i
= 0; i
< (int)num_locks
; i
++) {
8436 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8437 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8438 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8440 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8441 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8442 locks
[i
].brltype
= PENDING_READ_LOCK
;
8444 locks
[i
].brltype
= READ_LOCK
;
8447 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8448 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8450 locks
[i
].brltype
= WRITE_LOCK
;
8455 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8456 if (!NT_STATUS_IS_OK(status
)) {
8457 END_PROFILE(SMBlockingX
);
8458 reply_nterror(req
, status
);
8462 status
= smbd_do_locking(req
, fsp
,
8463 locktype
, lock_timeout
,
8466 if (!NT_STATUS_IS_OK(status
)) {
8467 END_PROFILE(SMBlockingX
);
8468 reply_nterror(req
, status
);
8472 END_PROFILE(SMBlockingX
);
8476 reply_outbuf(req
, 2, 0);
8477 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8478 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8480 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8481 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8483 END_PROFILE(SMBlockingX
);
8487 #define DBGC_CLASS DBGC_ALL
8489 /****************************************************************************
8490 Reply to a SMBreadbmpx (read block multiplex) request.
8491 Always reply with an error, if someone has a platform really needs this,
8492 please contact vl@samba.org
8493 ****************************************************************************/
8495 void reply_readbmpx(struct smb_request
*req
)
8497 START_PROFILE(SMBreadBmpx
);
8498 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8499 END_PROFILE(SMBreadBmpx
);
8503 /****************************************************************************
8504 Reply to a SMBreadbs (read block multiplex secondary) request.
8505 Always reply with an error, if someone has a platform really needs this,
8506 please contact vl@samba.org
8507 ****************************************************************************/
8509 void reply_readbs(struct smb_request
*req
)
8511 START_PROFILE(SMBreadBs
);
8512 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8513 END_PROFILE(SMBreadBs
);
8517 /****************************************************************************
8518 Reply to a SMBsetattrE.
8519 ****************************************************************************/
8521 void reply_setattrE(struct smb_request
*req
)
8523 connection_struct
*conn
= req
->conn
;
8524 struct smb_file_time ft
;
8528 START_PROFILE(SMBsetattrE
);
8532 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8536 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8538 if(!fsp
|| (fsp
->conn
!= conn
)) {
8539 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8544 * Convert the DOS times into unix times.
8547 ft
.atime
= convert_time_t_to_timespec(
8548 srv_make_unix_date2(req
->vwv
+3));
8549 ft
.mtime
= convert_time_t_to_timespec(
8550 srv_make_unix_date2(req
->vwv
+5));
8551 ft
.create_time
= convert_time_t_to_timespec(
8552 srv_make_unix_date2(req
->vwv
+1));
8554 reply_outbuf(req
, 0, 0);
8557 * Patch from Ray Frush <frush@engr.colostate.edu>
8558 * Sometimes times are sent as zero - ignore them.
8561 /* Ensure we have a valid stat struct for the source. */
8562 status
= vfs_stat_fsp(fsp
);
8563 if (!NT_STATUS_IS_OK(status
)) {
8564 reply_nterror(req
, status
);
8568 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8569 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8573 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8574 if (!NT_STATUS_IS_OK(status
)) {
8575 reply_nterror(req
, status
);
8579 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8582 (unsigned int)ft
.atime
.tv_sec
,
8583 (unsigned int)ft
.mtime
.tv_sec
,
8584 (unsigned int)ft
.create_time
.tv_sec
8587 END_PROFILE(SMBsetattrE
);
8592 /* Back from the dead for OS/2..... JRA. */
8594 /****************************************************************************
8595 Reply to a SMBwritebmpx (write block multiplex primary) request.
8596 Always reply with an error, if someone has a platform really needs this,
8597 please contact vl@samba.org
8598 ****************************************************************************/
8600 void reply_writebmpx(struct smb_request
*req
)
8602 START_PROFILE(SMBwriteBmpx
);
8603 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8604 END_PROFILE(SMBwriteBmpx
);
8608 /****************************************************************************
8609 Reply to a SMBwritebs (write block multiplex secondary) request.
8610 Always reply with an error, if someone has a platform really needs this,
8611 please contact vl@samba.org
8612 ****************************************************************************/
8614 void reply_writebs(struct smb_request
*req
)
8616 START_PROFILE(SMBwriteBs
);
8617 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8618 END_PROFILE(SMBwriteBs
);
8622 /****************************************************************************
8623 Reply to a SMBgetattrE.
8624 ****************************************************************************/
8626 void reply_getattrE(struct smb_request
*req
)
8628 connection_struct
*conn
= req
->conn
;
8631 struct timespec create_ts
;
8633 START_PROFILE(SMBgetattrE
);
8636 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8637 END_PROFILE(SMBgetattrE
);
8641 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8643 if(!fsp
|| (fsp
->conn
!= conn
)) {
8644 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8645 END_PROFILE(SMBgetattrE
);
8649 /* Do an fstat on this file */
8651 reply_nterror(req
, map_nt_error_from_unix(errno
));
8652 END_PROFILE(SMBgetattrE
);
8656 mode
= dos_mode(conn
, fsp
->fsp_name
);
8659 * Convert the times into dos times. Set create
8660 * date to be last modify date as UNIX doesn't save
8664 reply_outbuf(req
, 11, 0);
8666 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8667 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8668 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8669 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8670 /* Should we check pending modtime here ? JRA */
8671 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8672 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8674 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8675 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8676 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8678 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8679 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8680 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8682 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8684 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8686 END_PROFILE(SMBgetattrE
);