2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2018
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "lib/util/tevent_ntstatus.h"
22 #include "libcli/composite/composite.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "libcli/smb_composite/smb_composite.h"
26 #include "lib/socket/socket.h"
27 #include "libcli/resolve/resolve.h"
28 #include "librpc/gen_ndr/ndr_nbt.h"
29 #include "libcli/smb/smbXcli_base.h"
31 struct smb_connect_nego_state
{
32 struct tevent_context
*ev
;
33 struct resolve_context
*resolve_ctx
;
34 const char *socket_options
;
35 struct smbcli_options options
;
36 const char *dest_hostname
;
37 const char *dest_address
;
38 const char **dest_ports
;
39 const char *target_hostname
;
40 struct nbt_name calling
, called
;
41 struct smbXcli_conn
*conn
;
44 static void smb_connect_nego_connect_done(struct composite_context
*creq
);
45 static void smb_connect_nego_nego_done(struct tevent_req
*subreq
);
47 struct tevent_req
*smb_connect_nego_send(TALLOC_CTX
*mem_ctx
,
48 struct tevent_context
*ev
,
49 struct resolve_context
*resolve_ctx
,
50 const struct smbcli_options
*options
,
51 const char *socket_options
,
52 const char *dest_hostname
,
53 const char *dest_address
, /* optional */
54 const char **dest_ports
,
55 const char *target_hostname
,
56 const char *called_name
,
57 const char *calling_name
)
59 struct tevent_req
*req
= NULL
;
60 struct smb_connect_nego_state
*state
= NULL
;
61 struct composite_context
*creq
= NULL
;
63 req
= tevent_req_create(mem_ctx
, &state
,
64 struct smb_connect_nego_state
);
69 state
->resolve_ctx
= resolve_ctx
;
70 state
->options
= *options
;
71 state
->socket_options
= socket_options
;
72 state
->dest_hostname
= dest_hostname
;
73 state
->dest_address
= dest_address
;
74 state
->dest_ports
= dest_ports
;
75 state
->target_hostname
= target_hostname
;
77 make_nbt_name_client(&state
->calling
, calling_name
);
79 nbt_choose_called_name(state
, &state
->called
,
80 called_name
, NBT_NAME_SERVER
);
81 if (tevent_req_nomem(state
->called
.name
, req
)) {
82 return tevent_req_post(req
, ev
);
85 creq
= smbcli_sock_connect_send(state
,
91 state
->socket_options
,
94 if (tevent_req_nomem(creq
, req
)) {
95 return tevent_req_post(req
, ev
);
97 creq
->async
.private_data
= req
;
98 creq
->async
.fn
= smb_connect_nego_connect_done
;
103 static void smb_connect_nego_connect_done(struct composite_context
*creq
)
105 struct tevent_req
*req
=
106 talloc_get_type_abort(creq
->async
.private_data
,
108 struct smb_connect_nego_state
*state
=
110 struct smb_connect_nego_state
);
111 struct tevent_req
*subreq
= NULL
;
112 struct smbcli_socket
*sock
= NULL
;
113 uint32_t smb1_capabilities
;
114 uint32_t timeout_msec
= state
->options
.request_timeout
* 1000;
117 status
= smbcli_sock_connect_recv(creq
, state
, &sock
);
119 if (tevent_req_nterror(req
, status
)) {
123 TALLOC_FREE(sock
->event
.fde
);
124 TALLOC_FREE(sock
->event
.te
);
126 smb1_capabilities
= 0;
127 smb1_capabilities
|= CAP_LARGE_FILES
;
128 smb1_capabilities
|= CAP_NT_SMBS
| CAP_RPC_REMOTE_APIS
;
129 smb1_capabilities
|= CAP_LOCK_AND_READ
| CAP_NT_FIND
;
130 smb1_capabilities
|= CAP_DFS
| CAP_W2K_SMBS
;
131 smb1_capabilities
|= CAP_LARGE_READX
|CAP_LARGE_WRITEX
;
132 smb1_capabilities
|= CAP_LWIO
;
134 if (state
->options
.ntstatus_support
) {
135 smb1_capabilities
|= CAP_STATUS32
;
138 if (state
->options
.unicode
) {
139 smb1_capabilities
|= CAP_UNICODE
;
142 if (state
->options
.use_spnego
) {
143 smb1_capabilities
|= CAP_EXTENDED_SECURITY
;
146 if (state
->options
.use_level2_oplocks
) {
147 smb1_capabilities
|= CAP_LEVEL_II_OPLOCKS
;
150 state
->conn
= smbXcli_conn_create(state
,
152 state
->target_hostname
,
153 state
->options
.signing
,
155 &state
->options
.client_guid
,
156 state
->options
.smb2_capabilities
);
157 if (tevent_req_nomem(state
->conn
, req
)) {
163 subreq
= smbXcli_negprot_send(state
,
167 state
->options
.min_protocol
,
168 state
->options
.max_protocol
,
169 state
->options
.max_credits
);
170 if (tevent_req_nomem(subreq
, req
)) {
173 tevent_req_set_callback(subreq
, smb_connect_nego_nego_done
, req
);
176 static void smb_connect_nego_nego_done(struct tevent_req
*subreq
)
178 struct tevent_req
*req
=
179 tevent_req_callback_data(subreq
,
183 status
= smbXcli_negprot_recv(subreq
);
185 if (tevent_req_nterror(req
, status
)) {
189 tevent_req_done(req
);
192 NTSTATUS
smb_connect_nego_recv(struct tevent_req
*req
,
194 struct smbXcli_conn
**_conn
)
196 struct smb_connect_nego_state
*state
=
198 struct smb_connect_nego_state
);
201 if (tevent_req_is_nterror(req
, &status
)) {
202 tevent_req_received(req
);
206 *_conn
= talloc_move(mem_ctx
, &state
->conn
);
207 tevent_req_received(req
);