56ac645242090c5f69b4e0081978dd869163323b
[freeradius.git] / src / modules / rlm_eap / types / rlm_eap_tls / rlm_eap_tls.c
1 /*
2  * rlm_eap_tls.c  contains the interfaces that are called from eap
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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
19  *
20  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
21  * Copyright 2003  Alan DeKok <aland@freeradius.org>
22  * Copyright 2006  The FreeRADIUS server project
23  *
24  */
25
26 #include <freeradius-devel/ident.h>
27 RCSID("$Id$")
28
29 #include <freeradius-devel/autoconf.h>
30
31 #ifdef HAVE_OPENSSL_RAND_H
32 #include <openssl/rand.h>
33 #endif
34
35 #ifdef HAVE_OPENSSL_EVP_H
36 #include <openssl/evp.h>
37 #endif
38
39 #include "rlm_eap_tls.h"
40 #include "config.h"
41
42 #ifdef HAVE_SYS_STAT_H
43 #include <sys/stat.h>
44 #endif
45
46 /*
47  *      Detach the EAP-TLS module.
48  */
49 static int eaptls_detach(void *arg)
50 {
51         tls_server_conf_free(arg);
52         return 0;
53 }
54
55
56 /*
57  *      Attach the EAP-TLS module.
58  */
59 static int eaptls_attach(CONF_SECTION *cs, void **instance)
60 {
61         fr_tls_server_conf_t     *inst;
62
63         /*
64          *      Parse the config file & get all the configured values
65          */
66         inst = tls_server_conf_parse(cs);
67         if (!inst) {
68                 radlog(L_ERR, "rlm_eap_tls: Failed initializing SSL context");
69                 return -1;
70         }
71
72         /*
73          *      The EAP RFC's say 1020, but we're less picky.
74          */
75         if (inst->fragment_size < 100) {
76                 radlog(L_ERR, "rlm_eap_tls: Fragment size is too small.");
77                 eaptls_detach(inst);
78                 return -1;
79         }
80
81         /*
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.
86          */
87         if (inst->fragment_size > 4000) {
88                 radlog(L_ERR, "rlm_eap_tls: Fragment size is too large.");
89                 eaptls_detach(inst);
90                 return -1;
91         }
92
93         /*
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.
97          */
98         inst->fragment_size -= 10;
99
100         *instance = inst;
101
102         return 0;
103 }
104
105
106 /*
107  *      Send an initial eap-tls request to the peer.
108  *
109  *      Frame eap reply packet.
110  *      len = header + type + tls_typedata
111  *      tls_typedata = flags(Start (S) bit set, and no data)
112  *
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
119  *      be the TLS data.
120  *
121  *      Fragment length is Framed-MTU - 4.
122  *
123  *      http://mail.frascone.com/pipermail/public/eap/2003-July/001426.html
124  */
125 static int eaptls_initiate(void *type_arg, EAP_HANDLER *handler)
126 {
127         int             status;
128         tls_session_t   *ssn;
129         fr_tls_server_conf_t    *inst;
130         VALUE_PAIR      *vp;
131         int             client_cert = TRUE;
132         int             verify_mode = 0;
133         REQUEST         *request = handler->request;
134
135         inst = type_arg;
136
137         handler->tls = TRUE;
138         handler->finished = FALSE;
139
140         /*
141          *      If we're TTLS or PEAP, then do NOT require a client
142          *      certificate.
143          *
144          *      FIXME: This should be more configurable.
145          */
146         if (handler->eap_type != PW_EAP_TLS) {
147                 vp = pairfind(handler->request->config_items,
148                               PW_EAP_TLS_REQUIRE_CLIENT_CERT, 0);
149                 if (!vp) {
150                         client_cert = FALSE;
151                 } else {
152                         client_cert = vp->vp_integer;
153                 }
154         }
155
156         /*
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
162          */
163         ssn = tls_new_session(inst, request, client_cert);
164         if (!ssn) {
165                 return 0;
166         }
167
168         /*
169          *      Verify the peer certificate, if asked.
170          */
171         if (client_cert) {
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;
176         }
177         SSL_set_verify(ssn->ssl, verify_mode, cbtls_verify);
178
179         /*
180          *      Create a structure for all the items required to be
181          *      verified for each client and set that as opaque data
182          *      structure.
183          *
184          *      NOTE: If we want to set each item sepearately then
185          *      this index should be global.
186          */
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);
193 #endif
194
195         handler->opaque = ((void *)ssn);
196         handler->free_opaque = session_free;
197
198         /*
199          *      Set up type-specific information.
200          */
201         switch (handler->eap_type) {
202         case PW_EAP_TLS:
203         default:
204                 ssn->prf_label = "client EAP encryption";
205                 break;
206
207         case PW_EAP_TTLS:
208                 ssn->prf_label = "ttls keying material";
209                 break;
210
211                 /*
212                  *      PEAP-specific breakage.
213                  */
214         case PW_EAP_PEAP:
215                 /*
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.
223                  */
224                 ssn->peap_flag = 0x00;
225
226                 /*
227                  *      PEAP version 0 requires 'include_length = no',
228                  *      so rather than hoping the user figures it out,
229                  *      we force it here.
230                  */
231                 ssn->length_flag = 0;
232
233                 ssn->prf_label = "client EAP encryption";
234                 break;
235         }
236
237         /*
238          *      TLS session initialization is over.  Now handle TLS
239          *      related handshaking or application data.
240          */
241         status = eaptls_start(handler->eap_ds, ssn->peap_flag);
242         RDEBUG2("Start returned %d", status);
243         if (status == 0)
244                 return 0;
245
246         /*
247          *      The next stage to process the packet.
248          */
249         handler->stage = AUTHENTICATE;
250
251         return 1;
252 }
253
254 /*
255  *      Do authentication, by letting EAP-TLS do most of the work.
256  */
257 static int eaptls_authenticate(UNUSED void *arg, EAP_HANDLER *handler)
258 {
259         fr_tls_status_t status;
260         tls_session_t *tls_session = (tls_session_t *) handler->opaque;
261         REQUEST *request = handler->request;
262
263         RDEBUG2("Authenticate");
264
265         status = eaptls_process(handler);
266         RDEBUG2("eaptls_process returned %d\n", status);
267         switch (status) {
268                 /*
269                  *      EAP-TLS handshake was successful, return an
270                  *      EAP-TLS-Success packet here.
271                  */
272         case FR_TLS_SUCCESS:
273                 break;
274
275                 /*
276                  *      The TLS code is still working on the TLS
277                  *      exchange, and it's a valid TLS request.
278                  *      do nothing.
279                  */
280         case FR_TLS_HANDLED:
281                 return 1;
282
283                 /*
284                  *      Handshake is done, proceed with decoding tunneled
285                  *      data.
286                  */
287         case FR_TLS_OK:
288                 RDEBUG2("Received unexpected tunneled data after successful handshake.");
289 #ifndef NDEBUG
290                 if ((debug_flag > 2) && fr_log_fp) {
291                         unsigned int i;
292                         unsigned int data_len;
293                         unsigned char buffer[1024];
294
295                         data_len = (tls_session->record_minus)(&tls_session->dirty_in,
296                                                 buffer, sizeof(buffer));
297                         log_debug("  Tunneled data (%u bytes)\n", data_len);
298                         for (i = 0; i < data_len; i++) {
299                                 if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "  %x: ", i);
300                                 if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
301
302                                 fprintf(fr_log_fp, "%02x ", buffer[i]);
303                         }
304                         fprintf(fr_log_fp, "\n");
305                 }
306 #endif
307
308                 eaptls_fail(handler, 0);
309                 return 0;
310                 break;
311
312                 /*
313                  *      Anything else: fail.
314                  *
315                  *      Also, remove the session from the cache so that
316                  *      the client can't re-use it.
317                  */
318         default:
319                 tls_fail(tls_session);
320
321                 return 0;
322         }
323
324         /*
325          *      Success: Automatically return MPPE keys.
326          */
327         return eaptls_success(handler, 0);
328 }
329
330 /*
331  *      The module name should be the only globally exported symbol.
332  *      That is, everything else should be 'static'.
333  */
334 EAP_TYPE rlm_eap_tls = {
335         "eap_tls",
336         eaptls_attach,                  /* attach */
337         eaptls_initiate,                /* Start the initial request */
338         NULL,                           /* authorization */
339         eaptls_authenticate,            /* authentication */
340         eaptls_detach                   /* detach */
341 };