6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
21 * Copyright 2003 Alan DeKok <aland@freeradius.org>
22 * Copyright 2006 The FreeRADIUS server project
27 #include <freeradius-devel/ident.h>
28 RCSIDH(eap_tls_h, "$Id$")
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <netinet/tcp.h>
44 #include <arpa/inet.h>
56 * For RH 9, which apparently needs this.
58 #ifndef OPENSSL_NO_KRB5
59 #define OPENSSL_NO_KRB5
61 #include <openssl/err.h>
62 #ifdef HAVE_OPENSSL_ENGINE_H
63 #include <openssl/engine.h>
65 #include <openssl/ssl.h>
66 #endif /* !defined(NO_OPENSSL) */
71 EAPTLS_INVALID = 0, /* invalid, don't reply */
72 EAPTLS_REQUEST, /* request, ok to send, invalid to receive */
73 EAPTLS_RESPONSE, /* response, ok to receive, invalid to send */
74 EAPTLS_SUCCESS, /* success, send success */
75 EAPTLS_FAIL, /* fail, send fail */
76 EAPTLS_NOOP, /* noop, continue */
78 EAPTLS_START, /* start, ok to send, invalid to receive */
79 EAPTLS_OK, /* ok, continue */
80 EAPTLS_ACK, /* acknowledge, continue */
81 EAPTLS_FIRST_FRAGMENT, /* first fragment */
82 EAPTLS_MORE_FRAGMENTS, /* more fragments, to send/receive */
83 EAPTLS_LENGTH_INCLUDED, /* length included */
84 EAPTLS_MORE_FRAGMENTS_WITH_LENGTH, /* more fragments with length */
85 EAPTLS_HANDLED /* tls code has handled it */
88 #define MAX_RECORD_SIZE 16384
91 * A single TLS record may be up to 16384 octets in length, but a
92 * TLS message may span multiple TLS records, and a TLS
93 * certificate message may in principle be as long as 16MB.
95 * However, note that in order to protect against reassembly
96 * lockup and denial of service attacks, it may be desirable for
97 * an implementation to set a maximum size for one such group of
100 * The TLS Message Length field is four octets, and provides the
101 * total length of the TLS message or set of messages that is
102 * being fragmented; this simplifies buffer allocation.
106 * FIXME: Dynamic allocation of buffer to overcome MAX_RECORD_SIZE overflows.
107 * or configure TLS not to exceed MAX_RECORD_SIZE.
109 typedef struct _record_t {
110 unsigned char data[MAX_RECORD_SIZE];
114 typedef struct _tls_info_t {
115 unsigned char origin;
116 unsigned char content_type;
117 unsigned char handshake_type;
118 unsigned char alert_level;
119 unsigned char alert_description;
120 char info_description[256];
127 * tls_session_t Structure gets stored as opaque in EAP_HANDLER
128 * This contains EAP-REQUEST specific data
129 * (ie EAPTLS_DATA(fragment), EAPTLS-ALERT, EAPTLS-REQUEST ...)
131 * clean_in - data that needs to be sent but only after it is soiled.
132 * dirty_in - data EAP server receives.
133 * clean_out - data that is cleaned after receiving.
134 * dirty_out - data EAP server sends.
135 * offset - current fragment size transmitted
136 * fragment - Flag, In fragment mode or not.
137 * tls_msg_len - Actual/Total TLS message length.
138 * length_flag - A flag to include length in every TLS Data/Alert packet
139 * if set to no then only the first fragment contains length
141 typedef struct _tls_session_t {
153 void (*record_init)(record_t *buf);
154 void (*record_close)(record_t *buf);
155 unsigned int (*record_plus)(record_t *buf, const void *ptr,
157 unsigned int (*record_minus)(record_t *buf, void *ptr,
162 * Framed-MTU attribute in RADIUS,
163 * if present, can also be used to set this
166 unsigned int tls_msg_len;
172 * Used by TTLS & PEAP to keep track of other per-session
176 void (*free_opaque)(void *opaque);
178 const char *prf_label;
179 int allow_session_resumption;
184 * Externally exported TLS functions.
186 eaptls_status_t eaptls_process(EAP_HANDLER *handler);
188 int eaptls_success(EAP_HANDLER *handler, int peap_flag);
189 int eaptls_fail(EAP_HANDLER *handler, int peap_flag);
190 int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn);
193 /* MPPE key generation */
194 void eaptls_gen_mppe_keys(VALUE_PAIR **reply_vps, SSL *s,
195 const char *prf_label);
196 void eapttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size);
198 #define BUFFER_SIZE 1024
200 #define EAP_TLS_START 1
201 #define EAP_TLS_ACK 2
202 #define EAP_TLS_SUCCESS 3
203 #define EAP_TLS_FAIL 4
204 #define EAP_TLS_ALERT 9
206 #define TLS_HEADER_LEN 4
209 * RFC 2716, Section 4.2:
218 * L = Length included
223 #define TLS_START(x) (((x) & 0x20) != 0)
224 #define TLS_MORE_FRAGMENTS(x) (((x) & 0x40) != 0)
225 #define TLS_LENGTH_INCLUDED(x) (((x) & 0x80) != 0)
227 #define TLS_CHANGE_CIPHER_SPEC(x) (((x) & 0x0014) == 0x0014)
228 #define TLS_ALERT(x) (((x) & 0x0015) == 0x0015)
229 #define TLS_HANDSHAKE(x) (((x) & 0x0016) == 0x0016)
231 #define SET_START(x) ((x) | (0x20))
232 #define SET_MORE_FRAGMENTS(x) ((x) | (0x40))
233 #define SET_LENGTH_INCLUDED(x) ((x) | (0x80))
236 * Following enums from rfc2246
238 * Hmm... since we dpeend on OpenSSL, it would be smarter to
239 * use the OpenSSL names for these.
242 change_cipher_spec = 20,
245 application_data = 23
253 enum AlertDescription {
255 unexpected_message = 10,
257 decryption_failed = 21,
258 record_overflow = 22,
259 decompression_failure = 30,
260 handshake_failure = 40,
261 bad_certificate = 42,
262 unsupported_certificate = 43,
263 certificate_revoked = 44,
264 certificate_expired = 45,
265 certificate_unknown = 46,
266 illegal_parameter = 47,
271 export_restriction = 60,
272 protocol_version = 70,
273 insufficient_security = 71,
276 no_renegotiation = 100
284 server_key_exchange = 12,
285 certificate_request = 13,
286 server_hello_done = 14,
287 certificate_verify = 15,
288 client_key_exchange = 16,
307 The L bit (length included) is set to indicate the presence of the
308 four octet TLS Message Length field, and MUST be set for the first
309 fragment of a fragmented TLS message or set of messages. The M bit
310 (more fragments) is set on all but the last fragment. The S bit
311 (EAP-TLS start) is set in an EAP-TLS Start message. This
312 differentiates the EAP-TLS Start message from a fragment
317 The TLS Message Length field is four octets, and is present only
318 if the L bit is set. This field provides the total length of the
319 TLS message or set of messages that is being fragmented.
323 The TLS data consists of the encapsulated TLS packet in TLS record
326 * The data structures present here
327 * maps only to the typedata in the EAP packet
329 * Based on the L bit flag, first 4 bytes of data indicate the length
331 typedef struct tls_packet_t {
336 typedef struct tls_packet {
344 //uint8_t *packet; /* Wired EAP-TLS packet as found in typdedata of EAP_PACKET */
348 /* EAP-TLS framework */
349 EAPTLS_PACKET *eaptls_alloc(void);
350 void eaptls_free(EAPTLS_PACKET **eaptls_packet_ptr);
351 int eaptls_start(EAP_DS *eap_ds, int peap);
352 int eaptls_compose(EAP_DS *eap_ds, EAPTLS_PACKET *reply);
355 int cbtls_password(char *buf, int num, int rwflag, void *userdata);
356 void cbtls_info(const SSL *s, int where, int ret);
357 void cbtls_msg(int write_p, int msg_version, int content_type,
358 const void *buf, size_t len, SSL *ssl, void *arg);
361 tls_session_t *eaptls_new_session(SSL_CTX *ssl_ctx, int client_cert);
362 int tls_handshake_recv(REQUEST *, tls_session_t *ssn);
363 int tls_handshake_send(REQUEST *,tls_session_t *ssn);
364 void tls_session_information(tls_session_t *tls_session);
367 void session_free(void *ssn);
368 void session_close(tls_session_t *ssn);
369 void session_init(tls_session_t *ssn);
371 /* SSL Indicies for ex data */
372 extern int eaptls_handle_idx;
373 extern int eaptls_conf_idx;
374 extern int eaptls_session_idx;
376 #endif /*_EAP_TLS_H*/