Changeset 919 for vendor/current/source3/rpc_client
- Timestamp:
- Jun 9, 2016, 2:17:22 PM (9 years ago)
- Location:
- vendor/current/source3/rpc_client
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/rpc_client/cli_pipe.c
r860 r919 29 29 #include "ntlmssp_wrap.h" 30 30 #include "librpc/gen_ndr/ndr_dcerpc.h" 31 #include "librpc/gen_ndr/ndr_netlogon_c.h" 31 32 #include "librpc/rpc/dcerpc.h" 32 33 #include "librpc/crypto/gse.h" … … 400 401 DATA_BLOB *pdu, 401 402 uint8_t expected_pkt_type, 403 uint32_t call_id, 402 404 DATA_BLOB *rdata, 403 405 DATA_BLOB *reply_pdu) 404 406 { 405 struct dcerpc_response *r; 407 const struct dcerpc_response *r = NULL; 408 DATA_BLOB tmp_stub = data_blob_null; 406 409 NTSTATUS ret = NT_STATUS_OK; 407 size_t pad_len = 0;408 410 409 411 /* … … 413 415 *rdata = *pdu; 414 416 417 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) && 418 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) { 419 /* 420 * TODO: do we still need this hack which was introduced 421 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0. 422 * 423 * I don't even know what AS/U might be... 424 */ 425 DEBUG(5, (__location__ ": bug in server (AS/U?), setting " 426 "fragment first/last ON.\n")); 427 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; 428 } 429 415 430 /* Ensure we have the correct type. */ 416 431 switch (pkt->ptype) { 432 case DCERPC_PKT_BIND_NAK: 433 DEBUG(1, (__location__ ": Bind NACK received from %s!\n", 434 rpccli_pipe_txt(talloc_tos(), cli))); 435 436 ret = dcerpc_verify_ncacn_packet_header(pkt, 437 DCERPC_PKT_BIND_NAK, 438 0, /* max_auth_info */ 439 DCERPC_PFC_FLAG_FIRST | 440 DCERPC_PFC_FLAG_LAST, 441 0); /* optional flags */ 442 if (!NT_STATUS_IS_OK(ret)) { 443 DEBUG(1, (__location__ ": Connection to %s got an unexpected " 444 "RPC packet type - %u, expected %u: %s\n", 445 rpccli_pipe_txt(talloc_tos(), cli), 446 pkt->ptype, expected_pkt_type, 447 nt_errstr(ret))); 448 NDR_PRINT_DEBUG(ncacn_packet, pkt); 449 return ret; 450 } 451 452 /* Use this for now... */ 453 return NT_STATUS_NETWORK_ACCESS_DENIED; 454 455 case DCERPC_PKT_BIND_ACK: 456 ret = dcerpc_verify_ncacn_packet_header(pkt, 457 expected_pkt_type, 458 pkt->u.bind_ack.auth_info.length, 459 DCERPC_PFC_FLAG_FIRST | 460 DCERPC_PFC_FLAG_LAST, 461 DCERPC_PFC_FLAG_CONC_MPX | 462 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN); 463 if (!NT_STATUS_IS_OK(ret)) { 464 DEBUG(1, (__location__ ": Connection to %s got an unexpected " 465 "RPC packet type - %u, expected %u: %s\n", 466 rpccli_pipe_txt(talloc_tos(), cli), 467 pkt->ptype, expected_pkt_type, 468 nt_errstr(ret))); 469 NDR_PRINT_DEBUG(ncacn_packet, pkt); 470 return ret; 471 } 472 473 break; 474 417 475 case DCERPC_PKT_ALTER_RESP: 418 case DCERPC_PKT_BIND_ACK: 419 420 /* Client code never receives this kind of packets */ 476 ret = dcerpc_verify_ncacn_packet_header(pkt, 477 expected_pkt_type, 478 pkt->u.alter_resp.auth_info.length, 479 DCERPC_PFC_FLAG_FIRST | 480 DCERPC_PFC_FLAG_LAST, 481 DCERPC_PFC_FLAG_CONC_MPX | 482 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN); 483 if (!NT_STATUS_IS_OK(ret)) { 484 DEBUG(1, (__location__ ": Connection to %s got an unexpected " 485 "RPC packet type - %u, expected %u: %s\n", 486 rpccli_pipe_txt(talloc_tos(), cli), 487 pkt->ptype, expected_pkt_type, 488 nt_errstr(ret))); 489 NDR_PRINT_DEBUG(ncacn_packet, pkt); 490 return ret; 491 } 492 421 493 break; 422 494 423 424 495 case DCERPC_PKT_RESPONSE: 425 496 426 497 r = &pkt->u.response; 498 499 ret = dcerpc_verify_ncacn_packet_header(pkt, 500 expected_pkt_type, 501 r->stub_and_verifier.length, 502 0, /* required_flags */ 503 DCERPC_PFC_FLAG_FIRST | 504 DCERPC_PFC_FLAG_LAST); 505 if (!NT_STATUS_IS_OK(ret)) { 506 DEBUG(1, (__location__ ": Connection to %s got an unexpected " 507 "RPC packet type - %u, expected %u: %s\n", 508 rpccli_pipe_txt(talloc_tos(), cli), 509 pkt->ptype, expected_pkt_type, 510 nt_errstr(ret))); 511 NDR_PRINT_DEBUG(ncacn_packet, pkt); 512 return ret; 513 } 514 515 tmp_stub.data = r->stub_and_verifier.data; 516 tmp_stub.length = r->stub_and_verifier.length; 427 517 428 518 /* Here's where we deal with incoming sign/seal. */ 429 519 ret = dcerpc_check_auth(cli->auth, pkt, 430 & r->stub_and_verifier,520 &tmp_stub, 431 521 DCERPC_RESPONSE_LENGTH, 432 pdu , &pad_len);522 pdu); 433 523 if (!NT_STATUS_IS_OK(ret)) { 524 DEBUG(1, (__location__ ": Connection to %s got an unexpected " 525 "RPC packet type - %u, expected %u: %s\n", 526 rpccli_pipe_txt(talloc_tos(), cli), 527 pkt->ptype, expected_pkt_type, 528 nt_errstr(ret))); 529 NDR_PRINT_DEBUG(ncacn_packet, pkt); 434 530 return ret; 435 531 } 436 532 437 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {438 return NT_STATUS_BUFFER_TOO_SMALL;439 }440 441 533 /* Point the return values at the NDR data. */ 442 rdata->data = r->stub_and_verifier.data; 443 444 if (pkt->auth_length) { 445 /* We've already done integer wrap tests in 446 * dcerpc_check_auth(). */ 447 rdata->length = r->stub_and_verifier.length 448 - pad_len 449 - DCERPC_AUTH_TRAILER_LENGTH 450 - pkt->auth_length; 451 } else { 452 rdata->length = r->stub_and_verifier.length; 453 } 454 455 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n", 534 *rdata = tmp_stub; 535 536 DEBUG(10, ("Got pdu len %lu, data_len %lu\n", 456 537 (long unsigned int)pdu->length, 457 (long unsigned int)rdata->length, 458 (unsigned int)pad_len)); 538 (long unsigned int)rdata->length)); 459 539 460 540 /* … … 477 557 break; 478 558 479 case DCERPC_PKT_BIND_NAK:480 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",481 rpccli_pipe_txt(talloc_tos(), cli)));482 /* Use this for now... */483 return NT_STATUS_NETWORK_ACCESS_DENIED;484 485 559 case DCERPC_PKT_FAULT: 560 561 ret = dcerpc_verify_ncacn_packet_header(pkt, 562 DCERPC_PKT_FAULT, 563 0, /* max_auth_info */ 564 DCERPC_PFC_FLAG_FIRST | 565 DCERPC_PFC_FLAG_LAST, 566 DCERPC_PFC_FLAG_DID_NOT_EXECUTE); 567 if (!NT_STATUS_IS_OK(ret)) { 568 DEBUG(1, (__location__ ": Connection to %s got an unexpected " 569 "RPC packet type - %u, expected %u: %s\n", 570 rpccli_pipe_txt(talloc_tos(), cli), 571 pkt->ptype, expected_pkt_type, 572 nt_errstr(ret))); 573 NDR_PRINT_DEBUG(ncacn_packet, pkt); 574 return ret; 575 } 486 576 487 577 DEBUG(1, (__location__ ": RPC fault code %s received " … … 498 588 (unsigned int)pkt->ptype, 499 589 rpccli_pipe_txt(talloc_tos(), cli))); 500 return NT_STATUS_INVALID_INFO_CLASS; 501 } 502 503 if (pkt->ptype != expected_pkt_type) { 590 return NT_STATUS_RPC_PROTOCOL_ERROR; 591 } 592 593 594 if (pkt->call_id != call_id) { 504 595 DEBUG(3, (__location__ ": Connection to %s got an unexpected " 505 "RPC packet type- %u, not %u\n",596 "RPC call_id - %u, not %u\n", 506 597 rpccli_pipe_txt(talloc_tos(), cli), 507 pkt->ptype, expected_pkt_type)); 508 return NT_STATUS_INVALID_INFO_CLASS; 509 } 510 511 /* Do this just before return - we don't want to modify any rpc header 512 data before now as we may have needed to do cryptographic actions on 513 it before. */ 514 515 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) && 516 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) { 517 DEBUG(5, (__location__ ": bug in server (AS/U?), setting " 518 "fragment first/last ON.\n")); 519 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; 598 pkt->call_id, call_id)); 599 return NT_STATUS_RPC_PROTOCOL_ERROR; 520 600 } 521 601 … … 874 954 state->pkt = talloc(state, struct ncacn_packet); 875 955 if (!state->pkt) { 956 /* 957 * TODO: do a real async disconnect ... 958 * 959 * For now do it sync... 960 */ 961 TALLOC_FREE(state->cli->transport); 876 962 tevent_req_nterror(req, NT_STATUS_NO_MEMORY); 877 963 return; … … 883 969 !state->endianess); 884 970 if (!NT_STATUS_IS_OK(status)) { 971 /* 972 * TODO: do a real async disconnect ... 973 * 974 * For now do it sync... 975 */ 976 TALLOC_FREE(state->cli->transport); 885 977 tevent_req_nterror(req, status); 886 return;887 }888 889 if (state->incoming_frag.length != state->pkt->frag_length) {890 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",891 (unsigned int)state->incoming_frag.length,892 (unsigned int)state->pkt->frag_length));893 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);894 978 return; 895 979 } … … 899 983 &state->incoming_frag, 900 984 state->expected_pkt_type, 985 state->call_id, 901 986 &rdata, 902 987 &state->reply_pdu); … … 907 992 nt_errstr(status))); 908 993 994 if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) { 995 /* 996 * TODO: do a real async disconnect ... 997 * 998 * For now do it sync... 999 */ 1000 TALLOC_FREE(state->cli->transport); 1001 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) { 1002 /* 1003 * TODO: do a real async disconnect ... 1004 * 1005 * For now do it sync... 1006 */ 1007 TALLOC_FREE(state->cli->transport); 1008 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) { 1009 /* 1010 * TODO: do a real async disconnect ... 1011 * 1012 * For now do it sync... 1013 */ 1014 TALLOC_FREE(state->cli->transport); 1015 } 909 1016 if (!NT_STATUS_IS_OK(status)) { 910 1017 tevent_req_nterror(req, status); … … 931 1038 state->endianess?"little":"big", 932 1039 state->pkt->drep[0]?"little":"big")); 933 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 1040 /* 1041 * TODO: do a real async disconnect ... 1042 * 1043 * For now do it sync... 1044 */ 1045 TALLOC_FREE(state->cli->transport); 1046 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 1047 return; 1048 } 1049 1050 if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) { 1051 /* 1052 * TODO: do a real async disconnect ... 1053 * 1054 * For now do it sync... 1055 */ 1056 TALLOC_FREE(state->cli->transport); 1057 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 934 1058 return; 935 1059 } … … 939 1063 if (!data_blob_realloc(NULL, &state->reply_pdu, 940 1064 state->reply_pdu_offset + rdata.length)) { 1065 /* 1066 * TODO: do a real async disconnect ... 1067 * 1068 * For now do it sync... 1069 */ 1070 TALLOC_FREE(state->cli->transport); 941 1071 tevent_req_nterror(req, NT_STATUS_NO_MEMORY); 942 1072 return; … … 968 1098 state->call_id, 969 1099 &state->incoming_frag); 1100 if (subreq == NULL) { 1101 /* 1102 * TODO: do a real async disconnect ... 1103 * 1104 * For now do it sync... 1105 */ 1106 TALLOC_FREE(state->cli->transport); 1107 } 970 1108 if (tevent_req_nomem(subreq, req)) { 971 1109 return; … … 1237 1375 auth->auth_level, 1238 1376 0, /* auth_pad_length */ 1239 1, /* auth_context_id */1377 auth->auth_context_id, 1240 1378 &auth_token, 1241 1379 &auth_info); … … 1270 1408 DATA_BLOB *req_data; 1271 1409 uint32_t req_data_sent; 1410 DATA_BLOB req_trailer; 1411 uint32_t req_trailer_sent; 1412 bool verify_bitmask1; 1413 bool verify_pcontext; 1272 1414 DATA_BLOB rpc_out; 1273 1415 DATA_BLOB reply_pdu; … … 1276 1418 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq); 1277 1419 static void rpc_api_pipe_req_done(struct tevent_req *subreq); 1420 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state); 1278 1421 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, 1279 1422 bool *is_last_frag); … … 1311 1454 } 1312 1455 1456 status = prepare_verification_trailer(state); 1457 if (!NT_STATUS_IS_OK(status)) { 1458 goto post_status; 1459 } 1460 1313 1461 status = prepare_next_frag(state, &is_last_frag); 1314 1462 if (!NT_STATUS_IS_OK(status)) { … … 1345 1493 } 1346 1494 1495 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state) 1496 { 1497 struct pipe_auth_data *a = state->cli->auth; 1498 struct dcerpc_sec_verification_trailer *t; 1499 struct dcerpc_sec_vt *c = NULL; 1500 struct ndr_push *ndr = NULL; 1501 enum ndr_err_code ndr_err; 1502 size_t align = 0; 1503 size_t pad = 0; 1504 1505 if (a == NULL) { 1506 return NT_STATUS_OK; 1507 } 1508 1509 if (a->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) { 1510 return NT_STATUS_OK; 1511 } 1512 1513 t = talloc_zero(state, struct dcerpc_sec_verification_trailer); 1514 if (t == NULL) { 1515 return NT_STATUS_NO_MEMORY; 1516 } 1517 1518 if (!a->verified_bitmask1) { 1519 t->commands = talloc_realloc(t, t->commands, 1520 struct dcerpc_sec_vt, 1521 t->count.count + 1); 1522 if (t->commands == NULL) { 1523 return NT_STATUS_NO_MEMORY; 1524 } 1525 c = &t->commands[t->count.count++]; 1526 ZERO_STRUCTP(c); 1527 1528 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1; 1529 state->verify_bitmask1 = true; 1530 } 1531 1532 if (!state->cli->verified_pcontext) { 1533 t->commands = talloc_realloc(t, t->commands, 1534 struct dcerpc_sec_vt, 1535 t->count.count + 1); 1536 if (t->commands == NULL) { 1537 return NT_STATUS_NO_MEMORY; 1538 } 1539 c = &t->commands[t->count.count++]; 1540 ZERO_STRUCTP(c); 1541 1542 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT; 1543 c->u.pcontext.abstract_syntax = state->cli->abstract_syntax; 1544 c->u.pcontext.transfer_syntax = state->cli->transfer_syntax; 1545 1546 state->verify_pcontext = true; 1547 } 1548 1549 if (true) { /* We do not support header signing */ 1550 t->commands = talloc_realloc(t, t->commands, 1551 struct dcerpc_sec_vt, 1552 t->count.count + 1); 1553 if (t->commands == NULL) { 1554 return NT_STATUS_NO_MEMORY; 1555 } 1556 c = &t->commands[t->count.count++]; 1557 ZERO_STRUCTP(c); 1558 1559 c->command = DCERPC_SEC_VT_COMMAND_HEADER2; 1560 c->u.header2.ptype = DCERPC_PKT_REQUEST; 1561 c->u.header2.drep[0] = DCERPC_DREP_LE; 1562 c->u.header2.drep[1] = 0; 1563 c->u.header2.drep[2] = 0; 1564 c->u.header2.drep[3] = 0; 1565 c->u.header2.call_id = state->call_id; 1566 c->u.header2.context_id = 0; 1567 c->u.header2.opnum = state->op_num; 1568 } 1569 1570 if (t->count.count == 0) { 1571 TALLOC_FREE(t); 1572 return NT_STATUS_OK; 1573 } 1574 1575 c = &t->commands[t->count.count - 1]; 1576 c->command |= DCERPC_SEC_VT_COMMAND_END; 1577 1578 if (DEBUGLEVEL >= 10) { 1579 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t); 1580 } 1581 1582 ndr = ndr_push_init_ctx(state); 1583 if (ndr == NULL) { 1584 return NT_STATUS_NO_MEMORY; 1585 } 1586 1587 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr, 1588 NDR_SCALARS | NDR_BUFFERS, 1589 t); 1590 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1591 return ndr_map_error2ntstatus(ndr_err); 1592 } 1593 state->req_trailer = ndr_push_blob(ndr); 1594 1595 align = state->req_data->length & 0x3; 1596 if (align > 0) { 1597 pad = 4 - align; 1598 } 1599 if (pad > 0) { 1600 bool ok; 1601 uint8_t *p; 1602 const uint8_t zeros[4] = { 0, }; 1603 1604 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad); 1605 if (!ok) { 1606 return NT_STATUS_NO_MEMORY; 1607 } 1608 1609 /* move the padding to the start */ 1610 p = state->req_trailer.data; 1611 memmove(p + pad, p, state->req_trailer.length - pad); 1612 memset(p, 0, pad); 1613 } 1614 1615 return NT_STATUS_OK; 1616 } 1617 1347 1618 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, 1348 1619 bool *is_last_frag) 1349 1620 { 1350 size_t data_sent_thistime;1351 1621 size_t auth_len; 1352 1622 size_t frag_len; … … 1354 1624 size_t pad_len; 1355 1625 size_t data_left; 1356 NTSTATUS status; 1626 size_t data_thistime; 1627 size_t trailer_left; 1628 size_t trailer_thistime = 0; 1629 size_t total_left; 1630 size_t total_thistime; 1631 NTSTATUS status; 1632 bool ok; 1357 1633 union dcerpc_payload u; 1358 1634 1359 1635 data_left = state->req_data->length - state->req_data_sent; 1636 trailer_left = state->req_trailer.length - state->req_trailer_sent; 1637 total_left = data_left + trailer_left; 1638 if ((total_left < data_left) || (total_left < trailer_left)) { 1639 /* 1640 * overflow 1641 */ 1642 return NT_STATUS_INVALID_PARAMETER_MIX; 1643 } 1360 1644 1361 1645 status = dcerpc_guess_sizes(state->cli->auth, 1362 DCERPC_REQUEST_LENGTH, data_left,1646 DCERPC_REQUEST_LENGTH, total_left, 1363 1647 state->cli->max_xmit_frag, 1364 1648 CLIENT_NDR_PADDING_SIZE, 1365 & data_sent_thistime,1649 &total_thistime, 1366 1650 &frag_len, &auth_len, &pad_len); 1367 1651 if (!NT_STATUS_IS_OK(status)) { … … 1373 1657 } 1374 1658 1375 if ( data_sent_thistime == data_left) {1659 if (total_thistime == total_left) { 1376 1660 flags |= DCERPC_PFC_FLAG_LAST; 1377 1661 } 1378 1662 1663 data_thistime = MIN(total_thistime, data_left); 1664 if (data_thistime < total_thistime) { 1665 trailer_thistime = total_thistime - data_thistime; 1666 } 1667 1379 1668 data_blob_free(&state->rpc_out); 1380 1669 1381 1670 ZERO_STRUCT(u.request); 1382 1671 1383 u.request.alloc_hint = state->req_data->length;1672 u.request.alloc_hint = total_left; 1384 1673 u.request.context_id = 0; 1385 1674 u.request.opnum = state->op_num; … … 1401 1690 dcerpc_set_frag_length(&state->rpc_out, frag_len); 1402 1691 1403 /* Copy in the data. */ 1404 if (!data_blob_append(NULL, &state->rpc_out, 1692 if (data_thistime > 0) { 1693 /* Copy in the data. */ 1694 ok = data_blob_append(NULL, &state->rpc_out, 1405 1695 state->req_data->data + state->req_data_sent, 1406 data_sent_thistime)) { 1407 return NT_STATUS_NO_MEMORY; 1696 data_thistime); 1697 if (!ok) { 1698 return NT_STATUS_NO_MEMORY; 1699 } 1700 state->req_data_sent += data_thistime; 1701 } 1702 1703 if (trailer_thistime > 0) { 1704 /* Copy in the verification trailer. */ 1705 ok = data_blob_append(NULL, &state->rpc_out, 1706 state->req_trailer.data + state->req_trailer_sent, 1707 trailer_thistime); 1708 if (!ok) { 1709 return NT_STATUS_NO_MEMORY; 1710 } 1711 state->req_trailer_sent += trailer_thistime; 1408 1712 } 1409 1713 … … 1425 1729 } 1426 1730 1427 state->req_data_sent += data_sent_thistime;1428 1731 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0); 1429 1732 … … 1489 1792 return; 1490 1793 } 1794 1795 if (state->cli->auth == NULL) { 1796 tevent_req_done(req); 1797 return; 1798 } 1799 1800 if (state->verify_bitmask1) { 1801 state->cli->auth->verified_bitmask1 = true; 1802 } 1803 1804 if (state->verify_pcontext) { 1805 state->cli->verified_pcontext = true; 1806 } 1807 1491 1808 tevent_req_done(req); 1492 1809 } … … 1560 1877 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx, 1561 1878 struct rpc_pipe_client *cli, 1562 uint32 rpc_call_id, 1563 enum dcerpc_AuthType auth_type, 1564 enum dcerpc_AuthLevel auth_level, 1879 struct pipe_auth_data *auth, 1880 uint32_t rpc_call_id, 1565 1881 DATA_BLOB *pauth_blob, 1566 1882 DATA_BLOB *rpc_out) … … 1572 1888 1573 1889 status = dcerpc_push_dcerpc_auth(mem_ctx, 1574 auth _type,1575 auth _level,1890 auth->auth_type, 1891 auth->auth_level, 1576 1892 0, /* auth_pad_length */ 1577 1, /* auth_context_id */1893 auth->auth_context_id, 1578 1894 pauth_blob, 1579 1895 &u.auth3.auth_info); … … 1605 1921 1606 1922 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx, 1607 enum dcerpc_AuthType auth_type, 1608 enum dcerpc_AuthLevel auth_level, 1609 uint32 rpc_call_id, 1923 struct pipe_auth_data *auth, 1924 uint32_t rpc_call_id, 1610 1925 const struct ndr_syntax_id *abstract, 1611 1926 const struct ndr_syntax_id *transfer, … … 1617 1932 1618 1933 status = dcerpc_push_dcerpc_auth(mem_ctx, 1619 auth _type,1620 auth _level,1934 auth->auth_type, 1935 auth->auth_level, 1621 1936 0, /* auth_pad_length */ 1622 1, /* auth_context_id */1937 auth->auth_context_id, 1623 1938 pauth_blob, 1624 1939 &auth_info); … … 1648 1963 bool auth3; 1649 1964 uint32_t rpc_call_id; 1965 struct netr_Authenticator auth; 1966 struct netr_Authenticator return_auth; 1967 struct netlogon_creds_CredentialState *creds; 1968 union netr_Capabilities capabilities; 1969 struct netr_LogonGetCapabilities r; 1650 1970 }; 1651 1971 1652 1972 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq); 1973 static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req); 1653 1974 static NTSTATUS rpc_bind_next_send(struct tevent_req *req, 1654 1975 struct rpc_pipe_bind_state *state, … … 1754 2075 case DCERPC_AUTH_TYPE_NONE: 1755 2076 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM: 1756 case DCERPC_AUTH_TYPE_SCHANNEL:1757 2077 /* Bind complete. */ 1758 2078 tevent_req_done(req); 1759 2079 return; 1760 2080 1761 case DCERPC_AUTH_TYPE_NTLMSSP: 1762 case DCERPC_AUTH_TYPE_SPNEGO: 1763 case DCERPC_AUTH_TYPE_KRB5: 1764 /* Paranoid lenght checks */ 1765 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH 1766 + pkt->auth_length) { 1767 tevent_req_nterror(req, 1768 NT_STATUS_INFO_LENGTH_MISMATCH); 2081 case DCERPC_AUTH_TYPE_SCHANNEL: 2082 rpc_pipe_bind_step_two_trigger(req); 2083 return; 2084 2085 default: 2086 if (pkt->auth_length == 0) { 2087 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 1769 2088 return; 1770 2089 } 1771 2090 /* get auth credentials */ 1772 status = dcerpc_pull_ dcerpc_auth(talloc_tos(),1773 &pkt->u.bind_ack.auth_info,1774 &auth, false);2091 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(), 2092 &pkt->u.bind_ack.auth_info, 2093 &auth, NULL, true); 1775 2094 if (!NT_STATUS_IS_OK(status)) { 1776 2095 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n", … … 1779 2098 return; 1780 2099 } 2100 2101 if (auth.auth_type != pauth->auth_type) { 2102 DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n", 2103 auth.auth_type, pauth->auth_type)); 2104 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 2105 return; 2106 } 2107 2108 if (auth.auth_level != pauth->auth_level) { 2109 DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n", 2110 auth.auth_level, pauth->auth_level)); 2111 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 2112 return; 2113 } 2114 2115 if (auth.auth_context_id != pauth->auth_context_id) { 2116 DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n", 2117 (unsigned)auth.auth_context_id, 2118 (unsigned)pauth->auth_context_id)); 2119 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR); 2120 return; 2121 } 2122 1781 2123 break; 1782 1783 default:1784 goto err_out;1785 2124 } 1786 2125 … … 1870 2209 } 1871 2210 2211 static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq); 2212 2213 static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req) 2214 { 2215 struct rpc_pipe_bind_state *state = 2216 tevent_req_data(req, 2217 struct rpc_pipe_bind_state); 2218 struct dcerpc_binding_handle *b = state->cli->binding_handle; 2219 struct schannel_state *schannel_auth = 2220 talloc_get_type_abort(state->cli->auth->auth_ctx, 2221 struct schannel_state); 2222 struct tevent_req *subreq; 2223 2224 if (schannel_auth == NULL || 2225 !ndr_syntax_id_equal(&state->cli->abstract_syntax, 2226 &ndr_table_netlogon.syntax_id)) { 2227 tevent_req_done(req); 2228 return; 2229 } 2230 2231 ZERO_STRUCT(state->return_auth); 2232 2233 state->creds = netlogon_creds_copy(state, schannel_auth->creds); 2234 if (state->creds == NULL) { 2235 tevent_req_nterror(req, NT_STATUS_NO_MEMORY); 2236 return; 2237 } 2238 2239 netlogon_creds_client_authenticator(state->creds, &state->auth); 2240 2241 state->r.in.server_name = state->cli->srv_name_slash; 2242 state->r.in.computer_name = state->creds->computer_name; 2243 state->r.in.credential = &state->auth; 2244 state->r.in.query_level = 1; 2245 state->r.in.return_authenticator = &state->return_auth; 2246 2247 state->r.out.capabilities = &state->capabilities; 2248 state->r.out.return_authenticator = &state->return_auth; 2249 2250 subreq = dcerpc_netr_LogonGetCapabilities_r_send(talloc_tos(), 2251 state->ev, 2252 b, 2253 &state->r); 2254 if (subreq == NULL) { 2255 tevent_req_nterror(req, NT_STATUS_NO_MEMORY); 2256 return; 2257 } 2258 2259 tevent_req_set_callback(subreq, rpc_pipe_bind_step_two_done, req); 2260 return; 2261 } 2262 2263 static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq) 2264 { 2265 struct tevent_req *req = 2266 tevent_req_callback_data(subreq, 2267 struct tevent_req); 2268 struct rpc_pipe_bind_state *state = 2269 tevent_req_data(req, 2270 struct rpc_pipe_bind_state); 2271 struct schannel_state *schannel_auth = 2272 talloc_get_type_abort(state->cli->auth->auth_ctx, 2273 struct schannel_state); 2274 NTSTATUS status; 2275 2276 status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, talloc_tos()); 2277 TALLOC_FREE(subreq); 2278 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { 2279 if (state->cli->dc->negotiate_flags & 2280 NETLOGON_NEG_SUPPORTS_AES) { 2281 DEBUG(5, ("AES is not supported and the error was %s\n", 2282 nt_errstr(status))); 2283 tevent_req_nterror(req, 2284 NT_STATUS_INVALID_NETWORK_RESPONSE); 2285 return; 2286 } 2287 2288 /* This is probably NT */ 2289 DEBUG(5, ("We are checking against an NT - %s\n", 2290 nt_errstr(status))); 2291 tevent_req_done(req); 2292 return; 2293 } else if (!NT_STATUS_IS_OK(status)) { 2294 DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n", 2295 nt_errstr(status))); 2296 tevent_req_nterror(req, status); 2297 return; 2298 } 2299 2300 if (NT_STATUS_EQUAL(state->r.out.result, NT_STATUS_NOT_IMPLEMENTED)) { 2301 if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { 2302 /* This means AES isn't supported. */ 2303 DEBUG(5, ("AES is not supported and the error was %s\n", 2304 nt_errstr(state->r.out.result))); 2305 tevent_req_nterror(req, 2306 NT_STATUS_INVALID_NETWORK_RESPONSE); 2307 return; 2308 } 2309 2310 /* This is probably an old Samba version */ 2311 DEBUG(5, ("We are checking against an old Samba version - %s\n", 2312 nt_errstr(state->r.out.result))); 2313 tevent_req_done(req); 2314 return; 2315 } 2316 2317 /* We need to check the credential state here, cause win2k3 and earlier 2318 * returns NT_STATUS_NOT_IMPLEMENTED */ 2319 if (!netlogon_creds_client_check(state->creds, 2320 &state->r.out.return_authenticator->cred)) { 2321 /* 2322 * Server replied with bad credential. Fail. 2323 */ 2324 DEBUG(0,("rpc_pipe_bind_step_two_done: server %s " 2325 "replied with bad credential\n", 2326 state->cli->desthost)); 2327 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL); 2328 return; 2329 } 2330 2331 TALLOC_FREE(schannel_auth->creds); 2332 schannel_auth->creds = talloc_steal(state->cli, state->creds); 2333 2334 if (!NT_STATUS_IS_OK(state->r.out.result)) { 2335 DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n", 2336 nt_errstr(state->r.out.result))); 2337 tevent_req_nterror(req, state->r.out.result); 2338 return; 2339 } 2340 2341 if (state->creds->negotiate_flags != 2342 state->r.out.capabilities->server_capabilities) { 2343 DEBUG(0, ("The client capabilities don't match the server " 2344 "capabilities: local[0x%08X] remote[0x%08X]\n", 2345 state->creds->negotiate_flags, 2346 state->capabilities.server_capabilities)); 2347 tevent_req_nterror(req, 2348 NT_STATUS_INVALID_NETWORK_RESPONSE); 2349 return; 2350 } 2351 2352 /* TODO: Add downgrade dectection. */ 2353 2354 tevent_req_done(req); 2355 return; 2356 } 2357 1872 2358 static NTSTATUS rpc_bind_next_send(struct tevent_req *req, 1873 2359 struct rpc_pipe_bind_state *state, … … 1881 2367 data_blob_free(&state->rpc_out); 1882 2368 1883 status = create_rpc_alter_context(state, 1884 auth->auth_type, 1885 auth->auth_level, 2369 status = create_rpc_alter_context(state, auth, 1886 2370 state->rpc_call_id, 1887 2371 &state->cli->abstract_syntax, … … 1916 2400 data_blob_free(&state->rpc_out); 1917 2401 1918 status = create_rpc_bind_auth3(state, state->cli, 2402 status = create_rpc_bind_auth3(state, state->cli, auth, 1919 2403 state->rpc_call_id, 1920 auth->auth_type,1921 auth->auth_level,1922 2404 auth_token, 1923 2405 &state->rpc_out); … … 2153 2635 * TODO: do a real async disconnect ... 2154 2636 * 2155 * For now the caller needs to free rpc_cli2637 * For now we do it sync... 2156 2638 */ 2639 TALLOC_FREE(hs->rpc_cli->transport); 2157 2640 hs->rpc_cli = NULL; 2158 2641 … … 2291 2774 result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM; 2292 2775 result->auth_level = DCERPC_AUTH_LEVEL_CONNECT; 2776 result->auth_context_id = 1; 2293 2777 2294 2778 result->user_name = talloc_strdup(result, ""); … … 2315 2799 result->auth_type = DCERPC_AUTH_TYPE_NONE; 2316 2800 result->auth_level = DCERPC_AUTH_LEVEL_NONE; 2801 result->auth_context_id = 0; 2317 2802 2318 2803 result->user_name = talloc_strdup(result, ""); … … 2352 2837 result->auth_type = auth_type; 2353 2838 result->auth_level = auth_level; 2839 result->auth_context_id = 1; 2354 2840 2355 2841 result->user_name = talloc_strdup(result, username); … … 2423 2909 result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL; 2424 2910 result->auth_level = auth_level; 2911 result->auth_context_id = 1; 2425 2912 2426 2913 result->user_name = talloc_strdup(result, ""); … … 3087 3574 auth->auth_type = DCERPC_AUTH_TYPE_KRB5; 3088 3575 auth->auth_level = auth_level; 3576 auth->auth_context_id = 1; 3089 3577 3090 3578 if (!username) { … … 3157 3645 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO; 3158 3646 auth->auth_level = auth_level; 3647 auth->auth_context_id = 1; 3159 3648 3160 3649 if (!username) { … … 3231 3720 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO; 3232 3721 auth->auth_level = auth_level; 3722 auth->auth_context_id = 1; 3233 3723 3234 3724 if (!username) { -
vendor/current/source3/rpc_client/rpc_client.h
r917 r919 40 40 struct ndr_syntax_id abstract_syntax; 41 41 struct ndr_syntax_id transfer_syntax; 42 bool verified_pcontext; 42 43 43 44 char *desthost;
Note:
See TracChangeset
for help on using the changeset viewer.