All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rlm_eap_ttls.c
Go to the documentation of this file.
1 /*
2  * rlm_eap_ttls.c contains the interfaces that are called from eap
3  *
4  * Version: $Id: 0385c516187f4fac97c55749a98a05afbee5bb67 $
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 2003 Alan DeKok <aland@freeradius.org>
21  * Copyright 2006 The FreeRADIUS server project
22  */
23 
24 RCSID("$Id: 0385c516187f4fac97c55749a98a05afbee5bb67 $")
25 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
26 
27 #include "eap_ttls.h"
28 
29 typedef struct rlm_eap_ttls_t {
30  /*
31  * TLS configuration
32  */
33  char const *tls_conf_name;
34  fr_tls_server_conf_t *tls_conf;
35 
36  /*
37  * Default tunneled EAP type
38  */
39  char const *default_method_name;
41 
42  /*
43  * Use the reply attributes from the tunneled session in
44  * the non-tunneled reply to the client.
45  */
47 
48  /*
49  * Use SOME of the request attributes from outside of the
50  * tunneled session in the tunneled request
51  */
53 
54  /*
55  * RFC 5281 (TTLS) says that the length field MUST NOT be
56  * in fragments after the first one. However, we've done
57  * it that way for years, and no one has complained.
58  *
59  * In the interests of allowing the server to follow the
60  * RFC, we add the option here. If set to "no", it sends
61  * the length field in ONLY the first fragment.
62  */
64 
65  /*
66  * Virtual server for inner tunnel session.
67  */
68  char const *virtual_server;
69 
70  /*
71  * Do we do require a client cert?
72  */
75 
76 
78  { FR_CONF_OFFSET("tls", PW_TYPE_STRING, rlm_eap_ttls_t, tls_conf_name) },
79  { FR_CONF_OFFSET("default_eap_type", PW_TYPE_STRING, rlm_eap_ttls_t, default_method_name), .dflt = "md5" },
80  { FR_CONF_OFFSET("copy_request_to_tunnel", PW_TYPE_BOOLEAN, rlm_eap_ttls_t, copy_request_to_tunnel), .dflt = "no" },
81  { FR_CONF_OFFSET("use_tunneled_reply", PW_TYPE_BOOLEAN, rlm_eap_ttls_t, use_tunneled_reply), .dflt = "no" },
82  { FR_CONF_OFFSET("virtual_server", PW_TYPE_STRING, rlm_eap_ttls_t, virtual_server) },
83  { FR_CONF_OFFSET("include_length", PW_TYPE_BOOLEAN, rlm_eap_ttls_t, include_length), .dflt = "yes" },
84  { FR_CONF_OFFSET("require_client_cert", PW_TYPE_BOOLEAN, rlm_eap_ttls_t, req_client_cert), .dflt = "no" },
86 };
87 
88 
89 /*
90  * Attach the module.
91  */
92 static int mod_instantiate(CONF_SECTION *cs, void **instance)
93 {
95 
96  *instance = inst = talloc_zero(cs, rlm_eap_ttls_t);
97  if (!inst) return -1;
98 
99  /*
100  * Parse the configuration attributes.
101  */
102  if (cf_section_parse(cs, inst, module_config) < 0) {
103  return -1;
104  }
105 
106  /*
107  * Convert the name to an integer, to make it easier to
108  * handle.
109  */
111  if (inst->default_method < 0) {
112  ERROR("rlm_eap_ttls: Unknown EAP type %s",
113  inst->default_method_name);
114  return -1;
115  }
116 
117  /*
118  * Read tls configuration, either from group given by 'tls'
119  * option, or from the eap-tls configuration.
120  */
121  inst->tls_conf = eap_tls_conf_parse(cs, "tls");
122 
123  if (!inst->tls_conf) {
124  ERROR("rlm_eap_ttls: Failed initializing SSL context");
125  return -1;
126  }
127 
128  return 0;
129 }
130 
131 /*
132  * Allocate the TTLS per-session data
133  */
134 static ttls_tunnel_t *ttls_alloc(TALLOC_CTX *ctx, rlm_eap_ttls_t *inst)
135 {
136  ttls_tunnel_t *t;
137 
138  t = talloc_zero(ctx, ttls_tunnel_t);
139 
140  t->default_method = inst->default_method;
143  t->virtual_server = inst->virtual_server;
144  return t;
145 }
146 
147 static int CC_HINT(nonnull) mod_process(void *instance, eap_session_t *eap_session);
148 
149 /*
150  * Send an initial eap-tls request to the peer, using the libeap functions.
151  */
152 static int mod_session_init(void *type_arg, eap_session_t *eap_session)
153 {
154  tls_session_t *tls_session;
156  VALUE_PAIR *vp;
157  bool client_cert;
158 
159  inst = type_arg;
160 
161  eap_session->tls = true;
162 
163  /*
164  * EAP-TLS-Require-Client-Cert attribute will override
165  * the require_client_cert configuration option.
166  */
167  vp = fr_pair_find_by_num(eap_session->request->config, 0, PW_EAP_TLS_REQUIRE_CLIENT_CERT, TAG_ANY);
168  if (vp) {
169  client_cert = vp->vp_integer ? true : false;
170  } else {
171  client_cert = inst->req_client_cert;
172  }
173 
174  tls_session = eap_tls_session_init(eap_session, inst->tls_conf, client_cert);
175  if (!tls_session) return 0;
176 
177  eap_session->opaque = ((void *)tls_session);
178 
179  /*
180  * Set up type-specific information.
181  */
182  tls_session->prf_label = "ttls keying material";
183 
184  /*
185  * TLS session initialization is over. Now handle TLS
186  * related handshaking or application data.
187  */
188  if (eap_tls_start(eap_session) < 0) {
189  talloc_free(tls_session);
190  return 0;
191  }
192 
193  eap_session->process = mod_process;
194 
195  return 1;
196 }
197 
198 
199 /*
200  * Do authentication, by letting EAP-TLS do most of the work.
201  */
202 static int mod_process(void *arg, eap_session_t *eap_session)
203 {
204  int rcode;
205  fr_tls_status_t status;
207  tls_session_t *tls_session = (tls_session_t *) eap_session->opaque;
208  ttls_tunnel_t *t = (ttls_tunnel_t *) tls_session->opaque;
209  REQUEST *request = eap_session->request;
210 
211  RDEBUG2("Authenticate");
212 
213  tls_session->length_flag = inst->include_length;
214 
215  /*
216  * Process TLS layer until done.
217  */
218  status = eap_tls_process(eap_session);
219  if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
220  REDEBUG("[eap-tls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
221  } else {
222  RDEBUG2("[eap-tls process] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
223  }
224 
225  switch (status) {
226  /*
227  * EAP-TLS handshake was successful, tell the
228  * client to keep talking.
229  *
230  * If this was EAP-TLS, we would just return
231  * an EAP-TLS-Success packet here.
232  */
233  case FR_TLS_SUCCESS:
234  if (SSL_session_reused(tls_session->ssl)) {
235  RDEBUG("Skipping Phase2 due to session resumption");
236  goto do_keys;
237  }
238 
239  if (t && t->authenticated) {
240  if (t->accept_vps) {
241  RDEBUG2("Using saved attributes from the original Access-Accept");
242  rdebug_pair_list(L_DBG_LVL_2, request, t->accept_vps, NULL);
244  &eap_session->request->reply->vps, &t->accept_vps, 0, 0,
245  TAG_ANY);
246  } else if (t->use_tunneled_reply) {
247  RDEBUG2("No saved attributes in the original Access-Accept");
248  }
249 
250  do_keys:
251  /*
252  * Success: Automatically return MPPE keys.
253  */
254  if (eap_tls_success(eap_session) < 0) return 0;
255  return 1;
256  } else {
257  eap_tls_request(eap_session);
258  }
259  return 1;
260 
261  /*
262  * The TLS code is still working on the TLS
263  * exchange, and it's a valid TLS request.
264  * do nothing.
265  */
266  case FR_TLS_HANDLED:
267  return 1;
268 
269  /*
270  * Handshake is done, proceed with decoding tunneled
271  * data.
272  */
273  case FR_TLS_RECORD_COMPLETE:
274  break;
275 
276  /*
277  * Anything else: fail.
278  */
279  default:
280  return 0;
281  }
282 
283  /*
284  * Session is established, proceed with decoding
285  * tunneled data.
286  */
287  RDEBUG2("Session established. Proceeding to decode tunneled attributes");
288 
289  /*
290  * We may need TTLS data associated with the session, so
291  * allocate it here, if it wasn't already alloacted.
292  */
293  if (!tls_session->opaque) tls_session->opaque = ttls_alloc(tls_session, inst);
294 
295  /*
296  * Process the TTLS portion of the request.
297  */
298  rcode = eap_ttls_process(eap_session, tls_session);
299  switch (rcode) {
301  eap_tls_fail(eap_session);
302  return 0;
303 
304  /*
305  * Access-Challenge, continue tunneled conversation.
306  */
308  eap_tls_request(eap_session);
309  return 1;
310 
311  /*
312  * Success: Automatically return MPPE keys.
313  */
315  if (eap_tls_success(eap_session) < 0) return 0;
316  return 1;
317 
318  /*
319  * No response packet, MUST be proxying it.
320  * The main EAP module will take care of discovering
321  * that the request now has a "proxy" packet, and
322  * will proxy it, rather than returning an EAP packet.
323  */
325 #ifdef WITH_PROXY
326  rad_assert(eap_session->request->proxy != NULL);
327 #endif
328  return 1;
329 
330  default:
331  break;
332  }
333 
334  /*
335  * Something we don't understand: Reject it.
336  */
337  eap_tls_fail(eap_session);
338  return 0;
339 }
340 
341 /*
342  * The module name should be the only globally exported symbol.
343  * That is, everything else should be 'static'.
344  */
346 rlm_eap_module_t rlm_eap_ttls = {
347  .name = "eap_ttls",
348  .instantiate = mod_instantiate, /* Create new submodule instance */
349  .session_init = mod_session_init, /* Initialise a new EAP session */
350  .process = mod_process /* Process next round of EAP method */
351 };
bool use_tunneled_reply
Definition: eap_ttls.h:37
bool copy_request_to_tunnel
Definition: eap_ttls.h:36
2nd highest priority debug messages (-xx | -X).
Definition: log.h:52
static int mod_instantiate(CONF_SECTION *cs, void **instance)
Definition: rlm_eap_ttls.c:92
RFC2865 - Access-Challenge.
Definition: radius.h:102
bool use_tunneled_reply
Definition: rlm_eap_ttls.c:46
PW_CODE eap_ttls_process(eap_session_t *eap_session, tls_session_t *tls_session) CC_HINT(nonnull)
Definition: ttls.c:929
void fr_pair_list_mcopy_by_num(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from, unsigned int vendor, unsigned int attr, int8_t tag)
Copy / delete matching pairs between VALUE_PAIR lists.
Definition: pair.c:1823
char const * virtual_server
Definition: eap_ttls.h:38
int default_method
Definition: eap_ttls.h:35
eap_type_t eap_name2type(char const *name)
Return an EAP-Type for a particular name.
Definition: eapcommon.c:88
bool req_client_cert
Definition: rlm_eap_ttls.c:73
char const * tls_conf_name
Definition: rlm_eap_ttls.c:33
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
#define CONF_PARSER_TERMINATOR
Definition: conffile.h:289
#define inst
void * opaque
Opaque data used by EAP methods.
Definition: eap.h:80
Defines a CONF_PAIR to C data type mapping.
Definition: conffile.h:267
REQUEST * request
Request that contains the response we're processing.
Definition: eap.h:71
static int mod_session_init(void *instance, eap_session_t *eap_session)
Definition: rlm_eap_gtc.c:89
RADIUS_PACKET * proxy
Outgoing request to proxy server.
Definition: radiusd.h:237
RFC2865 - Access-Reject.
Definition: radius.h:94
#define rad_assert(expr)
Definition: rad_assert.h:38
static int CC_HINT(nonnull)
Definition: rlm_eap_ttls.c:147
rlm_eap_module_t rlm_eap_ttls
Definition: rlm_eap_ttls.c:346
char const * default_method_name
Definition: rlm_eap_ttls.c:39
int eap_tls_success(eap_session_t *eap_session)
Send an EAP-TLS success.
Definition: eap_tls.c:211
Tracks the progress of a single session of any EAP method.
Definition: eap.h:60
int cf_section_parse(CONF_SECTION *, void *base, CONF_PARSER const *variables)
Parse a configuration section into user-supplied variables.
Definition: conffile.c:2234
RFC2865 - Access-Accept.
Definition: radius.h:93
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
RADIUS_PACKET * reply
Outgoing response.
Definition: radiusd.h:225
fr_tls_status_t eap_tls_process(eap_session_t *eap_session)
Process an EAP TLS request.
Definition: eap_tls.c:708
static int mod_process(void *arg, eap_session_t *eap_session)
Definition: rlm_eap_ttls.c:202
A truth value.
Definition: radius.h:56
char const * name
The name of the sub-module (without rlm_ prefix).
Definition: eap.h:96
void rdebug_pair_list(log_lvl_t level, REQUEST *, VALUE_PAIR *, char const *)
Print a list of VALUE_PAIRs.
Definition: pair.c:757
USES_APPLE_DEPRECATED_API struct rlm_eap_ttls_t rlm_eap_ttls_t
#define RDEBUG2(fmt,...)
Definition: log.h:244
tls_session_t * eap_tls_session_init(eap_session_t *eap_session, fr_tls_server_conf_t *tls_conf, bool client_cert)
Create a new tls_session_t associated with an eap_session_t.
Definition: eap_tls.c:844
bool copy_request_to_tunnel
Definition: rlm_eap_ttls.c:52
#define TAG_ANY
Definition: pair.h:191
Interface to call EAP sub mdoules.
Definition: eap.h:95
#define FR_CONF_OFFSET(_n, _t, _s, _f)
Definition: conffile.h:168
RFC2865/RFC5997 - Status Server (response)
Definition: radius.h:104
#define REDEBUG(fmt,...)
Definition: log.h:254
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
Definition: pair.c:639
int eap_tls_fail(eap_session_t *eap_session)
Send an EAP-TLS failure.
Definition: eap_tls.c:254
static CONF_PARSER module_config[]
Definition: rlm_eap_ttls.c:77
fr_tls_server_conf_t * tls_conf
Definition: rlm_eap_ttls.c:34
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
Definition: token.c:506
static ttls_tunnel_t * ttls_alloc(TALLOC_CTX *ctx, rlm_eap_ttls_t *inst)
Definition: rlm_eap_ttls.c:134
fr_tls_server_conf_t * eap_tls_conf_parse(CONF_SECTION *cs, char const *attr)
Parse TLS configuration.
Definition: eap_tls.c:891
String of printable characters.
Definition: radius.h:33
#define RCSID(id)
Definition: build.h:135
int eap_tls_request(eap_session_t *eap_session)
Frames the OpenSSL data that needs to be sent to the client in an EAP-Request.
Definition: eap_tls.c:299
int eap_tls_start(eap_session_t *eap_session)
Send an initial EAP-TLS request to the peer.
Definition: eap_tls.c:192
#define RDEBUG(fmt,...)
Definition: log.h:243
char const * virtual_server
Definition: rlm_eap_ttls.c:68
#define ERROR(fmt,...)
Definition: log.h:145
#define USES_APPLE_DEPRECATED_API
Definition: build.h:122