The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_eap_ttls.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: 38951a61642261902a8148b916367b648fe5fcf9 $
19 * @file rlm_eap_ttls.c
20 * @brief EAP-TTLS as defined by RFC 5281
21 *
22 * @copyright 2003 Alan DeKok (aland@freeradius.org)
23 * @copyright 2006 The FreeRADIUS server project
24 */
25
26RCSID("$Id: 38951a61642261902a8148b916367b648fe5fcf9 $")
27USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
28
29#include <freeradius-devel/eap/tls.h>
30#include "eap_ttls.h"
31
32typedef struct {
33 SSL_CTX *ssl_ctx; //!< Thread local SSL_CTX.
35
36typedef struct {
37 /*
38 * TLS configuration
39 */
40 char const *tls_conf_name;
41 fr_tls_conf_t *tls_conf;
42
43 /*
44 * RFC 5281 (TTLS) says that the length field MUST NOT be
45 * in fragments after the first one. However, we've done
46 * it that way for years, and no one has complained.
47 *
48 * In the interests of allowing the server to follow the
49 * RFC, we add the option here. If set to "no", it sends
50 * the length field in ONLY the first fragment.
51 */
53
54 /*
55 * Virtual server for inner tunnel session.
56 */
57 char const *virtual_server;
59
60 /*
61 * Do we do require a client cert?
62 */
65
66
68 { FR_CONF_OFFSET("tls", rlm_eap_ttls_t, tls_conf_name) },
69 { FR_CONF_DEPRECATED("copy_request_to_tunnel", rlm_eap_ttls_t, NULL), .dflt = "no" },
70 { FR_CONF_DEPRECATED("use_tunneled_reply", rlm_eap_ttls_t, NULL), .dflt = "no" },
71 { FR_CONF_OFFSET_FLAGS("virtual_server", CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, rlm_eap_ttls_t, virtual_server) },
72 { FR_CONF_OFFSET("include_length", rlm_eap_ttls_t, include_length), .dflt = "yes" },
73 { FR_CONF_OFFSET("require_client_cert", rlm_eap_ttls_t, req_client_cert), .dflt = "no" },
75};
76
78static fr_dict_t const *dict_radius;
79
82 { .out = &dict_freeradius, .proto = "freeradius" },
83 { .out = &dict_radius, .proto = "radius" },
84 { NULL }
85};
86
88
98
101 { .out = &attr_eap_tls_require_client_cert, .name = "EAP-TLS-Require-Client-Cert", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
102
103 { .out = &attr_chap_challenge, .name = "CHAP-Challenge", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
104 { .out = &attr_eap_message, .name = "EAP-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
105 { .out = &attr_ms_chap_challenge, .name = "Vendor-Specific.Microsoft.CHAP-Challenge", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
106 { .out = &attr_ms_chap2_success, .name = "Vendor-Specific.Microsoft.CHAP2-Success", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
107 { .out = &attr_reply_message, .name = "Reply-Message", .type = FR_TYPE_STRING, .dict = &dict_radius },
108 { .out = &attr_eap_channel_binding_message, .name = "Vendor-Specific.UKERNA.EAP-Channel-Binding-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
109 { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius },
110 { .out = &attr_user_password, .name = "User-Password", .type = FR_TYPE_STRING, .dict = &dict_radius },
111 { .out = &attr_vendor_specific, .name = "Vendor-Specific", .type = FR_TYPE_VSA, .dict = &dict_radius },
112 { NULL }
113};
114
115/*
116 * Allocate the TTLS per-session data
117 */
118static ttls_tunnel_t *ttls_alloc(TALLOC_CTX *ctx, rlm_eap_ttls_t *inst)
119{
120 ttls_tunnel_t *t;
121
122 t = talloc_zero(ctx, ttls_tunnel_t);
123 t->server_cs = inst->server_cs;
124
125 return t;
126}
127
129{
130 eap_session_t *eap_session = talloc_get_type_abort(mctx->rctx, eap_session_t);
131 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
132 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
133
134 ttls_tunnel_t *tunnel = talloc_get_type_abort(tls_session->opaque, ttls_tunnel_t);
135
136 if ((eap_tls_session->state == EAP_TLS_INVALID) || (eap_tls_session->state == EAP_TLS_FAIL)) {
137 REDEBUG("[eap-tls process] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
138 } else {
139 RDEBUG2("[eap-tls process] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
140 }
141
142 switch (eap_tls_session->state) {
143 /*
144 * EAP-TLS handshake was successful, tell the
145 * client to keep talking.
146 *
147 * If this was EAP-TLS, we would just return
148 * an EAP-TLS-Success packet here.
149 */
151 if (SSL_session_reused(tls_session->ssl)) {
152 RDEBUG2("Skipping Phase2 due to session resumption");
153 return eap_ttls_success(p_result, request, eap_session);
154 }
155
156 if (tunnel && tunnel->authenticated) return eap_ttls_success(p_result, request, eap_session);
157
158 eap_tls_request(request, eap_session);
160
161 /*
162 * The TLS code is still working on the TLS
163 * exchange, and it's a valid TLS request.
164 * do nothing.
165 */
166 case EAP_TLS_HANDLED:
168
169 /*
170 * Handshake is done, proceed with decoding tunneled
171 * data.
172 */
174 break;
175
176 /*
177 * Anything else: fail.
178 */
179 default:
181 }
182
183 /*
184 * Session is established, proceed with decoding
185 * tunneled data.
186 */
187 RDEBUG2("Session established. Decoding Diameter attributes");
188
189 /*
190 * Process the TTLS portion of the request.
191 */
192 return eap_ttls_process(request, eap_session, tls_session);
193}
194
195/*
196 * Do authentication, by letting EAP-TLS do most of the work.
197 */
199 request_t *request)
200{
201 eap_session_t *eap_session = eap_session_get(request->parent);
202
203 /*
204 * Setup the resumption frame to process the result
205 */
206 (void)unlang_module_yield(request, mod_handshake_resume, NULL, 0, eap_session);
207
208 /*
209 * Process TLS layer until done.
210 */
211 return eap_tls_process(request, eap_session);
212}
213
214/*
215 * Send an initial eap-tls request to the peer, using the libeap functions.
216 */
217static unlang_action_t mod_session_init(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
218{
219 rlm_eap_ttls_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_ttls_t);
220 rlm_eap_ttls_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_ttls_thread_t);
221 eap_session_t *eap_session = eap_session_get(request->parent);
222
223 eap_tls_session_t *eap_tls_session;
224 fr_tls_session_t *tls_session;
225 fr_pair_t *vp;
226 bool client_cert;
227
228 eap_session->tls = true;
229
230 /*
231 * EAP-TLS-Require-Client-Cert attribute will override
232 * the require_client_cert configuration option.
233 */
234 vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_eap_tls_require_client_cert);
235 if (vp) {
236 client_cert = vp->vp_uint32 ? true : false;
237 } else {
238 client_cert = inst->req_client_cert;
239 }
240
241 eap_session->opaque = eap_tls_session = eap_tls_session_init(request, eap_session, t->ssl_ctx, client_cert);
242 if (!eap_tls_session) RETURN_MODULE_FAIL;
243 tls_session = eap_tls_session->tls_session;
244
245 eap_tls_session->include_length = inst->include_length;
246
247 /*
248 * TLS session initialization is over. Now handle TLS
249 * related handshaking or application data.
250 */
251 if (eap_tls_start(request, eap_session) < 0) {
252 talloc_free(eap_tls_session);
254 }
255
256 tls_session->opaque = ttls_alloc(tls_session, inst);
257
258 eap_session->process = mod_handshake_process;
259
261}
262
264{
265 rlm_eap_ttls_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_ttls_t);
266 rlm_eap_ttls_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_ttls_thread_t);
267
268 t->ssl_ctx = fr_tls_ctx_alloc(inst->tls_conf, false);
269 if (!t->ssl_ctx) return -1;
270
271 return 0;
272}
273
275{
276 rlm_eap_ttls_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_ttls_thread_t);
277
278 if (likely(t->ssl_ctx != NULL)) SSL_CTX_free(t->ssl_ctx);
279 t->ssl_ctx = NULL;
280
281 return 0;
282}
283
284/*
285 * Attach the module.
286 */
287static int mod_instantiate(module_inst_ctx_t const *mctx)
288{
289 rlm_eap_ttls_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_ttls_t);
290 CONF_SECTION *conf = mctx->mi->conf;
291 virtual_server_t const *virtual_server = virtual_server_find(inst->virtual_server);
292
293 if (!virtual_server) {
294 cf_log_err_by_child(conf, "virtual_server", "Unknown virtual server '%s'", inst->virtual_server);
295 return -1;
296 }
297
298 inst->server_cs = virtual_server_cs(virtual_server);
299 if (!inst->server_cs) {
300 cf_log_err_by_child(conf, "virtual_server", "Virtual server \"%s\" missing", inst->virtual_server);
301 return -1;
302 }
303
304 /*
305 * Read tls configuration, either from group given by 'tls'
306 * option, or from the eap-tls configuration.
307 */
308 inst->tls_conf = eap_tls_conf_parse(conf, "tls");
309 if (!inst->tls_conf) {
310 cf_log_err(conf, "Failed initializing SSL context");
311 return -1;
312 }
313
314 return 0;
315}
316
317/*
318 * The module name should be the only globally exported symbol.
319 * That is, everything else should be 'static'.
320 */
323 .common = {
324 .magic = MODULE_MAGIC_INIT,
325 .name = "eap_ttls",
326
327 .inst_size = sizeof(rlm_eap_ttls_t),
329 .instantiate = mod_instantiate, /* Create new submodule instance */
330
331 .thread_inst_size = sizeof(rlm_eap_ttls_thread_t),
332 .thread_instantiate = mod_thread_instantiate,
333 .thread_detach = mod_thread_detach,
334 },
335 .provides = { FR_EAP_METHOD_TTLS },
336 .session_init = mod_session_init, /* Initialise a new EAP session */
337};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
#define USES_APPLE_DEPRECATED_API
Definition build.h:470
#define RCSID(id)
Definition build.h:483
#define UNUSED
Definition build.h:315
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
Definition cf_parse.h:398
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:268
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:256
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:418
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition cf_parse.h:433
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_log_err_by_child(_parent, _child, _fmt,...)
Log an error message against a specified child.
Definition cf_util.h:316
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:268
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
@ FR_EAP_METHOD_TTLS
Definition types.h:66
Declarations for EAP-TTLS as defined by RFC 5281.
unlang_action_t eap_ttls_process(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
Definition ttls.c:634
CONF_SECTION * server_cs
Definition eap_ttls.h:46
bool authenticated
Definition eap_ttls.h:45
unlang_action_t eap_ttls_success(rlm_rcode_t *p_result, request_t *request, eap_session_t *eap_session)
Definition ttls.c:595
static eap_session_t * eap_session_get(request_t *request)
Definition session.h:82
void * opaque
Opaque data used by EAP methods.
Definition session.h:62
bool tls
Whether EAP method uses TLS.
Definition session.h:70
module_method_t process
Callback that should be used to process the next round.
Definition session.h:64
Tracks the progress of a single session of any EAP method.
Definition session.h:40
talloc_free(reap)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_OCTETS
Raw octets.
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
void * thread
Thread specific instance data.
Definition module_ctx.h:43
void * rctx
Resume ctx that a module previously set.
Definition module_ctx.h:45
void * thread
Thread instance data.
Definition module_ctx.h:67
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:64
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
Temporary structure to hold arguments for thread_instantiation calls.
Definition module_ctx.h:63
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:693
static const conf_parser_t config[]
Definition base.c:183
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG2(fmt,...)
Definition radclient.h:54
static rs_t * conf
Definition radsniff.c:53
#define RETURN_MODULE_HANDLED
Definition rcode.h:58
#define RETURN_MODULE_OK
Definition rcode.h:57
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
static ttls_tunnel_t * ttls_alloc(TALLOC_CTX *ctx, rlm_eap_ttls_t *inst)
fr_dict_attr_t const * attr_user_password
static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
char const * tls_conf_name
fr_dict_attr_t const * attr_eap_message
static unlang_action_t mod_handshake_process(UNUSED rlm_rcode_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request)
fr_dict_attr_t const * attr_eap_channel_binding_message
static fr_dict_t const * dict_freeradius
fr_dict_attr_t const * attr_eap_tls_require_client_cert
SSL_CTX * ssl_ctx
Thread local SSL_CTX.
fr_dict_attr_t const * attr_ms_chap2_success
static fr_dict_t const * dict_radius
fr_dict_attr_t const * attr_ms_chap_challenge
fr_dict_attr_t const * attr_chap_challenge
fr_dict_attr_t const * attr_vendor_specific
fr_dict_attr_t const * attr_reply_message
char const * virtual_server
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
fr_tls_conf_t * tls_conf
CONF_SECTION * server_cs
fr_dict_attr_t const * attr_user_name
static conf_parser_t submodule_config[]
fr_dict_attr_autoload_t rlm_eap_ttls_dict_attr[]
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static int mod_instantiate(module_inst_ctx_t const *mctx)
fr_dict_autoload_t rlm_eap_ttls_dict[]
rlm_eap_submodule_t rlm_eap_ttls
static unlang_action_t mod_session_init(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1310
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:329
size_t inst_size
Size of the module's instance data.
Definition module.h:203
void * data
Module's instance data.
Definition module.h:271
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition module.c:419
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
module_t common
Common fields provided by all modules.
Definition submodule.h:50
Interface exported by EAP submodules.
Definition submodule.h:49
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
eap_tls_session_t * eap_tls_session_init(request_t *request, eap_session_t *eap_session, SSL_CTX *ssl_ctx, bool client_cert)
Create a new fr_tls_session_t associated with an eap_session_t.
Definition tls.c:1131
int eap_tls_start(request_t *request, eap_session_t *eap_session)
Send an initial EAP-TLS request to the peer.
Definition tls.c:239
int eap_tls_request(request_t *request, eap_session_t *eap_session)
Frames the OpenSSL data that needs to be sent to the client in an EAP-Request.
Definition tls.c:372
USES_APPLE_DEPRECATED_API fr_table_num_ordered_t const eap_tls_status_table[]
Definition tls.c:80
fr_tls_conf_t * eap_tls_conf_parse(CONF_SECTION *cs, char const *attr)
Parse TLS configuration.
Definition tls.c:1264
unlang_action_t eap_tls_process(request_t *request, eap_session_t *eap_session)
Process an EAP TLS request.
Definition tls.c:963
eap_tls_status_t state
The state of the EAP-TLS session.
Definition tls.h:127
@ EAP_TLS_INVALID
Invalid, don't reply.
Definition tls.h:91
@ EAP_TLS_HANDLED
TLS code has handled it.
Definition tls.h:94
@ EAP_TLS_RECORD_RECV_COMPLETE
Received final fragment of a record.
Definition tls.h:111
@ EAP_TLS_FAIL
Fail, send fail.
Definition tls.h:93
@ EAP_TLS_ESTABLISHED
Session established, send success (or start phase2).
Definition tls.h:92
fr_tls_session_t * tls_session
TLS session used to authenticate peer or tunnel sensitive data.
Definition tls.h:129
bool include_length
A flag to include length in every TLS Data/Alert packet.
Definition tls.h:138
Tracks the state of an EAP-TLS session.
Definition tls.h:126
virtual_server_t const * virtual_server_find(char const *name)
Return virtual server matching the specified name.
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.