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.
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");
}
* 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
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) {
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);
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);
* 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) {
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);
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
{
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;
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
* 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;
/*
*/
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:
talloc_free(tlspacket);
return NULL;
}
+
memcpy(tlspacket->data, data, data_len);
}
* 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;
}
* 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;
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);
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);
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)
uint16_t len;
int total_len;
vp_cursor_t cursor;
+ bool allow_o = false;
/*
* Get only EAP-Message attribute list
/*
* 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;
}
/*
* 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;
}
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;
}
USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
#include "eap_tls.h"
+#include <openssl/kdf.h>
#include <openssl/ssl.h>
#include <openssl/hmac.h>
#include <freeradius-devel/openssl3.h>
#include <openssl/provider.h>
#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
*/
#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];
}
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);
eap_add_reply(request, "EAP-EMSK", out + 64, 64);
}
-
#define FR_TLS_PRF_CHALLENGE "ttls challenge"
/*
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;
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...
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;
* 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, "<INVALID>"));
} else {
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;
* 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, "<INVALID>"));
} else {
* 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, "<INVALID>"));
} else {
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;
* 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;
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;