Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : dcerpc schannel operations
5 :
6 : Copyright (C) Andrew Tridgell 2004
7 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
8 : Copyright (C) Rafal Szczesniak 2006
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "includes.h"
25 : #include <tevent.h>
26 : #include "auth/auth.h"
27 : #include "libcli/composite/composite.h"
28 : #include "libcli/auth/libcli_auth.h"
29 : #include "librpc/gen_ndr/ndr_netlogon.h"
30 : #include "librpc/gen_ndr/ndr_netlogon_c.h"
31 : #include "auth/credentials/credentials.h"
32 : #include "librpc/rpc/dcerpc_proto.h"
33 : #include "param/param.h"
34 : #include "lib/param/loadparm.h"
35 :
36 : struct schannel_key_state {
37 : struct dcerpc_pipe *pipe;
38 : struct dcerpc_pipe *pipe2;
39 : struct dcerpc_binding *binding;
40 : bool dcerpc_schannel_auto;
41 : struct cli_credentials *credentials;
42 : struct netlogon_creds_CredentialState *creds;
43 : uint32_t local_negotiate_flags;
44 : uint32_t remote_negotiate_flags;
45 : struct netr_Credential credentials1;
46 : struct netr_Credential credentials2;
47 : struct netr_Credential credentials3;
48 : struct netr_ServerReqChallenge r;
49 : struct netr_ServerAuthenticate2 a;
50 : const struct samr_Password *mach_pwd;
51 : };
52 :
53 :
54 : static void continue_secondary_connection(struct composite_context *ctx);
55 : static void continue_bind_auth_none(struct composite_context *ctx);
56 : static void continue_srv_challenge(struct tevent_req *subreq);
57 : static void continue_srv_auth2(struct tevent_req *subreq);
58 : static void continue_get_capabilities(struct tevent_req *subreq);
59 :
60 :
61 : /*
62 : Stage 2 of schannel_key: Receive endpoint mapping and request secondary
63 : rpc connection
64 : */
65 473 : static void continue_epm_map_binding(struct composite_context *ctx)
66 : {
67 56 : struct composite_context *c;
68 56 : struct schannel_key_state *s;
69 56 : struct composite_context *sec_conn_req;
70 :
71 473 : c = talloc_get_type(ctx->async.private_data, struct composite_context);
72 473 : s = talloc_get_type(c->private_data, struct schannel_key_state);
73 :
74 : /* receive endpoint mapping */
75 473 : c->status = dcerpc_epm_map_binding_recv(ctx);
76 473 : if (!NT_STATUS_IS_OK(c->status)) {
77 0 : DEBUG(0,("Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s\n",
78 : NDR_NETLOGON_UUID, nt_errstr(c->status)));
79 0 : composite_error(c, c->status);
80 0 : return;
81 : }
82 :
83 : /* send a request for secondary rpc connection */
84 529 : sec_conn_req = dcerpc_secondary_connection_send(s->pipe,
85 473 : s->binding);
86 473 : if (composite_nomem(sec_conn_req, c)) return;
87 :
88 473 : composite_continue(c, sec_conn_req, continue_secondary_connection, c);
89 : }
90 :
91 :
92 : /*
93 : Stage 3 of schannel_key: Receive secondary rpc connection and perform
94 : non-authenticated bind request
95 : */
96 473 : static void continue_secondary_connection(struct composite_context *ctx)
97 : {
98 56 : struct composite_context *c;
99 56 : struct schannel_key_state *s;
100 56 : struct composite_context *auth_none_req;
101 :
102 473 : c = talloc_get_type(ctx->async.private_data, struct composite_context);
103 473 : s = talloc_get_type(c->private_data, struct schannel_key_state);
104 :
105 : /* receive secondary rpc connection */
106 473 : c->status = dcerpc_secondary_connection_recv(ctx, &s->pipe2);
107 473 : if (!composite_is_ok(c)) return;
108 :
109 473 : talloc_steal(s, s->pipe2);
110 :
111 : /* initiate a non-authenticated bind */
112 473 : auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe2, &ndr_table_netlogon);
113 473 : if (composite_nomem(auth_none_req, c)) return;
114 :
115 473 : composite_continue(c, auth_none_req, continue_bind_auth_none, c);
116 : }
117 :
118 :
119 : /*
120 : Stage 4 of schannel_key: Receive non-authenticated bind and get
121 : a netlogon challenge
122 : */
123 473 : static void continue_bind_auth_none(struct composite_context *ctx)
124 : {
125 56 : struct composite_context *c;
126 56 : struct schannel_key_state *s;
127 56 : struct tevent_req *subreq;
128 :
129 473 : c = talloc_get_type(ctx->async.private_data, struct composite_context);
130 473 : s = talloc_get_type(c->private_data, struct schannel_key_state);
131 :
132 : /* receive result of non-authenticated bind request */
133 473 : c->status = dcerpc_bind_auth_none_recv(ctx);
134 473 : if (!composite_is_ok(c)) return;
135 :
136 : /* prepare a challenge request */
137 473 : s->r.in.server_name = talloc_asprintf(c, "\\\\%s", dcerpc_server_name(s->pipe));
138 473 : if (composite_nomem(s->r.in.server_name, c)) return;
139 473 : s->r.in.computer_name = cli_credentials_get_workstation(s->credentials);
140 473 : s->r.in.credentials = &s->credentials1;
141 473 : s->r.out.return_credentials = &s->credentials2;
142 :
143 473 : generate_random_buffer(s->credentials1.data, sizeof(s->credentials1.data));
144 :
145 : /*
146 : request a netlogon challenge - a rpc request over opened secondary pipe
147 : */
148 529 : subreq = dcerpc_netr_ServerReqChallenge_r_send(s, c->event_ctx,
149 473 : s->pipe2->binding_handle,
150 : &s->r);
151 473 : if (composite_nomem(subreq, c)) return;
152 :
153 473 : tevent_req_set_callback(subreq, continue_srv_challenge, c);
154 : }
155 :
156 :
157 : /*
158 : Stage 5 of schannel_key: Receive a challenge and perform authentication
159 : on the netlogon pipe
160 : */
161 473 : static void continue_srv_challenge(struct tevent_req *subreq)
162 : {
163 56 : struct composite_context *c;
164 56 : struct schannel_key_state *s;
165 :
166 473 : c = tevent_req_callback_data(subreq, struct composite_context);
167 473 : s = talloc_get_type(c->private_data, struct schannel_key_state);
168 :
169 : /* receive rpc request result - netlogon challenge */
170 473 : c->status = dcerpc_netr_ServerReqChallenge_r_recv(subreq, s);
171 473 : TALLOC_FREE(subreq);
172 473 : if (!composite_is_ok(c)) return;
173 :
174 : /* prepare credentials for auth2 request */
175 473 : s->mach_pwd = cli_credentials_get_nt_hash(s->credentials, c);
176 473 : if (s->mach_pwd == NULL) {
177 0 : return composite_error(c, NT_STATUS_INTERNAL_ERROR);
178 : }
179 :
180 : /* auth2 request arguments */
181 473 : s->a.in.server_name = s->r.in.server_name;
182 473 : s->a.in.account_name = cli_credentials_get_username(s->credentials);
183 529 : s->a.in.secure_channel_type =
184 473 : cli_credentials_get_secure_channel_type(s->credentials);
185 473 : s->a.in.computer_name = cli_credentials_get_workstation(s->credentials);
186 473 : s->a.in.negotiate_flags = &s->local_negotiate_flags;
187 473 : s->a.in.credentials = &s->credentials3;
188 473 : s->a.out.negotiate_flags = &s->remote_negotiate_flags;
189 473 : s->a.out.return_credentials = &s->credentials3;
190 :
191 946 : s->creds = netlogon_creds_client_init(s,
192 : s->a.in.account_name,
193 : s->a.in.computer_name,
194 473 : s->a.in.secure_channel_type,
195 473 : &s->credentials1, &s->credentials2,
196 : s->mach_pwd, &s->credentials3,
197 : s->local_negotiate_flags);
198 473 : if (composite_nomem(s->creds, c)) {
199 0 : return;
200 : }
201 : /*
202 : authenticate on the netlogon pipe - a rpc request over secondary pipe
203 : */
204 529 : subreq = dcerpc_netr_ServerAuthenticate2_r_send(s, c->event_ctx,
205 473 : s->pipe2->binding_handle,
206 : &s->a);
207 473 : if (composite_nomem(subreq, c)) return;
208 :
209 473 : tevent_req_set_callback(subreq, continue_srv_auth2, c);
210 : }
211 :
212 :
213 : /*
214 : Stage 6 of schannel_key: Receive authentication request result and verify
215 : received credentials
216 : */
217 473 : static void continue_srv_auth2(struct tevent_req *subreq)
218 : {
219 56 : struct composite_context *c;
220 56 : struct schannel_key_state *s;
221 :
222 473 : c = tevent_req_callback_data(subreq, struct composite_context);
223 473 : s = talloc_get_type(c->private_data, struct schannel_key_state);
224 :
225 : /* receive rpc request result - auth2 credentials */
226 473 : c->status = dcerpc_netr_ServerAuthenticate2_r_recv(subreq, s);
227 473 : TALLOC_FREE(subreq);
228 473 : if (!composite_is_ok(c)) return;
229 :
230 473 : if (!NT_STATUS_EQUAL(s->a.out.result, NT_STATUS_ACCESS_DENIED) &&
231 471 : !NT_STATUS_IS_OK(s->a.out.result)) {
232 2 : composite_error(c, s->a.out.result);
233 2 : return;
234 : }
235 :
236 : /*
237 : * Strong keys could be unsupported (NT4) or disabled. So retry with the
238 : * flags returned by the server. - asn
239 : */
240 471 : if (NT_STATUS_EQUAL(s->a.out.result, NT_STATUS_ACCESS_DENIED)) {
241 2 : uint32_t lf = s->local_negotiate_flags;
242 2 : const char *ln = NULL;
243 2 : uint32_t rf = s->remote_negotiate_flags;
244 2 : const char *rn = NULL;
245 :
246 2 : if (!s->dcerpc_schannel_auto) {
247 0 : composite_error(c, s->a.out.result);
248 2 : return;
249 : }
250 2 : s->dcerpc_schannel_auto = false;
251 :
252 2 : if (lf & NETLOGON_NEG_SUPPORTS_AES) {
253 2 : ln = "aes";
254 2 : if (rf & NETLOGON_NEG_SUPPORTS_AES) {
255 2 : composite_error(c, s->a.out.result);
256 2 : return;
257 : }
258 0 : } else if (lf & NETLOGON_NEG_STRONG_KEYS) {
259 0 : ln = "strong";
260 0 : if (rf & NETLOGON_NEG_STRONG_KEYS) {
261 0 : composite_error(c, s->a.out.result);
262 0 : return;
263 : }
264 : } else {
265 0 : ln = "des";
266 : }
267 :
268 0 : if (rf & NETLOGON_NEG_SUPPORTS_AES) {
269 0 : rn = "aes";
270 0 : } else if (rf & NETLOGON_NEG_STRONG_KEYS) {
271 0 : rn = "strong";
272 : } else {
273 0 : rn = "des";
274 : }
275 :
276 0 : DEBUG(3, ("Server doesn't support %s keys, downgrade to %s"
277 : "and retry! local[0x%08X] remote[0x%08X]\n",
278 : ln, rn, lf, rf));
279 :
280 0 : s->local_negotiate_flags = s->remote_negotiate_flags;
281 :
282 0 : generate_random_buffer(s->credentials1.data,
283 : sizeof(s->credentials1.data));
284 :
285 0 : subreq = dcerpc_netr_ServerReqChallenge_r_send(s,
286 : c->event_ctx,
287 0 : s->pipe2->binding_handle,
288 : &s->r);
289 0 : if (composite_nomem(subreq, c)) return;
290 :
291 0 : tevent_req_set_callback(subreq, continue_srv_challenge, c);
292 0 : return;
293 : }
294 :
295 469 : s->creds->negotiate_flags = s->remote_negotiate_flags;
296 :
297 : /* verify credentials */
298 469 : if (!netlogon_creds_client_check(s->creds, s->a.out.return_credentials)) {
299 0 : composite_error(c, NT_STATUS_UNSUCCESSFUL);
300 0 : return;
301 : }
302 :
303 469 : composite_done(c);
304 : }
305 :
306 : /*
307 : Initiate establishing a schannel key using netlogon challenge
308 : on a secondary pipe
309 : */
310 473 : static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx,
311 : struct dcerpc_pipe *p,
312 : struct cli_credentials *credentials,
313 : struct loadparm_context *lp_ctx)
314 : {
315 56 : struct composite_context *c;
316 56 : struct schannel_key_state *s;
317 56 : struct composite_context *epm_map_req;
318 473 : enum netr_SchannelType schannel_type = cli_credentials_get_secure_channel_type(credentials);
319 473 : struct cli_credentials *epm_creds = NULL;
320 :
321 : /* composite context allocation and setup */
322 473 : c = composite_create(mem_ctx, p->conn->event_ctx);
323 473 : if (c == NULL) return NULL;
324 :
325 473 : s = talloc_zero(c, struct schannel_key_state);
326 473 : if (composite_nomem(s, c)) return c;
327 473 : c->private_data = s;
328 :
329 : /* store parameters in the state structure */
330 473 : s->pipe = p;
331 473 : s->credentials = credentials;
332 473 : s->local_negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
333 :
334 : /* allocate credentials */
335 473 : if (s->pipe->conn->flags & DCERPC_SCHANNEL_128) {
336 93 : s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
337 : }
338 473 : if (s->pipe->conn->flags & DCERPC_SCHANNEL_AES) {
339 92 : s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
340 92 : s->local_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
341 : }
342 473 : if (s->pipe->conn->flags & DCERPC_SCHANNEL_AUTO) {
343 288 : s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
344 288 : s->local_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
345 288 : s->dcerpc_schannel_auto = true;
346 : }
347 :
348 : /* type of authentication depends on schannel type */
349 473 : if (schannel_type == SEC_CHAN_RODC) {
350 0 : s->local_negotiate_flags |= NETLOGON_NEG_RODC_PASSTHROUGH;
351 : }
352 :
353 473 : if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
354 0 : s->local_negotiate_flags &= ~NETLOGON_NEG_ARCFOUR;
355 : }
356 :
357 473 : epm_creds = cli_credentials_init_anon(s);
358 473 : if (composite_nomem(epm_creds, c)) return c;
359 :
360 : /* allocate binding structure */
361 473 : s->binding = dcerpc_binding_dup(s, s->pipe->binding);
362 473 : if (composite_nomem(s->binding, c)) return c;
363 :
364 : /* request the netlogon endpoint mapping */
365 529 : epm_map_req = dcerpc_epm_map_binding_send(c, s->binding,
366 : &ndr_table_netlogon,
367 : epm_creds,
368 473 : s->pipe->conn->event_ctx,
369 : lp_ctx);
370 473 : if (composite_nomem(epm_map_req, c)) return c;
371 :
372 473 : composite_continue(c, epm_map_req, continue_epm_map_binding, c);
373 473 : return c;
374 : }
375 :
376 :
377 : /*
378 : Receive result of schannel key request
379 : */
380 473 : static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c,
381 : TALLOC_CTX *mem_ctx,
382 : struct netlogon_creds_CredentialState **creds)
383 : {
384 473 : NTSTATUS status = composite_wait(c);
385 :
386 473 : if (NT_STATUS_IS_OK(status)) {
387 56 : struct schannel_key_state *s =
388 469 : talloc_get_type_abort(c->private_data,
389 : struct schannel_key_state);
390 469 : *creds = talloc_move(mem_ctx, &s->creds);
391 : }
392 :
393 473 : talloc_free(c);
394 473 : return status;
395 : }
396 :
397 :
398 : struct auth_schannel_state {
399 : struct dcerpc_pipe *pipe;
400 : struct cli_credentials *credentials;
401 : const struct ndr_interface_table *table;
402 : struct loadparm_context *lp_ctx;
403 : uint8_t auth_level;
404 : struct netlogon_creds_CredentialState *creds_state;
405 : struct netlogon_creds_CredentialState save_creds_state;
406 : struct netr_Authenticator auth;
407 : struct netr_Authenticator return_auth;
408 : union netr_Capabilities capabilities;
409 : struct netr_LogonGetCapabilities c;
410 : };
411 :
412 :
413 : static void continue_bind_auth(struct composite_context *ctx);
414 :
415 :
416 : /*
417 : Stage 2 of auth_schannel: Receive schannel key and initiate an
418 : authenticated bind using received credentials
419 : */
420 473 : static void continue_schannel_key(struct composite_context *ctx)
421 : {
422 56 : struct composite_context *auth_req;
423 473 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
424 : struct composite_context);
425 473 : struct auth_schannel_state *s = talloc_get_type(c->private_data,
426 : struct auth_schannel_state);
427 56 : NTSTATUS status;
428 :
429 : /* receive schannel key */
430 473 : status = c->status = dcerpc_schannel_key_recv(ctx, s, &s->creds_state);
431 473 : if (!composite_is_ok(c)) {
432 4 : DEBUG(1, ("Failed to setup credentials: %s\n", nt_errstr(status)));
433 4 : return;
434 : }
435 :
436 : /* send bind auth request with received creds */
437 469 : cli_credentials_set_netlogon_creds(s->credentials, s->creds_state);
438 :
439 469 : auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials,
440 : lpcfg_gensec_settings(c, s->lp_ctx),
441 469 : DCERPC_AUTH_TYPE_SCHANNEL, s->auth_level,
442 : NULL);
443 469 : if (composite_nomem(auth_req, c)) return;
444 :
445 469 : composite_continue(c, auth_req, continue_bind_auth, c);
446 : }
447 :
448 :
449 : /*
450 : Stage 3 of auth_schannel: Receive result of authenticated bind
451 : and say if we're done ok.
452 : */
453 469 : static void continue_bind_auth(struct composite_context *ctx)
454 : {
455 469 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
456 : struct composite_context);
457 469 : struct auth_schannel_state *s = talloc_get_type(c->private_data,
458 : struct auth_schannel_state);
459 56 : struct tevent_req *subreq;
460 :
461 469 : c->status = dcerpc_bind_auth_recv(ctx);
462 469 : if (!composite_is_ok(c)) return;
463 :
464 : /* if we have a AES encrypted connection, verify the capabilities */
465 469 : if (ndr_syntax_id_equal(&s->table->syntax_id,
466 : &ndr_table_netlogon.syntax_id)) {
467 8 : NTSTATUS status;
468 187 : ZERO_STRUCT(s->return_auth);
469 :
470 187 : s->save_creds_state = *s->creds_state;
471 187 : status = netlogon_creds_client_authenticator(&s->save_creds_state,
472 : &s->auth);
473 187 : if (!NT_STATUS_IS_OK(status)) {
474 0 : composite_error(c, status);
475 0 : return;
476 : }
477 :
478 187 : s->c.in.server_name = talloc_asprintf(c,
479 : "\\\\%s",
480 : dcerpc_server_name(s->pipe));
481 187 : if (composite_nomem(s->c.in.server_name, c)) return;
482 187 : s->c.in.computer_name = cli_credentials_get_workstation(s->credentials);
483 187 : s->c.in.credential = &s->auth;
484 187 : s->c.in.return_authenticator = &s->return_auth;
485 187 : s->c.in.query_level = 1;
486 :
487 187 : s->c.out.capabilities = &s->capabilities;
488 187 : s->c.out.return_authenticator = &s->return_auth;
489 :
490 187 : DEBUG(5, ("We established a AES connection, verifying logon "
491 : "capabilities\n"));
492 :
493 195 : subreq = dcerpc_netr_LogonGetCapabilities_r_send(s,
494 : c->event_ctx,
495 187 : s->pipe->binding_handle,
496 : &s->c);
497 187 : if (composite_nomem(subreq, c)) return;
498 :
499 187 : tevent_req_set_callback(subreq, continue_get_capabilities, c);
500 187 : return;
501 : }
502 :
503 282 : composite_done(c);
504 : }
505 :
506 : /*
507 : Stage 4 of auth_schannel: Get the Logon Capabilities and verify them.
508 : */
509 187 : static void continue_get_capabilities(struct tevent_req *subreq)
510 : {
511 8 : struct composite_context *c;
512 8 : struct auth_schannel_state *s;
513 :
514 187 : c = tevent_req_callback_data(subreq, struct composite_context);
515 187 : s = talloc_get_type(c->private_data, struct auth_schannel_state);
516 :
517 : /* receive rpc request result */
518 187 : c->status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, s);
519 187 : TALLOC_FREE(subreq);
520 187 : if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
521 0 : if (s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
522 0 : composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
523 0 : return;
524 : } else {
525 : /* This is probably NT */
526 0 : composite_done(c);
527 0 : return;
528 : }
529 187 : } else if (!composite_is_ok(c)) {
530 0 : return;
531 : }
532 :
533 187 : if (NT_STATUS_EQUAL(s->c.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
534 0 : if (s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
535 : /* This means AES isn't supported. */
536 0 : composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
537 0 : return;
538 : }
539 :
540 : /* This is probably an old Samba version */
541 0 : composite_done(c);
542 0 : return;
543 : }
544 :
545 : /* verify credentials */
546 187 : if (!netlogon_creds_client_check(&s->save_creds_state,
547 187 : &s->c.out.return_authenticator->cred)) {
548 0 : composite_error(c, NT_STATUS_UNSUCCESSFUL);
549 0 : return;
550 : }
551 :
552 187 : *s->creds_state = s->save_creds_state;
553 187 : cli_credentials_set_netlogon_creds(s->credentials, s->creds_state);
554 :
555 187 : if (!NT_STATUS_IS_OK(s->c.out.result)) {
556 0 : composite_error(c, s->c.out.result);
557 0 : return;
558 : }
559 :
560 : /* compare capabilities */
561 187 : if (s->creds_state->negotiate_flags != s->capabilities.server_capabilities) {
562 0 : DEBUG(2, ("The client capabilities don't match the server "
563 : "capabilities: local[0x%08X] remote[0x%08X]\n",
564 : s->creds_state->negotiate_flags,
565 : s->capabilities.server_capabilities));
566 0 : composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
567 0 : return;
568 : }
569 :
570 : /* TODO: Add downgrade detection. */
571 :
572 187 : composite_done(c);
573 : }
574 :
575 :
576 : /*
577 : Initiate schannel authentication request
578 : */
579 473 : struct composite_context *dcerpc_bind_auth_schannel_send(TALLOC_CTX *tmp_ctx,
580 : struct dcerpc_pipe *p,
581 : const struct ndr_interface_table *table,
582 : struct cli_credentials *credentials,
583 : struct loadparm_context *lp_ctx,
584 : uint8_t auth_level)
585 : {
586 56 : struct composite_context *c;
587 56 : struct auth_schannel_state *s;
588 56 : struct composite_context *schan_key_req;
589 :
590 : /* composite context allocation and setup */
591 473 : c = composite_create(tmp_ctx, p->conn->event_ctx);
592 473 : if (c == NULL) return NULL;
593 :
594 473 : s = talloc_zero(c, struct auth_schannel_state);
595 473 : if (composite_nomem(s, c)) return c;
596 473 : c->private_data = s;
597 :
598 : /* store parameters in the state structure */
599 473 : s->pipe = p;
600 473 : s->credentials = credentials;
601 473 : s->table = table;
602 473 : s->auth_level = auth_level;
603 473 : s->lp_ctx = lp_ctx;
604 :
605 : /* start getting schannel key first */
606 473 : schan_key_req = dcerpc_schannel_key_send(c, p, credentials, lp_ctx);
607 473 : if (composite_nomem(schan_key_req, c)) return c;
608 :
609 473 : composite_continue(c, schan_key_req, continue_schannel_key, c);
610 473 : return c;
611 : }
612 :
613 :
614 : /*
615 : Receive result of schannel authentication request
616 : */
617 473 : NTSTATUS dcerpc_bind_auth_schannel_recv(struct composite_context *c)
618 : {
619 473 : NTSTATUS status = composite_wait(c);
620 :
621 473 : talloc_free(c);
622 473 : return status;
623 : }
|