All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
eap_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: 6602d0c38f4288e8d33c6f81aab75135ebb9fbf8 $
19  * @file 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: 6602d0c38f4288e8d33c6f81aab75135ebb9fbf8 $")
72 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
73 
74 #include "eap_tls.h"
75 
76 /** Convert the EAP-TLS reply packet into an EAP packet
77  *
78  * The EAP packet will be written to eap_round->request, with the original reply
79  * being untouched.
80  *
81  * @param eap_session to continue.
82  * @param status What type of packet we're sending.
83  * @param flags to set. This is checked to determine if we need to include a length field.
84  * @param record The record buffer to read from. This most only be set for FR_TLS_REQUEST packets.
85  * @param record_len the length of the record we're sending.
86  * @param frag_len the length of the fragment we're sending.
87  * @return
88  * - 0 on success.
89  * - -1 on failure.
90  */
91 static int eap_tls_compose(eap_session_t *eap_session, fr_tls_status_t status, uint8_t flags,
92  tls_record_t *record, size_t record_len, size_t frag_len)
93 {
94  eap_round_t *eap_round = eap_session->this_round;
95  tls_session_t *tls_session = eap_session->opaque;
96  uint8_t *p;
97  size_t len = 1; /* Flags */
98 
99  rad_assert(!record || (status == FR_TLS_REQUEST));
100 
101  /*
102  * Determine the length (sans header) of our EAP-TLS
103  * packet. The reason for not including the length is
104  * that the fields are the same as normal EAP messages.
105  */
106  if (status == FR_TLS_REQUEST) {
107  if (TLS_LENGTH_INCLUDED(flags)) len += 4; /* TLS record length field */
108  if (record) len += frag_len;
109  }
110 
111  /*
112  * When the EAP server receives an EAP-Response with the
113  * M bit set, it MUST respond with an EAP-Request with
114  * EAP-Type = EAP-TLS and no data. This serves as a
115  * fragment ACK. The EAP peer MUST wait until it receives
116  * the EAP-Request before sending another fragment.
117  *
118  * In order to prevent errors in the processing of
119  * fragments, the EAP server MUST use increment the
120  * Identifier value for each fragment ACK contained
121  * within an EAP-Request, and the peer MUST include this
122  * Identifier value in the subsequent fragment contained
123  * within an EAP-Reponse.
124  */
125  eap_round->request->type.data = p = talloc_array(eap_round->request, uint8_t, len);
126  if (!p) return -1;
127  eap_round->request->type.length = len;
128 
129  *p++ = flags;
130 
131  if (TLS_LENGTH_INCLUDED(flags)) {
132  uint32_t net_record_len;
133 
134  /*
135  * If we need to add the length field,
136  * convert the total record length to
137  * network byte order and copy it in at the
138  * start of the packet.
139  */
140  net_record_len = htonl(record_len);
141  memcpy(p, &net_record_len, sizeof(net_record_len));
142  p += sizeof(net_record_len);
143  }
144 
145  if (record) tls_session->record_to_buff(record, p, frag_len);
146 
147  switch (status) {
148  case FR_TLS_ACK:
149  case FR_TLS_START:
150  case FR_TLS_REQUEST:
151  eap_round->request->code = PW_EAP_REQUEST;
152  break;
153 
154  case FR_TLS_SUCCESS:
155  eap_round->request->code = PW_EAP_SUCCESS;
156  break;
157 
158  case FR_TLS_FAIL:
159  eap_round->request->code = PW_EAP_FAILURE;
160  break;
161 
162  default:
163  /* Should never enter here */
164  rad_assert(0);
165  break;
166  }
167 
168  return 0;
169 }
170 
171 /** Send an initial EAP-TLS request to the peer.
172  *
173  * Once having received the peer's Identity, the EAP server MUST respond with an
174  * EAP-TLS/Start packet, which is an EAP-Request packet with EAP-Type = EAP-TLS,
175  * the Start (S) bit set, and no data.
176  *
177  * The EAP-TLS conversation will then begin, with the peer sending an EAP-Response
178  * packet with EAP-Type = EAP-TLS. The data field of that packet will be the TLS data.
179  *
180  * The S flag is set only within the EAP-TLS start message sent from the EAP server to the peer.
181  *
182  * - len = header + type + tls_typedata
183  * - tls_typedata = flags(Start (S) bit set, and no data)
184  *
185  * Fragment length is Framed-MTU - 4.
186  *
187  * @param eap_session to initiate.
188  * @return
189  * - 0 on success.
190  * - -1 on failure.
191  */
192 int eap_tls_start(eap_session_t *eap_session)
193 {
194  return eap_tls_compose(eap_session, FR_TLS_START,
195  SET_START(((tls_session_t *)eap_session->opaque)->base_flags), NULL, 0, 0);
196 }
197 
198 /** Send an EAP-TLS success
199  *
200  * Composes an EAP-TLS-Success. This is a message with code FR_TLS_SUCCESS.
201  * It contains no cryptographic material, and is not protected.
202  *
203  * We add the MPPE keys here. These are used by the NAS. The supplicant
204  * will derive the same keys separately.
205  *
206  * @param eap_session that completed successfully.
207  * @return
208  * - 0 on success.
209  * - -1 on failure.
210  */
212 {
213  REQUEST *request = eap_session->request;
214  tls_session_t *tls_session = eap_session->opaque;
215 
216  eap_session->finished = true;
217 
218  /*
219  * Check session resumption is allowed (if we're in a resumed session)
220  */
221  if (tls_success(tls_session, request) < 0) return -1;
222 
223  /*
224  * Build the success packet
225  */
226  if (eap_tls_compose(eap_session, FR_TLS_SUCCESS, tls_session->base_flags, NULL, 0, 0) < 0) return -1;
227 
228  /*
229  * Automatically generate MPPE keying material.
230  */
231  if (tls_session->prf_label) {
232  eap_tls_gen_mppe_keys(eap_session->request, tls_session->ssl, tls_session->prf_label);
233  } else {
234  RWDEBUG("Not adding MPPE keys because there is no PRF label");
235  }
236 
237  eap_tls_gen_eap_key(eap_session->request->reply, tls_session->ssl, eap_session->type);
238 
239  return 0;
240 }
241 
242 /** Send an EAP-TLS failure
243  *
244  * Composes an EAP-TLS-Failure. This is a message with code FR_TLS_FAILURE.
245  * It contains no cryptographic material, and is not protected.
246  *
247  * In addition to sending the failure, will destroy any cached session data.
248  *
249  * @param eap_session that failed.
250  * @return
251  * - 0 on success.
252  * - -1 on failure (to compose a valid packet).
253  */
254 int eap_tls_fail(eap_session_t *eap_session)
255 {
256  tls_session_t *tls_session = eap_session->opaque;
257 
258  eap_session->finished = true;
259 
260  /*
261  * Destroy any cached session data
262  */
263  tls_fail(tls_session);
264 
265  if (eap_tls_compose(eap_session, FR_TLS_START, SET_START(tls_session->base_flags), NULL, 0, 0) < 0) return -1;
266  return 0;
267 }
268 
269 /** Frames the OpenSSL data that needs to be sent to the client in an EAP-Request
270  *
271  * A single TLS record may be up to 16384 octets in length, but a TLS message
272  * may span multiple TLS records, and a TLS certificate message may
273  * theoretically, be as long as 16MB.
274  *
275  * In EAP-TLS with no inner method, this is used primarily to send our certificate
276  * chain to the peer.
277  *
278  * In other methods this function is also called to package up application data
279  * for the inner tunnel method.
280  *
281  * The tls_session->length_included flag determines whether we include the extra
282  * four byte length field in the request and set the L flag.
283  *
284  * If present, the tls_length field indicates the total length of the reassembled
285  * TLS record.
286  *
287  * If tls_session->length_included this means we include L flag and the tls_length
288  * field in EVERY packet we send out.
289  *
290  * If !tls_session->length_included this means we include L flag and tls_length
291  * field **ONLY** in First packet of a fragment series. We do not use it anywhere
292  * else.
293  *
294  * @param eap_session that's continuing.
295  * @return
296  * - 0 on success.
297  * - -1 on failure.
298  */
300 {
301  tls_session_t *tls_session = eap_session->opaque;
302  uint8_t flags = tls_session->base_flags;
303  size_t frag_len;
304  bool length_included = false;
305 
306  /*
307  * We don't need to always include the length
308  * (just in the first fragment) but it is
309  * configurable for compatibility.
310  */
311  if (tls_session->length_flag) length_included = true;
312 
313  /*
314  * If this is the first fragment, record the complete
315  * TLS record length.
316  */
317  if (tls_session->record_out_started == false) tls_session->record_out_total_len = tls_session->dirty_out.used;
318 
319  /*
320  * If the data we're sending is greater than the MTU
321  * then we need to fragment it.
322  */
323  if (tls_session->dirty_out.used > tls_session->mtu) {
324  frag_len = tls_session->mtu; /* Data we're draining for this fragment */
325  flags = SET_MORE_FRAGMENTS(flags);
326 
327  /*
328  * Length MUST be included if we're record_out_started
329  * and this is the first fragment.
330  */
331  if (tls_session->record_out_started == false) length_included = true;
332  tls_session->record_out_started = true; /* Start a new series of fragments */
333  /*
334  * Otherwise, we're either sending a record smaller
335  * than the MTU or this is the final fragment.
336  */
337  } else {
338  frag_len = tls_session->dirty_out.used; /* Remaining data to drain */
339  tls_session->record_out_started = false;
340  }
341 
342  /*
343  * Update the flags to say we're including the
344  * TLS record length.
345  */
346  if (length_included) flags = SET_LENGTH_INCLUDED(flags);
347 
348  return eap_tls_compose(eap_session, FR_TLS_REQUEST, flags,
349  &tls_session->dirty_out, tls_session->record_out_total_len, frag_len);
350 }
351 
352 /** ACK a fragment of the TLS record from the peer
353  *
354  * EAP server sends an ACK when it determines there are More fragments to
355  * receive to make the complete TLS-record.
356  *
357  * When the EAP server receives an EAP-Response with the M bit set, it MUST
358  * respond with an EAP-Request with EAP-Type = EAP-TLS and no data. This serves
359  * as a fragment ACK.
360  *
361  * In order to prevent errors in the processing of fragments, the EAP server
362  * MUST use increment the Identifier value for each fragment ACK contained
363  * within an EAP-Request, and the peer MUST include this Identifier value in
364  * the subsequent fragment contained within an EAP-Reponse.
365  *
366  * @param eap_session that we're acking the fragment for.
367  */
368 static int eap_tls_send_ack(eap_session_t *eap_session)
369 {
370  REQUEST *request = eap_session->request;
371 
372  RDEBUG2("ACKing Peer's TLS record fragment");
373  return eap_tls_compose(eap_session, FR_TLS_ACK,
374  ((tls_session_t *)eap_session->opaque)->base_flags, NULL, 0, 0);
375 }
376 
377 /** Check that this EAP-TLS packet is correct and the progression of EAP-TLS packets is sane
378  *
379  * @note In the received packet, No data will be present incase of ACK or NAK
380  * in this case the packet->data pointer will be NULL.
381  *
382  * @param[in] eap_session the current EAP session state.
383  * @return
384  * - FR_TLS_INVALID if the TLS record or progression is invalid.
385  * - FR_TLS_FAIL handshake failed.
386  * - FR_TLS_RECORD_FRAGMENT_INIT this is the start of a new sequence of record fragments.
387  * - FR_TLS_RECORD_FRAGMENT_MORE this is a continuation of a sequence of fragments.
388  * - FR_TLS_REQUEST send more data to peer.
389  * - FR_TLS_RECORD_COMPLETE we received a completed record.
390  * - FR_TLS_SUCCESS handshake is complete, TLS session has been established.
391  */
392 static fr_tls_status_t eap_tls_verify(eap_session_t *eap_session)
393 {
394  eap_round_t *this_round = eap_session->this_round;
395  eap_round_t *prev_round = eap_session->prev_round;
396  tls_session_t *tls_session = eap_session->opaque;
397 
398  eap_tls_data_t *eap_tls_data;
399  REQUEST *request = eap_session->request;
400  size_t frag_len, header_len;
401 
402  /*
403  * All EAP-TLS packets must contain type and flags fields.
404  */
405  if (this_round->response->length < (EAP_HEADER_LEN + 2)) {
406  REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
407  (size_t)EAP_HEADER_LEN + 2, this_round->response->length);
408  return FR_TLS_INVALID;
409  }
410 
411  /*
412  * We don't check ANY of the input parameters. It's all
413  * code which works together, so if something is wrong,
414  * we SHOULD core dump.
415  *
416  * e.g. if this_round is NULL, of if this_round->response is
417  * NULL, of if it's NOT an EAP-Response, or if the packet
418  * is too short. See eap_validation()., in ../../eap.c
419  */
420  eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
421 
422  /*
423  * First output the flags (for debugging)
424  */
425  RDEBUG3("Peer sent flags %c%c%c%c%c%c%c%c",
426  TLS_START(eap_tls_data->flags) ? 'S' : '-',
427  TLS_MORE_FRAGMENTS(eap_tls_data->flags) ? 'M' : '-',
428  TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 'L' : '-',
429  TLS_RESERVED0(eap_tls_data->flags) ? 'R' : '-',
430  TLS_RESERVED1(eap_tls_data->flags) ? 'R' : '-',
431  TLS_RESERVED2(eap_tls_data->flags) ? 'R' : '-',
432  TLS_RESERVED3(eap_tls_data->flags) ? 'R' : '-',
433  TLS_RESERVED4(eap_tls_data->flags) ? 'R' : '-');
434 
435  /*
436  * This length includes the type and flags field and
437  * the message length field if the flags indicate it's present.
438  */
439  header_len = EAP_HEADER_LEN + (TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 6 : 2);
440  if (this_round->response->length < header_len) {
441  REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
442  header_len, this_round->response->length);
443  return FR_TLS_INVALID;
444  }
445 
446  /*
447  * check for ACK
448  *
449  * If there's no TLS data, or there's 1 byte of TLS data,
450  * with the flags set to zero, then it's an ACK.
451  *
452  * Find if this is a reply to the previous request sent
453  */
454  if ((!eap_tls_data) ||
455  ((this_round->response->length == EAP_HEADER_LEN + 2) &&
456  ((eap_tls_data->flags & 0xc0) == 0x00))) {
457  if (!prev_round || (prev_round->request->id != this_round->response->id)) {
458  REDEBUG("Received Invalid TLS ACK");
459  return FR_TLS_INVALID;
460  }
461  return tls_ack_handler(eap_session->opaque, request);
462  }
463 
464  /*
465  * We send TLS_START, but do not receive it.
466  */
467  if (TLS_START(eap_tls_data->flags)) {
468  REDEBUG("Peer sent EAP-TLS Start message (only the server is allowed to do this)");
469  return FR_TLS_INVALID;
470  }
471 
472  /*
473  * Calculate this fragment's length
474  */
475  frag_len = this_round->response->length - header_len;
476 
477  /*
478  * The L bit (length included) is set to indicate the
479  * presence of the four octet TLS Message Length field,
480  * and MUST be set for the first fragment of a fragmented
481  * TLS message or set of messages.
482  *
483  * The M bit (more fragments) is set on all but the last
484  * fragment.
485  *
486  * The S bit (EAP-TLS start) is set in an EAP-TLS Start
487  * message. This differentiates the EAP-TLS Start message
488  * from a fragment acknowledgement.
489  */
490  if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
491  size_t total_len;
492 
493  total_len = eap_tls_data->data[2] * 256 | eap_tls_data->data[3];
494  if (frag_len > total_len) {
495  REDEBUG("TLS fragment length (%zu bytes) greater than TLS record length (%zu bytes)",
496  frag_len, total_len);
497  return FR_TLS_INVALID;
498  }
499 
500  if (total_len > MAX_RECORD_SIZE) {
501  REDEBUG("Reassembled TLS record will be %zu bytes, "
502  "greater than our maximum record size (" STRINGIFY(MAX_RECORD_SIZE) " bytes)",
503  total_len);
504  return FR_TLS_INVALID;
505  }
506 
507  /*
508  * wpa_supplicant's implementation of PEAPv0, and likely other
509  * implementations of PEAPv0 will always include a Length flag
510  * for every record fragment if performing mutual TLS auth.
511  *
512  * If the eap_session says this is not the first fragment, then
513  * don't count this as a new record, and continue as if we
514  * hadn't seen the length flag.
515  */
516  if (tls_session->record_in_started) goto ignore_length;
517 
518  /*
519  * This is the first fragment of a fragmented TLS record transfer.
520  */
521  RDEBUG2("Peer indicated complete TLS record size will be %zu bytes", total_len);
522  if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
523  /*
524  * The peer is free to send fragments of wildly varying
525  * lengths, but the vast majority won't.
526  *
527  * In this calculation we take into account the fact that the future
528  * fragments are likely to be 4 bytes larger than the initial one
529  * as they won't contain the length field.
530  */
531  if (frag_len + 4) { /* check for wrap, else clang scan gets excited */
532  RDEBUG2("Expecting %i TLS record fragments",
533  (int)((((total_len - frag_len) + ((frag_len + 4) - 1)) / (frag_len + 4)) + 1));
534  }
535 
536  /*
537  * First fragment. record_in_started bool was false,
538  * and we received a length included + more fragments packet.
539  */
540  RDEBUG2("Got first TLS record fragment (%zu bytes). Peer indicated more fragments "
541  "to follow", frag_len);
542  tls_session->record_in_total_len = total_len;
543  tls_session->record_in_recvd_len = frag_len;
544  tls_session->record_in_started = true;
545 
546  return FR_TLS_RECORD_FRAGMENT_INIT;
547  }
548 
549  /*
550  * Else this is the complete TLS record.
551  */
552  if (total_len != frag_len) {
553  REDEBUG("Peer indicated no more fragments, but TLS record length (%zu bytes) "
554  "does not match EAP-TLS data length (%zu bytes)", total_len, frag_len);
555  return FR_TLS_INVALID;
556  }
557 
558  /*
559  * RFC5216 doesn't specify explicitly whether a non-fragmented
560  * packet should include the length or not.
561  *
562  * We support both options for maximum compatibility.
563  */
564  RDEBUG2("Got complete TLS record, with length (%zu bytes)", frag_len);
565  return FR_TLS_RECORD_COMPLETE;
566  }
567 
568 ignore_length:
569  if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
570  /*
571  * If this is not an ongoing transfer, and we have the M flag
572  * then this record transfer is invalid.
573  */
574  if (!tls_session->record_in_started) {
575  REDEBUG("TLS More (M) flag set, but no fragmented record transfer was in progress");
576  return FR_TLS_INVALID;
577  }
578 
579  /*
580  * If this is an ongoing transfer, and we have the M flag,
581  * then this is just an additional fragment.
582  */
583  RDEBUG2("Got additional TLS record fragment (%zu bytes). "
584  "Peer indicated more fragments to follow", frag_len);
585  tls_session->record_in_recvd_len += frag_len;
586  if (tls_session->record_in_recvd_len > tls_session->record_in_total_len) {
587  REDEBUG("Total received TLS record fragments (%zu bytes), exceeds "
588  "indicated TLS record length (%zu bytes)",
589  tls_session->record_in_recvd_len, tls_session->record_in_total_len);
590  return FR_TLS_INVALID;
591  }
592  return FR_TLS_RECORD_FRAGMENT_MORE;
593  }
594 
595  /*
596  * No L flag and no M flag. This is either the final fragment,
597  * or a new transfer that was not started with a L flag, which
598  * RFC5216 hints, may be acceptable.
599  *
600  * If it's an in-progress record transfer, check we now have
601  * the complete record.
602  */
603  if (tls_session->record_in_started) {
604  tls_session->record_in_started = false;
605 
606  RDEBUG2("Got final TLS record fragment (%zu bytes)", frag_len);
607  tls_session->record_in_recvd_len += frag_len;
608  if (tls_session->record_in_recvd_len != tls_session->record_in_total_len) {
609  REDEBUG("Total received TLS record fragments (%zu bytes), does not equal indicated "
610  "TLS record length (%zu bytes)",
611  tls_session->record_in_recvd_len, tls_session->record_in_total_len);
612  return FR_TLS_INVALID;
613  }
614  return FR_TLS_RECORD_COMPLETE;
615  }
616 
617  /*
618  * None of the flags are set, it wasn't an in progress transfer,
619  * but it's still a valid EAP-TLS packet.
620  */
621  RDEBUG2("Got complete TLS record (%zu bytes)", frag_len);
622 
623  return FR_TLS_RECORD_COMPLETE;
624 }
625 
626 /** Continue with the handshake
627  *
628  * @param eap_session to continue.
629  * @return
630  * - FR_TLS_FAIL if the message is invalid.
631  * - FR_TLS_HANDLED if we need to send an additional request to the peer.
632  * - FR_TLS_SUCCESS if the handshake completed successfully, and there's
633  * no more data to send.
634  */
635 static fr_tls_status_t eap_tls_handshake(eap_session_t *eap_session)
636 {
637  REQUEST *request = eap_session->request;
638  tls_session_t *tls_session = eap_session->opaque;
639 
640  /*
641  * We have the complete TLS-data or TLS-message.
642  *
643  * Clean the dirty message.
644  *
645  * Authenticate the user and send Success/Failure.
646  *
647  * If more info is required then send another request.
648  */
649  if (!tls_handshake_recv(eap_session->request, tls_session)) {
650  REDEBUG("TLS receive handshake failed during operation");
651  tls_fail(tls_session);
652  return FR_TLS_FAIL;
653  }
654 
655  /*
656  * FIXME: return success/fail.
657  *
658  * TLS proper can decide what to do, then.
659  */
660  if (tls_session->dirty_out.used > 0) {
661  eap_tls_request(eap_session);
662  return FR_TLS_HANDLED;
663  }
664 
665  /*
666  * If there is no data to send i.e dirty_out.used <=0 and
667  * if the SSL handshake is finished, then return a
668  * FR_TLS_SUCCESS
669  */
670  if (SSL_is_init_finished(tls_session->ssl)) {
671  /*
672  * Init is finished. The rest is
673  * application data.
674  */
675  tls_session->info.content_type = application_data;
676  return FR_TLS_SUCCESS;
677  }
678 
679  /*
680  * Who knows what happened...
681  */
682  REDEBUG("TLS failed during operation");
683  return FR_TLS_FAIL;
684 }
685 
686 /** Process an EAP TLS request
687  *
688  * Here we implement a basic state machine. The state machine is implicit and
689  * is driven by the state of the TLS session and the flags sent.
690  * INCOMING DATA:
691  * 1. EAP-TLS should get the compelete TLS data from the peer.
692  * 2. Store that data in a data structure with any other required info
693  * 3. Hand this data structure to the TLS module.
694  * 4. TLS module will perform its operations on the data and hands back to EAP-TLS
695  * OUTGOING DATA:
696  * 1. EAP-TLS if necessary will fragment it and send it to the destination.
697  *
698  * During EAP-TLS initialization, TLS Context object will be initialised and stored.
699  * For every new authentication request, TLS will open a new session object and that
700  * session object SHOULD be maintained even after the session is completed, for session
701  * resumption.
702  *
703  * @param eap_session to continue.
704  * @return
705  * - FR_TLS_SUCCESS
706  * - FR_TLS_HANDLED
707  */
708 fr_tls_status_t eap_tls_process(eap_session_t *eap_session)
709 {
710  tls_session_t *tls_session = (tls_session_t *) eap_session->opaque;
711  eap_round_t *this_round = eap_session->this_round;
712  fr_tls_status_t status;
713  REQUEST *request = eap_session->request;
714 
715  eap_tls_data_t *eap_tls_data;
716  uint8_t *data;
717  size_t data_len;
718 
719  if (!request) return FR_TLS_FAIL;
720 
721  RDEBUG2("Continuing EAP-TLS");
722 
723  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request);
724 
725  /*
726  * Call eap_tls_verify to sanity check the incoming EAP data.
727  */
728  status = eap_tls_verify(eap_session);
729  switch (status) {
730  case FR_TLS_INVALID:
731  case FR_TLS_FAIL:
732  REDEBUG("[eap-tls verify] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
733  break;
734 
735  default:
736  RDEBUG2("[eap-tls verify] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
737  break;
738  }
739 
740  /*
741  * Status in this here means 'state'. Our state is determined passively
742  * for EAP-TLS, based on what state OpenSSL reported the TLS session
743  * to be in, and what flags were last received from the peer.
744  */
745  switch (status) {
746  /*
747  * We've received a complete TLS record, this is the same as receiving a
748  * fragment, except we also process the complete record.
749  */
750  case FR_TLS_RECORD_COMPLETE:
751  /*
752  * We've received a fragment of a TLS record
753  *
754  * Determine where the TLS record starts.
755  *
756  * If the length included flag is set, we need to skip over the 4 byte
757  * message length field.
758  *
759  * Next - Copy the fragment data into OpenSSL's dirty in buffer so that it
760  * can process it in a later call.
761  */
762  case FR_TLS_RECORD_FRAGMENT_INIT:
763  case FR_TLS_RECORD_FRAGMENT_MORE:
764  eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
765  if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
766  data = (this_round->response->type.data + 5); /* flags + TLS-Length */
767  data_len = this_round->response->type.length - 5; /* flags + TLS-Length */
768  } else {
769  data = this_round->response->type.data + 1; /* flags */
770  data_len = this_round->response->type.length - 1; /* flags */
771  }
772 
773  /*
774  * Update the dirty_in buffer (data for reading by OpenSSL)
775  *
776  * This buffer will contain partial data when M bit is set, and should
777  * should only be reinitialized when M but is not set.
778  */
779  if ((tls_session->record_from_buff)(&tls_session->dirty_in, data, data_len) != data_len) {
780  REDEBUG("Exceeded maximum record size");
781  status = FR_TLS_FAIL;
782  goto done;
783  }
784 
785  /*
786  * ACK fragments until we get a complete TLS record.
787  */
788  if (status != FR_TLS_RECORD_COMPLETE) {
789  eap_tls_send_ack(eap_session);
790  status = FR_TLS_HANDLED;
791  goto done;
792  }
793 
794  /*
795  * We have a complete record. If the handshake is finished
796  * process it as application data, otherwise continue
797  * the handshake.
798  */
799  status = SSL_is_init_finished(tls_session->ssl) ? tls_application_data(tls_session, request) :
800  eap_tls_handshake(eap_session);
801  break;
802  /*
803  * We have fragments or records to send to the peer
804  */
805  case FR_TLS_REQUEST:
806  eap_tls_request(eap_session);
807  status = FR_TLS_HANDLED;
808  goto done;
809 
810  /*
811  * Bad things happened and we're unable to continue.
812  */
813  case FR_TLS_INVALID:
814  case FR_TLS_FAIL:
815  /*
816  * Success means that we're done the initial handshake. For TTLS, this
817  * means send stuff back to the peer, and the peer sends us more
818  * tunnelled data.
819  */
820  case FR_TLS_SUCCESS:
821  default:
822  goto done;
823  }
824 
825  done:
826  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL);
827 
828  return status;
829 }
830 
831 /** Create a new tls_session_t associated with an #eap_session_t
832  *
833  * Creates a new server tls_session_t and associates it with an #eap_session_t
834  * adding EAP specific opaque data to the SSL session created during tls_session_t
835  * initialisation.
836  *
837  * @param eap_session to use as a context for the tls_session_t
838  * @param tls_conf to use to configure the tls_session_t.
839  * @param client_cert Whether we require the peer to prevent a certificate.
840  * @return
841  * - A new tls_session on success.
842  * - NULL on error.
843  */
844 tls_session_t *eap_tls_session_init(eap_session_t *eap_session, fr_tls_server_conf_t *tls_conf, bool client_cert)
845 {
846  tls_session_t *tls_session;
847  REQUEST *request = eap_session->request;
848 
849  /*
850  * This EAP session is associated with a TLS session
851  */
852  eap_session->tls = true;
853 
854  /*
855  * Every new session is started only from EAP-TLS-START.
856  * Before Sending our initial EAP-TLS start open a new
857  * SSL session.
858  * Create all the required data structures & store them
859  * in the SSL session's opaque data so that we can use
860  * these data structures when we get the response.
861  */
862  tls_session = tls_session_init_server(eap_session, tls_conf, request, client_cert);
863  if (!tls_session) return NULL;
864 
865  /*
866  * Associate various bits of opaque data with the session.
867  */
868  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_EAP_SESSION, (void *)eap_session);
869  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)tls_session);
870  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (void *)tls_conf);
871  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_IDENTITY, (void *)&(eap_session->identity));
872 #ifdef HAVE_OPENSSL_OCSP_H
873  SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_STORE, (void *)tls_conf->ocsp_store);
874 #endif
875 
876  return tls_session;
877 }
878 
879 /** Parse TLS configuration
880  *
881  * If the option given by 'attr' is set, we find the config section of that name and use
882  * that for the TLS configuration. If not, we fall back to compatibility mode and read
883  * the TLS options from the 'tls' section.
884  *
885  * @param cs to derive the configuration from.
886  * @param attr identifier for common TLS configuration.
887  * @return
888  * - NULL on error.
889  * - A new fr_tls_server_conf_t on success.
890  */
891 fr_tls_server_conf_t *eap_tls_conf_parse(CONF_SECTION *cs, char const *attr)
892 {
893  char const *tls_conf_name;
894  CONF_PAIR *cp;
895  CONF_SECTION *parent;
896  CONF_SECTION *tls_cs;
897  fr_tls_server_conf_t *tls_conf;
898 
899  if (!cs) return NULL;
900 
901  rad_assert(attr != NULL);
902 
903  parent = cf_item_parent(cf_section_to_item(cs));
904 
905  cp = cf_pair_find(cs, attr);
906  if (cp) {
907  tls_conf_name = cf_pair_value(cp);
908 
909  tls_cs = cf_section_sub_find_name2(parent, TLS_CONFIG_SECTION, tls_conf_name);
910  if (!tls_cs) {
911  ERROR("Cannot find tls config \"%s\"", tls_conf_name);
912  return NULL;
913  }
914  } else {
915  /*
916  * If we can't find the section given by the 'attr', we
917  * fall-back to looking for the "tls" section, as in
918  * previous versions.
919  *
920  * We don't fall back if the 'attr' is specified, but we can't
921  * find the section - that is just a config error.
922  */
923  INFO("TLS section \"%s\" missing, trying to use legacy configuration", attr);
924  tls_cs = cf_section_sub_find(parent, "tls");
925  }
926 
927  if (!tls_cs) return NULL;
928 
929  tls_conf = tls_server_conf_parse(tls_cs);
930  if (!tls_conf) return NULL;
931 
932  /*
933  * The EAP RFC's say 1020, but we're less picky.
934  */
935  if (tls_conf->fragment_size < 100) {
936  ERROR("Configured fragment size is too small, must be >= 100");
937  return NULL;
938  }
939 
940  /*
941  * The maximum size for a RADIUS packet is 4096,
942  * minus the header (20), Message-Authenticator (18),
943  * and State (18), etc. results in about 4000 bytes of data
944  * that can be devoted *solely* to EAP.
945  */
946  if (tls_conf->fragment_size > 4000) {
947  ERROR("Configured fragment size is too large, must be <= 4000");
948  return NULL;
949  }
950 
951  /*
952  * Account for the EAP header (4), and the EAP-TLS header
953  * (6), as per Section 4.2 of RFC 2716. What's left is
954  * the maximum amount of data we read from a TLS buffer.
955  */
956  tls_conf->fragment_size -= 10;
957 
958  return tls_conf;
959 }
960 
void eap_tls_gen_eap_key(RADIUS_PACKET *packet, SSL *s, uint32_t header)
Definition: mppe_keys.c:188
size_t length
Definition: eap_types.h:135
static fr_tls_status_t eap_tls_verify(eap_session_t *eap_session)
Check that this EAP-TLS packet is correct and the progression of EAP-TLS packets is sane...
Definition: eap_tls.c:392
#define TLS_CONFIG_SECTION
Definition: eap.h:36
void eap_tls_gen_mppe_keys(REQUEST *request, SSL *s, char const *prf_label)
Generate keys according to RFC 2716 and add to the reply.
Definition: mppe_keys.c:108
#define INFO(fmt,...)
Definition: log.h:143
bool tls
Whether EAP method uses TLS.
Definition: eap.h:88
#define EAP_HEADER_LEN
Definition: eap_types.h:35
bool finished
Whether we consider this session complete.
Definition: eap.h:89
eap_packet_t * request
Packet we will send to the peer.
Definition: eap.h:45
void * opaque
Opaque data used by EAP methods.
Definition: eap.h:80
eap_round_t * prev_round
Previous response/request pair.
Definition: eap.h:75
static fr_tls_status_t eap_tls_handshake(eap_session_t *eap_session)
Continue with the handshake.
Definition: eap_tls.c:635
eap_type_data_t type
Definition: eap_types.h:136
REQUEST * request
Request that contains the response we're processing.
Definition: eap.h:71
CONF_PAIR * cf_pair_find(CONF_SECTION const *, char const *name)
Definition: conffile.c:3478
char const * cf_pair_value(CONF_PAIR const *pair)
Definition: conffile.c:3506
#define rad_assert(expr)
Definition: rad_assert.h:38
eap_type_t type
EAP method number.
Definition: eap.h:69
uint8_t id
Definition: eap_types.h:134
int eap_tls_success(eap_session_t *eap_session)
Send an EAP-TLS success.
Definition: eap_tls.c:211
Tracks the progress of a single session of any EAP method.
Definition: eap.h:60
#define STRINGIFY(x)
Definition: build.h:34
CONF_SECTION * cf_item_parent(CONF_ITEM const *ci)
Definition: conffile.c:3896
static bool done
Definition: radclient.c:53
static int eap_tls_send_ack(eap_session_t *eap_session)
ACK a fragment of the TLS record from the peer.
Definition: eap_tls.c:368
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Definition: eap.h:77
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition: conffile.c:224
size_t length
Definition: eap_types.h:123
RADIUS_PACKET * reply
Outgoing response.
Definition: radiusd.h:225
fr_tls_status_t eap_tls_process(eap_session_t *eap_session)
Process an EAP TLS request.
Definition: eap_tls.c:708
Configuration AVP similar to a VALUE_PAIR.
Definition: conffile.c:82
Contains a pair of request and response packets.
Definition: eap.h:43
CONF_SECTION * cf_section_sub_find(CONF_SECTION const *, char const *name)
Find a sub-section in a section.
Definition: conffile.c:3708
char * identity
NAI (User-Name) from EAP-Identity.
Definition: eap.h:73
static USES_APPLE_DEPRECATED_API int eap_tls_compose(eap_session_t *eap_session, fr_tls_status_t status, uint8_t flags, tls_record_t *record, size_t record_len, size_t frag_len)
Convert the EAP-TLS reply packet into an EAP packet.
Definition: eap_tls.c:91
#define RDEBUG2(fmt,...)
Definition: log.h:244
uint8_t data[]
Definition: eap_pwd.h:625
tls_session_t * eap_tls_session_init(eap_session_t *eap_session, fr_tls_server_conf_t *tls_conf, bool client_cert)
Create a new tls_session_t associated with an eap_session_t.
Definition: eap_tls.c:844
#define REDEBUG(fmt,...)
Definition: log.h:254
uint8_t data[1]
Definition: eap_tls.h:85
int eap_tls_fail(eap_session_t *eap_session)
Send an EAP-TLS failure.
Definition: eap_tls.c:254
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
Definition: token.c:506
fr_tls_server_conf_t * eap_tls_conf_parse(CONF_SECTION *cs, char const *attr)
Parse TLS configuration.
Definition: eap_tls.c:891
eap_packet_t * response
Packet we received from the peer.
Definition: eap.h:44
#define RWDEBUG(fmt,...)
Definition: log.h:251
CONF_SECTION * cf_section_sub_find_name2(CONF_SECTION const *, char const *name1, char const *name2)
Find a CONF_SECTION with both names.
Definition: conffile.c:3728
uint8_t flags
Definition: eap_tls.h:84
#define RCSID(id)
Definition: build.h:135
int eap_tls_request(eap_session_t *eap_session)
Frames the OpenSSL data that needs to be sent to the client in an EAP-Request.
Definition: eap_tls.c:299
int eap_tls_start(eap_session_t *eap_session)
Send an initial EAP-TLS request to the peer.
Definition: eap_tls.c:192
#define ERROR(fmt,...)
Definition: log.h:145
eap_code_t code
Definition: eap_types.h:133
#define USES_APPLE_DEPRECATED_API
Definition: build.h:122
uint8_t * data
Definition: eap_types.h:124
#define RDEBUG3(fmt,...)
Definition: log.h:245