The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
eap_fast.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: cf84959a488cf9cfd1a71b796b97c86847de9bc8 $
19 * @file eap_fast.c
20 * @brief Contains the interfaces that are called from the main handler
21 *
22 * @author Alexander Clouter (alex@digriz.org.uk)
23
24 * @copyright 2016 Alan DeKok (aland@freeradius.org)
25 * @copyright 2016 The FreeRADIUS server project
26 */
27RCSID("$Id: cf84959a488cf9cfd1a71b796b97c86847de9bc8 $")
28
29#include "eap_fast.h"
30#include "eap_fast_crypto.h"
31#include <freeradius-devel/tls/utils.h>
32#include <freeradius-devel/util/sha1.h>
33#include <freeradius-devel/tls/openssl_user_macros.h>
34#include <openssl/rand.h>
35#include <openssl/ssl.h>
36
37#define RANDFILL(x) do { fr_assert(sizeof(x) % sizeof(uint32_t) == 0); for (size_t i = 0; i < sizeof(x); i += sizeof(uint32_t)) *((uint32_t *)&x[i]) = fr_rand(); } while(0)
38
39/**
40 * RFC 4851 section 5.1 - EAP-FAST Authentication Phase 1: Key Derivations
41 */
42static void eap_fast_init_keys(request_t *request, fr_tls_session_t *tls_session)
43{
44 eap_fast_tunnel_t *t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
45 uint8_t *buf;
46 uint8_t *scratch;
47 size_t ksize;
48
49 RDEBUG2("Deriving EAP-FAST keys");
50
51 fr_assert(t->s_imck == NULL);
52
53 ksize = fr_tls_utils_keyblock_size_get(request, tls_session->ssl);
54 fr_assert(ksize > 0);
55 buf = talloc_array(request, uint8_t, ksize + sizeof(*t->keyblock));
56 scratch = talloc_array(request, uint8_t, ksize + sizeof(*t->keyblock));
57
58 t->keyblock = talloc(t, eap_fast_keyblock_t);
59
60 eap_fast_tls_gen_challenge(tls_session->ssl, buf, scratch, ksize + sizeof(*t->keyblock), "key expansion");
61 memcpy(t->keyblock, &buf[ksize], sizeof(*t->keyblock));
62 memset(buf, 0, ksize + sizeof(*t->keyblock));
63
64 t->s_imck = talloc_array(t, uint8_t, EAP_FAST_SIMCK_LEN);
65 memcpy(t->s_imck, t->keyblock, EAP_FAST_SKS_LEN); /* S-IMCK[0] = session_key_seed */
66
67 t->cmk = talloc_array(t, uint8_t, EAP_FAST_CMK_LEN); /* note that CMK[0] is not defined */
68 t->imck_count = 0;
69
70 talloc_free(buf);
71 talloc_free(scratch);
72}
73
74/**
75 * RFC 4851 section 5.2 - Intermediate Compound Key Derivations
76 */
77static void eap_fast_update_icmk(request_t *request, fr_tls_session_t *tls_session, uint8_t *msk)
78{
79 eap_fast_tunnel_t *t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
81
82 RDEBUG2("Updating ICMK");
83
84 T_PRF(t->s_imck, EAP_FAST_SIMCK_LEN, "Inner Methods Compound Keys", msk, 32, imck, sizeof(imck)); //-V512
85
86 memcpy(t->s_imck, imck, EAP_FAST_SIMCK_LEN);
87 RHEXDUMP3(t->s_imck, EAP_FAST_SIMCK_LEN, "S-IMCK[j]");
88
89 memcpy(t->cmk, &imck[EAP_FAST_SIMCK_LEN], EAP_FAST_CMK_LEN);
90 RHEXDUMP3(t->cmk, EAP_FAST_CMK_LEN, "CMK[j]");
91
92 t->imck_count++;
93
94 /*
95 * Calculate MSK/EMSK at the same time as they are coupled to ICMK
96 *
97 * RFC 4851 section 5.4 - EAP Master Session Key Generation
98 */
99 t->msk = talloc_array(t, uint8_t, EAP_FAST_KEY_LEN);
100 T_PRF(t->s_imck, EAP_FAST_SIMCK_LEN, "Session Key Generating Function", NULL, 0, t->msk, EAP_FAST_KEY_LEN);
101 RHEXDUMP3(t->msk, EAP_FAST_KEY_LEN, "MSK");
102
103 t->emsk = talloc_array(t, uint8_t, EAP_EMSK_LEN);
104 T_PRF(t->s_imck, EAP_FAST_SIMCK_LEN, "Extended Session Key Generating Function", NULL, 0, t->emsk, EAP_EMSK_LEN);
105 RHEXDUMP3(t->emsk, EAP_EMSK_LEN, "EMSK");
106}
107
108void eap_fast_tlv_append(fr_tls_session_t *tls_session, fr_dict_attr_t const *tlv, bool mandatory, int length, void const *data)
109{
110 uint16_t hdr[2];
111
112 hdr[0] = (mandatory) ? htons(tlv->attr | EAP_FAST_TLV_MANDATORY) : htons(tlv->attr);
113 hdr[1] = htons(length);
114
115 tls_session->record_from_buff(&tls_session->clean_in, &hdr, 4);
116 tls_session->record_from_buff(&tls_session->clean_in, data, length);
117}
118
119static void eap_fast_send_error(fr_tls_session_t *tls_session, int error)
120{
122 value = htonl(error);
123
124 eap_fast_tlv_append(tls_session, attr_eap_fast_error, true, sizeof(value), &value);
125}
126
127static void eap_fast_append_result(fr_tls_session_t *tls_session, fr_radius_packet_code_t code)
128{
129 eap_fast_tunnel_t *t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
130 uint16_t state;
131 fr_dict_attr_t const *da;
132
133
136
137 eap_fast_tlv_append(tls_session, da, true, sizeof(state), &state);
138}
139
140static void eap_fast_send_identity_request(request_t *request, fr_tls_session_t *tls_session, eap_session_t *eap_session)
141{
142 eap_packet_raw_t eap_packet;
143
144 RDEBUG2("Sending EAP-Identity");
145
146 eap_packet.code = FR_EAP_CODE_REQUEST;
147 eap_packet.id = eap_session->this_round->response->id + 1;
148 eap_packet.length[0] = 0;
149 eap_packet.length[1] = EAP_HEADER_LEN + 1;
150 eap_packet.data[0] = FR_EAP_METHOD_IDENTITY;
151
152 eap_fast_tlv_append(tls_session, attr_eap_fast_eap_payload, true, sizeof(eap_packet), &eap_packet);
153}
154
155static void eap_fast_send_pac_tunnel(request_t *request, fr_tls_session_t *tls_session)
156{
157 eap_fast_tunnel_t *t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
158 eap_fast_pac_t pac;
160 int alen, dlen;
161
162 memset(&pac, 0, sizeof(pac));
163 memset(&opaque_plaintext, 0, sizeof(opaque_plaintext));
164
165 RDEBUG2("Sending Tunnel PAC");
166
168 pac.key.hdr.length = htons(sizeof(pac.key.data));
169 fr_assert(sizeof(pac.key.data) % sizeof(uint32_t) == 0);
170 RANDFILL(pac.key.data);
171
173 pac.info.lifetime.hdr.length = htons(sizeof(pac.info.lifetime.data));
174 pac.info.lifetime.data = htonl(fr_time_to_sec(fr_time_add(request->packet->timestamp, t->pac_lifetime)));
175
177 pac.info.a_id.hdr.length = htons(sizeof(pac.info.a_id.data));
178 memcpy(pac.info.a_id.data, t->a_id, sizeof(pac.info.a_id.data));
179
180 pac.info.a_id_info.hdr.type = htons(attr_eap_fast_pac_a_id->attr);
181 pac.info.a_id_info.hdr.length = htons(sizeof(pac.info.a_id_info.data));
182
183#define MIN(a,b) (((a)>(b)) ? (b) : (a))
184 alen = MIN(talloc_array_length(t->authority_identity) - 1, sizeof(pac.info.a_id_info.data));
185 memcpy(pac.info.a_id_info.data, t->authority_identity, alen);
186
188 pac.info.type.hdr.length = htons(sizeof(pac.info.type.data));
189 pac.info.type.data = htons(PAC_TYPE_TUNNEL);
190
192 pac.info.hdr.length = htons(sizeof(pac.info.lifetime)
193 + sizeof(pac.info.a_id)
194 + sizeof(pac.info.a_id_info)
195 + sizeof(pac.info.type));
196
197 memcpy(&opaque_plaintext.type, &pac.info.type, sizeof(opaque_plaintext.type));
198 memcpy(&opaque_plaintext.lifetime, &pac.info.lifetime, sizeof(opaque_plaintext.lifetime));
199 memcpy(&opaque_plaintext.key, &pac.key, sizeof(opaque_plaintext.key));
200
201 RHEXDUMP3((uint8_t const *)&opaque_plaintext, sizeof(opaque_plaintext), "PAC-Opaque plaintext data section");
202
203 fr_assert(PAC_A_ID_LENGTH <= EVP_GCM_TLS_TAG_LEN);
204 memcpy(pac.opaque.aad, t->a_id, PAC_A_ID_LENGTH);
205 fr_assert(RAND_bytes(pac.opaque.iv, sizeof(pac.opaque.iv)) != 0);
206 dlen = eap_fast_encrypt((unsigned const char *)&opaque_plaintext, sizeof(opaque_plaintext),
208 pac.opaque.data, pac.opaque.tag);
209
211 pac.opaque.hdr.length = htons(sizeof(pac.opaque) - sizeof(pac.opaque.hdr) - sizeof(pac.opaque.data) + dlen);
212 RHEXDUMP3((uint8_t const *)&pac.opaque, sizeof(pac.opaque) - sizeof(pac.opaque.data) + dlen, "PAC-Opaque");
213
214 eap_fast_tlv_append(tls_session, attr_eap_fast_pac_tlv, true, sizeof(pac) - sizeof(pac.opaque.data) + dlen, &pac);
215}
216
217static void eap_fast_append_crypto_binding(request_t *request, fr_tls_session_t *tls_session)
218{
219 eap_fast_tunnel_t *t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
220 eap_tlv_crypto_binding_tlv_t binding = {0};
221 int const len = sizeof(binding) - (&binding.reserved - (uint8_t *)&binding);
222
223 RDEBUG2("Sending Cryptobinding");
224
226 binding.length = htons(len);
227 binding.version = EAP_FAST_VERSION;
228 binding.received_version = EAP_FAST_VERSION; /* FIXME use the clients value */
230
231 fr_assert(sizeof(binding.nonce) % sizeof(uint32_t) == 0);
232 RANDFILL(binding.nonce);
233 binding.nonce[sizeof(binding.nonce) - 1] &= ~0x01; /* RFC 4851 section 4.2.8 */
234 RHEXDUMP3(binding.nonce, sizeof(binding.nonce), "NONCE");
235
236 RHEXDUMP3((uint8_t const *) &binding, sizeof(binding), "Crypto-Binding TLV for Compound MAC calculation");
237
238 fr_hmac_sha1(binding.compound_mac, (uint8_t *)&binding, sizeof(binding), t->cmk, EAP_FAST_CMK_LEN);
239 RHEXDUMP3(binding.compound_mac, sizeof(binding.compound_mac), "Compound MAC");
240
241 eap_fast_tlv_append(tls_session, attr_eap_fast_crypto_binding, true, len, &binding.reserved);
242}
243
244#define EAP_FAST_TLV_MAX 11
245
246static int eap_fast_verify(request_t *request, fr_tls_session_t *tls_session, uint8_t const *data, unsigned int data_len)
247{
248 uint16_t attr;
249 uint16_t length;
250 unsigned int remaining = data_len;
251 int total = 0;
252 int num[EAP_FAST_TLV_MAX] = {0};
253 eap_fast_tunnel_t *t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
254 uint32_t present = 0;
255
256 fr_assert(sizeof(present) * 8 > EAP_FAST_TLV_MAX);
257
258 while (remaining > 0) {
259 if (remaining < 4) {
260 RDEBUG2("EAP-FAST TLV is too small (%u) to contain a EAP-FAST TLV header", remaining);
261 return 0;
262 }
263
264 memcpy(&attr, data, sizeof(attr));
265 attr = ntohs(attr) & EAP_FAST_TLV_TYPE;
266
267 if ((attr == attr_eap_fast_result->attr) ||
268 (attr == attr_eap_fast_nak->attr) ||
269 (attr == attr_eap_fast_error->attr) ||
270 (attr == attr_eap_fast_vendor_specific->attr) ||
271 (attr == attr_eap_fast_eap_payload->attr) ||
272 (attr == attr_eap_fast_intermediate_result->attr) ||
273 (attr == attr_eap_fast_pac_tlv->attr) ||
274 (attr == attr_eap_fast_crypto_binding->attr)) {
275 num[attr]++;
276 present |= 1 << attr;
277
278 if (num[attr_eap_fast_eap_payload->attr] > 1) {
279 REDEBUG("Too many EAP-Payload TLVs");
280unexpected:
281 for (int i = 0; i < EAP_FAST_TLV_MAX; i++) {
282 if (present & (1 << i)) RDEBUG2(" - attribute %d is present", i);
283 }
285 return 0;
286 }
287
288 if (num[attr_eap_fast_intermediate_result->attr] > 1) {
289 REDEBUG("Too many Intermediate-Result TLVs");
290 goto unexpected;
291 }
292 } else {
293 if ((data[0] & 0x80) != 0) {
294 REDEBUG("Unknown mandatory TLV %02x", attr);
295 goto unexpected;
296 }
297
298 num[0]++;
299 }
300
301 total++;
302
303 memcpy(&length, data + 2, sizeof(length));
304 length = ntohs(length);
305
306 data += 4;
307 remaining -= 4;
308
309 if (length > remaining) {
310 RDEBUG2("EAP-FAST TLV %u is longer than room remaining in the packet (%u > %u).", attr,
311 length, remaining);
312 return 0;
313 }
314
315 /*
316 * If the rest of the TLVs are larger than
317 * this attribute, continue.
318 *
319 * Otherwise, if the attribute over-flows the end
320 * of the TLCs, die.
321 */
322 if (remaining < length) {
323 RDEBUG2("EAP-FAST TLV overflows packet!");
324 return 0;
325 }
326
327 /*
328 * If there's an error, we bail out of the
329 * authentication process before allocating
330 * memory.
331 */
332 if ((attr == attr_eap_fast_intermediate_result->attr) || (attr == attr_eap_fast_result->attr)) {
333 uint16_t status;
334
335 if (length < 2) {
336 REDEBUG("EAP-FAST TLV %u is too short. Expected 2, got %d", attr, length);
337 return 0;
338 }
339
340 memcpy(&status, data, 2);
341 status = ntohs(status);
342
343 if (status == EAP_FAST_TLV_RESULT_FAILURE) {
344 REDEBUG("EAP-FAST TLV %u indicates failure. Rejecting request", attr);
345 return 0;
346 }
347
348 if (status != EAP_FAST_TLV_RESULT_SUCCESS) {
349 REDEBUG("EAP-FAST TLV %u contains unknown value. Rejecting request", attr);
350 goto unexpected;
351 }
352 }
353
354 /*
355 * remaining > length, continue.
356 */
357 remaining -= length;
358 data += length;
359 }
360
361 /*
362 * Check if the peer mixed & matched TLVs.
363 */
364 if ((num[attr_eap_fast_nak->attr] > 0) && (num[attr_eap_fast_nak->attr] != total)) {
365 REDEBUG("NAK TLV sent with non-NAK TLVs. Rejecting request");
366 goto unexpected;
367 }
368
369 if (num[attr_eap_fast_intermediate_result->attr] > 0) {
370 REDEBUG("NAK TLV sent with non-NAK TLVs. Rejecting request");
371 goto unexpected;
372 }
373
374 /*
375 * Check mandatory or not mandatory TLVs.
376 */
377 switch (t->stage) {
379 if (present) {
380 REDEBUG("Unexpected TLVs in TLS Session Handshake stage");
381 goto unexpected;
382 }
383 break;
385 if (present != (uint32_t)(1 << attr_eap_fast_eap_payload->attr)) {
386 REDEBUG("Unexpected TLVs in authentication stage");
387 goto unexpected;
388 }
389 break;
391 {
392 uint32_t bits = (t->result_final)
393 ? 1 << attr_eap_fast_result->attr
395 if (present & ~(bits | (1 << attr_eap_fast_crypto_binding->attr) | (1 << attr_eap_fast_pac_tlv->attr))) {
396 REDEBUG("Unexpected TLVs in cryptobind checking stage");
397 goto unexpected;
398 }
399 break;
400 }
402 if (present & ~((1 << attr_eap_fast_pac_tlv->attr) | (1 << attr_eap_fast_result->attr))) {
403 REDEBUG("Unexpected TLVs in provisioning stage");
404 goto unexpected;
405 }
406 break;
408 if (present) {
409 REDEBUG("Unexpected TLVs in complete stage");
410 goto unexpected;
411 }
412 break;
413 default:
414 REDEBUG("Unexpected stage %d", t->stage);
415 return 0;
416 }
417
418 /*
419 * We got this far. It looks OK.
420 */
421 return 1;
422}
423
424/**
425 *
426 * FIXME do something with mandatory
427 */
429 uint8_t const *data, size_t data_len,
430 void *decode_ctx)
431{
432 fr_dict_attr_t const *da;
433 uint8_t const *p = data, *end = p + data_len;
434
435 /*
436 * Decode the TLVs
437 */
438 while (p < end) {
439 ssize_t ret;
440 uint16_t attr;
441 uint16_t len;
442 fr_pair_t *vp;
443
445 p += 2;
446 len = fr_nbo_to_uint16(p);
447 p += 2;
448
450 if (!da) {
451 MEM(vp = fr_pair_afrom_child_num(ctx, parent, attr));
452
453 } else if (da->type == FR_TYPE_TLV) {
454 p += (size_t) eap_fast_decode_pair(ctx, out, parent, p, len, decode_ctx);
455 continue;
456
457 } else {
458 MEM(vp = fr_pair_afrom_da(ctx, da));
459 }
460
461 ret = fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
462 &FR_DBUFF_TMP(p, (size_t)len), len, true);
463 if (ret != len) {
464 fr_pair_raw_afrom_pair(vp, p, len);
465 }
467 p += len;
468 }
469
470 return p - data;
471}
472
473
474/*
475 * Use a reply packet to determine what to do.
476 */
478 fr_tls_session_t *tls_session,
479 request_t *request,
480 fr_packet_t *reply, fr_pair_list_t *reply_list)
481{
483 fr_pair_t *vp;
484 fr_dcursor_t cursor;
485
486 eap_fast_tunnel_t *t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
487
488 /*
489 * If the response packet was Access-Accept, then
490 * we're OK. If not, die horribly.
491 *
492 * FIXME: EAP-Messages can only start with 'identity',
493 * NOT 'eap start', so we should check for that....
494 */
495 switch (reply->code) {
497 RDEBUG2("Got tunneled Access-Accept");
498
499 rcode = RLM_MODULE_OK;
500
501 /*
502 * Copy what we need into the TTLS tunnel and leave
503 * the rest to be cleaned up.
504 */
505 for (vp = fr_pair_list_head(reply_list); vp; vp = fr_pair_list_next(reply_list, vp)) {
507
508 /* FIXME must be a better way to capture/re-derive this later for ISK */
509 switch (vp->da->attr) {
511 if (vp->vp_length != MD5_DIGEST_LENGTH) {
512 wrong_length:
513 REDEBUG("Found %s with incorrect length. Expected %u, got %zu",
514 vp->da->name, MD5_DIGEST_LENGTH, vp->vp_length);
515 rcode = RLM_MODULE_INVALID;
516 break;
517 }
518
519 memcpy(t->isk.mppe_send, vp->vp_octets, MD5_DIGEST_LENGTH);
520 break;
521
523 if (vp->vp_length != MD5_DIGEST_LENGTH) goto wrong_length;
524 memcpy(t->isk.mppe_recv, vp->vp_octets, MD5_DIGEST_LENGTH);
525 break;
526
528 RDEBUG2("Got %s, tunneling it to the client in a challenge", vp->da->name);
529 rcode = RLM_MODULE_HANDLED;
530 t->authenticated = true;
531 break;
532
533 default:
534 break;
535 }
536 }
537 RHEXDUMP3((uint8_t *)&t->isk, 2 * MD5_DIGEST_LENGTH, "ISK[j]"); /* FIXME (part of above) */
538 break;
539
541 REDEBUG("Got tunneled Access-Reject");
542 rcode = RLM_MODULE_REJECT;
543 break;
544
546 RDEBUG2("Got tunneled Access-Challenge");
547
548 /*
549 * Copy the EAP-Message back to the tunnel.
550 */
551
552 for (vp = fr_pair_dcursor_by_da_init(&cursor, reply_list, attr_eap_message);
553 vp;
554 vp = fr_dcursor_next(&cursor)) {
555 eap_fast_tlv_append(tls_session, attr_eap_fast_eap_payload, true, vp->vp_length, vp->vp_octets);
556 }
557
558 rcode = RLM_MODULE_HANDLED;
559 break;
560
561 default:
562 REDEBUG("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
563 rcode = RLM_MODULE_INVALID;
564 break;
565 }
566
567 return rcode;
568}
569
571 fr_tls_session_t *tls_session, fr_pair_t *tlv_eap_payload)
572{
574 rlm_rcode_t rcode;
575 fr_pair_t *vp;
578
579 RDEBUG2("Processing received EAP Payload");
580
581 /*
582 * Allocate a fake request_t structure.
583 */
584 fake = request_alloc_internal(request, &(request_init_args_t){ .parent = request });
585 fr_assert(fr_pair_list_empty(&fake->request_pairs));
586
587 t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
588
589 /*
590 * Add the tunneled attributes to the fake request.
591 */
592
593 MEM(vp = fr_pair_afrom_da(fake->request_ctx, attr_eap_message));
594 fr_pair_append(&fake->request_pairs, vp);
595 fr_pair_value_memdup(vp, tlv_eap_payload->vp_octets, tlv_eap_payload->vp_length, false);
596
597 RDEBUG2("Got tunneled request");
598 log_request_pair_list(L_DBG_LVL_1, fake, NULL, &fake->request_pairs, NULL);
599
600 /*
601 * Tell the request that it's a fake one.
602 */
603 MEM(fr_pair_prepend_by_da(fake->request_ctx, &vp, &fake->request_pairs, attr_freeradius_proxied_to) >= 0);
604 (void)fr_pair_value_from_str(vp, "127.0.0.1", sizeof("127.0.0.1") - 1, NULL, false);
605
606 /*
607 * If there's no User-Name in the stored data, look for
608 * an EAP-Identity, and pull it out of there.
609 */
610 if (!t->username) {
611 fr_assert(vp->da == attr_eap_message); /* cached from above */
612
613 if ((vp->vp_length >= EAP_HEADER_LEN + 2) &&
614 (vp->vp_strvalue[0] == FR_EAP_CODE_RESPONSE) &&
615 (vp->vp_strvalue[EAP_HEADER_LEN] == FR_EAP_METHOD_IDENTITY) &&
616 (vp->vp_strvalue[EAP_HEADER_LEN + 1] != 0)) {
617 /*
618 * Create and remember a User-Name
619 */
621 t->username->vp_tainted = true;
622 fr_pair_value_bstrndup(t->username, (char const *)vp->vp_octets + 5, vp->vp_length - 5, true);
623
624 RDEBUG2("Got tunneled identity of %pV", &t->username->data);
625 } else {
626 /*
627 * Don't reject the request outright,
628 * as it's permitted to do EAP without
629 * user-name.
630 */
631 RWDEBUG2("No EAP-Identity found to start EAP conversation");
632 }
633 } /* else there WAS a t->username */
634
635 if (t->username) {
636 vp = fr_pair_copy(fake->request_ctx, t->username);
637 fr_pair_append(&fake->request_pairs, vp);
638 }
639
640 if (t->stage == EAP_FAST_AUTHENTICATION) { /* FIXME do this only for MSCHAPv2 */
641 fr_pair_t *tvp;
642
644 tvp->vp_uint32 = t->default_provisioning_method;
645 fr_pair_append(&fake->control_pairs, tvp);
646
647 /*
648 * RFC 5422 section 3.2.3 - Authenticating Using EAP-FAST-MSCHAPv2
649 */
653 fr_pair_append(&fake->control_pairs, tvp);
654 RHEXDUMP3(t->keyblock->server_challenge, MD5_DIGEST_LENGTH, "MSCHAPv2 auth_challenge");
655
658 fr_pair_append(&fake->control_pairs, tvp);
659 RHEXDUMP3(t->keyblock->client_challenge, MD5_DIGEST_LENGTH, "MSCHAPv2 peer_challenge");
660 }
661 }
662
663 /*
664 * Call authentication recursively, which will
665 * do PAP, CHAP, MS-CHAP, etc.
666 */
667 eap_virtual_server(request, eap_session, t->server_cs);
668
669 /*
670 * Decide what to do with the reply.
671 */
672 switch (fake->reply->code) {
673 case 0: /* No reply code, must be proxied... */
674#ifdef WITH_PROXY
675 vp = fr_pair_find_by_da(&fake->control, NULL, attr_proxy_to_realm);
676 if (vp) {
677 int ret;
678 eap_tunnel_data_t *tunnel;
679
680 RDEBUG2("Tunneled authentication will be proxied to %pV", &vp->data);
681
682 /*
683 * Tell the original request that it's going to be proxied.
684 */
685 fr_pair_list_copy_by_da(request->control_ctx, &request->control_pairs,
686 &fake->control_pairs, attr_proxy_to_realm, 0);
687
688 /*
689 * Seed the proxy packet with the tunneled request.
690 */
691 fr_assert(!request->proxy);
692
693 /*
694 * FIXME: Actually proxy stuff
695 */
696 request->proxy = request_alloc_internal(request, &(request_init_args_t){ .parent = request });
697
698 request->proxy->packet = talloc_steal(request->proxy, fake->packet);
699 memset(&request->proxy->packet->src_ipaddr, 0,
700 sizeof(request->proxy->packet->src_ipaddr));
701 memset(&request->proxy->packet->src_ipaddr, 0,
702 sizeof(request->proxy->packet->src_ipaddr));
703 request->proxy->packet->src_port = 0;
704 request->proxy->packet->dst_port = 0;
705 fake->packet = NULL;
706 fr_packet_free(&fake->reply);
707 fake->reply = NULL;
708
709 /*
710 * Set up the callbacks for the tunnel
711 */
712 tunnel = talloc_zero(request, eap_tunnel_data_t);
713 tunnel->tls_session = tls_session;
714
715 /*
716 * Associate the callback with the request.
717 */
718 ret = request_data_add(request, request->proxy, REQUEST_DATA_EAP_TUNNEL_CALLBACK,
719 tunnel, false, false, false);
720 fr_cond_assert(ret == 0);
721
722 /*
723 * rlm_eap.c has taken care of associating the eap_session
724 * with the fake request.
725 *
726 * So we associate the fake request with this request.
727 */
728 ret = request_data_add(request, request->proxy, REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK,
729 fake, true, false, false);
730 fr_cond_assert(ret == 0);
731
732 fake = NULL;
733
734 /*
735 * Didn't authenticate the packet, but we're proxying it.
736 */
738
739 } else
740#endif /* WITH_PROXY */
741 {
742 REDEBUG("No tunneled reply was found, and the request was not proxied: rejecting the user");
744 }
745 break;
746
747 default:
748 /*
749 * Returns RLM_MODULE_FOO, and we want to return FR_FOO
750 */
751 rcode = process_reply(eap_session, tls_session, request, fake->reply, &fake->reply_pairs);
752 switch (rcode) {
755 break;
756
759 break;
760
761 case RLM_MODULE_OK:
763 break;
764
765 default:
767 break;
768 }
769 break;
770 }
771
773
774 return code;
775}
776
778 fr_tls_session_t *tls_session, eap_tlv_crypto_binding_tlv_t *binding)
779{
780 uint8_t cmac[sizeof(binding->compound_mac)];
781 eap_fast_tunnel_t *t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
782
783 memcpy(cmac, binding->compound_mac, sizeof(cmac));
784 memset(binding->compound_mac, 0, sizeof(binding->compound_mac));
785
786 RHEXDUMP3((uint8_t const *) binding, sizeof(*binding), "Crypto-Binding TLV for Compound MAC calculation");
787 RHEXDUMP3(cmac, sizeof(cmac), "Received Compound MAC");
788
789 fr_hmac_sha1(binding->compound_mac, (uint8_t *)binding, sizeof(*binding), t->cmk, EAP_FAST_CMK_LEN);
790 if (memcmp(binding->compound_mac, cmac, sizeof(cmac))) {
791 RDEBUG2("Crypto-Binding TLV mismatch");
792 RHEXDUMP3((uint8_t const *) binding->compound_mac,
793 sizeof(binding->compound_mac), "Calculated Compound MAC");
795 }
796
798}
799
801 fr_tls_session_t *tls_session, fr_pair_list_t *fast_vps)
802{
803 eap_fast_tunnel_t *t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
804 fr_pair_t *vp;
805 eap_tlv_crypto_binding_tlv_t my_binding, *binding = NULL;
806
807 memset(&my_binding, 0, sizeof(my_binding));
808
809 for (vp = fr_pair_list_head(fast_vps);
810 vp;
811 vp = fr_pair_list_next(fast_vps, vp)) {
813 if (vp->da->parent == fr_dict_root(dict_eap_fast)) {
815 code = eap_fast_eap_payload(request, eap_session, tls_session, vp);
817 } else if ((vp->da == attr_eap_fast_result) ||
821 } else {
822 RDEBUG2("ignoring unknown %pP", vp);
823 continue;
824 }
825 } else if (vp->da->parent == attr_eap_fast_crypto_binding) {
826 binding = &my_binding;
827
828 /*
829 * fr_radius_encode_pair() does not work for structures
830 */
831 switch (vp->da->attr) {
832 case 1: /* FR_EAP_FAST_CRYPTO_BINDING_RESERVED */
833 binding->reserved = vp->vp_uint8;
834 break;
835 case 2: /* FR_EAP_FAST_CRYPTO_BINDING_VERSION */
836 binding->version = vp->vp_uint8;
837 break;
838 case 3: /* FR_EAP_FAST_CRYPTO_BINDING_RECV_VERSION */
839 binding->received_version = vp->vp_uint8;
840 break;
841 case 4: /* FR_EAP_FAST_CRYPTO_BINDING_SUB_TYPE */
842 binding->subtype = vp->vp_uint8;
843 break;
844 case 5: /* FR_EAP_FAST_CRYPTO_BINDING_NONCE */
845 if (vp->vp_length >= sizeof(binding->nonce)) {
846 memcpy(binding->nonce, vp->vp_octets, vp->vp_length);
847 }
848 break;
849 case 6: /* FR_EAP_FAST_CRYPTO_BINDING_COMPOUND_MAC */
850 if (vp->vp_length >= sizeof(binding->compound_mac)) {
851 memcpy(binding->compound_mac, vp->vp_octets, sizeof(binding->compound_mac));
852 }
853 break;
854 }
855 continue;
856 } else if (vp->da->parent == attr_eap_fast_pac_tlv) {
858 if (vp->vp_uint32 == EAP_FAST_TLV_RESULT_SUCCESS) {
860 t->pac.expires = fr_time_max();
861 t->pac.expired = false;
863 }
864 } else if (vp->da == attr_eap_fast_pac_info_pac_type) {
865 if (vp->vp_uint32 != PAC_TYPE_TUNNEL) {
866 RDEBUG2("only able to serve Tunnel PAC's, ignoring request");
867 continue;
868 }
869 t->pac.send = true;
870 continue;
871 } else {
872 RDEBUG2("ignoring unknown EAP-FAST-PAC-TLV %pP", vp);
873 continue;
874 }
875 } else {
876 RDEBUG2("ignoring non-EAP-FAST TLV %pP", vp);
877 continue;
878 }
879
881 }
882
883 if (binding) {
884 fr_radius_packet_code_t code = eap_fast_crypto_binding(request, eap_session, tls_session, binding);
885 if (code == FR_RADIUS_CODE_ACCESS_ACCEPT) {
887 }
888 return code;
889 }
890
892}
893
894
895/*
896 * Process the inner tunnel data
897 */
898fr_radius_packet_code_t eap_fast_process(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
899{
901 fr_pair_list_t fast_vps;
902 uint8_t const *data;
903 size_t data_len;
905
906 fr_pair_list_init(&fast_vps);
907 /*
908 * Just look at the buffer directly, without doing
909 * record_to_buff.
910 */
911 data_len = tls_session->clean_out.used;
912 tls_session->clean_out.used = 0;
913 data = tls_session->clean_out.data;
914
915 t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
916
917 /*
918 * See if the tunneled data is well formed.
919 */
920 if (!eap_fast_verify(request, tls_session, data, data_len)) return FR_RADIUS_CODE_ACCESS_REJECT;
921
923 char buf[256];
924
926
927 if (strstr(SSL_CIPHER_description(SSL_get_current_cipher(tls_session->ssl),
928 buf, sizeof(buf)), "Au=None")) {
929 /* FIXME enforce MSCHAPv2 - RFC 5422 section 3.2.2 */
930 RDEBUG2("Using anonymous provisioning");
932 t->pac.send = true;
933 } else {
934 fr_time_t renew;
935
936 if (SSL_session_reused(tls_session->ssl)) {
937 RDEBUG2("Session Resumed from PAC");
939 } else {
940 RDEBUG2("Using authenticated provisioning");
942 }
943
944 /*
945 * Send a new pac at 60% of the lifetime,
946 * or if the PAC has expired, or if no lifetime was set.
947 */
948 renew = fr_time_add(request->packet->timestamp,
950
951 if (t->pac.expired || fr_time_eq(t->pac.expires, fr_time_wrap(0)) ||
952 fr_time_lteq(t->pac.expires, renew)) {
953 t->pac.send = true;
954 }
955 }
956
957 eap_fast_init_keys(request, tls_session);
958
959 eap_fast_send_identity_request(request, tls_session, eap_session);
960
963 }
964
965 if (eap_fast_decode_pair(request, &fast_vps, fr_dict_root(dict_eap_fast),
966 data, data_len, NULL) < 0) return FR_RADIUS_CODE_ACCESS_REJECT;
967
968 RDEBUG2("Got Tunneled FAST TLVs");
969 log_request_pair_list(L_DBG_LVL_1, request, NULL, &fast_vps, NULL);
970 code = eap_fast_process_tlvs(request, eap_session, tls_session, &fast_vps);
971 fr_pair_list_free(&fast_vps);
972
974
975 switch (t->stage) {
978 break;
979
981 {
982 if (t->mode != EAP_FAST_PROVISIONING_ANON && !t->pac.send)
983 t->result_final = true;
984
985 eap_fast_append_result(tls_session, code);
986
987 eap_fast_update_icmk(request, tls_session, (uint8_t *)&t->isk);
988 eap_fast_append_crypto_binding(request, tls_session);
989
991 break;
992 }
994 t->result_final = true;
995
996 eap_fast_append_result(tls_session, code);
997
998 if (t->pac.send) {
999 RDEBUG2("Peer requires new PAC");
1000 eap_fast_send_pac_tunnel(request, tls_session);
1002 break;
1003 }
1004
1007
1008 case EAP_FAST_COMPLETE:
1009 /*
1010 * RFC 5422 section 3.5 - Network Access after EAP-FAST Provisioning
1011 */
1012 if (t->pac.type && t->pac.expired) {
1013 REDEBUG("Rejecting expired PAC.");
1015 break;
1016 }
1017
1018 if (t->mode == EAP_FAST_PROVISIONING_ANON) {
1019 REDEBUG("Rejecting unauthenticated provisioning");
1021 break;
1022 }
1023
1024 /*
1025 * eap_crypto_mppe_keys() is unsuitable for EAP-FAST as Cisco decided
1026 * it would be a great idea to flip the recv/send keys around
1027 */
1028 #define EAPTLS_MPPE_KEY_LEN 32
1033
1034 break;
1035
1036 default:
1037 RERROR("Internal sanity check failed in EAP-FAST at %d", t->stage);
1039 }
1040
1041 return code;
1042}
#define RCSID(id)
Definition build.h:483
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:322
#define UNUSED
Definition build.h:315
eap_packet_t * response
Packet we received from the peer.
Definition compose.h:49
uint8_t id
Definition compose.h:37
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:514
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:139
#define MEM(x)
Definition debug.h:36
#define FR_MSCHAP_MPPE_RECV_KEY
Definition defs.h:162
fr_radius_packet_code_t
RADIUS packet codes.
Definition defs.h:31
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
Definition defs.h:43
@ FR_RADIUS_CODE_STATUS_CLIENT
RFC2865/RFC5997 - Status Server (response)
Definition defs.h:45
@ FR_RADIUS_CODE_ACCESS_ACCEPT
RFC2865 - Access-Accept.
Definition defs.h:34
@ FR_RADIUS_CODE_ACCESS_REJECT
RFC2865 - Access-Reject.
Definition defs.h:35
#define VENDORPEC_MICROSOFT
Definition defs.h:145
#define FR_MSCHAP_MPPE_SEND_KEY
Definition defs.h:161
#define FR_MSCHAP2_SUCCESS
Definition defs.h:164
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2400
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Definition dict_util.c:3328
static uint32_t fr_dict_vendor_num_by_da(fr_dict_attr_t const *da)
Return the vendor number for an attribute.
Definition dict_ext.h:212
Test enumeration values.
Definition dict_test.h:92
#define REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK
Definition base.h:45
#define REQUEST_DATA_EAP_TUNNEL_CALLBACK
Definition base.h:44
void * tls_session
Definition base.h:53
@ FR_EAP_CODE_RESPONSE
Definition types.h:38
@ FR_EAP_CODE_REQUEST
Definition types.h:37
uint8_t data[1]
Definition types.h:125
uint8_t code
Definition types.h:122
#define EAP_HEADER_LEN
Definition types.h:34
uint8_t length[2]
Definition types.h:124
uint8_t id
Definition types.h:123
@ FR_EAP_METHOD_IDENTITY
Definition types.h:46
Structure to represent packet format of eap on wire
Definition types.h:121
ssize_t eap_fast_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decode_ctx)
FIXME do something with mandatory.
Definition eap_fast.c:428
static int eap_fast_verify(request_t *request, fr_tls_session_t *tls_session, uint8_t const *data, unsigned int data_len)
Definition eap_fast.c:246
#define RANDFILL(x)
Definition eap_fast.c:37
static fr_radius_packet_code_t eap_fast_eap_payload(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session, fr_pair_t *tlv_eap_payload)
Definition eap_fast.c:570
#define MIN(a, b)
static void eap_fast_send_identity_request(request_t *request, fr_tls_session_t *tls_session, eap_session_t *eap_session)
Definition eap_fast.c:140
#define EAPTLS_MPPE_KEY_LEN
void eap_fast_tlv_append(fr_tls_session_t *tls_session, fr_dict_attr_t const *tlv, bool mandatory, int length, void const *data)
Definition eap_fast.c:108
static void eap_fast_append_result(fr_tls_session_t *tls_session, fr_radius_packet_code_t code)
Definition eap_fast.c:127
static void eap_fast_send_error(fr_tls_session_t *tls_session, int error)
Definition eap_fast.c:119
static fr_radius_packet_code_t eap_fast_crypto_binding(request_t *request, UNUSED eap_session_t *eap_session, fr_tls_session_t *tls_session, eap_tlv_crypto_binding_tlv_t *binding)
Definition eap_fast.c:777
static void eap_fast_init_keys(request_t *request, fr_tls_session_t *tls_session)
RFC 4851 section 5.1 - EAP-FAST Authentication Phase 1: Key Derivations.
Definition eap_fast.c:42
#define EAP_FAST_TLV_MAX
Definition eap_fast.c:244
fr_radius_packet_code_t eap_fast_process(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
Definition eap_fast.c:898
static rlm_rcode_t process_reply(UNUSED eap_session_t *eap_session, fr_tls_session_t *tls_session, request_t *request, fr_packet_t *reply, fr_pair_list_t *reply_list)
Definition eap_fast.c:477
static void eap_fast_send_pac_tunnel(request_t *request, fr_tls_session_t *tls_session)
Definition eap_fast.c:155
static void eap_fast_append_crypto_binding(request_t *request, fr_tls_session_t *tls_session)
Definition eap_fast.c:217
static fr_radius_packet_code_t eap_fast_process_tlvs(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session, fr_pair_list_t *fast_vps)
Definition eap_fast.c:800
static void eap_fast_update_icmk(request_t *request, fr_tls_session_t *tls_session, uint8_t *msk)
RFC 4851 section 5.2 - Intermediate Compound Key Derivations.
Definition eap_fast.c:77
HIDDEN fr_dict_attr_t const * attr_eap_fast_result
HIDDEN fr_dict_attr_t const * attr_eap_fast_nak
#define EAP_FAST_TLV_MANDATORY
Definition eap_fast.h:42
HIDDEN fr_dict_attr_t const * attr_proxy_to_realm
uint8_t const * a_id
Definition eap_fast.h:189
#define EAP_FAST_SKS_LEN
Definition eap_fast.h:38
unsigned char aad[PAC_A_ID_LENGTH]
Definition eap_fast.h:122
eap_fast_pac_attr_lifetime_t lifetime
Definition eap_fast.h:116
eap_fast_pac_attr_hdr_t hdr
Definition eap_fast.h:100
HIDDEN fr_dict_attr_t const * attr_eap_fast_pac_key
uint8_t client_challenge[MD5_DIGEST_LENGTH]
Definition eap_fast.h:163
HIDDEN fr_dict_attr_t const * attr_eap_fast_pac_info_tlv
eap_fast_pac_attr_lifetime_t lifetime
Definition eap_fast.h:130
HIDDEN fr_dict_attr_t const * attr_eap_fast_error
eap_fast_stage_t stage
Definition eap_fast.h:172
#define EAP_FAST_KEY_LEN
Definition eap_fast.h:36
#define PAC_A_ID_LENGTH
Definition eap_fast.h:75
eap_fast_pac_attr_pac_key_t key
Definition eap_fast.h:137
#define EAP_FAST_VERSION
Definition eap_fast.h:34
eap_fast_keyblock_t * keyblock
Definition eap_fast.h:173
eap_fast_pac_attr_hdr_t hdr
Definition eap_fast.h:85
fr_time_delta_t pac_lifetime
Definition eap_fast.h:187
uint8_t * s_imck
Definition eap_fast.h:174
@ EAP_FAST_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST
Definition eap_fast.h:155
HIDDEN fr_dict_attr_t const * attr_eap_fast_pac_info_pac_type
#define EAP_FAST_SIMCK_LEN
Definition eap_fast.h:39
HIDDEN fr_dict_attr_t const * attr_eap_fast_pac_info_pac_lifetime
eap_fast_pac_attr_a_id_info_t a_id_info
Definition eap_fast.h:132
HIDDEN fr_dict_attr_t const * attr_ms_chap_peer_challenge
#define EAP_FAST_TLV_TYPE
Definition eap_fast.h:43
uint8_t data[PAC_A_ID_INFO_LENGTH]
Definition eap_fast.h:101
int default_provisioning_method
Definition eap_fast.h:185
eap_fast_pac_attr_hdr_t hdr
Definition eap_fast.h:129
unsigned char iv[EVP_MAX_IV_LENGTH]
Definition eap_fast.h:123
uint8_t data[PAC_KEY_LENGTH]
Definition eap_fast.h:111
fr_pair_t * username
Definition eap_fast.h:167
eap_fast_pac_attr_hdr_t hdr
Definition eap_fast.h:121
HIDDEN fr_dict_attr_t const * attr_eap_fast_intermediate_result
unsigned char tag[EVP_GCM_TLS_TAG_LEN]
Definition eap_fast.h:124
uint8_t * emsk
Definition eap_fast.h:182
HIDDEN fr_dict_attr_t const * attr_eap_fast_pac_tlv
eap_fast_pac_attr_hdr_t hdr
Definition eap_fast.h:110
eap_fast_attr_pac_opaque_t opaque
Definition eap_fast.h:139
struct eap_fast_tunnel_t::@158 isk
HIDDEN fr_dict_attr_t const * attr_eap_fast_eap_payload
#define EAP_FAST_TLV_RESULT_SUCCESS
Definition eap_fast.h:49
eap_fast_pac_attr_pac_type_t type
Definition eap_fast.h:115
HIDDEN fr_dict_attr_t const * attr_eap_fast_crypto_binding
#define EAP_FAST_ERR_UNEXPECTED_TLV
Definition eap_fast.h:47
HIDDEN fr_dict_attr_t const * attr_eap_fast_vendor_specific
eap_fast_pac_attr_hdr_t hdr
Definition eap_fast.h:90
HIDDEN fr_dict_t const * dict_eap_fast
uint8_t data[PAC_A_ID_LENGTH]
Definition eap_fast.h:91
char const * authority_identity
Definition eap_fast.h:188
eap_fast_attr_pac_info_t info
Definition eap_fast.h:138
struct eap_fast_tunnel_t::@159 pac
eap_fast_pac_attr_a_id_t a_id
Definition eap_fast.h:131
eap_fast_pac_attr_hdr_t hdr
Definition eap_fast.h:105
uint8_t * cmk
Definition eap_fast.h:175
uint8_t server_challenge[MD5_DIGEST_LENGTH]
Definition eap_fast.h:162
uint8_t data[sizeof(eap_fast_attr_pac_opaque_plaintext_t) *2]
Definition eap_fast.h:125
eap_fast_pac_attr_pac_type_t type
Definition eap_fast.h:133
@ EAP_FAST_COMPLETE
Definition eap_fast.h:57
@ EAP_FAST_AUTHENTICATION
Definition eap_fast.h:54
@ EAP_FAST_CRYPTOBIND_CHECK
Definition eap_fast.h:55
@ EAP_FAST_PROVISIONING
Definition eap_fast.h:56
@ EAP_FAST_TLS_SESSION_HANDSHAKE
Definition eap_fast.h:53
@ EAP_FAST_UNKNOWN
Definition eap_fast.h:61
@ EAP_FAST_NORMAL_AUTH
Definition eap_fast.h:64
@ EAP_FAST_PROVISIONING_ANON
Definition eap_fast.h:62
@ EAP_FAST_PROVISIONING_AUTH
Definition eap_fast.h:63
HIDDEN fr_dict_attr_t const * attr_eap_fast_pac_opaque_tlv
CONF_SECTION * server_cs
Definition eap_fast.h:206
eap_fast_pac_attr_pac_key_t key
Definition eap_fast.h:117
#define EAP_EMSK_LEN
Definition eap_fast.h:37
#define EAP_FAST_TLV_RESULT_FAILURE
Definition eap_fast.h:50
HIDDEN fr_dict_attr_t const * attr_eap_fast_pac_a_id
@ PAC_TYPE_TUNNEL
Definition eap_fast.h:68
uint8_t const * pac_opaque_key
Definition eap_fast.h:190
HIDDEN fr_dict_attr_t const * attr_eap_fast_pac_acknowledge
#define EAP_FAST_CMK_LEN
Definition eap_fast.h:40
uint8_t * msk
Definition eap_fast.h:181
void eap_fast_tls_gen_challenge(SSL *s, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label)
int eap_fast_encrypt(uint8_t const *plaintext, size_t plaintext_len, uint8_t const *aad, size_t aad_len, uint8_t const *key, uint8_t *iv, unsigned char *ciphertext, uint8_t *tag)
USES_APPLE_DEPRECATED_API 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)
Crypto function declarations.
int fr_hmac_sha1(uint8_t digest[static SHA1_DIGEST_LENGTH], uint8_t const *in, size_t inlen, uint8_t const *key, size_t key_len)
Calculate HMAC using internal SHA1 implementation.
Definition hmac_sha1.c:124
HIDDEN fr_dict_attr_t const * attr_ms_mppe_send_key
Definition base.c:101
HIDDEN fr_dict_attr_t const * attr_ms_mppe_recv_key
Definition base.c:102
HIDDEN fr_dict_attr_t const * attr_freeradius_proxied_to
Definition base.c:100
HIDDEN fr_dict_attr_t const * attr_eap_msk
Definition base.c:97
HIDDEN fr_dict_attr_t const * attr_eap_emsk
Definition base.c:98
HIDDEN fr_dict_attr_t const * attr_eap_message
Definition base.c:96
HIDDEN fr_dict_attr_t const * attr_eap_type
Definition base.c:92
unlang_action_t eap_virtual_server(request_t *request, eap_session_t *eap_session, CONF_SECTION *server_cs)
Run a subrequest through a virtual server.
Definition base.c:427
void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
Definition base.c:387
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Definition session.h:59
Tracks the progress of a single session of any EAP method.
Definition session.h:40
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.
Definition log.c:830
#define RWDEBUG2(fmt,...)
Definition log.h:362
#define RERROR(fmt,...)
Definition log.h:298
#define RHEXDUMP3(_data, _len, _fmt,...)
Definition log.h:705
talloc_free(reap)
@ L_DBG_LVL_1
Highest priority debug messages (-x).
Definition log.h:70
void fr_packet_free(fr_packet_t **packet_p)
Free a fr_packet_t.
Definition packet.c:89
#define MD5_DIGEST_LENGTH
unsigned short uint16_t
@ FR_TYPE_TLV
Contains nested attributes.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
unsigned long int size_t
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition nbo.h:146
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.
Definition pair.c:2406
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.
Definition pair.c:2981
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.
Definition pair.c:693
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1345
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.
Definition pair.c:283
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
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.
Definition pair.c:2784
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
Definition pair.c:489
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, bool tainted)
Convert string value to native attribute value.
Definition pair.c:2589
int fr_pair_raw_afrom_pair(fr_pair_t *vp, uint8_t const *data, size_t data_len)
Mark malformed attribute as raw.
Definition pair.c:593
int fr_pair_prepend_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and prepend)
Definition pair.c:1493
fr_pair_t * fr_pair_afrom_child_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
Create a new valuepair.
Definition pair.c:371
#define fr_assert(_expr)
Definition rad_assert.h:38
static fr_dict_attr_t const * attr_ms_chap_challenge
static fr_dict_attr_t const * attr_user_name
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG2(fmt,...)
Definition radclient.h:54
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition rcode.h:45
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:43
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:41
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:44
#define request_alloc_internal(_ctx, _args)
Allocate a new internal request.
Definition request.h:305
Optional arguments for initialising requests.
Definition request.h:254
#define request_data_add(_request, _unique_ptr, _unique_int, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
static const void * fake
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
static int64_t fr_time_to_sec(fr_time_t when)
Convert an fr_time_t (internal time) to number of sec since the unix epoch (wallclock time)
Definition time.h:731
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
Definition time.h:154
#define fr_time_delta_wrap(_time)
Definition time.h:152
#define fr_time_wrap(_time)
Definition time.h:145
#define fr_time_lteq(_a, _b)
Definition time.h:240
#define fr_time_eq(_a, _b)
Definition time.h:241
#define fr_time_add(_a, _b)
Add a time/time delta together.
Definition time.h:196
#define fr_time_max()
Definition time.h:143
"server local" time.
Definition time.h:69
unsigned int code
Packet code (type).
Definition packet.h:61
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
Definition pair.h:628
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.
Definition pair_inline.c:70
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.
Definition pair_inline.c:43
static fr_slen_t parent
Definition pair.h:851
int fr_tls_utils_keyblock_size_get(request_t *request, SSL *ssl)
Returns the OpenSSL keyblock size.
Definition utils.c:80
ssize_t fr_value_box_from_network(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, fr_dbuff_t *dbuff, size_t len, bool tainted)
Decode a fr_value_box_t from serialized binary data.
Definition value.c:1754
static fr_slen_t data
Definition value.h:1265
int nonnull(2, 5))
static size_t char ** out
Definition value.h:997