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: 261c048e06f784e24ea9e6b274e7b412dd3797c7 $
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: 261c048e06f784e24ea9e6b274e7b412dd3797c7 $")
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  /*
535  * If the last message was from us, then the session is established
536  */
537  if (tls_session->info.origin == 1) return EAP_TLS_ESTABLISHED;
538  REDEBUG("Invalid ACK received: %d", tls_session->info.content_type);
539  return EAP_TLS_INVALID;
540  }
541 }
542 
543 /** Check that this EAP-TLS packet is correct and the progression of EAP-TLS packets is sane
544  *
545  * @note In the received packet, No data will be present in case of ACK or NAK
546  * in this case the packet->data pointer will be NULL.
547  *
548  * @param[in] request the current subrequest.
549  * @param[in] eap_session the current EAP session state.
550  * @return
551  * - EAP_TLS_INVALID if the TLS record or progression is invalid.
552  * - EAP_TLS_FAIL handshake failed.
553  * - EAP_TLS_RECORD_RECV_FIRST this is the start of a new sequence of record fragments.
554  * - EAP_TLS_RECORD_RECV_MORE this is a continuation of a sequence of fragments.
555  * - EAP_TLS_RECORD_RECV_COMPLETE we received a completed record.
556  * - EAP_TLS_RECORD_SEND send more data to peer.
557  * - EAP_TLS_ESTABLISHED handshake is complete, TLS session has been established.
558  */
560 {
561  eap_round_t *this_round = eap_session->this_round;
562  eap_round_t *prev_round = eap_session->prev_round;
563  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
564 
565  eap_tls_data_t *eap_tls_data;
566  size_t frag_len, header_len;
567 
568  fr_assert(request->parent); /* must be a subrequest */
569 
570  /*
571  * All EAP-TLS packets must contain type and flags fields.
572  */
573  if (this_round->response->length < (EAP_HEADER_LEN + 2)) {
574  REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
575  (size_t)EAP_HEADER_LEN + 2, this_round->response->length);
576  return EAP_TLS_INVALID;
577  }
578 
579  /*
580  * We don't check ANY of the input parameters. It's all
581  * code which works together, so if something is wrong,
582  * we SHOULD core dump.
583  *
584  * e.g. if this_round is NULL, or if this_round->response is
585  * NULL, or if it's NOT an EAP-Response, or if the packet
586  * is too short. See eap_validate()., in ../../eap.c
587  */
588  eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
589  if (!eap_tls_data) {
590  REDEBUG("Invalid EAP-TLS packet; no data");
591  return EAP_TLS_INVALID;
592  }
593 
594  /*
595  * First output the flags (for debugging)
596  */
597  RDEBUG3("Peer sent flags %c%c%c%c%c%c%c%c",
598  TLS_START(eap_tls_data->flags) ? 'S' : '-',
599  TLS_MORE_FRAGMENTS(eap_tls_data->flags) ? 'M' : '-',
600  TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 'L' : '-',
601  TLS_RESERVED0(eap_tls_data->flags) ? 'R' : '-',
602  TLS_RESERVED1(eap_tls_data->flags) ? 'R' : '-',
603  TLS_RESERVED2(eap_tls_data->flags) ? 'R' : '-',
604  TLS_RESERVED3(eap_tls_data->flags) ? 'R' : '-',
605  TLS_RESERVED4(eap_tls_data->flags) ? 'R' : '-');
606 
607  /*
608  * This length includes the type and flags field and
609  * the message length field if the flags indicate it's present.
610  */
611  header_len = EAP_HEADER_LEN + (TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 6 : 2);
612  if (this_round->response->length < header_len) {
613  REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
614  header_len, this_round->response->length);
615  return EAP_TLS_INVALID;
616  }
617 
618  /*
619  * check for ACK
620  *
621  * If there's no TLS data, or there's 1 byte of TLS data,
622  * with the flags set to zero, then it's an ACK.
623  *
624  * Find if this is a reply to the previous request sent
625  */
626  if ((this_round->response->length == EAP_HEADER_LEN + 2) &&
627  ((eap_tls_data->flags & 0xc0) == 0x00)) {
628  if (!prev_round || (prev_round->request->id != this_round->response->id)) {
629  REDEBUG("Received Invalid TLS ACK");
630  return EAP_TLS_INVALID;
631  }
632  return eap_tls_session_status(request, eap_session);
633  }
634 
635  /*
636  * We send TLS_START, but do not receive it.
637  */
638  if (TLS_START(eap_tls_data->flags)) {
639  REDEBUG("Peer sent EAP-TLS Start message (only the server is allowed to do this)");
640  return EAP_TLS_INVALID;
641  }
642 
643  /*
644  * Calculate this fragment's length
645  */
646  frag_len = this_round->response->length - header_len;
647 
648  /*
649  * The L bit (length included) is set to indicate the
650  * presence of the four octet TLS Message Length field,
651  * and MUST be set for the first fragment of a fragmented
652  * TLS message or set of messages.
653  *
654  * The M bit (more fragments) is set on all but the last
655  * fragment.
656  *
657  * The S bit (EAP-TLS start) is set in an EAP-TLS Start
658  * message. This differentiates the EAP-TLS Start message
659  * from a fragment acknowledgement.
660  */
661  if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
662  size_t total_len;
663 
664  total_len = eap_tls_data->data[2] * 256 | eap_tls_data->data[3];
665  if (frag_len > total_len) {
666  REDEBUG("TLS fragment length (%zu bytes) greater than TLS record length (%zu bytes)",
667  frag_len, total_len);
668  return EAP_TLS_INVALID;
669  }
670 
671  if (total_len > FR_TLS_MAX_RECORD_SIZE) {
672  REDEBUG("Reassembled TLS record will be %zu bytes, "
673  "greater than our maximum record size (" STRINGIFY(FR_TLS_MAX_RECORD_SIZE) " bytes)",
674  total_len);
675  return EAP_TLS_INVALID;
676  }
677 
678  /*
679  * wpa_supplicant's implementation of PEAPv0, and likely other
680  * implementations of PEAPv0 will always include a Length flag
681  * for every record fragment if performing mutual TLS auth.
682  *
683  * If the eap_session says this is not the first fragment, then
684  * don't count this as a new record, and continue as if we
685  * hadn't seen the length flag.
686  */
687  if (eap_tls_session->record_in_started) goto ignore_length;
688 
689  /*
690  * This is the first fragment of a fragmented TLS record transfer.
691  */
692  RDEBUG2("Peer indicated complete TLS record size will be %zu bytes", total_len);
693  if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
694  /*
695  * The peer is free to send fragments of wildly varying
696  * lengths, but the vast majority won't.
697  *
698  * In this calculation we take into account the fact that the future
699  * fragments are likely to be 4 bytes larger than the initial one
700  * as they won't contain the length field.
701  */
702  if (frag_len + 4) { /* check for wrap, else clang scan gets excited */
703  RDEBUG2("Expecting %i TLS record fragments",
704  (int)((((total_len - frag_len) + ((frag_len + 4) - 1)) / (frag_len + 4)) + 1));
705  }
706 
707  /*
708  * First fragment. record_in_started bool was false,
709  * and we received a length included + more fragments packet.
710  */
711  RDEBUG2("Got first TLS record fragment (%zu bytes). Peer indicated more fragments "
712  "to follow", frag_len);
713  eap_tls_session->record_in_total_len = total_len;
714  eap_tls_session->record_in_recvd_len = frag_len;
715  eap_tls_session->record_in_started = true;
716 
718  }
719 
720  /*
721  * Else this is the complete TLS record.
722  */
723  if (total_len != frag_len) {
724  REDEBUG("Peer indicated no more fragments, but TLS record length (%zu bytes) "
725  "does not match EAP-TLS data length (%zu bytes)", total_len, frag_len);
726  return EAP_TLS_INVALID;
727  }
728 
729  /*
730  * RFC5216 doesn't specify explicitly whether a non-fragmented
731  * packet should include the length or not.
732  *
733  * We support both options for maximum compatibility.
734  */
735  RDEBUG2("Got complete TLS record, with length field (%zu bytes)", frag_len);
737  }
738 
739 ignore_length:
740  if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
741  /*
742  * If this is not an ongoing transfer, and we have the M flag
743  * then this record transfer is invalid.
744  */
745  if (!eap_tls_session->record_in_started) {
746  REDEBUG("TLS More (M) flag set, but no fragmented record transfer was in progress");
747  return EAP_TLS_INVALID;
748  }
749 
750  /*
751  * If this is an ongoing transfer, and we have the M flag,
752  * then this is just an additional fragment.
753  */
754  RDEBUG2("Got additional TLS record fragment (%zu bytes). Peer indicated more fragments to follow",
755  frag_len);
756  eap_tls_session->record_in_recvd_len += frag_len;
757  if (eap_tls_session->record_in_recvd_len > eap_tls_session->record_in_total_len) {
758  REDEBUG("Total received TLS record fragments (%zu bytes), exceeds "
759  "indicated TLS record length (%zu bytes)",
760  eap_tls_session->record_in_recvd_len, eap_tls_session->record_in_total_len);
761  return EAP_TLS_INVALID;
762  }
764  }
765 
766  /*
767  * No L flag and no M flag. This is either the final fragment,
768  * or a new transfer that was not started with a L flag, which
769  * RFC5216 hints, may be acceptable.
770  *
771  * If it's an in-progress record transfer, check we now have
772  * the complete record.
773  */
774  if (eap_tls_session->record_in_started) {
775  eap_tls_session->record_in_started = false;
776 
777  RDEBUG2("Got final TLS record fragment (%zu bytes)", frag_len);
778  eap_tls_session->record_in_recvd_len += frag_len;
779  if (eap_tls_session->record_in_recvd_len != eap_tls_session->record_in_total_len) {
780  REDEBUG("Total received TLS record fragments (%zu bytes), does not equal indicated "
781  "TLS record length (%zu bytes)",
782  eap_tls_session->record_in_recvd_len, eap_tls_session->record_in_total_len);
783  return EAP_TLS_INVALID;
784  }
786  }
787 
788  /*
789  * None of the flags are set, it wasn't an in progress transfer,
790  * but it's still a valid EAP-TLS packet.
791  */
792  RDEBUG2("Got complete TLS record (%zu bytes)", frag_len);
793 
795 }
796 
797 /** Process the result from the last TLS handshake round
798  *
799  * @return
800  * - eap_tls_session->state = EAP_TLS_FAIL if the message is invalid.
801  * - eap_tls_session->state = EAP_TLS_HANDLED if we need to send an
802  * additional request to the peer.
803  * - eap_tls_session->state = EAP_TLS_ESTABLISHED if the handshake
804  * completed successfully, and there's no more data to send.
805  */
807  request_t *request, void *uctx)
808 {
809  eap_session_t *eap_session = talloc_get_type_abort(uctx, eap_session_t);
810  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
811  fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->tls_session, fr_tls_session_t);
812 
813  switch (tls_session->result) {
814  case FR_TLS_RESULT_IN_PROGRESS:
815  default:
816  fr_assert(0); /* Shouldn't have been called */
817  goto finish;
818 
819  case FR_TLS_RESULT_ERROR:
820  REDEBUG("TLS receive handshake failed during operation");
821  fr_tls_cache_deny(request, tls_session);
822  eap_tls_session->state = EAP_TLS_FAIL;
823  goto finish;
824 
825  case FR_TLS_RESULT_SUCCESS:
826  break;
827  }
828 
829 #ifdef TLS1_3_VERSION
830  /*
831  * https://tools.ietf.org/html/draft-ietf-emu-eap-tls13#section-2.5
832  *
833  * We need to signal the other end that TLS negotiation
834  * is done. We can't send a zero-length application data
835  * message, so we send application data which is one byte
836  * of zero.
837  *
838  * Note this is only done for when there is no application
839  * data to be sent. So this is done always for EAP-TLS but
840  * notibly not for PEAP even on resumption.
841  *
842  * We only want to send this application data IF:
843  *
844  * * EAP-TLS / TTLS / PEAP - session was resumed
845  * * EAP-TLS
846  * * SSL init is finished (presumed to be checked elsewhere)
847  * * we saw the client cert
848  * * OR we're using unauthenticated EAP-TLS where
849  * the administrator has decided to not ask for
850  * the client cert
851  */
852  if ((tls_session->info.version == TLS1_3_VERSION) &&
853  (tls_session->client_cert_ok || eap_tls_session->authentication_success || SSL_session_reused(tls_session->ssl))) {
854  if ((eap_session->type == FR_EAP_METHOD_TLS) || SSL_session_reused(tls_session->ssl)) {
855  eap_tls_session->authentication_success = true;
856 
857  RDEBUG("(TLS) EAP Sending final Commitment Message.");
858  tls_session->record_from_buff(&tls_session->clean_in, "\0", 1);
859  }
860 
861  /*
862  * Always returns UNLANG_ACTION_CALCULATE_RESULT
863  */
864  (void) fr_tls_session_async_handshake_push(request, tls_session);
865  if (tls_session->result != FR_TLS_RESULT_SUCCESS) {
866  REDEBUG("TLS receive handshake failed during operation");
867  fr_tls_cache_deny(request, tls_session);
868  eap_tls_session->state = EAP_TLS_FAIL;
870  }
871  }
872 #endif
873 
874  /*
875  * FIXME: return success/fail.
876  *
877  * TLS proper can decide what to do, then.
878  */
879  if (tls_session->dirty_out.used > 0) {
880  eap_tls_request(request, eap_session);
881  eap_tls_session->state = EAP_TLS_HANDLED;
882  goto finish;
883  }
884 
885  /*
886  * If there is no data to send i.e dirty_out.used <=0 and
887  * if the SSL handshake is finished, then return
888  * EAP_TLS_ESTABLISHED.
889  *
890  * For EAP-TLS this translates to an EAP-Success, for others
891  * this begins phase2.
892  */
893  if (eap_tls_session->phase2 || SSL_is_init_finished(tls_session->ssl)) {
894  eap_tls_session->phase2 = true;
895 
896  /*
897  * Init is finished. The rest is
898  * application data.
899  */
900  tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
901  eap_tls_session->state = EAP_TLS_ESTABLISHED;
902  goto finish;
903  }
904 
905  /*
906  * Who knows what happened...
907  */
908  REDEBUG("TLS failed during operation");
909  eap_tls_session->state = EAP_TLS_FAIL;
910 
911 finish:
913 }
914 
915 /** Push functions to continue the handshake asynchronously
916  *
917  * @param[in] request the current subrequest.
918  * @param[in] eap_session to continue.
919  * @return
920  * - UNLANG_ACTION_PUSHED_CHILD
921  */
922 static inline CC_HINT(always_inline) unlang_action_t eap_tls_handshake_push(request_t *request, eap_session_t *eap_session)
923 {
924  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
925  fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->tls_session, fr_tls_session_t);
926 
927  /*
928  * Will run after the handshake round completes
929  */
930  if (unlang_function_push(request,
931  NULL,
933  NULL, 0, UNLANG_SUB_FRAME, eap_session) < 0) return UNLANG_ACTION_FAIL;
934 
935  if (fr_tls_session_async_handshake_push(request, tls_session) < 0) return UNLANG_ACTION_FAIL;
936 
938 }
939 
940 /** Process an EAP TLS request
941  *
942  * Here we implement a basic state machine. The state machine is implicit and
943  * is driven by the state of the TLS session and the flags sent.
944  * INCOMING DATA:
945  * 1. EAP-TLS should get the complete TLS data from the peer.
946  * 2. Store that data in a data structure with any other required info
947  * 3. Hand this data structure to the TLS module.
948  * 4. TLS module will perform its operations on the data and hands back to EAP-TLS
949  * OUTGOING DATA:
950  * 1. EAP-TLS if necessary will fragment it and send it to the destination.
951  *
952  * During EAP-TLS initialization, TLS Context object will be initialised and stored.
953  * For every new authentication request, TLS will open a new session object and that
954  * session object SHOULD be maintained even after the session is completed, for session
955  * resumption.
956  *
957  * @param request the request
958  * @param eap_session to continue.
959  * @return
960  * - EAP_TLS_ESTABLISHED
961  * - EAP_TLS_HANDLED
962  */
964 {
965  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
966  fr_tls_session_t *tls_session = eap_tls_session->tls_session;
967 
968  eap_round_t *this_round = eap_session->this_round;
969 
970  eap_tls_data_t *eap_tls_data;
971  uint8_t *data;
972  size_t data_len;
973 
974  fr_assert(request->parent); /* must be a subrequest */
975 
976  RDEBUG2("Continuing EAP-TLS");
977 
978  /*
979  * Call eap_tls_verify to sanity check the incoming EAP data.
980  */
981  eap_tls_session->state = eap_tls_verify(request, eap_session);
982  switch (eap_tls_session->state) {
983  case EAP_TLS_INVALID:
984  case EAP_TLS_FAIL:
985  REDEBUG("[eap-tls verify] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
986  break;
987 
988  default:
989  RDEBUG2("[eap-tls verify] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
990  break;
991  }
992 
993  /*
994  * Status in this here means 'state'. Our state is determined passively
995  * for EAP-TLS, based on what state OpenSSL reported the TLS session
996  * to be in, and what flags were last received from the peer.
997  */
998  switch (eap_tls_session->state) {
999  /*
1000  * We've received a complete TLS record, this is the same as receiving a
1001  * fragment, except we also process the complete record.
1002  */
1004  /*
1005  * We've received a fragment of a TLS record
1006  *
1007  * Determine where the TLS record starts.
1008  *
1009  * If the length included flag is set, we need to skip over the 4 byte
1010  * message length field.
1011  *
1012  * Next - Copy the fragment data into OpenSSL's dirty in buffer so that it
1013  * can process it in a later call.
1014  */
1017  eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
1018  if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
1019  data = (this_round->response->type.data + 5); /* flags + TLS-Length */
1020  data_len = this_round->response->type.length - 5; /* flags + TLS-Length */
1021  } else {
1022  data = this_round->response->type.data + 1; /* flags */
1023  data_len = this_round->response->type.length - 1; /* flags */
1024  }
1025 
1026  /*
1027  * Update the dirty_in buffer (data for reading by OpenSSL)
1028  *
1029  * This buffer will contain partial data when M bit is set, and should
1030  * should only be reinitialized when M bit is not set.
1031  */
1032  if ((tls_session->record_from_buff)(&tls_session->dirty_in, data, data_len) != data_len) {
1033  REDEBUG("Exceeded maximum record size");
1034  eap_tls_session->state = EAP_TLS_FAIL;
1035  goto done;
1036  }
1037 
1038  /*
1039  * ACK fragments until we get a complete TLS record.
1040  */
1041  if (eap_tls_session->state != EAP_TLS_RECORD_RECV_COMPLETE) {
1042  eap_tls_ack(request, eap_session);
1043  eap_tls_session->state = EAP_TLS_HANDLED;
1044  goto done;
1045  }
1046 
1047  /*
1048  * We have a complete record. If the handshake is finished
1049  * process it as application data, otherwise continue
1050  * the handshake.
1051  */
1052  if (eap_tls_session->phase2 || SSL_is_init_finished(tls_session->ssl)) {
1053  int ret;
1054 
1055  eap_tls_session->phase2 = true;
1056 
1057  ret = fr_tls_session_recv(request, tls_session);
1058  switch (ret) {
1059  case 0:
1060  eap_tls_session->state = EAP_TLS_RECORD_RECV_COMPLETE;
1061  break;
1062 
1063  case 1:
1064  eap_tls_session->state = EAP_TLS_RECORD_RECV_MORE;
1065  break;
1066 
1067  default:
1068  eap_tls_session->state = EAP_TLS_FAIL;
1069  break;
1070  }
1071  } else {
1072  /*
1073  * Asynchronously process more handshake data
1074  */
1075  return eap_tls_handshake_push(request, eap_session);
1076  }
1077  break;
1078  /*
1079  * We have fragments or records to send to the peer
1080  */
1081  case EAP_TLS_RECORD_SEND:
1082  /*
1083  * Return a "yes we're done" if there's no more data to send,
1084  * and we've just managed to finish the SSL session initialization.
1085  */
1086  if (!eap_tls_session->phase2 && (tls_session->dirty_out.used == 0) &&
1087  SSL_is_init_finished(tls_session->ssl)) {
1088  eap_tls_session->phase2 = true;
1089  eap_tls_session->state = EAP_TLS_ESTABLISHED;
1090  goto done;
1091  }
1092 
1093  eap_tls_request(request, eap_session);
1094  eap_tls_session->state = EAP_TLS_HANDLED;
1095  goto done;
1096 
1097  /*
1098  * Bad things happened and we're unable to continue.
1099  */
1100  case EAP_TLS_INVALID:
1101  case EAP_TLS_FAIL:
1102  /*
1103  * Established means that we're done the initial handshake.
1104  *
1105  * For TTLS and PEAP that means begin phase2
1106  */
1107  case EAP_TLS_ESTABLISHED:
1108  default:
1109  goto done;
1110  }
1111 
1112  done:
1113 
1115 }
1116 
1117 /** Create a new fr_tls_session_t associated with an #eap_session_t
1118  *
1119  * Creates a new server fr_tls_session_t and associates it with an #eap_session_t
1120  * adding EAP specific opaque data to the SSL session created during fr_tls_session_t
1121  * initialisation.
1122  *
1123  * @param[in] request The current subrequest.
1124  * @param[in] eap_session to use as a context for the eap_tls_session_t
1125  * @param[in] ssl_ctx to use to configure the fr_tls_session_t.
1126  * @param[in] client_cert Whether we require the peer to prevent a certificate.
1127  * @return
1128  * - A new eap_tls_session on success.
1129  * - NULL on error.
1130  */
1132  SSL_CTX *ssl_ctx, bool client_cert)
1133 {
1134  eap_tls_session_t *eap_tls_session;
1135  fr_tls_session_t *tls_session;
1136  fr_tls_conf_t *conf = fr_tls_ctx_conf(ssl_ctx);
1137  fr_pair_t *vp;
1138 
1139  fr_assert(request->parent); /* must be a subrequest */
1140 
1141  /*
1142  * This EAP session is associated with a TLS session
1143  */
1144  eap_session->tls = true;
1145  MEM(eap_tls_session = talloc_zero(eap_session, eap_tls_session_t));
1146 
1147  /*
1148  * Initial state.
1149  */
1150  eap_tls_session->state = EAP_TLS_START_SEND;
1151 
1152  /*
1153  * As per the RFC...
1154  *
1155  * Broken protocols like PEAPv0 need this set to false.
1156  */
1157  eap_tls_session->include_length = true;
1158 
1159  /*
1160  * We use default fragment size, unless the Framed-MTU
1161  * tells us it's too big. Note that we do NOT account
1162  * for the EAP-TLS headers if conf->fragment_size is
1163  * large, because that config item looks to be confusing.
1164  *
1165  * i.e. it should REALLY be called MTU, and the code here
1166  * should figure out what that means for TLS fragment size.
1167  * asking the administrator to know the internal details
1168  * of EAP-TLS in order to calculate fragment sizes is
1169  * just too much.
1170  */
1171  vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_framed_mtu);
1172 
1173  /*
1174  * Every new session is started only from EAP-TLS-START.
1175  * Before Sending our initial EAP-TLS start open a new
1176  * SSL session.
1177  * Create all the required data structures & store them
1178  * in the SSL session's opaque data so that we can use
1179  * these data structures when we get the response.
1180  */
1181  eap_tls_session->tls_session = tls_session = fr_tls_session_alloc_server(eap_tls_session, ssl_ctx,
1182  request, vp ? vp->vp_uint32 : 0, client_cert);
1183  if (unlikely(!tls_session)) return NULL;
1184 
1185  /*
1186  * Add the EAP-Identity value to the TLS session so
1187  * it's available in all the TLS callbacks.
1188  */
1189  {
1190  fr_pair_t *identity;
1191 
1192  MEM(identity = fr_pair_afrom_da(tls_session, attr_eap_identity));
1193  fr_pair_value_bstrdup_buffer(identity, eap_session->identity, true);
1194  fr_tls_session_extra_pair_add_shallow(tls_session, identity);
1195  }
1196 
1197  /*
1198  * Add the EAP-Type we're running to the subrequest.
1199  */
1200  {
1201  fr_pair_t *type_vp;
1202 
1203  MEM(type_vp = fr_pair_afrom_da(tls_session, attr_eap_type));
1204  type_vp->vp_uint32 = eap_session->type;
1205  fr_tls_session_extra_pair_add_shallow(tls_session, type_vp);
1206  }
1207 
1208  /*
1209  * Associate various bits of opaque data with the session.
1210  */
1211  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_EAP_SESSION, (void *)eap_session);
1212  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)tls_session);
1213  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
1214  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_IDENTITY, (void *)&(eap_session->identity));
1215 
1216  return eap_tls_session;
1217 }
1218 
1219 /** Parse TLS configuration
1220  *
1221  * If the option given by 'attr' is set, we find the config section of that name and use
1222  * that for the TLS configuration. If not, we fall back to compatibility mode and read
1223  * the TLS options from the 'tls' section.
1224  *
1225  * @param cs to derive the configuration from.
1226  * @param attr identifier for common TLS configuration.
1227  * @return
1228  * - NULL on error.
1229  * - A new fr_tls_conf_t on success.
1230  */
1231 fr_tls_conf_t *eap_tls_conf_parse(CONF_SECTION *cs, char const *attr)
1232 {
1233  char const *tls_conf_name;
1234  CONF_PAIR *cp;
1236  CONF_SECTION *tls_cs;
1237  fr_tls_conf_t *tls_conf;
1238 
1240 
1241  cp = cf_pair_find(cs, attr);
1242  if (cp) {
1243  tls_conf_name = cf_pair_value(cp);
1244 
1245  tls_cs = cf_section_find(parent, TLS_CONFIG_SECTION, tls_conf_name);
1246  if (!tls_cs) {
1247  ERROR("Cannot find tls config \"%s\"", tls_conf_name);
1248  return NULL;
1249  }
1250  } else {
1251  /*
1252  * If we can't find the section given by the 'attr', we
1253  * fall-back to looking for the "tls" section, as in
1254  * previous versions.
1255  *
1256  * We don't fall back if the 'attr' is specified, but we can't
1257  * find the section - that is just a config error.
1258  */
1259  INFO("TLS section \"%s\" missing, trying to use legacy configuration", attr);
1260  tls_cs = cf_section_find(parent, "tls", NULL);
1261  }
1262 
1263  if (!tls_cs) return NULL;
1264 
1265  tls_conf = fr_tls_conf_parse_server(tls_cs);
1266  if (!tls_conf) return NULL;
1267 
1268  /*
1269  * The EAP RFC's say 1020, but we're less picky.
1270  */
1271  FR_INTEGER_BOUND_CHECK("fragment_size", tls_conf->fragment_size, >=, 100);
1272  /*
1273  * The maximum size for a RADIUS packet is 4096, but we're
1274  * not just a RADIUS server.
1275  *
1276  * Maximum size for a TLS record is 16K, so little point in
1277  * setting it higher than that.
1278  */
1279  FR_INTEGER_BOUND_CHECK("fragment_size", tls_conf->fragment_size, <=, FR_TLS_MAX_RECORD_SIZE);
1280 
1281  /*
1282  * Account for the EAP header (4), and the EAP-TLS header
1283  * (6), as per Section 4.2 of RFC 2716. What's left is
1284  * the maximum amount of data we read from a TLS buffer.
1285  */
1286  tls_conf->fragment_size -= 10;
1287 
1288  return tls_conf;
1289 }
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:468
#define RCSID(id)
Definition: build.h:481
#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:487
Configuration AVP similar to a fr_pair_t.
Definition: cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:101
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:1028
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:1439
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition: cf_util.c:1594
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
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
#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, 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:89
HIDDEN fr_dict_attr_t const * attr_framed_mtu
Definition: base.c:97
HIDDEN fr_dict_attr_t const * attr_eap_session_id
Definition: base.c:88
HIDDEN fr_dict_attr_t const * attr_eap_type
Definition: base.c:90
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_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition: pair.c:693
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition: pair.c:283
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:3056
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:772
An element in an arbitrarily ordered array of name to num mappings.
Definition: table.h:57
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:559
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:922
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:1131
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:806
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:1231
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:963
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:851
static fr_slen_t data
Definition: value.h:1265