Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Generic Authentication Interface
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
8 : Copyright (C) Stefan Metzmacher 2004
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 "libcli/composite/composite.h"
27 : #include "auth/gensec/gensec.h"
28 : #include "librpc/rpc/dcerpc.h"
29 : #include "librpc/rpc/dcerpc_proto.h"
30 : #include "param/param.h"
31 :
32 : /*
33 : return the rpc syntax and transfer syntax given the pipe uuid and version
34 : */
35 18213 : static NTSTATUS dcerpc_init_syntaxes(struct dcerpc_pipe *p,
36 : const struct ndr_interface_table *table,
37 : struct ndr_syntax_id *syntax,
38 : struct ndr_syntax_id *transfer_syntax)
39 : {
40 18213 : struct GUID *object = NULL;
41 :
42 18213 : p->object = dcerpc_binding_get_object(p->binding);
43 18213 : if (!GUID_all_zero(&p->object)) {
44 8 : object = &p->object;
45 : }
46 :
47 18213 : p->binding_handle = dcerpc_pipe_binding_handle(p, object, table);
48 18213 : if (p->binding_handle == NULL) {
49 0 : return NT_STATUS_NO_MEMORY;
50 : }
51 :
52 18213 : syntax->uuid = table->syntax_id.uuid;
53 18213 : syntax->if_version = table->syntax_id.if_version;
54 :
55 18213 : if (p->conn->flags & DCERPC_NDR64) {
56 0 : *transfer_syntax = ndr_transfer_syntax_ndr64;
57 : } else {
58 18213 : *transfer_syntax = ndr_transfer_syntax_ndr;
59 : }
60 :
61 18213 : return NT_STATUS_OK;
62 : }
63 :
64 :
65 : /*
66 : Send request to do a non-authenticated dcerpc bind
67 : */
68 : static void dcerpc_bind_auth_none_done(struct tevent_req *subreq);
69 :
70 10228 : struct composite_context *dcerpc_bind_auth_none_send(TALLOC_CTX *mem_ctx,
71 : struct dcerpc_pipe *p,
72 : const struct ndr_interface_table *table)
73 : {
74 : struct ndr_syntax_id syntax;
75 : struct ndr_syntax_id transfer_syntax;
76 :
77 : struct composite_context *c;
78 : struct tevent_req *subreq;
79 :
80 10228 : c = composite_create(mem_ctx, p->conn->event_ctx);
81 10228 : if (c == NULL) return NULL;
82 :
83 10228 : c->status = dcerpc_init_syntaxes(p, table,
84 : &syntax, &transfer_syntax);
85 10228 : if (!NT_STATUS_IS_OK(c->status)) {
86 0 : DEBUG(2,("Invalid uuid string in "
87 : "dcerpc_bind_auth_none_send\n"));
88 0 : composite_error(c, c->status);
89 0 : return c;
90 : }
91 :
92 10228 : subreq = dcerpc_bind_send(mem_ctx, p->conn->event_ctx, p,
93 : &syntax, &transfer_syntax);
94 10228 : if (composite_nomem(subreq, c)) return c;
95 10228 : tevent_req_set_callback(subreq, dcerpc_bind_auth_none_done, c);
96 :
97 10228 : return c;
98 : }
99 :
100 10228 : static void dcerpc_bind_auth_none_done(struct tevent_req *subreq)
101 : {
102 8535 : struct composite_context *ctx =
103 10228 : tevent_req_callback_data(subreq,
104 : struct composite_context);
105 :
106 10228 : ctx->status = dcerpc_bind_recv(subreq);
107 10228 : TALLOC_FREE(subreq);
108 10228 : if (!composite_is_ok(ctx)) return;
109 :
110 10159 : composite_done(ctx);
111 : }
112 :
113 : /*
114 : Receive result of a non-authenticated dcerpc bind
115 : */
116 10228 : NTSTATUS dcerpc_bind_auth_none_recv(struct composite_context *ctx)
117 : {
118 10228 : NTSTATUS result = composite_wait(ctx);
119 10228 : TALLOC_FREE(ctx);
120 10228 : return result;
121 : }
122 :
123 :
124 : /*
125 : Perform sync non-authenticated dcerpc bind
126 : */
127 175 : _PUBLIC_ NTSTATUS dcerpc_bind_auth_none(struct dcerpc_pipe *p,
128 : const struct ndr_interface_table *table)
129 : {
130 : struct composite_context *ctx;
131 :
132 175 : ctx = dcerpc_bind_auth_none_send(p, p, table);
133 175 : return dcerpc_bind_auth_none_recv(ctx);
134 : }
135 :
136 :
137 : struct bind_auth_state {
138 : struct dcerpc_pipe *pipe;
139 : struct ndr_syntax_id syntax;
140 : struct ndr_syntax_id transfer_syntax;
141 : struct dcerpc_auth out_auth_info;
142 : struct dcerpc_auth in_auth_info;
143 : bool more_processing; /* Is there anything more to do after the
144 : * first bind itself received? */
145 : };
146 :
147 : static void bind_auth_next_gensec_done(struct tevent_req *subreq);
148 : static void bind_auth_recv_alter(struct tevent_req *subreq);
149 :
150 13086 : static void bind_auth_next_step(struct composite_context *c)
151 : {
152 : struct bind_auth_state *state;
153 : struct dcecli_security *sec;
154 : struct tevent_req *subreq;
155 :
156 13086 : state = talloc_get_type(c->private_data, struct bind_auth_state);
157 13086 : sec = &state->pipe->conn->security_state;
158 :
159 13086 : if (state->in_auth_info.auth_type != sec->auth_type) {
160 0 : composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
161 0 : return;
162 : }
163 :
164 13086 : if (state->in_auth_info.auth_level != sec->auth_level) {
165 0 : composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
166 0 : return;
167 : }
168 :
169 13086 : if (state->in_auth_info.auth_context_id != sec->auth_context_id) {
170 0 : composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
171 0 : return;
172 : }
173 :
174 13086 : state->out_auth_info = (struct dcerpc_auth) {
175 12566 : .auth_type = sec->auth_type,
176 12566 : .auth_level = sec->auth_level,
177 12566 : .auth_context_id = sec->auth_context_id,
178 : };
179 :
180 : /* The status value here, from GENSEC is vital to the security
181 : * of the system. Even if the other end accepts, if GENSEC
182 : * claims 'MORE_PROCESSING_REQUIRED' then you must keep
183 : * feeding it blobs, or else the remote host/attacker might
184 : * avoid mutal authentication requirements.
185 : *
186 : * Likewise, you must not feed GENSEC too much (after the OK),
187 : * it doesn't like that either
188 : */
189 :
190 13086 : state->pipe->inhibit_timeout_processing = true;
191 13086 : state->pipe->timed_out = false;
192 :
193 23776 : subreq = gensec_update_send(state,
194 12566 : state->pipe->conn->event_ctx,
195 : sec->generic_state,
196 : state->in_auth_info.credentials);
197 13086 : if (composite_nomem(subreq, c)) return;
198 13086 : tevent_req_set_callback(subreq, bind_auth_next_gensec_done, c);
199 : }
200 :
201 13086 : static void bind_auth_next_gensec_done(struct tevent_req *subreq)
202 : {
203 11210 : struct composite_context *c =
204 13086 : tevent_req_callback_data(subreq,
205 : struct composite_context);
206 11210 : struct bind_auth_state *state =
207 13086 : talloc_get_type_abort(c->private_data,
208 : struct bind_auth_state);
209 13086 : struct dcerpc_pipe *p = state->pipe;
210 13086 : struct dcecli_security *sec = &p->conn->security_state;
211 13086 : bool more_processing = false;
212 :
213 13086 : state->pipe->inhibit_timeout_processing = false;
214 :
215 13086 : c->status = gensec_update_recv(subreq, state,
216 : &state->out_auth_info.credentials);
217 13086 : TALLOC_FREE(subreq);
218 :
219 13086 : if (NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
220 5184 : more_processing = true;
221 5184 : c->status = NT_STATUS_OK;
222 : }
223 :
224 14313 : if (!composite_is_ok(c)) return;
225 :
226 13086 : if (!more_processing) {
227 7902 : if (state->pipe->conn->flags & DCERPC_HEADER_SIGNING) {
228 6934 : gensec_want_feature(sec->generic_state,
229 : GENSEC_FEATURE_SIGN_PKT_HEADER);
230 : }
231 : }
232 :
233 13086 : if (state->out_auth_info.credentials.length == 0) {
234 7721 : composite_done(c);
235 7721 : return;
236 : }
237 :
238 5365 : state->in_auth_info = (struct dcerpc_auth) {
239 : .auth_type = DCERPC_AUTH_TYPE_NONE,
240 : };
241 5365 : sec->tmp_auth_info.in = &state->in_auth_info;
242 5365 : sec->tmp_auth_info.mem = state;
243 5365 : sec->tmp_auth_info.out = &state->out_auth_info;
244 :
245 5365 : if (!more_processing) {
246 : /* NO reply expected, so just send it */
247 181 : c->status = dcerpc_auth3(state->pipe, state);
248 181 : if (!composite_is_ok(c)) return;
249 :
250 181 : composite_done(c);
251 181 : return;
252 : }
253 :
254 : /* We are demanding a reply, so use a request that will get us one */
255 :
256 5184 : subreq = dcerpc_alter_context_send(state, state->pipe->conn->event_ctx,
257 : state->pipe,
258 5184 : &state->pipe->syntax,
259 5184 : &state->pipe->transfer_syntax);
260 5184 : if (composite_nomem(subreq, c)) return;
261 5184 : tevent_req_set_callback(subreq, bind_auth_recv_alter, c);
262 : }
263 :
264 :
265 5184 : static void bind_auth_recv_alter(struct tevent_req *subreq)
266 : {
267 4535 : struct composite_context *c =
268 5184 : tevent_req_callback_data(subreq,
269 : struct composite_context);
270 5184 : struct bind_auth_state *state = talloc_get_type(c->private_data,
271 : struct bind_auth_state);
272 5184 : struct dcecli_security *sec = &state->pipe->conn->security_state;
273 :
274 5184 : ZERO_STRUCT(sec->tmp_auth_info);
275 :
276 5184 : c->status = dcerpc_alter_context_recv(subreq);
277 5184 : TALLOC_FREE(subreq);
278 5184 : if (!composite_is_ok(c)) return;
279 :
280 5184 : bind_auth_next_step(c);
281 : }
282 :
283 :
284 7961 : static void bind_auth_recv_bindreply(struct tevent_req *subreq)
285 : {
286 6722 : struct composite_context *c =
287 7961 : tevent_req_callback_data(subreq,
288 : struct composite_context);
289 7961 : struct bind_auth_state *state = talloc_get_type(c->private_data,
290 : struct bind_auth_state);
291 7961 : struct dcecli_security *sec = &state->pipe->conn->security_state;
292 :
293 7961 : ZERO_STRUCT(sec->tmp_auth_info);
294 :
295 7961 : c->status = dcerpc_bind_recv(subreq);
296 7961 : TALLOC_FREE(subreq);
297 7961 : if (!composite_is_ok(c)) return;
298 :
299 7902 : if (!state->more_processing) {
300 : /* The first gensec_update has not requested a second run, so
301 : * we're done here. */
302 0 : composite_done(c);
303 0 : return;
304 : }
305 :
306 7902 : bind_auth_next_step(c);
307 : }
308 :
309 :
310 : static void dcerpc_bind_auth_gensec_done(struct tevent_req *subreq);
311 :
312 : /**
313 : Bind to a DCE/RPC pipe, send async request
314 : @param mem_ctx TALLOC_CTX for the allocation of the composite_context
315 : @param p The dcerpc_pipe to bind (must already be connected)
316 : @param table The interface table to use (the DCE/RPC bind both selects and interface and authenticates)
317 : @param credentials The credentials of the account to connect with
318 : @param auth_type Select the authentication scheme to use
319 : @param auth_level Chooses between unprotected (connect), signed or sealed
320 : @param service The service (used by Kerberos to select the service principal to contact)
321 : @retval A composite context describing the partial state of the bind
322 : */
323 :
324 7985 : struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
325 : struct dcerpc_pipe *p,
326 : const struct ndr_interface_table *table,
327 : struct cli_credentials *credentials,
328 : struct gensec_settings *gensec_settings,
329 : uint8_t auth_type, uint8_t auth_level,
330 : const char *service)
331 : {
332 : struct composite_context *c;
333 : struct bind_auth_state *state;
334 : struct dcecli_security *sec;
335 : struct tevent_req *subreq;
336 7985 : const char *target_principal = NULL;
337 :
338 : /* composite context allocation and setup */
339 7985 : c = composite_create(mem_ctx, p->conn->event_ctx);
340 7985 : if (c == NULL) return NULL;
341 :
342 7985 : state = talloc(c, struct bind_auth_state);
343 7985 : if (composite_nomem(state, c)) return c;
344 7985 : c->private_data = state;
345 :
346 7985 : state->pipe = p;
347 :
348 7985 : c->status = dcerpc_init_syntaxes(p, table,
349 : &state->syntax,
350 : &state->transfer_syntax);
351 7985 : if (!composite_is_ok(c)) return c;
352 :
353 7985 : sec = &p->conn->security_state;
354 :
355 7985 : c->status = gensec_client_start(p, &sec->generic_state,
356 : gensec_settings);
357 7985 : if (!NT_STATUS_IS_OK(c->status)) {
358 0 : DEBUG(1, ("Failed to start GENSEC client mode: %s\n",
359 : nt_errstr(c->status)));
360 0 : composite_error(c, c->status);
361 0 : return c;
362 : }
363 :
364 7985 : c->status = gensec_set_credentials(sec->generic_state, credentials);
365 7985 : if (!NT_STATUS_IS_OK(c->status)) {
366 0 : DEBUG(1, ("Failed to set GENSEC client credentials: %s\n",
367 : nt_errstr(c->status)));
368 0 : composite_error(c, c->status);
369 0 : return c;
370 : }
371 :
372 7985 : c->status = gensec_set_target_hostname(sec->generic_state,
373 : dcerpc_server_name(p));
374 7985 : if (!NT_STATUS_IS_OK(c->status)) {
375 0 : DEBUG(1, ("Failed to set GENSEC target hostname: %s\n",
376 : nt_errstr(c->status)));
377 0 : composite_error(c, c->status);
378 0 : return c;
379 : }
380 :
381 7985 : if (service != NULL) {
382 7576 : c->status = gensec_set_target_service(sec->generic_state,
383 : service);
384 7576 : if (!NT_STATUS_IS_OK(c->status)) {
385 0 : DEBUG(1, ("Failed to set GENSEC target service: %s\n",
386 : nt_errstr(c->status)));
387 0 : composite_error(c, c->status);
388 0 : return c;
389 : }
390 : }
391 :
392 7985 : if (p->binding != NULL) {
393 7985 : target_principal = dcerpc_binding_get_string_option(p->binding,
394 : "target_principal");
395 : }
396 7985 : if (target_principal != NULL) {
397 215 : c->status = gensec_set_target_principal(sec->generic_state,
398 : target_principal);
399 215 : if (!NT_STATUS_IS_OK(c->status)) {
400 0 : DEBUG(1, ("Failed to set GENSEC target principal to %s: %s\n",
401 : target_principal, nt_errstr(c->status)));
402 0 : composite_error(c, c->status);
403 0 : return c;
404 : }
405 : }
406 :
407 7985 : c->status = gensec_start_mech_by_authtype(sec->generic_state,
408 : auth_type, auth_level);
409 7985 : if (!NT_STATUS_IS_OK(c->status)) {
410 24 : DEBUG(1, ("Failed to start GENSEC client mechanism %s: %s\n",
411 : gensec_get_name_by_authtype(sec->generic_state, auth_type),
412 : nt_errstr(c->status)));
413 24 : composite_error(c, c->status);
414 24 : return c;
415 : }
416 :
417 7961 : sec->auth_type = auth_type;
418 7961 : sec->auth_level = auth_level,
419 : /*
420 : * We use auth_context_id = 1 as some older
421 : * Samba versions (<= 4.2.3) use that value hardcoded
422 : * in a response.
423 : */
424 7961 : sec->auth_context_id = 1;
425 :
426 7961 : state->out_auth_info = (struct dcerpc_auth) {
427 7525 : .auth_type = sec->auth_type,
428 7525 : .auth_level = sec->auth_level,
429 7525 : .auth_context_id = sec->auth_context_id,
430 : };
431 :
432 : /* The status value here, from GENSEC is vital to the security
433 : * of the system. Even if the other end accepts, if GENSEC
434 : * claims 'MORE_PROCESSING_REQUIRED' then you must keep
435 : * feeding it blobs, or else the remote host/attacker might
436 : * avoid mutal authentication requirements.
437 : *
438 : * Likewise, you must not feed GENSEC too much (after the OK),
439 : * it doesn't like that either
440 : */
441 :
442 7961 : state->pipe->inhibit_timeout_processing = true;
443 7961 : state->pipe->timed_out = false;
444 :
445 14683 : subreq = gensec_update_send(state,
446 7961 : p->conn->event_ctx,
447 : sec->generic_state,
448 : data_blob_null);
449 7961 : if (composite_nomem(subreq, c)) return c;
450 7961 : tevent_req_set_callback(subreq, dcerpc_bind_auth_gensec_done, c);
451 :
452 7961 : return c;
453 : }
454 :
455 7961 : static void dcerpc_bind_auth_gensec_done(struct tevent_req *subreq)
456 : {
457 6722 : struct composite_context *c =
458 7961 : tevent_req_callback_data(subreq,
459 : struct composite_context);
460 6722 : struct bind_auth_state *state =
461 7961 : talloc_get_type_abort(c->private_data,
462 : struct bind_auth_state);
463 7961 : struct dcerpc_pipe *p = state->pipe;
464 7961 : struct dcecli_security *sec = &p->conn->security_state;
465 :
466 7961 : state->pipe->inhibit_timeout_processing = false;
467 :
468 7961 : c->status = gensec_update_recv(subreq, state,
469 : &state->out_auth_info.credentials);
470 7961 : TALLOC_FREE(subreq);
471 14247 : if (!NT_STATUS_IS_OK(c->status) &&
472 7525 : !NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
473 0 : composite_error(c, c->status);
474 0 : return;
475 : }
476 :
477 7961 : state->more_processing = NT_STATUS_EQUAL(c->status,
478 : NT_STATUS_MORE_PROCESSING_REQUIRED);
479 :
480 7961 : if (state->out_auth_info.credentials.length == 0) {
481 0 : composite_done(c);
482 0 : return;
483 : }
484 :
485 7961 : if (gensec_have_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER)) {
486 7521 : if (sec->auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
487 7485 : state->pipe->conn->flags |= DCERPC_PROPOSE_HEADER_SIGNING;
488 : }
489 : }
490 :
491 7961 : state->in_auth_info = (struct dcerpc_auth) {
492 : .auth_type = DCERPC_AUTH_TYPE_NONE,
493 : };
494 7961 : sec->tmp_auth_info.in = &state->in_auth_info;
495 7961 : sec->tmp_auth_info.mem = state;
496 7961 : sec->tmp_auth_info.out = &state->out_auth_info;
497 :
498 : /* The first request always is a dcerpc_bind. The subsequent ones
499 : * depend on gensec results */
500 7961 : subreq = dcerpc_bind_send(state, p->conn->event_ctx, p,
501 7961 : &state->syntax, &state->transfer_syntax);
502 7961 : if (composite_nomem(subreq, c)) return;
503 7961 : tevent_req_set_callback(subreq, bind_auth_recv_bindreply, c);
504 :
505 7961 : return;
506 : }
507 :
508 :
509 : /**
510 : Bind to a DCE/RPC pipe, receive result
511 : @param creq A composite context describing state of async call
512 : @retval NTSTATUS code
513 : */
514 :
515 7985 : NTSTATUS dcerpc_bind_auth_recv(struct composite_context *creq)
516 : {
517 7985 : NTSTATUS result = composite_wait(creq);
518 7985 : struct bind_auth_state *state = talloc_get_type(creq->private_data,
519 : struct bind_auth_state);
520 :
521 7985 : if (NT_STATUS_IS_OK(result)) {
522 : /*
523 : after a successful authenticated bind the session
524 : key reverts to the generic session key
525 : */
526 7902 : state->pipe->conn->security_state.session_key = dcecli_generic_session_key;
527 : }
528 :
529 7985 : talloc_free(creq);
530 7985 : return result;
531 : }
532 :
533 :
534 : /**
535 : Perform a GENSEC authenticated bind to a DCE/RPC pipe, sync
536 : @param p The dcerpc_pipe to bind (must already be connected)
537 : @param table The interface table to use (the DCE/RPC bind both selects and interface and authenticates)
538 : @param credentials The credentials of the account to connect with
539 : @param auth_type Select the authentication scheme to use
540 : @param auth_level Chooses between unprotected (connect), signed or sealed
541 : @param service The service (used by Kerberos to select the service principal to contact)
542 : @retval NTSTATUS status code
543 : */
544 :
545 32 : _PUBLIC_ NTSTATUS dcerpc_bind_auth(struct dcerpc_pipe *p,
546 : const struct ndr_interface_table *table,
547 : struct cli_credentials *credentials,
548 : struct gensec_settings *gensec_settings,
549 : uint8_t auth_type, uint8_t auth_level,
550 : const char *service)
551 : {
552 : struct composite_context *creq;
553 32 : creq = dcerpc_bind_auth_send(p, p, table, credentials, gensec_settings,
554 : auth_type, auth_level, service);
555 32 : return dcerpc_bind_auth_recv(creq);
556 : }
|