Ignore:
Timestamp:
Jun 9, 2016, 2:17:22 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: apply latest security patches to vendor

Location:
vendor/current/source3/rpc_client
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/rpc_client/cli_pipe.c

    r860 r919  
    2929#include "ntlmssp_wrap.h"
    3030#include "librpc/gen_ndr/ndr_dcerpc.h"
     31#include "librpc/gen_ndr/ndr_netlogon_c.h"
    3132#include "librpc/rpc/dcerpc.h"
    3233#include "librpc/crypto/gse.h"
     
    400401                                                DATA_BLOB *pdu,
    401402                                                uint8_t expected_pkt_type,
     403                                                uint32_t call_id,
    402404                                                DATA_BLOB *rdata,
    403405                                                DATA_BLOB *reply_pdu)
    404406{
    405         struct dcerpc_response *r;
     407        const struct dcerpc_response *r = NULL;
     408        DATA_BLOB tmp_stub = data_blob_null;
    406409        NTSTATUS ret = NT_STATUS_OK;
    407         size_t pad_len = 0;
    408410
    409411        /*
     
    413415        *rdata = *pdu;
    414416
     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
    415430        /* Ensure we have the correct type. */
    416431        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
    417475        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
    421493                break;
    422494
    423 
    424495        case DCERPC_PKT_RESPONSE:
    425496
    426497                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;
    427517
    428518                /* Here's where we deal with incoming sign/seal. */
    429519                ret = dcerpc_check_auth(cli->auth, pkt,
    430                                         &r->stub_and_verifier,
     520                                        &tmp_stub,
    431521                                        DCERPC_RESPONSE_LENGTH,
    432                                         pdu, &pad_len);
     522                                        pdu);
    433523                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);
    434530                        return ret;
    435531                }
    436532
    437                 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
    438                         return NT_STATUS_BUFFER_TOO_SMALL;
    439                 }
    440 
    441533                /* 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",
    456537                           (long unsigned int)pdu->length,
    457                            (long unsigned int)rdata->length,
    458                            (unsigned int)pad_len));
     538                           (long unsigned int)rdata->length));
    459539
    460540                /*
     
    477557                break;
    478558
    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 
    485559        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                }
    486576
    487577                DEBUG(1, (__location__ ": RPC fault code %s received "
     
    498588                          (unsigned int)pkt->ptype,
    499589                          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) {
    504595                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",
    506597                          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;
    520600        }
    521601
     
    874954        state->pkt = talloc(state, struct ncacn_packet);
    875955        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);
    876962                tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
    877963                return;
     
    883969                                          !state->endianess);
    884970        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);
    885977                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);
    894978                return;
    895979        }
     
    899983                                                &state->incoming_frag,
    900984                                                state->expected_pkt_type,
     985                                                state->call_id,
    901986                                                &rdata,
    902987                                                &state->reply_pdu);
     
    907992                  nt_errstr(status)));
    908993
     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        }
    9091016        if (!NT_STATUS_IS_OK(status)) {
    9101017                tevent_req_nterror(req, status);
     
    9311038                         state->endianess?"little":"big",
    9321039                         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);
    9341058                return;
    9351059        }
     
    9391063                if (!data_blob_realloc(NULL, &state->reply_pdu,
    9401064                                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);
    9411071                        tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
    9421072                        return;
     
    9681098                                        state->call_id,
    9691099                                        &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        }
    9701108        if (tevent_req_nomem(subreq, req)) {
    9711109                return;
     
    12371375                                                auth->auth_level,
    12381376                                                0, /* auth_pad_length */
    1239                                                 1, /* auth_context_id */
     1377                                                auth->auth_context_id,
    12401378                                                &auth_token,
    12411379                                                &auth_info);
     
    12701408        DATA_BLOB *req_data;
    12711409        uint32_t req_data_sent;
     1410        DATA_BLOB req_trailer;
     1411        uint32_t req_trailer_sent;
     1412        bool verify_bitmask1;
     1413        bool verify_pcontext;
    12721414        DATA_BLOB rpc_out;
    12731415        DATA_BLOB reply_pdu;
     
    12761418static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
    12771419static void rpc_api_pipe_req_done(struct tevent_req *subreq);
     1420static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
    12781421static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
    12791422                                  bool *is_last_frag);
     
    13111454        }
    13121455
     1456        status = prepare_verification_trailer(state);
     1457        if (!NT_STATUS_IS_OK(status)) {
     1458                goto post_status;
     1459        }
     1460
    13131461        status = prepare_next_frag(state, &is_last_frag);
    13141462        if (!NT_STATUS_IS_OK(status)) {
     
    13451493}
    13461494
     1495static 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
    13471618static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
    13481619                                  bool *is_last_frag)
    13491620{
    1350         size_t data_sent_thistime;
    13511621        size_t auth_len;
    13521622        size_t frag_len;
     
    13541624        size_t pad_len;
    13551625        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;
    13571633        union dcerpc_payload u;
    13581634
    13591635        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        }
    13601644
    13611645        status = dcerpc_guess_sizes(state->cli->auth,
    1362                                     DCERPC_REQUEST_LENGTH, data_left,
     1646                                    DCERPC_REQUEST_LENGTH, total_left,
    13631647                                    state->cli->max_xmit_frag,
    13641648                                    CLIENT_NDR_PADDING_SIZE,
    1365                                     &data_sent_thistime,
     1649                                    &total_thistime,
    13661650                                    &frag_len, &auth_len, &pad_len);
    13671651        if (!NT_STATUS_IS_OK(status)) {
     
    13731657        }
    13741658
    1375         if (data_sent_thistime == data_left) {
     1659        if (total_thistime == total_left) {
    13761660                flags |= DCERPC_PFC_FLAG_LAST;
    13771661        }
    13781662
     1663        data_thistime = MIN(total_thistime, data_left);
     1664        if (data_thistime < total_thistime) {
     1665                trailer_thistime = total_thistime - data_thistime;
     1666        }
     1667
    13791668        data_blob_free(&state->rpc_out);
    13801669
    13811670        ZERO_STRUCT(u.request);
    13821671
    1383         u.request.alloc_hint    = state->req_data->length;
     1672        u.request.alloc_hint    = total_left;
    13841673        u.request.context_id    = 0;
    13851674        u.request.opnum         = state->op_num;
     
    14011690        dcerpc_set_frag_length(&state->rpc_out, frag_len);
    14021691
    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,
    14051695                                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;
    14081712        }
    14091713
     
    14251729        }
    14261730
    1427         state->req_data_sent += data_sent_thistime;
    14281731        *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
    14291732
     
    14891792                return;
    14901793        }
     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
    14911808        tevent_req_done(req);
    14921809}
     
    15601877static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
    15611878                                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,
    15651881                                DATA_BLOB *pauth_blob,
    15661882                                DATA_BLOB *rpc_out)
     
    15721888
    15731889        status = dcerpc_push_dcerpc_auth(mem_ctx,
    1574                                          auth_type,
    1575                                          auth_level,
     1890                                         auth->auth_type,
     1891                                         auth->auth_level,
    15761892                                         0, /* auth_pad_length */
    1577                                          1, /* auth_context_id */
     1893                                         auth->auth_context_id,
    15781894                                         pauth_blob,
    15791895                                         &u.auth3.auth_info);
     
    16051921
    16061922static 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,
    16101925                                        const struct ndr_syntax_id *abstract,
    16111926                                        const struct ndr_syntax_id *transfer,
     
    16171932
    16181933        status = dcerpc_push_dcerpc_auth(mem_ctx,
    1619                                          auth_type,
    1620                                          auth_level,
     1934                                         auth->auth_type,
     1935                                         auth->auth_level,
    16211936                                         0, /* auth_pad_length */
    1622                                          1, /* auth_context_id */
     1937                                         auth->auth_context_id,
    16231938                                         pauth_blob,
    16241939                                         &auth_info);
     
    16481963        bool auth3;
    16491964        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;
    16501970};
    16511971
    16521972static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
     1973static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req);
    16531974static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
    16541975                                   struct rpc_pipe_bind_state *state,
     
    17542075        case DCERPC_AUTH_TYPE_NONE:
    17552076        case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
    1756         case DCERPC_AUTH_TYPE_SCHANNEL:
    17572077                /* Bind complete. */
    17582078                tevent_req_done(req);
    17592079                return;
    17602080
    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);
    17692088                        return;
    17702089                }
    17712090                /* 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);
    17752094                if (!NT_STATUS_IS_OK(status)) {
    17762095                        DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
     
    17792098                        return;
    17802099                }
     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
    17812123                break;
    1782 
    1783         default:
    1784                 goto err_out;
    17852124        }
    17862125
     
    18702209}
    18712210
     2211static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq);
     2212
     2213static 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
     2263static 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
    18722358static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
    18732359                                   struct rpc_pipe_bind_state *state,
     
    18812367        data_blob_free(&state->rpc_out);
    18822368
    1883         status = create_rpc_alter_context(state,
    1884                                           auth->auth_type,
    1885                                           auth->auth_level,
     2369        status = create_rpc_alter_context(state, auth,
    18862370                                          state->rpc_call_id,
    18872371                                          &state->cli->abstract_syntax,
     
    19162400        data_blob_free(&state->rpc_out);
    19172401
    1918         status = create_rpc_bind_auth3(state, state->cli,
     2402        status = create_rpc_bind_auth3(state, state->cli, auth,
    19192403                                        state->rpc_call_id,
    1920                                         auth->auth_type,
    1921                                         auth->auth_level,
    19222404                                        auth_token,
    19232405                                        &state->rpc_out);
     
    21532635         * TODO: do a real async disconnect ...
    21542636         *
    2155          * For now the caller needs to free rpc_cli
     2637         * For now we do it sync...
    21562638         */
     2639        TALLOC_FREE(hs->rpc_cli->transport);
    21572640        hs->rpc_cli = NULL;
    21582641
     
    22912774        result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
    22922775        result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
     2776        result->auth_context_id = 1;
    22932777
    22942778        result->user_name = talloc_strdup(result, "");
     
    23152799        result->auth_type = DCERPC_AUTH_TYPE_NONE;
    23162800        result->auth_level = DCERPC_AUTH_LEVEL_NONE;
     2801        result->auth_context_id = 0;
    23172802
    23182803        result->user_name = talloc_strdup(result, "");
     
    23522837        result->auth_type = auth_type;
    23532838        result->auth_level = auth_level;
     2839        result->auth_context_id = 1;
    23542840
    23552841        result->user_name = talloc_strdup(result, username);
     
    24232909        result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
    24242910        result->auth_level = auth_level;
     2911        result->auth_context_id = 1;
    24252912
    24262913        result->user_name = talloc_strdup(result, "");
     
    30873574        auth->auth_type = DCERPC_AUTH_TYPE_KRB5;
    30883575        auth->auth_level = auth_level;
     3576        auth->auth_context_id = 1;
    30893577
    30903578        if (!username) {
     
    31573645        auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
    31583646        auth->auth_level = auth_level;
     3647        auth->auth_context_id = 1;
    31593648
    31603649        if (!username) {
     
    32313720        auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
    32323721        auth->auth_level = auth_level;
     3722        auth->auth_context_id = 1;
    32333723
    32343724        if (!username) {
  • vendor/current/source3/rpc_client/rpc_client.h

    r917 r919  
    4040        struct ndr_syntax_id abstract_syntax;
    4141        struct ndr_syntax_id transfer_syntax;
     42        bool verified_pcontext;
    4243
    4344        char *desthost;
Note: See TracChangeset for help on using the changeset viewer.