The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
tls.c
Go to the documentation of this file.
1 /*
2  * This program is 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: 1d71573a9a6f8e91f2f58efa8cdfdfe0042828c1 $
19  * @file lib/eap/tls.c
20  * @brief Implements the EAP part of EAP-TLS
21  *
22  * RFC 2716 Section 4.2. PPP EAP TLS Request Packet
23  @verbatim
24  0 1 2 3
25  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
26  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27  | Code | Identifier | Length |
28  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29  | Type | Flags | TLS Message Length
30  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31  | TLS Message Length | TLS Data...
32  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33  @endverbatim
34  *
35  * Structure of an EAP-TLS packet
36  *
37  @verbatim
38  code = EAP-code
39  id = EAP-id
40  length = code + id + length + flags + tlsdata
41  = 1 + 1 + 2 + 1 + X
42  length = EAP-length - 1(EAP-Type = 1 octet)
43  flags = EAP-typedata[0] (1 octet)
44  data_len = EAP-typedata[1-4] (4 octets), if L flag set
45  = length - 5(code+id+length+flags), otherwise
46  data = EAP-typedata[5-n], if L flag set
47  = EAP-typedata[1-n], otherwise
48  packet = EAP-typedata (complete typedata)
49  @endverbatim
50  *
51  * The S flag is set only within the EAP-TLS start message sent from the EAP
52  * server to the peer.
53  *
54  * Similarly, when the EAP server receives an EAP-Response with the M bit set,
55  * it MUST respond with an EAP-Request with EAP-Type = EAP-TLS and no data.
56  * This serves as a fragment ACK. The EAP peer MUST wait.
57  *
58  * The Length field is two octets and indicates the length of the EAP
59  * packet including the Code, Identifier, Length, Type, and TLS data
60  * fields.
61  *
62  * The TLS Message Length field is four octets and indicates the
63  * complete reassembled length of the TLS record fragment.
64  *
65  * @copyright 2001 hereUare Communications, Inc. (raghud@hereuare.com)
66  * @copyright 2003 Alan DeKok (aland@freeradius.org)
67  * @copyright 2006,2015 The FreeRADIUS server project
68  * @copyright 2015 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
69  */
70 
71 RCSID("$Id: 1d71573a9a6f8e91f2f58efa8cdfdfe0042828c1 $")
72 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
73 
74 #include <freeradius-devel/unlang/function.h>
75 #include "tls.h"
76 #include "attrs.h"
77 
79  { L("invalid"), EAP_TLS_INVALID },
80  { L("established"), EAP_TLS_ESTABLISHED },
81  { L("fail"), EAP_TLS_FAIL },
82  { L("handled"), EAP_TLS_HANDLED },
83 
84  { L("start"), EAP_TLS_START_SEND },
85  { L("request"), EAP_TLS_RECORD_SEND },
86  { L("ack"), EAP_TLS_ACK_SEND },
87 
88  { L("first"), EAP_TLS_RECORD_RECV_FIRST },
89  { L("more"), EAP_TLS_RECORD_RECV_MORE },
90  { L("complete"), EAP_TLS_RECORD_RECV_COMPLETE }
91 };
93 
94 /** Convert the EAP-TLS reply packet into an EAP packet
95  *
96  * The EAP packet will be written to eap_round->request, with the original reply
97  * being untouched.
98  *
99  * @param[in] request The current subrequest.
100  * @param[in] eap_session to continue.
101  * @param[in] status What type of packet we're sending.
102  * @param[in] flags to set. This is checked to determine if
103  * we need to include a length field.
104  * @param[in] record The record buffer to read from. This
105  * most only be set for EAP_TLS_RECORD_SEND packets.
106  * @param[in] record_len the length of the record we're sending.
107  * @param[in] frag_len the length of the fragment we're sending.
108  * @return
109  * - 0 on success.
110  * - -1 on failure.
111  */
112 int eap_tls_compose(request_t *request, eap_session_t *eap_session, eap_tls_status_t status, uint8_t flags,
113  fr_tls_record_t *record, size_t record_len, size_t frag_len)
114 {
115  eap_round_t *eap_round = eap_session->this_round;
116  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
117  fr_tls_session_t *tls_session = eap_tls_session->tls_session;
118  uint8_t *p;
119  size_t len = 1; /* Flags */
120 
121  fr_assert(request->parent); /* must be a subrequest */
122 
123  /*
124  * First output the flags (for debugging)
125  */
126  RDEBUG3("Setting flags %c%c%c%c%c%c%c%c",
127  TLS_START(flags) ? 'S' : '-',
128  TLS_MORE_FRAGMENTS(flags) ? 'M' : '-',
129  TLS_LENGTH_INCLUDED(flags) ? 'L' : '-',
130  TLS_RESERVED0(flags) ? 'R' : '-',
131  TLS_RESERVED1(flags) ? 'R' : '-',
132  TLS_RESERVED2(flags) ? 'R' : '-',
133  TLS_RESERVED3(flags) ? 'R' : '-',
134  TLS_RESERVED4(flags) ? 'R' : '-');
135 
136  /*
137  * Determine the length (sans header) of our EAP-TLS
138  * packet. The reason for not including the length is
139  * that the fields are the same as normal EAP messages.
140  */
141  switch (status) {
142  case EAP_TLS_RECORD_SEND:
143  if (TLS_LENGTH_INCLUDED(flags)) len += TLS_HEADER_LENGTH_FIELD_LEN; /* TLS record length field */
144  if (record) len += frag_len;
145  break;
146 
147  case EAP_TLS_START_SEND:
148  if (record_len != 0) len += frag_len;
149  break;
150 
151  default:
152  break;
153  }
154 
155  /*
156  * When the EAP server receives an EAP-Response with the
157  * M bit set, it MUST respond with an EAP-Request with
158  * EAP-Type = EAP-TLS and no data. This serves as a
159  * fragment ACK. The EAP peer MUST wait until it receives
160  * the EAP-Request before sending another fragment.
161  *
162  * In order to prevent errors in the processing of
163  * fragments, the EAP server MUST use increment the
164  * Identifier value for each fragment ACK contained
165  * within an EAP-Request, and the peer MUST include this
166  * Identifier value in the subsequent fragment contained
167  * within an EAP-Reponse.
168  */
169  eap_round->request->type.data = p = talloc_array(eap_round->request, uint8_t, len);
170  if (!p) return -1;
171  eap_round->request->type.length = len;
172 
173  *p++ = flags;
174 
175  if (TLS_LENGTH_INCLUDED(flags)) {
176  uint32_t net_record_len;
177 
178  /*
179  * If we need to add the length field,
180  * convert the total record length to
181  * network byte order and copy it in at the
182  * start of the packet.
183  */
184  net_record_len = htonl(record_len);
185  memcpy(p, &net_record_len, sizeof(net_record_len));
186  p += sizeof(net_record_len);
187  }
188 
189  if (record) tls_session->record_to_buff(record, p, frag_len);
190 
191  switch (status) {
192  case EAP_TLS_ACK_SEND:
193  case EAP_TLS_START_SEND:
194  case EAP_TLS_RECORD_SEND:
195  eap_round->request->code = FR_EAP_CODE_REQUEST;
196  break;
197 
198  case EAP_TLS_ESTABLISHED:
199  eap_round->request->code = FR_EAP_CODE_SUCCESS;
200  break;
201 
202  case EAP_TLS_FAIL:
203  eap_round->request->code = FR_EAP_CODE_FAILURE;
204  break;
205 
206  default:
207  /* Should never enter here */
208  fr_assert(0);
209  break;
210  }
211 
212  return 0;
213 }
214 
215 /** Send an initial EAP-TLS request to the peer.
216  *
217  * Once having received the peer's Identity, the EAP server MUST respond with an
218  * EAP-TLS/Start packet, which is an EAP-Request packet with EAP-Type = EAP-TLS,
219  * the Start (S) bit set, and no data.
220  *
221  * The EAP-TLS conversation will then begin, with the peer sending an EAP-Response
222  * packet with EAP-Type = EAP-TLS. The data field of that packet will be the TLS data.
223  *
224  * The S flag is set only within the EAP-TLS start message sent from the EAP server to the peer.
225  *
226  * - len = header + type + tls_typedata
227  * - tls_typedata = flags(Start (S) bit set, and no data)
228  *
229  * Fragment length is Framed-MTU - 4.
230  *
231  * @param[in] request The current subrequest.
232  * @param[in] eap_session to initiate.
233  * @return
234  * - 0 on success.
235  * - -1 on failure.
236  */
237 int eap_tls_start(request_t *request, eap_session_t *eap_session)
238 {
239  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
240 
241  fr_assert(request->parent); /* must be a subrequest */
242 
243  return eap_tls_compose(request, eap_session, EAP_TLS_START_SEND,
244  SET_START(eap_tls_session->base_flags), NULL, 0, 0);
245 }
246 
247 /** Send an EAP-TLS success
248  *
249  * Composes an EAP-TLS-Success. This is a message with code EAP_TLS_ESTABLISHED.
250  * It contains no cryptographic material, and is not protected.
251  *
252  * We add the MPPE keys here. These are used by the NAS. The supplicant
253  * will derive the same keys separately.
254  *
255  * @param[in] request The current subrequest.
256  * @param[in] eap_session that completed successfully.
257  * @param[in] prf_label PRF label struct
258  * @return
259  * - 0 on success.
260  * - -1 on failure.
261  */
262 int eap_tls_success(request_t *request, eap_session_t *eap_session, eap_tls_prf_label_t *prf_label)
263 {
264  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
265  fr_tls_session_t *tls_session = eap_tls_session->tls_session;
266 
267  fr_assert(request->parent); /* must be a subrequest */
268 
269  eap_session->finished = true;
270 
271  /*
272  * Build the success packet
273  */
274  if (eap_tls_compose(request, eap_session, EAP_TLS_ESTABLISHED,
275  eap_tls_session->base_flags, NULL, 0, 0) < 0) return -1;
276 
277  if (!prf_label) return 0;
278 
279  /*
280  * Automatically generate MPPE keying material.
281  */
282  if (eap_crypto_mppe_keys(request->parent, tls_session->ssl, prf_label) < 0) return -1;
283 
284  /*
285  * Add the EAP session ID to the request
286  */
287  {
288  uint8_t *session_id;
289  fr_pair_t *vp;
290 
292  if (eap_crypto_tls_session_id(vp, request, tls_session->ssl, prf_label,
293  &session_id, eap_session->type) < 0) {
295  return -1;
296  }
297  fr_pair_value_memdup_buffer_shallow(vp, session_id, false);
298 
299  RINDENT();
300  RDEBUG2("&reply.%pP", vp);
301  REXDENT();
302  }
303 
304  return 0;
305 }
306 
307 /** Send an EAP-TLS failure
308  *
309  * Composes an EAP-TLS-Failure. This is a message with code EAP_TLS_FAILURE.
310  * It contains no cryptographic material, and is not protected.
311  *
312  * In addition to sending the failure, will destroy any cached session data.
313  *
314  * @param[in] request The current subrequest.
315  * @param[in] eap_session that failed.
316  * @return
317  * - 0 on success.
318  * - -1 on failure (to compose a valid packet).
319  */
320 int eap_tls_fail(request_t *request, eap_session_t *eap_session)
321 {
322  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
323  fr_tls_session_t *tls_session = eap_tls_session->tls_session;
324 
325  fr_assert(request->parent); /* must be a subrequest */
326 
327  eap_session->finished = true;
328 
329  /*
330  * Destroy any cached session data
331  */
332  fr_tls_cache_deny(request, tls_session);
333 
334  if (eap_tls_compose(request, eap_session, EAP_TLS_FAIL,
335  eap_tls_session->base_flags, NULL, 0, 0) < 0) return -1;
336  return 0;
337 }
338 
339 /** Frames the OpenSSL data that needs to be sent to the client in an EAP-Request
340  *
341  * A single TLS record may be up to 16384 octets in length, but a TLS message
342  * may span multiple TLS records, and a TLS certificate message may theoretically,
343  * be as big as 16MB.
344  *
345  * In EAP-TLS with no inner method, this is used primarily to send our certificate
346  * chain to the peer.
347  *
348  * In other methods this function is also called to package up application data
349  * for the inner tunnel method.
350  *
351  * The eap_tls_session->length_included flag determines whether we include the extra
352  * four byte length field in the request and set the L flag.
353  *
354  * If present, the tls_length field indicates the total length of the reassembled
355  * TLS record.
356  *
357  * If eap_tls_session->length_included this means we include L flag and the tls_length
358  * field in EVERY packet we send out.
359  *
360  * If !eap_tls_session->length_included this means we include L flag and tls_length
361  * field **ONLY** in First packet of a fragment series. We do not use it anywhere
362  * else.
363  *
364  * @param request the request
365  * @param eap_session that's continuing.
366  * @return
367  * - 0 on success.
368  * - -1 on failure.
369  */
370 int eap_tls_request(request_t *request, eap_session_t *eap_session)
371 {
372  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
373  fr_tls_session_t *tls_session = eap_tls_session->tls_session;
374  uint8_t flags = eap_tls_session->base_flags;
375  size_t frag_len;
376  bool length_included;
377 
378  /*
379  * We don't need to always include the length
380  * (just in the first fragment) but it is
381  * configurable for compatibility.
382  */
383  length_included = eap_tls_session->include_length;
384 
385  /*
386  * If this is the first fragment, record the complete
387  * TLS record length.
388  */
389  if (eap_tls_session->record_out_started == false) {
390  eap_tls_session->record_out_total_len = tls_session->dirty_out.used;
391  }
392 
393  /*
394  * If the data we're sending is greater than the MTU
395  * then we need to fragment it.
396  */
397  if ((tls_session->dirty_out.used +
398  (length_included ? TLS_HEADER_LENGTH_FIELD_LEN : 0)) > tls_session->mtu) {
399  if (eap_tls_session->record_out_started == false) length_included = true;
400 
401  frag_len = length_included ? tls_session->mtu - TLS_HEADER_LENGTH_FIELD_LEN:
402  tls_session->mtu;
403 
404  flags = SET_MORE_FRAGMENTS(flags);
405 
406  /*
407  * Length MUST be included if we're record_out_started
408  * and this is the first fragment.
409  */
410  if (eap_tls_session->record_out_started == false) {
411  RDEBUG2("Complete TLS record (%zu bytes) larger than MTU (%zu bytes), will fragment",
412  eap_tls_session->record_out_total_len, frag_len); /* frag_len is correct here */
413  RDEBUG2("Sending first TLS record fragment (%zu bytes), %zu bytes remaining",
414  frag_len, tls_session->dirty_out.used - frag_len);
415  } else {
416  RDEBUG2("Sending additional TLS record fragment (%zu bytes), %zu bytes remaining",
417  frag_len, tls_session->dirty_out.used - frag_len);
418  }
419  eap_tls_session->record_out_started = true; /* Start a new series of fragments */
420  /*
421  * Otherwise, we're either sending a record smaller
422  * than the MTU or this is the final fragment.
423  */
424  } else {
425  frag_len = tls_session->dirty_out.used; /* Remaining data to drain */
426 
427  if (eap_tls_session->record_out_started == false) {
428  RDEBUG2("Sending complete TLS record (%zu bytes)", frag_len);
429  } else {
430  RDEBUG2("Sending final TLS record fragment (%zu bytes)", frag_len);
431  }
432  eap_tls_session->record_out_started = false;
433  }
434 
435  /*
436  * Update the flags to say we're including the
437  * TLS record length.
438  */
439  if (length_included) flags = SET_LENGTH_INCLUDED(flags);
440 
441  return eap_tls_compose(request, eap_session, EAP_TLS_RECORD_SEND, flags,
442  &tls_session->dirty_out, eap_tls_session->record_out_total_len, frag_len);
443 }
444 
445 /** ACK a fragment of the TLS record from the peer
446  *
447  * EAP server sends an ACK when it determines there are More fragments to
448  * receive to make the complete TLS-record.
449  *
450  * When the EAP server receives an EAP-Response with the M bit set, it MUST
451  * respond with an EAP-Request with EAP-Type = EAP-TLS and no data. This serves
452  * as a fragment ACK.
453  *
454  * In order to prevent errors in the processing of fragments, the EAP server
455  * MUST use increment the Identifier value for each fragment ACK contained
456  * within an EAP-Request, and the peer MUST include this Identifier value in
457  * the subsequent fragment contained within an EAP-Reponse.
458  *
459  * @param[in] request The current subrequest.
460  * @param[in] eap_session that we're acking the fragment for.
461  */
462 static int eap_tls_ack(request_t *request, eap_session_t *eap_session)
463 {
464  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
465 
466  fr_assert(request->parent); /* must be a subrequest */
467 
468  RDEBUG2("ACKing Peer's TLS record fragment");
469  return eap_tls_compose(request, eap_session, EAP_TLS_ACK_SEND,
470  eap_tls_session->base_flags, NULL, 0, 0);
471 }
472 
473 /** Reduce session states down into an easy to use status
474  *
475  * @param[in] request The current subrequest.
476  * @param[in] eap_session that we're acking the fragment for.
477  * @return
478  * - EAP_TLS_ESTABLISHED - Handshake completed.
479  * - EAP_TLS_FAIL - Fatal alert from the client.
480  * - EAP_TLS_RECORD_SEND - Need more data, or previous fragment was acked.
481  */
483 {
484  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
485  fr_tls_session_t *tls_session = eap_tls_session->tls_session;
486 
487  if (tls_session == NULL){
488  REDEBUG("Unexpected ACK received: No ongoing SSL tls_session");
489  return EAP_TLS_INVALID;
490  }
491  if (!tls_session->info.initialized) {
492  RDEBUG2("No SSL info available. Waiting for more SSL data");
493  return EAP_TLS_RECORD_SEND;
494  }
495 
496  if ((tls_session->info.content_type == SSL3_RT_HANDSHAKE) && (tls_session->info.origin == 0)) {
497  REDEBUG("Unexpected ACK received: We sent no previous messages");
498  return EAP_TLS_INVALID;
499  }
500 
501  switch (tls_session->info.content_type) {
502  case SSL3_RT_ALERT:
503  RDEBUG2("Peer ACKed our alert");
504  return EAP_TLS_FAIL;
505 
506  case SSL3_RT_HANDSHAKE:
507  if (SSL_is_init_finished(tls_session->ssl) && (tls_session->dirty_out.used == 0)) {
508  RDEBUG2("Peer ACKed our handshake fragment. handshake is finished");
509 
510  /*
511  * From now on all the content is
512  * application data set it here as nobody else
513  * sets it.
514  */
515  tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
516  return EAP_TLS_ESTABLISHED;
517  } /* else more data to send */
518 
519  RDEBUG2("Peer ACKed our handshake fragment");
520  /* Fragmentation handler, send next fragment */
521  return EAP_TLS_RECORD_SEND;
522 
523  case SSL3_RT_APPLICATION_DATA:
524  RDEBUG2("Peer ACKed our application data fragment");
525  return EAP_TLS_RECORD_SEND;
526 
527  /*
528  * For the rest of the conditions, switch over
529  * to the default section below.
530  */
531  default:
532  REDEBUG("Invalid ACK received: %d", tls_session->info.content_type);
533  return EAP_TLS_INVALID;
534  }
535 }
536 
537 /** Check that this EAP-TLS packet is correct and the progression of EAP-TLS packets is sane
538  *
539  * @note In the received packet, No data will be present in case of ACK or NAK
540  * in this case the packet->data pointer will be NULL.
541  *
542  * @param[in] request the current subrequest.
543  * @param[in] eap_session the current EAP session state.
544  * @return
545  * - EAP_TLS_INVALID if the TLS record or progression is invalid.
546  * - EAP_TLS_FAIL handshake failed.
547  * - EAP_TLS_RECORD_RECV_FIRST this is the start of a new sequence of record fragments.
548  * - EAP_TLS_RECORD_RECV_MORE this is a continuation of a sequence of fragments.
549  * - EAP_TLS_RECORD_RECV_COMPLETE we received a completed record.
550  * - EAP_TLS_RECORD_SEND send more data to peer.
551  * - EAP_TLS_ESTABLISHED handshake is complete, TLS session has been established.
552  */
554 {
555  eap_round_t *this_round = eap_session->this_round;
556  eap_round_t *prev_round = eap_session->prev_round;
557  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
558 
559  eap_tls_data_t *eap_tls_data;
560  size_t frag_len, header_len;
561 
562  fr_assert(request->parent); /* must be a subrequest */
563 
564  /*
565  * All EAP-TLS packets must contain type and flags fields.
566  */
567  if (this_round->response->length < (EAP_HEADER_LEN + 2)) {
568  REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
569  (size_t)EAP_HEADER_LEN + 2, this_round->response->length);
570  return EAP_TLS_INVALID;
571  }
572 
573  /*
574  * We don't check ANY of the input parameters. It's all
575  * code which works together, so if something is wrong,
576  * we SHOULD core dump.
577  *
578  * e.g. if this_round is NULL, or if this_round->response is
579  * NULL, or if it's NOT an EAP-Response, or if the packet
580  * is too short. See eap_validate()., in ../../eap.c
581  */
582  eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
583  if (!eap_tls_data) {
584  REDEBUG("Invalid EAP-TLS packet; no data");
585  return EAP_TLS_INVALID;
586  }
587 
588  /*
589  * First output the flags (for debugging)
590  */
591  RDEBUG3("Peer sent flags %c%c%c%c%c%c%c%c",
592  TLS_START(eap_tls_data->flags) ? 'S' : '-',
593  TLS_MORE_FRAGMENTS(eap_tls_data->flags) ? 'M' : '-',
594  TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 'L' : '-',
595  TLS_RESERVED0(eap_tls_data->flags) ? 'R' : '-',
596  TLS_RESERVED1(eap_tls_data->flags) ? 'R' : '-',
597  TLS_RESERVED2(eap_tls_data->flags) ? 'R' : '-',
598  TLS_RESERVED3(eap_tls_data->flags) ? 'R' : '-',
599  TLS_RESERVED4(eap_tls_data->flags) ? 'R' : '-');
600 
601  /*
602  * This length includes the type and flags field and
603  * the message length field if the flags indicate it's present.
604  */
605  header_len = EAP_HEADER_LEN + (TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 6 : 2);
606  if (this_round->response->length < header_len) {
607  REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
608  header_len, this_round->response->length);
609  return EAP_TLS_INVALID;
610  }
611 
612  /*
613  * check for ACK
614  *
615  * If there's no TLS data, or there's 1 byte of TLS data,
616  * with the flags set to zero, then it's an ACK.
617  *
618  * Find if this is a reply to the previous request sent
619  */
620  if ((this_round->response->length == EAP_HEADER_LEN + 2) &&
621  ((eap_tls_data->flags & 0xc0) == 0x00)) {
622  if (!prev_round || (prev_round->request->id != this_round->response->id)) {
623  REDEBUG("Received Invalid TLS ACK");
624  return EAP_TLS_INVALID;
625  }
626  return eap_tls_session_status(request, eap_session);
627  }
628 
629  /*
630  * We send TLS_START, but do not receive it.
631  */
632  if (TLS_START(eap_tls_data->flags)) {
633  REDEBUG("Peer sent EAP-TLS Start message (only the server is allowed to do this)");
634  return EAP_TLS_INVALID;
635  }
636 
637  /*
638  * Calculate this fragment's length
639  */
640  frag_len = this_round->response->length - header_len;
641 
642  /*
643  * The L bit (length included) is set to indicate the
644  * presence of the four octet TLS Message Length field,
645  * and MUST be set for the first fragment of a fragmented
646  * TLS message or set of messages.
647  *
648  * The M bit (more fragments) is set on all but the last
649  * fragment.
650  *
651  * The S bit (EAP-TLS start) is set in an EAP-TLS Start
652  * message. This differentiates the EAP-TLS Start message
653  * from a fragment acknowledgement.
654  */
655  if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
656  size_t total_len;
657 
658  total_len = eap_tls_data->data[2] * 256 | eap_tls_data->data[3];
659  if (frag_len > total_len) {
660  REDEBUG("TLS fragment length (%zu bytes) greater than TLS record length (%zu bytes)",
661  frag_len, total_len);
662  return EAP_TLS_INVALID;
663  }
664 
665  if (total_len > FR_TLS_MAX_RECORD_SIZE) {
666  REDEBUG("Reassembled TLS record will be %zu bytes, "
667  "greater than our maximum record size (" STRINGIFY(FR_TLS_MAX_RECORD_SIZE) " bytes)",
668  total_len);
669  return EAP_TLS_INVALID;
670  }
671 
672  /*
673  * wpa_supplicant's implementation of PEAPv0, and likely other
674  * implementations of PEAPv0 will always include a Length flag
675  * for every record fragment if performing mutual TLS auth.
676  *
677  * If the eap_session says this is not the first fragment, then
678  * don't count this as a new record, and continue as if we
679  * hadn't seen the length flag.
680  */
681  if (eap_tls_session->record_in_started) goto ignore_length;
682 
683  /*
684  * This is the first fragment of a fragmented TLS record transfer.
685  */
686  RDEBUG2("Peer indicated complete TLS record size will be %zu bytes", total_len);
687  if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
688  /*
689  * The peer is free to send fragments of wildly varying
690  * lengths, but the vast majority won't.
691  *
692  * In this calculation we take into account the fact that the future
693  * fragments are likely to be 4 bytes larger than the initial one
694  * as they won't contain the length field.
695  */
696  if (frag_len + 4) { /* check for wrap, else clang scan gets excited */
697  RDEBUG2("Expecting %i TLS record fragments",
698  (int)((((total_len - frag_len) + ((frag_len + 4) - 1)) / (frag_len + 4)) + 1));
699  }
700 
701  /*
702  * First fragment. record_in_started bool was false,
703  * and we received a length included + more fragments packet.
704  */
705  RDEBUG2("Got first TLS record fragment (%zu bytes). Peer indicated more fragments "
706  "to follow", frag_len);
707  eap_tls_session->record_in_total_len = total_len;
708  eap_tls_session->record_in_recvd_len = frag_len;
709  eap_tls_session->record_in_started = true;
710 
712  }
713 
714  /*
715  * Else this is the complete TLS record.
716  */
717  if (total_len != frag_len) {
718  REDEBUG("Peer indicated no more fragments, but TLS record length (%zu bytes) "
719  "does not match EAP-TLS data length (%zu bytes)", total_len, frag_len);
720  return EAP_TLS_INVALID;
721  }
722 
723  /*
724  * RFC5216 doesn't specify explicitly whether a non-fragmented
725  * packet should include the length or not.
726  *
727  * We support both options for maximum compatibility.
728  */
729  RDEBUG2("Got complete TLS record, with length field (%zu bytes)", frag_len);
731  }
732 
733 ignore_length:
734  if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
735  /*
736  * If this is not an ongoing transfer, and we have the M flag
737  * then this record transfer is invalid.
738  */
739  if (!eap_tls_session->record_in_started) {
740  REDEBUG("TLS More (M) flag set, but no fragmented record transfer was in progress");
741  return EAP_TLS_INVALID;
742  }
743 
744  /*
745  * If this is an ongoing transfer, and we have the M flag,
746  * then this is just an additional fragment.
747  */
748  RDEBUG2("Got additional TLS record fragment (%zu bytes). Peer indicated more fragments to follow",
749  frag_len);
750  eap_tls_session->record_in_recvd_len += frag_len;
751  if (eap_tls_session->record_in_recvd_len > eap_tls_session->record_in_total_len) {
752  REDEBUG("Total received TLS record fragments (%zu bytes), exceeds "
753  "indicated TLS record length (%zu bytes)",
754  eap_tls_session->record_in_recvd_len, eap_tls_session->record_in_total_len);
755  return EAP_TLS_INVALID;
756  }
758  }
759 
760  /*
761  * No L flag and no M flag. This is either the final fragment,
762  * or a new transfer that was not started with a L flag, which
763  * RFC5216 hints, may be acceptable.
764  *
765  * If it's an in-progress record transfer, check we now have
766  * the complete record.
767  */
768  if (eap_tls_session->record_in_started) {
769  eap_tls_session->record_in_started = false;
770 
771  RDEBUG2("Got final TLS record fragment (%zu bytes)", frag_len);
772  eap_tls_session->record_in_recvd_len += frag_len;
773  if (eap_tls_session->record_in_recvd_len != eap_tls_session->record_in_total_len) {
774  REDEBUG("Total received TLS record fragments (%zu bytes), does not equal indicated "
775  "TLS record length (%zu bytes)",
776  eap_tls_session->record_in_recvd_len, eap_tls_session->record_in_total_len);
777  return EAP_TLS_INVALID;
778  }
780  }
781 
782  /*
783  * None of the flags are set, it wasn't an in progress transfer,
784  * but it's still a valid EAP-TLS packet.
785  */
786  RDEBUG2("Got complete TLS record (%zu bytes)", frag_len);
787 
789 }
790 
791 /** Process the result from the last TLS handshake round
792  *
793  * @return
794  * - eap_tls_session->state = EAP_TLS_FAIL if the message is invalid.
795  * - eap_tls_session->state = EAP_TLS_HANDLED if we need to send an
796  * additional request to the peer.
797  * - eap_tls_session->state = EAP_TLS_ESTABLISHED if the handshake
798  * completed successfully, and there's no more data to send.
799  */
801  request_t *request, void *uctx)
802 {
803  eap_session_t *eap_session = talloc_get_type_abort(uctx, eap_session_t);
804  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
805  fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->tls_session, fr_tls_session_t);
806 
807  switch (tls_session->result) {
808  case FR_TLS_RESULT_IN_PROGRESS:
809  default:
810  fr_assert(0); /* Shouldn't have been called */
811  goto finish;
812 
813  case FR_TLS_RESULT_ERROR:
814  REDEBUG("TLS receive handshake failed during operation");
815  fr_tls_cache_deny(request, tls_session);
816  eap_tls_session->state = EAP_TLS_FAIL;
817  goto finish;
818 
819  case FR_TLS_RESULT_SUCCESS:
820  break;
821  }
822 
823 #ifdef TLS1_3_VERSION
824  /*
825  * https://tools.ietf.org/html/draft-ietf-emu-eap-tls13#section-2.5
826  *
827  * We need to signal the other end that TLS negotiation
828  * is done. We can't send a zero-length application data
829  * message, so we send application data which is one byte
830  * of zero.
831  *
832  * Note this is only done for when there is no application
833  * data to be sent. So this is done always for EAP-TLS but
834  * notibly not for PEAP even on resumption.
835  *
836  * We only want to send this application data IF:
837  *
838  * * EAP-TLS / TTLS / PEAP - session was resumed
839  * * EAP-TLS
840  * * SSL init is finished (presumed to be checked elsewhere)
841  * * we saw the client cert
842  * * OR we're using unauthenticated EAP-TLS where
843  * the administrator has decided to not ask for
844  * the client cert
845  */
846  if ((tls_session->info.version == TLS1_3_VERSION) &&
847  (tls_session->client_cert_ok || eap_tls_session->authentication_success || SSL_session_reused(tls_session->ssl))) {
848  if ((eap_session->type == FR_EAP_METHOD_TLS) || SSL_session_reused(tls_session->ssl)) {
849  eap_tls_session->authentication_success = true;
850 
851  RDEBUG("(TLS) EAP Sending final Commitment Message.");
852  tls_session->record_from_buff(&tls_session->clean_in, "\0", 1);
853  }
854 
855  /*
856  * Always returns UNLANG_ACTION_CALCULATE_RESULT
857  */
858  (void) fr_tls_session_async_handshake_push(request, tls_session);
859  if (tls_session->result != FR_TLS_RESULT_SUCCESS) {
860  REDEBUG("TLS receive handshake failed during operation");
861  fr_tls_cache_deny(request, tls_session);
862  eap_tls_session->state = EAP_TLS_FAIL;
864  }
865  }
866 #endif
867 
868  /*
869  * FIXME: return success/fail.
870  *
871  * TLS proper can decide what to do, then.
872  */
873  if (tls_session->dirty_out.used > 0) {
874  eap_tls_request(request, eap_session);
875  eap_tls_session->state = EAP_TLS_HANDLED;
876  goto finish;
877  }
878 
879  /*
880  * If there is no data to send i.e dirty_out.used <=0 and
881  * if the SSL handshake is finished, then return
882  * EAP_TLS_ESTABLISHED.
883  *
884  * For EAP-TLS this translates to an EAP-Success, for others
885  * this begins phase2.
886  */
887  if (eap_tls_session->phase2 || SSL_is_init_finished(tls_session->ssl)) {
888  eap_tls_session->phase2 = true;
889 
890  /*
891  * Init is finished. The rest is
892  * application data.
893  */
894  tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
895  eap_tls_session->state = EAP_TLS_ESTABLISHED;
896  goto finish;
897  }
898 
899  /*
900  * Who knows what happened...
901  */
902  REDEBUG("TLS failed during operation");
903  eap_tls_session->state = EAP_TLS_FAIL;
904 
905 finish:
907 }
908 
909 /** Push functions to continue the handshake asynchronously
910  *
911  * @param[in] request the current subrequest.
912  * @param[in] eap_session to continue.
913  * @return
914  * - UNLANG_ACTION_PUSHED_CHILD
915  */
916 static inline CC_HINT(always_inline) unlang_action_t eap_tls_handshake_push(request_t *request, eap_session_t *eap_session)
917 {
918  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
919  fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->tls_session, fr_tls_session_t);
920 
921  /*
922  * Will run after the handshake round completes
923  */
924  if (unlang_function_push(request,
925  NULL,
927  NULL, 0, UNLANG_SUB_FRAME, eap_session) < 0) return UNLANG_ACTION_FAIL;
928 
929  if (fr_tls_session_async_handshake_push(request, tls_session) < 0) return UNLANG_ACTION_FAIL;
930 
932 }
933 
934 /** Process an EAP TLS request
935  *
936  * Here we implement a basic state machine. The state machine is implicit and
937  * is driven by the state of the TLS session and the flags sent.
938  * INCOMING DATA:
939  * 1. EAP-TLS should get the complete TLS data from the peer.
940  * 2. Store that data in a data structure with any other required info
941  * 3. Hand this data structure to the TLS module.
942  * 4. TLS module will perform its operations on the data and hands back to EAP-TLS
943  * OUTGOING DATA:
944  * 1. EAP-TLS if necessary will fragment it and send it to the destination.
945  *
946  * During EAP-TLS initialization, TLS Context object will be initialised and stored.
947  * For every new authentication request, TLS will open a new session object and that
948  * session object SHOULD be maintained even after the session is completed, for session
949  * resumption.
950  *
951  * @param request the request
952  * @param eap_session to continue.
953  * @return
954  * - EAP_TLS_ESTABLISHED
955  * - EAP_TLS_HANDLED
956  */
958 {
959  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
960  fr_tls_session_t *tls_session = eap_tls_session->tls_session;
961 
962  eap_round_t *this_round = eap_session->this_round;
963 
964  eap_tls_data_t *eap_tls_data;
965  uint8_t *data;
966  size_t data_len;
967 
968  fr_assert(request->parent); /* must be a subrequest */
969 
970  RDEBUG2("Continuing EAP-TLS");
971 
972  /*
973  * Call eap_tls_verify to sanity check the incoming EAP data.
974  */
975  eap_tls_session->state = eap_tls_verify(request, eap_session);
976  switch (eap_tls_session->state) {
977  case EAP_TLS_INVALID:
978  case EAP_TLS_FAIL:
979  REDEBUG("[eap-tls verify] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
980  break;
981 
982  default:
983  RDEBUG2("[eap-tls verify] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
984  break;
985  }
986 
987  /*
988  * Status in this here means 'state'. Our state is determined passively
989  * for EAP-TLS, based on what state OpenSSL reported the TLS session
990  * to be in, and what flags were last received from the peer.
991  */
992  switch (eap_tls_session->state) {
993  /*
994  * We've received a complete TLS record, this is the same as receiving a
995  * fragment, except we also process the complete record.
996  */
998  /*
999  * We've received a fragment of a TLS record
1000  *
1001  * Determine where the TLS record starts.
1002  *
1003  * If the length included flag is set, we need to skip over the 4 byte
1004  * message length field.
1005  *
1006  * Next - Copy the fragment data into OpenSSL's dirty in buffer so that it
1007  * can process it in a later call.
1008  */
1011  eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
1012  if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
1013  data = (this_round->response->type.data + 5); /* flags + TLS-Length */
1014  data_len = this_round->response->type.length - 5; /* flags + TLS-Length */
1015  } else {
1016  data = this_round->response->type.data + 1; /* flags */
1017  data_len = this_round->response->type.length - 1; /* flags */
1018  }
1019 
1020  /*
1021  * Update the dirty_in buffer (data for reading by OpenSSL)
1022  *
1023  * This buffer will contain partial data when M bit is set, and should
1024  * should only be reinitialized when M bit is not set.
1025  */
1026  if ((tls_session->record_from_buff)(&tls_session->dirty_in, data, data_len) != data_len) {
1027  REDEBUG("Exceeded maximum record size");
1028  eap_tls_session->state = EAP_TLS_FAIL;
1029  goto done;
1030  }
1031 
1032  /*
1033  * ACK fragments until we get a complete TLS record.
1034  */
1035  if (eap_tls_session->state != EAP_TLS_RECORD_RECV_COMPLETE) {
1036  eap_tls_ack(request, eap_session);
1037  eap_tls_session->state = EAP_TLS_HANDLED;
1038  goto done;
1039  }
1040 
1041  /*
1042  * We have a complete record. If the handshake is finished
1043  * process it as application data, otherwise continue
1044  * the handshake.
1045  */
1046  if (eap_tls_session->phase2 || SSL_is_init_finished(tls_session->ssl)) {
1047  int ret;
1048 
1049  eap_tls_session->phase2 = true;
1050 
1051  ret = fr_tls_session_recv(request, tls_session);
1052  switch (ret) {
1053  case 0:
1054  eap_tls_session->state = EAP_TLS_RECORD_RECV_COMPLETE;
1055  break;
1056 
1057  case 1:
1058  eap_tls_session->state = EAP_TLS_RECORD_RECV_MORE;
1059  break;
1060 
1061  default:
1062  eap_tls_session->state = EAP_TLS_FAIL;
1063  break;
1064  }
1065  } else {
1066  /*
1067  * Asynchronously process more handshake data
1068  */
1069  return eap_tls_handshake_push(request, eap_session);
1070  }
1071  break;
1072  /*
1073  * We have fragments or records to send to the peer
1074  */
1075  case EAP_TLS_RECORD_SEND:
1076  /*
1077  * Return a "yes we're done" if there's no more data to send,
1078  * and we've just managed to finish the SSL session initialization.
1079  */
1080  if (!eap_tls_session->phase2 && (tls_session->dirty_out.used == 0) &&
1081  SSL_is_init_finished(tls_session->ssl)) {
1082  eap_tls_session->phase2 = true;
1083  eap_tls_session->state = EAP_TLS_ESTABLISHED;
1084  goto done;
1085  }
1086 
1087  eap_tls_request(request, eap_session);
1088  eap_tls_session->state = EAP_TLS_HANDLED;
1089  goto done;
1090 
1091  /*
1092  * Bad things happened and we're unable to continue.
1093  */
1094  case EAP_TLS_INVALID:
1095  case EAP_TLS_FAIL:
1096  /*
1097  * Established means that we're done the initial handshake.
1098  *
1099  * For TTLS and PEAP that means begin phase2
1100  */
1101  case EAP_TLS_ESTABLISHED:
1102  default:
1103  goto done;
1104  }
1105 
1106  done:
1107 
1109 }
1110 
1111 /** Create a new fr_tls_session_t associated with an #eap_session_t
1112  *
1113  * Creates a new server fr_tls_session_t and associates it with an #eap_session_t
1114  * adding EAP specific opaque data to the SSL session created during fr_tls_session_t
1115  * initialisation.
1116  *
1117  * @param[in] request The current subrequest.
1118  * @param[in] eap_session to use as a context for the eap_tls_session_t
1119  * @param[in] ssl_ctx to use to configure the fr_tls_session_t.
1120  * @param[in] client_cert Whether we require the peer to prevent a certificate.
1121  * @return
1122  * - A new eap_tls_session on success.
1123  * - NULL on error.
1124  */
1126  SSL_CTX *ssl_ctx, bool client_cert)
1127 {
1128  eap_tls_session_t *eap_tls_session;
1129  fr_tls_session_t *tls_session;
1130  fr_tls_conf_t *conf = fr_tls_ctx_conf(ssl_ctx);
1131 
1132  fr_assert(request->parent); /* must be a subrequest */
1133 
1134  /*
1135  * This EAP session is associated with a TLS session
1136  */
1137  eap_session->tls = true;
1138  MEM(eap_tls_session = talloc_zero(eap_session, eap_tls_session_t));
1139 
1140  /*
1141  * Initial state.
1142  */
1143  eap_tls_session->state = EAP_TLS_START_SEND;
1144 
1145  /*
1146  * As per the RFC...
1147  *
1148  * Broken protocols like PEAPv0 need this set to false.
1149  */
1150  eap_tls_session->include_length = true;
1151 
1152  /*
1153  * Every new session is started only from EAP-TLS-START.
1154  * Before Sending our initial EAP-TLS start open a new
1155  * SSL session.
1156  * Create all the required data structures & store them
1157  * in the SSL session's opaque data so that we can use
1158  * these data structures when we get the response.
1159  */
1160  eap_tls_session->tls_session = tls_session = fr_tls_session_alloc_server(eap_tls_session, ssl_ctx,
1161  request, client_cert);
1162  if (unlikely(!tls_session)) return NULL;
1163 
1164  /*
1165  * Add the EAP-Identity value to the TLS session so
1166  * it's available in all the TLS callbacks.
1167  */
1168  {
1169  fr_pair_t *identity;
1170 
1171  MEM(identity = fr_pair_afrom_da(tls_session, attr_eap_identity));
1172  fr_pair_value_bstrdup_buffer(identity, eap_session->identity, true);
1173  fr_tls_session_extra_pair_add_shallow(tls_session, identity);
1174  }
1175 
1176  /*
1177  * Add the EAP-Type we're running to the subrequest.
1178  */
1179  {
1180  fr_pair_t *type_vp;
1181 
1182  MEM(type_vp = fr_pair_afrom_da(tls_session, attr_eap_type));
1183  type_vp->vp_uint32 = eap_session->type;
1184  fr_tls_session_extra_pair_add_shallow(tls_session, type_vp);
1185  }
1186 
1187  /*
1188  * Associate various bits of opaque data with the session.
1189  */
1190  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_EAP_SESSION, (void *)eap_session);
1191  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)tls_session);
1192  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
1193  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_IDENTITY, (void *)&(eap_session->identity));
1194 
1195  return eap_tls_session;
1196 }
1197 
1198 /** Parse TLS configuration
1199  *
1200  * If the option given by 'attr' is set, we find the config section of that name and use
1201  * that for the TLS configuration. If not, we fall back to compatibility mode and read
1202  * the TLS options from the 'tls' section.
1203  *
1204  * @param cs to derive the configuration from.
1205  * @param attr identifier for common TLS configuration.
1206  * @return
1207  * - NULL on error.
1208  * - A new fr_tls_conf_t on success.
1209  */
1210 fr_tls_conf_t *eap_tls_conf_parse(CONF_SECTION *cs, char const *attr)
1211 {
1212  char const *tls_conf_name;
1213  CONF_PAIR *cp;
1215  CONF_SECTION *tls_cs;
1216  fr_tls_conf_t *tls_conf;
1217 
1219 
1220  cp = cf_pair_find(cs, attr);
1221  if (cp) {
1222  tls_conf_name = cf_pair_value(cp);
1223 
1224  tls_cs = cf_section_find(parent, TLS_CONFIG_SECTION, tls_conf_name);
1225  if (!tls_cs) {
1226  ERROR("Cannot find tls config \"%s\"", tls_conf_name);
1227  return NULL;
1228  }
1229  } else {
1230  /*
1231  * If we can't find the section given by the 'attr', we
1232  * fall-back to looking for the "tls" section, as in
1233  * previous versions.
1234  *
1235  * We don't fall back if the 'attr' is specified, but we can't
1236  * find the section - that is just a config error.
1237  */
1238  INFO("TLS section \"%s\" missing, trying to use legacy configuration", attr);
1239  tls_cs = cf_section_find(parent, "tls", NULL);
1240  }
1241 
1242  if (!tls_cs) return NULL;
1243 
1244  tls_conf = fr_tls_conf_parse_server(tls_cs);
1245  if (!tls_conf) return NULL;
1246 
1247  /*
1248  * The EAP RFC's say 1020, but we're less picky.
1249  */
1250  FR_INTEGER_BOUND_CHECK("fragment_size", tls_conf->fragment_size, >=, 100);
1251  /*
1252  * The maximum size for a RADIUS packet is 4096, but we're
1253  * not just a RADIUS server.
1254  *
1255  * Maximum size for a TLS record is 16K, so little point in
1256  * setting it higher than that.
1257  */
1258  FR_INTEGER_BOUND_CHECK("fragment_size", tls_conf->fragment_size, <=, FR_TLS_MAX_RECORD_SIZE);
1259 
1260  /*
1261  * Account for the EAP header (4), and the EAP-TLS header
1262  * (6), as per Section 4.2 of RFC 2716. What's left is
1263  * the maximum amount of data we read from a TLS buffer.
1264  */
1265  tls_conf->fragment_size -= 10;
1266 
1267  return tls_conf;
1268 }
1269 
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition: action.h:39
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition: action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition: action.h:37
#define USES_APPLE_DEPRECATED_API
Definition: build.h:431
#define RCSID(id)
Definition: build.h:444
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define STRINGIFY(x)
Definition: build.h:195
#define unlikely(_x)
Definition: build.h:378
#define UNUSED
Definition: build.h:313
#define NUM_ELEMENTS(_t)
Definition: build.h:335
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition: cf_parse.h:486
Configuration AVP similar to a fr_pair_t.
Definition: cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition: cf_util.c:970
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition: cf_util.c:1356
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition: cf_util.c:1511
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:649
#define cf_parent(_cf)
Definition: cf_util.h:98
eap_type_data_t type
Definition: compose.h:39
size_t length
Definition: compose.h:38
eap_packet_t * response
Packet we received from the peer.
Definition: compose.h:49
eap_code_t code
Definition: compose.h:36
uint8_t id
Definition: compose.h:37
eap_packet_t * request
Packet we will send to the peer.
Definition: compose.h:50
Contains a pair of request and response packets.
Definition: compose.h:48
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
#define TLS_CONFIG_SECTION
Definition: base.h:40
int eap_crypto_mppe_keys(request_t *request, SSL *ssl, eap_tls_prf_label_t *prf_label)
Generate keys according to RFC 5216 and add to the reply.
Definition: crypto.c:85
int eap_crypto_tls_session_id(TALLOC_CTX *ctx, UNUSED request_t *request, SSL *ssl, eap_tls_prf_label_t *prf_label, uint8_t **out, uint8_t eap_type)
Definition: crypto.c:132
@ FR_EAP_CODE_FAILURE
Definition: types.h:40
@ FR_EAP_CODE_REQUEST
Definition: types.h:37
@ FR_EAP_CODE_SUCCESS
Definition: types.h:39
size_t length
Definition: types.h:111
#define EAP_HEADER_LEN
Definition: types.h:34
uint8_t * data
Definition: types.h:112
@ FR_EAP_METHOD_TLS
Definition: types.h:58
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition: function.h:111
#define UNLANG_SUB_FRAME
Definition: interpret.h:36
HIDDEN fr_dict_attr_t const * attr_eap_identity
Definition: base.c:85
HIDDEN fr_dict_attr_t const * attr_eap_session_id
Definition: base.c:84
HIDDEN fr_dict_attr_t const * attr_eap_type
Definition: base.c:86
char * identity
NAI (User-Name) from EAP-Identity.
Definition: session.h:55
void * opaque
Opaque data used by EAP methods.
Definition: session.h:62
bool tls
Whether EAP method uses TLS.
Definition: session.h:70
eap_type_t type
EAP method number.
Definition: session.h:49
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Definition: session.h:59
eap_round_t * prev_round
Previous response/request pair.
Definition: session.h:57
bool finished
Whether we consider this session complete.
Definition: session.h:71
Tracks the progress of a single session of any EAP method.
Definition: session.h:40
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition: log.h:443
#define RDEBUG3(fmt,...)
Definition: log.h:343
#define RINDENT()
Indent R* messages by one level.
Definition: log.h:430
unsigned int uint32_t
Definition: merged_model.c:33
unsigned char uint8_t
Definition: merged_model.c:30
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_buffer_shallow(fr_pair_t *vp, uint8_t const *src, bool tainted)
Assign a talloced buffer to a "octets" type value pair.
Definition: pair.c:3053
VQP attributes.
static bool done
Definition: radclient.c:80
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#define RDEBUG(fmt,...)
Definition: radclient.h:53
#define INFO(fmt,...)
Definition: radict.c:54
static rs_t * conf
Definition: radsniff.c:53
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
#define pair_delete_reply(_pair_or_da)
Delete a fr_pair_t in the reply list.
Definition: pair.h:181
#define pair_append_reply(_attr, _da)
Allocate and append a fr_pair_t to reply list.
Definition: pair.h:47
if(!subtype_vp) goto fail
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_pair_value_bstrdup_buffer(vp, eap_session->identity, true)
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:253
An element in an arbitrarily ordered array of name to num mappings.
Definition: table.h:53
int eap_tls_success(request_t *request, eap_session_t *eap_session, eap_tls_prf_label_t *prf_label)
Send an EAP-TLS success.
Definition: tls.c:262
static eap_tls_status_t eap_tls_verify(request_t *request, eap_session_t *eap_session)
Check that this EAP-TLS packet is correct and the progression of EAP-TLS packets is sane.
Definition: tls.c:553
static unlang_action_t eap_tls_handshake_push(request_t *request, eap_session_t *eap_session)
Push functions to continue the handshake asynchronously.
Definition: tls.c:916
eap_tls_session_t * eap_tls_session_init(request_t *request, eap_session_t *eap_session, SSL_CTX *ssl_ctx, bool client_cert)
Create a new fr_tls_session_t associated with an eap_session_t.
Definition: tls.c:1125
static int eap_tls_ack(request_t *request, eap_session_t *eap_session)
ACK a fragment of the TLS record from the peer.
Definition: tls.c:462
static unlang_action_t eap_tls_handshake_resume(UNUSED rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Process the result from the last TLS handshake round.
Definition: tls.c:800
int eap_tls_compose(request_t *request, eap_session_t *eap_session, eap_tls_status_t status, uint8_t flags, fr_tls_record_t *record, size_t record_len, size_t frag_len)
Convert the EAP-TLS reply packet into an EAP packet.
Definition: tls.c:112
size_t eap_tls_status_table_len
Definition: tls.c:92
int eap_tls_start(request_t *request, eap_session_t *eap_session)
Send an initial EAP-TLS request to the peer.
Definition: tls.c:237
int eap_tls_request(request_t *request, eap_session_t *eap_session)
Frames the OpenSSL data that needs to be sent to the client in an EAP-Request.
Definition: tls.c:370
int eap_tls_fail(request_t *request, eap_session_t *eap_session)
Send an EAP-TLS failure.
Definition: tls.c:320
USES_APPLE_DEPRECATED_API fr_table_num_ordered_t const eap_tls_status_table[]
Definition: tls.c:78
fr_tls_conf_t * eap_tls_conf_parse(CONF_SECTION *cs, char const *attr)
Parse TLS configuration.
Definition: tls.c:1210
static eap_tls_status_t eap_tls_session_status(request_t *request, eap_session_t *eap_session)
Reduce session states down into an easy to use status.
Definition: tls.c:482
unlang_action_t eap_tls_process(request_t *request, eap_session_t *eap_session)
Process an EAP TLS request.
Definition: tls.c:957
Generic EAP over TLS API.
int base_flags
Some protocols use the reserved bits of the EAP-TLS flags (such as PEAP).
Definition: tls.h:132
eap_tls_status_t state
The state of the EAP-TLS session.
Definition: tls.h:127
bool phase2
Whether we're in phase 2.
Definition: tls.h:136
#define TLS_RESERVED1(x)
Definition: tls.h:76
eap_tls_status_t
Definition: tls.h:90
@ EAP_TLS_RECORD_RECV_FIRST
Received first fragment of a record.
Definition: tls.h:109
@ EAP_TLS_INVALID
Invalid, don't reply.
Definition: tls.h:91
@ EAP_TLS_HANDLED
TLS code has handled it.
Definition: tls.h:94
@ EAP_TLS_RECORD_RECV_MORE
Received additional fragment of a record.
Definition: tls.h:110
@ EAP_TLS_ACK_SEND
Acknowledge receipt of a record or record fragment.
Definition: tls.h:102
@ EAP_TLS_RECORD_SEND
We're sending a record.
Definition: tls.h:101
@ EAP_TLS_RECORD_RECV_COMPLETE
Received final fragment of a record.
Definition: tls.h:111
@ EAP_TLS_START_SEND
We're starting a new TLS session.
Definition: tls.h:100
@ EAP_TLS_FAIL
Fail, send fail.
Definition: tls.h:93
@ EAP_TLS_ESTABLISHED
Session established, send success (or start phase2).
Definition: tls.h:92
#define TLS_MORE_FRAGMENTS(x)
Definition: tls.h:79
fr_tls_session_t * tls_session
TLS session used to authenticate peer or tunnel sensitive data.
Definition: tls.h:129
bool record_in_started
Whether a record transfer from the peer is currently in progress.
Definition: tls.h:147
size_t record_out_total_len
Actual/Total TLS message length we're sending.
Definition: tls.h:145
#define SET_START(x)
Definition: tls.h:86
#define TLS_RESERVED3(x)
Definition: tls.h:74
#define SET_LENGTH_INCLUDED(x)
Definition: tls.h:88
uint8_t flags
Definition: tls.h:115
#define TLS_START(x)
Definition: tls.h:78
size_t record_in_total_len
How long the peer indicated the complete tls record would be.
Definition: tls.h:149
#define TLS_RESERVED0(x)
Definition: tls.h:77
bool record_out_started
for methods with inner auth, if the inner auth succeeded.
Definition: tls.h:143
size_t record_in_recvd_len
How much of the record we've received so far.
Definition: tls.h:151
uint8_t data[1]
Definition: tls.h:116
#define TLS_LENGTH_INCLUDED(x)
Definition: tls.h:80
#define TLS_RESERVED2(x)
Definition: tls.h:75
#define TLS_RESERVED4(x)
Definition: tls.h:73
#define TLS_HEADER_LENGTH_FIELD_LEN
Definition: tls.h:56
#define SET_MORE_FRAGMENTS(x)
Definition: tls.h:87
bool authentication_success
Definition: tls.h:141
bool include_length
A flag to include length in every TLS Data/Alert packet.
Definition: tls.h:138
Tracks the state of an EAP-TLS session.
Definition: tls.h:126
static fr_slen_t parent
Definition: pair.h:844
static fr_slen_t data
Definition: value.h:1259