s4:libcli/smb2: SMB_SIGNING_DEFAULT matches SMB_SIGNING_SUPPORTED on the client for now
[Samba/gebeck_regimport.git] / source4 / libcli / smb2 / connect.c
blob530e635a68484dc604b8d7c350c38ee95c8451fc
1 /*
2 Unix SMB/CIFS implementation.
4 SMB2 composite connection setup
6 Copyright (C) Andrew Tridgell 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include <tevent.h>
24 #include "lib/util/tevent_ntstatus.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/raw/raw_proto.h"
27 #include "libcli/smb2/smb2.h"
28 #include "libcli/smb2/smb2_calls.h"
29 #include "libcli/composite/composite.h"
30 #include "libcli/resolve/resolve.h"
31 #include "param/param.h"
33 struct smb2_connect_state {
34 struct tevent_context *ev;
35 struct cli_credentials *credentials;
36 struct resolve_context *resolve_ctx;
37 const char *host;
38 const char *share;
39 const char **ports;
40 const char *socket_options;
41 struct gensec_settings *gensec_settings;
42 struct smbcli_options options;
43 struct smb2_negprot negprot;
44 struct smb2_tree_connect tcon;
45 struct smb2_session *session;
46 struct smb2_tree *tree;
49 static void smb2_connect_resolve_done(struct composite_context *creq);
52 a composite function that does a full negprot/sesssetup/tcon, returning
53 a connected smb2_tree
55 struct tevent_req *smb2_connect_send(TALLOC_CTX *mem_ctx,
56 struct tevent_context *ev,
57 const char *host,
58 const char **ports,
59 const char *share,
60 struct resolve_context *resolve_ctx,
61 struct cli_credentials *credentials,
62 struct smbcli_options *options,
63 const char *socket_options,
64 struct gensec_settings *gensec_settings)
66 struct tevent_req *req;
67 struct smb2_connect_state *state;
68 struct nbt_name name;
69 struct composite_context *creq;
71 req = tevent_req_create(mem_ctx, &state,
72 struct smb2_connect_state);
73 if (req == NULL) {
74 return NULL;
77 state->ev = ev;
78 state->credentials = credentials;
79 state->options = *options;
80 state->host = host;
81 state->ports = ports;
82 state->share = share;
83 state->resolve_ctx = resolve_ctx;
84 state->socket_options = socket_options;
85 state->gensec_settings = gensec_settings;
87 ZERO_STRUCT(name);
88 name.name = host;
90 creq = resolve_name_send(resolve_ctx, state, &name, ev);
91 if (tevent_req_nomem(creq, req)) {
92 return tevent_req_post(req, ev);
94 creq->async.fn = smb2_connect_resolve_done;
95 creq->async.private_data = req;
96 return req;
99 static void smb2_connect_socket_done(struct composite_context *creq);
101 static void smb2_connect_resolve_done(struct composite_context *creq)
103 struct tevent_req *req =
104 talloc_get_type_abort(creq->async.private_data,
105 struct tevent_req);
106 struct smb2_connect_state *state =
107 tevent_req_data(req,
108 struct smb2_connect_state);
109 NTSTATUS status;
110 const char *addr;
111 const char **ports;
112 const char *default_ports[] = { "445", NULL };
114 status = resolve_name_recv(creq, state, &addr);
115 if (tevent_req_nterror(req, status)) {
116 return;
119 if (state->ports == NULL) {
120 ports = default_ports;
121 } else {
122 ports = state->ports;
125 creq = smbcli_sock_connect_send(state, addr, ports,
126 state->host, state->resolve_ctx,
127 state->ev, state->socket_options);
128 if (tevent_req_nomem(creq, req)) {
129 return;
131 creq->async.fn = smb2_connect_socket_done;
132 creq->async.private_data = req;
135 static void smb2_connect_negprot_done(struct smb2_request *smb2req);
137 static void smb2_connect_socket_done(struct composite_context *creq)
139 struct tevent_req *req =
140 talloc_get_type_abort(creq->async.private_data,
141 struct tevent_req);
142 struct smb2_connect_state *state =
143 tevent_req_data(req,
144 struct smb2_connect_state);
145 struct smbcli_socket *sock;
146 struct smb2_transport *transport;
147 struct smb2_request *smb2req;
148 NTSTATUS status;
149 uint16_t dialects[3] = {
150 SMB2_DIALECT_REVISION_000,
151 SMB2_DIALECT_REVISION_202,
152 SMB2_DIALECT_REVISION_210
155 status = smbcli_sock_connect_recv(creq, state, &sock);
156 if (tevent_req_nterror(req, status)) {
157 return;
160 transport = smb2_transport_init(sock, state, &state->options);
161 if (tevent_req_nomem(transport, req)) {
162 return;
165 ZERO_STRUCT(state->negprot);
166 state->negprot.in.dialect_count = ARRAY_SIZE(dialects);
167 switch (transport->options.signing) {
168 case SMB_SIGNING_OFF:
169 state->negprot.in.security_mode = 0;
170 break;
171 case SMB_SIGNING_DEFAULT:
172 case SMB_SIGNING_SUPPORTED:
173 case SMB_SIGNING_AUTO:
174 state->negprot.in.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
175 break;
176 case SMB_SIGNING_REQUIRED:
177 state->negprot.in.security_mode =
178 SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED;
179 break;
181 state->negprot.in.capabilities = 0;
182 unix_to_nt_time(&state->negprot.in.start_time, time(NULL));
183 state->negprot.in.dialects = dialects;
185 smb2req = smb2_negprot_send(transport, &state->negprot);
186 if (tevent_req_nomem(smb2req, req)) {
187 return;
189 smb2req->async.fn = smb2_connect_negprot_done;
190 smb2req->async.private_data = req;
193 static void smb2_connect_session_done(struct tevent_req *subreq);
195 static void smb2_connect_negprot_done(struct smb2_request *smb2req)
197 struct tevent_req *req =
198 talloc_get_type_abort(smb2req->async.private_data,
199 struct tevent_req);
200 struct smb2_connect_state *state =
201 tevent_req_data(req,
202 struct smb2_connect_state);
203 struct smb2_transport *transport = smb2req->transport;
204 struct tevent_req *subreq;
205 NTSTATUS status;
207 status = smb2_negprot_recv(smb2req, state, &state->negprot);
208 if (tevent_req_nterror(req, status)) {
209 return;
212 transport->negotiate.secblob = state->negprot.out.secblob;
213 talloc_steal(transport, transport->negotiate.secblob.data);
214 transport->negotiate.system_time = state->negprot.out.system_time;
215 transport->negotiate.server_start_time = state->negprot.out.server_start_time;
216 transport->negotiate.security_mode = state->negprot.out.security_mode;
217 transport->negotiate.dialect_revision = state->negprot.out.dialect_revision;
219 switch (transport->options.signing) {
220 case SMB_SIGNING_OFF:
221 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
222 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
223 return;
225 transport->signing_required = false;
226 break;
227 case SMB_SIGNING_DEFAULT:
228 case SMB_SIGNING_SUPPORTED:
229 case SMB_SIGNING_AUTO:
230 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
231 transport->signing_required = true;
232 } else {
233 transport->signing_required = false;
235 break;
236 case SMB_SIGNING_REQUIRED:
237 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) {
238 transport->signing_required = true;
239 } else {
240 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
241 return;
243 break;
246 state->session = smb2_session_init(transport, state->gensec_settings, state, true);
247 if (tevent_req_nomem(state->session, req)) {
248 return;
251 subreq = smb2_session_setup_spnego_send(state, state->ev,
252 state->session,
253 state->credentials);
254 if (tevent_req_nomem(subreq, req)) {
255 return;
257 tevent_req_set_callback(subreq, smb2_connect_session_done, req);
260 static void smb2_connect_tcon_done(struct smb2_request *smb2req);
262 static void smb2_connect_session_done(struct tevent_req *subreq)
264 struct tevent_req *req =
265 tevent_req_callback_data(subreq,
266 struct tevent_req);
267 struct smb2_connect_state *state =
268 tevent_req_data(req,
269 struct smb2_connect_state);
270 struct smb2_request *smb2req;
271 NTSTATUS status;
273 status = smb2_session_setup_spnego_recv(subreq);
274 TALLOC_FREE(subreq);
275 if (tevent_req_nterror(req, status)) {
276 return;
279 state->tree = smb2_tree_init(state->session, state, true);
280 if (tevent_req_nomem(state->tree, req)) {
281 return;
284 state->tcon.in.reserved = 0;
285 state->tcon.in.path = talloc_asprintf(state, "\\\\%s\\%s",
286 state->host, state->share);
287 if (tevent_req_nomem(state->tcon.in.path, req)) {
288 return;
291 smb2req = smb2_tree_connect_send(state->tree, &state->tcon);
292 if (tevent_req_nomem(smb2req, req)) {
293 return;
295 smb2req->async.fn = smb2_connect_tcon_done;
296 smb2req->async.private_data = req;
299 static void smb2_connect_tcon_done(struct smb2_request *smb2req)
301 struct tevent_req *req =
302 talloc_get_type_abort(smb2req->async.private_data,
303 struct tevent_req);
304 struct smb2_connect_state *state =
305 tevent_req_data(req,
306 struct smb2_connect_state);
307 NTSTATUS status;
309 status = smb2_tree_connect_recv(smb2req, &state->tcon);
310 if (tevent_req_nterror(req, status)) {
311 return;
314 state->tree->tid = state->tcon.out.tid;
316 tevent_req_done(req);
319 NTSTATUS smb2_connect_recv(struct tevent_req *req,
320 TALLOC_CTX *mem_ctx,
321 struct smb2_tree **tree)
323 struct smb2_connect_state *state =
324 tevent_req_data(req,
325 struct smb2_connect_state);
326 NTSTATUS status;
328 if (tevent_req_is_nterror(req, &status)) {
329 tevent_req_received(req);
330 return status;
333 *tree = talloc_move(mem_ctx, &state->tree);
335 tevent_req_received(req);
336 return NT_STATUS_OK;
340 sync version of smb2_connect
342 NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx,
343 const char *host,
344 const char **ports,
345 const char *share,
346 struct resolve_context *resolve_ctx,
347 struct cli_credentials *credentials,
348 struct smb2_tree **tree,
349 struct tevent_context *ev,
350 struct smbcli_options *options,
351 const char *socket_options,
352 struct gensec_settings *gensec_settings)
354 struct tevent_req *subreq;
355 NTSTATUS status;
356 bool ok;
357 TALLOC_CTX *frame = talloc_stackframe();
359 if (frame == NULL) {
360 return NT_STATUS_NO_MEMORY;
363 subreq = smb2_connect_send(frame,
365 host,
366 ports,
367 share,
368 resolve_ctx,
369 credentials,
370 options,
371 socket_options,
372 gensec_settings);
373 if (subreq == NULL) {
374 TALLOC_FREE(frame);
375 return NT_STATUS_NO_MEMORY;
378 ok = tevent_req_poll(subreq, ev);
379 if (!ok) {
380 status = map_nt_error_from_unix_common(errno);
381 TALLOC_FREE(frame);
382 return status;
385 status = smb2_connect_recv(subreq, mem_ctx, tree);
386 TALLOC_FREE(subreq);
387 if (!NT_STATUS_IS_OK(status)) {
388 TALLOC_FREE(frame);
389 return status;
392 TALLOC_FREE(frame);
393 return NT_STATUS_OK;