1/* 2 Unix SMB/CIFS implementation. 3 4 Copyright (C) Stefan Metzmacher 2004 5 Copyright (C) Rafal Szczesniak 2005 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19*/ 20 21#include "includes.h" 22#include "libnet/libnet.h" 23#include "libcli/libcli.h" 24#include "libcli/composite/composite.h" 25#include "librpc/rpc/dcerpc.h" 26#include "librpc/rpc/dcerpc_proto.h" 27#include "librpc/gen_ndr/ndr_lsa_c.h" 28#include "librpc/gen_ndr/ndr_samr.h" 29 30 31struct rpc_connect_srv_state { 32 struct libnet_context *ctx; 33 struct libnet_RpcConnect r; 34 const char *binding; 35 36 /* information about the progress */ 37 void (*monitor_fn)(struct monitor_msg*); 38}; 39 40 41static void continue_pipe_connect(struct composite_context *ctx); 42 43 44/** 45 * Initiates connection to rpc pipe on remote server 46 * 47 * @param ctx initialised libnet context 48 * @param mem_ctx memory context of this call 49 * @param r data structure containing necessary parameters and return values 50 * @return composite context of this call 51 **/ 52 53static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context *ctx, 54 TALLOC_CTX *mem_ctx, 55 struct libnet_RpcConnect *r, 56 void (*monitor)(struct monitor_msg*)) 57{ 58 struct composite_context *c; 59 struct rpc_connect_srv_state *s; 60 struct dcerpc_binding *b; 61 struct composite_context *pipe_connect_req; 62 63 /* composite context allocation and setup */ 64 c = composite_create(ctx, ctx->event_ctx); 65 if (c == NULL) return c; 66 67 s = talloc_zero(c, struct rpc_connect_srv_state); 68 if (composite_nomem(s, c)) return c; 69 70 c->private_data = s; 71 s->monitor_fn = monitor; 72 73 s->ctx = ctx; 74 s->r = *r; 75 ZERO_STRUCT(s->r.out); 76 77 /* prepare binding string */ 78 switch (r->level) { 79 case LIBNET_RPC_CONNECT_SERVER: 80 s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.name); 81 break; 82 case LIBNET_RPC_CONNECT_SERVER_ADDRESS: 83 s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.address); 84 break; 85 86 case LIBNET_RPC_CONNECT_BINDING: 87 s->binding = talloc_strdup(s, r->in.binding); 88 break; 89 90 case LIBNET_RPC_CONNECT_DC: 91 case LIBNET_RPC_CONNECT_PDC: 92 /* this should never happen - DC and PDC level has a separate 93 composite function */ 94 case LIBNET_RPC_CONNECT_DC_INFO: 95 /* this should never happen - DC_INFO level has a separate 96 composite function */ 97 composite_error(c, NT_STATUS_INVALID_LEVEL); 98 return c; 99 } 100 101 /* parse binding string to the structure */ 102 c->status = dcerpc_parse_binding(c, s->binding, &b); 103 if (!NT_STATUS_IS_OK(c->status)) { 104 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", s->binding)); 105 composite_error(c, c->status); 106 return c; 107 } 108 109 switch (r->level) { 110 case LIBNET_RPC_CONNECT_SERVER: 111 case LIBNET_RPC_CONNECT_SERVER_ADDRESS: 112 b->flags = r->in.dcerpc_flags; 113 } 114 115 if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) { 116 b->target_hostname = talloc_strdup(b, r->in.name); 117 if (composite_nomem(b->target_hostname, c)) { 118 return c; 119 } 120 } 121 122 /* connect to remote dcerpc pipe */ 123 pipe_connect_req = dcerpc_pipe_connect_b_send(c, b, r->in.dcerpc_iface, 124 ctx->cred, c->event_ctx, 125 ctx->lp_ctx); 126 if (composite_nomem(pipe_connect_req, c)) return c; 127 128 composite_continue(c, pipe_connect_req, continue_pipe_connect, c); 129 return c; 130} 131 132 133/* 134 Step 2 of RpcConnectSrv - get rpc connection 135*/ 136static void continue_pipe_connect(struct composite_context *ctx) 137{ 138 struct composite_context *c; 139 struct rpc_connect_srv_state *s; 140 141 c = talloc_get_type(ctx->async.private_data, struct composite_context); 142 s = talloc_get_type(c->private_data, struct rpc_connect_srv_state); 143 144 /* receive result of rpc pipe connection */ 145 c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->r.out.dcerpc_pipe); 146 147 /* post monitor message */ 148 if (s->monitor_fn) { 149 struct monitor_msg msg; 150 struct msg_net_rpc_connect data; 151 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding; 152 153 /* prepare monitor message and post it */ 154 data.host = binding->host; 155 data.endpoint = binding->endpoint; 156 data.transport = binding->transport; 157 data.domain_name = binding->target_hostname; 158 159 msg.type = mon_NetRpcConnect; 160 msg.data = (void*)&data; 161 msg.data_size = sizeof(data); 162 s->monitor_fn(&msg); 163 } 164 165 composite_done(c); 166} 167 168 169/** 170 * Receives result of connection to rpc pipe on remote server 171 * 172 * @param c composite context 173 * @param ctx initialised libnet context 174 * @param mem_ctx memory context of this call 175 * @param r data structure containing necessary parameters and return values 176 * @return nt status of rpc connection 177 **/ 178 179static NTSTATUS libnet_RpcConnectSrv_recv(struct composite_context *c, 180 struct libnet_context *ctx, 181 TALLOC_CTX *mem_ctx, 182 struct libnet_RpcConnect *r) 183{ 184 NTSTATUS status; 185 struct rpc_connect_srv_state *s = talloc_get_type(c->private_data, 186 struct rpc_connect_srv_state); 187 188 status = composite_wait(c); 189 if (NT_STATUS_IS_OK(status)) { 190 /* move the returned rpc pipe between memory contexts */ 191 s = talloc_get_type(c->private_data, struct rpc_connect_srv_state); 192 r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe); 193 194 /* reference created pipe structure to long-term libnet_context 195 so that it can be used by other api functions even after short-term 196 mem_ctx is freed */ 197 if (r->in.dcerpc_iface == &ndr_table_samr) { 198 ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe); 199 200 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) { 201 ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe); 202 } 203 204 r->out.error_string = talloc_strdup(mem_ctx, "Success"); 205 206 } else { 207 r->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status)); 208 } 209 210 talloc_free(c); 211 return status; 212} 213 214 215struct rpc_connect_dc_state { 216 struct libnet_context *ctx; 217 struct libnet_RpcConnect r; 218 struct libnet_RpcConnect r2; 219 struct libnet_LookupDCs f; 220 const char *connect_name; 221 222 /* information about the progress */ 223 void (*monitor_fn)(struct monitor_msg *); 224}; 225 226 227static void continue_lookup_dc(struct composite_context *ctx); 228static void continue_rpc_connect(struct composite_context *ctx); 229 230 231/** 232 * Initiates connection to rpc pipe on domain pdc 233 * 234 * @param ctx initialised libnet context 235 * @param mem_ctx memory context of this call 236 * @param r data structure containing necessary parameters and return values 237 * @return composite context of this call 238 **/ 239 240static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context *ctx, 241 TALLOC_CTX *mem_ctx, 242 struct libnet_RpcConnect *r, 243 void (*monitor)(struct monitor_msg *msg)) 244{ 245 struct composite_context *c; 246 struct rpc_connect_dc_state *s; 247 struct composite_context *lookup_dc_req; 248 249 /* composite context allocation and setup */ 250 c = composite_create(ctx, ctx->event_ctx); 251 if (c == NULL) return c; 252 253 s = talloc_zero(c, struct rpc_connect_dc_state); 254 if (composite_nomem(s, c)) return c; 255 256 c->private_data = s; 257 s->monitor_fn = monitor; 258 259 s->ctx = ctx; 260 s->r = *r; 261 ZERO_STRUCT(s->r.out); 262 263 switch (r->level) { 264 case LIBNET_RPC_CONNECT_PDC: 265 s->f.in.name_type = NBT_NAME_PDC; 266 break; 267 268 case LIBNET_RPC_CONNECT_DC: 269 s->f.in.name_type = NBT_NAME_LOGON; 270 break; 271 272 default: 273 break; 274 } 275 276 s->f.in.domain_name = r->in.name; 277 s->f.out.num_dcs = 0; 278 s->f.out.dcs = NULL; 279 280 /* find the domain pdc first */ 281 lookup_dc_req = libnet_LookupDCs_send(ctx, c, &s->f); 282 if (composite_nomem(lookup_dc_req, c)) return c; 283 284 composite_continue(c, lookup_dc_req, continue_lookup_dc, c); 285 return c; 286} 287 288 289/* 290 Step 2 of RpcConnectDC: get domain controller name and 291 initiate RpcConnect to it 292*/ 293static void continue_lookup_dc(struct composite_context *ctx) 294{ 295 struct composite_context *c; 296 struct rpc_connect_dc_state *s; 297 struct composite_context *rpc_connect_req; 298 struct monitor_msg msg; 299 struct msg_net_lookup_dc data; 300 301 c = talloc_get_type(ctx->async.private_data, struct composite_context); 302 s = talloc_get_type(c->private_data, struct rpc_connect_dc_state); 303 304 /* receive result of domain controller lookup */ 305 c->status = libnet_LookupDCs_recv(ctx, c, &s->f); 306 if (!composite_is_ok(c)) return; 307 308 /* decide on preferred address type depending on DC type */ 309 s->connect_name = s->f.out.dcs[0].name; 310 311 /* post monitor message */ 312 if (s->monitor_fn) { 313 /* prepare a monitor message and post it */ 314 data.domain_name = s->f.in.domain_name; 315 data.hostname = s->f.out.dcs[0].name; 316 data.address = s->f.out.dcs[0].address; 317 318 msg.type = mon_NetLookupDc; 319 msg.data = &data; 320 msg.data_size = sizeof(data); 321 s->monitor_fn(&msg); 322 } 323 324 /* ok, pdc has been found so do attempt to rpc connect */ 325 s->r2.level = LIBNET_RPC_CONNECT_SERVER_ADDRESS; 326 327 /* this will cause yet another name resolution, but at least 328 * we pass the right name down the stack now */ 329 s->r2.in.name = talloc_strdup(s, s->connect_name); 330 s->r2.in.address = talloc_steal(s, s->f.out.dcs[0].address); 331 s->r2.in.dcerpc_iface = s->r.in.dcerpc_iface; 332 s->r2.in.dcerpc_flags = s->r.in.dcerpc_flags; 333 334 /* send rpc connect request to the server */ 335 rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2, s->monitor_fn); 336 if (composite_nomem(rpc_connect_req, c)) return; 337 338 composite_continue(c, rpc_connect_req, continue_rpc_connect, c); 339} 340 341 342/* 343 Step 3 of RpcConnectDC: get rpc connection to the server 344*/ 345static void continue_rpc_connect(struct composite_context *ctx) 346{ 347 struct composite_context *c; 348 struct rpc_connect_dc_state *s; 349 350 c = talloc_get_type(ctx->async.private_data, struct composite_context); 351 s = talloc_get_type(c->private_data, struct rpc_connect_dc_state); 352 353 c->status = libnet_RpcConnectSrv_recv(ctx, s->ctx, c, &s->r2); 354 355 /* error string is to be passed anyway */ 356 s->r.out.error_string = s->r2.out.error_string; 357 if (!composite_is_ok(c)) return; 358 359 s->r.out.dcerpc_pipe = s->r2.out.dcerpc_pipe; 360 361 /* post monitor message */ 362 if (s->monitor_fn) { 363 struct monitor_msg msg; 364 struct msg_net_rpc_connect data; 365 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding; 366 367 data.host = binding->host; 368 data.endpoint = binding->endpoint; 369 data.transport = binding->transport; 370 data.domain_name = binding->target_hostname; 371 372 msg.type = mon_NetRpcConnect; 373 msg.data = (void*)&data; 374 msg.data_size = sizeof(data); 375 s->monitor_fn(&msg); 376 } 377 378 composite_done(c); 379} 380 381 382/** 383 * Receives result of connection to rpc pipe on domain pdc 384 * 385 * @param c composite context 386 * @param ctx initialised libnet context 387 * @param mem_ctx memory context of this call 388 * @param r data structure containing necessary parameters and return values 389 * @return nt status of rpc connection 390 **/ 391 392static NTSTATUS libnet_RpcConnectDC_recv(struct composite_context *c, 393 struct libnet_context *ctx, 394 TALLOC_CTX *mem_ctx, 395 struct libnet_RpcConnect *r) 396{ 397 NTSTATUS status; 398 struct rpc_connect_dc_state *s = talloc_get_type(c->private_data, 399 struct rpc_connect_dc_state); 400 401 status = composite_wait(c); 402 if (NT_STATUS_IS_OK(status)) { 403 /* move connected rpc pipe between memory contexts 404 405 The use of talloc_reparent(talloc_parent(), ...) is 406 bizarre, but it is needed because of the absolutely 407 atrocious use of talloc in this code. We need to 408 force the original parent to change, but finding 409 the original parent is well nigh impossible at this 410 point in the code (yes, I tried). 411 */ 412 r->out.dcerpc_pipe = talloc_reparent(talloc_parent(s->r.out.dcerpc_pipe), 413 mem_ctx, s->r.out.dcerpc_pipe); 414 415 /* reference created pipe structure to long-term libnet_context 416 so that it can be used by other api functions even after short-term 417 mem_ctx is freed */ 418 if (r->in.dcerpc_iface == &ndr_table_samr) { 419 ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe); 420 421 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) { 422 ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe); 423 } 424 425 } else { 426 r->out.error_string = talloc_asprintf(mem_ctx, 427 "Failed to rpc connect: %s", 428 nt_errstr(status)); 429 } 430 431 talloc_free(c); 432 return status; 433} 434 435 436 437struct rpc_connect_dci_state { 438 struct libnet_context *ctx; 439 struct libnet_RpcConnect r; 440 struct libnet_RpcConnect rpc_conn; 441 struct policy_handle lsa_handle; 442 struct lsa_QosInfo qos; 443 struct lsa_ObjectAttribute attr; 444 struct lsa_OpenPolicy2 lsa_open_policy; 445 struct dcerpc_pipe *lsa_pipe; 446 struct lsa_QueryInfoPolicy2 lsa_query_info2; 447 struct lsa_QueryInfoPolicy lsa_query_info; 448 struct dcerpc_binding *final_binding; 449 struct dcerpc_pipe *final_pipe; 450 451 /* information about the progress */ 452 void (*monitor_fn)(struct monitor_msg*); 453}; 454 455 456static void continue_dci_rpc_connect(struct composite_context *ctx); 457static void continue_lsa_policy(struct rpc_request *req); 458static void continue_lsa_query_info(struct rpc_request *req); 459static void continue_lsa_query_info2(struct rpc_request *req); 460static void continue_epm_map_binding(struct composite_context *ctx); 461static void continue_secondary_conn(struct composite_context *ctx); 462static void continue_epm_map_binding_send(struct composite_context *c); 463 464 465/** 466 * Initiates connection to rpc pipe on remote server or pdc. Received result 467 * contains info on the domain name, domain sid and realm. 468 * 469 * @param ctx initialised libnet context 470 * @param mem_ctx memory context of this call 471 * @param r data structure containing necessary parameters and return values. Must be a talloc context 472 * @return composite context of this call 473 **/ 474 475static struct composite_context* libnet_RpcConnectDCInfo_send(struct libnet_context *ctx, 476 TALLOC_CTX *mem_ctx, 477 struct libnet_RpcConnect *r, 478 void (*monitor)(struct monitor_msg*)) 479{ 480 struct composite_context *c, *conn_req; 481 struct rpc_connect_dci_state *s; 482 483 /* composite context allocation and setup */ 484 c = composite_create(ctx, ctx->event_ctx); 485 if (c == NULL) return c; 486 487 s = talloc_zero(c, struct rpc_connect_dci_state); 488 if (composite_nomem(s, c)) return c; 489 490 c->private_data = s; 491 s->monitor_fn = monitor; 492 493 s->ctx = ctx; 494 s->r = *r; 495 ZERO_STRUCT(s->r.out); 496 497 498 /* proceed to pure rpc connection if the binding string is provided, 499 otherwise try to connect domain controller */ 500 if (r->in.binding == NULL) { 501 /* Pass on any binding flags (such as anonymous fallback) that have been set */ 502 s->rpc_conn.in.dcerpc_flags = r->in.dcerpc_flags; 503 504 s->rpc_conn.in.name = r->in.name; 505 s->rpc_conn.level = LIBNET_RPC_CONNECT_DC; 506 } else { 507 s->rpc_conn.in.binding = r->in.binding; 508 s->rpc_conn.level = LIBNET_RPC_CONNECT_BINDING; 509 } 510 511 /* we need to query information on lsarpc interface first */ 512 s->rpc_conn.in.dcerpc_iface = &ndr_table_lsarpc; 513 514 /* request connection to the lsa pipe on the pdc */ 515 conn_req = libnet_RpcConnect_send(ctx, c, &s->rpc_conn, s->monitor_fn); 516 if (composite_nomem(c, conn_req)) return c; 517 518 composite_continue(c, conn_req, continue_dci_rpc_connect, c); 519 return c; 520} 521 522 523/* 524 Step 2 of RpcConnectDCInfo: receive opened rpc pipe and open 525 lsa policy handle 526*/ 527static void continue_dci_rpc_connect(struct composite_context *ctx) 528{ 529 struct composite_context *c; 530 struct rpc_connect_dci_state *s; 531 struct rpc_request *open_pol_req; 532 533 c = talloc_get_type(ctx->async.private_data, struct composite_context); 534 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state); 535 536 c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->rpc_conn); 537 if (!NT_STATUS_IS_OK(c->status)) { 538 composite_error(c, c->status); 539 return; 540 } 541 542 /* post monitor message */ 543 if (s->monitor_fn) { 544 struct monitor_msg msg; 545 struct msg_net_rpc_connect data; 546 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding; 547 548 data.host = binding->host; 549 data.endpoint = binding->endpoint; 550 data.transport = binding->transport; 551 data.domain_name = binding->target_hostname; 552 553 msg.type = mon_NetRpcConnect; 554 msg.data = (void*)&data; 555 msg.data_size = sizeof(data); 556 s->monitor_fn(&msg); 557 } 558 559 /* prepare to open a policy handle on lsa pipe */ 560 s->lsa_pipe = s->ctx->lsa.pipe; 561 562 s->qos.len = 0; 563 s->qos.impersonation_level = 2; 564 s->qos.context_mode = 1; 565 s->qos.effective_only = 0; 566 567 s->attr.sec_qos = &s->qos; 568 569 s->lsa_open_policy.in.attr = &s->attr; 570 s->lsa_open_policy.in.system_name = talloc_asprintf(c, "\\"); 571 if (composite_nomem(s->lsa_open_policy.in.system_name, c)) return; 572 573 s->lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; 574 s->lsa_open_policy.out.handle = &s->lsa_handle; 575 576 open_pol_req = dcerpc_lsa_OpenPolicy2_send(s->lsa_pipe, c, &s->lsa_open_policy); 577 if (composite_nomem(open_pol_req, c)) return; 578 579 composite_continue_rpc(c, open_pol_req, continue_lsa_policy, c); 580} 581 582 583/* 584 Step 3 of RpcConnectDCInfo: Get policy handle and query lsa info 585 for kerberos realm (dns name) and guid. The query may fail. 586*/ 587static void continue_lsa_policy(struct rpc_request *req) 588{ 589 struct composite_context *c; 590 struct rpc_connect_dci_state *s; 591 struct rpc_request *query_info_req; 592 593 c = talloc_get_type(req->async.private_data, struct composite_context); 594 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state); 595 596 c->status = dcerpc_ndr_request_recv(req); 597 if (!NT_STATUS_IS_OK(c->status)) { 598 composite_error(c, c->status); 599 return; 600 } 601 602 if (NT_STATUS_EQUAL(s->lsa_open_policy.out.result, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) { 603 s->r.out.realm = NULL; 604 s->r.out.guid = NULL; 605 s->r.out.domain_name = NULL; 606 s->r.out.domain_sid = NULL; 607 608 /* Skip to the creating the actual connection, no info available on this transport */ 609 continue_epm_map_binding_send(c); 610 return; 611 612 } else if (!NT_STATUS_IS_OK(s->lsa_open_policy.out.result)) { 613 composite_error(c, s->lsa_open_policy.out.result); 614 return; 615 } 616 617 /* post monitor message */ 618 if (s->monitor_fn) { 619 struct monitor_msg msg; 620 621 msg.type = mon_LsaOpenPolicy; 622 msg.data = NULL; 623 msg.data_size = 0; 624 s->monitor_fn(&msg); 625 } 626 627 /* query lsa info for dns domain name and guid */ 628 s->lsa_query_info2.in.handle = &s->lsa_handle; 629 s->lsa_query_info2.in.level = LSA_POLICY_INFO_DNS; 630 s->lsa_query_info2.out.info = talloc_zero(c, union lsa_PolicyInformation *); 631 if (composite_nomem(s->lsa_query_info2.out.info, c)) return; 632 633 query_info_req = dcerpc_lsa_QueryInfoPolicy2_send(s->lsa_pipe, c, &s->lsa_query_info2); 634 if (composite_nomem(query_info_req, c)) return; 635 636 composite_continue_rpc(c, query_info_req, continue_lsa_query_info2, c); 637} 638 639 640/* 641 Step 4 of RpcConnectDCInfo: Get realm and guid if provided (rpc call 642 may result in failure) and query lsa info for domain name and sid. 643*/ 644static void continue_lsa_query_info2(struct rpc_request *req) 645{ 646 struct composite_context *c; 647 struct rpc_connect_dci_state *s; 648 struct rpc_request *query_info_req; 649 650 c = talloc_get_type(req->async.private_data, struct composite_context); 651 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state); 652 653 c->status = dcerpc_ndr_request_recv(req); 654 655 /* In case of error just null the realm and guid and proceed 656 to the next step. After all, it doesn't have to be AD domain 657 controller we talking to - NT-style PDC also counts */ 658 659 if (NT_STATUS_EQUAL(c->status, NT_STATUS_NET_WRITE_FAULT)) { 660 s->r.out.realm = NULL; 661 s->r.out.guid = NULL; 662 663 } else { 664 if (!NT_STATUS_IS_OK(c->status)) { 665 s->r.out.error_string = talloc_asprintf(c, 666 "lsa_QueryInfoPolicy2 failed: %s", 667 nt_errstr(c->status)); 668 composite_error(c, c->status); 669 return; 670 } 671 672 if (!NT_STATUS_IS_OK(s->lsa_query_info2.out.result)) { 673 s->r.out.error_string = talloc_asprintf(c, 674 "lsa_QueryInfoPolicy2 failed: %s", 675 nt_errstr(s->lsa_query_info2.out.result)); 676 composite_error(c, s->lsa_query_info2.out.result); 677 return; 678 } 679 680 /* Copy the dns domain name and guid from the query result */ 681 682 /* this should actually be a conversion from lsa_StringLarge */ 683 s->r.out.realm = (*s->lsa_query_info2.out.info)->dns.dns_domain.string; 684 s->r.out.guid = talloc(c, struct GUID); 685 if (composite_nomem(s->r.out.guid, c)) { 686 s->r.out.error_string = NULL; 687 return; 688 } 689 *s->r.out.guid = (*s->lsa_query_info2.out.info)->dns.domain_guid; 690 } 691 692 /* post monitor message */ 693 if (s->monitor_fn) { 694 struct monitor_msg msg; 695 696 msg.type = mon_LsaQueryPolicy; 697 msg.data = NULL; 698 msg.data_size = 0; 699 s->monitor_fn(&msg); 700 } 701 702 /* query lsa info for domain name and sid */ 703 s->lsa_query_info.in.handle = &s->lsa_handle; 704 s->lsa_query_info.in.level = LSA_POLICY_INFO_DOMAIN; 705 s->lsa_query_info.out.info = talloc_zero(c, union lsa_PolicyInformation *); 706 if (composite_nomem(s->lsa_query_info.out.info, c)) return; 707 708 query_info_req = dcerpc_lsa_QueryInfoPolicy_send(s->lsa_pipe, c, &s->lsa_query_info); 709 if (composite_nomem(query_info_req, c)) return; 710 711 composite_continue_rpc(c, query_info_req, continue_lsa_query_info, c); 712} 713 714 715/* 716 Step 5 of RpcConnectDCInfo: Get domain name and sid 717*/ 718static void continue_lsa_query_info(struct rpc_request *req) 719{ 720 struct composite_context *c; 721 struct rpc_connect_dci_state *s; 722 723 c = talloc_get_type(req->async.private_data, struct composite_context); 724 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state); 725 726 c->status = dcerpc_ndr_request_recv(req); 727 if (!NT_STATUS_IS_OK(c->status)) { 728 s->r.out.error_string = talloc_asprintf(c, 729 "lsa_QueryInfoPolicy failed: %s", 730 nt_errstr(c->status)); 731 composite_error(c, c->status); 732 return; 733 } 734 735 /* post monitor message */ 736 if (s->monitor_fn) { 737 struct monitor_msg msg; 738 739 msg.type = mon_LsaQueryPolicy; 740 msg.data = NULL; 741 msg.data_size = 0; 742 s->monitor_fn(&msg); 743 } 744 745 /* Copy the domain name and sid from the query result */ 746 s->r.out.domain_sid = (*s->lsa_query_info.out.info)->domain.sid; 747 s->r.out.domain_name = (*s->lsa_query_info.out.info)->domain.name.string; 748 749 continue_epm_map_binding_send(c); 750} 751 752/* 753 Step 5 (continued) of RpcConnectDCInfo: request endpoint 754 map binding. 755 756 We may short-cut to this step if we don't support LSA OpenPolicy on this transport 757*/ 758static void continue_epm_map_binding_send(struct composite_context *c) 759{ 760 struct rpc_connect_dci_state *s; 761 struct composite_context *epm_map_req; 762 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state); 763 764 /* prepare to get endpoint mapping for the requested interface */ 765 s->final_binding = talloc(s, struct dcerpc_binding); 766 if (composite_nomem(s->final_binding, c)) return; 767 768 *s->final_binding = *s->lsa_pipe->binding; 769 /* Ensure we keep hold of the member elements */ 770 if (composite_nomem(talloc_reference(s->final_binding, s->lsa_pipe->binding), c)) return; 771 772 epm_map_req = dcerpc_epm_map_binding_send(c, s->final_binding, s->r.in.dcerpc_iface, 773 s->lsa_pipe->conn->event_ctx, s->ctx->lp_ctx); 774 if (composite_nomem(epm_map_req, c)) return; 775 776 composite_continue(c, epm_map_req, continue_epm_map_binding, c); 777} 778 779/* 780 Step 6 of RpcConnectDCInfo: Receive endpoint mapping and create secondary 781 rpc connection derived from already used pipe but connected to the requested 782 one (as specified in libnet_RpcConnect structure) 783*/ 784static void continue_epm_map_binding(struct composite_context *ctx) 785{ 786 struct composite_context *c, *sec_conn_req; 787 struct rpc_connect_dci_state *s; 788 789 c = talloc_get_type(ctx->async.private_data, struct composite_context); 790 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state); 791 792 c->status = dcerpc_epm_map_binding_recv(ctx); 793 if (!NT_STATUS_IS_OK(c->status)) { 794 s->r.out.error_string = talloc_asprintf(c, 795 "failed to map pipe with endpoint mapper - %s", 796 nt_errstr(c->status)); 797 composite_error(c, c->status); 798 return; 799 } 800 801 /* create secondary connection derived from lsa pipe */ 802 sec_conn_req = dcerpc_secondary_connection_send(s->lsa_pipe, s->final_binding); 803 if (composite_nomem(sec_conn_req, c)) return; 804 805 composite_continue(c, sec_conn_req, continue_secondary_conn, c); 806} 807 808 809/* 810 Step 7 of RpcConnectDCInfo: Get actual pipe to be returned 811 and complete this composite call 812*/ 813static void continue_secondary_conn(struct composite_context *ctx) 814{ 815 struct composite_context *c; 816 struct rpc_connect_dci_state *s; 817 818 c = talloc_get_type(ctx->async.private_data, struct composite_context); 819 s = talloc_get_type(c->private_data, struct rpc_connect_dci_state); 820 821 c->status = dcerpc_secondary_connection_recv(ctx, &s->final_pipe); 822 if (!NT_STATUS_IS_OK(c->status)) { 823 s->r.out.error_string = talloc_asprintf(c, 824 "secondary connection failed: %s", 825 nt_errstr(c->status)); 826 827 composite_error(c, c->status); 828 return; 829 } 830 831 s->r.out.dcerpc_pipe = s->final_pipe; 832 833 /* post monitor message */ 834 if (s->monitor_fn) { 835 struct monitor_msg msg; 836 struct msg_net_rpc_connect data; 837 struct dcerpc_binding *binding = s->r.out.dcerpc_pipe->binding; 838 839 /* prepare monitor message and post it */ 840 data.host = binding->host; 841 data.endpoint = binding->endpoint; 842 data.transport = binding->transport; 843 data.domain_name = binding->target_hostname; 844 845 msg.type = mon_NetRpcConnect; 846 msg.data = (void*)&data; 847 msg.data_size = sizeof(data); 848 s->monitor_fn(&msg); 849 } 850 851 composite_done(c); 852} 853 854 855/** 856 * Receives result of connection to rpc pipe and gets basic 857 * domain info (name, sid, realm, guid) 858 * 859 * @param c composite context 860 * @param ctx initialised libnet context 861 * @param mem_ctx memory context of this call 862 * @param r data structure containing return values 863 * @return nt status of rpc connection 864 **/ 865 866static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct libnet_context *ctx, 867 TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r) 868{ 869 NTSTATUS status; 870 struct rpc_connect_dci_state *s = talloc_get_type(c->private_data, 871 struct rpc_connect_dci_state); 872 873 status = composite_wait(c); 874 if (NT_STATUS_IS_OK(status)) { 875 r->out.realm = talloc_steal(mem_ctx, s->r.out.realm); 876 r->out.guid = talloc_steal(mem_ctx, s->r.out.guid); 877 r->out.domain_name = talloc_steal(mem_ctx, s->r.out.domain_name); 878 r->out.domain_sid = talloc_steal(mem_ctx, s->r.out.domain_sid); 879 880 r->out.dcerpc_pipe = talloc_steal(mem_ctx, s->r.out.dcerpc_pipe); 881 882 /* reference created pipe structure to long-term libnet_context 883 so that it can be used by other api functions even after short-term 884 mem_ctx is freed */ 885 if (r->in.dcerpc_iface == &ndr_table_samr) { 886 ctx->samr.pipe = talloc_reference(ctx, r->out.dcerpc_pipe); 887 888 } else if (r->in.dcerpc_iface == &ndr_table_lsarpc) { 889 ctx->lsa.pipe = talloc_reference(ctx, r->out.dcerpc_pipe); 890 } 891 892 } else { 893 if (s->r.out.error_string) { 894 r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string); 895 } else if (r->in.binding == NULL) { 896 r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC failed: %s", nt_errstr(status)); 897 } else { 898 r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC %s failed: %s", 899 r->in.binding, nt_errstr(status)); 900 } 901 } 902 903 talloc_free(c); 904 return status; 905} 906 907 908/** 909 * Initiates connection to rpc pipe on remote server or pdc, optionally 910 * providing domain info 911 * 912 * @param ctx initialised libnet context 913 * @param mem_ctx memory context of this call 914 * @param r data structure containing necessary parameters and return values 915 * @return composite context of this call 916 **/ 917 918struct composite_context* libnet_RpcConnect_send(struct libnet_context *ctx, 919 TALLOC_CTX *mem_ctx, 920 struct libnet_RpcConnect *r, 921 void (*monitor)(struct monitor_msg*)) 922{ 923 struct composite_context *c; 924 925 switch (r->level) { 926 case LIBNET_RPC_CONNECT_SERVER: 927 case LIBNET_RPC_CONNECT_SERVER_ADDRESS: 928 case LIBNET_RPC_CONNECT_BINDING: 929 c = libnet_RpcConnectSrv_send(ctx, mem_ctx, r, monitor); 930 break; 931 932 case LIBNET_RPC_CONNECT_PDC: 933 case LIBNET_RPC_CONNECT_DC: 934 c = libnet_RpcConnectDC_send(ctx, mem_ctx, r, monitor); 935 break; 936 937 case LIBNET_RPC_CONNECT_DC_INFO: 938 c = libnet_RpcConnectDCInfo_send(ctx, mem_ctx, r, monitor); 939 break; 940 941 default: 942 c = talloc_zero(mem_ctx, struct composite_context); 943 composite_error(c, NT_STATUS_INVALID_LEVEL); 944 } 945 946 return c; 947} 948 949 950/** 951 * Receives result of connection to rpc pipe on remote server or pdc 952 * 953 * @param c composite context 954 * @param ctx initialised libnet context 955 * @param mem_ctx memory context of this call 956 * @param r data structure containing necessary parameters and return values 957 * @return nt status of rpc connection 958 **/ 959 960NTSTATUS libnet_RpcConnect_recv(struct composite_context *c, struct libnet_context *ctx, 961 TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r) 962{ 963 switch (r->level) { 964 case LIBNET_RPC_CONNECT_SERVER: 965 case LIBNET_RPC_CONNECT_BINDING: 966 return libnet_RpcConnectSrv_recv(c, ctx, mem_ctx, r); 967 968 case LIBNET_RPC_CONNECT_PDC: 969 case LIBNET_RPC_CONNECT_DC: 970 return libnet_RpcConnectDC_recv(c, ctx, mem_ctx, r); 971 972 case LIBNET_RPC_CONNECT_DC_INFO: 973 return libnet_RpcConnectDCInfo_recv(c, ctx, mem_ctx, r); 974 975 default: 976 ZERO_STRUCT(r->out); 977 return NT_STATUS_INVALID_LEVEL; 978 } 979} 980 981 982/** 983 * Connect to a rpc pipe on a remote server - sync version 984 * 985 * @param ctx initialised libnet context 986 * @param mem_ctx memory context of this call 987 * @param r data structure containing necessary parameters and return values 988 * @return nt status of rpc connection 989 **/ 990 991NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, 992 struct libnet_RpcConnect *r) 993{ 994 struct composite_context *c; 995 996 c = libnet_RpcConnect_send(ctx, mem_ctx, r, NULL); 997 return libnet_RpcConnect_recv(c, ctx, mem_ctx, r); 998} 999