23RCSID(
"$Id: 09eed869b36e6a7d79a82824f617870c24348ccb $")
25#include <freeradius-devel/eap/tls.h>
71#define EAP_TLV_SUCCESS (1)
72#define EAP_TLV_FAILURE (2)
73#define EAP_TLV_ACK_RESULT (3)
75#define FR_PEAP_EXTENSIONS_TYPE 33
135 tlv_packet[5] = 0x80;
142 (tls_session->record_from_buff)(&tls_session->clean_in, tlv_packet, 11);
147 fr_tls_session_send(request, tls_session);
168 tlv_packet[5] = 0x80;
175 (tls_session->record_from_buff)(&tls_session->clean_in, tlv_packet, 11);
180 fr_tls_session_send(request, tls_session);
196 (tls_session->record_from_buff)(&tls_session->clean_in, &eap_packet,
sizeof(eap_packet));
197 fr_tls_session_send(request, tls_session);
198 (tls_session->record_init)(&tls_session->clean_in);
225 switch (peap_tunnel->
status) {
229 REDEBUG(
"Invalid inner tunnel data, expected method (%u), got (%u)",
239 eap_method =
data[0];
240 switch (eap_method) {
242 RDEBUG2(
"Received EAP-Identity-Response");
268 if (data_len > 65535)
return;
272 if (total > 249) total = 249;
285 while (total < data_len) {
289 total +=
vp->vp_length;
311 (tls_session->record_from_buff)(&tls_session->clean_in, this->vp_octets +
EAP_HEADER_LEN,
320 (tls_session->record_from_buff)(&tls_session->clean_in, this->vp_octets, this->vp_length);
323 fr_tls_session_send(request, tls_session);
336 if (data_len < 11)
return 0;
348 RDEBUG2(
"Client rejected our response. The password is probably incorrect");
366 fr_tls_session_t *tls_session = eap_tls_session->
tls_session;
383 RDEBUG2(
"Got tunneled reply code %i", reply->
code);
388 switch (reply->
code) {
390 RDEBUG2(
"Tunneled authentication was successful");
396 RDEBUG2(
"Tunneled authentication was rejected");
402 RDEBUG2(
"Got tunneled Access-Challenge");
423 RDEBUG2(
"Unknown RADIUS packet type %d: rejecting tunneled user", reply->
code);
433 return "TUNNEL ESTABLISHED";
436 return "WAITING FOR INNER IDENTITY";
439 return "send tlv success";
442 return "send tlv failure";
445 return "phase2_init";
475 data_len = tls_session->clean_out.used;
476 tls_session->clean_out.used = 0;
477 data = tls_session->clean_out.data;
482 REDEBUG(
"Tunneled data is invalid");
490 if (SSL_session_reused(tls_session->ssl)) {
491 RDEBUG2(
"Skipping Phase2 because of session resumption");
509 REDEBUG(
"Expected EAP-Identity, got something else");
545 RDEBUG2(
"Client rejected session resumption. Re-starting full authentication");
558 REDEBUG(
"Sent a success, but received something weird in return");
567 REDEBUG(
"The users session was previously rejected: returning reject (again.)");
568 RIDEBUG(
"This means you need to read the PREVIOUS messages in the debug output");
569 RIDEBUG(
"to find out the reason why the user was rejected");
570 RIDEBUG(
"Look for \"reject\" or \"fail\". Those earlier messages will tell you");
571 RIDEBUG(
"what went wrong, and how to fix the problem");
577 RDEBUG2(
"In state machine in phase2 init?");
584 REDEBUG(
"Unhandled state in peap");
612 q[2] = (len >> 8) & 0xff;
623 eap_round,
data, data_len);
626 RDEBUG2(
"Unable to convert tunneled EAP packet to internal server data structures");
633 REDEBUG(
"Invalid state change in PEAP");
638 RDEBUG2(
"Got tunneled request");
664 RDEBUG2(
"Setting request.User-Name from tunneled (inner) identity \"%s\"",
667 RDEBUG2(
"No tunnel username (SSL resumption?)");
743 fr_tls_session_t *tls_session = eap_tls_session->
tls_session;
745 RDEBUG3(
"Tunneled request complete");
761 "client EAP encryption",
762 sizeof(
"client EAP encryption") - 1);
782 return fr_tls_cache_pending_push(request, tls_session);
806 fr_tls_session_t *tls_session = eap_tls_session->
tls_session;
815 switch (eap_tls_session->
state) {
865 RDEBUG2(
"Session established. Decoding tunneled data");
871 if (!tls_session->opaque) tls_session->opaque =
peap_alloc(tls_session);
910 fr_tls_session_t *tls_session;
921 client_cert =
vp->vp_uint32 ? true :
false;
923 client_cert =
inst->req_client_cert;
962 tls_session->opaque =
peap_alloc(tls_session);
977 eap_session->
tls =
true;
981 if (
inst->tls_conf->new_session)
return fr_tls_new_session_push(request,
inst->tls_conf);
991 t->
ssl_ctx = fr_tls_ctx_alloc(
inst->tls_conf,
false);
1024 if (!
inst->tls_conf) {
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.
#define CONF_PARSER_TERMINATOR
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
eap_packet_t * response
Packet we received from the peer.
Contains a pair of request and response packets.
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
@ FR_RADIUS_CODE_ACCESS_ACCEPT
RFC2865 - Access-Accept.
@ FR_RADIUS_CODE_ACCESS_REJECT
RFC2865 - Access-Reject.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
void eap_crypto_prf_label_init(eap_tls_prf_label_t *prf_label, eap_session_t *eap_session, char const *keying_prf_label, size_t keying_prf_label_len)
Initialize the PRF label fields.
char const * eap_type2name(eap_type_t method)
Return an EAP-name for a particular type.
Structure to represent packet format of eap on wire
#define unlang_function_push_with_result(_result_p, _request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack that produces a result.
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
unlang_mod_action_t priority
The priority or action for that rcode.
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
unlang_action_t eap_virtual_server(request_t *request, eap_session_t *eap_session, virtual_server_t *virtual_server)
Run a subrequest through a virtual server.
static eap_session_t * eap_session_get(request_t *request)
void * opaque
Opaque data used by EAP methods.
bool tls
Whether EAP method uses TLS.
module_method_t process
Callback that should be used to process the next round.
unlang_result_t submodule_result
Result of last submodule call.
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Tracks the progress of a single session of any EAP method.
void log_request_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a fr_pair_list_t.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RINDENT()
Indent R* messages by one level.
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_OCTETS
Raw octets.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
void * rctx
Resume ctx that a module previously set.
void * thread
Thread instance data.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
int fr_pair_list_copy_by_da(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from, fr_dict_attr_t const *da, unsigned int count)
Duplicate pairs in a list matching the specified da.
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
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.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
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.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
int fr_pair_value_mem_alloc(fr_pair_t *vp, uint8_t **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "octets" type value pair.
static const conf_parser_t config[]
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
#define RDEBUG_ENABLED2()
#define FR_RADIUS_PACKET_CODE_VALID(_x)
#define RETURN_UNLANG_HANDLED
#define RETURN_UNLANG_RCODE(_rcode)
#define RETURN_UNLANG_FAIL
#define RETURN_UNLANG_REJECT
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
int request_detach(request_t *child)
Unlink a subrequest from its parent.
static unlang_action_t mod_handshake_process(UNUSED unlang_result_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request)
static unlang_action_t mod_handshake_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
bool copy_request_to_tunnel
Use SOME of the request attributes from outside of the tunneled session in the tunneled request.
@ PEAP_STATUS_PHASE2_INIT
@ PEAP_STATUS_TUNNEL_ESTABLISHED
@ PEAP_STATUS_INNER_IDENTITY_REQ_SENT
@ PEAP_STATUS_SENT_TLV_SUCCESS
@ PEAP_STATUS_SENT_TLV_FAILURE
static unlang_action_t process_reply(unlang_result_t *p_result, request_t *request, UNUSED void *uctx)
fr_dict_attr_t const * attr_eap_message
static peap_tunnel_t * peap_alloc(TALLOC_CTX *ctx)
virtual_server_t * virtual_server
Virtual server for inner tunnel session.
static fr_dict_t const * dict_freeradius
fr_dict_attr_t const * attr_eap_tls_require_client_cert
static int eap_peap_success(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
SSL_CTX * ssl_ctx
Thread local SSL_CTX.
fr_dict_attr_autoload_t rlm_eap_peap_dict_attr[]
fr_dict_autoload_t rlm_eap_peap_dict[]
static unlang_action_t mod_session_init_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static fr_dict_t const * dict_radius
static int eap_peap_identity(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
#define FR_PEAP_EXTENSIONS_TYPE
fr_dict_attr_t const * attr_auth_type
static unlang_action_t eap_peap_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
char const * tls_conf_name
TLS configuration.
static int eap_peap_check_tlv(request_t *request, uint8_t const *data, size_t data_len)
static void eap_peap_inner_to_pairs(TALLOC_CTX *ctx, fr_pair_list_t *pairs, eap_round_t *eap_round, uint8_t const *data, size_t data_len)
peap_resumption session_resumption_state
bool req_client_cert
Do we do require a client cert?
rlm_eap_submodule_t rlm_eap_peap
bool use_tunneled_reply
Use the reply attributes from the tunneled session in the non-tunneled reply to the client.
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static int eap_peap_inner_from_pairs(request_t *request, fr_tls_session_t *tls_session, fr_pair_list_t *vps)
static unlang_action_t process_rcode(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static char const * peap_state(peap_tunnel_t *t)
fr_dict_attr_t const * attr_user_name
static conf_parser_t submodule_config[]
static int eap_peap_failure(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
static unlang_action_t mod_session_init(UNUSED unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static int eap_peap_verify(request_t *request, peap_tunnel_t *peap_tunnel, uint8_t const *data, size_t data_len)
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static int mod_instantiate(module_inst_ctx_t const *mctx)
#define EAP_TLV_ACK_RESULT
CONF_SECTION * conf
Module's instance configuration.
size_t inst_size
Size of the module's instance data.
void * data
Module's instance data.
@ FR_SIGNAL_CANCEL
Request has been cancelled.
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
eap_aka_sim_process_conf_t * inst
Stores an attribute, a value and various bits of other data.
module_t common
Common fields provided by all modules.
Interface exported by EAP submodules.
request_t * unlang_subrequest_alloc(request_t *parent, fr_dict_t const *namespace)
Allocate a subrequest to run through a virtual server at some point in the future.
int unlang_subrequest_child_push(unlang_result_t *p_result, request_t *child, void const *unique_session_ptr, bool free_child, bool top_frame)
Push a pre-existing child back onto the stack as a subrequest.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
int eap_tls_success(request_t *request, eap_session_t *eap_session, eap_tls_prf_label_t *prf_label)
Send an EAP-TLS success.
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.
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.
int 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[]
fr_tls_conf_t * eap_tls_conf_parse(CONF_SECTION *cs)
Parse TLS configuration.
unlang_action_t eap_tls_process(request_t *request, eap_session_t *eap_session)
Process an EAP TLS request.
int base_flags
Some protocols use the reserved bits of the EAP-TLS flags (such as PEAP).
eap_tls_status_t state
The state of the EAP-TLS session.
@ EAP_TLS_INVALID
Invalid, don't reply.
@ EAP_TLS_HANDLED
TLS code has handled it.
@ EAP_TLS_RECORD_RECV_COMPLETE
Received final fragment of a record.
@ EAP_TLS_FAIL
Fail, send fail.
@ EAP_TLS_ESTABLISHED
Session established, send success (or start phase2).
fr_tls_session_t * tls_session
TLS session used to authenticate peer or tunnel sensitive data.
bool include_length
A flag to include length in every TLS Data/Alert packet.
Tracks the state of an EAP-TLS session.
unsigned int code
Packet code (type).
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
int virtual_server_cf_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Wrapper for the config parser to allow pass1 resolution of virtual servers.
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.
Additional validation rules for virtual server lookup.