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
27 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
29 #ifdef HAVE_OPENSSL_RAND_H
30 #include <openssl/rand.h>
33 #ifdef HAVE_OPENSSL_EVP_H
34 #include <openssl/evp.h>
37 #include "rlm_eap_tls.h"
39 #ifdef HAVE_SYS_STAT_H
43 static CONF_PARSER module_config[] = {
44 { "tls", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_tls_t, tls_conf_name), NULL },
46 { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_tls_t, virtual_server), NULL },
48 { NULL, -1, 0, NULL, NULL } /* end the list */
53 * Attach the EAP-TLS module.
55 static int eaptls_attach(CONF_SECTION *cs, void **instance)
60 * Parse the config file & get all the configured values
62 *instance = inst = talloc_zero(cs, rlm_eap_tls_t);
65 if (cf_section_parse(cs, inst, module_config) < 0) {
69 inst->tls_conf = eaptls_conf_parse(cs, "tls");
71 if (!inst->tls_conf) {
72 ERROR("rlm_eap_tls: Failed initializing SSL context");
81 * Send an initial eap-tls request to the peer, using the libeap functions.
83 static int eaptls_initiate(void *type_arg, eap_handler_t *handler)
88 REQUEST *request = handler->request;
93 handler->finished = false;
96 * EAP-TLS always requires a client certificate.
98 ssn = eaptls_session(handler, inst->tls_conf, true);
103 handler->opaque = ((void *)ssn);
106 * Set up type-specific information.
108 ssn->prf_label = "client EAP encryption";
111 * TLS session initialization is over. Now handle TLS
112 * related handshaking or application data.
114 status = eaptls_start(handler->eap_ds, ssn->peap_flag);
115 RDEBUG2("Start returned %d", status);
121 * The next stage to process the packet.
123 handler->stage = AUTHENTICATE;
129 * Do authentication, by letting EAP-TLS do most of the work.
131 static int CC_HINT(nonnull) mod_authenticate(void *type_arg, eap_handler_t *handler)
133 fr_tls_status_t status;
134 tls_session_t *tls_session = (tls_session_t *) handler->opaque;
135 REQUEST *request = handler->request;
140 RDEBUG2("Authenticate");
142 status = eaptls_process(handler);
143 RDEBUG2("eaptls_process returned %d\n", status);
146 * EAP-TLS handshake was successful, return an
147 * EAP-TLS-Success packet here.
149 * If a virtual server was configured, check that
150 * it accepts the certificates, too.
153 if (inst->virtual_server) {
157 /* create a fake request */
158 fake = request_alloc_fake(request);
159 rad_assert(!fake->packet->vps);
161 fake->packet->vps = paircopy(fake->packet, request->packet->vps);
163 /* set the virtual server to use */
164 if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
165 fake->server = vp->vp_strvalue;
167 fake->server = inst->virtual_server;
170 RDEBUG("Processing EAP-TLS Certificate check:");
171 rad_virtual_server(fake);
173 /* copy the reply vps back to our reply */
174 pairfilter(request->reply, &request->reply->vps,
175 &fake->reply->vps, 0, 0, TAG_ANY);
177 /* reject if virtual server didn't return accept */
178 if (fake->reply->code != PW_CODE_ACCESS_ACCEPT) {
179 RDEBUG2("Certificates were rejected by the virtual server");
181 eaptls_fail(handler, 0);
191 * The TLS code is still working on the TLS
192 * exchange, and it's a valid TLS request.
199 * Handshake is done, proceed with decoding tunneled
203 RDEBUG2("Received unexpected tunneled data after successful handshake");
205 if ((debug_flag > 2) && fr_log_fp) {
207 unsigned int data_len;
208 unsigned char buffer[1024];
210 data_len = (tls_session->record_minus)(&tls_session->dirty_in,
211 buffer, sizeof(buffer));
212 DEBUG(" Tunneled data (%u bytes)", data_len);
213 for (i = 0; i < data_len; i++) {
214 if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, " %x: ", i);
215 if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
217 fprintf(fr_log_fp, "%02x ", buffer[i]);
219 fprintf(fr_log_fp, "\n");
223 eaptls_fail(handler, 0);
228 * Anything else: fail.
230 * Also, remove the session from the cache so that
231 * the client can't re-use it.
234 tls_fail(tls_session);
240 * Success: Automatically return MPPE keys.
242 return eaptls_success(handler, 0);
246 * The module name should be the only globally exported symbol.
247 * That is, everything else should be 'static'.
249 rlm_eap_module_t rlm_eap_tls = {
251 eaptls_attach, /* attach */
252 eaptls_initiate, /* Start the initial request */
253 NULL, /* authorization */
254 mod_authenticate, /* authentication */