1From 8716bb5e03cc4f10e2d4edc704d8defe7e8045f1 Mon Sep 17 00:00:00 2001 2From: Stefan Metzmacher <metze@samba.org> 3Date: Thu, 16 Jul 2015 22:46:05 +0200 4Subject: [PATCH 01/40] CVE-2015-5370: dcerpc.idl: add 5 DCERPC_{NCACN_PAYLOAD,FRAG}_MAX_SIZE defines 6MIME-Version: 1.0 7Content-Type: text/plain; charset=UTF-8 8Content-Transfer-Encoding: 8bit 9 10BUG: https://bugzilla.samba.org/show_bug.cgi?id=11344 11 12Signed-off-by: Stefan Metzmacher <metze@samba.org> 13Reviewed-by: G��nther Deschner <gd@samba.org> 14--- 15 librpc/idl/dcerpc.idl | 2 ++ 16 1 file changed, 2 insertions(+) 17 18--- a/librpc/idl/dcerpc.idl 19+++ b/librpc/idl/dcerpc.idl 20@@ -475,9 +475,11 @@ interface dcerpc 21 const uint8 DCERPC_PFC_OFFSET = 3; 22 const uint8 DCERPC_DREP_OFFSET = 4; 23 const uint8 DCERPC_FRAG_LEN_OFFSET = 8; 24+ const uint32 DCERPC_FRAG_MAX_SIZE = 5840; 25 const uint8 DCERPC_AUTH_LEN_OFFSET = 10; 26 const uint8 DCERPC_CALL_ID_OFFSET = 12; 27 const uint8 DCERPC_NCACN_PAYLOAD_OFFSET = 16; 28+ const uint32 DCERPC_NCACN_PAYLOAD_MAX_SIZE = 0x400000; /* 4 MByte */ 29 30 /* little-endian flag */ 31 const uint8 DCERPC_DREP_LE = 0x10; 32--- a/librpc/rpc/dcerpc_util.c 33+++ b/librpc/rpc/dcerpc_util.c 34@@ -92,31 +92,49 @@ uint8_t dcerpc_get_endian_flag(DATA_BLOB 35 * 36 * @return - A NTSTATUS error code. 37 */ 38-NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt, 39+NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt, 40 TALLOC_CTX *mem_ctx, 41- DATA_BLOB *pkt_trailer, 42+ const DATA_BLOB *pkt_trailer, 43 struct dcerpc_auth *auth, 44- uint32_t *auth_length, 45+ uint32_t *_auth_length, 46 bool auth_data_only) 47 { 48 struct ndr_pull *ndr; 49 enum ndr_err_code ndr_err; 50- uint32_t data_and_pad; 51+ uint16_t data_and_pad; 52+ uint16_t auth_length; 53+ uint32_t tmp_length; 54 55- data_and_pad = pkt_trailer->length 56- - (DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length); 57+ ZERO_STRUCTP(auth); 58+ if (_auth_length != NULL) { 59+ *_auth_length = 0; 60+ } 61+ 62+ /* Paranoia checks for auth_length. The caller should check this... */ 63+ if (pkt->auth_length == 0) { 64+ return NT_STATUS_INTERNAL_ERROR; 65+ } 66+ 67+ /* Paranoia checks for auth_length. The caller should check this... */ 68+ if (pkt->auth_length > pkt->frag_length) { 69+ return NT_STATUS_INTERNAL_ERROR; 70+ } 71+ tmp_length = DCERPC_NCACN_PAYLOAD_OFFSET; 72+ tmp_length += DCERPC_AUTH_TRAILER_LENGTH; 73+ tmp_length += pkt->auth_length; 74+ if (tmp_length > pkt->frag_length) { 75+ return NT_STATUS_INTERNAL_ERROR; 76+ } 77+ if (pkt_trailer->length > UINT16_MAX) { 78+ return NT_STATUS_INTERNAL_ERROR; 79+ } 80 81- /* paranoia check for pad size. This would be caught anyway by 82- the ndr_pull_advance() a few lines down, but it scared 83- Jeremy enough for him to call me, so we might as well check 84- it now, just to prevent someone posting a bogus YouTube 85- video in the future. 86- */ 87- if (data_and_pad > pkt_trailer->length) { 88- return NT_STATUS_INFO_LENGTH_MISMATCH; 89+ auth_length = DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length; 90+ if (pkt_trailer->length < auth_length) { 91+ return NT_STATUS_RPC_PROTOCOL_ERROR; 92 } 93 94- *auth_length = pkt_trailer->length - data_and_pad; 95+ data_and_pad = pkt_trailer->length - auth_length; 96 97 ndr = ndr_pull_init_blob(pkt_trailer, mem_ctx); 98 if (!ndr) { 99@@ -136,14 +154,28 @@ NTSTATUS dcerpc_pull_auth_trailer(struct 100 ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth); 101 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 102 talloc_free(ndr); 103+ ZERO_STRUCTP(auth); 104 return ndr_map_error2ntstatus(ndr_err); 105 } 106 107+ if (data_and_pad < auth->auth_pad_length) { 108+ DEBUG(1, (__location__ ": ERROR: pad length mismatch. " 109+ "Calculated %u got %u\n", 110+ (unsigned)data_and_pad, 111+ (unsigned)auth->auth_pad_length)); 112+ talloc_free(ndr); 113+ ZERO_STRUCTP(auth); 114+ return NT_STATUS_RPC_PROTOCOL_ERROR; 115+ } 116+ 117 if (auth_data_only && data_and_pad != auth->auth_pad_length) { 118- DEBUG(1, (__location__ ": WARNING: pad length mismatch. " 119+ DEBUG(1, (__location__ ": ERROR: pad length mismatch. " 120 "Calculated %u got %u\n", 121 (unsigned)data_and_pad, 122 (unsigned)auth->auth_pad_length)); 123+ talloc_free(ndr); 124+ ZERO_STRUCTP(auth); 125+ return NT_STATUS_RPC_PROTOCOL_ERROR; 126 } 127 128 DEBUG(6,(__location__ ": auth_pad_length %u\n", 129@@ -152,6 +184,83 @@ NTSTATUS dcerpc_pull_auth_trailer(struct 130 talloc_steal(mem_ctx, auth->credentials.data); 131 talloc_free(ndr); 132 133+ if (_auth_length != NULL) { 134+ *_auth_length = auth_length; 135+ } 136+ 137+ return NT_STATUS_OK; 138+} 139+ 140+/** 141+* @brief Verify the fields in ncacn_packet header. 142+* 143+* @param pkt - The ncacn_packet strcuture 144+* @param ptype - The expected PDU type 145+* @param max_auth_info - The maximum size of a possible auth trailer 146+* @param required_flags - The required flags for the pdu. 147+* @param optional_flags - The possible optional flags for the pdu. 148+* 149+* @return - A NTSTATUS error code. 150+*/ 151+NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt, 152+ enum dcerpc_pkt_type ptype, 153+ size_t max_auth_info, 154+ uint8_t required_flags, 155+ uint8_t optional_flags) 156+{ 157+ if (pkt->rpc_vers != 5) { 158+ return NT_STATUS_RPC_PROTOCOL_ERROR; 159+ } 160+ 161+ if (pkt->rpc_vers_minor != 0) { 162+ return NT_STATUS_RPC_PROTOCOL_ERROR; 163+ } 164+ 165+ if (pkt->auth_length > pkt->frag_length) { 166+ return NT_STATUS_RPC_PROTOCOL_ERROR; 167+ } 168+ 169+ if (pkt->ptype != ptype) { 170+ return NT_STATUS_RPC_PROTOCOL_ERROR; 171+ } 172+ 173+ if (max_auth_info > UINT16_MAX) { 174+ return NT_STATUS_INTERNAL_ERROR; 175+ } 176+ 177+ if (pkt->auth_length > 0) { 178+ size_t max_auth_length; 179+ 180+ if (max_auth_info <= DCERPC_AUTH_TRAILER_LENGTH) { 181+ return NT_STATUS_RPC_PROTOCOL_ERROR; 182+ } 183+ max_auth_length = max_auth_info - DCERPC_AUTH_TRAILER_LENGTH; 184+ 185+ if (pkt->auth_length > max_auth_length) { 186+ return NT_STATUS_RPC_PROTOCOL_ERROR; 187+ } 188+ } 189+ 190+ if ((pkt->pfc_flags & required_flags) != required_flags) { 191+ return NT_STATUS_RPC_PROTOCOL_ERROR; 192+ } 193+ if (pkt->pfc_flags & ~(optional_flags|required_flags)) { 194+ return NT_STATUS_RPC_PROTOCOL_ERROR; 195+ } 196+ 197+ if (pkt->drep[0] & ~DCERPC_DREP_LE) { 198+ return NT_STATUS_RPC_PROTOCOL_ERROR; 199+ } 200+ if (pkt->drep[1] != 0) { 201+ return NT_STATUS_RPC_PROTOCOL_ERROR; 202+ } 203+ if (pkt->drep[2] != 0) { 204+ return NT_STATUS_RPC_PROTOCOL_ERROR; 205+ } 206+ if (pkt->drep[3] != 0) { 207+ return NT_STATUS_RPC_PROTOCOL_ERROR; 208+ } 209+ 210 return NT_STATUS_OK; 211 } 212 213--- a/librpc/rpc/rpc_common.h 214+++ b/librpc/rpc/rpc_common.h 215@@ -158,12 +158,17 @@ uint8_t dcerpc_get_endian_flag(DATA_BLOB 216 * 217 * @return - A NTSTATUS error code. 218 */ 219-NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt, 220+NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt, 221 TALLOC_CTX *mem_ctx, 222- DATA_BLOB *pkt_trailer, 223+ const DATA_BLOB *pkt_trailer, 224 struct dcerpc_auth *auth, 225 uint32_t *auth_length, 226 bool auth_data_only); 227+NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt, 228+ enum dcerpc_pkt_type ptype, 229+ size_t max_auth_info, 230+ uint8_t required_flags, 231+ uint8_t optional_flags); 232 struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx, 233 struct tevent_context *ev, 234 struct tstream_context *stream); 235--- a/source3/librpc/rpc/dcerpc_helpers.c 236+++ b/source3/librpc/rpc/dcerpc_helpers.c 237@@ -210,47 +210,6 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_ 238 } 239 240 /** 241-* @brief Decodes a dcerpc_auth blob 242-* 243-* @param mem_ctx The memory context on which to allocate the packet 244-* elements 245-* @param blob The blob of data to decode 246-* @param r An empty dcerpc_auth structure, must not be NULL 247-* 248-* @return a NTSTATUS error code 249-*/ 250-NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, 251- const DATA_BLOB *blob, 252- struct dcerpc_auth *r, 253- bool bigendian) 254-{ 255- enum ndr_err_code ndr_err; 256- struct ndr_pull *ndr; 257- 258- ndr = ndr_pull_init_blob(blob, mem_ctx); 259- if (!ndr) { 260- return NT_STATUS_NO_MEMORY; 261- } 262- if (bigendian) { 263- ndr->flags |= LIBNDR_FLAG_BIGENDIAN; 264- } 265- 266- ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, r); 267- 268- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 269- talloc_free(ndr); 270- return ndr_map_error2ntstatus(ndr_err); 271- } 272- talloc_free(ndr); 273- 274- if (DEBUGLEVEL >= 10) { 275- NDR_PRINT_DEBUG(dcerpc_auth, r); 276- } 277- 278- return NT_STATUS_OK; 279-} 280- 281-/** 282 * @brief Calculate how much data we can in a packet, including calculating 283 * auth token and pad lengths. 284 * 285@@ -782,7 +741,7 @@ NTSTATUS dcerpc_add_auth_footer(struct p 286 auth->auth_type, 287 auth->auth_level, 288 pad_len, 289- 1 /* context id. */, 290+ auth->auth_context_id, 291 &auth_blob, 292 &auth_info); 293 if (!NT_STATUS_IS_OK(status)) { 294@@ -844,19 +803,18 @@ NTSTATUS dcerpc_add_auth_footer(struct p 295 * 296 * @param auth The auth data for the connection 297 * @param pkt The actual ncacn_packet 298-* @param pkt_trailer The stub_and_verifier part of the packet 299+* @param pkt_trailer [in][out] The stub_and_verifier part of the packet, 300+* the auth_trailer and padding will be removed. 301 * @param header_size The header size 302 * @param raw_pkt The whole raw packet data blob 303-* @param pad_len [out] The padding length used in the packet 304 * 305 * @return A NTSTATUS error code 306 */ 307 NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, 308 struct ncacn_packet *pkt, 309 DATA_BLOB *pkt_trailer, 310- size_t header_size, 311- DATA_BLOB *raw_pkt, 312- size_t *pad_len) 313+ uint8_t header_size, 314+ DATA_BLOB *raw_pkt) 315 { 316 struct schannel_state *schannel_auth; 317 struct auth_ntlmssp_state *ntlmssp_ctx; 318@@ -868,6 +826,14 @@ NTSTATUS dcerpc_check_auth(struct pipe_a 319 DATA_BLOB full_pkt; 320 DATA_BLOB data; 321 322+ /* 323+ * These check should be done in the caller. 324+ */ 325+ SMB_ASSERT(raw_pkt->length == pkt->frag_length); 326+ SMB_ASSERT(header_size <= pkt->frag_length); 327+ SMB_ASSERT(pkt_trailer->length < pkt->frag_length); 328+ SMB_ASSERT((pkt_trailer->length + header_size) <= pkt->frag_length); 329+ 330 switch (auth->auth_level) { 331 case DCERPC_AUTH_LEVEL_PRIVACY: 332 DEBUG(10, ("Requested Privacy.\n")); 333@@ -881,7 +847,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_a 334 if (pkt->auth_length != 0) { 335 break; 336 } 337- *pad_len = 0; 338 return NT_STATUS_OK; 339 340 case DCERPC_AUTH_LEVEL_NONE: 341@@ -890,7 +855,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_a 342 "authenticated connection!\n")); 343 return NT_STATUS_INVALID_PARAMETER; 344 } 345- *pad_len = 0; 346 return NT_STATUS_OK; 347 348 default: 349@@ -899,16 +863,8 @@ NTSTATUS dcerpc_check_auth(struct pipe_a 350 return NT_STATUS_INVALID_PARAMETER; 351 } 352 353- /* Paranioa checks for auth_length. */ 354- if (pkt->auth_length > pkt->frag_length) { 355- return NT_STATUS_INFO_LENGTH_MISMATCH; 356- } 357- if (((unsigned int)pkt->auth_length 358- + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) || 359- ((unsigned int)pkt->auth_length 360- + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) { 361- /* Integer wrap attempt. */ 362- return NT_STATUS_INFO_LENGTH_MISMATCH; 363+ if (pkt->auth_length == 0) { 364+ return NT_STATUS_INVALID_PARAMETER; 365 } 366 367 status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer, 368@@ -917,10 +873,23 @@ NTSTATUS dcerpc_check_auth(struct pipe_a 369 return status; 370 } 371 372+ if (auth_info.auth_type != auth->auth_type) { 373+ return NT_STATUS_INVALID_PARAMETER; 374+ } 375+ 376+ if (auth_info.auth_level != auth->auth_level) { 377+ return NT_STATUS_INVALID_PARAMETER; 378+ } 379+ 380+ if (auth_info.auth_context_id != auth->auth_context_id) { 381+ return NT_STATUS_INVALID_PARAMETER; 382+ } 383+ 384+ pkt_trailer->length -= auth_length; 385 data = data_blob_const(raw_pkt->data + header_size, 386- pkt_trailer->length - auth_length); 387- full_pkt = data_blob_const(raw_pkt->data, 388- raw_pkt->length - auth_info.credentials.length); 389+ pkt_trailer->length); 390+ full_pkt = data_blob_const(raw_pkt->data, raw_pkt->length); 391+ full_pkt.length -= auth_info.credentials.length; 392 393 switch (auth->auth_type) { 394 case DCERPC_AUTH_TYPE_NONE: 395@@ -996,10 +965,13 @@ NTSTATUS dcerpc_check_auth(struct pipe_a 396 * pkt_trailer actually has a copy of the raw data, and they 397 * are still both used in later calls */ 398 if (auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { 399+ if (pkt_trailer->length != data.length) { 400+ return NT_STATUS_INVALID_PARAMETER; 401+ } 402 memcpy(pkt_trailer->data, data.data, data.length); 403 } 404 405- *pad_len = auth_info.auth_pad_length; 406+ pkt_trailer->length -= auth_info.auth_pad_length; 407 data_blob_free(&auth_info.credentials); 408 return NT_STATUS_OK; 409 } 410--- a/source3/rpc_client/cli_pipe.c 411+++ b/source3/rpc_client/cli_pipe.c 412@@ -404,9 +404,9 @@ static NTSTATUS cli_pipe_validate_curren 413 DATA_BLOB *rdata, 414 DATA_BLOB *reply_pdu) 415 { 416- struct dcerpc_response *r; 417+ const struct dcerpc_response *r = NULL; 418+ DATA_BLOB tmp_stub = data_blob_null; 419 NTSTATUS ret = NT_STATUS_OK; 420- size_t pad_len = 0; 421 422 /* 423 * Point the return values at the real data including the RPC 424@@ -414,50 +414,128 @@ static NTSTATUS cli_pipe_validate_curren 425 */ 426 *rdata = *pdu; 427 428+ if ((pkt->ptype == DCERPC_PKT_BIND_ACK) && 429+ !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) { 430+ /* 431+ * TODO: do we still need this hack which was introduced 432+ * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0. 433+ * 434+ * I don't even know what AS/U might be... 435+ */ 436+ DEBUG(5, (__location__ ": bug in server (AS/U?), setting " 437+ "fragment first/last ON.\n")); 438+ pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; 439+ } 440+ 441 /* Ensure we have the correct type. */ 442 switch (pkt->ptype) { 443- case DCERPC_PKT_ALTER_RESP: 444+ case DCERPC_PKT_BIND_NAK: 445+ DEBUG(1, (__location__ ": Bind NACK received from %s!\n", 446+ rpccli_pipe_txt(talloc_tos(), cli))); 447+ 448+ ret = dcerpc_verify_ncacn_packet_header(pkt, 449+ DCERPC_PKT_BIND_NAK, 450+ 0, /* max_auth_info */ 451+ DCERPC_PFC_FLAG_FIRST | 452+ DCERPC_PFC_FLAG_LAST, 453+ 0); /* optional flags */ 454+ if (!NT_STATUS_IS_OK(ret)) { 455+ DEBUG(1, (__location__ ": Connection to %s got an unexpected " 456+ "RPC packet type - %u, expected %u: %s\n", 457+ rpccli_pipe_txt(talloc_tos(), cli), 458+ pkt->ptype, expected_pkt_type, 459+ nt_errstr(ret))); 460+ NDR_PRINT_DEBUG(ncacn_packet, pkt); 461+ return ret; 462+ } 463+ 464+ /* Use this for now... */ 465+ return NT_STATUS_NETWORK_ACCESS_DENIED; 466+ 467 case DCERPC_PKT_BIND_ACK: 468+ ret = dcerpc_verify_ncacn_packet_header(pkt, 469+ expected_pkt_type, 470+ pkt->u.bind_ack.auth_info.length, 471+ DCERPC_PFC_FLAG_FIRST | 472+ DCERPC_PFC_FLAG_LAST, 473+ DCERPC_PFC_FLAG_CONC_MPX | 474+ DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN); 475+ if (!NT_STATUS_IS_OK(ret)) { 476+ DEBUG(1, (__location__ ": Connection to %s got an unexpected " 477+ "RPC packet type - %u, expected %u: %s\n", 478+ rpccli_pipe_txt(talloc_tos(), cli), 479+ pkt->ptype, expected_pkt_type, 480+ nt_errstr(ret))); 481+ NDR_PRINT_DEBUG(ncacn_packet, pkt); 482+ return ret; 483+ } 484 485- /* Client code never receives this kind of packets */ 486 break; 487 488+ case DCERPC_PKT_ALTER_RESP: 489+ ret = dcerpc_verify_ncacn_packet_header(pkt, 490+ expected_pkt_type, 491+ pkt->u.alter_resp.auth_info.length, 492+ DCERPC_PFC_FLAG_FIRST | 493+ DCERPC_PFC_FLAG_LAST, 494+ DCERPC_PFC_FLAG_CONC_MPX | 495+ DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN); 496+ if (!NT_STATUS_IS_OK(ret)) { 497+ DEBUG(1, (__location__ ": Connection to %s got an unexpected " 498+ "RPC packet type - %u, expected %u: %s\n", 499+ rpccli_pipe_txt(talloc_tos(), cli), 500+ pkt->ptype, expected_pkt_type, 501+ nt_errstr(ret))); 502+ NDR_PRINT_DEBUG(ncacn_packet, pkt); 503+ return ret; 504+ } 505+ 506+ break; 507 508 case DCERPC_PKT_RESPONSE: 509 510 r = &pkt->u.response; 511 512+ ret = dcerpc_verify_ncacn_packet_header(pkt, 513+ expected_pkt_type, 514+ r->stub_and_verifier.length, 515+ 0, /* required_flags */ 516+ DCERPC_PFC_FLAG_FIRST | 517+ DCERPC_PFC_FLAG_LAST); 518+ if (!NT_STATUS_IS_OK(ret)) { 519+ DEBUG(1, (__location__ ": Connection to %s got an unexpected " 520+ "RPC packet type - %u, expected %u: %s\n", 521+ rpccli_pipe_txt(talloc_tos(), cli), 522+ pkt->ptype, expected_pkt_type, 523+ nt_errstr(ret))); 524+ NDR_PRINT_DEBUG(ncacn_packet, pkt); 525+ return ret; 526+ } 527+ 528+ tmp_stub.data = r->stub_and_verifier.data; 529+ tmp_stub.length = r->stub_and_verifier.length; 530+ 531 /* Here's where we deal with incoming sign/seal. */ 532 ret = dcerpc_check_auth(cli->auth, pkt, 533- &r->stub_and_verifier, 534+ &tmp_stub, 535 DCERPC_RESPONSE_LENGTH, 536- pdu, &pad_len); 537+ pdu); 538 if (!NT_STATUS_IS_OK(ret)) { 539+ DEBUG(1, (__location__ ": Connection to %s got an unexpected " 540+ "RPC packet type - %u, expected %u: %s\n", 541+ rpccli_pipe_txt(talloc_tos(), cli), 542+ pkt->ptype, expected_pkt_type, 543+ nt_errstr(ret))); 544+ NDR_PRINT_DEBUG(ncacn_packet, pkt); 545 return ret; 546 } 547 548- if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) { 549- return NT_STATUS_BUFFER_TOO_SMALL; 550- } 551- 552 /* Point the return values at the NDR data. */ 553- rdata->data = r->stub_and_verifier.data; 554+ *rdata = tmp_stub; 555 556- if (pkt->auth_length) { 557- /* We've already done integer wrap tests in 558- * dcerpc_check_auth(). */ 559- rdata->length = r->stub_and_verifier.length 560- - pad_len 561- - DCERPC_AUTH_TRAILER_LENGTH 562- - pkt->auth_length; 563- } else { 564- rdata->length = r->stub_and_verifier.length; 565- } 566- 567- DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n", 568+ DEBUG(10, ("Got pdu len %lu, data_len %lu\n", 569 (long unsigned int)pdu->length, 570- (long unsigned int)rdata->length, 571- (unsigned int)pad_len)); 572+ (long unsigned int)rdata->length)); 573 574 /* 575 * If this is the first reply, and the allocation hint is 576@@ -478,14 +556,24 @@ static NTSTATUS cli_pipe_validate_curren 577 578 break; 579 580- case DCERPC_PKT_BIND_NAK: 581- DEBUG(1, (__location__ ": Bind NACK received from %s!\n", 582- rpccli_pipe_txt(talloc_tos(), cli))); 583- /* Use this for now... */ 584- return NT_STATUS_NETWORK_ACCESS_DENIED; 585- 586 case DCERPC_PKT_FAULT: 587 588+ ret = dcerpc_verify_ncacn_packet_header(pkt, 589+ DCERPC_PKT_FAULT, 590+ 0, /* max_auth_info */ 591+ DCERPC_PFC_FLAG_FIRST | 592+ DCERPC_PFC_FLAG_LAST, 593+ DCERPC_PFC_FLAG_DID_NOT_EXECUTE); 594+ if (!NT_STATUS_IS_OK(ret)) { 595+ DEBUG(1, (__location__ ": Connection to %s got an unexpected " 596+ "RPC packet type - %u, expected %u: %s\n", 597+ rpccli_pipe_txt(talloc_tos(), cli), 598+ pkt->ptype, expected_pkt_type, 599+ nt_errstr(ret))); 600+ NDR_PRINT_DEBUG(ncacn_packet, pkt); 601+ return ret; 602+ } 603+ 604 DEBUG(1, (__location__ ": RPC fault code %s received " 605 "from %s!\n", 606 dcerpc_errstr(talloc_tos(), 607@@ -502,13 +590,6 @@ static NTSTATUS cli_pipe_validate_curren 608 return NT_STATUS_RPC_PROTOCOL_ERROR; 609 } 610 611- if (pkt->ptype != expected_pkt_type) { 612- DEBUG(3, (__location__ ": Connection to %s got an unexpected " 613- "RPC packet type - %u, not %u\n", 614- rpccli_pipe_txt(talloc_tos(), cli), 615- pkt->ptype, expected_pkt_type)); 616- return NT_STATUS_RPC_PROTOCOL_ERROR; 617- } 618 619 if (pkt->call_id != call_id) { 620 DEBUG(3, (__location__ ": Connection to %s got an unexpected " 621@@ -518,17 +599,6 @@ static NTSTATUS cli_pipe_validate_curren 622 return NT_STATUS_RPC_PROTOCOL_ERROR; 623 } 624 625- /* Do this just before return - we don't want to modify any rpc header 626- data before now as we may have needed to do cryptographic actions on 627- it before. */ 628- 629- if ((pkt->ptype == DCERPC_PKT_BIND_ACK) && 630- !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) { 631- DEBUG(5, (__location__ ": bug in server (AS/U?), setting " 632- "fragment first/last ON.\n")); 633- pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; 634- } 635- 636 return NT_STATUS_OK; 637 } 638 639@@ -883,6 +953,12 @@ static void rpc_api_pipe_got_pdu(struct 640 641 state->pkt = talloc(state, struct ncacn_packet); 642 if (!state->pkt) { 643+ /* 644+ * TODO: do a real async disconnect ... 645+ * 646+ * For now do it sync... 647+ */ 648+ TALLOC_FREE(state->cli->transport); 649 tevent_req_nterror(req, NT_STATUS_NO_MEMORY); 650 return; 651 } 652@@ -892,18 +968,16 @@ static void rpc_api_pipe_got_pdu(struct 653 state->pkt, 654 !state->endianess); 655 if (!NT_STATUS_IS_OK(status)) { 656+ /* 657+ * TODO: do a real async disconnect ... 658+ * 659+ * For now do it sync... 660+ */ 661+ TALLOC_FREE(state->cli->transport); 662 tevent_req_nterror(req, status); 663 return; 664 } 665 666- if (state->incoming_frag.length != state->pkt->frag_length) { 667- DEBUG(5, ("Incorrect pdu length %u, expected %u\n", 668- (unsigned int)state->incoming_frag.length, 669- (unsigned int)state->pkt->frag_length)); 670- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 671- return; 672- } 673- 674 status = cli_pipe_validate_current_pdu(state, 675 state->cli, state->pkt, 676 &state->incoming_frag, 677@@ -917,6 +991,28 @@ static void rpc_api_pipe_got_pdu(struct 678 (unsigned)state->reply_pdu_offset, 679 nt_errstr(status))); 680 681+ if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) { 682+ /* 683+ * TODO: do a real async disconnect ... 684+ * 685+ * For now do it sync... 686+ */ 687+ TALLOC_FREE(state->cli->transport); 688+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) { 689+ /* 690+ * TODO: do a real async disconnect ... 691+ * 692+ * For now do it sync... 693+ */ 694+ TALLOC_FREE(state->cli->transport); 695+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) { 696+ /* 697+ * TODO: do a real async disconnect ... 698+ * 699+ * For now do it sync... 700+ */ 701+ TALLOC_FREE(state->cli->transport); 702+ } 703 if (!NT_STATUS_IS_OK(status)) { 704 tevent_req_nterror(req, status); 705 return; 706@@ -941,7 +1037,24 @@ static void rpc_api_pipe_got_pdu(struct 707 "%s\n", 708 state->endianess?"little":"big", 709 state->pkt->drep[0]?"little":"big")); 710- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 711+ /* 712+ * TODO: do a real async disconnect ... 713+ * 714+ * For now do it sync... 715+ */ 716+ TALLOC_FREE(state->cli->transport); 717+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 718+ return; 719+ } 720+ 721+ if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) { 722+ /* 723+ * TODO: do a real async disconnect ... 724+ * 725+ * For now do it sync... 726+ */ 727+ TALLOC_FREE(state->cli->transport); 728+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 729 return; 730 } 731 732@@ -949,6 +1062,12 @@ static void rpc_api_pipe_got_pdu(struct 733 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) { 734 if (!data_blob_realloc(NULL, &state->reply_pdu, 735 state->reply_pdu_offset + rdata.length)) { 736+ /* 737+ * TODO: do a real async disconnect ... 738+ * 739+ * For now do it sync... 740+ */ 741+ TALLOC_FREE(state->cli->transport); 742 tevent_req_nterror(req, NT_STATUS_NO_MEMORY); 743 return; 744 } 745@@ -978,6 +1097,14 @@ static void rpc_api_pipe_got_pdu(struct 746 subreq = get_complete_frag_send(state, state->ev, state->cli, 747 state->call_id, 748 &state->incoming_frag); 749+ if (subreq == NULL) { 750+ /* 751+ * TODO: do a real async disconnect ... 752+ * 753+ * For now do it sync... 754+ */ 755+ TALLOC_FREE(state->cli->transport); 756+ } 757 if (tevent_req_nomem(subreq, req)) { 758 return; 759 } 760@@ -1247,7 +1374,7 @@ static NTSTATUS create_rpc_bind_req(TALL 761 auth->auth_type, 762 auth->auth_level, 763 0, /* auth_pad_length */ 764- 1, /* auth_context_id */ 765+ auth->auth_context_id, 766 &auth_token, 767 &auth_info); 768 if (!NT_STATUS_IS_OK(ret)) { 769@@ -1749,9 +1876,8 @@ static bool check_bind_response(const st 770 771 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx, 772 struct rpc_pipe_client *cli, 773- uint32 rpc_call_id, 774- enum dcerpc_AuthType auth_type, 775- enum dcerpc_AuthLevel auth_level, 776+ struct pipe_auth_data *auth, 777+ uint32_t rpc_call_id, 778 DATA_BLOB *pauth_blob, 779 DATA_BLOB *rpc_out) 780 { 781@@ -1761,10 +1887,10 @@ static NTSTATUS create_rpc_bind_auth3(TA 782 u.auth3._pad = 0; 783 784 status = dcerpc_push_dcerpc_auth(mem_ctx, 785- auth_type, 786- auth_level, 787+ auth->auth_type, 788+ auth->auth_level, 789 0, /* auth_pad_length */ 790- 1, /* auth_context_id */ 791+ auth->auth_context_id, 792 pauth_blob, 793 &u.auth3.auth_info); 794 if (!NT_STATUS_IS_OK(status)) { 795@@ -1794,9 +1920,8 @@ static NTSTATUS create_rpc_bind_auth3(TA 796 ********************************************************************/ 797 798 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx, 799- enum dcerpc_AuthType auth_type, 800- enum dcerpc_AuthLevel auth_level, 801- uint32 rpc_call_id, 802+ struct pipe_auth_data *auth, 803+ uint32_t rpc_call_id, 804 const struct ndr_syntax_id *abstract, 805 const struct ndr_syntax_id *transfer, 806 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */ 807@@ -1806,10 +1931,10 @@ static NTSTATUS create_rpc_alter_context 808 NTSTATUS status; 809 810 status = dcerpc_push_dcerpc_auth(mem_ctx, 811- auth_type, 812- auth_level, 813+ auth->auth_type, 814+ auth->auth_level, 815 0, /* auth_pad_length */ 816- 1, /* auth_context_id */ 817+ auth->auth_context_id, 818 pauth_blob, 819 &auth_info); 820 if (!NT_STATUS_IS_OK(status)) { 821@@ -1957,30 +2082,45 @@ static void rpc_pipe_bind_step_one_done( 822 rpc_pipe_bind_step_two_trigger(req); 823 return; 824 825- case DCERPC_AUTH_TYPE_NTLMSSP: 826- case DCERPC_AUTH_TYPE_SPNEGO: 827- case DCERPC_AUTH_TYPE_KRB5: 828- /* Paranoid lenght checks */ 829- if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH 830- + pkt->auth_length) { 831- tevent_req_nterror(req, 832- NT_STATUS_INFO_LENGTH_MISMATCH); 833+ default: 834+ if (pkt->auth_length == 0) { 835+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 836 return; 837 } 838 /* get auth credentials */ 839- status = dcerpc_pull_dcerpc_auth(talloc_tos(), 840- &pkt->u.bind_ack.auth_info, 841- &auth, false); 842+ status = dcerpc_pull_auth_trailer(pkt, talloc_tos(), 843+ &pkt->u.bind_ack.auth_info, 844+ &auth, NULL, true); 845 if (!NT_STATUS_IS_OK(status)) { 846 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n", 847 nt_errstr(status))); 848 tevent_req_nterror(req, status); 849 return; 850 } 851- break; 852 853- default: 854- goto err_out; 855+ if (auth.auth_type != pauth->auth_type) { 856+ DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n", 857+ auth.auth_type, pauth->auth_type)); 858+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 859+ return; 860+ } 861+ 862+ if (auth.auth_level != pauth->auth_level) { 863+ DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n", 864+ auth.auth_level, pauth->auth_level)); 865+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 866+ return; 867+ } 868+ 869+ if (auth.auth_context_id != pauth->auth_context_id) { 870+ DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n", 871+ (unsigned)auth.auth_context_id, 872+ (unsigned)pauth->auth_context_id)); 873+ tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 874+ return; 875+ } 876+ 877+ break; 878 } 879 880 /* 881@@ -2226,9 +2366,7 @@ static NTSTATUS rpc_bind_next_send(struc 882 /* Now prepare the alter context pdu. */ 883 data_blob_free(&state->rpc_out); 884 885- status = create_rpc_alter_context(state, 886- auth->auth_type, 887- auth->auth_level, 888+ status = create_rpc_alter_context(state, auth, 889 state->rpc_call_id, 890 &state->cli->abstract_syntax, 891 &state->cli->transfer_syntax, 892@@ -2261,10 +2399,8 @@ static NTSTATUS rpc_bind_finish_send(str 893 /* Now prepare the auth3 context pdu. */ 894 data_blob_free(&state->rpc_out); 895 896- status = create_rpc_bind_auth3(state, state->cli, 897+ status = create_rpc_bind_auth3(state, state->cli, auth, 898 state->rpc_call_id, 899- auth->auth_type, 900- auth->auth_level, 901 auth_token, 902 &state->rpc_out); 903 if (!NT_STATUS_IS_OK(status)) { 904@@ -2498,8 +2634,9 @@ static struct tevent_req *rpccli_bh_disc 905 /* 906 * TODO: do a real async disconnect ... 907 * 908- * For now the caller needs to free rpc_cli 909+ * For now we do it sync... 910 */ 911+ TALLOC_FREE(hs->rpc_cli->transport); 912 hs->rpc_cli = NULL; 913 914 tevent_req_done(req); 915@@ -2636,6 +2773,7 @@ NTSTATUS rpccli_ncalrpc_bind_data(TALLOC 916 917 result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM; 918 result->auth_level = DCERPC_AUTH_LEVEL_CONNECT; 919+ result->auth_context_id = 1; 920 921 result->user_name = talloc_strdup(result, ""); 922 result->domain = talloc_strdup(result, ""); 923@@ -2660,6 +2798,7 @@ NTSTATUS rpccli_anon_bind_data(TALLOC_CT 924 925 result->auth_type = DCERPC_AUTH_TYPE_NONE; 926 result->auth_level = DCERPC_AUTH_LEVEL_NONE; 927+ result->auth_context_id = 0; 928 929 result->user_name = talloc_strdup(result, ""); 930 result->domain = talloc_strdup(result, ""); 931@@ -2697,6 +2836,7 @@ static NTSTATUS rpccli_ntlmssp_bind_data 932 933 result->auth_type = auth_type; 934 result->auth_level = auth_level; 935+ result->auth_context_id = 1; 936 937 result->user_name = talloc_strdup(result, username); 938 result->domain = talloc_strdup(result, domain); 939@@ -2768,6 +2908,7 @@ NTSTATUS rpccli_schannel_bind_data(TALLO 940 941 result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL; 942 result->auth_level = auth_level; 943+ result->auth_context_id = 1; 944 945 result->user_name = talloc_strdup(result, ""); 946 result->domain = talloc_strdup(result, domain); 947@@ -3432,6 +3573,7 @@ NTSTATUS cli_rpc_pipe_open_krb5(struct c 948 } 949 auth->auth_type = DCERPC_AUTH_TYPE_KRB5; 950 auth->auth_level = auth_level; 951+ auth->auth_context_id = 1; 952 953 if (!username) { 954 username = ""; 955@@ -3502,6 +3644,7 @@ NTSTATUS cli_rpc_pipe_open_spnego_krb5(s 956 } 957 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO; 958 auth->auth_level = auth_level; 959+ auth->auth_context_id = 1; 960 961 if (!username) { 962 username = ""; 963@@ -3576,6 +3719,7 @@ NTSTATUS cli_rpc_pipe_open_spnego_ntlmss 964 } 965 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO; 966 auth->auth_level = auth_level; 967+ auth->auth_context_id = 1; 968 969 if (!username) { 970 username = ""; 971--- a/source4/rpc_server/dcesrv_auth.c 972+++ b/source4/rpc_server/dcesrv_auth.c 973@@ -46,7 +46,7 @@ bool dcesrv_auth_bind(struct dcesrv_call 974 NTSTATUS status; 975 uint32_t auth_length; 976 977- if (pkt->u.bind.auth_info.length == 0) { 978+ if (pkt->auth_length == 0) { 979 dce_conn->auth_state.auth_info = NULL; 980 return true; 981 } 982@@ -108,7 +108,7 @@ NTSTATUS dcesrv_auth_bind_ack(struct dce 983 struct dcesrv_connection *dce_conn = call->conn; 984 NTSTATUS status; 985 986- if (!call->conn->auth_state.gensec_security) { 987+ if (call->pkt.auth_length == 0) { 988 return NT_STATUS_OK; 989 } 990 991@@ -155,10 +155,16 @@ bool dcesrv_auth_auth3(struct dcesrv_cal 992 NTSTATUS status; 993 uint32_t auth_length; 994 995- /* We can't work without an existing gensec state, and an new blob to feed it */ 996- if (!dce_conn->auth_state.auth_info || 997- !dce_conn->auth_state.gensec_security || 998- pkt->u.auth3.auth_info.length == 0) { 999+ if (pkt->auth_length == 0) { 1000+ return false; 1001+ } 1002+ 1003+ if (!dce_conn->auth_state.auth_info) { 1004+ return false; 1005+ } 1006+ 1007+ /* We can't work without an existing gensec state */ 1008+ if (!dce_conn->auth_state.gensec_security) { 1009 return false; 1010 } 1011 1012@@ -203,7 +209,7 @@ bool dcesrv_auth_alter(struct dcesrv_cal 1013 uint32_t auth_length; 1014 1015 /* on a pure interface change there is no auth blob */ 1016- if (pkt->u.alter.auth_info.length == 0) { 1017+ if (pkt->auth_length == 0) { 1018 return true; 1019 } 1020 1021@@ -238,8 +244,7 @@ NTSTATUS dcesrv_auth_alter_ack(struct dc 1022 1023 /* on a pure interface change there is no auth_info structure 1024 setup */ 1025- if (!call->conn->auth_state.auth_info || 1026- dce_conn->auth_state.auth_info->credentials.length == 0) { 1027+ if (call->pkt.auth_length == 0) { 1028 return NT_STATUS_OK; 1029 } 1030 1031@@ -315,6 +320,11 @@ bool dcesrv_auth_request(struct dcesrv_c 1032 return false; 1033 } 1034 1035+ if (pkt->auth_length == 0) { 1036+ DEBUG(1,("dcesrv_auth_request: unexpected auth_length of 0\n")); 1037+ return false; 1038+ } 1039+ 1040 status = dcerpc_pull_auth_trailer(pkt, call, 1041 &pkt->u.request.stub_and_verifier, 1042 &auth, &auth_length, false); 1043--- a/source4/librpc/rpc/dcerpc.c 1044+++ b/source4/librpc/rpc/dcerpc.c 1045@@ -701,6 +701,14 @@ static NTSTATUS ncacn_pull_request_auth( 1046 return NT_STATUS_INVALID_LEVEL; 1047 } 1048 1049+ if (pkt->auth_length == 0) { 1050+ return NT_STATUS_INVALID_NETWORK_RESPONSE; 1051+ } 1052+ 1053+ if (c->security_state.generic_state == NULL) { 1054+ return NT_STATUS_INTERNAL_ERROR; 1055+ } 1056+ 1057 status = dcerpc_pull_auth_trailer(pkt, mem_ctx, 1058 &pkt->u.response.stub_and_verifier, 1059 &auth, &auth_length, false); 1060@@ -1074,7 +1082,7 @@ static void dcerpc_bind_recv_handler(str 1061 } 1062 1063 /* the bind_ack might contain a reply set of credentials */ 1064- if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) { 1065+ if (conn->security_state.auth_info && pkt->auth_length) { 1066 NTSTATUS status; 1067 uint32_t auth_length; 1068 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info, 1069@@ -1847,8 +1855,7 @@ static void dcerpc_alter_recv_handler(st 1070 } 1071 1072 /* the alter_resp might contain a reply set of credentials */ 1073- if (recv_pipe->conn->security_state.auth_info && 1074- pkt->u.alter_resp.auth_info.length) { 1075+ if (recv_pipe->conn->security_state.auth_info && pkt->auth_length) { 1076 struct dcecli_connection *conn = recv_pipe->conn; 1077 NTSTATUS status; 1078 uint32_t auth_length; 1079--- a/source3/librpc/rpc/dcerpc.h 1080+++ b/source3/librpc/rpc/dcerpc.h 1081@@ -42,6 +42,7 @@ struct pipe_auth_data { 1082 bool verified_bitmask1; 1083 1084 void *auth_ctx; 1085+ uint32_t auth_context_id; 1086 1087 /* Only the client code uses these 3 for now */ 1088 char *domain; 1089@@ -71,10 +72,6 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_ 1090 uint32_t auth_context_id, 1091 const DATA_BLOB *credentials, 1092 DATA_BLOB *blob); 1093-NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, 1094- const DATA_BLOB *blob, 1095- struct dcerpc_auth *r, 1096- bool bigendian); 1097 NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, 1098 size_t header_len, size_t data_left, 1099 size_t max_xmit_frag, size_t pad_alignment, 1100@@ -85,9 +82,8 @@ NTSTATUS dcerpc_add_auth_footer(struct p 1101 NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, 1102 struct ncacn_packet *pkt, 1103 DATA_BLOB *pkt_trailer, 1104- size_t header_size, 1105- DATA_BLOB *raw_pkt, 1106- size_t *pad_len); 1107+ uint8_t header_size, 1108+ DATA_BLOB *raw_pkt); 1109 1110 /* The following definitions come from librpc/rpc/rpc_common.c */ 1111 1112--- a/source3/rpc_server/srv_pipe.c 1113+++ b/source3/rpc_server/srv_pipe.c 1114@@ -42,6 +42,7 @@ 1115 #include "auth.h" 1116 #include "ntdomain.h" 1117 #include "rpc_server/srv_pipe.h" 1118+#include "../librpc/gen_ndr/ndr_dcerpc.h" 1119 #include "../librpc/ndr/ndr_dcerpc.h" 1120 1121 #undef DBGC_CLASS 1122@@ -270,10 +271,14 @@ static bool setup_bind_nak(struct pipes_ 1123 p->out_data.data_sent_length = 0; 1124 p->out_data.current_pdu_sent = 0; 1125 1126+ set_incoming_fault(p); 1127 TALLOC_FREE(p->auth.auth_ctx); 1128 p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE; 1129 p->auth.auth_type = DCERPC_AUTH_TYPE_NONE; 1130 p->pipe_bound = False; 1131+ p->allow_bind = false; 1132+ p->allow_alter = false; 1133+ p->allow_auth3 = false; 1134 1135 return True; 1136 } 1137@@ -339,16 +344,46 @@ static bool check_bind_req(struct pipes_ 1138 DEBUG(3,("check_bind_req for %s\n", 1139 get_pipe_name_from_syntax(talloc_tos(), abstract))); 1140 1141+ ok = ndr_syntax_id_equal(transfer, &ndr_transfer_syntax); 1142+ if (!ok) { 1143+ DEBUG(1,("check_bind_req unknown transfer syntax for " 1144+ "%s context_id=%u\n", 1145+ get_pipe_name_from_syntax(talloc_tos(), abstract), 1146+ (unsigned)context_id)); 1147+ return false; 1148+ } 1149+ 1150+ for (context_fns = p->contexts; 1151+ context_fns != NULL; 1152+ context_fns = context_fns->next) 1153+ { 1154+ if (context_fns->context_id != context_id) { 1155+ continue; 1156+ } 1157+ 1158+ ok = ndr_syntax_id_equal(&context_fns->syntax, 1159+ abstract); 1160+ if (ok) { 1161+ return true; 1162+ } 1163+ 1164+ DEBUG(1,("check_bind_req: changing abstract syntax for " 1165+ "%s context_id=%u into %s not supported\n", 1166+ get_pipe_name_from_syntax(talloc_tos(), &context_fns->syntax), 1167+ (unsigned)context_id, 1168+ get_pipe_name_from_syntax(talloc_tos(), abstract))); 1169+ return false; 1170+ } 1171+ 1172 /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */ 1173- if (rpc_srv_pipe_exists_by_id(abstract) && 1174- ndr_syntax_id_equal(transfer, &ndr_transfer_syntax)) { 1175- DEBUG(3, ("check_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", 1176- rpc_srv_get_pipe_cli_name(abstract), 1177- rpc_srv_get_pipe_srv_name(abstract))); 1178- } else { 1179+ if (!rpc_srv_pipe_exists_by_id(abstract)) { 1180 return false; 1181 } 1182 1183+ DEBUG(3, ("check_bind_req: %s -> %s rpc service\n", 1184+ rpc_srv_get_pipe_cli_name(abstract), 1185+ rpc_srv_get_pipe_srv_name(abstract))); 1186+ 1187 context_fns = SMB_MALLOC_P(struct pipe_rpc_fns); 1188 if (context_fns == NULL) { 1189 DEBUG(0,("check_bind_req: malloc() failed!\n")); 1190@@ -447,6 +482,7 @@ static bool pipe_spnego_auth_bind(struct 1191 1192 p->auth.auth_ctx = spnego_ctx; 1193 p->auth.auth_type = DCERPC_AUTH_TYPE_SPNEGO; 1194+ p->auth.auth_context_id = auth_info->auth_context_id; 1195 1196 DEBUG(10, ("SPNEGO auth started\n")); 1197 1198@@ -557,6 +593,7 @@ static bool pipe_schannel_auth_bind(stru 1199 /* We're finished with this bind - no more packets. */ 1200 p->auth.auth_ctx = schannel_auth; 1201 p->auth.auth_type = DCERPC_AUTH_TYPE_SCHANNEL; 1202+ p->auth.auth_context_id = auth_info->auth_context_id; 1203 1204 p->pipe_bound = True; 1205 1206@@ -601,6 +638,7 @@ static bool pipe_ntlmssp_auth_bind(struc 1207 1208 p->auth.auth_ctx = ntlmssp_state; 1209 p->auth.auth_type = DCERPC_AUTH_TYPE_NTLMSSP; 1210+ p->auth.auth_context_id = auth_info->auth_context_id; 1211 1212 DEBUG(10, (__location__ ": NTLMSSP auth started\n")); 1213 1214@@ -776,6 +814,11 @@ static NTSTATUS pipe_auth_verify_final(s 1215 void *mech_ctx; 1216 NTSTATUS status; 1217 1218+ if (p->auth.auth_type == DCERPC_AUTH_TYPE_NONE) { 1219+ p->pipe_bound = true; 1220+ return NT_STATUS_OK; 1221+ } 1222+ 1223 switch (p->auth.auth_type) { 1224 case DCERPC_AUTH_TYPE_NTLMSSP: 1225 ntlmssp_ctx = talloc_get_type_abort(p->auth.auth_ctx, 1226@@ -867,16 +910,38 @@ static bool api_pipe_bind_req(struct pip 1227 DATA_BLOB auth_resp = data_blob_null; 1228 DATA_BLOB auth_blob = data_blob_null; 1229 1230- /* No rebinds on a bound pipe - use alter context. */ 1231- if (p->pipe_bound) { 1232- DEBUG(2,("api_pipe_bind_req: rejecting bind request on bound " 1233- "pipe %s.\n", 1234- get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); 1235+ if (!p->allow_bind) { 1236+ DEBUG(2,("Pipe not in allow bind state\n")); 1237 return setup_bind_nak(p, pkt); 1238 } 1239+ p->allow_bind = false; 1240+ 1241+ status = dcerpc_verify_ncacn_packet_header(pkt, 1242+ DCERPC_PKT_BIND, 1243+ pkt->u.bind.auth_info.length, 1244+ 0, /* required flags */ 1245+ DCERPC_PFC_FLAG_FIRST | 1246+ DCERPC_PFC_FLAG_LAST | 1247+ DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN | 1248+ 0x08 | /* this is not defined, but should be ignored */ 1249+ DCERPC_PFC_FLAG_CONC_MPX | 1250+ DCERPC_PFC_FLAG_DID_NOT_EXECUTE | 1251+ DCERPC_PFC_FLAG_MAYBE | 1252+ DCERPC_PFC_FLAG_OBJECT_UUID); 1253+ if (!NT_STATUS_IS_OK(status)) { 1254+ DEBUG(1, ("api_pipe_bind_req: invalid pdu: %s\n", 1255+ nt_errstr(status))); 1256+ NDR_PRINT_DEBUG(ncacn_packet, pkt); 1257+ goto err_exit; 1258+ } 1259 1260 if (pkt->u.bind.num_contexts == 0) { 1261- DEBUG(0, ("api_pipe_bind_req: no rpc contexts around\n")); 1262+ DEBUG(1, ("api_pipe_bind_req: no rpc contexts around\n")); 1263+ goto err_exit; 1264+ } 1265+ 1266+ if (pkt->u.bind.ctx_list[0].num_transfer_syntaxes == 0) { 1267+ DEBUG(1, ("api_pipe_bind_req: no transfer syntaxes around\n")); 1268 goto err_exit; 1269 } 1270 1271@@ -960,25 +1025,12 @@ static bool api_pipe_bind_req(struct pip 1272 * Check if this is an authenticated bind request. 1273 */ 1274 if (pkt->auth_length) { 1275- /* Quick length check. Won't catch a bad auth footer, 1276- * prevents overrun. */ 1277- 1278- if (pkt->frag_length < RPC_HEADER_LEN + 1279- DCERPC_AUTH_TRAILER_LENGTH + 1280- pkt->auth_length) { 1281- DEBUG(0,("api_pipe_bind_req: auth_len (%u) " 1282- "too long for fragment %u.\n", 1283- (unsigned int)pkt->auth_length, 1284- (unsigned int)pkt->frag_length)); 1285- goto err_exit; 1286- } 1287- 1288 /* 1289 * Decode the authentication verifier. 1290 */ 1291- status = dcerpc_pull_dcerpc_auth(pkt, 1292- &pkt->u.bind.auth_info, 1293- &auth_info, p->endian); 1294+ status = dcerpc_pull_auth_trailer(pkt, pkt, 1295+ &pkt->u.bind.auth_info, 1296+ &auth_info, NULL, true); 1297 if (!NT_STATUS_IS_OK(status)) { 1298 DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n")); 1299 goto err_exit; 1300@@ -1072,6 +1124,7 @@ static bool api_pipe_bind_req(struct pip 1301 p->pipe_bound = True; 1302 /* The session key was initialized from the SMB 1303 * session in make_internal_rpc_pipe_p */ 1304+ p->auth.auth_context_id = 0; 1305 } 1306 1307 ZERO_STRUCT(u.bind_ack); 1308@@ -1113,15 +1166,15 @@ static bool api_pipe_bind_req(struct pip 1309 if (!NT_STATUS_IS_OK(status)) { 1310 DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n", 1311 nt_errstr(status))); 1312+ goto err_exit; 1313 } 1314 1315 if (auth_resp.length) { 1316- 1317 status = dcerpc_push_dcerpc_auth(pkt, 1318 auth_type, 1319 auth_info.auth_level, 1320- 0, 1321- 1, /* auth_context_id */ 1322+ 0, /* pad_len */ 1323+ p->auth.auth_context_id, 1324 &auth_resp, 1325 &auth_blob); 1326 if (!NT_STATUS_IS_OK(status)) { 1327@@ -1152,6 +1205,22 @@ static bool api_pipe_bind_req(struct pip 1328 p->out_data.current_pdu_sent = 0; 1329 1330 TALLOC_FREE(auth_blob.data); 1331+ 1332+ if (bind_ack_ctx.result == 0) { 1333+ p->allow_alter = true; 1334+ p->allow_auth3 = true; 1335+ if (p->auth.auth_type == DCERPC_AUTH_TYPE_NONE) { 1336+ status = pipe_auth_verify_final(p); 1337+ if (!NT_STATUS_IS_OK(status)) { 1338+ DEBUG(0, ("pipe_auth_verify_final failed: %s\n", 1339+ nt_errstr(status))); 1340+ goto err_exit; 1341+ } 1342+ } 1343+ } else { 1344+ goto err_exit; 1345+ } 1346+ 1347 return True; 1348 1349 err_exit: 1350@@ -1176,18 +1245,39 @@ bool api_pipe_bind_auth3(struct pipes_st 1351 1352 DEBUG(5, ("api_pipe_bind_auth3: decode request. %d\n", __LINE__)); 1353 1354- if (pkt->auth_length == 0) { 1355- DEBUG(0, ("No auth field sent for bind request!\n")); 1356+ if (!p->allow_auth3) { 1357+ DEBUG(1, ("Pipe not in allow auth3 state.\n")); 1358 goto err; 1359 } 1360 1361- /* Ensure there's enough data for an authenticated request. */ 1362- if (pkt->frag_length < RPC_HEADER_LEN 1363- + DCERPC_AUTH_TRAILER_LENGTH 1364- + pkt->auth_length) { 1365- DEBUG(0,("api_pipe_ntlmssp_auth_process: auth_len " 1366- "%u is too large.\n", 1367- (unsigned int)pkt->auth_length)); 1368+ status = dcerpc_verify_ncacn_packet_header(pkt, 1369+ DCERPC_PKT_AUTH3, 1370+ pkt->u.auth3.auth_info.length, 1371+ 0, /* required flags */ 1372+ DCERPC_PFC_FLAG_FIRST | 1373+ DCERPC_PFC_FLAG_LAST | 1374+ DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN | 1375+ 0x08 | /* this is not defined, but should be ignored */ 1376+ DCERPC_PFC_FLAG_CONC_MPX | 1377+ DCERPC_PFC_FLAG_DID_NOT_EXECUTE | 1378+ DCERPC_PFC_FLAG_MAYBE | 1379+ DCERPC_PFC_FLAG_OBJECT_UUID); 1380+ if (!NT_STATUS_IS_OK(status)) { 1381+ DEBUG(1, ("api_pipe_bind_auth3: invalid pdu: %s\n", 1382+ nt_errstr(status))); 1383+ NDR_PRINT_DEBUG(ncacn_packet, pkt); 1384+ goto err; 1385+ } 1386+ 1387+ /* We can only finish if the pipe is unbound for now */ 1388+ if (p->pipe_bound) { 1389+ DEBUG(0, (__location__ ": Pipe already bound, " 1390+ "AUTH3 not supported!\n")); 1391+ goto err; 1392+ } 1393+ 1394+ if (pkt->auth_length == 0) { 1395+ DEBUG(1, ("No auth field sent for auth3 request!\n")); 1396 goto err; 1397 } 1398 1399@@ -1195,9 +1285,9 @@ bool api_pipe_bind_auth3(struct pipes_st 1400 * Decode the authentication verifier response. 1401 */ 1402 1403- status = dcerpc_pull_dcerpc_auth(pkt, 1404- &pkt->u.auth3.auth_info, 1405- &auth_info, p->endian); 1406+ status = dcerpc_pull_auth_trailer(pkt, pkt, 1407+ &pkt->u.auth3.auth_info, 1408+ &auth_info, NULL, true); 1409 if (!NT_STATUS_IS_OK(status)) { 1410 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n")); 1411 goto err; 1412@@ -1215,6 +1305,21 @@ bool api_pipe_bind_auth3(struct pipes_st 1413 goto err; 1414 } 1415 1416+ if (auth_info.auth_level != p->auth.auth_level) { 1417+ DEBUG(1, ("Auth level mismatch! Client sent %d, " 1418+ "but auth was started as level %d!\n", 1419+ auth_info.auth_level, p->auth.auth_level)); 1420+ goto err; 1421+ } 1422+ 1423+ if (auth_info.auth_context_id != p->auth.auth_context_id) { 1424+ DEBUG(0, ("Auth context id mismatch! Client sent %u, " 1425+ "but auth was started as level %u!\n", 1426+ (unsigned)auth_info.auth_context_id, 1427+ (unsigned)p->auth.auth_context_id)); 1428+ goto err; 1429+ } 1430+ 1431 switch (auth_info.auth_type) { 1432 case DCERPC_AUTH_TYPE_NTLMSSP: 1433 ntlmssp_ctx = talloc_get_type_abort(p->auth.auth_ctx, 1434@@ -1267,6 +1372,10 @@ bool api_pipe_bind_auth3(struct pipes_st 1435 return true; 1436 1437 err: 1438+ p->pipe_bound = false; 1439+ p->allow_bind = false; 1440+ p->allow_alter = false; 1441+ p->allow_auth3 = false; 1442 1443 TALLOC_FREE(p->auth.auth_ctx); 1444 return false; 1445@@ -1284,7 +1393,7 @@ static bool api_pipe_alter_context(struc 1446 uint16 assoc_gid; 1447 NTSTATUS status; 1448 union dcerpc_payload u; 1449- struct dcerpc_ack_ctx bind_ack_ctx; 1450+ struct dcerpc_ack_ctx alter_ack_ctx; 1451 DATA_BLOB auth_resp = data_blob_null; 1452 DATA_BLOB auth_blob = data_blob_null; 1453 int pad_len = 0; 1454@@ -1294,8 +1403,42 @@ static bool api_pipe_alter_context(struc 1455 1456 DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__)); 1457 1458- if (pkt->u.bind.assoc_group_id != 0) { 1459- assoc_gid = pkt->u.bind.assoc_group_id; 1460+ if (!p->allow_alter) { 1461+ DEBUG(1, ("Pipe not in allow alter state.\n")); 1462+ goto err_exit; 1463+ } 1464+ 1465+ status = dcerpc_verify_ncacn_packet_header(pkt, 1466+ DCERPC_PKT_ALTER, 1467+ pkt->u.alter.auth_info.length, 1468+ 0, /* required flags */ 1469+ DCERPC_PFC_FLAG_FIRST | 1470+ DCERPC_PFC_FLAG_LAST | 1471+ DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN | 1472+ 0x08 | /* this is not defined, but should be ignored */ 1473+ DCERPC_PFC_FLAG_CONC_MPX | 1474+ DCERPC_PFC_FLAG_DID_NOT_EXECUTE | 1475+ DCERPC_PFC_FLAG_MAYBE | 1476+ DCERPC_PFC_FLAG_OBJECT_UUID); 1477+ if (!NT_STATUS_IS_OK(status)) { 1478+ DEBUG(1, ("api_pipe_alter_context: invalid pdu: %s\n", 1479+ nt_errstr(status))); 1480+ NDR_PRINT_DEBUG(ncacn_packet, pkt); 1481+ goto err_exit; 1482+ } 1483+ 1484+ if (pkt->u.alter.num_contexts == 0) { 1485+ DEBUG(1, ("api_pipe_alter_context: no rpc contexts around\n")); 1486+ goto err_exit; 1487+ } 1488+ 1489+ if (pkt->u.alter.ctx_list[0].num_transfer_syntaxes == 0) { 1490+ DEBUG(1, ("api_pipe_alter_context: no transfer syntaxes around\n")); 1491+ goto err_exit; 1492+ } 1493+ 1494+ if (pkt->u.alter.assoc_group_id != 0) { 1495+ assoc_gid = pkt->u.alter.assoc_group_id; 1496 } else { 1497 assoc_gid = 0x53f0; 1498 } 1499@@ -1305,59 +1448,45 @@ static bool api_pipe_alter_context(struc 1500 */ 1501 1502 /* If the requested abstract synt uuid doesn't match our client pipe, 1503- reject the bind_ack & set the transfer interface synt to all 0's, 1504+ reject the alter_ack & set the transfer interface synt to all 0's, 1505 ver 0 (observed when NT5 attempts to bind to abstract interfaces 1506 unknown to NT4) 1507 Needed when adding entries to a DACL from NT5 - SK */ 1508 1509 if (check_bind_req(p, 1510- &pkt->u.bind.ctx_list[0].abstract_syntax, 1511- &pkt->u.bind.ctx_list[0].transfer_syntaxes[0], 1512- pkt->u.bind.ctx_list[0].context_id)) { 1513- 1514- bind_ack_ctx.result = 0; 1515- bind_ack_ctx.reason = 0; 1516- bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0]; 1517+ &pkt->u.alter.ctx_list[0].abstract_syntax, 1518+ &pkt->u.alter.ctx_list[0].transfer_syntaxes[0], 1519+ pkt->u.alter.ctx_list[0].context_id)) { 1520+ 1521+ alter_ack_ctx.result = 0; 1522+ alter_ack_ctx.reason = 0; 1523+ alter_ack_ctx.syntax = pkt->u.alter.ctx_list[0].transfer_syntaxes[0]; 1524 } else { 1525- p->pipe_bound = False; 1526 /* Rejection reason: abstract syntax not supported */ 1527- bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT; 1528- bind_ack_ctx.reason = DCERPC_BIND_REASON_ASYNTAX; 1529- bind_ack_ctx.syntax = null_ndr_syntax_id; 1530+ alter_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT; 1531+ alter_ack_ctx.reason = DCERPC_BIND_REASON_ASYNTAX; 1532+ alter_ack_ctx.syntax = null_ndr_syntax_id; 1533 } 1534 1535 /* 1536 * Check if this is an authenticated alter context request. 1537 */ 1538 if (pkt->auth_length) { 1539- /* Quick length check. Won't catch a bad auth footer, 1540- * prevents overrun. */ 1541- 1542- if (pkt->frag_length < RPC_HEADER_LEN + 1543- DCERPC_AUTH_TRAILER_LENGTH + 1544- pkt->auth_length) { 1545- DEBUG(0,("api_pipe_alter_context: auth_len (%u) " 1546- "too long for fragment %u.\n", 1547- (unsigned int)pkt->auth_length, 1548- (unsigned int)pkt->frag_length )); 1549+ /* We can only finish if the pipe is unbound for now */ 1550+ if (p->pipe_bound) { 1551+ DEBUG(0, (__location__ ": Pipe already bound, " 1552+ "Altering Context not yet supported!\n")); 1553 goto err_exit; 1554 } 1555 1556- status = dcerpc_pull_dcerpc_auth(pkt, 1557- &pkt->u.bind.auth_info, 1558- &auth_info, p->endian); 1559+ status = dcerpc_pull_auth_trailer(pkt, pkt, 1560+ &pkt->u.alter.auth_info, 1561+ &auth_info, NULL, true); 1562 if (!NT_STATUS_IS_OK(status)) { 1563 DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n")); 1564 goto err_exit; 1565 } 1566 1567- /* We can only finish if the pipe is unbound for now */ 1568- if (p->pipe_bound) { 1569- DEBUG(0, (__location__ ": Pipe already bound, " 1570- "Altering Context not yet supported!\n")); 1571- goto err_exit; 1572- } 1573- 1574 if (auth_info.auth_type != p->auth.auth_type) { 1575 DEBUG(0, ("Auth type mismatch! Client sent %d, " 1576 "but auth was started as type %d!\n", 1577@@ -1365,6 +1494,20 @@ static bool api_pipe_alter_context(struc 1578 goto err_exit; 1579 } 1580 1581+ if (auth_info.auth_level != p->auth.auth_level) { 1582+ DEBUG(0, ("Auth level mismatch! Client sent %d, " 1583+ "but auth was started as level %d!\n", 1584+ auth_info.auth_level, p->auth.auth_level)); 1585+ goto err_exit; 1586+ } 1587+ 1588+ if (auth_info.auth_context_id != p->auth.auth_context_id) { 1589+ DEBUG(0, ("Auth context id mismatch! Client sent %u, " 1590+ "but auth was started as level %u!\n", 1591+ (unsigned)auth_info.auth_context_id, 1592+ (unsigned)p->auth.auth_context_id)); 1593+ goto err_exit; 1594+ } 1595 1596 switch (auth_info.auth_type) { 1597 case DCERPC_AUTH_TYPE_SPNEGO: 1598@@ -1431,7 +1574,7 @@ static bool api_pipe_alter_context(struc 1599 u.alter_resp.secondary_address_size = 1; 1600 1601 u.alter_resp.num_results = 1; 1602- u.alter_resp.ctx_list = &bind_ack_ctx; 1603+ u.alter_resp.ctx_list = &alter_ack_ctx; 1604 1605 /* NOTE: We leave the auth_info empty so we can calculate the padding 1606 * later and then append the auth_info --simo */ 1607@@ -1451,8 +1594,9 @@ static bool api_pipe_alter_context(struc 1608 &u, 1609 &p->out_data.frag); 1610 if (!NT_STATUS_IS_OK(status)) { 1611- DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n", 1612+ DEBUG(0, ("Failed to marshall alter_resp packet. (%s)\n", 1613 nt_errstr(status))); 1614+ goto err_exit; 1615 } 1616 1617 if (auth_resp.length) { 1618@@ -1469,7 +1613,7 @@ static bool api_pipe_alter_context(struc 1619 auth_info.auth_type, 1620 auth_info.auth_level, 1621 pad_len, 1622- 1, /* auth_context_id */ 1623+ p->auth.auth_context_id, 1624 &auth_resp, 1625 &auth_blob); 1626 if (!NT_STATUS_IS_OK(status)) { 1627@@ -1618,6 +1762,7 @@ static bool api_pipe_request(struct pipe 1628 1629 if (!srv_pipe_check_verification_trailer(p, pkt, pipe_fns)) { 1630 DEBUG(1, ("srv_pipe_check_verification_trailer: failed\n")); 1631+ set_incoming_fault(p); 1632 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED)); 1633 data_blob_free(&p->out_data.rdata); 1634 TALLOC_FREE(frame); 1635@@ -1756,7 +1901,11 @@ void set_incoming_fault(struct pipes_str 1636 data_blob_free(&p->in_data.data); 1637 p->in_data.pdu_needed_len = 0; 1638 p->in_data.pdu.length = 0; 1639- p->fault_state = DCERPC_FAULT_CANT_PERFORM; 1640+ p->fault_state = DCERPC_NCA_S_PROTO_ERROR; 1641+ 1642+ p->allow_alter = false; 1643+ p->allow_auth3 = false; 1644+ p->pipe_bound = false; 1645 1646 DEBUG(10, ("Setting fault state\n")); 1647 } 1648@@ -1767,7 +1916,6 @@ static NTSTATUS dcesrv_auth_request(stru 1649 { 1650 NTSTATUS status; 1651 size_t hdr_size = DCERPC_REQUEST_LENGTH; 1652- size_t pad_len; 1653 1654 DEBUG(10, ("Checking request auth.\n")); 1655 1656@@ -1778,25 +1926,11 @@ static NTSTATUS dcesrv_auth_request(stru 1657 /* in case of sealing this function will unseal the data in place */ 1658 status = dcerpc_check_auth(auth, pkt, 1659 &pkt->u.request.stub_and_verifier, 1660- hdr_size, raw_pkt, 1661- &pad_len); 1662+ hdr_size, raw_pkt); 1663 if (!NT_STATUS_IS_OK(status)) { 1664 return status; 1665 } 1666 1667- 1668- /* remove padding and auth trailer, 1669- * this way the caller will get just the data */ 1670- if (pkt->auth_length) { 1671- size_t trail_len = pad_len 1672- + DCERPC_AUTH_TRAILER_LENGTH 1673- + pkt->auth_length; 1674- if (pkt->u.request.stub_and_verifier.length < trail_len) { 1675- return NT_STATUS_INFO_LENGTH_MISMATCH; 1676- } 1677- pkt->u.request.stub_and_verifier.length -= trail_len; 1678- } 1679- 1680 return NT_STATUS_OK; 1681 } 1682 1683@@ -1816,6 +1950,29 @@ static bool process_request_pdu(struct p 1684 return False; 1685 } 1686 1687+ /* 1688+ * We don't ignore DCERPC_PFC_FLAG_PENDING_CANCEL. 1689+ * TODO: we can reject it with DCERPC_FAULT_NO_CALL_ACTIVE later. 1690+ */ 1691+ status = dcerpc_verify_ncacn_packet_header(pkt, 1692+ DCERPC_PKT_REQUEST, 1693+ pkt->u.request.stub_and_verifier.length, 1694+ 0, /* required_flags */ 1695+ DCERPC_PFC_FLAG_FIRST | 1696+ DCERPC_PFC_FLAG_LAST | 1697+ 0x08 | /* this is not defined, but should be ignored */ 1698+ DCERPC_PFC_FLAG_CONC_MPX | 1699+ DCERPC_PFC_FLAG_DID_NOT_EXECUTE | 1700+ DCERPC_PFC_FLAG_MAYBE | 1701+ DCERPC_PFC_FLAG_OBJECT_UUID); 1702+ if (!NT_STATUS_IS_OK(status)) { 1703+ DEBUG(1, ("process_request_pdu: invalid pdu: %s\n", 1704+ nt_errstr(status))); 1705+ NDR_PRINT_DEBUG(ncacn_packet, pkt); 1706+ set_incoming_fault(p); 1707+ return false; 1708+ } 1709+ 1710 /* Store the opnum */ 1711 p->opnum = pkt->u.request.opnum; 1712 1713@@ -2065,7 +2222,7 @@ done: 1714 "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(), 1715 &p->syntax))); 1716 set_incoming_fault(p); 1717- setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); 1718+ setup_fault_pdu(p, NT_STATUS(DCERPC_NCA_S_PROTO_ERROR)); 1719 TALLOC_FREE(pkt); 1720 } else { 1721 /* 1722--- a/source3/include/ntdomain.h 1723+++ b/source3/include/ntdomain.h 1724@@ -135,6 +135,13 @@ struct pipes_struct { 1725 bool pipe_bound; 1726 1727 /* 1728+ * States we can be in. 1729+ */ 1730+ bool allow_alter; 1731+ bool allow_bind; 1732+ bool allow_auth3; 1733+ 1734+ /* 1735 * Set the DCERPC_FAULT to return. 1736 */ 1737 1738--- a/source3/rpc_server/rpc_ncacn_np.c 1739+++ b/source3/rpc_server/rpc_ncacn_np.c 1740@@ -171,6 +171,7 @@ struct pipes_struct *make_internal_rpc_p 1741 1742 p->syntax = *syntax; 1743 p->transport = NCALRPC; 1744+ p->allow_bind = true; 1745 1746 DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n", 1747 get_pipe_name_from_syntax(talloc_tos(), syntax), pipes_open)); 1748@@ -780,6 +781,7 @@ static NTSTATUS rpc_pipe_open_external(T 1749 } 1750 result->auth->auth_type = DCERPC_AUTH_TYPE_NONE; 1751 result->auth->auth_level = DCERPC_AUTH_LEVEL_NONE; 1752+ result->auth->auth_context_id = 0; 1753 1754 status = rpccli_anon_bind_data(result, &auth); 1755 if (!NT_STATUS_IS_OK(status)) { 1756--- a/source3/rpc_server/rpc_server.c 1757+++ b/source3/rpc_server/rpc_server.c 1758@@ -102,6 +102,7 @@ static int make_server_pipes_struct(TALL 1759 p->syntax = id; 1760 p->transport = transport; 1761 p->ncalrpc_as_system = ncalrpc_as_system; 1762+ p->allow_bind = true; 1763 1764 p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p); 1765 if (!p->mem_ctx) { 1766@@ -663,6 +664,12 @@ static void named_pipe_packet_done(struc 1767 goto fail; 1768 } 1769 1770+ if (npc->p->fault_state != 0) { 1771+ DEBUG(2, ("Disconnect after fault\n")); 1772+ sys_errno = EINVAL; 1773+ goto fail; 1774+ } 1775+ 1776 /* clear out any data that may have been left around */ 1777 npc->count = 0; 1778 TALLOC_FREE(npc->iov); 1779@@ -1391,6 +1398,12 @@ static void dcerpc_ncacn_packet_done(str 1780 goto fail; 1781 } 1782 1783+ if (ncacn_conn->p->fault_state != 0) { 1784+ DEBUG(2, ("Disconnect after fault\n")); 1785+ sys_errno = EINVAL; 1786+ goto fail; 1787+ } 1788+ 1789 /* clear out any data that may have been left around */ 1790 ncacn_conn->count = 0; 1791 TALLOC_FREE(ncacn_conn->iov); 1792