1/* 2 Unix SMB/CIFS implementation. 3 4 dcerpc connect functions 5 6 Copyright (C) Andrew Tridgell 2003 7 Copyright (C) Jelmer Vernooij 2004 8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007 9 Copyright (C) Rafal Szczesniak 2005 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 26#include "includes.h" 27#include "libcli/composite/composite.h" 28#include "libcli/smb_composite/smb_composite.h" 29#include "lib/events/events.h" 30#include "libcli/smb2/smb2.h" 31#include "libcli/smb2/smb2_calls.h" 32#include "librpc/rpc/dcerpc.h" 33#include "librpc/rpc/dcerpc_proto.h" 34#include "auth/credentials/credentials.h" 35#include "param/param.h" 36#include "libcli/resolve/resolve.h" 37 38 39struct pipe_np_smb_state { 40 struct smb_composite_connect conn; 41 struct smbcli_tree *tree; 42 struct dcerpc_pipe_connect io; 43}; 44 45 46/* 47 Stage 3 of ncacn_np_smb: Named pipe opened (or not) 48*/ 49static void continue_pipe_open_smb(struct composite_context *ctx) 50{ 51 struct composite_context *c = talloc_get_type(ctx->async.private_data, 52 struct composite_context); 53 54 /* receive result of named pipe open request on smb */ 55 c->status = dcerpc_pipe_open_smb_recv(ctx); 56 if (!composite_is_ok(c)) return; 57 58 composite_done(c); 59} 60 61 62/* 63 Stage 2 of ncacn_np_smb: Open a named pipe after successful smb connection 64*/ 65static void continue_smb_connect(struct composite_context *ctx) 66{ 67 struct composite_context *open_ctx; 68 struct composite_context *c = talloc_get_type(ctx->async.private_data, 69 struct composite_context); 70 struct pipe_np_smb_state *s = talloc_get_type(c->private_data, 71 struct pipe_np_smb_state); 72 73 /* receive result of smb connect request */ 74 c->status = smb_composite_connect_recv(ctx, c); 75 if (!composite_is_ok(c)) return; 76 77 /* prepare named pipe open parameters */ 78 s->tree = s->conn.out.tree; 79 s->io.pipe_name = s->io.binding->endpoint; 80 81 /* send named pipe open request */ 82 open_ctx = dcerpc_pipe_open_smb_send(s->io.pipe, s->tree, s->io.pipe_name); 83 if (composite_nomem(open_ctx, c)) return; 84 85 composite_continue(c, open_ctx, continue_pipe_open_smb, c); 86} 87 88 89/* 90 Initiate async open of a rpc connection to a rpc pipe on SMB using 91 the binding structure to determine the endpoint and options 92*/ 93static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CTX *mem_ctx, struct dcerpc_pipe_connect *io, struct loadparm_context *lp_ctx) 94{ 95 struct composite_context *c; 96 struct pipe_np_smb_state *s; 97 struct composite_context *conn_req; 98 struct smb_composite_connect *conn; 99 100 /* composite context allocation and setup */ 101 c = composite_create(mem_ctx, io->pipe->conn->event_ctx); 102 if (c == NULL) return NULL; 103 104 s = talloc_zero(c, struct pipe_np_smb_state); 105 if (composite_nomem(s, c)) return c; 106 c->private_data = s; 107 108 s->io = *io; 109 conn = &s->conn; 110 111 /* prepare smb connection parameters: we're connecting to IPC$ share on 112 remote rpc server */ 113 conn->in.dest_host = s->io.binding->host; 114 conn->in.dest_ports = lp_smb_ports(lp_ctx); 115 if (s->io.binding->target_hostname == NULL) 116 conn->in.called_name = "*SMBSERVER"; /* FIXME: This is invalid */ 117 else 118 conn->in.called_name = s->io.binding->target_hostname; 119 conn->in.socket_options = lp_socket_options(lp_ctx); 120 conn->in.service = "IPC$"; 121 conn->in.service_type = NULL; 122 conn->in.workgroup = lp_workgroup(lp_ctx); 123 conn->in.gensec_settings = lp_gensec_settings(conn, lp_ctx); 124 conn->in.iconv_convenience = lp_iconv_convenience(lp_ctx); 125 126 lp_smbcli_options(lp_ctx, &conn->in.options); 127 lp_smbcli_session_options(lp_ctx, &conn->in.session_options); 128 129 /* 130 * provide proper credentials - user supplied, but allow a 131 * fallback to anonymous if this is an schannel connection 132 * (might be NT4 not allowing machine logins at session 133 * setup) or if asked to do so by the caller (perhaps a SAMR password change?) 134 */ 135 s->conn.in.credentials = s->io.creds; 136 if (s->io.binding->flags & (DCERPC_SCHANNEL|DCERPC_ANON_FALLBACK)) { 137 conn->in.fallback_to_anonymous = true; 138 } else { 139 conn->in.fallback_to_anonymous = false; 140 } 141 142 /* send smb connect request */ 143 conn_req = smb_composite_connect_send(conn, s->io.pipe->conn, 144 s->io.resolve_ctx, 145 s->io.pipe->conn->event_ctx); 146 if (composite_nomem(conn_req, c)) return c; 147 148 composite_continue(c, conn_req, continue_smb_connect, c); 149 return c; 150} 151 152 153/* 154 Receive result of a rpc connection to a rpc pipe on SMB 155*/ 156static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv(struct composite_context *c) 157{ 158 NTSTATUS status = composite_wait(c); 159 160 talloc_free(c); 161 return status; 162} 163 164 165struct pipe_np_smb2_state { 166 struct smb2_tree *tree; 167 struct dcerpc_pipe_connect io; 168}; 169 170 171/* 172 Stage 3 of ncacn_np_smb: Named pipe opened (or not) 173*/ 174static void continue_pipe_open_smb2(struct composite_context *ctx) 175{ 176 struct composite_context *c = talloc_get_type(ctx->async.private_data, 177 struct composite_context); 178 179 /* receive result of named pipe open request on smb2 */ 180 c->status = dcerpc_pipe_open_smb2_recv(ctx); 181 if (!composite_is_ok(c)) return; 182 183 composite_done(c); 184} 185 186 187/* 188 Stage 2 of ncacn_np_smb2: Open a named pipe after successful smb2 connection 189*/ 190static void continue_smb2_connect(struct composite_context *ctx) 191{ 192 struct composite_context *open_req; 193 struct composite_context *c = talloc_get_type(ctx->async.private_data, 194 struct composite_context); 195 struct pipe_np_smb2_state *s = talloc_get_type(c->private_data, 196 struct pipe_np_smb2_state); 197 198 /* receive result of smb2 connect request */ 199 c->status = smb2_connect_recv(ctx, c, &s->tree); 200 if (!composite_is_ok(c)) return; 201 202 /* prepare named pipe open parameters */ 203 s->io.pipe_name = s->io.binding->endpoint; 204 205 /* send named pipe open request */ 206 open_req = dcerpc_pipe_open_smb2_send(s->io.pipe, s->tree, s->io.pipe_name); 207 if (composite_nomem(open_req, c)) return; 208 209 composite_continue(c, open_req, continue_pipe_open_smb2, c); 210} 211 212 213/* 214 Initiate async open of a rpc connection request on SMB2 using 215 the binding structure to determine the endpoint and options 216*/ 217static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send( 218 TALLOC_CTX *mem_ctx, 219 struct dcerpc_pipe_connect *io, 220 struct loadparm_context *lp_ctx) 221{ 222 struct composite_context *c; 223 struct pipe_np_smb2_state *s; 224 struct composite_context *conn_req; 225 struct smbcli_options options; 226 227 /* composite context allocation and setup */ 228 c = composite_create(mem_ctx, io->pipe->conn->event_ctx); 229 if (c == NULL) return NULL; 230 231 s = talloc_zero(c, struct pipe_np_smb2_state); 232 if (composite_nomem(s, c)) return c; 233 c->private_data = s; 234 235 s->io = *io; 236 237 /* 238 * provide proper credentials - user supplied or anonymous in case this is 239 * schannel connection 240 */ 241 if (s->io.binding->flags & DCERPC_SCHANNEL) { 242 s->io.creds = cli_credentials_init(mem_ctx); 243 if (composite_nomem(s->io.creds, c)) return c; 244 245 cli_credentials_guess(s->io.creds, lp_ctx); 246 } 247 248 lp_smbcli_options(lp_ctx, &options); 249 250 /* send smb2 connect request */ 251 conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, 252 lp_parm_string_list(mem_ctx, lp_ctx, NULL, "smb2", "ports", NULL), 253 "IPC$", 254 s->io.resolve_ctx, 255 s->io.creds, 256 c->event_ctx, 257 &options, 258 lp_socket_options(lp_ctx), 259 lp_gensec_settings(mem_ctx, lp_ctx) 260 ); 261 composite_continue(c, conn_req, continue_smb2_connect, c); 262 return c; 263} 264 265 266/* 267 Receive result of a rpc connection to a rpc pipe on SMB2 268*/ 269static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv(struct composite_context *c) 270{ 271 NTSTATUS status = composite_wait(c); 272 273 talloc_free(c); 274 return status; 275} 276 277 278struct pipe_ip_tcp_state { 279 struct dcerpc_pipe_connect io; 280 const char *host; 281 const char *target_hostname; 282 uint32_t port; 283}; 284 285 286/* 287 Stage 2 of ncacn_ip_tcp: rpc pipe opened (or not) 288*/ 289static void continue_pipe_open_ncacn_ip_tcp(struct composite_context *ctx) 290{ 291 struct composite_context *c = talloc_get_type(ctx->async.private_data, 292 struct composite_context); 293 294 /* receive result of named pipe open request on tcp/ip */ 295 c->status = dcerpc_pipe_open_tcp_recv(ctx); 296 if (!composite_is_ok(c)) return; 297 298 composite_done(c); 299} 300 301 302/* 303 Initiate async open of a rpc connection to a rpc pipe on TCP/IP using 304 the binding structure to determine the endpoint and options 305*/ 306static struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_ctx, 307 struct dcerpc_pipe_connect *io) 308{ 309 struct composite_context *c; 310 struct pipe_ip_tcp_state *s; 311 struct composite_context *pipe_req; 312 313 /* composite context allocation and setup */ 314 c = composite_create(mem_ctx, io->pipe->conn->event_ctx); 315 if (c == NULL) return NULL; 316 317 s = talloc_zero(c, struct pipe_ip_tcp_state); 318 if (composite_nomem(s, c)) return c; 319 c->private_data = s; 320 321 /* store input parameters in state structure */ 322 s->io = *io; 323 s->host = talloc_reference(c, io->binding->host); 324 s->target_hostname = talloc_reference(c, io->binding->target_hostname); 325 /* port number is a binding endpoint here */ 326 s->port = atoi(io->binding->endpoint); 327 328 /* send pipe open request on tcp/ip */ 329 pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->target_hostname, 330 s->port, io->resolve_ctx); 331 composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c); 332 return c; 333} 334 335 336/* 337 Receive result of a rpc connection to a rpc pipe on TCP/IP 338*/ 339static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv(struct composite_context *c) 340{ 341 NTSTATUS status = composite_wait(c); 342 343 talloc_free(c); 344 return status; 345} 346 347 348struct pipe_unix_state { 349 struct dcerpc_pipe_connect io; 350 const char *path; 351}; 352 353 354/* 355 Stage 2 of ncacn_unix: rpc pipe opened (or not) 356*/ 357static void continue_pipe_open_ncacn_unix_stream(struct composite_context *ctx) 358{ 359 struct composite_context *c = talloc_get_type(ctx->async.private_data, 360 struct composite_context); 361 362 /* receive result of pipe open request on unix socket */ 363 c->status = dcerpc_pipe_open_unix_stream_recv(ctx); 364 if (!composite_is_ok(c)) return; 365 366 composite_done(c); 367} 368 369 370/* 371 Initiate async open of a rpc connection to a rpc pipe on unix socket using 372 the binding structure to determine the endpoint and options 373*/ 374static struct composite_context* dcerpc_pipe_connect_ncacn_unix_stream_send(TALLOC_CTX *mem_ctx, 375 struct dcerpc_pipe_connect *io) 376{ 377 struct composite_context *c; 378 struct pipe_unix_state *s; 379 struct composite_context *pipe_req; 380 381 /* composite context allocation and setup */ 382 c = composite_create(mem_ctx, io->pipe->conn->event_ctx); 383 if (c == NULL) return NULL; 384 385 s = talloc_zero(c, struct pipe_unix_state); 386 if (composite_nomem(s, c)) return c; 387 c->private_data = s; 388 389 /* prepare pipe open parameters and store them in state structure 390 also, verify whether biding endpoint is not null */ 391 s->io = *io; 392 393 if (!io->binding->endpoint) { 394 DEBUG(0, ("Path to unix socket not specified\n")); 395 composite_error(c, NT_STATUS_INVALID_PARAMETER); 396 return c; 397 } 398 399 s->path = talloc_strdup(c, io->binding->endpoint); /* path is a binding endpoint here */ 400 if (composite_nomem(s->path, c)) return c; 401 402 /* send pipe open request on unix socket */ 403 pipe_req = dcerpc_pipe_open_unix_stream_send(s->io.pipe->conn, s->path); 404 composite_continue(c, pipe_req, continue_pipe_open_ncacn_unix_stream, c); 405 return c; 406} 407 408 409/* 410 Receive result of a rpc connection to a pipe on unix socket 411*/ 412static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv(struct composite_context *c) 413{ 414 NTSTATUS status = composite_wait(c); 415 416 talloc_free(c); 417 return status; 418} 419 420 421struct pipe_ncalrpc_state { 422 struct dcerpc_pipe_connect io; 423}; 424 425static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c); 426 427/* 428 Stage 2 of ncalrpc: rpc pipe opened (or not) 429*/ 430static void continue_pipe_open_ncalrpc(struct composite_context *ctx) 431{ 432 struct composite_context *c = talloc_get_type(ctx->async.private_data, 433 struct composite_context); 434 435 /* receive result of pipe open request on ncalrpc */ 436 c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx); 437 if (!composite_is_ok(c)) return; 438 439 composite_done(c); 440} 441 442 443/* 444 Initiate async open of a rpc connection request on NCALRPC using 445 the binding structure to determine the endpoint and options 446*/ 447static struct composite_context* dcerpc_pipe_connect_ncalrpc_send(TALLOC_CTX *mem_ctx, 448 struct dcerpc_pipe_connect *io, struct loadparm_context *lp_ctx) 449{ 450 struct composite_context *c; 451 struct pipe_ncalrpc_state *s; 452 struct composite_context *pipe_req; 453 454 /* composite context allocation and setup */ 455 c = composite_create(mem_ctx, io->pipe->conn->event_ctx); 456 if (c == NULL) return NULL; 457 458 s = talloc_zero(c, struct pipe_ncalrpc_state); 459 if (composite_nomem(s, c)) return c; 460 c->private_data = s; 461 462 /* store input parameters in state structure */ 463 s->io = *io; 464 465 /* send pipe open request */ 466 pipe_req = dcerpc_pipe_open_pipe_send(s->io.pipe->conn, lp_ncalrpc_dir(lp_ctx), 467 s->io.binding->endpoint); 468 composite_continue(c, pipe_req, continue_pipe_open_ncalrpc, c); 469 return c; 470} 471 472 473/* 474 Receive result of a rpc connection to a rpc pipe on NCALRPC 475*/ 476static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv(struct composite_context *c) 477{ 478 NTSTATUS status = composite_wait(c); 479 480 talloc_free(c); 481 return status; 482} 483 484 485struct pipe_connect_state { 486 struct dcerpc_pipe *pipe; 487 struct dcerpc_binding *binding; 488 const struct ndr_interface_table *table; 489 struct cli_credentials *credentials; 490 struct loadparm_context *lp_ctx; 491}; 492 493 494static void continue_map_binding(struct composite_context *ctx); 495static void continue_connect(struct composite_context *c, struct pipe_connect_state *s); 496static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx); 497static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx); 498static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx); 499static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx); 500static void continue_pipe_connect_ncalrpc(struct composite_context *ctx); 501static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s); 502static void continue_pipe_auth(struct composite_context *ctx); 503 504 505/* 506 Stage 2 of pipe_connect_b: Receive result of endpoint mapping 507*/ 508static void continue_map_binding(struct composite_context *ctx) 509{ 510 struct composite_context *c = talloc_get_type(ctx->async.private_data, 511 struct composite_context); 512 struct pipe_connect_state *s = talloc_get_type(c->private_data, 513 struct pipe_connect_state); 514 515 c->status = dcerpc_epm_map_binding_recv(ctx); 516 if (!composite_is_ok(c)) return; 517 518 DEBUG(2,("Mapped to DCERPC endpoint %s\n", s->binding->endpoint)); 519 520 continue_connect(c, s); 521} 522 523 524/* 525 Stage 2 of pipe_connect_b: Continue connection after endpoint is known 526*/ 527static void continue_connect(struct composite_context *c, struct pipe_connect_state *s) 528{ 529 struct dcerpc_pipe_connect pc; 530 531 /* potential exits to another stage by sending an async request */ 532 struct composite_context *ncacn_np_smb2_req; 533 struct composite_context *ncacn_np_smb_req; 534 struct composite_context *ncacn_ip_tcp_req; 535 struct composite_context *ncacn_unix_req; 536 struct composite_context *ncalrpc_req; 537 538 /* dcerpc pipe connect input parameters */ 539 pc.pipe = s->pipe; 540 pc.binding = s->binding; 541 pc.interface = s->table; 542 pc.creds = s->credentials; 543 pc.resolve_ctx = lp_resolve_context(s->lp_ctx); 544 545 /* connect dcerpc pipe depending on required transport */ 546 switch (s->binding->transport) { 547 case NCACN_NP: 548 if (pc.binding->flags & DCERPC_SMB2) { 549 /* new varient of SMB a.k.a. SMB2 */ 550 ncacn_np_smb2_req = dcerpc_pipe_connect_ncacn_np_smb2_send(c, &pc, s->lp_ctx); 551 composite_continue(c, ncacn_np_smb2_req, continue_pipe_connect_ncacn_np_smb2, c); 552 return; 553 554 } else { 555 /* good old ordinary SMB */ 556 ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send(c, &pc, s->lp_ctx); 557 composite_continue(c, ncacn_np_smb_req, continue_pipe_connect_ncacn_np_smb, c); 558 return; 559 } 560 break; 561 562 case NCACN_IP_TCP: 563 ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send(c, &pc); 564 composite_continue(c, ncacn_ip_tcp_req, continue_pipe_connect_ncacn_ip_tcp, c); 565 return; 566 567 case NCACN_UNIX_STREAM: 568 ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send(c, &pc); 569 composite_continue(c, ncacn_unix_req, continue_pipe_connect_ncacn_unix, c); 570 return; 571 572 case NCALRPC: 573 ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send(c, &pc, s->lp_ctx); 574 composite_continue(c, ncalrpc_req, continue_pipe_connect_ncalrpc, c); 575 return; 576 577 default: 578 /* looks like a transport we don't support now */ 579 composite_error(c, NT_STATUS_NOT_SUPPORTED); 580 } 581} 582 583 584/* 585 Stage 3 of pipe_connect_b: Receive result of pipe connect request on 586 named pipe on smb2 587*/ 588static void continue_pipe_connect_ncacn_np_smb2(struct composite_context *ctx) 589{ 590 struct composite_context *c = talloc_get_type(ctx->async.private_data, 591 struct composite_context); 592 struct pipe_connect_state *s = talloc_get_type(c->private_data, 593 struct pipe_connect_state); 594 595 c->status = dcerpc_pipe_connect_ncacn_np_smb2_recv(ctx); 596 if (!composite_is_ok(c)) return; 597 598 continue_pipe_connect(c, s); 599} 600 601 602/* 603 Stage 3 of pipe_connect_b: Receive result of pipe connect request on 604 named pipe on smb 605*/ 606static void continue_pipe_connect_ncacn_np_smb(struct composite_context *ctx) 607{ 608 struct composite_context *c = talloc_get_type(ctx->async.private_data, 609 struct composite_context); 610 struct pipe_connect_state *s = talloc_get_type(c->private_data, 611 struct pipe_connect_state); 612 613 c->status = dcerpc_pipe_connect_ncacn_np_smb_recv(ctx); 614 if (!composite_is_ok(c)) return; 615 616 continue_pipe_connect(c, s); 617} 618 619 620/* 621 Stage 3 of pipe_connect_b: Receive result of pipe connect request on tcp/ip 622*/ 623static void continue_pipe_connect_ncacn_ip_tcp(struct composite_context *ctx) 624{ 625 struct composite_context *c = talloc_get_type(ctx->async.private_data, 626 struct composite_context); 627 struct pipe_connect_state *s = talloc_get_type(c->private_data, 628 struct pipe_connect_state); 629 630 c->status = dcerpc_pipe_connect_ncacn_ip_tcp_recv(ctx); 631 if (!composite_is_ok(c)) return; 632 633 continue_pipe_connect(c, s); 634} 635 636 637/* 638 Stage 3 of pipe_connect_b: Receive result of pipe connect request on unix socket 639*/ 640static void continue_pipe_connect_ncacn_unix(struct composite_context *ctx) 641{ 642 struct composite_context *c = talloc_get_type(ctx->async.private_data, 643 struct composite_context); 644 struct pipe_connect_state *s = talloc_get_type(c->private_data, 645 struct pipe_connect_state); 646 647 c->status = dcerpc_pipe_connect_ncacn_unix_stream_recv(ctx); 648 if (!composite_is_ok(c)) return; 649 650 continue_pipe_connect(c, s); 651} 652 653 654/* 655 Stage 3 of pipe_connect_b: Receive result of pipe connect request on local rpc 656*/ 657static void continue_pipe_connect_ncalrpc(struct composite_context *ctx) 658{ 659 struct composite_context *c = talloc_get_type(ctx->async.private_data, 660 struct composite_context); 661 struct pipe_connect_state *s = talloc_get_type(c->private_data, 662 struct pipe_connect_state); 663 664 c->status = dcerpc_pipe_connect_ncalrpc_recv(ctx); 665 if (!composite_is_ok(c)) return; 666 667 continue_pipe_connect(c, s); 668} 669 670 671/* 672 Stage 4 of pipe_connect_b: Start an authentication on connected dcerpc pipe 673 depending on credentials and binding flags passed. 674*/ 675static void continue_pipe_connect(struct composite_context *c, struct pipe_connect_state *s) 676{ 677 struct composite_context *auth_bind_req; 678 679 s->pipe->binding = s->binding; 680 if (!talloc_reference(s->pipe, s->binding)) { 681 composite_error(c, NT_STATUS_NO_MEMORY); 682 return; 683 } 684 685 auth_bind_req = dcerpc_pipe_auth_send(s->pipe, s->binding, s->table, 686 s->credentials, s->lp_ctx); 687 composite_continue(c, auth_bind_req, continue_pipe_auth, c); 688} 689 690 691/* 692 Stage 5 of pipe_connect_b: Receive result of pipe authentication request 693 and say if all went ok 694*/ 695static void continue_pipe_auth(struct composite_context *ctx) 696{ 697 struct composite_context *c = talloc_get_type(ctx->async.private_data, 698 struct composite_context); 699 struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state); 700 701 c->status = dcerpc_pipe_auth_recv(ctx, s, &s->pipe); 702 if (!composite_is_ok(c)) return; 703 704 composite_done(c); 705} 706 707 708/* 709 handle timeouts of a dcerpc connect 710*/ 711static void dcerpc_connect_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, 712 struct timeval t, void *private_data) 713{ 714 struct composite_context *c = talloc_get_type(private_data, struct composite_context); 715 composite_error(c, NT_STATUS_IO_TIMEOUT); 716} 717 718/* 719 start a request to open a rpc connection to a rpc pipe, using 720 specified binding structure to determine the endpoint and options 721*/ 722_PUBLIC_ struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent_ctx, 723 struct dcerpc_binding *binding, 724 const struct ndr_interface_table *table, 725 struct cli_credentials *credentials, 726 struct tevent_context *ev, 727 struct loadparm_context *lp_ctx) 728{ 729 struct composite_context *c; 730 struct pipe_connect_state *s; 731 struct tevent_context *new_ev = NULL; 732 733 /* composite context allocation and setup */ 734 c = composite_create(parent_ctx, ev); 735 if (c == NULL) { 736 talloc_free(new_ev); 737 return NULL; 738 } 739 talloc_steal(c, new_ev); 740 741 s = talloc_zero(c, struct pipe_connect_state); 742 if (composite_nomem(s, c)) return c; 743 c->private_data = s; 744 745 /* initialise dcerpc pipe structure */ 746 s->pipe = dcerpc_pipe_init(c, ev, lp_iconv_convenience(lp_ctx)); 747 if (composite_nomem(s->pipe, c)) return c; 748 749 if (DEBUGLEVEL >= 10) 750 s->pipe->conn->packet_log_dir = lp_lockdir(lp_ctx); 751 752 /* store parameters in state structure */ 753 s->binding = binding; 754 s->table = table; 755 s->credentials = credentials; 756 s->lp_ctx = lp_ctx; 757 758 event_add_timed(c->event_ctx, c, 759 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0), 760 dcerpc_connect_timeout_handler, c); 761 762 switch (s->binding->transport) { 763 case NCA_UNKNOWN: { 764 struct composite_context *binding_req; 765 binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table, 766 s->pipe->conn->event_ctx, 767 s->lp_ctx); 768 composite_continue(c, binding_req, continue_map_binding, c); 769 return c; 770 } 771 772 case NCACN_NP: 773 case NCACN_IP_TCP: 774 case NCALRPC: 775 if (!s->binding->endpoint) { 776 struct composite_context *binding_req; 777 binding_req = dcerpc_epm_map_binding_send(c, s->binding, s->table, 778 s->pipe->conn->event_ctx, 779 s->lp_ctx); 780 composite_continue(c, binding_req, continue_map_binding, c); 781 return c; 782 } 783 784 default: 785 break; 786 } 787 788 continue_connect(c, s); 789 return c; 790} 791 792 793/* 794 receive result of a request to open a rpc connection to a rpc pipe 795*/ 796_PUBLIC_ NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, 797 struct dcerpc_pipe **p) 798{ 799 NTSTATUS status; 800 struct pipe_connect_state *s; 801 802 status = composite_wait(c); 803 804 if (NT_STATUS_IS_OK(status)) { 805 s = talloc_get_type(c->private_data, struct pipe_connect_state); 806 talloc_steal(mem_ctx, s->pipe); 807 *p = s->pipe; 808 } 809 talloc_free(c); 810 return status; 811} 812 813 814/* 815 open a rpc connection to a rpc pipe, using the specified 816 binding structure to determine the endpoint and options - sync version 817*/ 818_PUBLIC_ NTSTATUS dcerpc_pipe_connect_b(TALLOC_CTX *parent_ctx, 819 struct dcerpc_pipe **pp, 820 struct dcerpc_binding *binding, 821 const struct ndr_interface_table *table, 822 struct cli_credentials *credentials, 823 struct tevent_context *ev, 824 struct loadparm_context *lp_ctx) 825{ 826 struct composite_context *c; 827 828 c = dcerpc_pipe_connect_b_send(parent_ctx, binding, table, 829 credentials, ev, lp_ctx); 830 return dcerpc_pipe_connect_b_recv(c, parent_ctx, pp); 831} 832 833 834struct pipe_conn_state { 835 struct dcerpc_pipe *pipe; 836}; 837 838 839static void continue_pipe_connect_b(struct composite_context *ctx); 840 841 842/* 843 Initiate rpc connection to a rpc pipe, using the specified string 844 binding to determine the endpoint and options. 845 The string is to be parsed to a binding structure first. 846*/ 847_PUBLIC_ struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx, 848 const char *binding, 849 const struct ndr_interface_table *table, 850 struct cli_credentials *credentials, 851 struct tevent_context *ev, struct loadparm_context *lp_ctx) 852{ 853 struct composite_context *c; 854 struct pipe_conn_state *s; 855 struct dcerpc_binding *b; 856 struct composite_context *pipe_conn_req; 857 858 /* composite context allocation and setup */ 859 c = composite_create(parent_ctx, ev); 860 if (c == NULL) { 861 return NULL; 862 } 863 864 s = talloc_zero(c, struct pipe_conn_state); 865 if (composite_nomem(s, c)) return c; 866 c->private_data = s; 867 868 /* parse binding string to the structure */ 869 c->status = dcerpc_parse_binding(c, binding, &b); 870 if (!NT_STATUS_IS_OK(c->status)) { 871 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding)); 872 composite_error(c, c->status); 873 return c; 874 } 875 876 DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(c, b))); 877 878 /* 879 start connecting to a rpc pipe after binding structure 880 is established 881 */ 882 pipe_conn_req = dcerpc_pipe_connect_b_send(c, b, table, 883 credentials, ev, lp_ctx); 884 composite_continue(c, pipe_conn_req, continue_pipe_connect_b, c); 885 return c; 886} 887 888 889/* 890 Stage 2 of pipe_connect: Receive result of actual pipe connect request 891 and say if we're done ok 892*/ 893static void continue_pipe_connect_b(struct composite_context *ctx) 894{ 895 struct composite_context *c = talloc_get_type(ctx->async.private_data, 896 struct composite_context); 897 struct pipe_conn_state *s = talloc_get_type(c->private_data, 898 struct pipe_conn_state); 899 900 c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->pipe); 901 talloc_steal(s, s->pipe); 902 if (!composite_is_ok(c)) return; 903 904 composite_done(c); 905} 906 907 908/* 909 Receive result of pipe connect (using binding string) request 910 and return connected pipe structure. 911*/ 912NTSTATUS dcerpc_pipe_connect_recv(struct composite_context *c, 913 TALLOC_CTX *mem_ctx, 914 struct dcerpc_pipe **pp) 915{ 916 NTSTATUS status; 917 struct pipe_conn_state *s; 918 919 status = composite_wait(c); 920 if (NT_STATUS_IS_OK(status)) { 921 s = talloc_get_type(c->private_data, struct pipe_conn_state); 922 *pp = talloc_steal(mem_ctx, s->pipe); 923 } 924 talloc_free(c); 925 return status; 926} 927 928 929/* 930 Open a rpc connection to a rpc pipe, using the specified string 931 binding to determine the endpoint and options - sync version 932*/ 933_PUBLIC_ NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx, 934 struct dcerpc_pipe **pp, 935 const char *binding, 936 const struct ndr_interface_table *table, 937 struct cli_credentials *credentials, 938 struct tevent_context *ev, 939 struct loadparm_context *lp_ctx) 940{ 941 struct composite_context *c; 942 c = dcerpc_pipe_connect_send(parent_ctx, binding, 943 table, credentials, ev, lp_ctx); 944 return dcerpc_pipe_connect_recv(c, parent_ctx, pp); 945} 946 947