The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 96376cd812b1e92fa424a1b21d95eb1681626073 $
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  */
27 RCSID("$Id: 96376cd812b1e92fa424a1b21d95eb1681626073 $")
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  */
42 static 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  */
77 static 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 
108 void 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 
119 static void eap_fast_send_error(fr_tls_session_t *tls_session, int error)
120 {
121  uint32_t value;
122  value = htonl(error);
123 
124  eap_fast_tlv_append(tls_session, attr_eap_fast_error, true, sizeof(value), &value);
125 }
126 
127 static 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 
140 static 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 
155 static 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;
159  eap_fast_attr_pac_opaque_plaintext_t opaque_plaintext;
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 
217 static 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 
246 static 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");
280 unexpected:
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;
407  case EAP_FAST_COMPLETE:
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 
449  da = fr_dict_attr_child_by_num(parent, attr);
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  */
477 static rlm_rcode_t CC_HINT(nonnull) process_reply(UNUSED eap_session_t *eap_session,
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 
527  case FR_MSCHAP2_SUCCESS:
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;
577  request_t *fake;
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  */
650  if (t->mode == EAP_FAST_PROVISIONING_ANON) {
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->virtual_server);
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) {
753  case RLM_MODULE_REJECT:
755  break;
756 
757  case RLM_MODULE_HANDLED:
759  break;
760 
761  case RLM_MODULE_OK:
763  break;
764 
765  default:
767  break;
768  }
769  break;
770  }
771 
772  talloc_free(fake);
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)) {
814  if (vp->da == attr_eap_fast_eap_payload) {
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  */
898 fr_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 
1005  t->stage = EAP_FAST_COMPLETE;
1006  FALL_THROUGH;
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:444
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
#define UNUSED
Definition: build.h:313
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:509
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition: dcursor.h:287
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:137
#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:1997
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:2925
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:182
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
Definition: rlm_eap_fast.c:132
HIDDEN fr_dict_attr_t const * attr_eap_fast_nak
Definition: rlm_eap_fast.c:112
#define EAP_FAST_TLV_MANDATORY
Definition: eap_fast.h:42
HIDDEN fr_dict_attr_t const * attr_proxy_to_realm
Definition: rlm_eap_fast.c:99
struct eap_fast_tunnel_t::@149 isk
uint8_t const * a_id
Definition: eap_fast.h:189
#define EAP_FAST_SKS_LEN
Definition: eap_fast.h:38
struct eap_fast_tunnel_t::@150 pac
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
Definition: rlm_eap_fast.c:123
uint8_t client_challenge[MD5_DIGEST_LENGTH]
Definition: eap_fast.h:163
HIDDEN fr_dict_attr_t const * attr_eap_fast_pac_info_tlv
Definition: rlm_eap_fast.c:122
eap_fast_pac_attr_lifetime_t lifetime
Definition: eap_fast.h:130
HIDDEN fr_dict_attr_t const * attr_eap_fast_error
Definition: rlm_eap_fast.c:110
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
Definition: rlm_eap_fast.c:121
#define EAP_FAST_SIMCK_LEN
Definition: eap_fast.h:39
HIDDEN fr_dict_attr_t const * attr_eap_fast_pac_info_pac_lifetime
Definition: rlm_eap_fast.c:120
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
Definition: rlm_eap_fast.c:98
#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
char const * virtual_server
Definition: eap_fast.h:206
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
Definition: rlm_eap_fast.c:111
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
Definition: rlm_eap_fast.c:130
eap_fast_pac_attr_hdr_t hdr
Definition: eap_fast.h:110
eap_fast_attr_pac_opaque_t opaque
Definition: eap_fast.h:139
HIDDEN fr_dict_attr_t const * attr_eap_fast_eap_payload
Definition: rlm_eap_fast.c:109
#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
Definition: rlm_eap_fast.c:108
#define EAP_FAST_ERR_UNEXPECTED_TLV
Definition: eap_fast.h:47
HIDDEN fr_dict_attr_t const * attr_eap_fast_vendor_specific
Definition: rlm_eap_fast.c:133
eap_fast_pac_attr_hdr_t hdr
Definition: eap_fast.h:90
HIDDEN fr_dict_t const * dict_eap_fast
Definition: rlm_eap_fast.c:83
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
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
Definition: rlm_eap_fast.c:129
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
Definition: rlm_eap_fast.c:113
@ 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
Definition: rlm_eap_fast.c:115
#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:94
HIDDEN fr_dict_attr_t const * attr_ms_mppe_recv_key
Definition: base.c:95
HIDDEN fr_dict_attr_t const * attr_freeradius_proxied_to
Definition: base.c:93
HIDDEN fr_dict_attr_t const * attr_eap_msk
Definition: base.c:91
HIDDEN fr_dict_attr_t const * attr_eap_emsk
Definition: base.c:92
HIDDEN fr_dict_attr_t const * attr_eap_message
Definition: base.c:90
HIDDEN fr_dict_attr_t const * attr_eap_type
Definition: base.c:86
rlm_rcode_t eap_virtual_server(UNUSED request_t *request, UNUSED eap_session_t *eap_session, UNUSED char const *virtual_server)
Run a subrequest through a virtual server, managing the eap_session_t of the child.
Definition: base.c:401
void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
Definition: base.c:375
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:821
#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
Definition: merged_model.c:248
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
unsigned long int size_t
Definition: merged_model.c:25
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:137
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:2403
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:688
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:278
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:2978
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:1340
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition: pair.c:46
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:366
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:2781
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
Definition: pair.c:484
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:2586
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:588
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:1488
static fr_dict_attr_t const * attr_ms_chap_challenge
Definition: radclient-ng.c:115
static fr_dict_attr_t const * attr_user_name
Definition: radclient-ng.c:125
#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:304
Optional arguments for initialising requests.
Definition: request.h:253
#define request_data_add(_request, _unique_ptr, _unique_int, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
Definition: request_data.h:59
static const void * fake
Definition: rlm_sql_null.c:30
if(!subtype_vp) goto fail
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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:729
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
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
#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:627
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
Definition: pair_inline.c:125
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.
Definition: pair_inline.c:113
static fr_slen_t parent
Definition: pair.h:844
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:1709
static fr_slen_t data
Definition: value.h:1259
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:984