2 * rlm_eap_tls.c contains the interfaces that are called from eap
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
26 #include <freeradius-devel/ident.h>
29 #include <freeradius-devel/autoconf.h>
31 #ifdef HAVE_OPENSSL_RAND_H
32 #include <openssl/rand.h>
35 #ifdef HAVE_OPENSSL_EVP_H
36 #include <openssl/evp.h>
39 #include "rlm_eap_tls.h"
42 #ifdef HAVE_SYS_STAT_H
47 * Detach the EAP-TLS module.
49 static int eaptls_detach(void *arg)
51 tls_server_conf_free(arg);
57 * Attach the EAP-TLS module.
59 static int eaptls_attach(CONF_SECTION *cs, void **instance)
61 fr_tls_server_conf_t *inst;
64 * Parse the config file & get all the configured values
66 inst = tls_server_conf_parse(cs);
68 radlog(L_ERR, "rlm_eap_tls: Failed initializing SSL context");
73 * The EAP RFC's say 1020, but we're less picky.
75 if (inst->fragment_size < 100) {
76 radlog(L_ERR, "rlm_eap_tls: Fragment size is too small.");
82 * The maximum size for a RADIUS packet is 4096,
83 * minus the header (20), Message-Authenticator (18),
84 * and State (18), etc. results in about 4000 bytes of data
85 * that can be devoted *solely* to EAP.
87 if (inst->fragment_size > 4000) {
88 radlog(L_ERR, "rlm_eap_tls: Fragment size is too large.");
94 * Account for the EAP header (4), and the EAP-TLS header
95 * (6), as per Section 4.2 of RFC 2716. What's left is
96 * the maximum amount of data we read from a TLS buffer.
98 inst->fragment_size -= 10;
107 * Send an initial eap-tls request to the peer.
109 * Frame eap reply packet.
110 * len = header + type + tls_typedata
111 * tls_typedata = flags(Start (S) bit set, and no data)
113 * Once having received the peer's Identity, the EAP server MUST
114 * respond with an EAP-TLS/Start packet, which is an
115 * EAP-Request packet with EAP-Type=EAP-TLS, the Start (S) bit
116 * set, and no data. The EAP-TLS conversation will then begin,
117 * with the peer sending an EAP-Response packet with
118 * EAP-Type = EAP-TLS. The data field of that packet will
121 * Fragment length is Framed-MTU - 4.
123 * http://mail.frascone.com/pipermail/public/eap/2003-July/001426.html
125 static int eaptls_initiate(void *type_arg, EAP_HANDLER *handler)
129 fr_tls_server_conf_t *inst;
131 int client_cert = TRUE;
133 REQUEST *request = handler->request;
138 handler->finished = FALSE;
141 * If we're TTLS or PEAP, then do NOT require a client
144 * FIXME: This should be more configurable.
146 if (handler->eap_type != PW_EAP_TLS) {
147 vp = pairfind(handler->request->config_items,
148 PW_EAP_TLS_REQUIRE_CLIENT_CERT, 0);
152 client_cert = vp->vp_integer;
157 * Every new session is started only from EAP-TLS-START.
158 * Before Sending EAP-TLS-START, open a new SSL session.
159 * Create all the required data structures & store them
160 * in Opaque. So that we can use these data structures
161 * when we get the response
163 ssn = tls_new_session(inst, request, client_cert);
169 * Verify the peer certificate, if asked.
172 RDEBUG2("Requiring client certificate");
173 verify_mode = SSL_VERIFY_PEER;
174 verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
175 verify_mode |= SSL_VERIFY_CLIENT_ONCE;
177 SSL_set_verify(ssn->ssl, verify_mode, cbtls_verify);
180 * Create a structure for all the items required to be
181 * verified for each client and set that as opaque data
184 * NOTE: If we want to set each item sepearately then
185 * this index should be global.
187 SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_HANDLER, (void *)handler);
188 SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_CONF, (void *)inst);
189 SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_CERTS, (void *)&(handler->certs));
190 SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_IDENTITY, (void *)&(handler->identity));
191 #ifdef HAVE_OPENSSL_OCSP_H
192 SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_STORE, (void *)inst->ocsp_store);
195 handler->opaque = ((void *)ssn);
196 handler->free_opaque = session_free;
199 * Set up type-specific information.
201 switch (handler->eap_type) {
204 ssn->prf_label = "client EAP encryption";
208 ssn->prf_label = "ttls keying material";
212 * PEAP-specific breakage.
216 * As it is a poorly designed protocol, PEAP uses
217 * bits in the TLS header to indicate PEAP
218 * version numbers. For now, we only support
219 * PEAP version 0, so it doesn't matter too much.
220 * However, if we support later versions of PEAP,
221 * we will need this flag to indicate which
222 * version we're currently dealing with.
224 ssn->peap_flag = 0x00;
227 * PEAP version 0 requires 'include_length = no',
228 * so rather than hoping the user figures it out,
231 ssn->length_flag = 0;
233 ssn->prf_label = "client EAP encryption";
238 * TLS session initialization is over. Now handle TLS
239 * related handshaking or application data.
241 status = eaptls_start(handler->eap_ds, ssn->peap_flag);
242 RDEBUG2("Start returned %d", status);
247 * The next stage to process the packet.
249 handler->stage = AUTHENTICATE;
255 * Do authentication, by letting EAP-TLS do most of the work.
257 static int eaptls_authenticate(void *arg, EAP_HANDLER *handler)
259 fr_tls_status_t status;
260 tls_session_t *tls_session = (tls_session_t *) handler->opaque;
261 REQUEST *request = handler->request;
262 fr_tls_server_conf_t *inst = arg;
264 RDEBUG2("Authenticate");
266 status = eaptls_process(handler);
267 RDEBUG2("eaptls_process returned %d\n", status);
270 * EAP-TLS handshake was successful, return an
271 * EAP-TLS-Success packet here.
277 * The TLS code is still working on the TLS
278 * exchange, and it's a valid TLS request.
285 * Handshake is done, proceed with decoding tunneled
289 RDEBUG2("Received unexpected tunneled data after successful handshake.");
291 if ((debug_flag > 2) && fr_log_fp) {
293 unsigned int data_len;
294 unsigned char buffer[1024];
296 data_len = (tls_session->record_minus)(&tls_session->dirty_in,
297 buffer, sizeof(buffer));
298 log_debug(" Tunneled data (%u bytes)\n", data_len);
299 for (i = 0; i < data_len; i++) {
300 if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, " %x: ", i);
301 if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
303 fprintf(fr_log_fp, "%02x ", buffer[i]);
305 fprintf(fr_log_fp, "\n");
309 eaptls_fail(handler, 0);
314 * Anything else: fail.
316 * Also, remove the session from the cache so that
317 * the client can't re-use it.
320 tls_fail(tls_session);
326 * Success: Automatically return MPPE keys.
328 return eaptls_success(handler, 0);
332 * The module name should be the only globally exported symbol.
333 * That is, everything else should be 'static'.
335 EAP_TYPE rlm_eap_tls = {
337 eaptls_attach, /* attach */
338 eaptls_initiate, /* Start the initial request */
339 NULL, /* authorization */
340 eaptls_authenticate, /* authentication */
341 eaptls_detach /* detach */