The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
session.c
Go to the documentation of this file.
1/*
2 * This program 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
5 * (at 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: 46cbb29e338993480a73a9594200e12b5d9bd471 $
19 *
20 * @file tls/session.c
21 * @brief Initialise OpenSSL sessions, and read/write data to/from them.
22 *
23 * @copyright 2001 hereUare Communications, Inc. (raghud@hereuare.com)
24 * @copyright 2003 Alan DeKok (aland@freeradius.org)
25 * @copyright 2006-2016 The FreeRADIUS server project
26 */
27#ifdef WITH_TLS
28#define LOG_PREFIX "tls"
29
30#include <freeradius-devel/server/pair.h>
31#include <freeradius-devel/server/log.h>
32
33#include <freeradius-devel/util/debug.h>
34#include <freeradius-devel/util/base16.h>
35#include <freeradius-devel/util/misc.h>
36#include <freeradius-devel/util/pair_legacy.h>
37
38#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
39
40#include <freeradius-devel/unlang/call.h>
41#include <freeradius-devel/unlang/subrequest.h>
42#include <freeradius-devel/unlang/interpret.h>
43
44#include <sys/stat.h>
45#include <ctype.h>
46#include <fcntl.h>
47
48#include "attrs.h"
49#include "base.h"
50#include "log.h"
51
52#include <openssl/x509v3.h>
53#include <openssl/ssl.h>
54
55static char const *tls_version_str[] = {
56 [SSL2_VERSION] = "SSL 2.0",
57 [SSL3_VERSION] = "SSL 3.0",
58 [TLS1_VERSION] = "TLS 1.0",
59#ifdef TLS1_1_VERSION
60 [TLS1_1_VERSION] = "TLS 1.1",
61#endif
62#ifdef TLS1_2_VERSION
63 [TLS1_2_VERSION] = "TLS 1.2",
64#endif
65#ifdef TLS1_3_VERSION
66 [TLS1_3_VERSION] = "TLS 1.3",
67#endif
68#ifdef TLS1_4_VERSION
69 [TLS1_4_VERSION] = "TLS 1.4",
70#endif
71};
72
73static char const *tls_content_type_str[] = {
74 [SSL3_RT_CHANGE_CIPHER_SPEC] = "change_cipher_spec",
75 [SSL3_RT_ALERT] = "alert",
76 [SSL3_RT_HANDSHAKE] = "handshake",
77 [SSL3_RT_APPLICATION_DATA] = "application_data",
78#ifdef SSL3_RT_HEADER
79 [SSL3_RT_HEADER] = "header",
80#endif
81#ifdef SSL3_RT_INNER_CONTENT_TYPE
82 [SSL3_RT_INNER_CONTENT_TYPE] = "inner_content_type",
83#endif
84};
85
86static char const *tls_alert_description_str[] = {
87 [SSL3_AD_CLOSE_NOTIFY] = "close_notify",
88 [SSL3_AD_UNEXPECTED_MESSAGE] = "unexpected_message",
89 [SSL3_AD_BAD_RECORD_MAC] = "bad_record_mac",
90 [TLS1_AD_DECRYPTION_FAILED] = "decryption_failed",
91 [TLS1_AD_RECORD_OVERFLOW] = "record_overflow",
92 [SSL3_AD_DECOMPRESSION_FAILURE] = "decompression_failure",
93 [SSL3_AD_HANDSHAKE_FAILURE] = "handshake_failure",
94 [SSL3_AD_BAD_CERTIFICATE] = "bad_certificate",
95 [SSL3_AD_UNSUPPORTED_CERTIFICATE] = "unsupported_certificate",
96 [SSL3_AD_CERTIFICATE_REVOKED] = "certificate_revoked",
97 [SSL3_AD_CERTIFICATE_EXPIRED] = "certificate_expired",
98 [SSL3_AD_CERTIFICATE_UNKNOWN] = "certificate_unknown",
99 [SSL3_AD_ILLEGAL_PARAMETER] = "illegal_parameter",
100 [TLS1_AD_UNKNOWN_CA] = "unknown_ca",
101 [TLS1_AD_ACCESS_DENIED] = "access_denied",
102 [TLS1_AD_DECODE_ERROR] = "decode_error",
103 [TLS1_AD_DECRYPT_ERROR] = "decrypt_error",
104 [TLS1_AD_EXPORT_RESTRICTION] = "export_restriction",
105 [TLS1_AD_PROTOCOL_VERSION] = "protocol_version",
106 [TLS1_AD_INSUFFICIENT_SECURITY] = "insufficient_security",
107 [TLS1_AD_INTERNAL_ERROR] = "internal_error",
108 [TLS1_AD_USER_CANCELLED] = "user_cancelled",
109 [TLS1_AD_NO_RENEGOTIATION] = "no_renegotiation",
110#ifdef TLS13_AD_MISSING_EXTENSION
111 [TLS13_AD_MISSING_EXTENSION] = "missing_extension",
112#endif
113#ifdef TLS13_AD_CERTIFICATE_REQUIRED
114 [TLS13_AD_CERTIFICATE_REQUIRED] = "certificate_required",
115#endif
116#ifdef TLS1_AD_UNSUPPORTED_EXTENSION
117 [TLS1_AD_UNSUPPORTED_EXTENSION] = "unsupported_extension",
118#endif
119#ifdef TLS1_AD_CERTIFICATE_UNOBTAINABLE
120 [TLS1_AD_CERTIFICATE_UNOBTAINABLE] = "certificate_unobtainable",
121#endif
122#ifdef TLS1_AD_UNRECOGNIZED_NAME
123 [TLS1_AD_UNRECOGNIZED_NAME] = "unrecognised_name",
124#endif
125#ifdef TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
126 [TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE] = "bad_certificate_status_response",
127#endif
128#ifdef TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
129 [TLS1_AD_BAD_CERTIFICATE_HASH_VALUE] = "bad_certificate_hash_value",
130#endif
131#ifdef TLS1_AD_UNKNOWN_PSK_IDENTITY
132 [TLS1_AD_UNKNOWN_PSK_IDENTITY] = "unknown_psk_identity",
133#endif
134#ifdef TLS1_AD_NO_APPLICATION_PROTOCOL
135 [TLS1_AD_NO_APPLICATION_PROTOCOL] = "no_application_protocol",
136#endif
137};
138
139static char const *tls_handshake_type_str[] = {
140 [SSL3_MT_HELLO_REQUEST] = "hello_request",
141 [SSL3_MT_CLIENT_HELLO] = "client_hello",
142 [SSL3_MT_SERVER_HELLO] = "server_hello",
143#ifdef SSL3_MT_NEWSESSION_TICKET
144 [SSL3_MT_NEWSESSION_TICKET] = "new_session_ticket",
145#endif
146#ifdef SSL3_MT_END_OF_EARLY_DATA
147 [SSL3_MT_END_OF_EARLY_DATA] = "end_of_early_data",
148#endif
149#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS
150 [SSL3_MT_ENCRYPTED_EXTENSIONS] = "encrypted_extensions",
151#endif
152 [SSL3_MT_CERTIFICATE] = "certificate",
153 [SSL3_MT_SERVER_KEY_EXCHANGE] = "server_key_exchange",
154 [SSL3_MT_CERTIFICATE_REQUEST] = "certificate_request",
155 [SSL3_MT_SERVER_DONE] = "server_hello_done",
156 [SSL3_MT_CERTIFICATE_VERIFY] = "certificate_verify",
157 [SSL3_MT_CLIENT_KEY_EXCHANGE] = "client_key_exchange",
158 [SSL3_MT_FINISHED] = "finished",
159#ifdef SSL3_MT_CERTIFICATE_URL
160 [SSL3_MT_CERTIFICATE_URL] = "certificate_url",
161#endif
162#ifdef SSL3_MT_CERTIFICATE_STATUS
163 [SSL3_MT_CERTIFICATE_STATUS] = "certificate_status",
164#endif
165#ifdef SSL3_MT_SUPPLEMENTAL_DATA
166 [SSL3_MT_SUPPLEMENTAL_DATA] = "supplemental_data",
167#endif
168#ifdef SSL3_MT_KEY_UPDATE
169 [SSL3_MT_KEY_UPDATE] = "key_update",
170#endif
171#ifdef SSL3_MT_NEXT_PROTO
172 [SSL3_MT_NEXT_PROTO] = "next_proto",
173#endif
174#ifdef SSL3_MT_MESSAGE_HASH
175 [SSL3_MT_MESSAGE_HASH] = "message_hash",
176#endif
177#ifdef DTLS1_MT_HELLO_VERIFY_REQUEST
178 [DTLS1_MT_HELLO_VERIFY_REQUEST] = "hello_verify_request",
179#endif
180#ifdef SSL3_MT_CHANGE_CIPHER_SPEC
181 [SSL3_MT_CHANGE_CIPHER_SPEC] = "change_cipher_spec",
182#endif
183};
184
185/** Clear a record buffer
186 *
187 * @param record buffer to clear.
188 */
189inline static void record_init(fr_tls_record_t *record)
190{
191 record->used = 0;
192}
193
194/** Destroy a record buffer
195 *
196 * @param record buffer to destroy clear.
197 */
198inline static void record_close(fr_tls_record_t *record)
199{
200 record->used = 0;
201}
202
203/** Copy data to the intermediate buffer, before we send it somewhere
204 *
205 * @param[in] record buffer to write to.
206 * @param[in] in data to write.
207 * @param[in] inlen Length of data to write.
208 * @return the amount of data written to the record buffer.
209 */
210inline static unsigned int record_from_buff(fr_tls_record_t *record, void const *in, unsigned int inlen)
211{
212 unsigned int added = FR_TLS_MAX_RECORD_SIZE - record->used;
213
214 if (added > inlen) added = inlen;
215 if (added == 0) return 0;
216
217 memcpy(record->data + record->used, in, added);
218 record->used += added;
219
220 return added;
221}
222
223/** Take data from the buffer, and give it to the caller
224 *
225 * @param[in] record buffer to read from.
226 * @param[out] out where to write data from record buffer.
227 * @param[in] outlen The length of the output buffer.
228 * @return the amount of data written to the output buffer.
229 */
230inline static unsigned int record_to_buff(fr_tls_record_t *record, void *out, unsigned int outlen)
231{
232 unsigned int taken = record->used;
233
234 if (taken > outlen) taken = outlen;
235 if (taken == 0) return 0;
236 if (out) memcpy(out, record->data, taken);
237
238 record->used -= taken;
239
240 /*
241 * This is pretty bad...
242 */
243 if (record->used > 0) memmove(record->data, record->data + taken, record->used);
244
245 return taken;
246}
247
248/** Return the static private key password we have configured
249 *
250 * @param[out] buf Where to write the password to.
251 * @param[in] size The length of buf.
252 * @param[in] rwflag
253 * - 0 if password used for decryption.
254 * - 1 if password used for encryption.
255 * @param[in] u The static password.
256 * @return
257 * - 0 on error.
258 * - >0 on success (the length of the password).
259 */
260int fr_tls_session_password_cb(char *buf, int size, int rwflag UNUSED, void *u)
261{
262 size_t len;
263
264 /*
265 * We do this instead of not registering the callback
266 * to ensure OpenSSL doesn't try and read a password
267 * from stdin (causes server to block).
268 */
269 if (!u) {
270 ERROR("Private key encrypted but no private_key_password configured");
271 return 0;
272 }
273
274 len = strlcpy(buf, (char *)u, size);
275 if (len > (size_t)size) {
276 ERROR("Password too long. Maximum length is %i bytes", size - 1);
277 return 0;
278 }
279
280 return len;
281}
282
283#ifdef PSK_MAX_IDENTITY_LEN
284/** Verify the PSK identity contains no reserved chars
285 *
286 * @param identity to check.
287 * @return
288 * - true identity does not contain reserved chars.
289 * - false identity contains reserved chars.
290 */
291static bool session_psk_identity_is_safe(const char *identity)
292{
293 char c;
294
295 if (!identity) return true;
296
297 while ((c = *(identity++)) != '\0') {
298 if (isalpha((uint8_t) c) || isdigit((uint8_t) c) || isspace((uint8_t) c) ||
299 (c == '@') || (c == '-') || (c == '_') || (c == '.')) {
300 continue;
301 }
302
303 return false;
304 }
305
306 return true;
307}
308
309/** Determine the PSK to use for an outgoing connection
310 *
311 * @param[in] ssl session.
312 * @param[in] identity The identity of the PSK to search for.
313 * @param[out] psk Where to write the PSK we found (if any).
314 * @param[in] max_psk_len The length of the buffer provided for PSK.
315 * @return
316 * - 0 if no PSK matching identity was found.
317 * - >0 if a PSK matching identity was found (the length of bytes written to psk).
318 */
319unsigned int fr_tls_session_psk_client_cb(SSL *ssl, UNUSED char const *hint,
320 char *identity, unsigned int max_identity_len,
321 unsigned char *psk, unsigned int max_psk_len)
322{
323 unsigned int psk_len;
324 fr_tls_conf_t *conf;
325
326 conf = (fr_tls_conf_t *)SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_CONF);
327 if (!conf) return 0;
328
329 psk_len = strlen(conf->psk_password);
330 if (psk_len > (2 * max_psk_len)) return 0;
331
332 strlcpy(identity, conf->psk_identity, max_identity_len);
333
334 return fr_base16_decode(NULL,
335 &FR_DBUFF_TMP((uint8_t *)psk, (size_t)max_psk_len),
336 &FR_SBUFF_IN(conf->psk_password, (size_t)psk_len), false);
337}
338
339/** Determine the PSK to use for an incoming connection
340 *
341 * @param[in] ssl session.
342 * @param[in] identity The identity of the PSK to search for.
343 * @param[out] psk Where to write the PSK we found (if any).
344 * @param[in] max_psk_len The length of the buffer provided for PSK.
345 * @return
346 * - 0 if no PSK matching identity was found.
347 * - >0 if a PSK matching identity was found (the length of bytes written to psk).
348 */
349unsigned int fr_tls_session_psk_server_cb(SSL *ssl, const char *identity,
350 unsigned char *psk, unsigned int max_psk_len)
351{
352 size_t psk_len = 0;
353 fr_tls_conf_t *conf;
354 request_t *request;
355
356 conf = (fr_tls_conf_t *)SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_CONF);
357 if (!conf) return 0;
358
359 request = fr_tls_session_request(ssl);
360 if (request && conf->psk_query) {
361 size_t hex_len;
362 fr_pair_t *vp;
363 char buffer[2 * PSK_MAX_PSK_LEN + 4]; /* allow for too-long keys */
364
365 /*
366 * The passed identity is weird. Deny it.
367 */
368 if (!session_psk_identity_is_safe(identity)) {
369 RWDEBUG("Invalid characters in PSK identity %s", identity);
370 return 0;
371 }
372
374 if (fr_pair_value_from_str(vp, identity, strlen(identity), NULL, true) < 0) {
375 RPWDEBUG2("Failed parsing TLS PSK Identity");
377 return 0;
378 }
379
380 hex_len = xlat_eval(buffer, sizeof(buffer), request, conf->psk_query, NULL, NULL);
381 if (!hex_len) {
382 RWDEBUG("PSK expansion returned an empty string.");
383 return 0;
384 }
385
386 /*
387 * The returned key is truncated at MORE than
388 * OpenSSL can handle. That way we can detect
389 * the truncation, and complain about it.
390 */
391 if (hex_len > (2 * max_psk_len)) {
392 RWDEBUG("Returned PSK is too long (%u > %u)", (unsigned int) hex_len, 2 * max_psk_len);
393 return 0;
394 }
395
396 /*
397 * Leave the TLS-PSK-Identity in the request, and
398 * convert the expansion from printable string
399 * back to hex.
400 */
401 return fr_base16_decode(NULL,
402 &FR_DBUFF_TMP((uint8_t *)psk, (size_t)max_psk_len),
403 &FR_SBUFF_IN(buffer, hex_len), false);
404 }
405
406 if (!conf->psk_identity) {
407 DEBUG("No static PSK identity set. Rejecting the user");
408 return 0;
409 }
410
411 /*
412 * No request_t, or no dynamic query. Just look for a
413 * static identity.
414 */
415 if (strcmp(identity, conf->psk_identity) != 0) {
416 ERROR("Supplied PSK identity %s does not match configuration. Rejecting.",
417 identity);
418 return 0;
419 }
420
421 psk_len = strlen(conf->psk_password);
422 if (psk_len > (2 * max_psk_len)) return 0;
423
424 return fr_base16_decode(NULL,
425 &FR_DBUFF_TMP((uint8_t *)psk, (size_t)max_psk_len),
426 &FR_SBUFF_IN(conf->psk_password, psk_len), false);
427}
428#endif /* PSK_MAX_IDENTITY_LEN */
429
431DIAG_OFF(used-but-marked-unused) /* Fix spurious warnings for sk_ macros */
432/** Record session state changes
433 *
434 * Called by OpenSSL whenever the session state changes, an alert is received or an error occurs.
435 *
436 * @param[in] ssl session.
437 * @param[in] where Which context the callback is being called in.
438 * See https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_info_callback.html
439 * for additional info.
440 * @param[in] ret 0 if an error occurred, or the alert type if an alert was received.
441 */
442void fr_tls_session_info_cb(SSL const *ssl, int where, int ret)
443{
444 char const *role, *state;
445 request_t *request = SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_REQUEST);
446
447 if ((where & ~SSL_ST_MASK) & SSL_ST_CONNECT) {
448 role = "Client ";
449 } else if (((where & ~SSL_ST_MASK)) & SSL_ST_ACCEPT) {
450 role = "Server ";
451 } else {
452 role = "";
453 }
454
455 state = SSL_state_string_long(ssl);
456 state = state ? state : "<INVALID>";
457
458 if ((where & SSL_CB_LOOP) || (where & SSL_CB_HANDSHAKE_START) || (where & SSL_CB_HANDSHAKE_DONE)) {
460 char const *abbrv = SSL_state_string(ssl);
461 size_t len;
462
463 /*
464 * Trim crappy OpenSSL state strings...
465 */
466 len = strlen(abbrv);
467 if ((len > 1) && (abbrv[len - 1] == ' ')) len--;
468
469 ROPTIONAL(RDEBUG3, DEBUG3, "Handshake state [%.*s] - %s%s", (int)len, abbrv, role, state);
470
471#ifdef OPENSSL_NO_SSL_TRACE
472 {
473 STACK_OF(SSL_CIPHER) *server_ciphers;
474 STACK_OF(SSL_CIPHER) *client_ciphers;
475
476 /*
477 * After a ClientHello, list all the proposed ciphers
478 * from the client.
479 *
480 * Only do this if we don't have SSL_trace() as
481 * SSL_trace() prints this information and we don't
482 * want to duplicate it.
483 */
484 if (SSL_get_state(ssl) == TLS_ST_SR_CLNT_HELLO &&
485 (client_ciphers = SSL_get_client_ciphers(ssl))) {
486 int i;
487 int num_ciphers;
488 const SSL_CIPHER *this_cipher;
489
490 server_ciphers = SSL_get_ciphers(ssl);
491 /*
492 * These are printed on startup, so not usually
493 * required.
494 */
495 ROPTIONAL(RDEBUG4, DEBUG4, "Our preferred ciphers (by priority)");
497 if (request) RINDENT();
498 num_ciphers = sk_SSL_CIPHER_num(server_ciphers);
499 for (i = 0; i < num_ciphers; i++) {
500 this_cipher = sk_SSL_CIPHER_value(server_ciphers, i);
501 ROPTIONAL(RDEBUG4, DEBUG4, "[%i] %s", i, SSL_CIPHER_get_name(this_cipher));
502 }
503 if (request) REXDENT();
504 }
505
506 /*
507 * Print information about the client's
508 * handshake message.
509 */
511 ROPTIONAL(RDEBUG3, DEBUG3, "Client's preferred ciphers (by priority)");
512 if (request) RINDENT();
513 num_ciphers = sk_SSL_CIPHER_num(client_ciphers);
514 for (i = 0; i < num_ciphers; i++) {
515 this_cipher = sk_SSL_CIPHER_value(client_ciphers, i);
516 ROPTIONAL(RDEBUG3, DEBUG3, "[%i] %s", i, SSL_CIPHER_get_name(this_cipher));
517 }
518 if (request) REXDENT();
519 }
520 }
521 }
522# endif
523 } else {
524 ROPTIONAL(RDEBUG2, DEBUG2, "Handshake state - %s%s (%u)", role, state, SSL_get_state(ssl));
525 }
526 return;
527 }
528
529 if (where & SSL_CB_ALERT) {
530 if ((ret & 0xff) == SSL_AD_CLOSE_NOTIFY) return;
531
532 /*
533 * We got an alert...
534 */
535 if (where & SSL_CB_READ) {
536 fr_pair_t *vp;
537
538 ROPTIONAL(REDEBUG, ERROR, "Client sent %s TLS alert (%i) - %s", SSL_alert_type_string_long(ret),
539 ret & 0xff, SSL_alert_desc_string_long(ret));
540
541 /*
542 * Offer helpful advice... Should be expanded.
543 */
544 switch (ret & 0xff) {
545 case TLS1_AD_UNKNOWN_CA:
546 REDEBUG("Verify the client has a copy of the server's Certificate "
547 "Authority (CA) installed, and trusts that CA");
548 break;
549
550 default:
551 break;
552 }
553
555 vp->vp_uint8 = ret & 0xff;
556 ROPTIONAL(RDEBUG2, DEBUG2, "&TLS-Client-Error-Code := %pV", &vp->data);
557 /*
558 * We're sending the client an alert.
559 */
560 } else {
561 ROPTIONAL(REDEBUG, ERROR, "Sending client %s TLS alert (%i) - %s",
562 SSL_alert_type_string_long(ret), ret & 0xff, SSL_alert_desc_string_long(ret));
563
564 /*
565 * Offer helpful advice... Should be expanded.
566 */
567 switch (ret & 0xff) {
568 case TLS1_AD_PROTOCOL_VERSION:
569 ROPTIONAL(REDEBUG, ERROR, "Client requested a TLS protocol version that is not "
570 "enabled or not supported. Upgrade FreeRADIUS + OpenSSL to their latest "
571 "versions and/or adjust 'tls_max_version'/'tls_min_version' if you want "
572 "authentication to succeed");
573 break;
574
575 default:
576 break;
577 }
578 }
579 return;
580 }
581
582 if (where & SSL_CB_EXIT) {
583 if (ret == 0) {
584 ROPTIONAL(REDEBUG, ERROR, "Handshake exit state %s%s", role, state);
585 return;
586 }
587
588 if (ret < 0) {
589 if (SSL_want_read(ssl)) {
590 RDEBUG2("Need more data from client"); /* State same as previous call, don't print */
591 return;
592 }
593 ROPTIONAL(REDEBUG, ERROR, "Handshake exit state %s%s", role, state);
594 }
595 }
596}
597DIAG_ON(used-but-marked-unused)
599
600/** Print a message to the request or global log detailing handshake state
601 *
602 * @param[in] request The current #request_t.
603 * @param[in] tls_session The current TLS session.
604 */
605static void session_msg_log(request_t *request, fr_tls_session_t *tls_session, uint8_t const *data, size_t data_len)
606{
607 char const *version, *content_type;
608 char const *str_details1 = NULL;
609 char const *str_details2 = NULL;
610 char unknown_version[32];
611 char unknown_content_type[32];
612 char unknown_alert_level[32];
613 char unknown_alert_description[32];
614 char unknown_handshake_type[32];
615
616 /*
617 * Don't print this out in the normal course of
618 * operations.
619 */
621
622 if (((size_t)tls_session->info.version >= NUM_ELEMENTS(tls_version_str)) ||
623 !tls_version_str[tls_session->info.version]) {
624 snprintf(unknown_version, sizeof(unknown_version), "unknown_tls_version_0x%04x",
625 (unsigned int) tls_session->info.version);
626 version = unknown_version;
627 } else {
628 version = tls_version_str[tls_session->info.version];
629 }
630
631 /*
632 * TLS 1.0, 1.1, 1.2 content types are the same as SSLv3
633 */
634 if (((size_t)tls_session->info.content_type >= NUM_ELEMENTS(tls_content_type_str)) ||
635 !tls_content_type_str[tls_session->info.content_type]) {
636 snprintf(unknown_content_type, sizeof(unknown_content_type),
637 "unknown_content_type_0x%04x", (unsigned int) tls_session->info.content_type);
638 content_type = unknown_content_type;
639 } else {
640 content_type = tls_content_type_str[tls_session->info.content_type];
641 }
642
643 if (tls_session->info.content_type == SSL3_RT_ALERT) {
644 if (tls_session->info.record_len == 2) {
645 switch (tls_session->info.alert_level) {
646 case SSL3_AL_WARNING:
647 str_details1 = "warning";
648 break;
649 case SSL3_AL_FATAL:
650 str_details1 = "fatal";
651 break;
652
653 default:
654 snprintf(unknown_alert_level, sizeof(unknown_alert_level),
655 "unknown_alert_level_0x%04x", tls_session->info.alert_level);
656 str_details1 = unknown_alert_level;
657 break;
658 }
659
660 if (((size_t)tls_session->info.alert_description >= NUM_ELEMENTS(tls_alert_description_str)) ||
661 !tls_alert_description_str[tls_session->info.alert_description]) {
662 snprintf(unknown_alert_description, sizeof(unknown_alert_description),
663 "unknown_alert_0x%04x", tls_session->info.alert_description);
664 str_details2 = unknown_alert_description;
665 } else {
666 str_details2 = tls_alert_description_str[tls_session->info.alert_description];
667 }
668 } else {
669 str_details1 = "unknown_alert_level";
670 str_details2 = "unknown_alert";
671 }
672 }
673
674 if ((size_t)tls_session->info.content_type == SSL3_RT_HANDSHAKE) {
675 if (tls_session->info.record_len > 0) {
676 /*
677 * Range guard not needed due to size of array
678 * and underlying type.
679 */
680 if (!tls_handshake_type_str[tls_session->info.handshake_type]) {
681 snprintf(unknown_handshake_type, sizeof(unknown_handshake_type),
682 "unknown_handshake_type_0x%02x", tls_session->info.handshake_type);
683 str_details1 = unknown_handshake_type;
684 } else {
685 str_details1 = tls_handshake_type_str[tls_session->info.handshake_type];
686 }
687 }
688 }
689
690 snprintf(tls_session->info.info_description, sizeof(tls_session->info.info_description),
691 "%s %s, %s[length %lu]%s%s%s%s",
692 tls_session->info.origin ? ">>> send" : "<<< recv",
693 version,
694 content_type,
695 (unsigned long)tls_session->info.record_len,
696 str_details1 ? ", " : "",
697 str_details1 ? str_details1 : "",
698 str_details2 ? ", " : "",
699 str_details2 ? str_details2 : "");
700
701 /*
702 * Print out information about the record and print the
703 * data at higher debug levels.
704 */
706 ROPTIONAL(RHEXDUMP4, HEXDUMP4, data, data_len, "%s", tls_session->info.info_description);
707 } else {
708 ROPTIONAL(RDEBUG2, DEBUG2, "%s", tls_session->info.info_description);
709 }
710}
711
712/** Record the progression of the TLS handshake
713 *
714 * This callback is called by OpenSSL whenever a protocol message relating to a handshake is sent
715 * or received.
716 *
717 * This function copies state information from the various arguments into the state->info
718 * structure of the #fr_tls_session_t, to allow us to track the progression of the handshake.
719 *
720 * @param[in] write_p
721 * - 0 when a message has been received.
722 * - 1 when a message has been sent.
723 *
724 * @param[in] msg_version The TLS version negotiated, should be one of:
725 * - TLS1_VERSION
726 * - TLS1_1_VERSION
727 * - TLS1_2_VERSION
728 * - TLS1_3_VERSION
729 *
730 * @param[in] content_type One of the contentType values defined for TLS:
731 * - SSL3_RT_CHANGE_CIPHER_SPEC (20)
732 * - SSL3_RT_ALERT (21)
733 * - SSL3_RT_HANDSHAKE (22)
734 * - TLS1_RT_HEARTBEAT (24)
735 *
736 * @param[in] inbuf The raw protocol message.
737 * @param[in] len Length of the raw protocol message.
738 * @param[in] ssl The SSL session.
739 * @param[in] arg The #fr_tls_session_t holding the SSL session.
740 */
741void fr_tls_session_msg_cb(int write_p, int msg_version, int content_type,
742 void const *inbuf, size_t len,
743 SSL *ssl, void *arg)
744{
745 uint8_t const *buf = inbuf;
746 fr_tls_session_t *tls_session = talloc_get_type_abort(arg, fr_tls_session_t);
747 request_t *request = fr_tls_session_request(tls_session->ssl);
748
749 /*
750 * Mostly to check for memory corruption...
751 */
752 if (!fr_cond_assert(tls_session->ssl = ssl)) {
753 ROPTIONAL(REDEBUG, ERROR, "fr_tls_session_t and ssl arg do not match in fr_tls_session_msg_cb");
754 tls_session->invalid = true;
755 return;
756 }
757
758 /*
759 * As per https://tools.ietf.org/html/rfc7568
760 *
761 * We explicitly disable SSLv2/v3, hence the asserts.
762 */
763#ifdef SSL2_VERSION
764 if (!fr_cond_assert(msg_version != SSL2_VERSION)) {
765 ROPTIONAL(REDEBUG, ERROR, "Invalid version (SSLv2) in handshake");
766 tls_session->invalid = true;
767 return;
768 }
769#endif
770
771#ifdef SSL3_VERSION
772 if (!fr_cond_assert(msg_version != SSL3_VERSION)) {
773 ROPTIONAL(REDEBUG, ERROR, "Invalid version (SSLv3) in handshake");
774 tls_session->invalid = true;
775 return;
776 }
777#endif
778
779 /*
780 * OpenSSL >= 1.0.2 calls this function with 'pseudo'
781 * content types. Which breaks our tracking of
782 * the SSL Session state.
783 */
784 if ((msg_version == 0) && (content_type > UINT8_MAX)) {
785 ROPTIONAL(REDEBUG4, DEBUG4, "Ignoring fr_tls_session_msg_cb call with pseudo content type %i, version %i",
786 content_type, msg_version);
787 return;
788 }
789
790 if ((write_p != 0) && (write_p != 1)) {
791 ROPTIONAL(REDEBUG4, DEBUG4, "Ignoring fr_tls_session_msg_cb call with invalid write_p %d", write_p);
792 return;
793 }
794
795 /*
796 * 0 - received (from peer)
797 * 1 - sending (to peer)
798 */
799 tls_session->info.origin = write_p;
800 tls_session->info.content_type = content_type;
801 tls_session->info.record_len = len;
802 tls_session->info.version = msg_version;
803 tls_session->info.initialized = true;
804
805 switch (content_type) {
806 case SSL3_RT_ALERT:
807 tls_session->info.alert_level = buf[0];
808 tls_session->info.alert_description = buf[1];
809 tls_session->info.handshake_type = 0x00;
810 break;
811
812 case SSL3_RT_HANDSHAKE:
813 tls_session->info.handshake_type = buf[0];
814 tls_session->info.alert_level = 0x00;
815 tls_session->info.alert_description = 0x00;
816 break;
817
818#ifdef SSL3_RT_HEARTBEAT
819 case TLS1_RT_HEARTBEAT:
820 uint8_t *p = buf;
821
822 if ((len >= 3) && (p[0] == 1)) {
823 size_t payload_len;
824
825 payload_len = fr_nbo_to_uint16(p + 1);
826 if ((payload_len + 3) > len) {
827 tls_session->invalid = true;
828 ROPTIONAL(REDEBUG, ERROR, "OpenSSL Heartbeat attack detected. Closing connection");
829 return;
830 }
831 }
832 break;
833#endif
834 default:
835 break;
836 }
837
838 session_msg_log(request, tls_session, (uint8_t const *)inbuf, len);
839
840#ifndef OPENSSL_NO_SSL_TRACE
842 SSL_trace(tls_session->info.origin,
843 tls_session->info.version,
844 tls_session->info.content_type,
845 inbuf, len,
846 ssl,
847 request ?
848 fr_tls_request_log_bio(request, L_DBG, L_DBG_LVL_3) :
849 fr_tls_global_log_bio(L_DBG, L_DBG_LVL_3));
850 }
851#endif
852}
853
854/*
855 * By setting the environment variable SSLKEYLOGFILE to a filename keying
856 * material will be exported that you may use with Wireshark to decode any
857 * TLS flows. Please see the following for more details:
858 *
859 * https://gitlab.com/wireshark/wireshark/-/wikis/TLS#tls-decryption
860 *
861 * An example logging session is (you should delete the file on each run):
862 *
863 * rm -f /tmp/sslkey.log; env SSLKEYLOGFILE=/tmp/sslkey.log freeradius -X | tee /tmp/debug
864 *
865 * Note that we rely on the OS to check file permissions. If the
866 * caller can run radiusd, then they can only write to files which
867 * they own. If radiusd is running as root, then only root can
868 * change the environment variables for radiusd.
869 */
870void fr_tls_session_keylog_cb(const SSL *ssl, const char *line)
871{
872 int fd;
873 size_t len;
874 const char *filename;
875 char buffer[64 + 2*SSL3_RANDOM_SIZE + 2*SSL_MAX_MASTER_KEY_LENGTH];
876
877 /*
878 * Prefer the environment variable definition to the
879 * configuration file. This allows for "one-shot"
880 * dumping of EAP keys when you know you're not using
881 * RadSec, and you don't want to edit the configuration.
882 */
883 filename = getenv("SSLKEYLOGFILE");
884 if (!filename) {
885 fr_tls_conf_t *conf;
886
887 conf = (fr_tls_conf_t *)SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_CONF);
888 if (!conf || !conf->keylog_file || !*conf->keylog_file) return;
889
890 filename = conf->keylog_file;
891 }
892
893 /*
894 * We write all of the data at once. This is *generally*
895 * atomic on most systems.
896 */
897 len = strlen(line);
898 if ((len + 1) > sizeof(buffer)) {
899 DEBUG("SSLKEYLOGFILE buffer not large enough, max %lu, required %lu", sizeof(buffer), len + 1);
900 return;
901 }
902
903 /*
904 * Add a \n, which means that in order to write() the
905 * buffer AND the trailing \n, we have to place both
906 * strings into the same buffer.
907 */
908 memcpy(buffer, line, len);
909 buffer[len] = '\n';
910
911 fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
912 if (fd < 0) {
913 DEBUG("Failed to open file %s: %s", filename, strerror(errno));
914 return;
915 }
916
917 /*
918 * This should work in most situations.
919 */
920 if (write(fd, buffer, len + 1) < 0) {
921 DEBUG("Failed to write to file %s: %s", filename, strerror(errno));
922 }
923
924 close(fd);
925}
926
927/** Decrypt application data
928 *
929 * @note Handshake must have completed before this function may be called.
930 *
931 * Feed data from dirty_in to OpenSSL, and read the clean data into clean_out.
932 *
933 * @param[in] request The current #request_t.
934 * @param[in] tls_session The current TLS session.
935 * @return
936 * - -1 on error.
937 * - 1 if more fragments are required to fully reassemble the record for decryption.
938 * - 0 if we decrypted a complete record.
939 */
940int fr_tls_session_recv(request_t *request, fr_tls_session_t *tls_session)
941{
942 int ret;
943
944 fr_tls_session_request_bind(tls_session->ssl, request);
945
946 if (!SSL_is_init_finished(tls_session->ssl)) {
947 REDEBUG("Attempted to read application data before handshake completed");
948 error:
949 ret = -1;
950 goto finish;
951 }
952
953 /*
954 * Decrypt the complete record.
955 */
956 if (tls_session->dirty_in.used) {
957 ret = BIO_write(tls_session->into_ssl, tls_session->dirty_in.data, tls_session->dirty_in.used);
958 if (ret != (int) tls_session->dirty_in.used) {
959 record_init(&tls_session->dirty_in);
960 REDEBUG("Failed writing %zu bytes to SSL BIO: %d", tls_session->dirty_in.used, ret);
961 goto error;
962 }
963
964 record_init(&tls_session->dirty_in);
965 }
966
967 /*
968 * Clear the dirty buffer now that we are done with it
969 * and init the clean_out buffer to store decrypted data
970 */
971 record_init(&tls_session->clean_out);
972
973 /*
974 * Read (and decrypt) the tunneled data from the
975 * SSL session, and put it into the decrypted
976 * data buffer.
977 */
978 ret = SSL_read(tls_session->ssl, tls_session->clean_out.data, sizeof(tls_session->clean_out.data));
979 if (ret < 0) {
980 int code;
981
982 code = SSL_get_error(tls_session->ssl, ret);
983 switch (code) {
984 case SSL_ERROR_WANT_READ:
985 RWDEBUG("Peer indicated record was complete, but OpenSSL returned SSL_WANT_READ. "
986 "Attempting to continue");
987 ret = 1;
988 goto finish;
989
990 case SSL_ERROR_WANT_WRITE:
991 REDEBUG("Error in fragmentation logic: SSL_WANT_WRITE");
992 goto error;
993
994 case SSL_ERROR_NONE:
995 RDEBUG2("No application data received. Assuming handshake is continuing...");
996 ret = 0;
997 break;
998
999 default:
1000 REDEBUG("Error in fragmentation logic");
1001 fr_tls_log_io_error(request, code, "SSL_read (%s)", __FUNCTION__);
1002 goto error;
1003 }
1004 }
1005
1006 /*
1007 * Passed all checks, successfully decrypted data
1008 */
1009 tls_session->clean_out.used = ret;
1010 ret = 0;
1011
1012 if (RDEBUG_ENABLED3) {
1013 RHEXDUMP3(tls_session->clean_out.data, tls_session->clean_out.used,
1014 "Decrypted TLS application data (%zu bytes)", tls_session->clean_out.used);
1015 } else {
1016 RDEBUG2("Decrypted TLS application data (%zu bytes)", tls_session->clean_out.used);
1017 }
1018finish:
1019 fr_tls_session_request_unbind(tls_session->ssl);
1020
1021 return ret;
1022}
1023
1024/** Encrypt application data
1025 *
1026 * @note Handshake must have completed before this function may be called.
1027 *
1028 * Take cleartext data from clean_in, and feed it to OpenSSL, reading
1029 * the encrypted data into dirty_out.
1030 *
1031 * @param[in] request The current request.
1032 * @param[in] tls_session The current TLS session.
1033 * @return
1034 * - -1 on failure.
1035 * - 0 on success.
1036 */
1037int fr_tls_session_send(request_t *request, fr_tls_session_t *tls_session)
1038{
1039 int ret = 0;
1040
1041 fr_tls_session_request_bind(tls_session->ssl, request);
1042
1043 if (!SSL_is_init_finished(tls_session->ssl)) {
1044 REDEBUG("Attempted to write application data before handshake completed");
1045 ret = -1;
1046 goto finish;
1047 }
1048
1049 /*
1050 * If there's un-encrypted data in 'clean_in', then write
1051 * that data to the SSL session, and then call the BIO function
1052 * to get that encrypted data from the SSL session, into
1053 * a buffer which we can then package into an EAP packet.
1054 *
1055 * Based on Server's logic this clean_in is expected to
1056 * contain the data to send to the client.
1057 */
1058 if (tls_session->clean_in.used > 0) {
1059 if (RDEBUG_ENABLED3) {
1060 RHEXDUMP3(tls_session->clean_in.data, tls_session->clean_in.used,
1061 "TLS application data to encrypt (%zu bytes)", tls_session->clean_in.used);
1062 } else {
1063 RDEBUG2("TLS application data to encrypt (%zu bytes)", tls_session->clean_in.used);
1064 }
1065
1066 ret = SSL_write(tls_session->ssl, tls_session->clean_in.data, tls_session->clean_in.used);
1067 record_to_buff(&tls_session->clean_in, NULL, ret);
1068
1069 /* Get the dirty data from Bio to send it */
1070 ret = BIO_read(tls_session->from_ssl, tls_session->dirty_out.data,
1071 sizeof(tls_session->dirty_out.data));
1072 if (ret > 0) {
1073 tls_session->dirty_out.used = ret;
1074 ret = 0;
1075 } else {
1076 if (fr_tls_log_io_error(request, SSL_get_error(tls_session->ssl, ret),
1077 "SSL_write (%s)", __FUNCTION__) < 0) ret = -1;
1078 }
1079 }
1080
1081finish:
1082 fr_tls_session_request_unbind(tls_session->ssl);
1083
1084 return ret;
1085}
1086
1087/** Instruct fr_tls_session_async_handshake to create a synthesised TLS alert record and send it to the peer
1088 *
1089 */
1090int fr_tls_session_alert(UNUSED request_t *request, fr_tls_session_t *session, uint8_t level, uint8_t description)
1091{
1092 if (session->alerts_sent > 3) return -1; /* Some kind of state machine brokenness */
1093
1094 /*
1095 * Ignore less severe alerts
1096 */
1097 if (session->pending_alert && (level < session->pending_alert_level)) return 0;
1098
1099 session->pending_alert = true;
1100 session->pending_alert_level = level;
1101 session->pending_alert_description = description;
1102
1103 return 0;
1104}
1105
1106static void fr_tls_session_alert_send(request_t *request, fr_tls_session_t *session)
1107{
1108 /*
1109 * Update our internal view of the session
1110 */
1111 session->info.origin = TLS_INFO_ORIGIN_RECORD_SENT;
1112 session->info.content_type = SSL3_RT_ALERT;
1113 session->info.alert_level = session->pending_alert_level;
1114 session->info.alert_description = session->pending_alert_description;
1115
1116 session->dirty_out.data[0] = session->info.content_type;
1117 session->dirty_out.data[1] = 3;
1118 session->dirty_out.data[2] = 1;
1119 session->dirty_out.data[3] = 0;
1120 session->dirty_out.data[4] = 2;
1121 session->dirty_out.data[5] = session->pending_alert_level;
1122 session->dirty_out.data[6] = session->pending_alert_description;
1123
1124 session->dirty_out.used = 7;
1125
1126 session->pending_alert = false;
1127 session->alerts_sent++;
1128
1129 SSL_clear(session->ssl); /* Reset the SSL *, to allow the client to restart the session */
1130
1131 session_msg_log(request, session, session->dirty_out.data, session->dirty_out.used);
1132}
1133
1134/** Process the result of `establish session { ... }`
1135 *
1136 * As this is just a logging session, it's result doesn't affect the parent.
1137 */
1138static unlang_action_t tls_establish_session_result(UNUSED rlm_rcode_t *p_result, UNUSED int *priority,
1139 UNUSED request_t *request, UNUSED void *uctx)
1140{
1142}
1143
1144/** Push an `establish session { ... }` call into the current request, using a subrequest
1145 *
1146 * @param[in] request The current request.
1147 * @param[in] conf TLS configuration.
1148 * @param[in] tls_session The current TLS session.
1149 * @return
1150 * - UNLANG_ACTION_PUSHED_CHILD on success.
1151 * - UNLANG_ACTION_FAIL on failure.
1152 */
1153static inline CC_HINT(always_inline)
1154unlang_action_t tls_establish_session_push(request_t *request, fr_tls_conf_t *conf, fr_tls_session_t *tls_session)
1155{
1156 request_t *child;
1157 fr_pair_t *vp;
1158 unlang_action_t ua;
1159
1160 MEM(child = unlang_subrequest_alloc(request, dict_tls));
1161 request = child;
1162
1163 /*
1164 * Setup the child request for reporting session
1165 */
1167 vp->vp_uint32 = enum_tls_packet_type_establish_session->vb_uint32;
1168
1169 /*
1170 * Allocate a child, and set it up to call
1171 * the TLS virtual server.
1172 */
1173 ua = fr_tls_call_push(child, tls_establish_session_result, conf, tls_session);
1174 if (ua < 0) {
1175 talloc_free(child);
1176 return UNLANG_ACTION_FAIL;
1177 }
1178
1179 return ua;
1180}
1181
1182/** Finish off a handshake round, possibly adding attributes to the request
1183 *
1184 */
1185static unlang_action_t tls_session_async_handshake_done_round(UNUSED rlm_rcode_t *p_result, UNUSED int *priority,
1186 request_t *request, void *uctx)
1187{
1188 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
1189 int ret;
1190
1191 RDEBUG3("entered state %s", __FUNCTION__);
1192
1193 /*
1194 * This only occurs once per session, where calling
1195 * SSL_read updates the state of the SSL session, setting
1196 * this flag to true.
1197 *
1198 * Callbacks provide enough info so we don't need to
1199 * print debug statements when the handshake is in other
1200 * states.
1201 */
1202 if (SSL_is_init_finished(tls_session->ssl)) {
1203 SSL_CIPHER const *cipher;
1204 fr_pair_t *vp;
1205 char const *version;
1206
1207 char cipher_desc[256], cipher_desc_clean[256];
1208 char *p = cipher_desc, *q = cipher_desc_clean;
1209
1210 cipher = SSL_get_current_cipher(tls_session->ssl);
1211 SSL_CIPHER_description(cipher, cipher_desc, sizeof(cipher_desc));
1212
1213 /*
1214 * Cleanup the output from OpenSSL
1215 * Seems to print info in a tabular format.
1216 */
1217 while (*p != '\0') {
1218 if (isspace((uint8_t) *p)) {
1219 *q++ = *p;
1221 continue;
1222 }
1223 *q++ = *p++;
1224 }
1225 *q = '\0';
1226
1227 RDEBUG2("Cipher suite: %s", cipher_desc_clean);
1228
1229 RDEBUG2("Adding TLS session information to request");
1230 RINDENT();
1232 fr_pair_value_strdup(vp, SSL_CIPHER_get_name(cipher), false);
1233 RDEBUG2("&session-state.%pP", vp);
1234
1235 if (((size_t)tls_session->info.version >= NUM_ELEMENTS(tls_version_str)) ||
1236 !tls_version_str[tls_session->info.version]) {
1237 version = "UNKNOWN";
1238 } else {
1239 version = tls_version_str[tls_session->info.version];
1240 }
1241
1243 fr_pair_value_strdup(vp, version, false);
1244 RDEBUG2("&session-state.%pP", vp);
1245 REXDENT();
1246
1247 /*
1248 * Cache the SSL_SESSION pointer.
1249 *
1250 * Which contains all the data we need for session resumption.
1251 */
1252 if (!tls_session->session) {
1253 tls_session->session = SSL_get_session(tls_session->ssl);
1254 if (!tls_session->session) {
1255 REDEBUG("Failed getting TLS session");
1256 error:
1257 tls_session->result = FR_TLS_RESULT_ERROR;
1258 fr_tls_session_request_unbind(tls_session->ssl);
1260 }
1261 }
1262
1263 if (RDEBUG_ENABLED3) {
1264 if (SSL_SESSION_print(fr_tls_request_log_bio(request, L_DBG, L_DBG_LVL_3),
1265 tls_session->session) != 1) {
1266 } else {
1267 RDEBUG3("Failed retrieving session data");
1268 }
1269 }
1270
1271 /*
1272 * Session was resumed, add attribute to mark it as such.
1273 */
1274 if (SSL_session_reused(tls_session->ssl)) {
1275 /*
1276 * Mark the request as resumed.
1277 */
1279 vp->vp_bool = true;
1280 }
1281 }
1282
1283 /*
1284 * Get data to pack and send back to the TLS peer.
1285 */
1286 ret = BIO_ctrl_pending(tls_session->from_ssl);
1287 if (ret > 0) {
1288 ret = BIO_read(tls_session->from_ssl, tls_session->dirty_out.data,
1289 sizeof(tls_session->dirty_out.data));
1290 if (ret > 0) {
1291 tls_session->dirty_out.used = ret;
1292 } else if (BIO_should_retry(tls_session->from_ssl)) {
1293 record_init(&tls_session->dirty_in);
1294 RDEBUG2("Asking for more data in tunnel");
1295
1296 } else {
1297 fr_tls_log(NULL, NULL);
1298 record_init(&tls_session->dirty_in);
1299 goto error;
1300 }
1301 } else {
1302 /* Its clean application data, do whatever we want */
1303 record_init(&tls_session->clean_out);
1304 }
1305
1306 /*
1307 * Trash the current data in dirty_out, and synthesize
1308 * a TLS error record.
1309 *
1310 * OpensSL annoyingly provides no mechanism for us to
1311 * send alerts, and we need to send alerts as part of
1312 * RFC 5216, so this is our only option.
1313 */
1314 if (tls_session->pending_alert) fr_tls_session_alert_send(request, tls_session);
1315
1316 /* We are done with dirty_in, reinitialize it */
1317 record_init(&tls_session->dirty_in);
1318
1319 tls_session->result = FR_TLS_RESULT_SUCCESS;
1320 fr_tls_session_request_unbind(tls_session->ssl);
1321 if (SSL_is_init_finished(tls_session->ssl)) {
1322 fr_tls_conf_t *conf = fr_tls_session_conf(tls_session->ssl);
1323 if (conf->establish_session) return tls_establish_session_push(request, conf, tls_session);
1324 }
1326}
1327
1328/** Try very hard to get the SSL * into a consistent state where it's not yielded
1329 *
1330 * ...because if it's yielded, we'll probably leak thread contexts and all kinds of memory.
1331 *
1332 * @param[in] request being cancelled.
1333 * @param[in] action we're being signalled with.
1334 * @param[in] uctx the SSL * to cancel.
1335 */
1336static void tls_session_async_handshake_signal(UNUSED request_t *request, UNUSED fr_signal_t action, void *uctx)
1337{
1338 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
1339 int ret;
1340
1341 /*
1342 * We might want to set can_pause = false here
1343 * but that would trigger asserts in the
1344 * cache code.
1345 */
1346
1347 /*
1348 * If SSL_get_error returns SSL_ERROR_WANT_ASYNC
1349 * it means we're yielded in the middle of a
1350 * callback.
1351 *
1352 * Keep calling SSL_read() in a loop until we
1353 * no longer get SSL_ERROR_WANT_ASYNC, then
1354 * shut it down so it's in a consistent state.
1355 *
1356 * It'll get freed later when the request is
1357 * freed.
1358 */
1359 for (ret = tls_session->last_ret;
1360 SSL_get_error(tls_session->ssl, ret) == SSL_ERROR_WANT_ASYNC;
1361 ret = SSL_read(tls_session->ssl, tls_session->clean_out.data + tls_session->clean_out.used,
1362 sizeof(tls_session->clean_out.data) - tls_session->clean_out.used));
1363
1364 /*
1365 * Unbind the cancelled request from the SSL *
1366 */
1367 fr_tls_session_request_unbind(tls_session->ssl);
1368}
1369
1370/** Call SSL_read() to continue the TLS state machine
1371 *
1372 * This function may be called multiple times, once after every asynchronous request.
1373 *
1374 * @param[in,out] p_result UNUSED.
1375 * @param[out] priority UNUSED
1376 * @param[in] request The current request.
1377 * @param[in] uctx #fr_tls_session_t to continue.
1378 * @return
1379 * - UNLANG_ACTION_CALCULATE_RESULT - We're done with this round.
1380 * - UNLANG_ACTION_PUSHED_CHILD - Need to perform more asynchronous actions.
1381 */
1382static unlang_action_t tls_session_async_handshake_cont(rlm_rcode_t *p_result, int *priority,
1383 request_t *request, void *uctx)
1384{
1385 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
1386 int err;
1387
1388 RDEBUG3("(re-)entered state %s", __FUNCTION__);
1389
1390 /*
1391 * Magic/More magic? Although SSL_read is normally
1392 * used to read application data, it will also
1393 * continue the TLS handshake. Removing this call will
1394 * cause the handshake to fail.
1395 *
1396 * We don't ever expect to actually *receive* application
1397 * data here.
1398 *
1399 * The reason why we call SSL_read instead of SSL_accept,
1400 * or SSL_connect, as it allows this function
1401 * to be used, irrespective or whether we're acting
1402 * as a client or a server.
1403 *
1404 * If acting as a client SSL_set_connect_state must have
1405 * been called before this function.
1406 *
1407 * If acting as a server SSL_set_accept_state must have
1408 * been called before this function.
1409 */
1410 tls_session->can_pause = true;
1411 tls_session->last_ret = SSL_read(tls_session->ssl, tls_session->clean_out.data + tls_session->clean_out.used,
1412 sizeof(tls_session->clean_out.data) - tls_session->clean_out.used);
1413 tls_session->can_pause = false;
1414 if (tls_session->last_ret > 0) {
1415 tls_session->clean_out.used += tls_session->last_ret;
1416
1417 /*
1418 * Round successful, and we don't need to do any
1419 * further processing.
1420 */
1421 tls_session->result = FR_TLS_RESULT_SUCCESS;
1422 finish:
1423 /*
1424 * Was bound by caller
1425 */
1426 fr_tls_session_request_unbind(tls_session->ssl);
1428 }
1429
1430 /*
1431 * Bug in OpenSSL 3.0 - Normal handshaking behaviour
1432 * results in spurious "BIO_R_UNSUPPORTED_METHOD"
1433 * errors.
1434 *
1435 * SSL_get_error apparently returns SSL_ERROR_SSL if
1436 * there are any errors in the stack. This masks
1437 * SSL_ERROR_WANT_ASYNC and causes the handshake to
1438 * fail.
1439 *
1440 * Note: We may want some version of this code
1441 * included for all OpenSSL versions.
1442 *
1443 * It would call ERR_GET_FATAL() on each of the errors
1444 * in the stack to drain non-fatal errors and prevent
1445 * the other (more useful) return codes of
1446 * SSL_get_error from being masked. I guess we'll see
1447 * if this occurs in other scenarios.
1448 */
1449 if (SSL_get_error(tls_session->ssl, tls_session->last_ret) == SSL_ERROR_SSL) {
1450 unsigned long ssl_err;
1451
1452 /*
1453 * Some weird OpenSSL thing marking ERR_GET_REASON
1454 * as "unused". Unclear why this is done as it's
1455 * not deprecated.
1456 */
1458DIAG_OFF(used-but-marked-unused)
1459 while ((ssl_err = ERR_peek_error()) && (ERR_GET_REASON(ssl_err) == BIO_R_UNSUPPORTED_METHOD)) {
1460 (void) ERR_get_error();
1461 }
1462DIAG_ON(used-but-marked-unused)
1464 }
1465
1466 /*
1467 * Deal with asynchronous requests from OpenSSL.
1468 * These aren't actually errors, they're the
1469 * result of one of our callbacks indicating that
1470 * it'd like to perform the operation
1471 * asynchronously.
1472 */
1473 switch (err = SSL_get_error(tls_session->ssl, tls_session->last_ret)) {
1474 case SSL_ERROR_WANT_ASYNC: /* Certification validation or cache loads */
1475 {
1476 unlang_action_t ua;
1477
1478 RDEBUG3("Performing async action for libssl");
1479
1480 /*
1481 * Call this function again once we're done
1482 * asynchronously satisfying the load request.
1483 */
1484 if (unlikely(unlang_function_repeat_set(request, tls_session_async_handshake_cont) < 0)) {
1485 error:
1486 tls_session->result = FR_TLS_RESULT_ERROR;
1487 goto finish;
1488 }
1489
1490 /*
1491 * First service any pending cache actions
1492 */
1493 ua = fr_tls_cache_pending_push(request, tls_session);
1494 switch (ua) {
1495 case UNLANG_ACTION_FAIL:
1496 IGNORE(unlang_function_clear(request), int);
1497 goto error;
1498
1500 return ua;
1501
1502 default:
1503 break;
1504 }
1505
1506 /*
1507 * Next service any pending certificate
1508 * validation actions.
1509 */
1510 ua = fr_tls_verify_cert_pending_push(request, tls_session);
1511 switch (ua) {
1512 case UNLANG_ACTION_FAIL:
1513 IGNORE(unlang_function_clear(request), int);
1514 goto error;
1515
1516 default:
1517 return ua;
1518 }
1519 }
1520
1521 case SSL_ERROR_WANT_ASYNC_JOB:
1522 RERROR("No async jobs available in pool, increase thread.openssl_async_pool_max");
1523 goto error;
1524
1525 default:
1526 /*
1527 * Returns 0 if we can continue processing the handshake
1528 * Returns -1 if we encountered a fatal error.
1529 */
1530 if (fr_tls_log_io_error(request,
1531 err, "SSL_read (%s)", __FUNCTION__) < 0) goto error;
1532 return tls_session_async_handshake_done_round(p_result, priority, request, uctx);
1533 }
1534}
1535
1536/** Ingest data for another handshake round
1537 *
1538 * Advance the TLS handshake by feeding OpenSSL data from dirty_in,
1539 * and reading data from OpenSSL into dirty_out.
1540 *
1541 * Calls #tls_session_async_handshake_read to perform the actual ingestion.
1542 * #tls_session_async_handshake_read is split out because we may need to call
1543 * it multiple times, once after every async action.
1544 *
1545 * @param[in,out] p_result UNUSED.
1546 * @param[out] priority UNUSED
1547 * @param[in] request The current request.
1548 * @param[in] uctx #fr_tls_session_t to continue.
1549 * @return
1550 * - UNLANG_ACTION_CALCULATE_RESULT - We're done with this round.
1551 * - UNLANG_ACTION_PUSHED_CHILD - Need to perform more asynchronous actions.
1552 */
1553static unlang_action_t tls_session_async_handshake(rlm_rcode_t *p_result, int *priority,
1554 request_t *request, void *uctx)
1555{
1556 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
1557 int ret;
1558
1559 RDEBUG3("entered state %s", __FUNCTION__);
1560
1561 tls_session->result = FR_TLS_RESULT_IN_PROGRESS;
1562
1563 fr_tls_session_request_bind(tls_session->ssl, request); /* May be unbound in this function or asynchronously */
1564
1565 /*
1566 * This is a logic error. fr_tls_session_async_handshake
1567 * must not be called if the handshake is
1568 * complete fr_tls_session_recv must be
1569 * called instead.
1570 */
1571 if (SSL_is_init_finished(tls_session->ssl)) {
1572 REDEBUG("Attempted to continue TLS handshake, but handshake has completed");
1573 error:
1574 tls_session->result = FR_TLS_RESULT_ERROR;
1575 fr_tls_session_request_unbind(tls_session->ssl); /* Was bound in this function */
1577 }
1578
1579 if (tls_session->invalid) {
1580 REDEBUG("Preventing invalid session from continuing");
1581 goto error;
1582 }
1583
1584 /*
1585 * Feed dirty data into OpenSSL, so that is can either
1586 * process it as Application data (decrypting it)
1587 * or continue the TLS handshake.
1588 */
1589 if (tls_session->dirty_in.used) {
1590 ret = BIO_write(tls_session->into_ssl, tls_session->dirty_in.data, tls_session->dirty_in.used);
1591 if (ret != (int)tls_session->dirty_in.used) {
1592 REDEBUG("Failed writing %zu bytes to TLS BIO: %d", tls_session->dirty_in.used, ret);
1593 record_init(&tls_session->dirty_in);
1594 goto error;
1595 }
1596 record_init(&tls_session->dirty_in);
1597 }
1598
1599 return tls_session_async_handshake_cont(p_result, priority, request, uctx); /* Must unbind request, possibly asynchronously */
1600}
1601
1602/** Push a handshake call onto the stack
1603 *
1604 * We push the handshake frame (as opposed to having the caller do it),
1605 * so that we guarantee there's a frame that the handshake function can
1606 * manipulate to manage its own state.
1607 *
1608 * The result of processing this handshake round can be found in
1609 * tls_session->result.
1610 *
1611 * @param[in] request The current request.
1612 * @param[in] tls_session to continue handshaking.
1613 * @return
1614 * - UNLANG_ACTION_PUSHED_CHILD on success.
1615 * - UNLANG_ACTION_FAIL on failure.
1616 */
1617unlang_action_t fr_tls_session_async_handshake_push(request_t *request, fr_tls_session_t *tls_session)
1618{
1619 return unlang_function_push(request,
1620 tls_session_async_handshake,
1621 NULL,
1622 tls_session_async_handshake_signal,
1625 tls_session);
1626}
1627
1628/** Free a TLS session and any associated OpenSSL data
1629 *
1630 * @param session to free.
1631 * @return 0.
1632 */
1633static int _fr_tls_session_free(fr_tls_session_t *session)
1634{
1635 if (session->ssl) {
1636 SSL_set_quiet_shutdown(session->ssl, 1);
1637 SSL_shutdown(session->ssl);
1638 SSL_free(session->ssl);
1639 session->ssl = NULL;
1640 }
1641
1642 return 0;
1643}
1644
1645static void session_init(fr_tls_session_t *session)
1646{
1647 session->ssl = NULL;
1648 session->into_ssl = session->from_ssl = NULL;
1649 record_init(&session->clean_in);
1650 record_init(&session->clean_out);
1651 record_init(&session->dirty_in);
1652 record_init(&session->dirty_out);
1653
1654 memset(&session->info, 0, sizeof(session->info));
1655
1656 session->mtu = 0;
1657 session->opaque = NULL;
1658}
1659
1660/** Create a new client TLS session
1661 *
1662 * Configures a new client TLS session, configuring options, setting callbacks etc...
1663 *
1664 * @param[in] ctx to alloc session data in. Should usually be NULL unless the lifetime of the
1665 * session is tied to another talloc'd object.
1666 * @param[in] ssl_ctx containing the base configuration for this session.
1667 * @return
1668 * - A new session on success.
1669 * - NULL on error.
1670 */
1671fr_tls_session_t *fr_tls_session_alloc_client(TALLOC_CTX *ctx, SSL_CTX *ssl_ctx)
1672{
1673 int verify_mode;
1674 fr_tls_session_t *tls_session = NULL;
1675 fr_tls_conf_t *conf = fr_tls_ctx_conf(ssl_ctx);
1676
1677 MEM(tls_session = talloc_zero(ctx, fr_tls_session_t));
1678 talloc_set_destructor(tls_session, _fr_tls_session_free);
1679 fr_pair_list_init(&tls_session->extra_pairs);
1680
1681 tls_session->ssl = SSL_new(ssl_ctx);
1682 if (!tls_session->ssl) {
1683 talloc_free(tls_session);
1684 return NULL;
1685 }
1686
1687 /*
1688 * Add the message callback to identify what type of
1689 * message/handshake is passed
1690 */
1691 SSL_set_msg_callback(tls_session->ssl, fr_tls_session_msg_cb);
1692 SSL_set_msg_callback_arg(tls_session->ssl, tls_session);
1693 SSL_set_info_callback(tls_session->ssl, fr_tls_session_info_cb);
1694
1695 /*
1696 * In Client mode we only accept.
1697 *
1698 * This sets up the SSL session to work correctly with
1699 * fr_tls_session_handshake.
1700 */
1701 SSL_set_connect_state(tls_session->ssl);
1702
1703 /*
1704 * Always verify the peer certificate.
1705 */
1706 DEBUG2("Requiring Server certificate");
1707 verify_mode = SSL_VERIFY_PEER;
1708 verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1709
1710 /*
1711 * Callback should be fr_tls_verify_cert_cb but this
1712 * requires support around SSL_connect for dealing
1713 * with async.
1714 *
1715 * If the callback is NULL OpenSSL uses its own validation
1716 * function, and the flags modifies that function's
1717 * behaviour.
1718 */
1719 SSL_set_verify(tls_session->ssl, verify_mode, NULL);
1720 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
1721 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)tls_session);
1722
1723 tls_session->mtu = conf->fragment_size;
1724
1725 return tls_session;
1726}
1727
1728/** Create a new server TLS session
1729 *
1730 * Configures a new server TLS session, configuring options, setting callbacks etc...
1731 *
1732 * @param[in] ctx to alloc session data in. Should usually be NULL
1733 * unless the lifetime of the session is tied to another
1734 * talloc'd object.
1735 * @param[in] ssl_ctx containing the base configuration for this session.
1736 * @param[in] request The current #request_t.
1737 * @param[in] dynamic_mtu If greater than 100, overrides the MTU configured for the SSL_CTX.
1738 * @param[in] client_cert Whether to require a client_cert.
1739 * @return
1740 * - A new session on success.
1741 * - NULL on error.
1742 */
1743fr_tls_session_t *fr_tls_session_alloc_server(TALLOC_CTX *ctx, SSL_CTX *ssl_ctx, request_t *request, size_t dynamic_mtu, bool client_cert)
1744{
1745 fr_tls_session_t *tls_session = NULL;
1746 SSL *ssl = NULL;
1747 int verify_mode = 0;
1748 fr_pair_t *vp;
1749 fr_tls_conf_t *conf = fr_tls_ctx_conf(ssl_ctx);
1750
1751 RDEBUG2("Initiating new TLS session");
1752
1753 MEM(tls_session = talloc_zero(ctx, fr_tls_session_t));
1754
1755 ssl = SSL_new(ssl_ctx);
1756 if (ssl == NULL) {
1757 fr_tls_log(request, "Error creating new TLS session");
1758 return NULL;
1759 }
1760 fr_pair_list_init(&tls_session->extra_pairs);
1761
1762 session_init(tls_session);
1763 tls_session->ctx = ssl_ctx;
1764 tls_session->ssl = ssl;
1765 talloc_set_destructor(tls_session, _fr_tls_session_free);
1766
1767 fr_tls_session_request_bind(tls_session->ssl, request); /* Is unbound in this function */
1768
1769 /*
1770 * Initialize callbacks
1771 */
1772 tls_session->record_init = record_init;
1773 tls_session->record_close = record_close;
1774 tls_session->record_from_buff = record_from_buff;
1775 tls_session->record_to_buff = record_to_buff;
1776
1777 /*
1778 * Create & hook the BIOs to handle the dirty side of the
1779 * SSL. This is *very important* as we want to handle
1780 * the transmission part. Now the only IO interface
1781 * that SSL is aware of, is our defined BIO buffers.
1782 *
1783 * This means that all SSL IO is done to/from memory,
1784 * and we can update those BIOs from the packets we've
1785 * received.
1786 */
1787 MEM(tls_session->into_ssl = BIO_new(BIO_s_mem()));
1788 MEM(tls_session->from_ssl = BIO_new(BIO_s_mem()));
1789 SSL_set_bio(tls_session->ssl, tls_session->into_ssl, tls_session->from_ssl);
1790
1791 /*
1792 * Add the message callback to identify what type of
1793 * message/handshake is passed
1794 */
1795 SSL_set_msg_callback(ssl, fr_tls_session_msg_cb);
1796 SSL_set_msg_callback_arg(ssl, tls_session);
1797 SSL_set_info_callback(ssl, fr_tls_session_info_cb);
1798
1799 /*
1800 * This sets the context sessions can be resumed in.
1801 * This is to prevent sessions being created by one application
1802 * and used by another. In our case it prevents sessions being
1803 * reused between modules, or TLS server components such as
1804 * RADSEC.
1805 *
1806 * A context must always be set when doing session resumption
1807 * otherwise session resumption will fail.
1808 *
1809 * As the context ID must be <= 32, we digest the context
1810 * data with sha256.
1811 *
1812 * This seems to only be used for stateful session resumption
1813 * not session-tickets
1814 */
1815 if (conf->cache.mode != FR_TLS_CACHE_DISABLED) {
1816 char *context_id;
1817 EVP_MD_CTX *md_ctx;
1818 uint8_t digest[SHA256_DIGEST_LENGTH];
1819
1820 static_assert(sizeof(digest) <= SSL_MAX_SSL_SESSION_ID_LENGTH,
1821 "SSL_MAX_SSL_SESSION_ID_LENGTH must be >= SHA256_DIGEST_LENGTH");
1822 fr_assert(conf->cache.id_name);
1823
1824 if (tmpl_aexpand(tls_session, &context_id, request, conf->cache.id_name, NULL, NULL) < 0) {
1825 RPEDEBUG("Failed expanding session ID");
1826 error:
1827 fr_tls_session_request_unbind(tls_session->ssl); /* Was bound in this function */
1828 talloc_free(tls_session);
1829 return NULL;
1830 }
1831
1832 MEM(md_ctx = EVP_MD_CTX_create());
1833 EVP_DigestInit_ex(md_ctx, EVP_sha256(), NULL);
1834 EVP_DigestUpdate(md_ctx, context_id, talloc_array_length(context_id) - 1);
1835 EVP_DigestFinal_ex(md_ctx, digest, NULL);
1836 EVP_MD_CTX_destroy(md_ctx);
1837 talloc_free(context_id);
1838
1839 if (!fr_cond_assert(SSL_set_session_id_context(tls_session->ssl,
1840 digest, sizeof(digest)) == 1)) goto error;
1841 }
1842
1843 /*
1844 * Add the session certificate to the session.
1845 */
1846 vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_tls_session_cert_file);
1847 if (vp) {
1848 RDEBUG2("Loading TLS session certificate \"%pV\"", &vp->data);
1849
1850 if (SSL_use_certificate_file(tls_session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) {
1851 fr_tls_log(request, "Failed loading TLS session certificate \"%s\"",
1852 vp->vp_strvalue);
1853 goto error;
1854 }
1855
1856 if (SSL_use_PrivateKey_file(tls_session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) {
1857 fr_tls_log(request, "Failed loading TLS session certificate \"%s\"",
1858 vp->vp_strvalue);
1859 goto error;
1860 }
1861
1862 if (SSL_check_private_key(tls_session->ssl) != 1) {
1863 fr_tls_log(request, "Failed validating TLS session certificate \"%s\"",
1864 vp->vp_strvalue);
1865 goto error;
1866 }
1867 /*
1868 * Better to perform explicit checks, than rely
1869 * on OpenSSL's opaque error messages.
1870 */
1871 } else {
1872 if (!conf->chains || !conf->chains[0]->private_key_file) {
1873 ERROR("TLS Server requires a private key file");
1874 goto error;
1875 }
1876
1877 if (!conf->chains || !conf->chains[0]->certificate_file) {
1878 ERROR("TLS Server requires a certificate file");
1879 goto error;
1880 }
1881 }
1882
1883 /** Dynamic toggle for allowing disallowing client certs
1884 *
1885 * This is mainly used for testing in environments where we can't
1886 * get test credentials for the host.
1887 */
1888 vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_tls_session_require_client_cert);
1889 if (vp) client_cert = vp->vp_bool;
1890
1891 /*
1892 * In Server mode we only accept.
1893 *
1894 * This sets up the SSL session to work correctly with
1895 * fr_tls_session_handshake.
1896 */
1897 SSL_set_accept_state(tls_session->ssl);
1898
1899 /*
1900 * Verify the peer certificate, if asked.
1901 */
1902 if (client_cert) {
1903 RDEBUG2("Setting verify mode to require certificate from client");
1904 verify_mode = SSL_VERIFY_PEER;
1905 verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1906 verify_mode |= SSL_VERIFY_CLIENT_ONCE;
1907 }
1908 tls_session->verify_client_cert = client_cert;
1909
1910 SSL_set_verify(tls_session->ssl, verify_mode, fr_tls_verify_cert_cb);
1911 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
1912 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)tls_session);
1913
1914 tls_session->mtu = conf->fragment_size;
1915 if (dynamic_mtu > 100 && dynamic_mtu < tls_session->mtu) {
1916 RDEBUG2("Setting fragment_len to %zu from dynamic_mtu", dynamic_mtu);
1917 tls_session->mtu = dynamic_mtu;
1918 }
1919
1920 if (conf->cache.mode != FR_TLS_CACHE_DISABLED) {
1921 tls_session->allow_session_resumption = true; /* otherwise it's false */
1922 fr_tls_cache_session_alloc(tls_session);
1923 }
1924
1925 fr_tls_session_request_unbind(tls_session->ssl); /* Was bound in this function */
1926
1927 return tls_session;
1928}
1929
1930static unlang_action_t tls_new_session_result(UNUSED rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, UNUSED void *uctx)
1931{
1932 request_t *parent = request->parent;
1933
1935
1936 /*
1937 * Copy control attributes back to the parent.
1938 */
1939 if (fr_pair_list_copy(parent->control_ctx, &parent->control_pairs, &request->control_pairs) < 0) return UNLANG_ACTION_FAIL;
1940
1942}
1943
1944unlang_action_t fr_tls_new_session_push(request_t *request, fr_tls_conf_t const *tls_conf) {
1945 request_t *child;
1946 fr_pair_t *vp;
1947
1948 MEM(child = unlang_subrequest_alloc(request, dict_tls));
1949 request = child;
1950
1952 vp->vp_uint32 = enum_tls_packet_type_new_session->vb_uint32;
1953
1954 if (unlang_subrequest_child_push(NULL, child,
1956 .enable = true,
1957 .unique_ptr = child->parent
1958 },
1959 true, UNLANG_SUB_FRAME) < 0) {
1960 return UNLANG_ACTION_FAIL;
1961 }
1962 if (unlang_function_push(child, NULL, tls_new_session_result, NULL, 0, UNLANG_SUB_FRAME, NULL) < 0) return UNLANG_ACTION_FAIL;
1963
1964 if (unlang_call_push(child, tls_conf->virtual_server, UNLANG_SUB_FRAME) < 0) {
1965 return UNLANG_ACTION_FAIL;
1966 }
1968}
1969#endif /* WITH_TLS */
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition action.h:39
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:37
static int const char char buffer[256]
Definition acutest.h:576
int const char int line
Definition acutest.h:702
#define fr_base16_decode(_err, _out, _in, _no_trailing)
Definition base16.h:95
#define IGNORE(_expr, _type)
Definition build.h:507
#define DIAG_UNKNOWN_PRAGMAS
Definition build.h:456
#define DIAG_ON(_x)
Definition build.h:458
#define unlikely(_x)
Definition build.h:381
#define UNUSED
Definition build.h:315
#define NUM_ELEMENTS(_t)
Definition build.h:337
#define DIAG_OFF(_x)
Definition build.h:457
unlang_action_t unlang_call_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
Push a call frame onto the stack.
Definition call.c:147
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:514
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:139
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
static fr_slen_t err
Definition dict.h:824
static fr_slen_t in
Definition dict.h:824
int unlang_function_clear(request_t *request)
Clear pending repeat function calls, and remove the signal handler.
Definition function.c:160
#define unlang_function_repeat_set(_request, _repeat)
Set a new repeat function for an existing function frame.
Definition function.h:89
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition function.h:111
#define UNLANG_SUB_FRAME
Definition interpret.h:36
fr_dict_t const * dict_tls
Definition base.c:79
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:443
#define DEBUG_ENABLED2
True if global debug level 1-2 messages are enabled.
Definition log.h:258
#define DEBUG3(_fmt,...)
Definition log.h:266
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
Definition log.h:528
#define RWDEBUG(fmt,...)
Definition log.h:361
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition log.h:335
#define RDEBUG3(fmt,...)
Definition log.h:343
#define DEBUG_ENABLED4
True if global debug level 1-3 messages are enabled.
Definition log.h:260
#define RHEXDUMP4(_data, _len, _fmt,...)
Definition log.h:706
#define RERROR(fmt,...)
Definition log.h:298
#define DEBUG4(_fmt,...)
Definition log.h:267
#define ROPTIONAL_ENABLED(_e_request, _e_global)
Check if a debug level is set by the request (if !NULL) or by the global log.
Definition log.h:542
#define RPEDEBUG(fmt,...)
Definition log.h:376
#define RHEXDUMP3(_data, _len, _fmt,...)
Definition log.h:705
#define RDEBUG4(fmt,...)
Definition log.h:344
#define DEBUG_ENABLED3
True if global debug level 1-3 messages are enabled.
Definition log.h:259
#define RDEBUG_ENABLED4
True if request debug level 1-4 messages are enabled.
Definition log.h:336
#define HEXDUMP4(_data, _len, _fmt,...)
Definition log.h:724
#define RPWDEBUG2(fmt,...)
Definition log.h:367
#define REDEBUG4(fmt,...)
Definition log.h:374
#define RINDENT()
Indent R* messages by one level.
Definition log.h:430
HIDDEN fr_dict_attr_t const * attr_tls_packet_type
HIDDEN fr_dict_attr_t const * attr_session_resumed
HIDDEN fr_dict_attr_t const * attr_tls_session_version
HIDDEN fr_dict_attr_t const * attr_tls_session_require_client_cert
fr_value_box_t const * enum_tls_packet_type_new_session
HIDDEN fr_dict_attr_t const * attr_tls_client_error_code
fr_value_box_t const * enum_tls_packet_type_establish_session
HIDDEN fr_dict_attr_t const * attr_tls_session_cipher_suite
HIDDEN fr_dict_attr_t const * attr_tls_psk_identity
HIDDEN fr_dict_attr_t const * attr_tls_session_cert_file
talloc_free(reap)
@ L_DBG_LVL_3
3rd highest priority debug messages (-xxx | -Xx).
Definition log.h:72
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:59
ssize_t xlat_eval(char *out, size_t outlen, request_t *request, char const *fmt, xlat_escape_legacy_t escape, void const *escape_ctx)
unsigned char uint8_t
#define UINT8_MAX
static size_t used
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
Definition misc.h:59
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition nbo.h:146
int fr_pair_list_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from)
Duplicate a list of pairs.
Definition pair.c:2319
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition pair.c:2634
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
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, bool tainted)
Convert string value to native attribute value.
Definition pair.c:2589
#define fr_assert(_expr)
Definition rad_assert.h:38
#define pair_update_request(_attr, _da)
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG_ENABLED2()
Definition radclient.h:50
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define DEBUG2(fmt,...)
Definition radclient.h:43
static rs_t * conf
Definition radsniff.c:53
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
#define FR_SBUFF_IN(_start, _len_or_end)
#define pair_prepend_request(_attr, _da)
Allocate and prepend a fr_pair_t to the request list.
Definition pair.h:77
#define pair_update_session_state(_attr, _da)
Return or allocate a fr_pair_t in the session_state list.
Definition pair.h:151
#define tmpl_aexpand(_ctx, _out, _request, _vpt, _escape, _escape_ctx)
Expand a tmpl to a C type, allocing a new buffer to hold the string.
Definition tmpl.h:1070
fr_signal_t
Signals that can be generated/processed by request signal handlers.
Definition signal.h:38
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
fr_pair_t * vp
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition strlcpy.c:34
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
request_t * unlang_subrequest_alloc(request_t *parent, fr_dict_t const *namespace)
Allocate a subrequest to run through a virtual server at some point in the future.
Definition subrequest.c:287
int unlang_subrequest_child_push(rlm_rcode_t *out, request_t *child, unlang_subrequest_session_t const *session, bool free_child, bool top_frame)
Push a pre-existing child back onto the stack as a subrequest.
close(uq->fd)
static fr_slen_t parent
Definition pair.h:851
static fr_slen_t data
Definition value.h:1265
static size_t char fr_sbuff_t size_t inlen
Definition value.h:997
static size_t char ** out
Definition value.h:997