71RCSID(
"$Id: e8a0f50fe8ff40abcba8d3bdf8653c5ab0d05b6a $")
74#include <freeradius-devel/unlang/action.h>
75#include <freeradius-devel/unlang/function.h>
76#include <freeradius-devel/server/pair.h>
115 fr_dbuff_t *record,
size_t record_len,
size_t frag_len)
126 RDEBUG3(
"Setting flags %c%c%c%c%c%c%c%c",
144 if (record)
len += frag_len;
148 if (record_len != 0)
len += frag_len;
184 net_record_len = htonl(record_len);
185 memcpy(p, &net_record_len,
sizeof(net_record_len));
186 p +=
sizeof(net_record_len);
270 fr_tls_session_t *tls_session = eap_tls_session->
tls_session;
280 eap_tls_session->
base_flags, NULL, 0, 0) < 0)
return -1;
282 if (!prf_label)
return 0;
298 &session_id, eap_session->
type) < 0) {
331 fr_tls_session_t *tls_session = eap_tls_session->
tls_session;
338 eap_tls_session->
base_flags, NULL, 0, 0) < 0) {
339 REDEBUG(
"Failed composing EAP-Failure");
347 return fr_tls_session_fail_session(
request, tls_session);
384 fr_tls_session_t *tls_session = eap_tls_session->
tls_session;
387 bool length_included;
422 RDEBUG2(
"Complete TLS record (%zu bytes) larger than MTU (%zu bytes), will fragment",
424 RDEBUG2(
"Sending first TLS record fragment (%zu bytes), %zu bytes remaining",
427 RDEBUG2(
"Sending additional TLS record fragment (%zu bytes), %zu bytes remaining",
439 RDEBUG2(
"Sending complete TLS record (%zu bytes)", frag_len);
441 RDEBUG2(
"Sending final TLS record fragment (%zu bytes)", frag_len);
479 RDEBUG2(
"ACKing Peer's TLS record fragment");
496 fr_tls_session_t *tls_session = eap_tls_session->
tls_session;
498 if (tls_session == NULL){
499 REDEBUG(
"Unexpected ACK received: No ongoing SSL tls_session");
502 if (!tls_session->info.initialized) {
503 RDEBUG2(
"No SSL info available. Waiting for more SSL data");
507 if ((tls_session->info.content_type == SSL3_RT_HANDSHAKE) &&
508 (tls_session->info.origin == TLS_INFO_ORIGIN_RECORD_RECEIVED)) {
509 REDEBUG(
"Unexpected ACK received: We sent no previous messages");
513 switch (tls_session->info.content_type) {
515 RDEBUG2(
"Peer ACKed our alert");
518 case SSL3_RT_HANDSHAKE:
519 if (fr_tls_session_is_init_finished(tls_session) && (
fr_dbuff_remaining(tls_session->dirty_out) == 0)) {
520 RDEBUG2(
"Peer ACKed our handshake fragment. handshake is finished");
527 tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
531 RDEBUG2(
"Peer ACKed our handshake fragment");
535 case SSL3_RT_APPLICATION_DATA:
536 RDEBUG2(
"Peer ACKed our application data fragment");
548 if (tls_session->info.origin == TLS_INFO_ORIGIN_RECORD_SENT) {
552 REDEBUG(
"Invalid ACK received: %d", tls_session->info.content_type);
580 size_t frag_len, header_len;
588 REDEBUG(
"Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
604 REDEBUG(
"Invalid EAP-TLS packet; no data");
611 RDEBUG3(
"Peer sent flags %c%c%c%c%c%c%c%c",
627 REDEBUG(
"Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
641 ((eap_tls_data->
flags & 0xc0) == 0x00)) {
643 REDEBUG(
"Received Invalid TLS ACK");
653 REDEBUG(
"Peer sent EAP-TLS Start message (only the server is allowed to do this)");
666 REDEBUG(
"Peer sent EAP-TLS with zero-length fragment and 'more' bit set - if there is no data, there should not be more!");
686 if (eap_tls_data->
data[0] || eap_tls_data->
data[1]) {
687 REDEBUG(
"TLS record length is > 65536");
691 total_len = eap_tls_data->
data[2] * 256 | eap_tls_data->
data[3];
692 if (frag_len > total_len) {
693 REDEBUG(
"TLS fragment length (%zu bytes) greater than TLS record length (%zu bytes)",
694 frag_len, total_len);
698 if (total_len > SSL3_RT_MAX_PLAIN_LENGTH) {
699 REDEBUG(
"Reassembled TLS record will be %zu bytes, "
700 "greater than our maximum record size (" STRINGIFY(SSL3_RT_MAX_PLAIN_LENGTH)
" bytes)",
719 RDEBUG2(
"Peer indicated complete TLS record size will be %zu bytes", total_len);
730 RDEBUG2(
"Expecting %i TLS record fragments",
731 (
int)((((total_len - frag_len) + ((frag_len + 4) - 1)) / (frag_len + 4)) + 1));
738 RDEBUG2(
"Got first TLS record fragment (%zu bytes). Peer indicated more fragments "
739 "to follow", frag_len);
750 if (total_len != frag_len) {
751 REDEBUG(
"Peer indicated no more fragments, but TLS record length (%zu bytes) "
752 "does not match EAP-TLS data length (%zu bytes)", total_len, frag_len);
762 RDEBUG2(
"Got complete TLS record, with length field (%zu bytes)", frag_len);
773 REDEBUG(
"TLS More (M) flag set, but no fragmented record transfer was in progress");
781 RDEBUG2(
"Got additional TLS record fragment (%zu bytes). Peer indicated more fragments to follow",
785 REDEBUG(
"Total received TLS record fragments (%zu bytes), exceeds "
786 "indicated TLS record length (%zu bytes)",
804 RDEBUG2(
"Got final TLS record fragment (%zu bytes)", frag_len);
807 REDEBUG(
"Total received TLS record fragments (%zu bytes), does not equal indicated "
808 "TLS record length (%zu bytes)",
819 RDEBUG2(
"Got complete TLS record (%zu bytes)", frag_len);
837 fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->
tls_session, fr_tls_session_t);
840 switch (tls_session->result) {
841 case FR_TLS_RESULT_IN_PROGRESS:
846 case FR_TLS_RESULT_ERROR:
847 REDEBUG(
"TLS receive handshake failed during operation");
850 case FR_TLS_RESULT_SUCCESS:
877 if ((tls_session->info.version == TLS1_3_VERSION) &&
878 (tls_session->peer_cert_ok || eap_tls_session->
authentication_success || SSL_session_reused(tls_session->ssl))) {
886 if (!tls_session->sent_commitment) {
887 RDEBUG2(
"(TLS) EAP Sending final Commitment Message.");
889 tls_session->sent_commitment =
true;
895 if (SSL_is_init_finished(tls_session->ssl)) fr_tls_session_send(
request, tls_session);
901 ret = fr_tls_session_async_handshake_push(
request, tls_session);
904 REDEBUG(
"TLS receive handshake failed during operation");
916 REDEBUG(
"TLS failed composing a response");
931 if (eap_tls_session->
phase2 || fr_tls_session_is_init_finished(tls_session)) {
932 eap_tls_session->
phase2 =
true;
938 tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
946 REDEBUG(
"TLS failed during operation");
972 fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->
tls_session, fr_tls_session_t);
1021 fr_tls_session_t *tls_session = eap_tls_session->
tls_session;
1031 RDEBUG2(
"Continuing EAP-TLS");
1037 switch (eap_tls_session->
state) {
1053 switch (eap_tls_session->
state) {
1089 REDEBUG(
"Exceeded maximum record size");
1111 if (eap_tls_session->
phase2 || fr_tls_session_is_init_finished(tls_session)) {
1114 eap_tls_session->
phase2 =
true;
1116 ret = fr_tls_session_recv(
request, tls_session);
1146 fr_tls_session_is_init_finished(tls_session)) {
1147 eap_tls_session->
phase2 =
true;
1194 SSL_CTX *ssl_ctx,
bool client_cert)
1197 fr_tls_session_t *tls_session;
1198 fr_tls_conf_t *
conf = fr_tls_ctx_conf(ssl_ctx);
1207 eap_session->
tls =
true;
1244 SSL_CTX_set_max_early_data(ssl_ctx, 0);
1254 eap_tls_session->
tls_session = tls_session = fr_tls_session_alloc_server(eap_tls_session, ssl_ctx,
1256 if (
unlikely(!tls_session))
return NULL;
1265 tls_session->mtu =
conf->fragment_size - 10;
1266 if (
vp && (
vp->vp_uint32 > 100) && (
vp->vp_uint32 < tls_session->mtu)) {
1267 RDEBUG2(
"Setting fragment_len from %pP",
vp);
1268 tls_session->mtu =
vp->vp_uint32;
1280 fr_tls_session_extra_pair_add_shallow(tls_session, identity);
1290 type_vp->vp_uint32 = eap_session->
type;
1291 fr_tls_session_extra_pair_add_shallow(tls_session, type_vp);
1297 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_EAP_SESSION, (
void *)eap_session);
1298 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (
void *)tls_session);
1299 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (
void *)
conf);
1300 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_IDENTITY, (
void *)&(eap_session->
identity));
1304 if (tls_max && tls_min && (tls_min->vp_float32 > tls_max->vp_float32)) {
1305 RERROR(
"Can't set TLS min version greater than max version");
1306 goto skip_tls_version;
1309#define SET_TLS_VERSION(_type) \
1310 if (tls_ ## _type) { \
1311 int tls_version = 0; \
1312 if (tls_ ## _type->vp_float32 >= (float) 1.3) { \
1313 tls_version = TLS1_3_VERSION; \
1314 } else if (tls_ ## _type->vp_float32 >= (float) 1.2) { \
1315 tls_version = TLS1_2_VERSION; \
1316 } else if (tls_ ## _type->vp_float32 >= (float) 1.1) { \
1317 tls_version = TLS1_1_VERSION; \
1319 if (tls_version) { \
1320 if (SSL_set_ ## _type ## _proto_version(tls_session->ssl, tls_version) != 1) {\
1321 RERROR("Failed to set %pP", tls_ ## _type); \
1323 RDEBUG2("Setting TLS " #_type " version to %0.1f", (double) tls_ ## _type->vp_float32); \
1326 RWARN("Invalid value %pP", tls_ ## _type); \
1334 return eap_tls_session;
1357 if (!tls_conf->cache.min_lifetime_is_set ||
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
static uint8_t request[4]
#define USES_APPLE_DEPRECATED_API
#define L(_str)
Helper for initialising arrays of string literals.
A section grouping multiple CONF_PAIR.
#define cf_log_warn_by_child(_parent, _child, _fmt,...)
Log a warning message against a specified child.
eap_packet_t * response
Packet we received from the peer.
eap_packet_t * request
Packet we will send to the peer.
Contains a pair of request and response packets.
static size_t min(size_t x, size_t y)
#define fr_dbuff_out_memcpy(_out, _dbuff_or_marker, _outlen)
Copy exactly _outlen bytes from the dbuff.
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
#define fr_dbuff_in_memcpy_partial(_out, _in, _inlen)
Copy at most _inlen bytes into the dbuff.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
void unlang_interpet_frame_discard(request_t *request)
Discard the bottom most frame on the request's stack.
HIDDEN fr_dict_attr_t const * attr_eap_identity
HIDDEN fr_dict_attr_t const * attr_tls_min_version
HIDDEN fr_dict_attr_t const * attr_framed_mtu
HIDDEN fr_dict_attr_t const * attr_eap_session_id
HIDDEN fr_dict_attr_t const * attr_tls_max_version
HIDDEN fr_dict_attr_t const * attr_eap_type
int eap_crypto_mppe_keys(request_t *request, SSL *ssl, eap_tls_prf_label_t *prf_label)
Generate keys according to RFC 5216 and add to the reply.
int eap_crypto_tls_session_id(TALLOC_CTX *ctx, request_t *request, SSL *ssl, eap_tls_prf_label_t *prf_label, uint8_t **out, uint8_t eap_type)
char * identity
NAI (User-Name) from EAP-Identity.
void * opaque
Opaque data used by EAP methods.
bool tls
Whether EAP method uses TLS.
eap_type_t type
EAP method number.
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
eap_round_t * prev_round
Previous response/request pair.
bool finished
Whether we consider this session complete.
Tracks the progress of a single session of any EAP method.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RINDENT()
Indent R* messages by one level.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
int fr_pair_value_memdup_buffer_shallow(fr_pair_t *vp, uint8_t const *src, bool tainted)
Assign a talloced buffer to a "octets" type value pair.
#define pair_delete_reply(_pair_or_da)
Delete a fr_pair_t in the reply list.
#define pair_append_reply(_attr, _da)
Allocate and append a fr_pair_t to reply list.
@ FR_SIGNAL_NONE
No signals.
fr_pair_value_bstrdup_buffer(vp, eap_session->identity, true)
Stores an attribute, a value and various bits of other data.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in an arbitrarily ordered array of name to num mappings.
#define fr_time_delta_lt(_a, _b)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
int eap_tls_success(request_t *request, eap_session_t *eap_session, eap_tls_prf_label_t *prf_label)
Send an EAP-TLS success.
static eap_tls_status_t eap_tls_verify(request_t *request, eap_session_t *eap_session)
Check that this EAP-TLS packet is correct and the progression of EAP-TLS packets is sane.
eap_tls_session_t * eap_tls_session_init(request_t *request, eap_session_t *eap_session, SSL_CTX *ssl_ctx, bool client_cert)
Create a new fr_tls_session_t associated with an eap_session_t.
static unlang_action_t eap_tls_handshake_push(request_t *request, eap_session_t *eap_session)
Push functions to continue the handshake asynchronously.
static int eap_tls_ack(request_t *request, eap_session_t *eap_session)
ACK a fragment of the TLS record from the peer.
void eap_tls_conf_check(CONF_SECTION *cs, fr_tls_conf_t *tls_conf)
Apply the limits that EAP puts on a parsed tls { ... } section.
size_t eap_tls_status_table_len
int eap_tls_compose(request_t *request, eap_session_t *eap_session, eap_tls_status_t status, uint8_t flags, fr_dbuff_t *record, size_t record_len, size_t frag_len)
Convert the EAP-TLS reply packet into an EAP packet.
int eap_tls_start(request_t *request, eap_session_t *eap_session)
Send an initial EAP-TLS request to the peer.
int eap_tls_request(request_t *request, eap_session_t *eap_session)
Frames the OpenSSL data that needs to be sent to the client in an EAP-Request.
#define SET_TLS_VERSION(_type)
unlang_action_t eap_tls_fail(request_t *request, eap_session_t *eap_session)
Send an EAP-TLS failure.
USES_APPLE_DEPRECATED_API fr_table_num_ordered_t const eap_tls_status_table[]
static eap_tls_status_t eap_tls_session_status(request_t *request, eap_session_t *eap_session)
Reduce session states down into an easy to use status.
static unlang_action_t eap_tls_handshake_resume(request_t *request, void *uctx)
Process the result from the last TLS handshake round.
unlang_action_t eap_tls_process(request_t *request, eap_session_t *eap_session)
Process an EAP TLS request.
Generic EAP over TLS API.
int base_flags
Some protocols use the reserved bits of the EAP-TLS flags (such as PEAP).
@ EAP_TLS_RECORD_RECV_FIRST
Received first fragment of a record.
@ EAP_TLS_INVALID
Invalid, don't reply.
@ EAP_TLS_HANDLED
TLS code has handled it.
@ EAP_TLS_RECORD_RECV_MORE
Received additional fragment of a record.
@ EAP_TLS_ACK_SEND
Acknowledge receipt of a record or record fragment.
@ EAP_TLS_RECORD_SEND
We're sending a record.
@ EAP_TLS_RECORD_RECV_COMPLETE
Received final fragment of a record.
@ EAP_TLS_START_SEND
We're starting a new TLS session.
@ EAP_TLS_FAIL
Fail, send fail.
@ EAP_TLS_ESTABLISHED
Session established, send success (or start phase2).
eap_tls_status_t state
The state of the EAP-TLS session.
bool phase2
Whether we're in phase 2.
#define TLS_MORE_FRAGMENTS(x)
fr_tls_session_t * tls_session
TLS session used to authenticate peer or tunnel sensitive data.
bool record_in_started
Whether a record transfer from the peer is currently in progress.
size_t record_out_total_len
Actual/Total TLS message length we're sending.
#define SET_LENGTH_INCLUDED(x)
size_t record_in_total_len
How long the peer indicated the complete tls record would be.
bool record_out_started
for methods with inner auth, if the inner auth succeeded.
size_t record_in_recvd_len
How much of the record we've received so far.
#define TLS_LENGTH_INCLUDED(x)
#define TLS_HEADER_LENGTH_FIELD_LEN
#define SET_MORE_FRAGMENTS(x)
bool authentication_success
bool include_length
A flag to include length in every TLS Data/Alert packet.
Tracks the state of an EAP-TLS session.
static fr_sbuff_err_t char size_t fr_sbuff_t size_t max
static fr_sbuff_err_t char size_t * len
#define fr_box_time_delta(_val)