The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_eap_peap.c
Go to the documentation of this file.
1/*
2 * rlm_eap_peap.c contains the interfaces that are called from eap
3 *
4 * Version: $Id: 9fbe5cd673e6a19fc2b74d6de44fd780343e6657 $
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 */
23RCSID("$Id: 9fbe5cd673e6a19fc2b74d6de44fd780343e6657 $")
24
25#include <freeradius-devel/eap/tls.h>
26#include "eap_peap.h"
27
28typedef struct {
29 SSL_CTX *ssl_ctx; //!< Thread local SSL_CTX.
31
32typedef struct {
33 char const *tls_conf_name; //!< TLS configuration.
34 fr_tls_conf_t *tls_conf;
35
36 bool use_tunneled_reply; //!< Use the reply attributes from the tunneled session in
37 //!< the non-tunneled reply to the client.
38
39 bool copy_request_to_tunnel; //!< Use SOME of the request attributes from outside of the
40 //!< tunneled session in the tunneled request.
41
42 char const *virtual_server; //!< Virtual server for inner tunnel session.
44
45 bool req_client_cert; //!< Do we do require a client cert?
47
49 { FR_CONF_OFFSET("tls", rlm_eap_peap_t, tls_conf_name) },
50
51 { FR_CONF_DEPRECATED("copy_request_to_tunnel", rlm_eap_peap_t, NULL), .dflt = "no" },
52
53 { FR_CONF_DEPRECATED("use_tunneled_reply", rlm_eap_peap_t, NULL), .dflt = "no" },
54
55 { FR_CONF_OFFSET_FLAGS("virtual_server", CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, rlm_eap_peap_t, virtual_server) },
56
57 { FR_CONF_OFFSET("require_client_cert", rlm_eap_peap_t, req_client_cert), .dflt = "no" },
58
60};
61
63static fr_dict_t const *dict_radius;
64
67 { .out = &dict_freeradius, .proto = "freeradius" },
68 { .out = &dict_radius, .proto = "radius" },
69 { NULL }
70};
71
74
77
80 { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
81 { .out = &attr_eap_tls_require_client_cert, .name = "EAP-TLS-Require-Client-Cert", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
82
83 { .out = &attr_eap_message, .name = "EAP-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
84 { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius },
85 { NULL }
86};
87
88
89/*
90 * Allocate the PEAP per-session data
91 */
92static peap_tunnel_t *peap_alloc(TALLOC_CTX *ctx, rlm_eap_peap_t *inst)
93{
95
96 t = talloc_zero(ctx, peap_tunnel_t);
97
98 t->server_cs = inst->server_cs;
100
101 return t;
102}
103
104/*
105 * Construct the reply appropriately based on the rcode from PEAP processing.
106 */
108{
109 eap_session_t *eap_session = talloc_get_type_abort(mctx->rctx, eap_session_t);
110 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
111 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
112
113 RDEBUG3("Tunneled request complete");
114
115 switch (eap_session->submodule_result.rcode) {
117 eap_tls_fail(request, eap_session);
118 break;
119
121 eap_tls_request(request, eap_session);
122 break;
123
124 case RLM_MODULE_OK:
125 {
126 eap_tls_prf_label_t prf_label;
127
128 eap_crypto_prf_label_init(&prf_label, eap_session,
129 "client EAP encryption",
130 sizeof("client EAP encryption") - 1);
131
132 /*
133 * Success: Automatically return MPPE keys.
134 */
135 if (eap_tls_success(request, eap_session, &prf_label) > 0) RETURN_UNLANG_FAIL;
136 p_result->rcode = RLM_MODULE_OK;
137
138 /*
139 * Write the session to the session cache
140 *
141 * We do this here (instead of relying on OpenSSL to call the
142 * session caching callback), because we only want to write
143 * session data to the cache if all phases were successful.
144 *
145 * If we wrote out the cache data earlier, and the server
146 * exited whilst the session was in progress, the supplicant
147 * could resume the session (and get access) even if phase2
148 * never completed.
149 */
150 return fr_tls_cache_pending_push(request, tls_session);
151 }
152
153 /*
154 * No response packet, MUST be proxying it.
155 * The main EAP module will take care of discovering
156 * that the request now has a "proxy" packet, and
157 * will proxy it, rather than returning an EAP packet.
158 */
160 break;
161
162 default:
163 eap_tls_fail(request, eap_session);
164 break;
165 }
166
168}
169
171{
172 rlm_eap_peap_t *inst = talloc_get_type(mctx->mi->data, rlm_eap_peap_t);
173 eap_session_t *eap_session = talloc_get_type_abort(mctx->rctx, eap_session_t);
174 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
175 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
176 peap_tunnel_t *peap = talloc_get_type_abort(tls_session->opaque, peap_tunnel_t);
177
178 if ((eap_tls_session->state == EAP_TLS_INVALID) || (eap_tls_session->state == EAP_TLS_FAIL)) {
179 REDEBUG("[eap-tls process] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
180 } else {
181 RDEBUG2("[eap-tls process] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
182 }
183
184 switch (eap_tls_session->state) {
185 /*
186 * EAP-TLS handshake was successful, tell the
187 * client to keep talking.
188 *
189 * If this was EAP-TLS, we would just return
190 * an EAP-TLS-Success packet here.
191 */
194 break;
195
196 /*
197 * The TLS code is still working on the TLS
198 * exchange, and it's a valid TLS request.
199 * do nothing.
200 */
201 case EAP_TLS_HANDLED:
202 /*
203 * FIXME: If the SSL session is established, grab the state
204 * and EAP id from the inner tunnel, and update it with
205 * the expected EAP id!
206 */
208
209 /*
210 * Handshake is done, proceed with decoding tunneled
211 * data.
212 */
214 /*
215 * TLSv1.3 makes application data immediately
216 * available when the handshake is finished.
217 */
218 if (SSL_is_init_finished(tls_session->ssl) && (peap->status == PEAP_STATUS_INVALID)) {
220 }
221 break;
222
223 /*
224 * Anything else: fail.
225 */
226 default:
228 }
229
230 /*
231 * Session is established, proceed with decoding
232 * tunneled data.
233 */
234 RDEBUG2("Session established. Decoding tunneled data");
235
236 /*
237 * We may need PEAP data associated with the session, so
238 * allocate it here, if it wasn't already alloacted.
239 */
240 if (!tls_session->opaque) tls_session->opaque = peap_alloc(tls_session, inst);
241
242 /*
243 * Setup the resume point to prepare the correct reply based on
244 * the rcode coming back from PEAP processing.
245 */
246 (void) unlang_module_yield(request, process_rcode, NULL, 0, eap_session);
247
248 /*
249 * Process the PEAP portion of the request.
250 */
251 return eap_peap_process(&eap_session->submodule_result, request, eap_session, tls_session);
252}
253
254/*
255 * Do authentication, by letting EAP-TLS do most of the work.
256 */
258 request_t *request)
259{
260 eap_session_t *eap_session = eap_session_get(request->parent);
261
262 /*
263 * Setup the resumption frame to process the result
264 */
265 (void)unlang_module_yield(request, mod_handshake_resume, NULL, 0, eap_session);
266
267 /*
268 * Process TLS layer until done.
269 */
270 return eap_tls_process(request, eap_session);
271}
272
274{
275 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
276 rlm_eap_peap_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_peap_thread_t);
277 eap_session_t *eap_session = eap_session_get(request->parent);
278 eap_tls_session_t *eap_tls_session;
279 fr_tls_session_t *tls_session;
280
281 fr_pair_t *vp;
282 bool client_cert;
283
284 /*
285 * EAP-TLS-Require-Client-Cert attribute will override
286 * the require_client_cert configuration option.
287 */
288 vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_eap_tls_require_client_cert);
289 if (vp) {
290 client_cert = vp->vp_uint32 ? true : false;
291 } else {
292 client_cert = inst->req_client_cert;
293 }
294
295 eap_session->opaque = eap_tls_session = eap_tls_session_init(request, eap_session, t->ssl_ctx, client_cert);
296 if (!eap_tls_session) RETURN_UNLANG_FAIL;
297
298 tls_session = eap_tls_session->tls_session;
299
300 /*
301 * As it is a poorly designed protocol, PEAP uses
302 * bits in the TLS header to indicate PEAP
303 * version numbers. For now, we only support
304 * PEAP version 0, so it doesn't matter too much.
305 * However, if we support later versions of PEAP,
306 * we will need this flag to indicate which
307 * version we're currently dealing with.
308 */
309 eap_tls_session->base_flags = 0x00;
310
311 /*
312 * PEAP version 0 requires 'include_length = no',
313 * so rather than hoping the user figures it out,
314 * we force it here.
315 */
316 eap_tls_session->include_length = false;
317
318 /*
319 * TLS session initialization is over. Now handle TLS
320 * related handshaking or application data.
321 */
322 if (eap_tls_start(request, eap_session) < 0) {
323 talloc_free(eap_tls_session);
325 }
326
327 /*
328 * Session resumption requires the storage of data, so
329 * allocate it if it doesn't already exist.
330 */
331 tls_session->opaque = peap_alloc(tls_session, inst);
332
333 eap_session->process = mod_handshake_process;
334
336}
337
338/*
339 * Send an initial eap-tls request to the peer, using the libeap functions.
340 */
342{
343 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
344 eap_session_t *eap_session = eap_session_get(request->parent);
345
346 eap_session->tls = true;
347
348 (void) unlang_module_yield(request, mod_session_init_resume, NULL, 0, NULL);
349
350 if (inst->tls_conf->new_session) return fr_tls_new_session_push(request, inst->tls_conf);
351
353}
354
356{
357 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
358 rlm_eap_peap_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_peap_thread_t);
359
360 t->ssl_ctx = fr_tls_ctx_alloc(inst->tls_conf, false);
361 if (!t->ssl_ctx) return -1;
362
363 return 0;
364}
365
367{
368 rlm_eap_peap_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_peap_thread_t);
369
370 if (likely(t->ssl_ctx != NULL)) SSL_CTX_free(t->ssl_ctx);
371 t->ssl_ctx = NULL;
372
373 return 0;
374}
375
376/*
377 * Attach the module.
378 */
379static int mod_instantiate(module_inst_ctx_t const *mctx)
380{
381 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
382 CONF_SECTION *conf = mctx->mi->conf;
383 virtual_server_t const *virtual_server = virtual_server_find(inst->virtual_server);
384
385 if (!virtual_server) {
386 cf_log_err_by_child(conf, "virtual_server", "Unknown virtual server '%s'", inst->virtual_server);
387 return -1;
388 }
389
390 inst->server_cs = virtual_server_cs(virtual_server);
391 if (!inst->server_cs) {
392 cf_log_err_by_child(conf, "virtual_server", "Virtual server \"%s\" missing", inst->virtual_server);
393 return -1;
394 }
395
396 /*
397 * Read tls configuration, either from group given by 'tls'
398 * option, or from the eap-tls configuration.
399 */
400 inst->tls_conf = eap_tls_conf_parse(conf);
401 if (!inst->tls_conf) {
402 cf_log_err(conf, "Failed initializing SSL context");
403 return -1;
404 }
405
406 return 0;
407}
408
409/*
410 * The module name should be the only globally exported symbol.
411 * That is, everything else should be 'static'.
412 */
415 .common = {
416 .magic = MODULE_MAGIC_INIT,
417 .name = "eap_peap",
418 .inst_size = sizeof(rlm_eap_peap_t),
421
422 .thread_inst_size = sizeof(rlm_eap_peap_thread_t),
423 .thread_instantiate = mod_thread_instantiate,
424 .thread_detach = mod_thread_detach,
425 },
426 .provides = { FR_EAP_METHOD_PEAP },
427 .session_init = mod_session_init, /* Initialise a new EAP session */
428};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:37
#define RCSID(id)
Definition build.h:485
#define UNUSED
Definition build.h:317
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:658
#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:414
#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:284
#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:272
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:434
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition cf_parse.h:449
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:595
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:274
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:287
Specifies an attribute which must be present for the module to function.
Definition dict.h:273
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:286
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
void eap_crypto_prf_label_init(eap_tls_prf_label_t *prf_label, eap_session_t *eap_session, char const *keying_prf_label, size_t keying_prf_label_len)
Initialize the PRF label fields.
Definition crypto.c:48
@ FR_EAP_METHOD_PEAP
Definition types.h:70
@ PEAP_STATUS_TUNNEL_ESTABLISHED
Definition eap_peap.h:32
@ PEAP_STATUS_INVALID
Definition eap_peap.h:29
@ PEAP_RESUMPTION_MAYBE
Definition eap_peap.h:41
unlang_action_t eap_peap_process(unlang_result_t *p_result, request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
Definition peap.c:373
peap_status status
Definition eap_peap.h:46
peap_resumption session_resumption_state
Definition eap_peap.h:50
CONF_SECTION * server_cs
Definition eap_peap.h:49
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
Definition interpret.h:134
static eap_session_t * eap_session_get(request_t *request)
Definition session.h:83
void * opaque
Opaque data used by EAP methods.
Definition session.h:63
bool tls
Whether EAP method uses TLS.
Definition session.h:71
module_method_t process
Callback that should be used to process the next round.
Definition session.h:65
unlang_result_t submodule_result
Result of last submodule call.
Definition session.h:47
Tracks the progress of a single session of any EAP method.
Definition session.h:41
#define RDEBUG3(fmt,...)
Definition log.h:343
talloc_free(reap)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ 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:697
static const conf_parser_t config[]
Definition base.c:186
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG2(fmt,...)
Definition radclient.h:54
static rs_t * conf
Definition radsniff.c:53
#define RETURN_UNLANG_HANDLED
Definition rcode.h:59
#define RETURN_UNLANG_RCODE(_rcode)
Definition rcode.h:66
#define RETURN_UNLANG_FAIL
Definition rcode.h:57
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:43
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:41
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:49
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:44
static unlang_action_t mod_handshake_process(UNUSED unlang_result_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request)
static unlang_action_t mod_handshake_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
bool copy_request_to_tunnel
Use SOME of the request attributes from outside of the tunneled session in the tunneled request.
static peap_tunnel_t * peap_alloc(TALLOC_CTX *ctx, rlm_eap_peap_t *inst)
fr_dict_attr_t const * attr_eap_message
static fr_dict_t const * dict_freeradius
fr_dict_attr_t const * attr_eap_tls_require_client_cert
char const * virtual_server
Virtual server for inner tunnel session.
SSL_CTX * ssl_ctx
Thread local SSL_CTX.
fr_dict_attr_autoload_t rlm_eap_peap_dict_attr[]
fr_dict_autoload_t rlm_eap_peap_dict[]
static unlang_action_t mod_session_init_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static fr_dict_t const * dict_radius
fr_dict_attr_t const * attr_auth_type
char const * tls_conf_name
TLS configuration.
fr_tls_conf_t * tls_conf
bool req_client_cert
Do we do require a client cert?
rlm_eap_submodule_t rlm_eap_peap
bool use_tunneled_reply
Use the reply attributes from the tunneled session in the non-tunneled reply to the client.
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static unlang_action_t process_rcode(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
fr_dict_attr_t const * attr_user_name
static conf_parser_t submodule_config[]
static unlang_action_t mod_session_init(UNUSED unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static int mod_instantiate(module_inst_ctx_t const *mctx)
CONF_SECTION * server_cs
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1291
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:349
size_t inst_size
Size of the module's instance data.
Definition module.h:212
void * data
Module's instance data.
Definition module.h:291
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:434
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
int eap_tls_success(request_t *request, eap_session_t *eap_session, eap_tls_prf_label_t *prf_label)
Send an EAP-TLS success.
Definition tls.c:264
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:1134
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
int eap_tls_fail(request_t *request, eap_session_t *eap_session)
Send an EAP-TLS failure.
Definition tls.c:322
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)
Parse TLS configuration.
Definition tls.c:1266
unlang_action_t eap_tls_process(request_t *request, eap_session_t *eap_session)
Process an EAP TLS request.
Definition tls.c:966
int base_flags
Some protocols use the reserved bits of the EAP-TLS flags (such as PEAP).
Definition tls.h:132
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.