1/* 2 Unix SMB/CIFS implementation. 3 raw dcerpc operations 4 5 Copyright (C) Tim Potter 2003 6 Copyright (C) Andrew Tridgell 2003-2005 7 Copyright (C) Jelmer Vernooij 2004-2005 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21*/ 22 23#include "includes.h" 24#include "../lib/util/dlinklist.h" 25#include "lib/events/events.h" 26#include "librpc/rpc/dcerpc.h" 27#include "librpc/rpc/dcerpc_proto.h" 28#include "librpc/gen_ndr/ndr_misc.h" 29#include "librpc/gen_ndr/ndr_dcerpc.h" 30#include "libcli/composite/composite.h" 31#include "auth/gensec/gensec.h" 32#include "param/param.h" 33 34_PUBLIC_ NTSTATUS dcerpc_init(struct loadparm_context *lp_ctx) 35{ 36 return gensec_init(lp_ctx); 37} 38 39static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS status); 40static void dcerpc_ship_next_request(struct dcerpc_connection *c); 41 42/* destroy a dcerpc connection */ 43static int dcerpc_connection_destructor(struct dcerpc_connection *conn) 44{ 45 if (conn->dead) { 46 conn->free_skipped = true; 47 return -1; 48 } 49 dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT); 50 return 0; 51} 52 53 54/* initialise a dcerpc connection. 55 the event context is optional 56*/ 57static struct dcerpc_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx, 58 struct tevent_context *ev, 59 struct smb_iconv_convenience *ic) 60{ 61 struct dcerpc_connection *c; 62 63 c = talloc_zero(mem_ctx, struct dcerpc_connection); 64 if (!c) { 65 return NULL; 66 } 67 68 c->iconv_convenience = talloc_reference(c, ic); 69 70 c->event_ctx = ev; 71 72 if (c->event_ctx == NULL) { 73 talloc_free(c); 74 return NULL; 75 } 76 77 c->call_id = 1; 78 c->security_state.auth_info = NULL; 79 c->security_state.session_key = dcerpc_generic_session_key; 80 c->security_state.generic_state = NULL; 81 c->binding_string = NULL; 82 c->flags = 0; 83 c->srv_max_xmit_frag = 0; 84 c->srv_max_recv_frag = 0; 85 c->pending = NULL; 86 87 talloc_set_destructor(c, dcerpc_connection_destructor); 88 89 return c; 90} 91 92/* initialise a dcerpc pipe. */ 93_PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, 94 struct smb_iconv_convenience *ic) 95{ 96 struct dcerpc_pipe *p; 97 98 p = talloc(mem_ctx, struct dcerpc_pipe); 99 if (!p) { 100 return NULL; 101 } 102 103 p->conn = dcerpc_connection_init(p, ev, ic); 104 if (p->conn == NULL) { 105 talloc_free(p); 106 return NULL; 107 } 108 109 p->last_fault_code = 0; 110 p->context_id = 0; 111 p->request_timeout = DCERPC_REQUEST_TIMEOUT; 112 p->binding = NULL; 113 114 ZERO_STRUCT(p->syntax); 115 ZERO_STRUCT(p->transfer_syntax); 116 117 if (DEBUGLVL(100)) { 118 p->conn->flags |= DCERPC_DEBUG_PRINT_BOTH; 119 } 120 121 return p; 122} 123 124 125/* 126 choose the next call id to use 127*/ 128static uint32_t next_call_id(struct dcerpc_connection *c) 129{ 130 c->call_id++; 131 if (c->call_id == 0) { 132 c->call_id++; 133 } 134 return c->call_id; 135} 136 137/* we need to be able to get/set the fragment length without doing a full 138 decode */ 139void dcerpc_set_frag_length(DATA_BLOB *blob, uint16_t v) 140{ 141 if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) { 142 SSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v); 143 } else { 144 RSSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v); 145 } 146} 147 148uint16_t dcerpc_get_frag_length(const DATA_BLOB *blob) 149{ 150 if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) { 151 return SVAL(blob->data, DCERPC_FRAG_LEN_OFFSET); 152 } else { 153 return RSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET); 154 } 155} 156 157void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v) 158{ 159 if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) { 160 SSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, v); 161 } else { 162 RSSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, v); 163 } 164} 165 166 167/** 168 setup for a ndr pull, also setting up any flags from the binding string 169*/ 170static struct ndr_pull *ndr_pull_init_flags(struct dcerpc_connection *c, 171 DATA_BLOB *blob, TALLOC_CTX *mem_ctx) 172{ 173 struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx, c->iconv_convenience); 174 175 if (ndr == NULL) return ndr; 176 177 if (c->flags & DCERPC_DEBUG_PAD_CHECK) { 178 ndr->flags |= LIBNDR_FLAG_PAD_CHECK; 179 } 180 181 if (c->flags & DCERPC_NDR_REF_ALLOC) { 182 ndr->flags |= LIBNDR_FLAG_REF_ALLOC; 183 } 184 185 if (c->flags & DCERPC_NDR64) { 186 ndr->flags |= LIBNDR_FLAG_NDR64; 187 } 188 189 return ndr; 190} 191 192/* 193 parse a data blob into a ncacn_packet structure. This handles both 194 input and output packets 195*/ 196static NTSTATUS ncacn_pull(struct dcerpc_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 197 struct ncacn_packet *pkt) 198{ 199 struct ndr_pull *ndr; 200 enum ndr_err_code ndr_err; 201 202 ndr = ndr_pull_init_flags(c, blob, mem_ctx); 203 if (!ndr) { 204 return NT_STATUS_NO_MEMORY; 205 } 206 207 if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { 208 ndr->flags |= LIBNDR_FLAG_BIGENDIAN; 209 } 210 211 ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); 212 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 213 return ndr_map_error2ntstatus(ndr_err); 214 } 215 216 return NT_STATUS_OK; 217} 218 219/* 220 parse the authentication information on a dcerpc response packet 221*/ 222static NTSTATUS ncacn_pull_request_auth(struct dcerpc_connection *c, TALLOC_CTX *mem_ctx, 223 DATA_BLOB *raw_packet, 224 struct ncacn_packet *pkt) 225{ 226 struct ndr_pull *ndr; 227 NTSTATUS status; 228 struct dcerpc_auth auth; 229 DATA_BLOB auth_blob; 230 enum ndr_err_code ndr_err; 231 232 if (!c->security_state.auth_info || 233 !c->security_state.generic_state) { 234 return NT_STATUS_OK; 235 } 236 237 switch (c->security_state.auth_info->auth_level) { 238 case DCERPC_AUTH_LEVEL_PRIVACY: 239 case DCERPC_AUTH_LEVEL_INTEGRITY: 240 break; 241 242 case DCERPC_AUTH_LEVEL_CONNECT: 243 if (pkt->auth_length != 0) { 244 break; 245 } 246 return NT_STATUS_OK; 247 case DCERPC_AUTH_LEVEL_NONE: 248 if (pkt->auth_length != 0) { 249 return NT_STATUS_INVALID_NETWORK_RESPONSE; 250 } 251 return NT_STATUS_OK; 252 253 default: 254 return NT_STATUS_INVALID_LEVEL; 255 } 256 257 auth_blob.length = 8 + pkt->auth_length; 258 259 /* check for a valid length */ 260 if (pkt->u.response.stub_and_verifier.length < auth_blob.length) { 261 return NT_STATUS_INFO_LENGTH_MISMATCH; 262 } 263 264 auth_blob.data = 265 pkt->u.response.stub_and_verifier.data + 266 pkt->u.response.stub_and_verifier.length - auth_blob.length; 267 pkt->u.response.stub_and_verifier.length -= auth_blob.length; 268 269 /* pull the auth structure */ 270 ndr = ndr_pull_init_flags(c, &auth_blob, mem_ctx); 271 if (!ndr) { 272 return NT_STATUS_NO_MEMORY; 273 } 274 275 if (!(pkt->drep[0] & DCERPC_DREP_LE)) { 276 ndr->flags |= LIBNDR_FLAG_BIGENDIAN; 277 } 278 279 ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth); 280 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 281 return ndr_map_error2ntstatus(ndr_err); 282 } 283 status = NT_STATUS_OK; 284 285 /* check signature or unseal the packet */ 286 switch (c->security_state.auth_info->auth_level) { 287 case DCERPC_AUTH_LEVEL_PRIVACY: 288 status = gensec_unseal_packet(c->security_state.generic_state, 289 mem_ctx, 290 raw_packet->data + DCERPC_REQUEST_LENGTH, 291 pkt->u.response.stub_and_verifier.length, 292 raw_packet->data, 293 raw_packet->length - auth.credentials.length, 294 &auth.credentials); 295 memcpy(pkt->u.response.stub_and_verifier.data, 296 raw_packet->data + DCERPC_REQUEST_LENGTH, 297 pkt->u.response.stub_and_verifier.length); 298 break; 299 300 case DCERPC_AUTH_LEVEL_INTEGRITY: 301 status = gensec_check_packet(c->security_state.generic_state, 302 mem_ctx, 303 pkt->u.response.stub_and_verifier.data, 304 pkt->u.response.stub_and_verifier.length, 305 raw_packet->data, 306 raw_packet->length - auth.credentials.length, 307 &auth.credentials); 308 break; 309 310 case DCERPC_AUTH_LEVEL_CONNECT: 311 /* for now we ignore possible signatures here */ 312 status = NT_STATUS_OK; 313 break; 314 315 default: 316 status = NT_STATUS_INVALID_LEVEL; 317 break; 318 } 319 320 /* remove the indicated amount of paddiing */ 321 if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) { 322 return NT_STATUS_INFO_LENGTH_MISMATCH; 323 } 324 pkt->u.response.stub_and_verifier.length -= auth.auth_pad_length; 325 326 return status; 327} 328 329 330/* 331 push a dcerpc request packet into a blob, possibly signing it. 332*/ 333static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c, 334 DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 335 size_t sig_size, 336 struct ncacn_packet *pkt) 337{ 338 NTSTATUS status; 339 struct ndr_push *ndr; 340 DATA_BLOB creds2; 341 size_t payload_length; 342 enum ndr_err_code ndr_err; 343 size_t hdr_size = DCERPC_REQUEST_LENGTH; 344 345 /* non-signed packets are simpler */ 346 if (sig_size == 0) { 347 return ncacn_push_auth(blob, mem_ctx, c->iconv_convenience, pkt, NULL); 348 } 349 350 switch (c->security_state.auth_info->auth_level) { 351 case DCERPC_AUTH_LEVEL_PRIVACY: 352 case DCERPC_AUTH_LEVEL_INTEGRITY: 353 break; 354 355 case DCERPC_AUTH_LEVEL_CONNECT: 356 /* TODO: let the gensec mech decide if it wants to generate a signature */ 357 return ncacn_push_auth(blob, mem_ctx, c->iconv_convenience, pkt, NULL); 358 359 case DCERPC_AUTH_LEVEL_NONE: 360 return ncacn_push_auth(blob, mem_ctx, c->iconv_convenience, pkt, NULL); 361 362 default: 363 return NT_STATUS_INVALID_LEVEL; 364 } 365 366 ndr = ndr_push_init_ctx(mem_ctx, c->iconv_convenience); 367 if (!ndr) { 368 return NT_STATUS_NO_MEMORY; 369 } 370 371 if (c->flags & DCERPC_PUSH_BIGENDIAN) { 372 ndr->flags |= LIBNDR_FLAG_BIGENDIAN; 373 } 374 375 if (c->flags & DCERPC_NDR64) { 376 ndr->flags |= LIBNDR_FLAG_NDR64; 377 } 378 379 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) { 380 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT; 381 hdr_size += 16; 382 } 383 384 ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); 385 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 386 return ndr_map_error2ntstatus(ndr_err); 387 } 388 status = NT_STATUS_OK; 389 390 /* pad to 16 byte multiple in the payload portion of the 391 packet. This matches what w2k3 does */ 392 c->security_state.auth_info->auth_pad_length = 393 (16 - (pkt->u.request.stub_and_verifier.length & 15)) & 15; 394 ndr_err = ndr_push_zero(ndr, c->security_state.auth_info->auth_pad_length); 395 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 396 return ndr_map_error2ntstatus(ndr_err); 397 } 398 status = NT_STATUS_OK; 399 400 payload_length = pkt->u.request.stub_and_verifier.length + 401 c->security_state.auth_info->auth_pad_length; 402 403 /* we start without signature, it will appended later */ 404 c->security_state.auth_info->credentials = data_blob(NULL,0); 405 406 /* add the auth verifier */ 407 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, c->security_state.auth_info); 408 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 409 return ndr_map_error2ntstatus(ndr_err); 410 } 411 status = NT_STATUS_OK; 412 413 /* extract the whole packet as a blob */ 414 *blob = ndr_push_blob(ndr); 415 416 /* 417 * Setup the frag and auth length in the packet buffer. 418 * This is needed if the GENSEC mech does AEAD signing 419 * of the packet headers. The signature itself will be 420 * appended later. 421 */ 422 dcerpc_set_frag_length(blob, blob->length + sig_size); 423 dcerpc_set_auth_length(blob, sig_size); 424 425 /* sign or seal the packet */ 426 switch (c->security_state.auth_info->auth_level) { 427 case DCERPC_AUTH_LEVEL_PRIVACY: 428 status = gensec_seal_packet(c->security_state.generic_state, 429 mem_ctx, 430 blob->data + hdr_size, 431 payload_length, 432 blob->data, 433 blob->length, 434 &creds2); 435 if (!NT_STATUS_IS_OK(status)) { 436 return status; 437 } 438 break; 439 440 case DCERPC_AUTH_LEVEL_INTEGRITY: 441 status = gensec_sign_packet(c->security_state.generic_state, 442 mem_ctx, 443 blob->data + hdr_size, 444 payload_length, 445 blob->data, 446 blob->length, 447 &creds2); 448 if (!NT_STATUS_IS_OK(status)) { 449 return status; 450 } 451 break; 452 453 default: 454 status = NT_STATUS_INVALID_LEVEL; 455 break; 456 } 457 458 if (creds2.length != sig_size) { 459 DEBUG(0,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n", 460 creds2.length, (uint32_t)sig_size, 461 c->security_state.auth_info->auth_pad_length, 462 pkt->u.request.stub_and_verifier.length)); 463 return NT_STATUS_INTERNAL_ERROR; 464 } 465 466 if (!data_blob_append(mem_ctx, blob, creds2.data, creds2.length)) { 467 return NT_STATUS_NO_MEMORY; 468 } 469 470 return NT_STATUS_OK; 471} 472 473 474/* 475 fill in the fixed values in a dcerpc header 476*/ 477static void init_ncacn_hdr(struct dcerpc_connection *c, struct ncacn_packet *pkt) 478{ 479 pkt->rpc_vers = 5; 480 pkt->rpc_vers_minor = 0; 481 if (c->flags & DCERPC_PUSH_BIGENDIAN) { 482 pkt->drep[0] = 0; 483 } else { 484 pkt->drep[0] = DCERPC_DREP_LE; 485 } 486 pkt->drep[1] = 0; 487 pkt->drep[2] = 0; 488 pkt->drep[3] = 0; 489} 490 491/* 492 map a bind nak reason to a NTSTATUS 493*/ 494static NTSTATUS dcerpc_map_reason(uint16_t reason) 495{ 496 switch (reason) { 497 case DCERPC_BIND_REASON_ASYNTAX: 498 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX; 499 case DCERPC_BIND_REASON_INVALID_AUTH_TYPE: 500 return NT_STATUS_INVALID_PARAMETER; 501 } 502 return NT_STATUS_UNSUCCESSFUL; 503} 504 505/* 506 a bind or alter context has failed 507*/ 508static void dcerpc_composite_fail(struct rpc_request *req) 509{ 510 struct composite_context *c = talloc_get_type(req->async.private_data, 511 struct composite_context); 512 composite_error(c, req->status); 513} 514 515/* 516 remove requests from the pending or queued queues 517 */ 518static int dcerpc_req_dequeue(struct rpc_request *req) 519{ 520 switch (req->state) { 521 case RPC_REQUEST_QUEUED: 522 DLIST_REMOVE(req->p->conn->request_queue, req); 523 break; 524 case RPC_REQUEST_PENDING: 525 DLIST_REMOVE(req->p->conn->pending, req); 526 break; 527 case RPC_REQUEST_DONE: 528 break; 529 } 530 return 0; 531} 532 533 534/* 535 mark the dcerpc connection dead. All outstanding requests get an error 536*/ 537static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS status) 538{ 539 if (conn->dead) return; 540 541 conn->dead = true; 542 543 if (conn->transport.shutdown_pipe) { 544 conn->transport.shutdown_pipe(conn, status); 545 } 546 547 /* all pending requests get the error */ 548 while (conn->pending) { 549 struct rpc_request *req = conn->pending; 550 dcerpc_req_dequeue(req); 551 req->state = RPC_REQUEST_DONE; 552 req->status = status; 553 if (req->async.callback) { 554 req->async.callback(req); 555 } 556 } 557 558 talloc_set_destructor(conn, NULL); 559 if (conn->free_skipped) { 560 talloc_free(conn); 561 } 562} 563 564/* 565 forward declarations of the recv_data handlers for the types of 566 packets we need to handle 567*/ 568static void dcerpc_request_recv_data(struct dcerpc_connection *c, 569 DATA_BLOB *raw_packet, struct ncacn_packet *pkt); 570 571/* 572 receive a dcerpc reply from the transport. Here we work out what 573 type of reply it is (normal request, bind or alter context) and 574 dispatch to the appropriate handler 575*/ 576static void dcerpc_recv_data(struct dcerpc_connection *conn, DATA_BLOB *blob, NTSTATUS status) 577{ 578 struct ncacn_packet pkt; 579 580 if (NT_STATUS_IS_OK(status) && blob->length == 0) { 581 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; 582 } 583 584 /* the transport may be telling us of a severe error, such as 585 a dropped socket */ 586 if (!NT_STATUS_IS_OK(status)) { 587 data_blob_free(blob); 588 dcerpc_connection_dead(conn, status); 589 return; 590 } 591 592 /* parse the basic packet to work out what type of response this is */ 593 status = ncacn_pull(conn, blob, blob->data, &pkt); 594 if (!NT_STATUS_IS_OK(status)) { 595 data_blob_free(blob); 596 dcerpc_connection_dead(conn, status); 597 } 598 599 dcerpc_request_recv_data(conn, blob, &pkt); 600} 601 602 603/* 604 Receive a bind reply from the transport 605*/ 606static void dcerpc_bind_recv_handler(struct rpc_request *req, 607 DATA_BLOB *raw_packet, struct ncacn_packet *pkt) 608{ 609 struct composite_context *c; 610 struct dcerpc_connection *conn; 611 612 c = talloc_get_type(req->async.private_data, struct composite_context); 613 614 if (pkt->ptype == DCERPC_PKT_BIND_NAK) { 615 DEBUG(2,("dcerpc: bind_nak reason %d\n", 616 pkt->u.bind_nak.reject_reason)); 617 composite_error(c, dcerpc_map_reason(pkt->u.bind_nak. 618 reject_reason)); 619 return; 620 } 621 622 if ((pkt->ptype != DCERPC_PKT_BIND_ACK) || 623 (pkt->u.bind_ack.num_results == 0) || 624 (pkt->u.bind_ack.ctx_list[0].result != 0)) { 625 composite_error(c, NT_STATUS_NET_WRITE_FAULT); 626 return; 627 } 628 629 conn = req->p->conn; 630 631 conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag; 632 conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag; 633 634 if ((req->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) && 635 (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) { 636 conn->flags |= DCERPC_CONCURRENT_MULTIPLEX; 637 } 638 639 if ((req->p->binding->flags & DCERPC_HEADER_SIGNING) && 640 (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) { 641 conn->flags |= DCERPC_HEADER_SIGNING; 642 } 643 644 /* the bind_ack might contain a reply set of credentials */ 645 if (conn->security_state.auth_info && 646 pkt->u.bind_ack.auth_info.length) { 647 enum ndr_err_code ndr_err; 648 ndr_err = ndr_pull_struct_blob( 649 &pkt->u.bind_ack.auth_info, conn, 650 NULL, 651 conn->security_state.auth_info, 652 (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); 653 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 654 c->status = ndr_map_error2ntstatus(ndr_err); 655 if (!composite_is_ok(c)) return; 656 } 657 } 658 659 req->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id; 660 661 composite_done(c); 662} 663 664/* 665 handle timeouts of individual dcerpc requests 666*/ 667static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, 668 struct timeval t, void *private_data) 669{ 670 struct rpc_request *req = talloc_get_type(private_data, struct rpc_request); 671 672 if (req->ignore_timeout) { 673 dcerpc_req_dequeue(req); 674 req->state = RPC_REQUEST_DONE; 675 req->status = NT_STATUS_IO_TIMEOUT; 676 if (req->async.callback) { 677 req->async.callback(req); 678 } 679 return; 680 } 681 682 dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT); 683} 684 685/* 686 send a async dcerpc bind request 687*/ 688struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p, 689 TALLOC_CTX *mem_ctx, 690 const struct ndr_syntax_id *syntax, 691 const struct ndr_syntax_id *transfer_syntax) 692{ 693 struct composite_context *c; 694 struct ncacn_packet pkt; 695 DATA_BLOB blob; 696 struct rpc_request *req; 697 698 c = composite_create(mem_ctx,p->conn->event_ctx); 699 if (c == NULL) return NULL; 700 701 c->private_data = p; 702 703 p->syntax = *syntax; 704 p->transfer_syntax = *transfer_syntax; 705 706 init_ncacn_hdr(p->conn, &pkt); 707 708 pkt.ptype = DCERPC_PKT_BIND; 709 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; 710 pkt.call_id = p->conn->call_id; 711 pkt.auth_length = 0; 712 713 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) { 714 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; 715 } 716 717 if (p->binding->flags & DCERPC_HEADER_SIGNING) { 718 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; 719 } 720 721 pkt.u.bind.max_xmit_frag = 5840; 722 pkt.u.bind.max_recv_frag = 5840; 723 pkt.u.bind.assoc_group_id = p->binding->assoc_group_id; 724 pkt.u.bind.num_contexts = 1; 725 pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1); 726 if (composite_nomem(pkt.u.bind.ctx_list, c)) return c; 727 pkt.u.bind.ctx_list[0].context_id = p->context_id; 728 pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1; 729 pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax; 730 pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax; 731 pkt.u.bind.auth_info = data_blob(NULL, 0); 732 733 /* construct the NDR form of the packet */ 734 c->status = ncacn_push_auth(&blob, c, p->conn->iconv_convenience, &pkt, 735 p->conn->security_state.auth_info); 736 if (!composite_is_ok(c)) return c; 737 738 p->conn->transport.recv_data = dcerpc_recv_data; 739 740 /* 741 * we allocate a dcerpc_request so we can be in the same 742 * request queue as normal requests 743 */ 744 req = talloc_zero(c, struct rpc_request); 745 if (composite_nomem(req, c)) return c; 746 747 req->state = RPC_REQUEST_PENDING; 748 req->call_id = pkt.call_id; 749 req->async.private_data = c; 750 req->async.callback = dcerpc_composite_fail; 751 req->p = p; 752 req->recv_handler = dcerpc_bind_recv_handler; 753 DLIST_ADD_END(p->conn->pending, req, struct rpc_request *); 754 talloc_set_destructor(req, dcerpc_req_dequeue); 755 756 c->status = p->conn->transport.send_request(p->conn, &blob, 757 true); 758 if (!composite_is_ok(c)) return c; 759 760 event_add_timed(c->event_ctx, req, 761 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0), 762 dcerpc_timeout_handler, req); 763 764 return c; 765} 766 767/* 768 recv side of async dcerpc bind request 769*/ 770NTSTATUS dcerpc_bind_recv(struct composite_context *ctx) 771{ 772 NTSTATUS result = composite_wait(ctx); 773 talloc_free(ctx); 774 return result; 775} 776 777/* 778 perform a continued bind (and auth3) 779*/ 780NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p, 781 TALLOC_CTX *mem_ctx) 782{ 783 struct ncacn_packet pkt; 784 NTSTATUS status; 785 DATA_BLOB blob; 786 787 init_ncacn_hdr(p->conn, &pkt); 788 789 pkt.ptype = DCERPC_PKT_AUTH3; 790 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; 791 pkt.call_id = next_call_id(p->conn); 792 pkt.auth_length = 0; 793 pkt.u.auth3._pad = 0; 794 pkt.u.auth3.auth_info = data_blob(NULL, 0); 795 796 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) { 797 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; 798 } 799 800 if (p->binding->flags & DCERPC_HEADER_SIGNING) { 801 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; 802 } 803 804 /* construct the NDR form of the packet */ 805 status = ncacn_push_auth(&blob, mem_ctx, 806 p->conn->iconv_convenience, 807 &pkt, 808 p->conn->security_state.auth_info); 809 if (!NT_STATUS_IS_OK(status)) { 810 return status; 811 } 812 813 /* send it on its way */ 814 status = p->conn->transport.send_request(p->conn, &blob, false); 815 if (!NT_STATUS_IS_OK(status)) { 816 return status; 817 } 818 819 return NT_STATUS_OK; 820} 821 822 823/* 824 process a fragment received from the transport layer during a 825 request 826 827 This function frees the data 828*/ 829static void dcerpc_request_recv_data(struct dcerpc_connection *c, 830 DATA_BLOB *raw_packet, struct ncacn_packet *pkt) 831{ 832 struct rpc_request *req; 833 uint_t length; 834 NTSTATUS status = NT_STATUS_OK; 835 836 /* 837 if this is an authenticated connection then parse and check 838 the auth info. We have to do this before finding the 839 matching packet, as the request structure might have been 840 removed due to a timeout, but if it has been we still need 841 to run the auth routines so that we don't get the sign/seal 842 info out of step with the server 843 */ 844 if (c->security_state.auth_info && c->security_state.generic_state && 845 pkt->ptype == DCERPC_PKT_RESPONSE) { 846 status = ncacn_pull_request_auth(c, raw_packet->data, raw_packet, pkt); 847 } 848 849 /* find the matching request */ 850 for (req=c->pending;req;req=req->next) { 851 if (pkt->call_id == req->call_id) break; 852 } 853 854#if 0 855 /* useful for testing certain vendors RPC servers */ 856 if (req == NULL && c->pending && pkt->call_id == 0) { 857 DEBUG(0,("HACK FOR INCORRECT CALL ID\n")); 858 req = c->pending; 859 } 860#endif 861 862 if (req == NULL) { 863 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id)); 864 data_blob_free(raw_packet); 865 return; 866 } 867 868 talloc_steal(req, raw_packet->data); 869 870 if (req->recv_handler != NULL) { 871 dcerpc_req_dequeue(req); 872 req->state = RPC_REQUEST_DONE; 873 req->recv_handler(req, raw_packet, pkt); 874 return; 875 } 876 877 if (pkt->ptype == DCERPC_PKT_FAULT) { 878 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status))); 879 req->fault_code = pkt->u.fault.status; 880 req->status = NT_STATUS_NET_WRITE_FAULT; 881 goto req_done; 882 } 883 884 if (pkt->ptype != DCERPC_PKT_RESPONSE) { 885 DEBUG(2,("Unexpected packet type %d in dcerpc response\n", 886 (int)pkt->ptype)); 887 req->fault_code = DCERPC_FAULT_OTHER; 888 req->status = NT_STATUS_NET_WRITE_FAULT; 889 goto req_done; 890 } 891 892 /* now check the status from the auth routines, and if it failed then fail 893 this request accordingly */ 894 if (!NT_STATUS_IS_OK(status)) { 895 req->status = status; 896 goto req_done; 897 } 898 899 length = pkt->u.response.stub_and_verifier.length; 900 901 if (length > 0) { 902 req->payload.data = talloc_realloc(req, 903 req->payload.data, 904 uint8_t, 905 req->payload.length + length); 906 if (!req->payload.data) { 907 req->status = NT_STATUS_NO_MEMORY; 908 goto req_done; 909 } 910 memcpy(req->payload.data+req->payload.length, 911 pkt->u.response.stub_and_verifier.data, length); 912 req->payload.length += length; 913 } 914 915 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) { 916 c->transport.send_read(c); 917 return; 918 } 919 920 if (!(pkt->drep[0] & DCERPC_DREP_LE)) { 921 req->flags |= DCERPC_PULL_BIGENDIAN; 922 } else { 923 req->flags &= ~DCERPC_PULL_BIGENDIAN; 924 } 925 926 927req_done: 928 /* we've got the full payload */ 929 req->state = RPC_REQUEST_DONE; 930 DLIST_REMOVE(c->pending, req); 931 932 if (c->request_queue != NULL) { 933 /* We have to look at shipping further requests before calling 934 * the async function, that one might close the pipe */ 935 dcerpc_ship_next_request(c); 936 } 937 938 if (req->async.callback) { 939 req->async.callback(req); 940 } 941} 942 943/* 944 perform the send side of a async dcerpc request 945*/ 946static struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p, 947 const struct GUID *object, 948 uint16_t opnum, 949 bool async, 950 DATA_BLOB *stub_data) 951{ 952 struct rpc_request *req; 953 954 p->conn->transport.recv_data = dcerpc_recv_data; 955 956 req = talloc(p, struct rpc_request); 957 if (req == NULL) { 958 return NULL; 959 } 960 961 req->p = p; 962 req->call_id = next_call_id(p->conn); 963 req->status = NT_STATUS_OK; 964 req->state = RPC_REQUEST_QUEUED; 965 req->payload = data_blob(NULL, 0); 966 req->flags = 0; 967 req->fault_code = 0; 968 req->async_call = async; 969 req->ignore_timeout = false; 970 req->async.callback = NULL; 971 req->async.private_data = NULL; 972 req->recv_handler = NULL; 973 974 if (object != NULL) { 975 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object)); 976 if (req->object == NULL) { 977 talloc_free(req); 978 return NULL; 979 } 980 } else { 981 req->object = NULL; 982 } 983 984 req->opnum = opnum; 985 req->request_data.length = stub_data->length; 986 req->request_data.data = talloc_reference(req, stub_data->data); 987 if (req->request_data.length && req->request_data.data == NULL) { 988 return NULL; 989 } 990 991 DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *); 992 talloc_set_destructor(req, dcerpc_req_dequeue); 993 994 dcerpc_ship_next_request(p->conn); 995 996 if (p->request_timeout) { 997 event_add_timed(dcerpc_event_context(p), req, 998 timeval_current_ofs(p->request_timeout, 0), 999 dcerpc_timeout_handler, req); 1000 } 1001 1002 return req; 1003} 1004 1005/* 1006 Send a request using the transport 1007*/ 1008 1009static void dcerpc_ship_next_request(struct dcerpc_connection *c) 1010{ 1011 struct rpc_request *req; 1012 struct dcerpc_pipe *p; 1013 DATA_BLOB *stub_data; 1014 struct ncacn_packet pkt; 1015 DATA_BLOB blob; 1016 uint32_t remaining, chunk_size; 1017 bool first_packet = true; 1018 size_t sig_size = 0; 1019 1020 req = c->request_queue; 1021 if (req == NULL) { 1022 return; 1023 } 1024 1025 p = req->p; 1026 stub_data = &req->request_data; 1027 1028 if (!req->async_call && (c->pending != NULL)) { 1029 return; 1030 } 1031 1032 DLIST_REMOVE(c->request_queue, req); 1033 DLIST_ADD(c->pending, req); 1034 req->state = RPC_REQUEST_PENDING; 1035 1036 init_ncacn_hdr(p->conn, &pkt); 1037 1038 remaining = stub_data->length; 1039 1040 /* we can write a full max_recv_frag size, minus the dcerpc 1041 request header size */ 1042 chunk_size = p->conn->srv_max_recv_frag; 1043 chunk_size -= DCERPC_REQUEST_LENGTH; 1044 if (c->security_state.auth_info && 1045 c->security_state.generic_state) { 1046 sig_size = gensec_sig_size(c->security_state.generic_state, 1047 p->conn->srv_max_recv_frag); 1048 if (sig_size) { 1049 chunk_size -= DCERPC_AUTH_TRAILER_LENGTH; 1050 chunk_size -= sig_size; 1051 } 1052 } 1053 chunk_size -= (chunk_size % 16); 1054 1055 pkt.ptype = DCERPC_PKT_REQUEST; 1056 pkt.call_id = req->call_id; 1057 pkt.auth_length = 0; 1058 pkt.pfc_flags = 0; 1059 pkt.u.request.alloc_hint = remaining; 1060 pkt.u.request.context_id = p->context_id; 1061 pkt.u.request.opnum = req->opnum; 1062 1063 if (req->object) { 1064 pkt.u.request.object.object = *req->object; 1065 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID; 1066 chunk_size -= ndr_size_GUID(req->object,NULL,0); 1067 } 1068 1069 /* we send a series of pdus without waiting for a reply */ 1070 while (remaining > 0 || first_packet) { 1071 uint32_t chunk = MIN(chunk_size, remaining); 1072 bool last_frag = false; 1073 bool do_trans = false; 1074 1075 first_packet = false; 1076 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST); 1077 1078 if (remaining == stub_data->length) { 1079 pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST; 1080 } 1081 if (chunk == remaining) { 1082 pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST; 1083 last_frag = true; 1084 } 1085 1086 pkt.u.request.stub_and_verifier.data = stub_data->data + 1087 (stub_data->length - remaining); 1088 pkt.u.request.stub_and_verifier.length = chunk; 1089 1090 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt); 1091 if (!NT_STATUS_IS_OK(req->status)) { 1092 req->state = RPC_REQUEST_DONE; 1093 DLIST_REMOVE(p->conn->pending, req); 1094 return; 1095 } 1096 1097 if (last_frag && !req->async_call) { 1098 do_trans = true; 1099 } 1100 1101 req->status = p->conn->transport.send_request(p->conn, &blob, do_trans); 1102 if (!NT_STATUS_IS_OK(req->status)) { 1103 req->state = RPC_REQUEST_DONE; 1104 DLIST_REMOVE(p->conn->pending, req); 1105 return; 1106 } 1107 1108 if (last_frag && !do_trans) { 1109 req->status = p->conn->transport.send_read(p->conn); 1110 if (!NT_STATUS_IS_OK(req->status)) { 1111 req->state = RPC_REQUEST_DONE; 1112 DLIST_REMOVE(p->conn->pending, req); 1113 return; 1114 } 1115 } 1116 1117 remaining -= chunk; 1118 } 1119} 1120 1121/* 1122 return the event context for a dcerpc pipe 1123 used by callers who wish to operate asynchronously 1124*/ 1125_PUBLIC_ struct tevent_context *dcerpc_event_context(struct dcerpc_pipe *p) 1126{ 1127 return p->conn->event_ctx; 1128} 1129 1130 1131 1132/* 1133 perform the receive side of a async dcerpc request 1134*/ 1135NTSTATUS dcerpc_request_recv(struct rpc_request *req, 1136 TALLOC_CTX *mem_ctx, 1137 DATA_BLOB *stub_data) 1138{ 1139 NTSTATUS status; 1140 1141 while (req->state != RPC_REQUEST_DONE) { 1142 struct tevent_context *ctx = dcerpc_event_context(req->p); 1143 if (event_loop_once(ctx) != 0) { 1144 return NT_STATUS_CONNECTION_DISCONNECTED; 1145 } 1146 } 1147 *stub_data = req->payload; 1148 status = req->status; 1149 if (stub_data->data) { 1150 stub_data->data = talloc_steal(mem_ctx, stub_data->data); 1151 } 1152 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { 1153 req->p->last_fault_code = req->fault_code; 1154 } 1155 talloc_unlink(talloc_parent(req), req); 1156 return status; 1157} 1158 1159/* 1160 perform a full request/response pair on a dcerpc pipe 1161*/ 1162NTSTATUS dcerpc_request(struct dcerpc_pipe *p, 1163 struct GUID *object, 1164 uint16_t opnum, 1165 TALLOC_CTX *mem_ctx, 1166 DATA_BLOB *stub_data_in, 1167 DATA_BLOB *stub_data_out) 1168{ 1169 struct rpc_request *req; 1170 1171 req = dcerpc_request_send(p, object, opnum, false, stub_data_in); 1172 if (req == NULL) { 1173 return NT_STATUS_NO_MEMORY; 1174 } 1175 1176 return dcerpc_request_recv(req, mem_ctx, stub_data_out); 1177} 1178 1179 1180/* 1181 this is a paranoid NDR validator. For every packet we push onto the wire 1182 we pull it back again, then push it again. Then we compare the raw NDR data 1183 for that to the NDR we initially generated. If they don't match then we know 1184 we must have a bug in either the pull or push side of our code 1185*/ 1186static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_connection *c, 1187 TALLOC_CTX *mem_ctx, 1188 DATA_BLOB blob, 1189 size_t struct_size, 1190 ndr_push_flags_fn_t ndr_push, 1191 ndr_pull_flags_fn_t ndr_pull) 1192{ 1193 void *st; 1194 struct ndr_pull *pull; 1195 struct ndr_push *push; 1196 DATA_BLOB blob2; 1197 enum ndr_err_code ndr_err; 1198 1199 st = talloc_size(mem_ctx, struct_size); 1200 if (!st) { 1201 return NT_STATUS_NO_MEMORY; 1202 } 1203 1204 pull = ndr_pull_init_flags(c, &blob, mem_ctx); 1205 if (!pull) { 1206 return NT_STATUS_NO_MEMORY; 1207 } 1208 pull->flags |= LIBNDR_FLAG_REF_ALLOC; 1209 1210 ndr_err = ndr_pull(pull, NDR_IN, st); 1211 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1212 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1213 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE, 1214 "failed input validation pull - %s", 1215 nt_errstr(status)); 1216 return ndr_map_error2ntstatus(ndr_err); 1217 } 1218 1219 push = ndr_push_init_ctx(mem_ctx, c->iconv_convenience); 1220 if (!push) { 1221 return NT_STATUS_NO_MEMORY; 1222 } 1223 1224 ndr_err = ndr_push(push, NDR_IN, st); 1225 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1226 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1227 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE, 1228 "failed input validation push - %s", 1229 nt_errstr(status)); 1230 return ndr_map_error2ntstatus(ndr_err); 1231 } 1232 1233 blob2 = ndr_push_blob(push); 1234 1235 if (data_blob_cmp(&blob, &blob2) != 0) { 1236 DEBUG(3,("original:\n")); 1237 dump_data(3, blob.data, blob.length); 1238 DEBUG(3,("secondary:\n")); 1239 dump_data(3, blob2.data, blob2.length); 1240 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE, 1241 "failed input validation blobs doesn't match"); 1242 return ndr_map_error2ntstatus(ndr_err); 1243 } 1244 1245 return NT_STATUS_OK; 1246} 1247 1248/* 1249 this is a paranoid NDR input validator. For every packet we pull 1250 from the wire we push it back again then pull and push it 1251 again. Then we compare the raw NDR data for that to the NDR we 1252 initially generated. If they don't match then we know we must have a 1253 bug in either the pull or push side of our code 1254*/ 1255static NTSTATUS dcerpc_ndr_validate_out(struct dcerpc_connection *c, 1256 struct ndr_pull *pull_in, 1257 void *struct_ptr, 1258 size_t struct_size, 1259 ndr_push_flags_fn_t ndr_push, 1260 ndr_pull_flags_fn_t ndr_pull, 1261 ndr_print_function_t ndr_print) 1262{ 1263 void *st; 1264 struct ndr_pull *pull; 1265 struct ndr_push *push; 1266 DATA_BLOB blob, blob2; 1267 TALLOC_CTX *mem_ctx = pull_in; 1268 char *s1, *s2; 1269 enum ndr_err_code ndr_err; 1270 1271 st = talloc_size(mem_ctx, struct_size); 1272 if (!st) { 1273 return NT_STATUS_NO_MEMORY; 1274 } 1275 memcpy(st, struct_ptr, struct_size); 1276 1277 push = ndr_push_init_ctx(mem_ctx, c->iconv_convenience); 1278 if (!push) { 1279 return NT_STATUS_NO_MEMORY; 1280 } 1281 1282 ndr_err = ndr_push(push, NDR_OUT, struct_ptr); 1283 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1284 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1285 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE, 1286 "failed output validation push - %s", 1287 nt_errstr(status)); 1288 return ndr_map_error2ntstatus(ndr_err); 1289 } 1290 1291 blob = ndr_push_blob(push); 1292 1293 pull = ndr_pull_init_flags(c, &blob, mem_ctx); 1294 if (!pull) { 1295 return NT_STATUS_NO_MEMORY; 1296 } 1297 1298 pull->flags |= LIBNDR_FLAG_REF_ALLOC; 1299 ndr_err = ndr_pull(pull, NDR_OUT, st); 1300 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1301 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1302 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE, 1303 "failed output validation pull - %s", 1304 nt_errstr(status)); 1305 return ndr_map_error2ntstatus(ndr_err); 1306 } 1307 1308 push = ndr_push_init_ctx(mem_ctx, c->iconv_convenience); 1309 if (!push) { 1310 return NT_STATUS_NO_MEMORY; 1311 } 1312 1313 ndr_err = ndr_push(push, NDR_OUT, st); 1314 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1315 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 1316 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE, 1317 "failed output validation push2 - %s", 1318 nt_errstr(status)); 1319 return ndr_map_error2ntstatus(ndr_err); 1320 } 1321 1322 blob2 = ndr_push_blob(push); 1323 1324 if (data_blob_cmp(&blob, &blob2) != 0) { 1325 DEBUG(3,("original:\n")); 1326 dump_data(3, blob.data, blob.length); 1327 DEBUG(3,("secondary:\n")); 1328 dump_data(3, blob2.data, blob2.length); 1329 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE, 1330 "failed output validation blobs doesn't match"); 1331 return ndr_map_error2ntstatus(ndr_err); 1332 } 1333 1334 /* this checks the printed forms of the two structures, which effectively 1335 tests all of the value() attributes */ 1336 s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 1337 NDR_OUT, struct_ptr); 1338 s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 1339 NDR_OUT, st); 1340 if (strcmp(s1, s2) != 0) { 1341#if 1 1342 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2)); 1343#else 1344 /* this is sometimes useful */ 1345 printf("VALIDATE ERROR\n"); 1346 file_save("wire.dat", s1, strlen(s1)); 1347 file_save("gen.dat", s2, strlen(s2)); 1348 system("diff -u wire.dat gen.dat"); 1349#endif 1350 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE, 1351 "failed output validation strings doesn't match"); 1352 return ndr_map_error2ntstatus(ndr_err); 1353 } 1354 1355 return NT_STATUS_OK; 1356} 1357 1358 1359/** 1360 send a rpc request given a dcerpc_call structure 1361 */ 1362struct rpc_request *dcerpc_ndr_request_send(struct dcerpc_pipe *p, 1363 const struct GUID *object, 1364 const struct ndr_interface_table *table, 1365 uint32_t opnum, 1366 bool async, 1367 TALLOC_CTX *mem_ctx, 1368 void *r) 1369{ 1370 const struct ndr_interface_call *call; 1371 struct ndr_push *push; 1372 NTSTATUS status; 1373 DATA_BLOB request; 1374 struct rpc_request *req; 1375 enum ndr_err_code ndr_err; 1376 1377 call = &table->calls[opnum]; 1378 1379 /* setup for a ndr_push_* call */ 1380 push = ndr_push_init_ctx(mem_ctx, p->conn->iconv_convenience); 1381 if (!push) { 1382 return NULL; 1383 } 1384 1385 if (p->conn->flags & DCERPC_PUSH_BIGENDIAN) { 1386 push->flags |= LIBNDR_FLAG_BIGENDIAN; 1387 } 1388 1389 if (p->conn->flags & DCERPC_NDR64) { 1390 push->flags |= LIBNDR_FLAG_NDR64; 1391 } 1392 1393 /* push the structure into a blob */ 1394 ndr_err = call->ndr_push(push, NDR_IN, r); 1395 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1396 status = ndr_map_error2ntstatus(ndr_err); 1397 DEBUG(2,("Unable to ndr_push structure in dcerpc_ndr_request_send - %s\n", 1398 nt_errstr(status))); 1399 talloc_free(push); 1400 return NULL; 1401 } 1402 1403 /* retrieve the blob */ 1404 request = ndr_push_blob(push); 1405 1406 if (p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) { 1407 status = dcerpc_ndr_validate_in(p->conn, push, request, call->struct_size, 1408 call->ndr_push, call->ndr_pull); 1409 if (!NT_STATUS_IS_OK(status)) { 1410 DEBUG(2,("Validation failed in dcerpc_ndr_request_send - %s\n", 1411 nt_errstr(status))); 1412 talloc_free(push); 1413 return NULL; 1414 } 1415 } 1416 1417 DEBUG(10,("rpc request data:\n")); 1418 dump_data(10, request.data, request.length); 1419 1420 /* make the actual dcerpc request */ 1421 req = dcerpc_request_send(p, object, opnum, async, &request); 1422 1423 if (req != NULL) { 1424 req->ndr.table = table; 1425 req->ndr.opnum = opnum; 1426 req->ndr.struct_ptr = r; 1427 req->ndr.mem_ctx = mem_ctx; 1428 } 1429 1430 talloc_free(push); 1431 1432 return req; 1433} 1434 1435/* 1436 receive the answer from a dcerpc_ndr_request_send() 1437*/ 1438_PUBLIC_ NTSTATUS dcerpc_ndr_request_recv(struct rpc_request *req) 1439{ 1440 struct dcerpc_pipe *p = req->p; 1441 NTSTATUS status; 1442 DATA_BLOB response; 1443 struct ndr_pull *pull; 1444 uint_t flags; 1445 TALLOC_CTX *mem_ctx = req->ndr.mem_ctx; 1446 void *r = req->ndr.struct_ptr; 1447 uint32_t opnum = req->ndr.opnum; 1448 const struct ndr_interface_table *table = req->ndr.table; 1449 const struct ndr_interface_call *call = &table->calls[opnum]; 1450 enum ndr_err_code ndr_err; 1451 1452 /* make sure the recv code doesn't free the request, as we 1453 need to grab the flags element before it is freed */ 1454 if (talloc_reference(p, req) == NULL) { 1455 return NT_STATUS_NO_MEMORY; 1456 } 1457 1458 status = dcerpc_request_recv(req, mem_ctx, &response); 1459 if (!NT_STATUS_IS_OK(status)) { 1460 talloc_unlink(p, req); 1461 return status; 1462 } 1463 1464 flags = req->flags; 1465 1466 /* prepare for ndr_pull_* */ 1467 pull = ndr_pull_init_flags(p->conn, &response, mem_ctx); 1468 if (!pull) { 1469 talloc_unlink(p, req); 1470 return NT_STATUS_NO_MEMORY; 1471 } 1472 1473 if (pull->data) { 1474 pull->data = talloc_steal(pull, pull->data); 1475 } 1476 talloc_unlink(p, req); 1477 1478 if (flags & DCERPC_PULL_BIGENDIAN) { 1479 pull->flags |= LIBNDR_FLAG_BIGENDIAN; 1480 } 1481 1482 DEBUG(10,("rpc reply data:\n")); 1483 dump_data(10, pull->data, pull->data_size); 1484 1485 /* pull the structure from the blob */ 1486 ndr_err = call->ndr_pull(pull, NDR_OUT, r); 1487 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1488 status = ndr_map_error2ntstatus(ndr_err); 1489 dcerpc_log_packet(p->conn->packet_log_dir, 1490 table, opnum, NDR_OUT, 1491 &response); 1492 return status; 1493 } 1494 1495 if (p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) { 1496 status = dcerpc_ndr_validate_out(p->conn, pull, r, call->struct_size, 1497 call->ndr_push, call->ndr_pull, 1498 call->ndr_print); 1499 if (!NT_STATUS_IS_OK(status)) { 1500 dcerpc_log_packet(p->conn->packet_log_dir, 1501 table, opnum, NDR_OUT, 1502 &response); 1503 return status; 1504 } 1505 } 1506 1507 if (pull->offset != pull->data_size) { 1508 DEBUG(0,("Warning! ignoring %d unread bytes in rpc packet!\n", 1509 pull->data_size - pull->offset)); 1510 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here, 1511 but it turns out that early versions of NT 1512 (specifically NT3.1) add junk onto the end of rpc 1513 packets, so if we want to interoperate at all with 1514 those versions then we need to ignore this error */ 1515 } 1516 1517 /* TODO: make pull context independent from the output mem_ctx and free the pull context */ 1518 1519 return NT_STATUS_OK; 1520} 1521 1522 1523/* 1524 a useful helper function for synchronous rpc requests 1525 1526 this can be used when you have ndr push/pull functions in the 1527 standard format 1528*/ 1529_PUBLIC_ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p, 1530 const struct GUID *object, 1531 const struct ndr_interface_table *table, 1532 uint32_t opnum, 1533 TALLOC_CTX *mem_ctx, 1534 void *r) 1535{ 1536 struct rpc_request *req; 1537 1538 req = dcerpc_ndr_request_send(p, object, table, opnum, false, mem_ctx, r); 1539 if (req == NULL) { 1540 return NT_STATUS_NO_MEMORY; 1541 } 1542 1543 return dcerpc_ndr_request_recv(req); 1544} 1545 1546 1547/* 1548 a useful function for retrieving the server name we connected to 1549*/ 1550_PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p) 1551{ 1552 if (!p->conn->transport.target_hostname) { 1553 if (!p->conn->transport.peer_name) { 1554 return ""; 1555 } 1556 return p->conn->transport.peer_name(p->conn); 1557 } 1558 return p->conn->transport.target_hostname(p->conn); 1559} 1560 1561 1562/* 1563 get the dcerpc auth_level for a open connection 1564*/ 1565uint32_t dcerpc_auth_level(struct dcerpc_connection *c) 1566{ 1567 uint8_t auth_level; 1568 1569 if (c->flags & DCERPC_SEAL) { 1570 auth_level = DCERPC_AUTH_LEVEL_PRIVACY; 1571 } else if (c->flags & DCERPC_SIGN) { 1572 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; 1573 } else if (c->flags & DCERPC_CONNECT) { 1574 auth_level = DCERPC_AUTH_LEVEL_CONNECT; 1575 } else { 1576 auth_level = DCERPC_AUTH_LEVEL_NONE; 1577 } 1578 return auth_level; 1579} 1580 1581/* 1582 Receive an alter reply from the transport 1583*/ 1584static void dcerpc_alter_recv_handler(struct rpc_request *req, 1585 DATA_BLOB *raw_packet, struct ncacn_packet *pkt) 1586{ 1587 struct composite_context *c; 1588 struct dcerpc_pipe *recv_pipe; 1589 1590 c = talloc_get_type(req->async.private_data, struct composite_context); 1591 recv_pipe = talloc_get_type(c->private_data, struct dcerpc_pipe); 1592 1593 if (pkt->ptype == DCERPC_PKT_ALTER_RESP && 1594 pkt->u.alter_resp.num_results == 1 && 1595 pkt->u.alter_resp.ctx_list[0].result != 0) { 1596 DEBUG(2,("dcerpc: alter_resp failed - reason %d\n", 1597 pkt->u.alter_resp.ctx_list[0].reason)); 1598 composite_error(c, dcerpc_map_reason(pkt->u.alter_resp.ctx_list[0].reason)); 1599 return; 1600 } 1601 1602 if (pkt->ptype != DCERPC_PKT_ALTER_RESP || 1603 pkt->u.alter_resp.num_results == 0 || 1604 pkt->u.alter_resp.ctx_list[0].result != 0) { 1605 composite_error(c, NT_STATUS_NET_WRITE_FAULT); 1606 return; 1607 } 1608 1609 /* the alter_resp might contain a reply set of credentials */ 1610 if (recv_pipe->conn->security_state.auth_info && 1611 pkt->u.alter_resp.auth_info.length) { 1612 enum ndr_err_code ndr_err; 1613 ndr_err = ndr_pull_struct_blob( 1614 &pkt->u.alter_resp.auth_info, recv_pipe, 1615 NULL, 1616 recv_pipe->conn->security_state.auth_info, 1617 (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); 1618 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1619 c->status = ndr_map_error2ntstatus(ndr_err); 1620 if (!composite_is_ok(c)) return; 1621 } 1622 } 1623 1624 composite_done(c); 1625} 1626 1627/* 1628 send a dcerpc alter_context request 1629*/ 1630struct composite_context *dcerpc_alter_context_send(struct dcerpc_pipe *p, 1631 TALLOC_CTX *mem_ctx, 1632 const struct ndr_syntax_id *syntax, 1633 const struct ndr_syntax_id *transfer_syntax) 1634{ 1635 struct composite_context *c; 1636 struct ncacn_packet pkt; 1637 DATA_BLOB blob; 1638 struct rpc_request *req; 1639 1640 c = composite_create(mem_ctx, p->conn->event_ctx); 1641 if (c == NULL) return NULL; 1642 1643 c->private_data = p; 1644 1645 p->syntax = *syntax; 1646 p->transfer_syntax = *transfer_syntax; 1647 1648 init_ncacn_hdr(p->conn, &pkt); 1649 1650 pkt.ptype = DCERPC_PKT_ALTER; 1651 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; 1652 pkt.call_id = p->conn->call_id; 1653 pkt.auth_length = 0; 1654 1655 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) { 1656 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; 1657 } 1658 1659 if (p->binding->flags & DCERPC_HEADER_SIGNING) { 1660 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; 1661 } 1662 1663 pkt.u.alter.max_xmit_frag = 5840; 1664 pkt.u.alter.max_recv_frag = 5840; 1665 pkt.u.alter.assoc_group_id = p->binding->assoc_group_id; 1666 pkt.u.alter.num_contexts = 1; 1667 pkt.u.alter.ctx_list = talloc_array(c, struct dcerpc_ctx_list, 1); 1668 if (composite_nomem(pkt.u.alter.ctx_list, c)) return c; 1669 pkt.u.alter.ctx_list[0].context_id = p->context_id; 1670 pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1; 1671 pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax; 1672 pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax; 1673 pkt.u.alter.auth_info = data_blob(NULL, 0); 1674 1675 /* construct the NDR form of the packet */ 1676 c->status = ncacn_push_auth(&blob, mem_ctx, p->conn->iconv_convenience, &pkt, 1677 p->conn->security_state.auth_info); 1678 if (!composite_is_ok(c)) return c; 1679 1680 p->conn->transport.recv_data = dcerpc_recv_data; 1681 1682 /* 1683 * we allocate a dcerpc_request so we can be in the same 1684 * request queue as normal requests 1685 */ 1686 req = talloc_zero(c, struct rpc_request); 1687 if (composite_nomem(req, c)) return c; 1688 1689 req->state = RPC_REQUEST_PENDING; 1690 req->call_id = pkt.call_id; 1691 req->async.private_data = c; 1692 req->async.callback = dcerpc_composite_fail; 1693 req->p = p; 1694 req->recv_handler = dcerpc_alter_recv_handler; 1695 DLIST_ADD_END(p->conn->pending, req, struct rpc_request *); 1696 talloc_set_destructor(req, dcerpc_req_dequeue); 1697 1698 c->status = p->conn->transport.send_request(p->conn, &blob, true); 1699 if (!composite_is_ok(c)) return c; 1700 1701 event_add_timed(c->event_ctx, req, 1702 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0), 1703 dcerpc_timeout_handler, req); 1704 1705 return c; 1706} 1707 1708NTSTATUS dcerpc_alter_context_recv(struct composite_context *ctx) 1709{ 1710 NTSTATUS result = composite_wait(ctx); 1711 talloc_free(ctx); 1712 return result; 1713} 1714 1715/* 1716 send a dcerpc alter_context request 1717*/ 1718_PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p, 1719 TALLOC_CTX *mem_ctx, 1720 const struct ndr_syntax_id *syntax, 1721 const struct ndr_syntax_id *transfer_syntax) 1722{ 1723 struct composite_context *creq; 1724 creq = dcerpc_alter_context_send(p, mem_ctx, syntax, transfer_syntax); 1725 return dcerpc_alter_context_recv(creq); 1726} 1727