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