Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : dcerpc utility functions
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 : Copyright (C) Jelmer Vernooij 2004
8 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
9 : Copyright (C) Rafal Szczesniak 2006
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "includes.h"
26 : #include "lib/events/events.h"
27 : #include "libcli/composite/composite.h"
28 : #include "librpc/gen_ndr/ndr_epmapper_c.h"
29 : #include "librpc/gen_ndr/ndr_dcerpc.h"
30 : #include "librpc/gen_ndr/ndr_misc.h"
31 : #include "librpc/rpc/dcerpc_proto.h"
32 : #include "auth/credentials/credentials.h"
33 : #include "auth/gensec/gensec.h"
34 : #include "param/param.h"
35 : #include "librpc/rpc/rpc_common.h"
36 :
37 : /*
38 : find a dcerpc call on an interface by name
39 : */
40 0 : const struct ndr_interface_call *dcerpc_iface_find_call(const struct ndr_interface_table *iface,
41 : const char *name)
42 : {
43 0 : uint32_t i;
44 0 : for (i=0;i<iface->num_calls;i++) {
45 0 : if (strcmp(iface->calls[i].name, name) == 0) {
46 0 : return &iface->calls[i];
47 : }
48 : }
49 0 : return NULL;
50 : }
51 :
52 : struct epm_map_binding_state {
53 : struct dcerpc_binding *binding;
54 : const struct ndr_interface_table *table;
55 : struct dcerpc_pipe *pipe;
56 : struct policy_handle handle;
57 : struct GUID object;
58 : struct epm_twr_t twr;
59 : struct epm_twr_t *twr_r;
60 : uint32_t num_towers;
61 : struct epm_Map r;
62 : };
63 :
64 :
65 : static void continue_epm_recv_binding(struct composite_context *ctx);
66 : static void continue_epm_map(struct tevent_req *subreq);
67 :
68 :
69 : /*
70 : Stage 2 of epm_map_binding: Receive connected rpc pipe and send endpoint
71 : mapping rpc request
72 : */
73 10618 : static void continue_epm_recv_binding(struct composite_context *ctx)
74 : {
75 10618 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
76 : struct composite_context);
77 10618 : struct epm_map_binding_state *s = talloc_get_type(c->private_data,
78 : struct epm_map_binding_state);
79 125 : struct tevent_req *subreq;
80 :
81 : /* receive result of rpc pipe connect request */
82 10618 : c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe);
83 10618 : if (!composite_is_ok(c)) return;
84 :
85 6124 : c->status = dcerpc_binding_build_tower(s->pipe, s->binding, &s->twr.tower);
86 6124 : if (!composite_is_ok(c)) return;
87 :
88 : /* with some nice pretty paper around it of course */
89 6124 : s->r.in.object = &s->object;
90 6124 : s->r.in.map_tower = &s->twr;
91 6124 : s->r.in.entry_handle = &s->handle;
92 6124 : s->r.in.max_towers = 1;
93 6124 : s->r.out.entry_handle = &s->handle;
94 6124 : s->r.out.num_towers = &s->num_towers;
95 :
96 : /* send request for an endpoint mapping - a rpc request on connected pipe */
97 6249 : subreq = dcerpc_epm_Map_r_send(s, c->event_ctx,
98 6124 : s->pipe->binding_handle,
99 : &s->r);
100 6124 : if (composite_nomem(subreq, c)) return;
101 :
102 6124 : tevent_req_set_callback(subreq, continue_epm_map, c);
103 : }
104 :
105 :
106 : /*
107 : Stage 3 of epm_map_binding: Receive endpoint mapping and provide binding details
108 : */
109 6124 : static void continue_epm_map(struct tevent_req *subreq)
110 : {
111 6124 : struct composite_context *c = tevent_req_callback_data(subreq,
112 : struct composite_context);
113 6124 : struct epm_map_binding_state *s = talloc_get_type(c->private_data,
114 : struct epm_map_binding_state);
115 125 : const char *endpoint;
116 :
117 : /* receive result of a rpc request */
118 6124 : c->status = dcerpc_epm_Map_r_recv(subreq, s);
119 6124 : TALLOC_FREE(subreq);
120 6124 : if (!composite_is_ok(c)) return;
121 :
122 : /* check the details */
123 6124 : if (s->r.out.result != 0 || *s->r.out.num_towers != 1) {
124 94 : composite_error(c, NT_STATUS_PORT_UNREACHABLE);
125 94 : return;
126 : }
127 :
128 6030 : s->twr_r = s->r.out.towers[0].twr;
129 6030 : if (s->twr_r == NULL) {
130 0 : composite_error(c, NT_STATUS_PORT_UNREACHABLE);
131 0 : return;
132 : }
133 :
134 6030 : if (s->twr_r->tower.num_floors != s->twr.tower.num_floors ||
135 6030 : s->twr_r->tower.floors[3].lhs.protocol != s->twr.tower.floors[3].lhs.protocol) {
136 0 : composite_error(c, NT_STATUS_PORT_UNREACHABLE);
137 0 : return;
138 : }
139 :
140 : /* get received endpoint */
141 6030 : endpoint = dcerpc_floor_get_rhs_data(s, &s->twr_r->tower.floors[3]);
142 6030 : if (composite_nomem(endpoint, c)) return;
143 :
144 6030 : c->status = dcerpc_binding_set_string_option(s->binding,
145 : "endpoint",
146 : endpoint);
147 6030 : if (!composite_is_ok(c)) {
148 0 : return;
149 : }
150 :
151 6030 : composite_done(c);
152 : }
153 :
154 :
155 : /*
156 : Request for endpoint mapping of dcerpc binding - try to request for endpoint
157 : unless there is default one.
158 : */
159 28448 : struct composite_context *dcerpc_epm_map_binding_send(TALLOC_CTX *mem_ctx,
160 : struct dcerpc_binding *binding,
161 : const struct ndr_interface_table *table,
162 : struct cli_credentials *creds,
163 : struct tevent_context *ev,
164 : struct loadparm_context *lp_ctx)
165 : {
166 777 : struct composite_context *c;
167 777 : struct epm_map_binding_state *s;
168 777 : struct composite_context *pipe_connect_req;
169 777 : NTSTATUS status;
170 777 : struct dcerpc_binding *epmapper_binding;
171 777 : uint32_t i;
172 :
173 28448 : if (ev == NULL) {
174 0 : return NULL;
175 : }
176 :
177 : /* composite context allocation and setup */
178 28448 : c = composite_create(mem_ctx, ev);
179 28448 : if (c == NULL) {
180 0 : return NULL;
181 : }
182 :
183 28448 : s = talloc_zero(c, struct epm_map_binding_state);
184 28448 : if (composite_nomem(s, c)) return c;
185 28448 : c->private_data = s;
186 :
187 28448 : s->binding = binding;
188 28448 : s->object = dcerpc_binding_get_object(binding);
189 28448 : s->table = table;
190 :
191 28448 : c->status = dcerpc_binding_set_abstract_syntax(binding,
192 : &table->syntax_id);
193 28448 : if (!composite_is_ok(c)) {
194 0 : return c;
195 : }
196 :
197 : /*
198 : First, check if there is a default endpoint specified in the IDL
199 : */
200 77841 : for (i = 0; i < table->endpoints->count; i++) {
201 1282 : struct dcerpc_binding *default_binding;
202 1282 : enum dcerpc_transport_t transport;
203 1282 : enum dcerpc_transport_t dtransport;
204 67222 : const char *dendpoint = NULL;
205 :
206 67222 : status = dcerpc_parse_binding(s,
207 67222 : table->endpoints->names[i],
208 : &default_binding);
209 67222 : if (!NT_STATUS_IS_OK(status)) {
210 49393 : continue;
211 : }
212 :
213 67222 : transport = dcerpc_binding_get_transport(binding);
214 67222 : dtransport = dcerpc_binding_get_transport(default_binding);
215 67222 : if (transport == NCA_UNKNOWN) {
216 1188 : c->status = dcerpc_binding_set_transport(binding,
217 : dtransport);
218 1188 : if (!composite_is_ok(c)) {
219 17829 : return c;
220 : }
221 1132 : transport = dtransport;
222 : }
223 :
224 67222 : if (transport != dtransport) {
225 38832 : TALLOC_FREE(default_binding);
226 38832 : continue;
227 : }
228 :
229 28390 : dendpoint = dcerpc_binding_get_string_option(default_binding,
230 : "endpoint");
231 28390 : if (dendpoint == NULL) {
232 10561 : TALLOC_FREE(default_binding);
233 10561 : continue;
234 : }
235 :
236 17829 : c->status = dcerpc_binding_set_string_option(binding,
237 : "endpoint",
238 : dendpoint);
239 17829 : if (!composite_is_ok(c)) {
240 0 : return c;
241 : }
242 :
243 17829 : TALLOC_FREE(default_binding);
244 17829 : composite_done(c);
245 17829 : return c;
246 : }
247 :
248 10619 : epmapper_binding = dcerpc_binding_dup(s, binding);
249 10619 : if (composite_nomem(epmapper_binding, c)) return c;
250 :
251 : /* basic endpoint mapping data */
252 10619 : c->status = dcerpc_binding_set_string_option(epmapper_binding,
253 : "endpoint", NULL);
254 10619 : if (!composite_is_ok(c)) {
255 0 : return c;
256 : }
257 10619 : c->status = dcerpc_binding_set_flags(epmapper_binding, 0, UINT32_MAX);
258 10619 : if (!composite_is_ok(c)) {
259 0 : return c;
260 : }
261 10619 : c->status = dcerpc_binding_set_assoc_group_id(epmapper_binding, 0);
262 10619 : if (!composite_is_ok(c)) {
263 0 : return c;
264 : }
265 10619 : c->status = dcerpc_binding_set_object(epmapper_binding, GUID_zero());
266 10619 : if (!composite_is_ok(c)) {
267 0 : return c;
268 : }
269 :
270 : /* initiate rpc pipe connection */
271 10619 : pipe_connect_req = dcerpc_pipe_connect_b_send(s, epmapper_binding,
272 : &ndr_table_epmapper,
273 : creds, c->event_ctx,
274 : lp_ctx);
275 10619 : if (composite_nomem(pipe_connect_req, c)) return c;
276 :
277 10619 : composite_continue(c, pipe_connect_req, continue_epm_recv_binding, c);
278 10619 : return c;
279 : }
280 :
281 :
282 : /*
283 : Receive result of endpoint mapping request
284 : */
285 28447 : NTSTATUS dcerpc_epm_map_binding_recv(struct composite_context *c)
286 : {
287 28447 : NTSTATUS status = composite_wait(c);
288 :
289 28447 : talloc_free(c);
290 28447 : return status;
291 : }
292 :
293 :
294 : /*
295 : Get endpoint mapping for rpc connection
296 : */
297 1487 : _PUBLIC_ NTSTATUS dcerpc_epm_map_binding(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding,
298 : const struct ndr_interface_table *table, struct tevent_context *ev,
299 : struct loadparm_context *lp_ctx)
300 : {
301 195 : struct composite_context *c;
302 195 : struct cli_credentials *epm_creds;
303 :
304 1487 : epm_creds = cli_credentials_init_anon(mem_ctx);
305 1487 : if (epm_creds == NULL) {
306 0 : return NT_STATUS_NO_MEMORY;
307 : }
308 1487 : c = dcerpc_epm_map_binding_send(mem_ctx, binding, table, epm_creds, ev, lp_ctx);
309 1487 : if (c == NULL) {
310 0 : talloc_free(epm_creds);
311 0 : return NT_STATUS_NO_MEMORY;
312 : }
313 1487 : talloc_steal(c, epm_creds);
314 1487 : return dcerpc_epm_map_binding_recv(c);
315 : }
316 :
317 :
318 : struct pipe_auth_state {
319 : struct dcerpc_pipe *pipe;
320 : const struct dcerpc_binding *binding;
321 : const struct ndr_interface_table *table;
322 : struct loadparm_context *lp_ctx;
323 : struct cli_credentials *credentials;
324 : unsigned int logon_retries;
325 : };
326 :
327 :
328 : static void continue_auth_schannel(struct composite_context *ctx);
329 : static void continue_auth(struct composite_context *ctx);
330 : static void continue_auth_none(struct composite_context *ctx);
331 : static void continue_ntlmssp_connection(struct composite_context *ctx);
332 : static void continue_spnego_after_wrong_pass(struct composite_context *ctx);
333 :
334 :
335 : /*
336 : Stage 2 of pipe_auth: Receive result of schannel bind request
337 : */
338 473 : static void continue_auth_schannel(struct composite_context *ctx)
339 : {
340 473 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
341 : struct composite_context);
342 :
343 473 : c->status = dcerpc_bind_auth_schannel_recv(ctx);
344 473 : if (!composite_is_ok(c)) return;
345 :
346 469 : composite_done(c);
347 : }
348 :
349 :
350 : /*
351 : Stage 2 of pipe_auth: Receive result of authenticated bind request
352 : */
353 2708 : static void continue_auth(struct composite_context *ctx)
354 : {
355 2708 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
356 : struct composite_context);
357 :
358 2708 : c->status = dcerpc_bind_auth_recv(ctx);
359 2708 : if (!composite_is_ok(c)) return;
360 :
361 2702 : composite_done(c);
362 : }
363 : /*
364 : Stage 2 of pipe_auth: Receive result of authenticated bind request, but handle fallbacks:
365 : SPNEGO -> NTLMSSP
366 : */
367 5550 : static void continue_auth_auto(struct composite_context *ctx)
368 : {
369 5550 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
370 : struct composite_context);
371 5550 : struct pipe_auth_state *s = talloc_get_type(c->private_data, struct pipe_auth_state);
372 102 : struct composite_context *sec_conn_req;
373 :
374 5550 : c->status = dcerpc_bind_auth_recv(ctx);
375 5550 : if (NT_STATUS_EQUAL(c->status, NT_STATUS_INVALID_PARAMETER)) {
376 : /*
377 : * Retry with NTLMSSP auth as fallback
378 : * send a request for secondary rpc connection
379 : */
380 24 : sec_conn_req = dcerpc_secondary_connection_send(s->pipe,
381 : s->binding);
382 24 : composite_continue(c, sec_conn_req, continue_ntlmssp_connection, c);
383 31 : return;
384 5526 : } else if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE) ||
385 5424 : NT_STATUS_EQUAL(c->status, NT_STATUS_UNSUCCESSFUL)) {
386 : /*
387 : try a second time on any error. We don't just do it
388 : on LOGON_FAILURE as some servers will give a
389 : NT_STATUS_UNSUCCESSFUL on a authentication error on RPC
390 : */
391 6 : const char *principal;
392 6 : const char *endpoint;
393 :
394 25 : principal = gensec_get_target_principal(s->pipe->conn->security_state.generic_state);
395 25 : if (principal == NULL) {
396 25 : const char *hostname = gensec_get_target_hostname(s->pipe->conn->security_state.generic_state);
397 25 : const char *service = gensec_get_target_service(s->pipe->conn->security_state.generic_state);
398 25 : if (hostname != NULL && service != NULL) {
399 25 : principal = talloc_asprintf(c, "%s/%s", service, hostname);
400 : }
401 : }
402 :
403 25 : endpoint = dcerpc_binding_get_string_option(s->binding, "endpoint");
404 :
405 43 : if ((cli_credentials_failed_kerberos_login(s->credentials, principal, &s->logon_retries) ||
406 25 : cli_credentials_wrong_password(s->credentials)) &&
407 : endpoint != NULL) {
408 : /*
409 : * Retry SPNEGO with a better password
410 : * send a request for secondary rpc connection
411 : */
412 7 : sec_conn_req = dcerpc_secondary_connection_send(s->pipe,
413 : s->binding);
414 7 : composite_continue(c, sec_conn_req, continue_spnego_after_wrong_pass, c);
415 7 : return;
416 : }
417 : }
418 :
419 5519 : if (!composite_is_ok(c)) return;
420 :
421 5501 : composite_done(c);
422 : }
423 :
424 : /*
425 : Stage 3 of pipe_auth (fallback to NTLMSSP case): Receive secondary
426 : rpc connection (the first one can't be used any more, due to the
427 : bind nak) and perform authenticated bind request
428 : */
429 24 : static void continue_ntlmssp_connection(struct composite_context *ctx)
430 : {
431 0 : struct composite_context *c;
432 0 : struct pipe_auth_state *s;
433 0 : struct composite_context *auth_req;
434 0 : struct dcerpc_pipe *p2;
435 0 : void *pp;
436 :
437 24 : c = talloc_get_type(ctx->async.private_data, struct composite_context);
438 24 : s = talloc_get_type(c->private_data, struct pipe_auth_state);
439 :
440 : /* receive secondary rpc connection */
441 24 : c->status = dcerpc_secondary_connection_recv(ctx, &p2);
442 24 : if (!composite_is_ok(c)) return;
443 :
444 :
445 : /* this is a rather strange situation. When
446 : we come into the routine, s is a child of s->pipe, and
447 : when we created p2 above, it also became a child of
448 : s->pipe.
449 :
450 : Now we want p2 to be a parent of s->pipe, and we want s to
451 : be a parent of both of them! If we don't do this very
452 : carefully we end up creating a talloc loop
453 : */
454 :
455 : /* we need the new contexts to hang off the same context
456 : that s->pipe is on, but the only way to get that is
457 : via talloc_parent() */
458 24 : pp = talloc_parent(s->pipe);
459 :
460 : /* promote s to be at the top */
461 24 : talloc_steal(pp, s);
462 :
463 : /* and put p2 under s */
464 24 : talloc_steal(s, p2);
465 :
466 : /* now put s->pipe under p2 */
467 24 : talloc_steal(p2, s->pipe);
468 :
469 24 : s->pipe = p2;
470 :
471 : /* initiate a authenticated bind */
472 24 : auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
473 : s->credentials,
474 : lpcfg_gensec_settings(c, s->lp_ctx),
475 : DCERPC_AUTH_TYPE_NTLMSSP,
476 24 : dcerpc_auth_level(s->pipe->conn),
477 24 : s->table->authservices->names[0]);
478 24 : composite_continue(c, auth_req, continue_auth, c);
479 : }
480 :
481 : /*
482 : Stage 3 of pipe_auth (retry on wrong password): Receive secondary
483 : rpc connection (the first one can't be used any more, due to the
484 : bind nak) and perform authenticated bind request
485 : */
486 7 : static void continue_spnego_after_wrong_pass(struct composite_context *ctx)
487 : {
488 0 : struct composite_context *c;
489 0 : struct pipe_auth_state *s;
490 0 : struct composite_context *auth_req;
491 0 : struct dcerpc_pipe *p2;
492 :
493 7 : c = talloc_get_type(ctx->async.private_data, struct composite_context);
494 7 : s = talloc_get_type(c->private_data, struct pipe_auth_state);
495 :
496 : /* receive secondary rpc connection */
497 7 : c->status = dcerpc_secondary_connection_recv(ctx, &p2);
498 7 : if (!composite_is_ok(c)) return;
499 :
500 7 : talloc_steal(s, p2);
501 7 : talloc_steal(p2, s->pipe);
502 7 : s->pipe = p2;
503 :
504 : /* initiate a authenticated bind */
505 7 : auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
506 : s->credentials,
507 : lpcfg_gensec_settings(c, s->lp_ctx),
508 : DCERPC_AUTH_TYPE_SPNEGO,
509 7 : dcerpc_auth_level(s->pipe->conn),
510 7 : s->table->authservices->names[0]);
511 7 : composite_continue(c, auth_req, continue_auth, c);
512 : }
513 :
514 :
515 : /*
516 : Stage 2 of pipe_auth: Receive result of non-authenticated bind request
517 : */
518 10772 : static void continue_auth_none(struct composite_context *ctx)
519 : {
520 10772 : struct composite_context *c = talloc_get_type(ctx->async.private_data,
521 : struct composite_context);
522 :
523 10772 : c->status = dcerpc_bind_auth_none_recv(ctx);
524 10772 : if (!composite_is_ok(c)) return;
525 :
526 10715 : composite_done(c);
527 : }
528 :
529 :
530 : /*
531 : Request to perform an authenticated bind if required. Authentication
532 : is determined using credentials passed and binding flags.
533 : */
534 19472 : struct composite_context *dcerpc_pipe_auth_send(struct dcerpc_pipe *p,
535 : const struct dcerpc_binding *binding,
536 : const struct ndr_interface_table *table,
537 : struct cli_credentials *credentials,
538 : struct loadparm_context *lp_ctx)
539 : {
540 814 : struct composite_context *c;
541 814 : struct pipe_auth_state *s;
542 814 : struct composite_context *auth_schannel_req;
543 814 : struct composite_context *auth_req;
544 814 : struct composite_context *auth_none_req;
545 814 : struct dcecli_connection *conn;
546 814 : uint8_t auth_type;
547 :
548 : /* composite context allocation and setup */
549 19472 : c = composite_create(p, p->conn->event_ctx);
550 19472 : if (c == NULL) return NULL;
551 :
552 19472 : s = talloc_zero(c, struct pipe_auth_state);
553 19472 : if (composite_nomem(s, c)) return c;
554 19472 : c->private_data = s;
555 :
556 : /* store parameters in state structure */
557 19472 : s->binding = binding;
558 19472 : s->table = table;
559 19472 : s->credentials = credentials;
560 19472 : s->pipe = p;
561 19472 : s->lp_ctx = lp_ctx;
562 :
563 19472 : conn = s->pipe->conn;
564 19472 : conn->flags = dcerpc_binding_get_flags(binding);
565 :
566 19472 : if (DEBUGLVL(100)) {
567 0 : conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
568 : }
569 :
570 19472 : if (conn->transport.transport == NCALRPC) {
571 1402 : const char *v = dcerpc_binding_get_string_option(binding,
572 : "auth_type");
573 :
574 1402 : if (v != NULL && strcmp(v, "ncalrpc_as_system") == 0) {
575 440 : auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
576 : s->credentials,
577 : lpcfg_gensec_settings(c, s->lp_ctx),
578 : DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
579 : DCERPC_AUTH_LEVEL_CONNECT,
580 440 : s->table->authservices->names[0]);
581 440 : composite_continue(c, auth_req, continue_auth, c);
582 440 : return c;
583 : }
584 : }
585 :
586 19032 : if (cli_credentials_is_anonymous(s->credentials)) {
587 6319 : auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe, s->table);
588 6319 : composite_continue(c, auth_none_req, continue_auth_none, c);
589 6319 : return c;
590 : }
591 :
592 15050 : if ((conn->flags & DCERPC_SCHANNEL) &&
593 2337 : !cli_credentials_get_netlogon_creds(s->credentials)) {
594 : /* If we don't already have netlogon credentials for
595 : * the schannel bind, then we have to get these
596 : * first */
597 473 : auth_schannel_req = dcerpc_bind_auth_schannel_send(c, s->pipe, s->table,
598 : s->credentials, s->lp_ctx,
599 473 : dcerpc_auth_level(conn));
600 473 : composite_continue(c, auth_schannel_req, continue_auth_schannel, c);
601 473 : return c;
602 : }
603 :
604 : /*
605 : * we rely on the already authenticated CIFS connection
606 : * if not doing sign or seal
607 : */
608 12240 : if (conn->transport.transport == NCACN_NP &&
609 6766 : !(conn->flags & (DCERPC_PACKET|DCERPC_SIGN|DCERPC_SEAL))) {
610 4453 : auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe, s->table);
611 4453 : composite_continue(c, auth_none_req, continue_auth_none, c);
612 4453 : return c;
613 : }
614 :
615 :
616 : /* Perform an authenticated DCE-RPC bind
617 : */
618 7787 : if (!(conn->flags & (DCERPC_CONNECT|DCERPC_SEAL|DCERPC_PACKET))) {
619 : /*
620 : we are doing an authenticated connection,
621 : which needs to use [connect], [sign] or [seal].
622 : If nothing is specified, we default to [sign] now.
623 : This give roughly the same protection as
624 : ncacn_np with smb signing.
625 : */
626 2777 : conn->flags |= DCERPC_SIGN;
627 : }
628 :
629 7787 : if (conn->flags & DCERPC_AUTH_SPNEGO) {
630 220 : auth_type = DCERPC_AUTH_TYPE_SPNEGO;
631 :
632 7567 : } else if (conn->flags & DCERPC_AUTH_KRB5) {
633 93 : auth_type = DCERPC_AUTH_TYPE_KRB5;
634 :
635 7474 : } else if (conn->flags & DCERPC_SCHANNEL) {
636 1600 : auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
637 :
638 5610 : } else if (conn->flags & DCERPC_AUTH_NTLM) {
639 60 : auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
640 :
641 : } else {
642 : /* try SPNEGO with fallback to NTLMSSP */
643 5550 : auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
644 : s->credentials,
645 : lpcfg_gensec_settings(c, s->lp_ctx),
646 : DCERPC_AUTH_TYPE_SPNEGO,
647 5550 : dcerpc_auth_level(conn),
648 5550 : s->table->authservices->names[0]);
649 5550 : composite_continue(c, auth_req, continue_auth_auto, c);
650 5550 : return c;
651 : }
652 :
653 2237 : auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
654 : s->credentials,
655 : lpcfg_gensec_settings(c, s->lp_ctx),
656 : auth_type,
657 2237 : dcerpc_auth_level(conn),
658 2237 : s->table->authservices->names[0]);
659 2237 : composite_continue(c, auth_req, continue_auth, c);
660 2237 : return c;
661 : }
662 :
663 :
664 : /*
665 : Receive result of authenticated bind request on dcerpc pipe
666 :
667 : This returns *p, which may be different to the one originally
668 : supplied, as it rebinds to a new pipe due to authentication fallback
669 :
670 : */
671 19472 : NTSTATUS dcerpc_pipe_auth_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
672 : struct dcerpc_pipe **p)
673 : {
674 814 : NTSTATUS status;
675 :
676 19472 : struct pipe_auth_state *s = talloc_get_type(c->private_data,
677 : struct pipe_auth_state);
678 19472 : status = composite_wait(c);
679 19472 : if (!NT_STATUS_IS_OK(status)) {
680 85 : char *uuid_str = GUID_string(s->pipe, &s->table->syntax_id.uuid);
681 85 : DEBUG(0, ("Failed to bind to uuid %s for %s %s\n", uuid_str,
682 : dcerpc_binding_string(uuid_str, s->binding), nt_errstr(status)));
683 85 : talloc_free(uuid_str);
684 : } else {
685 19387 : talloc_steal(mem_ctx, s->pipe);
686 19387 : *p = s->pipe;
687 : }
688 :
689 19472 : talloc_free(c);
690 19472 : return status;
691 : }
692 :
693 :
694 : /*
695 : Perform an authenticated bind if needed - sync version
696 :
697 : This may change *p, as it rebinds to a new pipe due to authentication fallback
698 : */
699 0 : _PUBLIC_ NTSTATUS dcerpc_pipe_auth(TALLOC_CTX *mem_ctx,
700 : struct dcerpc_pipe **p,
701 : const struct dcerpc_binding *binding,
702 : const struct ndr_interface_table *table,
703 : struct cli_credentials *credentials,
704 : struct loadparm_context *lp_ctx)
705 : {
706 0 : struct composite_context *c;
707 :
708 0 : c = dcerpc_pipe_auth_send(*p, binding, table, credentials, lp_ctx);
709 0 : return dcerpc_pipe_auth_recv(c, mem_ctx, p);
710 : }
711 :
712 :
713 768 : NTSTATUS dcecli_generic_session_key(struct dcecli_connection *c,
714 : DATA_BLOB *session_key)
715 : {
716 768 : if (c != NULL) {
717 768 : if (c->transport.transport != NCALRPC &&
718 691 : c->transport.transport != NCACN_UNIX_STREAM)
719 : {
720 691 : return NT_STATUS_LOCAL_USER_SESSION_KEY;
721 : }
722 : }
723 :
724 77 : return dcerpc_generic_session_key(session_key);
725 : }
726 :
727 : /*
728 : fetch the user session key - may be default (above) or the SMB session key
729 :
730 : The key is always truncated to 16 bytes
731 : */
732 4002 : _PUBLIC_ NTSTATUS dcerpc_fetch_session_key(struct dcerpc_pipe *p,
733 : DATA_BLOB *session_key)
734 : {
735 72 : NTSTATUS status;
736 4002 : status = p->conn->security_state.session_key(p->conn, session_key);
737 4002 : if (!NT_STATUS_IS_OK(status)) {
738 691 : return status;
739 : }
740 :
741 3311 : session_key->length = MIN(session_key->length, 16);
742 :
743 3311 : return NT_STATUS_OK;
744 : }
745 :
746 8 : _PUBLIC_ bool dcerpc_transport_encrypted(struct dcerpc_pipe *p)
747 : {
748 8 : if (p == NULL) {
749 0 : return false;
750 : }
751 :
752 8 : if (p->conn == NULL) {
753 0 : return false;
754 : }
755 :
756 8 : return p->conn->transport.encrypted;
757 : }
758 :
759 : /*
760 : create a secondary context from a primary connection
761 :
762 : this uses dcerpc_alter_context() to create a new dcerpc context_id
763 : */
764 33 : _PUBLIC_ NTSTATUS dcerpc_secondary_context(struct dcerpc_pipe *p,
765 : struct dcerpc_pipe **pp2,
766 : const struct ndr_interface_table *table)
767 : {
768 6 : NTSTATUS status;
769 6 : struct dcerpc_pipe *p2;
770 33 : struct GUID *object = NULL;
771 :
772 33 : p2 = talloc_zero(p, struct dcerpc_pipe);
773 33 : if (p2 == NULL) {
774 0 : return NT_STATUS_NO_MEMORY;
775 : }
776 33 : p2->conn = talloc_reference(p2, p->conn);
777 33 : p2->request_timeout = p->request_timeout;
778 :
779 33 : p2->context_id = ++p->conn->next_context_id;
780 :
781 33 : p2->syntax = table->syntax_id;
782 :
783 33 : p2->transfer_syntax = p->transfer_syntax;
784 :
785 33 : p2->binding = dcerpc_binding_dup(p2, p->binding);
786 33 : if (p2->binding == NULL) {
787 0 : talloc_free(p2);
788 0 : return NT_STATUS_NO_MEMORY;
789 : }
790 :
791 33 : p2->object = dcerpc_binding_get_object(p2->binding);
792 33 : if (!GUID_all_zero(&p2->object)) {
793 0 : object = &p2->object;
794 : }
795 :
796 33 : p2->binding_handle = dcerpc_pipe_binding_handle(p2, object, table);
797 33 : if (p2->binding_handle == NULL) {
798 0 : talloc_free(p2);
799 0 : return NT_STATUS_NO_MEMORY;
800 : }
801 :
802 33 : status = dcerpc_alter_context(p2, p2, &p2->syntax, &p2->transfer_syntax);
803 33 : if (!NT_STATUS_IS_OK(status)) {
804 15 : talloc_free(p2);
805 15 : return status;
806 : }
807 :
808 18 : *pp2 = p2;
809 :
810 18 : return NT_STATUS_OK;
811 : }
|