27 RCSID(
"$Id: 4b7fbb5d31fbdca0659b3aaab8c27d15f0507630 $")
28 #include <freeradius-devel/eap/base.h>
29 #include <freeradius-devel/eap/types.h>
30 #include <freeradius-devel/server/pair.h>
31 #include <freeradius-devel/unlang/interpret.h>
32 #include <freeradius-devel/unlang/module.h>
33 #include <freeradius-devel/util/table.h>
34 #include <freeradius-devel/util/rand.h>
40 #ifndef EAP_TLS_MPPE_KEY_LEN
41 # define EAP_TLS_MPPE_KEY_LEN 32
44 #define STATE(_x) static inline unlang_action_t state_ ## _x(rlm_rcode_t *p_result, \
45 module_ctx_t const *mctx, \
47 #define STATE_GUARD(_x) static unlang_action_t guard_ ## _x(rlm_rcode_t *p_result, \
48 module_ctx_t const *mctx, \
51 #define RESUME(_x) static inline unlang_action_t resume_ ## _x(rlm_rcode_t *p_result, \
52 module_ctx_t const *mctx, \
55 #define STATE_TRANSITION(_x) guard_ ## _x(p_result, mctx, request)
57 #define CALL_SECTION(_x) unlang_module_yield_to_section(p_result, \
64 talloc_get_type_abort(mctx->rctx, eap_aka_sim_session_t))
95 {
L(
"EAP-IDENTITY"), (
void *)state_init },
96 {
L(
"SIM-START"), (
void *)state_sim_start },
97 {
L(
"AKA-IDENTITY"), (
void *)state_aka_identity },
99 {
L(
"SIM-CHALLENGE"), (
void *)state_sim_challenge },
100 {
L(
"AKA-CHALLENGE"), (
void *)state_aka_challenge },
102 {
L(
"SUCCESS-NOTIFICATION"), (
void *)state_common_success_notification },
103 {
L(
"FAILURE-NOTIFICATION"), (
void *)state_common_failure_notification },
105 {
L(
"REAUTHENTICATION"), (
void *)state_common_reauthentication },
107 {
L(
"EAP-SUCCESS"), (
void *)state_eap_success },
108 {
L(
"EAP-FAILURE"), (
void *)state_eap_failure }
120 RDEBUG2(
"Request cancelled - Destroying session");
134 #define SECTION_RCODE_IGNORED \
136 switch (unlang_interpret_stack_result(request)) { \
137 case RLM_MODULE_USER_SECTION_REJECT: \
138 RWDEBUG("Ignoring rcode (%s)", \
139 fr_table_str_by_value(rcode_table, unlang_interpret_stack_result(request), "<invalid>")); \
149 #define SECTION_RCODE_PROCESS \
151 if (after_authentication(eap_aka_sim_session)) { \
152 switch (unlang_interpret_stack_result(request)) { \
153 case RLM_MODULE_REJECT: \
154 case RLM_MODULE_DISALLOW: \
155 eap_aka_sim_session->failure_type = FR_NOTIFICATION_VALUE_TEMPORARILY_DENIED; \
156 return STATE_TRANSITION(common_failure_notification); \
157 case RLM_MODULE_NOTFOUND: \
158 eap_aka_sim_session->failure_type = FR_NOTIFICATION_VALUE_NOT_SUBSCRIBED; \
159 return STATE_TRANSITION(common_failure_notification); \
160 case RLM_MODULE_INVALID: \
161 case RLM_MODULE_FAIL: \
162 eap_aka_sim_session->failure_type = FR_NOTIFICATION_VALUE_GENERAL_FAILURE_AFTER_AUTHENTICATION;\
163 return STATE_TRANSITION(common_failure_notification); \
168 switch (unlang_interpret_stack_result(request)) { \
169 case RLM_MODULE_USER_SECTION_REJECT: \
170 REDEBUG("Section rcode (%s) indicates we should reject the user", \
171 fr_table_str_by_value(rcode_table, unlang_interpret_stack_result(request), "<INVALID>")); \
172 return STATE_TRANSITION(common_failure_notification); \
188 if (new_state != old_state) {
189 RDEBUG2(
"Changed state %s -> %s",
199 #define STATE_SET(_new_state) state_set(request, talloc_get_type_abort(mctx->rctx, eap_aka_sim_session_t), state_ ## _new_state)
218 REDEBUG(
"Peer has not supplied a AT_ERROR_CODE");
220 REDEBUG(
"Peer rejected request with error: %i (%pV)",
vp->vp_uint16, &
vp->data);
229 bool set_by_user =
false;
243 RDEBUG2(
"Previous section added &reply.%pP, will request additional identity",
vp);
263 request_t *request,
char const *identity)
272 identity, talloc_array_length(identity) - 1) < 0) {
273 RPWDEBUG2(
"Failed parsing identity, continuing anyway");
287 vp->vp_uint32 = FR_IDENTITY_TYPE_VALUE_PERMANENT;
291 vp->vp_uint32 = FR_IDENTITY_TYPE_VALUE_PSEUDONYM;
295 vp->vp_uint32 = FR_IDENTITY_TYPE_VALUE_FASTAUTH;
314 vp->vp_uint32 = FR_METHOD_HINT_VALUE_AKA_PRIME;
318 vp->vp_uint32 = FR_METHOD_HINT_VALUE_AKA;
322 vp->vp_uint32 = FR_METHOD_HINT_VALUE_SIM;
330 if (type_p) *type_p =
type;
331 if (method_p) *method_p = method;
367 REDEBUG(
"Cannot send %s, already sent %s",
383 goto id_out_of_order;
397 goto id_out_of_order;
412 goto id_out_of_order;
445 if (
in->vp_length == 0) {
446 RDEBUG2(
"Not processing zero length identity");
493 RDEBUG2(
"%s has incorrect hint byte, expected '%c', got '%c'. "
494 "'hint' byte not stripped",
531 fr_pair_t *peer_checkcode, *our_checkcode;
547 if (peer_checkcode) {
548 if (
fr_pair_cmp(peer_checkcode, our_checkcode) == 0) {
549 RDEBUG2(
"Received AT_CHECKCODE matches calculated AT_CHECKCODE");
552 REDEBUG(
"Received AT_CHECKCODE does not match calculated AT_CHECKCODE");
553 RHEXDUMP_INLINE2(peer_checkcode->vp_octets, peer_checkcode->vp_length,
"Received");
554 RHEXDUMP_INLINE2(our_checkcode->vp_octets, our_checkcode->vp_length,
"Expected");
561 RDEBUG2(
"Peer didn't include AT_CHECKCODE, skipping checkcode validation");
598 REDEBUG(
"Peer didn't include AT_MAC");
603 REDEBUG(
"Received AT_MAC does not match calculated AT_MAC");
609 RDEBUG2(
"Received AT_MAC matches calculated AT_MAC");
617 uint8_t const *identity,
size_t len)
688 if (
vp->vp_length == 0) {
692 RWDEBUG(
"Found empty Next-Reauth-Id, and told not to generate one. "
693 "Skipping store session { ... } section");
716 identity[talloc_array_length(identity) - 1] =
'\0';
724 vp->vp_strvalue,
vp->vp_length));
819 if (
vp->vp_length == 0) {
823 RWDEBUG(
"Found empty Pseudonym-Id, and told not to generate one. "
824 "Skipping store pseudonym { ... } section");
826 return resume_store_pseudonym(p_result, mctx, request);
847 identity[talloc_array_length(identity) - 1] =
'\0';
854 vp->vp_strvalue,
vp->vp_length));
858 return resume_store_pseudonym(p_result, mctx, request);
941 return resume_clear_pseudonym(p_result, mctx, request);
963 RWDEBUG(
"Silently discarding &reply.%pP: Encrypted attributes not "
964 "allowed in this round",
vp);
971 static void CC_HINT(
nonnull(1,2))
973 uint8_t const *hmac_extra_request,
size_t hmac_extra_request_len,
974 uint8_t const *hmac_extra_response,
size_t hmac_extra_response_len)
983 if (hmac_extra_request && hmac_extra_request_len) {
988 if (hmac_extra_response && hmac_extra_response_len) {
1116 sres_cat,
sizeof(sres_cat));
1134 if (!selected_version_vp) {
1135 REDEBUG(
"EAP-Response/SIM/Start does not contain AT_SELECTED_VERSION");
1150 selected_version[0] = (selected_version_vp->vp_uint16 & 0xff00) >> 8;
1151 selected_version[1] = (selected_version_vp->vp_uint16 & 0x00ff);
1154 if ((p[0] == selected_version[0]) && (p[1] == selected_version[1])) {
1166 REDEBUG(
"AT_SELECTED_VERSION (%u) does not match a value in our version list",
1167 selected_version_vp->vp_uint16);
1188 REDEBUG(
"EAP-Response/SIM/Start does not contain AT_NONCE_MT");
1193 REDEBUG(
"AT_NONCE_MT must be exactly %zu bytes, not %zu bytes",
1227 RDEBUG2(
"Sending EAP-Failure");
1289 case FR_SUBTYPE_VALUE_AKA_SIM_NOTIFICATION:
1290 RDEBUG2(
"Failure-Notification ACKed, sending EAP-Failure");
1291 return CALL_SECTION(recv_common_failure_notification_ack);
1295 RWDEBUG(
"Failure-Notification not ACKed correctly, sending EAP-Failure anyway");
1336 if (notification_vp)
fr_pair_remove(&request->reply_pairs, notification_vp);
1338 if (notification_vp)
fr_pair_append(&request->reply_pairs, notification_vp);
1345 if (!notification_vp) {
1350 notification_vp->vp_uint16 &= ~0x4000;
1391 if (!notification_vp) {
1393 notification_vp->vp_uint16 = FR_NOTIFICATION_VALUE_GENERAL_FAILURE;
1398 notification_vp->vp_uint16 |= 0x4000;
1401 notification_vp->vp_uint16 &= ~0x8000;
1425 guard_common_failure_notification);
1475 RDEBUG2(
"Sending EAP-Success");
1489 RWDEBUG(
"Ignoring rcode (%s) from send EAP-Success { ... } "
1490 "as we already sent a Success-Notification",
1492 RWDEBUG(
"If you need to force a failure, return an error code from "
1493 "send Success-Notification { ... }");
1510 RDEBUG2(
"Adding attributes for MSK");
1584 vp->vp_uint16 = FR_NOTIFICATION_VALUE_SUCCESS;
1656 RESUME(recv_common_reauthentication_response)
1682 RWDEBUG(
"Peer sent AT_COUNTER_TOO_SMALL (indicating our AT_COUNTER value (%u) wasn't fresh)",
1700 RDEBUG(
"We wanted to use protected result indications, but peer does not");
1706 RDEBUG(
"Peer wanted to use protected result indications, but we do not");
1730 REDEBUG(
"Missing AT_SUBTYPE");
1741 case FR_SUBTYPE_VALUE_AKA_SIM_REAUTHENTICATION:
1746 return CALL_SECTION(recv_common_reauthentication_response);
1751 case FR_SUBTYPE_VALUE_AKA_SIM_CLIENT_ERROR:
1795 (
uint8_t const *)kdf_id->vp_strvalue, kdf_id->vp_length);
1799 RDEBUG2(
"Generating new session keys");
1820 RDEBUG2(
"Composing EAP-Request/Reauthentication failed. Clearing reply attributes and "
1821 "requesting additional Identity");
1828 REDEBUG(
"Last requested fullauth or permanent ID, "
1829 "but received, or were told we received (by policy), "
1830 "a fastauth ID. Cannot continue");
1841 goto request_new_id;
1922 RDEBUG2(
"Previous section returned (%s), clearing reply attributes and "
1923 "requesting additional identity",
1935 REDEBUG(
"Last requested Full-Auth-Id or Permanent-Identity, "
1936 "but received a Fast-Auth-Id. Cannot continue");
1988 RDEBUG2(
"Previous section returned (%s), clearing reply attributes and "
1989 "requesting additional identity",
1996 REDEBUG(
"Last requested a Permanent-Identity, but received a Pseudonym. Cannot continue");
2051 RDEBUG2(
"Previous section returned (%s), clearing reply attributes and "
2052 "requesting additional identity",
2060 REDEBUG(
"Last requested Full-Auth-Id or Permanent-Identity, "
2061 "but received a Fast-Auth-Id. Cannot continue");
2080 return CALL_SECTION(send_common_reauthentication_request);
2145 REDEBUG(
"No &control.SQN value provided after resynchronisation, cannot continue");
2203 REDEBUG(
"AT_RES missing from challenge response");
2208 REDEBUG(
"Received RES' length (%zu) does not match calculated XRES' length (%zu)",
2214 REDEBUG(
"Received RES does not match calculated XRES");
2221 RDEBUG2(
"Received RES matches calculated XRES");
2234 RDEBUG(
"We wanted to use protected result indications, but peer does not");
2240 RDEBUG(
"Peer wanted to use protected result indications, but we do not");
2266 REDEBUG(
"Missing AT_SUBTYPE");
2271 case FR_SUBTYPE_VALUE_AKA_CHALLENGE:
2277 case FR_SUBTYPE_VALUE_AKA_AUTHENTICATION_REJECT:
2281 case FR_SUBTYPE_VALUE_AKA_SYNCHRONIZATION_FAILURE:
2289 REDEBUG(
"EAP-Response/AKA-Synchronisation-Failure missing AT_AUTS");
2302 vp->vp_uint64 = new_sqn;
2327 case FR_SUBTYPE_VALUE_AKA_SIM_CLIENT_ERROR:
2369 (
uint8_t const *)kdf_id->vp_strvalue, kdf_id->vp_length);
2373 RDEBUG2(
"Acquiring UMTS vector(s)");
2388 REDEBUG(
"No network name available, can't set AT_KDF_INPUT");
2407 REDEBUG(
"Failed retrieving UMTS vectors");
2514 uint8_t amf_buff[2] = { 0x80, 0x00 };
2586 RDEBUG(
"We wanted to use protected result indications, but peer does not");
2592 RDEBUG(
"Peer wanted to use protected result indications, but we do not");
2614 REDEBUG(
"Missing AT_SUBTYPE");
2619 case FR_SUBTYPE_VALUE_SIM_CHALLENGE:
2625 case FR_SUBTYPE_VALUE_AKA_SIM_CLIENT_ERROR:
2669 (
uint8_t const *)kdf_id->vp_strvalue, kdf_id->vp_length);
2673 RDEBUG2(
"Acquiring GSM vector(s)");
2680 REDEBUG(
"Failed retrieving SIM vectors");
2801 bool user_set_id_req;
2815 if (!user_set_id_req) {
2831 REDEBUG(
"Peer sent no usable identities");
2835 RDEBUG2(
"Previous section returned (%s), requesting next most permissive identity (%s)",
2848 if (identity_type)
switch (identity_type->vp_uint32) {
2849 case FR_IDENTITY_TYPE_VALUE_FASTAUTH:
2857 case FR_IDENTITY_TYPE_VALUE_PSEUDONYM:
2889 REDEBUG(
"Missing AT_SUBTYPE");
2897 case FR_SUBTYPE_VALUE_AKA_IDENTITY:
2912 REDEBUG(
"EAP-Response/Identity does not contain AT_IDENTITY");
2931 (
uint8_t const *)id->vp_strvalue, id->vp_length);
2939 resume_recv_aka_identity_response,
2952 case FR_SUBTYPE_VALUE_AKA_SIM_CLIENT_ERROR:
3045 resume_send_aka_identity_request,
3069 bool user_set_id_req;
3083 if (!user_set_id_req) {
3102 REDEBUG(
"Peer sent no usable identities");
3106 RDEBUG2(
"Previous section returned (%s), requesting next most permissive identity (%s)",
3119 if (identity_type)
switch (identity_type->vp_uint32) {
3120 case FR_IDENTITY_TYPE_VALUE_FASTAUTH:
3129 REDEBUG(
"AT_NONCE_MT is not allowed in EAP-Response/SIM-Reauthentication messages");
3141 REDEBUG(
"AT_SELECTED_VERSION is not allowed in EAP-Response/SIM-Reauthentication messages");
3152 case FR_IDENTITY_TYPE_VALUE_PSEUDONYM:
3165 case FR_IDENTITY_TYPE_VALUE_PERMANENT:
3198 REDEBUG(
"Missing AT_SUBTYPE");
3202 case FR_SUBTYPE_VALUE_SIM_START:
3223 REDEBUG(
"EAP-Response/SIM/Start does not contain AT_IDENTITY");
3245 (
uint8_t const *)id->vp_strvalue, id->vp_length);
3277 resume_recv_sim_start_response,
3290 case FR_SUBTYPE_VALUE_AKA_SIM_CLIENT_ERROR:
3357 if ((end - p) < 2)
break;
3362 *p++ = (
vp->vp_uint16 & 0xff00) >> 8;
3363 *p++ = (
vp->vp_uint16 & 0x00ff);
3410 resume_send_sim_start,
3465 if (
eap_type)
RWDEBUG(
"Ignoring &control.EAP-Type, this must be set *before* the EAP module is called");
3483 RDEBUG2(
"New EAP-SIM session");
3492 RDEBUG2(
"New EAP-AKA session");
3501 RDEBUG2(
"New EAP-AKA' session");
3520 switch (method->vp_uint32) {
3521 case FR_METHOD_HINT_VALUE_AKA_PRIME:
3525 case FR_METHOD_HINT_VALUE_AKA:
3529 case FR_METHOD_HINT_VALUE_SIM:
3538 if (hinted != running) {
3539 RWDEBUG(
"EAP-Identity hints that EAP-%s should be started, but we're attempting EAP-%s",
3553 RDEBUG2(
"Previous section returned (%s), requesting additional identity (%s)",
3559 RDEBUG2(
"Requesting additional identity (%s)",
3591 if (identity_type)
switch (identity_type->vp_uint32) {
3592 case FR_IDENTITY_TYPE_VALUE_FASTAUTH:
3600 case FR_IDENTITY_TYPE_VALUE_PSEUDONYM:
3604 case FR_IDENTITY_TYPE_VALUE_PERMANENT:
3631 REDEBUG(
"All SIM or AKA exchanges must begin with a EAP-Response/Identity message");
3658 talloc_array_length(eap_session->
identity) - 1);
3708 RPEDEBUG(
"Failed creating new EAP-SIM/AKA/AKA' session");
3715 return state_init(p_result, &our_mctx, request);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define L(_str)
Helper for initialising arrays of string literals.
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
fr_dict_attr_t const * fr_dict_attr_common_parent(fr_dict_attr_t const *a, fr_dict_attr_t const *b, bool is_ancestor)
Find a common ancestor that two TLV type attributes share.
@ FR_EAP_METHOD_AKA_PRIME
uint8_t * identity
Identity from AT_IDENTITY.
int fr_aka_sim_crypto_umts_kdf_0(fr_aka_sim_keys_t *keys)
Key Derivation Function as described in RFC4187 (EAP-AKA) section 7.
int fr_aka_sim_crypto_umts_kdf_1_reauth(fr_aka_sim_keys_t *keys)
Key Derivation Function (Fast-Reauthentication) as described in RFC 5448 (EAP-AKA') section 3....
#define AKA_SIM_VECTOR_UMTS_RAND_SIZE
#define AKA_SIM_VECTOR_GSM_RAND_SIZE
Length of RAND in GSM triplet.
uint8_t * network
Network name (EAP-AKA-Prime only).
void fr_aka_sim_crypto_keys_log(request_t *request, fr_aka_sim_keys_t *keys)
Dump the current state of all keys associated with the EAP SIM session.
#define AKA_SIM_VECTOR_GSM_SRES_SIZE
Length of SRES in GSM triplet.
size_t network_len
Length of the network name (EAP-AKA-Prime only).
int fr_aka_sim_crypto_kdf_0_reauth(fr_aka_sim_keys_t *keys)
Key Derivation Function (Fast-Reauthentication) as described in RFC4186/7 (EAP-SIM/AKA) section 7.
int fr_aka_sim_vector_gsm_umts_kdf_0_reauth_from_attrs(request_t *request, fr_pair_list_t *vps, fr_aka_sim_keys_t *keys)
Populate a fr_aka_sim_keys_t structure from attributes in the session-state list.
#define AKA_PRIME_MK_REAUTH_SIZE
The portion of the MK used for re-auth.
void fr_aka_sim_vector_umts_reauth_clear(fr_aka_sim_keys_t *keys)
Clear reauth data if reauthentication failed.
fr_aka_sim_vector_src_t
Where to get EAP-SIM vectors from.
@ AKA_SIM_VECTOR_SRC_AUTO
Discover where to get Triplets from automatically.
int fr_aka_sim_crypto_gsm_kdf_0(fr_aka_sim_keys_t *keys)
Key Derivation Function as described in RFC4186 (EAP-SIM) section 7.
size_t identity_len
Length of the identity.
uint8_t k_aut[32]
Derived authentication key.
size_t k_aut_len
Length of k_aut. 16 for AKA/SIM, 32 for AKA'.
int fr_aka_sim_crypto_umts_kdf_1(fr_aka_sim_keys_t *keys)
Key Derivation Function as described in RFC 5448 (EAP-AKA') section 3.3.
int fr_aka_sim_vector_gsm_from_attrs(request_t *request, fr_pair_list_t *vps, int idx, fr_aka_sim_keys_t *keys, fr_aka_sim_vector_src_t *src)
Retrieve GSM triplets from sets of attributes.
uint8_t k_encr[16]
Derived encryption key.
#define AKA_SIM_VECTOR_UMTS_AUTN_SIZE
int fr_aka_sim_vector_umts_kdf_1_reauth_from_attrs(request_t *request, fr_pair_list_t *vps, fr_aka_sim_keys_t *keys)
Populate a fr_aka_sim_keys_t structure from attributes in the session-state list.
uint8_t mk[AKA_SIM_MK_MAX_SIZE]
Master key from session attributes.
uint8_t msk[64]
Derived master session key.
int fr_aka_sim_umts_resync_from_attrs(uint64_t *new_sqn, request_t *request, fr_pair_t *auts_vp, fr_aka_sim_keys_t *keys)
Perform milenage AUTS validation and resynchronisation.
int fr_aka_sim_vector_umts_from_attrs(request_t *request, fr_pair_list_t *vps, fr_aka_sim_keys_t *keys, fr_aka_sim_vector_src_t *src)
Retrieve UMTS quintuplets from sets of attributes.
rlm_rcode_t unlang_interpret_stack_result(request_t *request)
Get the current rcode for the frame.
void unlang_interpret_stack_result_set(request_t *request, rlm_rcode_t rcode)
Overwrite the current stack rcode.
HIDDEN fr_dict_attr_t const * attr_ms_mppe_send_key
HIDDEN fr_dict_attr_t const * attr_ms_mppe_recv_key
HIDDEN fr_dict_attr_t const * attr_eap_type
void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
char * identity
NAI (User-Name) from EAP-Identity.
eap_type_t type
EAP method number.
static eap_session_t * eap_session_get(request_t *request)
Tracks the progress of a single session of any EAP method.
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_kdf
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_counter
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_nonce_s
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_permanent_id_req
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_encr_data
HIDDEN fr_dict_attr_t const * attr_session_data
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_next_reauth_id
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_counter_too_small
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_permanent_identity
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_nonce_mt
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_auts
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_kdf_identity
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_k_encr
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_version_list
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_checkcode
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_res
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_k_aut
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_identity
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_client_error_code
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_autn
HIDDEN fr_dict_attr_t const * attr_sim_opc
HIDDEN fr_dict_attr_t const * attr_session_id
HIDDEN fr_dict_attr_t const * attr_sim_ki
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_result_ind
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_next_pseudonym
HIDDEN fr_dict_attr_t const * attr_sim_sqn
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_any_id_req
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_mac
HIDDEN fr_dict_attr_t const * attr_sim_amf
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_method_hint
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_selected_version
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_fullauth_id_req
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_subtype
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_hmac_extra_request
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_notification
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_rand
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_identity_type
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_hmac_extra_response
HIDDEN fr_value_box_t const * enum_kdf_prime_with_ck_prime_ik_prime
HIDDEN fr_dict_attr_t const * attr_eap_aka_sim_kdf_input
fr_table_num_sorted_t const fr_aka_sim_id_method_table[]
char fr_aka_sim_hint_byte(fr_aka_sim_id_type_t type, fr_aka_sim_method_hint_t method)
Return the expected identity hint for a given type/method combination.
fr_table_num_sorted_t const fr_aka_sim_id_request_table[]
int fr_aka_sim_id_type(fr_aka_sim_id_type_t *type, fr_aka_sim_method_hint_t *hint, char const *id, size_t id_len)
Determine what type of ID was provided in the initial identity response.
@ AKA_SIM_INIT_ID_REQ
We've requested no ID. This is used for last_id_req.
@ AKA_SIM_NO_ID_REQ
We're not requesting any ID.
@ AKA_SIM_ANY_ID_REQ
Request IMSI, Pseudonym or Fast-reauth.
@ AKA_SIM_FULLAUTH_ID_REQ
Request IMSI or Pseudonym.
@ AKA_SIM_PERMANENT_ID_REQ
Request IMSI.
@ ID_TAG_AKA_PRIME_FASTAUTH
Fastuath, continue EAP-AKA-Prime.
@ ID_TAG_AKA_FASTAUTH
Fastauth, continue EAP-AKA.
@ ID_TAG_SIM_PSEUDONYM
Pseudonym, continue EAP-SIM.
@ ID_TAG_AKA_PRIME_PSEUDONYM
Pseudonym, continue EAP-AKA-Prime.
@ ID_TAG_AKA_PSEUDONYM
Pseudonym, continue EAP-AKA.
@ ID_TAG_SIM_FASTAUTH
Fastauth, continue EAP-SIM.
fr_aka_sim_method_hint_t
SIM/AKA method hints.
@ AKA_SIM_METHOD_HINT_AKA
The identity hints the supplicant wants to use EAP-AKA.
@ AKA_SIM_METHOD_HINT_SIM
The identity hints the supplicant wants to use EAP-SIM.
@ AKA_SIM_METHOD_HINT_AKA_PRIME
@ AKA_SIM_METHOD_HINT_UNKNOWN
We don't know what method the identity hints at.
fr_aka_sim_id_type_t
SIM/AKA identity type hints.
@ AKA_SIM_ID_TYPE_UNKNOWN
We don't know what type of identity this is.
@ AKA_SIM_ID_TYPE_PSEUDONYM
This is a custom pseudonym.
@ AKA_SIM_ID_TYPE_PERMANENT
This is a permanent identity (the IMSI of the SIM).
@ AKA_SIM_ID_TYPE_FASTAUTH
This is a fastauth (session-resumption) id.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
#define RHEXDUMP_INLINE2(_data, _len, _fmt,...)
#define RPEDEBUG(fmt,...)
#define RPWDEBUG2(fmt,...)
#define RINDENT()
Indent R* messages by one level.
module_instance_t const * mi
Instance of the module being instantiated.
void * rctx
Resume ctx that a module previously set.
Temporary structure to hold arguments for module calls.
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_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
int fr_pair_cmp(fr_pair_t const *a, fr_pair_t const *b)
Compare two pairs, using the operator from "a".
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
int fr_pair_delete_by_da(fr_pair_list_t *list, fr_dict_attr_t const *da)
Delete matching pairs from the specified list.
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.
int fr_pair_delete(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list and free.
int fr_pair_value_copy(fr_pair_t *dst, fr_pair_t *src)
Copy the value from one pair to another.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
#define pair_update_request(_attr, _da)
void fr_rand_str(uint8_t *out, size_t len, char class)
Generate a random string.
fr_table_num_sorted_t const rcode_table[]
#define RETURN_MODULE_REJECT
#define RETURN_MODULE_HANDLED
#define RLM_MODULE_USER_SECTION_REJECT
Rcodes that translate to a user configurable section failing overall.
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
void * request_data_get(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request.
void * request_data_reference(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request without removing it.
#define request_data_add(_request, _unique_ptr, _unique_int, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
void * data
Module's instance data.
unlang_action_t(* module_method_t)(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Module section callback.
#define pair_append_control(_attr, _da)
Allocate and append a fr_pair_t to the control list.
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
#define pair_append_session_state(_attr, _da)
Allocate and append a fr_pair_t to session-state list.
#define pair_append_request(_attr, _da)
Allocate and append a fr_pair_t to the request list.
#define pair_delete_request(_pair_or_da)
Delete a fr_pair_t in the request list.
#define pair_update_session_state(_attr, _da)
Return or allocate a fr_pair_t in the session_state list.
#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.
#define pair_delete_control(_pair_or_da)
Delete a fr_pair_t in the control list.
#define pair_update_control(_attr, _da)
Return or allocate a fr_pair_t in the control list.
unlang_action_t unlang_module_yield_to_section(rlm_rcode_t *p_result, request_t *request, CONF_SECTION *subcs, rlm_rcode_t default_rcode, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
static bool identity_req_set_by_user(request_t *request, eap_aka_sim_session_t *eap_aka_sim_session)
Sync up what identity we're requesting with attributes in the reply.
aka_challenge
AKA-CHALLENGE state - Continue the state machine after receiving a response to our EAP-Request/SIM-Ch...
static int checkcode_validate(request_t *request)
Check &control.checkcode matches &reply.checkcode.
eap_aka_sim_session_t * eap_aka_sim_session
static int sim_start_selected_version_check(request_t *request, eap_aka_sim_session_t *eap_aka_sim_session)
Helper function to check for the presence and length of AT_SELECTED_VERSION and copy its value into t...
common_success_notification
SUCCESS-NOTIFICATION state - Continue the state machine after receiving a response to our EAP-Request...
static int identity_req_pairs_add(request_t *request, eap_aka_sim_session_t *eap_aka_sim_session)
Add an Identity Request attribute to the reply.
static void mod_signal(module_ctx_t const *mctx, request_t *request, UNUSED fr_signal_t action)
Cancel a call to a submodule.
static int sim_start_nonce_mt_check(request_t *request, eap_aka_sim_session_t *eap_aka_sim_session)
Helper function to check for the presence and length of AT_NONCE_MT and copy its value into the keys ...
static void state_set(request_t *request, eap_aka_sim_session_t *eap_aka_sim_session, module_method_t new_state)
Print debugging information, and write new state to eap_aka_sim_session->state.
static unlang_action_t common_reauthentication_request_compose(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, eap_aka_sim_session_t *eap_aka_sim_session)
Send a EAP-Request/(AKA|SIM)-Reauthenticate message to the supplicant.
static unlang_action_t aka_challenge_request_send(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Called after 'store session { ...
common_failure_notification
FAILURE-NOTIFICATION state - Continue the state machine after receiving a response to our EAP-Request...
static int mac_validate(request_t *request)
Check &control.mac matches &reply.mac.
static void common_crypto_export(request_t *request, eap_aka_sim_session_t *eap_aka_sim_session, uint8_t const *hmac_extra_request, size_t hmac_extra_request_len, uint8_t const *hmac_extra_response, size_t hmac_extra_response_len)
static unlang_action_t session_and_pseudonym_store(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, eap_aka_sim_session_t *eap_aka_sim_session, module_method_t next)
Implements a set of states for storing pseudonym and fastauth identities.
static int identity_to_permanent_identity(request_t *request, fr_pair_t *in, eap_type_t eap_type, bool strip_hint)
Copy the incoming identity to the permanent identity attribute.
static size_t aka_sim_state_table_len
aka_identity
AKA-IDENTITY state - Continue the state machine after receiving a response to our EAP-Request/AKA-Ide...
static void identity_hint_pairs_add(fr_aka_sim_id_type_t *type_p, fr_aka_sim_method_hint_t *method_p, request_t *request, char const *identity)
Based on the hint byte in the identity, add &Identity-Type and &Method-Hint attributes.
#define STATE_SET(_new_state)
static void client_error_debug(request_t *request)
Print out the error the client returned.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
static unlang_action_t sim_challenge_request_send(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Called after 'store session { ...
static bool after_authentication(eap_aka_sim_session_t *eap_aka_sim_session)
Determine if we're after authentication.
init
Enter the EAP-IDENTITY state.
eap_aka_sim_process_conf_t * inst
static unlang_action_t common_reauthentication_request_send(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Called after 'store session { ...
fr_pair_value_bstrdup_buffer(vp, eap_session->identity, true)
#define EAP_TLS_MPPE_KEY_LEN
static fr_table_ptr_ordered_t const aka_sim_state_table[]
#define SECTION_RCODE_IGNORED
Warn the user that the rcode they provided is being ignored in this section.
eap_success
SUCCESS state - State machine exit point after sending EAP-Success.
static void common_reply(request_t *request, eap_aka_sim_session_t *eap_aka_sim_session, uint16_t subtype)
Export EAP-SIM/AKA['] attributes.
static int _eap_aka_sim_session_free(eap_aka_sim_session_t *eap_aka_sim_session)
Zero out the eap_aka_sim_session when we free it to clear knowledge of secret keys.
common_reauthentication
REAUTHENTICATION state - Continue the state machine after receiving a response to our EAP-Request/SIM...
static void crypto_identity_set(request_t *request, eap_aka_sim_session_t *eap_aka_sim_session, uint8_t const *identity, size_t len)
Set the crypto identity from a received identity.
#define SECTION_RCODE_PROCESS
Trigger a state transition to FAILURE-NOTIFICATION if the section returned a failure code.
static unlang_action_t session_and_pseudonym_clear(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, eap_aka_sim_session_t *eap_aka_sim_session, module_method_t next)
Implements a set of states for clearing out pseudonym and fastauth identities.
sim_start
SIM-START state - Continue the state machine after receiving a response to our EAP-Request/SIM-Start.
#define STATE_TRANSITION(_x)
fr_aka_sim_id_type_t type
unlang_action_t eap_aka_sim_state_machine_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Resumes the state machine when receiving a new response packet.
sim_challenge
SIM-CHALLENGE state - Continue the state machine after receiving a response to our EAP-Request/SIM-Ch...
eap_failure
FAILURE state - State machine exit point after sending EAP-Failure.
Declarations for EAP-AKA.
CONF_SECTION * recv_common_identity_response
Called when we receive a new identity.
bool protected_success
Send a success notification as well as and EAP-Success packet.
EVP_MD const * mac_md
HMAC-MD we use to generate the MAC.
eap_aka_sim_actions_t actions
Pre-compiled virtual server sections.
fr_aka_sim_id_req_type_t id_req
The type of identity we're requesting.
CONF_SECTION * load_session
Load cached authentication vectors.
bool challenge_success
Whether we received the correct challenge response.
size_t ephemeral_id_length
The length of any identities we're generating.
eap_type_t type
The preferred EAP-Type of this instance of the EAP-SIM/AKA/AKA' state machine.
fr_aka_sim_keys_t keys
Various EAP-AKA/AKA'/SIMkeys.
fr_aka_sim_id_req_type_t last_id_req
The last identity request we sent.
module_method_t state
The process function to run when we receive the next round of EAP-SIM/AKA/AKA'.
module_method_t next
Resumption function to call after executing common code.
uint16_t failure_type
One of the following values:
char const * network_name
Network ID as described by RFC 5448.
bool allow_encrypted
Whether we can send encrypted attributes at this phase of the attempt.
bool send_result_ind
Say that we would like to use protected result indications (AKA-Notification-Success).
char * pseudonym_sent
Pseudonym value we sent.
bool strip_permanent_identity_hint
Control whether the hint byte is stripped when populating Permanent-Identity.
bool reauthentication_success
Whether we got a valid reauthentication response.
char * fastauth_sent
Fastauth value we sent.
bool prev_recv_sync_failure
We only allow one sync failure per session for sanity.
eap_type_t type
Either FR_TYPE_AKA, or FR_TYPE_AKA_PRIME.
uint16_t kdf
The key derivation function used to derive session keys.
fr_aka_sim_id_req_type_t request_identity
Whether we always request the identity of the subscriber.
CONF_SECTION * load_pseudonym
Resolve a pseudonym to a permanent ID.
CONF_SECTION * send_common_identity_request
Called when we're about to request a different identity.
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
#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 ptr mappings.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Master include file to access all functions and structures in the library.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
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.
#define fr_pair_list_foreach(_list_head, _iter)
Iterate over the contents of a fr_pair_list_t.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
int fr_value_box_bstrdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated talloced buffer to a fr_value_box_t.
int fr_value_box_bstrdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a talloced buffer containing a nul terminated string to a box, but don't copy it.
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
#define fr_box_strvalue_len(_val, _len)