From 4743a58bf174f393edce075eb53670f7981c9a7c Mon Sep 17 00:00:00 2001 From: "Alan T. DeKok" Date: Tue, 30 May 2023 10:41:14 -0400 Subject: [PATCH] API changes and preparation for allowing outer TLVs --- src/modules/rlm_eap/libeap/eap_tls.c | 205 +++++++++++------- src/modules/rlm_eap/libeap/eap_tls.h | 5 +- src/modules/rlm_eap/libeap/eap_types.h | 4 +- src/modules/rlm_eap/libeap/eapcommon.c | 126 ++++++++++- src/modules/rlm_eap/libeap/mppe_keys.c | 50 ++++- .../rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c | 2 +- src/modules/rlm_eap/types/rlm_eap_peap/peap.c | 4 +- .../rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c | 4 +- .../rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c | 2 +- .../rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c | 6 +- src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c | 2 +- 11 files changed, 299 insertions(+), 111 deletions(-) diff --git a/src/modules/rlm_eap/libeap/eap_tls.c b/src/modules/rlm_eap/libeap/eap_tls.c index 2f37663df1..0ad1c255b7 100644 --- a/src/modules/rlm_eap/libeap/eap_tls.c +++ b/src/modules/rlm_eap/libeap/eap_tls.c @@ -102,29 +102,6 @@ tls_session_t *eaptls_session(eap_handler_t *handler, fr_tls_server_conf_t *tls_ return talloc_steal(handler, ssn); /* ssn */ } -/* - The S flag is set only within the EAP-TLS start message - sent from the EAP server to the peer. -*/ -int eaptls_start(EAP_DS *eap_ds, int peap_flag) -{ - EAPTLS_PACKET reply; - - reply.code = FR_TLS_START; - reply.length = TLS_HEADER_LEN + 1/*flags*/; - - reply.flags = peap_flag; - reply.flags = SET_START(reply.flags); - - reply.data = NULL; - reply.dlen = 0; - - eaptls_compose(eap_ds, &reply); - - return 1; -} - - /** Send an EAP-TLS success * * Composes an EAP-TLS-Success. This is a message with code EAP_TLS_ESTABLISHED. @@ -191,7 +168,7 @@ int eaptls_success(eap_handler_t *handler, int peap_flag) eaptls_gen_mppe_keys(request, tls_session->ssl, tls_session->label, context, context_size); - } else if (handler->type != PW_EAP_FAST) { + } else if ((handler->type != PW_EAP_FAST) && (handler->type != PW_EAP_TEAP)) { RWDEBUG("(TLS) EAP Not adding MPPE keys because there is no PRF label"); } @@ -230,13 +207,20 @@ int eaptls_fail(eap_handler_t *handler, int peap_flag) * EAP-Request. We always embed the TLS-length in all EAP-TLS * packets that we send, for easy reference purpose. Handle * fragmentation and sending the next fragment etc. + * + * FIXME: support fragmented start due to TEAP outer tlvs */ -int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) +int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn, bool start) { EAPTLS_PACKET reply; unsigned int size; - unsigned int nlen; unsigned int lbit = 0; + unsigned int obit = 0; + VALUE_PAIR *vp; + vp_cursor_t cursor; + uint32_t nlen; + uint16_t ohdr[2]; + uint32_t olen = 0; /* This value determines whether we set (L)ength flag for EVERY packet we send and add corresponding @@ -257,12 +241,31 @@ int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) if (ssn->length_flag) { lbit = 4; } + + /* + * This is included in the first fragment, and then never + * afterwards. + */ + if (start && ssn->outer_tlvs) { + for (vp = fr_cursor_init(&cursor, &ssn->outer_tlvs); + vp; + vp = fr_cursor_next(&cursor)) { + if (vp->da->type != PW_TYPE_OCTETS) { + DEBUG("FIXME Outer-TLV %s is of not type octets", vp->da->name); + continue; + } + obit = 4; + break; + } + } + if (ssn->fragment == 0) { ssn->tls_msg_len = ssn->dirty_out.used; } - reply.code = FR_TLS_REQUEST; + reply.code = start ? FR_TLS_START : FR_TLS_REQUEST; reply.flags = ssn->peap_flag; + if (start) reply.flags = SET_START(reply.flags); /* Send data, NOT more than the FRAGMENT size */ if (ssn->dirty_out.used > ssn->mtu) { @@ -278,7 +281,16 @@ int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) ssn->fragment = 0; } - reply.dlen = lbit + size; + if (obit) { + for (vp = fr_cursor_init(&cursor, &ssn->outer_tlvs); + vp; + vp = fr_cursor_next(&cursor)) { + if (vp->da->type != PW_TYPE_OCTETS) continue; + olen += sizeof(ohdr) + vp->vp_length; + } + } + + reply.dlen = lbit + obit + size + olen; reply.length = TLS_HEADER_LEN + 1/*flags*/ + reply.dlen; reply.data = talloc_array(eap_ds, uint8_t, reply.length); @@ -286,10 +298,58 @@ int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) if (lbit) { nlen = htonl(ssn->tls_msg_len); - memcpy(reply.data, &nlen, lbit); + memcpy(reply.data, &nlen, sizeof(nlen)); reply.flags = SET_LENGTH_INCLUDED(reply.flags); } - (ssn->record_minus)(&ssn->dirty_out, reply.data + lbit, size); + if (obit) { + nlen = 0; + for (vp = fr_cursor_init(&cursor, &ssn->outer_tlvs); + vp; + vp = fr_cursor_next(&cursor)) { + if (vp->da->type != PW_TYPE_OCTETS) continue; + nlen += sizeof(ohdr) + vp->vp_length; + } + + ssn->outer_tlvs_octets = talloc_array(ssn, uint8_t, olen); + if (!ssn->outer_tlvs_octets) return 0; + + nlen = htonl(nlen); + memcpy(reply.data + lbit, &nlen, sizeof(nlen)); + reply.flags = SET_OUTER_TLV_INCLUDED(reply.flags); + } + + (ssn->record_minus)(&ssn->dirty_out, reply.data + lbit + obit, size); + + /* + * Tack on the outer TLVs after the TLS data. + */ + if (obit) { + olen = 0; + for (vp = fr_cursor_init(&cursor, &ssn->outer_tlvs); + vp; + vp = fr_cursor_next(&cursor)) { + if (vp->da->type != PW_TYPE_OCTETS) continue; + + /* FIXME duplicates eap_teap_tlv_append */ + + /* + * RFC7170, Section 4.3.1 - Outer TLVs must be marked optional + */ + ohdr[0] = htons((vp->da->attr >> fr_attr_shift[1]) & fr_attr_mask[1]); + ohdr[1] = htons(vp->vp_length); + + /* use by Crypto-Binding TLV */ + memcpy(ssn->outer_tlvs_octets + olen, ohdr, sizeof(ohdr)); + olen += sizeof(ohdr); + memcpy(ssn->outer_tlvs_octets + olen, vp->vp_octets, vp->vp_length); + olen += vp->vp_length; + + memcpy(reply.data + lbit + obit + size, ohdr, sizeof(ohdr)); + size += sizeof(ohdr); + memcpy(reply.data + lbit + obit + size, vp->vp_octets, vp->vp_length); + size += vp->vp_length; + } + } eaptls_compose(eap_ds, &reply); talloc_free(reply.data); @@ -425,6 +485,9 @@ static fr_tls_status_t eaptls_verify(eap_handler_t *handler) * from a fragment acknowledgement. */ if (TLS_LENGTH_INCLUDED(eaptls_packet->flags)) { + /* + * data[0] and data[1] are always zero, vi eap_vp2packet() + */ size_t total_len = eaptls_packet->data[2] * 256 | eaptls_packet->data[3]; if (frag_len > total_len) { @@ -463,6 +526,14 @@ static fr_tls_status_t eaptls_verify(eap_handler_t *handler) return FR_TLS_FIRST_FRAGMENT; } + /* + * The "O" bit is only allowed for the first fragment. + */ + if (TLS_OUTER_TLV_INCLUDED(eaptls_packet->flags)) { + REDEBUG("(TLS) EAP Peer set 'O' bit after initial fragment"); + return FR_TLS_INVALID; + } + RDEBUG2("(TLS) EAP Got additional fragment with length (%zu bytes). " "Peer says more fragments will follow", frag_len); @@ -493,6 +564,10 @@ static fr_tls_status_t eaptls_verify(eap_handler_t *handler) return FR_TLS_LENGTH_INCLUDED; } + /* + * eap_vp2packet() ensures that the 'O' bit is not set here. + */ + /* * The previous packet had the M flags set, but this one doesn't, * this must be the final record fragment @@ -563,7 +638,7 @@ static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_st { EAPTLS_PACKET *tlspacket; uint32_t data_len = 0; - uint32_t len = 0; + uint32_t obit = 0; uint8_t *data = NULL; if (status == FR_TLS_INVALID) return NULL; @@ -599,36 +674,8 @@ static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_st tlspacket->flags = eap_ds->response->type.data[0]; /* - * A quick sanity check of the flags. If we've been told - * that there's a length, and there isn't one, then stop. - */ - if (TLS_LENGTH_INCLUDED(tlspacket->flags) && - (tlspacket->length < 5)) { /* flags + TLS message length */ - REDEBUG("(TLS) EAP Invalid packet received: Length bit is set," - "but packet too short to contain length field"); - talloc_free(tlspacket); - return NULL; - } - - /* - * If the final TLS packet is larger than we can handle, die - * now. - * - * Likewise, if the EAP packet says N bytes, and the TLS - * packet says there's fewer bytes, it's a problem. + * eaptls_verify() ensures that all of the flags are correct. */ - if (TLS_LENGTH_INCLUDED(tlspacket->flags)) { - memcpy(&data_len, &eap_ds->response->type.data[1], 4); - data_len = ntohl(data_len); - if (data_len > MAX_RECORD_SIZE) { - REDEBUG("(TLS) EAP Reassembled data will be %u bytes, " - "greater than the size that we can handle (" STRINGIFY(MAX_RECORD_SIZE) " bytes)", - data_len); - talloc_free(tlspacket); - return NULL; - } - } - switch (status) { /* * The TLS Message Length field is four octets, and @@ -640,30 +687,19 @@ static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_st * length should solve the problem. */ case FR_TLS_FIRST_FRAGMENT: - case FR_TLS_LENGTH_INCLUDED: - case FR_TLS_MORE_FRAGMENTS_WITH_LENGTH: - if (tlspacket->length < 5) { /* flags + TLS message length */ - REDEBUG("(TLS) EAP Invalid packet received: Expected length, got none"); - talloc_free(tlspacket); - return NULL; - } + obit = TLS_OUTER_TLV_INCLUDED(tlspacket->flags) << 2; /* - * Extract all the TLS fragments from the - * previous eap_ds Start appending this - * fragment to the above ds + * @todo - decode outer TLVs, too */ - memcpy(&data_len, &eap_ds->response->type.data[1], sizeof(uint32_t)); - data_len = ntohl(data_len); - data = (eap_ds->response->type.data + 5/*flags+TLS-Length*/); - len = eap_ds->response->type.length - 5/*flags+TLS-Length*/; - /* - * Hmm... this should be an error, too. - */ - if (data_len > len) { - data_len = len; - } + /* FALL-THROUGH */ + + case FR_TLS_LENGTH_INCLUDED: + case FR_TLS_MORE_FRAGMENTS_WITH_LENGTH: + memcpy(&data_len, &eap_ds->response->type.data[1], 4); + data_len = ntohl(data_len); + data = eap_ds->response->type.data + 5 + obit; break; /* @@ -671,8 +707,8 @@ static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_st */ case FR_TLS_MORE_FRAGMENTS: case FR_TLS_OK: - data_len = eap_ds->response->type.length - 1/*flags*/; - data = eap_ds->response->type.data + 1/*flags*/; + data_len = eap_ds->response->type.length - 1; + data = eap_ds->response->type.data + 1; break; default: @@ -689,6 +725,7 @@ static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_st talloc_free(tlspacket); return NULL; } + memcpy(tlspacket->data, data, data_len); } @@ -784,7 +821,7 @@ static fr_tls_status_t eaptls_operation(fr_tls_status_t status, eap_handler_t *h * TLS proper can decide what to do, then. */ if (tls_session->dirty_out.used > 0) { - eaptls_request(handler->eap_ds, tls_session); + eaptls_request(handler->eap_ds, tls_session, false); return FR_TLS_HANDLED; } @@ -890,7 +927,7 @@ fr_tls_status_t eaptls_process(eap_handler_t *handler) * of fragments" phase. */ case FR_TLS_REQUEST: - eaptls_request(handler->eap_ds, tls_session); + eaptls_request(handler->eap_ds, tls_session, false); status = FR_TLS_HANDLED; goto done; diff --git a/src/modules/rlm_eap/libeap/eap_tls.h b/src/modules/rlm_eap/libeap/eap_tls.h index 8e5fc773d6..08713aa0a1 100644 --- a/src/modules/rlm_eap/libeap/eap_tls.h +++ b/src/modules/rlm_eap/libeap/eap_tls.h @@ -59,10 +59,12 @@ fr_tls_status_t eaptls_process(eap_handler_t *handler); int eaptls_success(eap_handler_t *handler, int peap_flag) CC_HINT(nonnull); int eaptls_fail(eap_handler_t *handler, int peap_flag) CC_HINT(nonnull); -int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn) CC_HINT(nonnull); +int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn, bool start) CC_HINT(nonnull); +void TLS_PRF(SSL *ssl, unsigned char *sec, size_t seclen, struct iovec *iov, size_t iovcnt, unsigned char *key, size_t keylen); void T_PRF(unsigned char const *secret, unsigned int secret_len, char const *prf_label, unsigned char const *seed, unsigned int seed_len, unsigned char *out, unsigned int out_len) CC_HINT(nonnull(1,3,6)); +void eaptls_gen_keys_only(REQUEST *request, SSL *s, char const *label, uint8_t const *context, UNUSED size_t context_size, uint8_t *out, size_t outlen); void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t const *context, size_t context_size); void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size); void eaptls_gen_eap_key(eap_handler_t *handler); @@ -101,7 +103,6 @@ typedef struct tls_packet { EAPTLS_PACKET *eaptls_alloc(void); void eaptls_free(EAPTLS_PACKET **eaptls_packet_ptr); tls_session_t *eaptls_session(eap_handler_t *handler, fr_tls_server_conf_t *tls_conf, bool client_cert, bool allow_tls13); -int eaptls_start(EAP_DS *eap_ds, int peap); int eaptls_compose(EAP_DS *eap_ds, EAPTLS_PACKET *reply); fr_tls_server_conf_t *eaptls_conf_parse(CONF_SECTION *cs, char const *key); diff --git a/src/modules/rlm_eap/libeap/eap_types.h b/src/modules/rlm_eap/libeap/eap_types.h index c6568ffedf..beee998651 100644 --- a/src/modules/rlm_eap/libeap/eap_types.h +++ b/src/modules/rlm_eap/libeap/eap_types.h @@ -98,7 +98,9 @@ typedef enum eap_method { PW_EAP_GPSK, /* 51 */ PW_EAP_PWD, /* 52 */ PW_EAP_EKE, /* 53 */ - PW_EAP_MAX_TYPES /* 54 - for validation */ + PW_EAP_PT_EAP, /* 54 */ + PW_EAP_TEAP, /* 55 */ + PW_EAP_MAX_TYPES /* 56 - for validation */ } eap_type_t; #define PW_EAP_EXPANDED_TYPE (254) diff --git a/src/modules/rlm_eap/libeap/eapcommon.c b/src/modules/rlm_eap/libeap/eapcommon.c index 96db30b144..4f85fd3735 100644 --- a/src/modules/rlm_eap/libeap/eapcommon.c +++ b/src/modules/rlm_eap/libeap/eapcommon.c @@ -302,6 +302,7 @@ eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps) uint16_t len; int total_len; vp_cursor_t cursor; + bool allow_o = false; /* * Get only EAP-Message attribute list @@ -315,7 +316,7 @@ eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps) /* * Sanity check the length before doing anything. */ - if (first->vp_length < 4) { + if (first->vp_length < 5) { fr_strerror_printf("EAP packet is too short"); return NULL; } @@ -330,8 +331,8 @@ eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps) /* * Take out even more weird things. */ - if (len < 4) { - fr_strerror_printf("EAP packet has invalid length (less than 4 bytes)"); + if (len < 5) { + fr_strerror_printf("EAP packet has invalid length (less than 5 bytes)"); return NULL; } @@ -379,6 +380,125 @@ eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps) ptr += i->vp_length; } + /* + * Do additional sanity check for TLS-based EAP types, so + * that we don't have to do any of that later. + */ + switch (eap_packet->data[0]) { + /* + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Code | Identifier | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Flags | Ver | Message Length : + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * : Message Length | + * + * Flags are: + * + * 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+ + * |L M S O R R R R| + * +-+-+-+-+-+-+-+-+ + * + * L = Length included + * M = More fragments + * S = EAP-TLS start + * O = outer TLV length included (4 octets, only for TEAP) + * R = Reserved + */ + case PW_EAP_TEAP: + allow_o = true; + /* FALL-THROUGH */ + + case PW_EAP_TLS: + case PW_EAP_TTLS: + case PW_EAP_PEAP: + case PW_EAP_FAST: + if (len < 2) { + fr_strerror_printf("Malformed EAP packet - packet is too small to contain TLS flags"); + talloc_free(eap_packet); + return NULL; + } + + /* + * L bit set means we have 4 octets of Length + * following the flags field. + */ + if ((eap_packet->data[1] & 0x80) != 0) { + uint32_t tls_len; + + if (len <= (2 + 4)) { + fr_strerror_printf("Malformed EAP packet - TLS 'L' bit is set, but packet is too small to contain 'length' field"); + talloc_free(eap_packet); + return NULL; + } + + /* + * This is arguably wrong... a single TLS + * record is max 16K in length. But a + * TLS message may span multiple TLS + * records. + */ + memcpy(&tls_len, eap_packet->data + 2, 4); + tls_len = ntohl(tls_len); + if (tls_len > MAX_RECORD_SIZE) { + fr_strerror_printf("Malformed EAP packet - TLS reassembled data length %u (%08x) (will be greater than the TLS maximum record size of 16384 bytes", tls_len, tls_len); + talloc_free(eap_packet); + return NULL; + } + + /* + * O bit set means we have 4 octets of Outer TLV Length + * following the Length field. + */ + if ((eap_packet->data[1] & 0x10) != 0) { + uint32_t tlv_len; + + if (!allow_o) { + fr_strerror_printf("Malformed EAP packet - TLS 'O' bit is set, but EAP method does not use it."); + talloc_free(eap_packet); + return NULL; + } + + if (len <= (2 + 4 + 4)) { + fr_strerror_printf("Malformed EAP packet - TLS 'O' bit is set, but packet is too small to contain 'outer tlv length' field"); + talloc_free(eap_packet); + return NULL; + } + + memcpy(&tlv_len, eap_packet->data + 2 + 4, 4); + tlv_len = ntohl(tlv_len); + + /* + * The EAP header includes all of + * the data in the packet. The + * outer TLV length cannot + * include the EAP header, type, + * flags, length field, or outer + * tlv length field. + */ + if ((int)tlv_len > (len - (2 + 4 + 4))) { + fr_strerror_printf("Malformed EAP packet - TLS 'O' bit is set, but 'outer tlv length' field is larger than the current fragment"); + talloc_free(eap_packet); + return NULL; + } + } + } else { + if ((eap_packet->data[1] & 0x10) != 0) { + fr_strerror_printf("Malformed EAP packet - TLS 'O' bit is set, but 'L' bit is not set."); + talloc_free(eap_packet); + return NULL; + } + + } + break; + + default: + break; + } + return eap_packet; } diff --git a/src/modules/rlm_eap/libeap/mppe_keys.c b/src/modules/rlm_eap/libeap/mppe_keys.c index 385441c62f..4a54290935 100644 --- a/src/modules/rlm_eap/libeap/mppe_keys.c +++ b/src/modules/rlm_eap/libeap/mppe_keys.c @@ -26,6 +26,7 @@ RCSID("$Id$") USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ #include "eap_tls.h" +#include #include #include #include @@ -34,6 +35,28 @@ USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ #include #endif +void TLS_PRF(SSL *ssl, + unsigned char *sec, size_t seclen, + struct iovec *iov, size_t iovcnt, + unsigned char *key, size_t keylen) +{ + const EVP_MD *md = SSL_CIPHER_get_handshake_digest(SSL_get_current_cipher(ssl)); + + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL); + + EVP_PKEY_derive_init(pctx); + EVP_PKEY_CTX_set_tls1_prf_md(pctx, md); + EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, seclen); + + for (unsigned int i = 0; i < iovcnt; i++) { + EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, iov[i].iov_base, iov[i].iov_len); + } + + EVP_PKEY_derive(pctx, key, &keylen); + + EVP_PKEY_CTX_free(pctx); +} + /* * TLS P_hash from RFC 2246/5246 section 5 */ @@ -210,23 +233,20 @@ void T_PRF(unsigned char const *secret, unsigned int secret_len, #define EAPTLS_MPPE_KEY_LEN 32 /* - * Generate keys according to RFC 2716 and add to reply + * Generate keys according to RFC 5216 (section 2.3) */ -void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t const *context, UNUSED size_t context_size) +void eaptls_gen_keys_only(UNUSED REQUEST *request, SSL *s, char const *label, uint8_t const *context, UNUSED size_t context_size, uint8_t *out, size_t outlen) { - uint8_t out[4 * EAPTLS_MPPE_KEY_LEN]; - uint8_t *p; - size_t len; - - len = strlen(label); + size_t len = strlen(label); #if OPENSSL_VERSION_NUMBER >= 0x10001000L - if (SSL_export_keying_material(s, out, sizeof(out), label, len, context, context_size, context != NULL) != 1) { + if (SSL_export_keying_material(s, out, outlen, label, len, context, context_size, context != NULL) != 1) { ERROR("Failed generating keying material"); return; } #else { + uint8_t *p; uint8_t seed[64 + (2 * SSL3_RANDOM_SIZE) + (context ? 2 + context_size : 0)]; uint8_t buf[4 * EAPTLS_MPPE_KEY_LEN]; @@ -255,9 +275,20 @@ void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t c } PRF(s->session->master_key, s->session->master_key_length, - seed, len, out, buf, sizeof(out)); + seed, len, out, buf, outlen); } #endif +} + +/* + * Generate keys according to RFC 5216 (section 2.3) and add to reply + */ +void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t const *context, UNUSED size_t context_size) +{ + uint8_t out[4 * EAPTLS_MPPE_KEY_LEN]; + uint8_t *p; + + eaptls_gen_keys_only(request, s, label, context, context_size, out, sizeof(out)); p = out; eap_add_reply(request, "MS-MPPE-Recv-Key", p, EAPTLS_MPPE_KEY_LEN); @@ -268,7 +299,6 @@ void eaptls_gen_mppe_keys(REQUEST *request, SSL *s, char const *label, uint8_t c eap_add_reply(request, "EAP-EMSK", out + 64, 64); } - #define FR_TLS_PRF_CHALLENGE "ttls challenge" /* diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c index 093dc868cd..d1f45b7976 100644 --- a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c +++ b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c @@ -479,7 +479,7 @@ static int mod_process(void *arg, eap_handler_t *handler) case PW_CODE_ACCESS_CHALLENGE: RDEBUG("Challenge"); tls_handshake_send(request, tls_session); - eaptls_request(handler->eap_ds, tls_session); + eaptls_request(handler->eap_ds, tls_session, false); ret = 1; goto done; diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/peap.c b/src/modules/rlm_eap/types/rlm_eap_peap/peap.c index a8589aeaea..bf84243037 100644 --- a/src/modules/rlm_eap/types/rlm_eap_peap/peap.c +++ b/src/modules/rlm_eap/types/rlm_eap_peap/peap.c @@ -591,8 +591,6 @@ static int CC_HINT(nonnull) eappeap_postproxy(eap_handler_t *handler, void *data fprintf(fr_log_fp, "server %s {\n", fake->server); } - fake->reply->code = PW_CODE_ACCESS_ACCEPT; - /* * Perform a post-auth stage, which will get the EAP * handler, too... @@ -667,7 +665,7 @@ static int CC_HINT(nonnull) eappeap_postproxy(eap_handler_t *handler, void *data case RLM_MODULE_HANDLED: RDEBUG2("Reply was handled"); - eaptls_request(handler->eap_ds, tls_session); + eaptls_request(handler->eap_ds, tls_session, false); request->proxy_reply->code = PW_CODE_ACCESS_CHALLENGE; return 1; diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c b/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c index d9f850cef2..704b86c262 100644 --- a/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c +++ b/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c @@ -233,7 +233,7 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) * TLS session initialization is over. Now handle TLS * related handshaking or application data. */ - status = eaptls_start(handler->eap_ds, ssn->peap_flag); + status = eaptls_request(handler->eap_ds, ssn, true); if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) { REDEBUG("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "")); } else { @@ -357,7 +357,7 @@ static int mod_process(void *arg, eap_handler_t *handler) goto done; case RLM_MODULE_HANDLED: - eaptls_request(handler->eap_ds, tls_session); + eaptls_request(handler->eap_ds, tls_session, false); ret = 1; goto done; diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c index d327c575fc..7a78fb6f5d 100644 --- a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c +++ b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c @@ -135,7 +135,7 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) * TLS session initialization is over. Now handle TLS * related handshaking or application data. */ - status = eaptls_start(handler->eap_ds, ssn->peap_flag); + status = eaptls_request(handler->eap_ds, ssn, true); if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) { REDEBUG("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "")); } else { diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c index 4e53c92244..035a1f6044 100644 --- a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c +++ b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c @@ -204,7 +204,7 @@ static int mod_session_init(void *type_arg, eap_handler_t *handler) * TLS session initialization is over. Now handle TLS * related handshaking or application data. */ - status = eaptls_start(handler->eap_ds, ssn->peap_flag); + status = eaptls_request(handler->eap_ds, ssn, true); if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) { REDEBUG("[eaptls start] = %s", fr_int2str(fr_tls_status_table, status, "")); } else { @@ -284,7 +284,7 @@ static int mod_process(void *arg, eap_handler_t *handler) ret = eaptls_success(handler, 0); goto done; } else { - eaptls_request(handler->eap_ds, tls_session); + eaptls_request(handler->eap_ds, tls_session, false); } ret = 1; goto done; @@ -341,7 +341,7 @@ static int mod_process(void *arg, eap_handler_t *handler) * Access-Challenge, continue tunneled conversation. */ case PW_CODE_ACCESS_CHALLENGE: - eaptls_request(handler->eap_ds, tls_session); + eaptls_request(handler->eap_ds, tls_session, false); ret = 1; goto done; diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c b/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c index cbe423951a..f4d28660cf 100644 --- a/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c +++ b/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c @@ -914,7 +914,7 @@ static int CC_HINT(nonnull) eapttls_postproxy(eap_handler_t *handler, void *data case RLM_MODULE_HANDLED: RDEBUG("Reply was handled"); - eaptls_request(handler->eap_ds, tls_session); + eaptls_request(handler->eap_ds, tls_session, false); request->proxy_reply->code = PW_CODE_ACCESS_CHALLENGE; return 1; -- 2.47.3