The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
base.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: 1b6cf4ca7f583d137ce887e5a259b6505f19330e $
19 *
20 * @file src/lib/tls/base.c
21 * @brief Initialise OpenSSL
22 *
23 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
24 */
25RCSID("$Id: 1b6cf4ca7f583d137ce887e5a259b6505f19330e $")
26USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
27
28#ifdef WITH_TLS
29#define LOG_PREFIX "tls"
30
31#include "log.h"
32#include "bio.h"
33#include "dtls.h"
34
35#include <sys/mman.h>
36#include <openssl/conf.h>
37#include <openssl/provider.h>
38
39#include <freeradius-devel/server/base.h>
40#include <freeradius-devel/tls/attrs.h>
41#include <freeradius-devel/tls/base.h>
42#include <freeradius-devel/util/atexit.h>
43#include <freeradius-devel/util/debug.h>
44#include <freeradius-devel/util/math.h>
45#include <freeradius-devel/util/syserror.h>
46#include <freeradius-devel/util/md5.h>
47#include <freeradius-devel/util/md4.h>
48
49static uint32_t openssl_instance_count = 0;
50
51/** How big of a stack we allocate, taken from the default thread stack size
52 */
53static size_t openssl_stack_size;
54
55/** The context which holds any memory OpenSSL allocates
56 *
57 * This should be used to work around memory leaks in the OpenSSL.
58 */
59_Thread_local TALLOC_CTX *ssl_talloc_ctx;
60
61/** Used to control freeing of thread local OpenSSL resources
62 *
63 */
64static _Thread_local bool *async_pool_init;
65
66static OSSL_PROVIDER *openssl_default_provider = NULL;
67static OSSL_PROVIDER *openssl_legacy_provider = NULL;
68
69static uint32_t tls_instance_count = 0;
70
73fr_dict_t const *dict_tls;
74fr_dict_t const *dict_der;
75
76extern fr_dict_autoload_t tls_dict[];
77fr_dict_autoload_t tls_dict[] = {
78 { .out = &dict_freeradius, .proto = "freeradius" },
79 { .out = &dict_tls, .proto = "tls" },
80 { .out = &dict_der, .proto = "der" },
81
83};
84
87
88/*
89 * Certificate decoding attributes
90 */
110
118
123
131
133
139
145
147
148extern fr_dict_attr_autoload_t tls_dict_attr[];
149fr_dict_attr_autoload_t tls_dict_attr[] = {
150 { .out = &attr_allow_session_resumption, .name = "Allow-Session-Resumption", .type = FR_TYPE_BOOL, .dict = &dict_freeradius },
151 { .out = &attr_session_resumed, .name = "EAP-Session-Resumed", .type = FR_TYPE_BOOL, .dict = &dict_freeradius },
152
153 /*
154 * Certificate decoding attributes
155 */
156 { .out = &attr_tls_certificate, .name = "TLS-Certificate", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
157 { .out = &attr_tls_certificate_serial, .name = "TLS-Certificate.Serial", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
158 { .out = &attr_tls_certificate_signature, .name = "TLS-Certificate.Signature", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
159 { .out = &attr_tls_certificate_signature_algorithm, .name = "TLS-Certificate.Signature-Algorithm", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
160 { .out = &attr_tls_certificate_issuer, .name = "TLS-Certificate.Issuer", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
161 { .out = &attr_tls_certificate_not_before, .name = "TLS-Certificate.Not-Before", .type = FR_TYPE_DATE, .dict = &dict_freeradius },
162 { .out = &attr_tls_certificate_not_after, .name = "TLS-Certificate.Not-After", .type = FR_TYPE_DATE, .dict = &dict_freeradius },
163 { .out = &attr_tls_certificate_subject, .name = "TLS-Certificate.Subject", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
164 { .out = &attr_tls_certificate_common_name, .name = "TLS-Certificate.Common-Name", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
165 { .out = &attr_tls_certificate_subject_alt_name_dns, .name = "TLS-Certificate.Subject-Alt-Name-Dns", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
166 { .out = &attr_tls_certificate_subject_alt_name_email, .name = "TLS-Certificate.Subject-Alt-Name-Email", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
167 { .out = &attr_tls_certificate_subject_alt_name_upn, .name = "TLS-Certificate.Subject-Alt-Name-Upn", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
168 { .out = &attr_tls_certificate_x509v3_extended_key_usage, .name = "TLS-Certificate.X509v3-Extended-Key-Usage", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
169 { .out = &attr_tls_certificate_x509v3_subject_key_identifier, .name = "TLS-Certificate.X509v3-Subject-Key-Identifier", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
170 { .out = &attr_tls_certificate_x509v3_authority_key_identifier, .name = "TLS-Certificate.X509v3-Authority-Key-Identifier", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
171 { .out = &attr_tls_certificate_x509v3_basic_constraints, .name = "TLS-Certificate.X509v3-Basic-Constraints", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
172 { .out = &attr_tls_certificate_x509v3_crl_distribution_points, .name = "TLS-Certificate.X509v3-CRL-Distribution-Points", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
173 { .out = &attr_tls_certificate_ocsp_uri, .name = "TLS-Certificate.OCSP-URI", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
174 { .out = &attr_tls_certificate_ocsp_cert_id, .name = "TLS-Certificate.OCSP-Cert-Id", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
175
176 { .out = &attr_tls_certificate_chain_depth, .name = "TLS-Certificate-Chain-Depth", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
177 { .out = &attr_tls_client_error_code, .name = "TLS-Client-Error-Code", .type = FR_TYPE_UINT8, .dict = &dict_freeradius },
178 { .out = &attr_tls_ocsp_cert_valid, .name = "TLS-OCSP-Cert-Valid", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
179 { .out = &attr_tls_ocsp_next_update, .name = "TLS-OCSP-Next-Update", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
180 { .out = &attr_tls_ocsp_response, .name = "TLS-OCSP-Response", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
181 { .out = &attr_tls_psk_identity, .name = "TLS-PSK-Identity", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
182 { .out = &attr_tls_psk_key, .name = "TLS-PSK-Key", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
183
184 { .out = &attr_tls_session_cert_file, .name = "TLS-Session-Certificate-File", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
185 { .out = &attr_tls_session_require_client_cert, .name = "TLS-Session-Require-Client-Certificate", .type = FR_TYPE_BOOL, .dict = &dict_freeradius },
186 { .out = &attr_tls_session_cipher_suite, .name = "TLS-Session-Cipher-Suite", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
187 { .out = &attr_tls_session_version, .name = "TLS-Session-Version", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
188
189 { .out = &attr_tls_client_hello, .name = "TLS-Client-Hello", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
190 { .out = &attr_tls_client_hello_tls_version, .name = "TLS-Client-Hello.TLS-Version", .type = FR_TYPE_UINT16, .dict = &dict_freeradius },
191 { .out = &attr_tls_client_hello_cipher, .name = "TLS-Client-Hello.Cipher", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
192 { .out = &attr_tls_client_hello_sig_algo, .name = "TLS-Client-Hello.Signature-Algorithm", .type = FR_TYPE_UINT16, .dict = &dict_freeradius },
193 { .out = &attr_tls_client_hello_supported_group, .name = "TLS-Client-Hello.Supported-Group", .type = FR_TYPE_UINT16, .dict = &dict_freeradius },
194 { .out = &attr_tls_client_hello_ec_point_format, .name = "TLS-Client-Hello.EC-Point-Format", .type = FR_TYPE_UINT8, .dict = &dict_freeradius },
195 { .out = &attr_tls_client_hello_psk_key_mode, .name = "TLS-Client-Hello.PSK-Key-Mode", .type = FR_TYPE_UINT8, .dict = &dict_freeradius },
196
197 { .out = &attr_module_failure_message, .name = "Module-Failure-Message", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
198
199 /*
200 * Eventually all TLS attributes will be in the TLS dictionary
201 */
202 { .out = &attr_tls_error, .name = "Error", .type = FR_TYPE_UINT32, .dict = &dict_tls },
203 { .out = &attr_tls_alert, .name = "Alert", .type = FR_TYPE_STRUCT, .dict = &dict_tls },
204 { .out = &attr_tls_alert_level, .name = "Alert.Level", .type = FR_TYPE_UINT8, .dict = &dict_tls },
205 { .out = &attr_tls_alert_description, .name = "Alert.Description", .type = FR_TYPE_UINT8, .dict = &dict_tls },
206 { .out = &attr_tls_alpn, .name = "ALPN", .type = FR_TYPE_STRING, .dict = &dict_tls },
207
208 { .out = &attr_tls_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_tls },
209 { .out = &attr_tls_session_data, .name = "Session-Data", .type = FR_TYPE_OCTETS, .dict = &dict_tls },
210 { .out = &attr_tls_session_id, .name = "Session-Id", .type = FR_TYPE_OCTETS, .dict = &dict_tls },
211 { .out = &attr_tls_session_resumed, .name = "Session-Resumed", .type = FR_TYPE_BOOL, .dict = &dict_tls },
212 { .out = &attr_tls_session_ttl, .name = "Session-TTL", .type = FR_TYPE_TIME_DELTA, .dict = &dict_tls },
213
214 { .out = &attr_der_certificate, .name = "Certificate", .type = FR_TYPE_TLV, .dict = &dict_der },
215
217};
218
219/*
220 * request types
221 */
232
233/*
234 * response types
235 */
239
240/*
241 * session resumption
242 */
245
246extern fr_dict_enum_autoload_t tls_dict_enum[];
247fr_dict_enum_autoload_t tls_dict_enum[] = {
248 { .out = &enum_tls_packet_type_load_session, .name = "Load-Session", .attr = &attr_tls_packet_type },
249 { .out = &enum_tls_packet_type_store_session, .name = "Store-Session", .attr = &attr_tls_packet_type },
250 { .out = &enum_tls_packet_type_clear_session, .name = "Clear-Session", .attr = &attr_tls_packet_type },
251 { .out = &enum_tls_packet_type_verify_certificate, .name = "Verify-Certificate", .attr = &attr_tls_packet_type },
252 { .out = &enum_tls_packet_type_new_session, .name = "New-Session", .attr = &attr_tls_packet_type },
253 { .out = &enum_tls_packet_type_establish_session, .name = "Establish-Session", .attr = &attr_tls_packet_type },
254 { .out = &enum_tls_packet_type_fail_session, .name = "Fail-Session", .attr = &attr_tls_packet_type },
255 { .out = &enum_tls_packet_type_encode_session, .name = "Encode-Session", .attr = &attr_tls_packet_type },
256 { .out = &enum_tls_packet_type_decode_session, .name = "Decode-Session", .attr = &attr_tls_packet_type },
257 { .out = &enum_tls_packet_type_load_psk, .name = "Load-PSK", .attr = &attr_tls_packet_type },
258
259 { .out = &enum_tls_packet_type_success, .name = "Success", .attr = &attr_tls_packet_type },
260 { .out = &enum_tls_packet_type_failure, .name = "Failure", .attr = &attr_tls_packet_type },
261 { .out = &enum_tls_packet_type_notfound, .name = "Notfound", .attr = &attr_tls_packet_type },
262
264};
265
266/*
267 * Updated by threads.c in the server, and left alone for everyone else.
268 */
269int fr_tls_max_threads = 1;
270
271/** Allocate memory for OpenSSL in the NULL context
272 *
273 * @param len to alloc.
274 * @return realloc.
275 */
276static void *fr_openssl_talloc(size_t len, char const *file, NDEBUG_UNUSED int line)
277{
278 static char const *async_file;
279 void *chunk;
280
281 if (!file) {
282 chunk = talloc_array(ssl_talloc_ctx, uint8_t, len);
283
284#ifndef NDEBUG
285 talloc_set_name(chunk, "fr_openssl_talloc");
286#endif
287 return chunk;
288 }
289
290 /*
291 * Cache the filename pointer for the async_posix.c
292 * source file, so we can figure out when we're
293 * being asked for stack memory.
294 *
295 * This is terrible, we're basically guessing at the
296 * stack size. OpenSSL 3.1.0 will have proper
297 * allocation functions so we can something more
298 * sensible.
299 */
300 if (!async_file) {
301 char const *sep;
302
303 sep = strrchr(file, '/');
304 if (!sep) {
305 sep = file;
306 } else {
307 sep++;
308 }
309 if (strcmp(sep, "async_posix.c") == 0) {
310 async_file = file;
311 alloc_stack:
312 len *= 4;
313 }
314 } else if (file == async_file) goto alloc_stack;
315
316 chunk = talloc_array(ssl_talloc_ctx, uint8_t, len);
317#ifndef NDEBUG
318 talloc_set_name(chunk, "%s:%d", file, line);
319#endif
320 return chunk;
321}
322
323/** Reallocate memory for OpenSSL in the NULL context
324 *
325 * @param old memory to realloc.
326 * @param len to extend to.
327 * @return realloced memory.
328 */
329static void *fr_openssl_talloc_realloc(void *old, size_t len, NDEBUG_UNUSED char const *file, NDEBUG_UNUSED int line)
330{
331 void *chunk;
332
333 chunk = talloc_realloc_size(ssl_talloc_ctx, old, len);
334#ifndef NDEBUG
335 talloc_set_name(chunk, "%s:%d", file, line);
336#endif
337 return chunk;
338}
339
340/** Free memory allocated by OpenSSL
341 *
342 * @param to_free memory to free.
343 */
344#ifdef NDEBUG
345/*
346 * If we're not debugging, use only the filename. Otherwise the
347 * cost of snprintf() is too large.
348 */
349static void fr_openssl_talloc_free(void *to_free, char const *file, UNUSED int line)
350{
351 (void)_talloc_free(to_free, file);
352}
353#else
354static void fr_openssl_talloc_free(void *to_free, char const *file, int line)
355{
356 char buffer[256];
357
358 snprintf(buffer, sizeof(buffer), "%s:%i", file, line);
359 (void)_talloc_free(to_free, buffer);
360}
361#endif
362
363/** Cleanup async pools if the thread exits
364 *
365 */
366static int _openssl_thread_free(void *init)
367{
368 ASYNC_cleanup_thread();
369 return talloc_free(init);
370}
371
372/** Perform thread-specific initialisation for OpenSSL
373 *
374 * Async contexts are what OpenSSL uses to track
375 *
376 * @param[in] async_pool_size_init The initial number of async contexts
377 * we keep in the pool.
378 * @param[in] async_pool_size_max The maximum number of async contexts
379 * we keep in the thread-local pool.
380 * @return
381 * - 0 on success.
382 * - -1 on failure.
383 */
384int fr_openssl_thread_init(size_t async_pool_size_init, size_t async_pool_size_max)
385{
386 /*
387 * Hack to use thread local destructor code
388 */
389 if (!async_pool_init) {
390 bool *init = talloc_zero(NULL, bool);
391
392 if (ASYNC_init_thread(async_pool_size_max, async_pool_size_init) != 1) {
393 fr_openssl_log_perror(NULL, "Failed initialising OpenSSL async context pool");
394 return -1;
395 }
396
397 fr_atexit_thread_local(async_pool_init, _openssl_thread_free, init);
398 }
399
400 return 0;
401}
402
403/** Free any memory alloced by libssl
404 *
405 * OpenSSL >= 1.1.0 uses an atexit handler to automatically free
406 * memory. However, we need to call OPENSSL_cleanup manually because
407 * some of the SSL ctx is parented to the main config which will get
408 * freed before the atexit handler, causing a segfault on exit.
409 */
410void fr_openssl_free(void)
411{
412 if (--openssl_instance_count > 0) return;
413
414 fr_tls_log_free();
415
416 fr_tls_bio_free();
417
418 fr_md5_openssl_free();
419 fr_md4_openssl_free();
420}
421
422static void _openssl_provider_free(void)
423{
424 if (openssl_default_provider && !OSSL_PROVIDER_unload(openssl_default_provider)) {
425 fr_openssl_log_perror(NULL, "Failed unloading default provider");
426 }
427 openssl_default_provider = NULL;
428
429 if (openssl_legacy_provider && !OSSL_PROVIDER_unload(openssl_legacy_provider)) {
430 fr_openssl_log_perror(NULL, "Failed unloading legacy provider");
431 }
432 openssl_legacy_provider = NULL;
433}
434
435static int fr_openssl_cleanup(UNUSED void *uctx)
436{
437 OPENSSL_cleanup();
438 return 0;
439}
440
441#ifdef HAVE_ASYNC_SET_MEM_FUNCTIONS
442
443static void *fr_openssl_stack_alloc(size_t *len)
444{
445 void *stack;
446
447 /*
448 * Use mmap to sparsely allocate the stack
449 */
450#if defined(__linux__) || defined(__FreeBSD__)
451 stack = mmap(NULL, openssl_stack_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_STACK, -1, 0);
452#else
453 stack = mmap(NULL, openssl_stack_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
454#endif
455 if (stack == MAP_FAILED) {
456 fr_openssl_log_perror(NULL, "Failed allocating OpenSSL stack: %s", fr_syserror(errno));
457 return NULL;
458 }
459 *len = openssl_stack_size;
460
461 return stack;
462}
463
464static void fr_openssl_stack_free(void *stack)
465{
466 munmap(stack, openssl_stack_size);
467}
468#endif
469
470/** Add all the default ciphers and message digests to our context.
471 *
472 * This should be called exactly once from main, before reading the main config
473 * or initialising any modules.
474 */
475int fr_tls_session_ex_index = -1;
476
477int fr_openssl_init(void)
478{
479 int rcode;
480 pthread_attr_t tattr;
481
482 if (openssl_instance_count > 0) {
483 openssl_instance_count++;
484 return 0;
485 }
486
487 pthread_attr_init(&tattr);
488 rcode = pthread_attr_getstacksize(&tattr, &openssl_stack_size);
489 pthread_attr_destroy(&tattr);
490
491 if (rcode != 0) {
492 fr_openssl_log_perror(NULL, "Failed getting stack size");
493 return -1;
494 }
495
496 /*
497 * This will only fail if memory has already been allocated
498 * by OpenSSL.
499 */
500 if (CRYPTO_set_mem_functions(fr_openssl_talloc, fr_openssl_talloc_realloc, fr_openssl_talloc_free) != 1) {
501 fr_openssl_log_perror(NULL, "Failed to set OpenSSL memory allocation functions. fr_openssl_init() called too late");
502 return -1;
503 }
504
505 /*
506 * Setup custom memory allocators for allocating greenthread
507 * stacks, so we can add guard pages.
508 */
509#ifdef HAVE_ASYNC_SET_MEM_FUNCTIONS
510 if (ASYNC_set_mem_functions(fr_openssl_stack_alloc, fr_openssl_stack_free) != 1) {
511 fr_openssl_log_perror(NULL, "Failed to set OpenSSL async stack allocation functions");
512 return -1;
513 }
514#endif
515
516 /*
517 * NO_ATEXIT has no effect if init is done after
518 * loading providers, and we need to control the
519 * exit handler as it needs to be executed last
520 * after all the EVP_MD ctx have been called, as
521 * they may unload elements of providers once all
522 * the contexts have been cleaned up.
523 */
524 if (OPENSSL_init_ssl(OPENSSL_INIT_NO_ATEXIT | OPENSSL_INIT_LOAD_CONFIG, NULL) != 1) {
525 fr_openssl_log_perror(NULL, "Failed calling OPENSSL_init_crypto()");
526 return -1;
527 }
528
529 /*
530 * Load the default provider for most algorithms
531 */
532 openssl_default_provider = OSSL_PROVIDER_load(NULL, "default");
533 if (!openssl_default_provider) {
534 fr_openssl_log_perror(NULL, "Failed loading default provider");
535 return -1;
536 }
537
538 /*
539 * Needed for MD4
540 *
541 * https://www.openssl.org/docs/man3.0/man7/migration_guide.html#Legacy-Algorithms
542 */
543 openssl_legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
544 if (!openssl_legacy_provider) {
545 fr_openssl_log_perror(NULL, "Failed loading legacy provider");
546 return -1;
547 }
548
549 /*
550 * It's best to use OpenSSL's cleanup stack
551 * as then everything is cleaned up relative
552 * to the OPENSSL_cleanup() call.
553 */
554 OPENSSL_atexit(_openssl_provider_free);
555
556 /*
557 * SHA256 is in all versions of OpenSSL, but isn't
558 * initialized by default. It's needed for WiMAX
559 * certificates.
560 */
561 EVP_add_digest(EVP_sha256());
562
563 /*
564 * Allocate an index via the OpenSSL API. This tells
565 * OpenSSL that the ex_data pointer can be duplicated
566 * when the SSL_SESSION is duplicated.
567 *
568 * No callbacks are needed: the default is to copy the
569 * pointer, which is what we need. The #fr_tls_session_t
570 * outlives every SSL_SESSION which points to it.
571 */
572 fr_tls_session_ex_index = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, NULL);
573 if (fr_tls_session_ex_index < 0) {
574 fr_openssl_log_perror(NULL, "Failed allocating an SSL_SESSION ex_data index");
575 return -1;
576 }
577
578 fr_tls_log_init();
579
580 fr_tls_bio_init();
581
582 /*
583 * The key every DTLS cookie is generated with, see
584 * fr_dtls_cookie_generate_cb().
585 */
586 if (fr_dtls_cookie_init() < 0) {
587 fr_openssl_log_perror(NULL, "Failed generating the DTLS cookie key");
588 return -1;
589 }
590
591 fr_md5_openssl_init();
592 fr_md4_openssl_init();
593
594 /*
595 * Use an atexit handler to try and ensure
596 * that OpenSSL gets freed last.
597 *
598 * All EVP_*ctxs need to be freed before we
599 * de-initialise the libraries else we get
600 * crashes (at least with OpenSSL 3.0.1).
601 */
602 fr_atexit_global(fr_openssl_cleanup, NULL);
603
604 openssl_instance_count++;
605
606 return 0;
607}
608
609/** Enable or disable fips mode
610 *
611 * @param[in] enabled If true enable fips mode if false disable fips mode.
612 * @return
613 * - 0 on success.
614 * - -1 on failure
615 */
616int fr_openssl_fips_mode(bool enabled)
617{
618 if (!EVP_set_default_properties(NULL, enabled ? "fips=yes" : "-fips")) {
619 fr_openssl_log_perror(NULL, "Failed %s OpenSSL FIPS mode", enabled ? "enabling" : "disabling");
620 return -1;
621 }
622
623 /*
624 * Swap the MD4 / MD5 functions as appropriate.
625 */
626 if (enabled) {
627 fr_md5_openssl_init();
628 fr_md4_openssl_init();
629 } else {
630 fr_md5_openssl_free();
631 fr_md4_openssl_free();
632 }
633
634 return 0;
635}
636
637/** Load dictionary attributes
638 *
639 * This is a separate function because of ordering issues.
640 * OpenSSL may need to be initialised before anything else
641 * including the dictionary loader.
642 *
643 * fr_openssl_free will unload both the dictionary and the
644 * OpenSSL library.
645 */
646int fr_tls_dict_init(void)
647{
648 if (tls_instance_count > 0) {
649 tls_instance_count++;
650 return 0;
651 }
652
653 tls_instance_count++;
654
655 if (fr_dict_autoload(tls_dict) < 0) {
656 PERROR("Failed initialising protocol library");
657 fail:
658 tls_instance_count--;
659 fr_openssl_free();
660 return -1;
661 }
662
663 if (fr_dict_attr_autoload(tls_dict_attr) < 0) {
664 PERROR("Failed resolving attributes");
665 goto fail;
666 }
667
668 if (fr_dict_enum_autoload(tls_dict_enum) < 0) {
669 PERROR("Failed resolving enums");
670 goto fail;
671 }
672
673 return 0;
674}
675
676void fr_tls_dict_free(void)
677{
678 if (--tls_instance_count > 0) return;
679
680 fr_dict_autofree(tls_dict);
681}
682#endif /* WITH_TLS */
static int const char char buffer[256]
Definition acutest.h:641
int const char * file
Definition acutest.h:855
void int line
Definition acutest.h:810
#define _Thread_local
Definition atexit.h:213
#define fr_atexit_global(_func, _uctx)
Add a free function to the global free list.
Definition atexit.h:58
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition atexit.h:224
#define USES_APPLE_DEPRECATED_API
Definition build.h:590
#define RCSID(id)
Definition build.h:603
#define NDEBUG_UNUSED
Definition build.h:426
#define UNUSED
Definition build.h:415
int fr_dict_enum_autoload(fr_dict_enum_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition dict_util.c:4493
#define fr_dict_autofree(_to_free)
Definition dict.h:937
fr_value_box_t const ** out
Enumeration value.
Definition dict.h:305
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:316
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:329
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition dict_util.c:4532
#define fr_dict_autoload(_to_load)
Definition dict.h:934
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:335
Specifies an attribute which must be present for the module to function.
Definition dict.h:315
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:328
Specifies a value which must be present for the module to function.
Definition dict.h:304
talloc_free(hp)
static fr_dict_t const * dict_freeradius
Definition base.c:37
fr_dict_attr_t const * attr_tls_certificate
Attribute definitions for lib curl.
Definition base.c:36
static fr_dict_t const * dict_tls
Definition base.c:77
fr_dict_t const * dict_radius
Definition base.c:76
static fr_dict_attr_t const * attr_module_failure_message
Definition log.c:206
#define PERROR(_fmt,...)
Definition log.h:233
fr_value_box_t const * enum_tls_packet_type_store_session
fr_value_box_t const * enum_tls_packet_type_load_psk
HIDDEN fr_dict_attr_t const * attr_tls_certificate_subject
HIDDEN fr_dict_attr_t const * attr_tls_certificate_x509v3_extended_key_usage
HIDDEN fr_dict_attr_t const * attr_tls_packet_type
HIDDEN fr_dict_attr_t const * attr_tls_certificate_x509v3_authority_key_identifier
HIDDEN fr_dict_attr_t const * attr_session_resumed
fr_value_box_t const * enum_tls_packet_type_failure
HIDDEN fr_dict_attr_t const * attr_tls_session_resumed
HIDDEN fr_dict_attr_t const * attr_tls_session_version
HIDDEN fr_dict_attr_t const * attr_tls_ocsp_cert_valid
HIDDEN fr_dict_attr_t const * attr_tls_alert_level
HIDDEN fr_dict_attr_t const * attr_tls_client_hello
HIDDEN fr_dict_attr_t const * attr_tls_client_hello_psk_key_mode
HIDDEN fr_dict_attr_t const * attr_tls_certificate_x509v3_basic_constraints
fr_value_box_t const * enum_tls_packet_type_success
HIDDEN fr_dict_attr_t const * attr_tls_psk_key
HIDDEN fr_dict_attr_t const * attr_tls_certificate_serial
HIDDEN fr_dict_attr_t const * attr_tls_session_require_client_cert
HIDDEN fr_dict_t const * dict_der
Definition base.c:38
HIDDEN fr_dict_attr_t const * attr_tls_certificate_subject_alt_name_dns
HIDDEN fr_dict_attr_t const * attr_tls_client_hello_supported_group
HIDDEN fr_dict_attr_t const * attr_tls_session_ttl
fr_value_box_t const * enum_tls_session_resumed_stateful
HIDDEN fr_dict_attr_t const * attr_tls_session_data
HIDDEN fr_dict_attr_t const * attr_tls_certificate_not_after
HIDDEN fr_dict_attr_t const * attr_tls_certificate_not_before
HIDDEN fr_dict_attr_t const * attr_tls_alpn
fr_value_box_t const * enum_tls_packet_type_new_session
HIDDEN fr_dict_attr_t const * attr_tls_certificate_signature_algorithm
HIDDEN fr_dict_attr_t const * attr_tls_client_error_code
fr_value_box_t const * enum_tls_packet_type_load_session
fr_value_box_t const * enum_tls_packet_type_establish_session
HIDDEN fr_dict_attr_t const * attr_tls_error
HIDDEN fr_dict_attr_t const * attr_tls_certificate_subject_alt_name_upn
HIDDEN fr_dict_attr_t const * attr_tls_ocsp_response
HIDDEN fr_dict_attr_t const * attr_tls_session_id
fr_value_box_t const * enum_tls_packet_type_fail_session
HIDDEN fr_dict_attr_t const * attr_tls_client_hello_sig_algo
HIDDEN fr_dict_attr_t const * attr_tls_certificate_ocsp_uri
HIDDEN fr_dict_attr_t const * attr_tls_certificate_x509v3_subject_key_identifier
fr_value_box_t const * enum_tls_packet_type_clear_session
HIDDEN fr_dict_attr_t const * attr_tls_session_cipher_suite
HIDDEN fr_dict_attr_t const * attr_tls_certificate_common_name
HIDDEN fr_dict_attr_t const * attr_tls_certificate_ocsp_cert_id
HIDDEN fr_dict_attr_t const * attr_tls_psk_identity
HIDDEN fr_dict_attr_t const * attr_tls_alert_description
HIDDEN fr_dict_attr_t const * attr_tls_certificate_issuer
fr_value_box_t const * enum_tls_session_resumed_stateless
HIDDEN fr_dict_attr_t const * attr_tls_certificate_x509v3_crl_distribution_points
fr_value_box_t const * enum_tls_packet_type_notfound
HIDDEN fr_dict_attr_t const * attr_tls_client_hello_ec_point_format
HIDDEN fr_dict_attr_t const * attr_der_certificate
HIDDEN fr_dict_attr_t const * attr_tls_certificate_signature
HIDDEN fr_dict_attr_t const * attr_tls_alert
fr_value_box_t const * enum_tls_packet_type_decode_session
HIDDEN fr_dict_attr_t const * attr_tls_ocsp_next_update
fr_value_box_t const * enum_tls_packet_type_encode_session
HIDDEN fr_dict_attr_t const * attr_tls_client_hello_tls_version
fr_value_box_t const * enum_tls_packet_type_verify_certificate
HIDDEN fr_dict_attr_t const * attr_tls_client_hello_cipher
HIDDEN fr_dict_attr_t const * attr_tls_session_cert_file
HIDDEN fr_dict_attr_t const * attr_tls_certificate_chain_depth
HIDDEN fr_dict_attr_t const * attr_tls_certificate_subject_alt_name_email
HIDDEN fr_dict_attr_t const * attr_allow_session_resumption
static char * stack[MAX_STACK]
Definition radmin.c:158
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_OCTETS
Raw octets.
unsigned int uint32_t
unsigned char uint8_t
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
init
Enter the EAP-IDENTITY state.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
static fr_sbuff_err_t char size_t * len
Definition value.h:1061