26RCSID(
"$Id: 02b7224adf7d1ed30c2fd245ad116666fca5f323 $")
30#define LOG_PREFIX "tls"
32#include <freeradius-devel/tls/base.h>
33#include <freeradius-devel/tls/engine.h>
34#include <freeradius-devel/tls/log.h>
35#include <freeradius-devel/tls/strerror.h>
36#include <freeradius-devel/util/strerror.h>
38#if OPENSSL_VERSION_NUMBER < 0x30000000L
50 fr_tls_engine_ctrl_list_t pre_ctrls;
51 fr_tls_engine_ctrl_list_t post_ctrls;
68static int8_t tls_engine_cmp(
void const *one,
void const *two)
74 ret =
CMP(strcmp(a->id, b->id), 0);
75 if (ret != 0)
return ret;
80 if (!a->instance && !b->instance)
return 0;
81 if (!a->instance)
return -1;
82 if (!b->instance)
return +1;
84 return CMP(strcmp(a->instance, b->instance), 0);
94static void CC_HINT(
nonnull) tls_engine_control_notfound_strerror(ENGINE *e,
char const *bad_ctrl)
106 pool = talloc_pool(NULL, 256);
109 fr_strerror_printf(
"engine %s does not export control %s", ENGINE_get_id(e), bad_ctrl);
111 for (cmd = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, 0, NULL, NULL);
113 cmd = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, cmd, NULL, NULL)) {
114 size_t name_len, desc_len;
118 if (!ENGINE_cmd_is_executable(e, cmd))
continue;
123 name_len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, 0, NULL, NULL);
124 if (
unlikely(name_len == 0))
continue;
126 name = talloc_array(pool,
char, name_len + 1);
129 if (
unlikely(ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, 0,
name, NULL) <= 0))
break;
134 desc_len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, 0, NULL, NULL);
136 desc = talloc_array(pool,
char, desc_len + 1);
139 if (
unlikely(ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, 0, desc, NULL) <= 0))
break;
144 ret = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, 0, NULL, NULL);
145 if (ret & ENGINE_CMD_FLAG_NO_INPUT) {
147 }
else if ((ret & ENGINE_CMD_FLAG_NUMERIC) && (ret & ENGINE_CMD_FLAG_STRING)) {
148 flags =
"number and string";
149 }
else if (ret & ENGINE_CMD_FLAG_NUMERIC) {
151 }
else if (ret & ENGINE_CMD_FLAG_STRING) {
154 flags =
"unavailable";
162 talloc_free_children(pool);
177static inline CC_HINT(always_inline) fr_tls_engine_ctrl_t *tls_engine_ctrl_dup(TALLOC_CTX *ctx,
178 fr_tls_engine_ctrl_t
const *
in)
180 fr_tls_engine_ctrl_t *
n;
182 n = talloc(ctx, fr_tls_engine_ctrl_t);
188 *
n = (fr_tls_engine_ctrl_t){
199static int _tls_engine_free(tls_engine_t *our_e)
207 if (
unlikely(ENGINE_finish(our_e->e) != 1)) {
208 fr_tls_log(NULL,
"de-init on engine %s failed", our_e->id);
212 if (
unlikely(ENGINE_free(our_e->e) != 1)) {
213 fr_tls_log(NULL,
"free on engine %s failed", our_e->id);
243int fr_tls_engine_init(ENGINE **e_out,
244 char const *
id,
char const *instance,
245 fr_tls_engine_ctrl_list_t
const *pre_ctrls, fr_tls_engine_ctrl_list_t
const *post_ctrls)
247 tls_engine_t *our_e = NULL;
249 fr_tls_engine_ctrl_t *ctrl = NULL, *
n;
259 tls_engine_t *found = NULL;
261 found =
fr_rb_find(tls_engines, &(tls_engine_t){ .id = id, .instance = instance });
264 instance ?
" (" :
"",
265 instance ? instance :
"",
266 instance ?
") " :
"");
271 e = ENGINE_by_id(
id);
277 if (pre_ctrls)
while ((ctrl =
fr_dlist_next(pre_ctrls, ctrl))) {
280 cmd = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FROM_NAME, 0,
UNCONST(
void *, ctrl->name), NULL);
287 tls_engine_control_notfound_strerror(e, ctrl->name);
302 flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, 0, NULL, NULL);
303 if (flags & ENGINE_CMD_FLAG_NO_INPUT) {
304 ret = ENGINE_ctrl(e, cmd, 0, NULL, NULL);
308 }
else if (
unlikely((flags & ENGINE_CMD_FLAG_STRING) && (flags & ENGINE_CMD_FLAG_NUMERIC))) {
310 "both numeric and string commands needed for OpenSSL engine controls");
316 }
else if (flags & ENGINE_CMD_FLAG_NUMERIC) {
323 ret = ENGINE_ctrl(e, cmd, vb.vb_int32, NULL, 0);
324 }
else if (flags & ENGINE_CMD_FLAG_STRING) {
325 ret = ENGINE_ctrl(e, cmd, 0,
UNCONST(
void *, ctrl->value), NULL);
336 fr_tls_strerror_printf(
"control %s failed (%i)", ctrl->name, ret);
341 if (
unlikely(ENGINE_init(e) != 1)) {
342 fr_tls_strerror_printf(
"failed initialising engine %s",
id);
346 our_e = talloc(tls_engines, tls_engine_t);
349 *our_e = (tls_engine_t){
354 talloc_set_destructor(our_e, _tls_engine_free);
368 n = tls_engine_ctrl_dup(our_e, ctrl);
380 n = tls_engine_ctrl_dup(our_e, ctrl);
423int fr_tls_engine(ENGINE **e_out,
char const *
id,
char const *instance,
bool auto_init)
425 tls_engine_t *found = NULL;
431 instance ?
" (" :
"",
432 instance ? instance :
"",
433 instance ?
") " :
"");
438 return fr_tls_engine_init(e_out,
id, instance, NULL, NULL);
442 found =
fr_rb_find(tls_engines, &(tls_engine_t){ .id = id, .instance = instance });
444 if (!auto_init)
goto not_init;
455void fr_tls_engine_load_builtin(
void)
457 ENGINE_load_builtin_engines();
462 if (!tls_engines || !
fr_rb_find(tls_engines, &(tls_engine_t){ .id =
"rdrand" })) {
465 ENGINE_register_all_RAND();
471 rand_engine = ENGINE_get_default_RAND();
472 if (!rand_engine)
goto done;
474 if(strcmp(ENGINE_get_id(rand_engine),
"rdrand") == 0) {
475 ENGINE_unregister_RAND(rand_engine);
481 ENGINE_finish(rand_engine);
482 ENGINE_free(rand_engine);
486 ENGINE_register_all_complete();
492void fr_tls_engine_free_all(
void)
494 TALLOC_FREE(tls_engines);
496#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define USES_APPLE_DEPRECATED_API
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
#define fr_dlist_talloc_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
@ FR_TYPE_INT32
32 Bit signed integer.
void * fr_rb_remove(fr_rb_tree_t *tree, void const *data)
Remove an entry from the tree, without freeing the data.
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
The main red black tree structure.
void talloc_free_data(void *data)
A wrapper that can be passed to tree or hash alloc functions that take a fr_free_t.
#define talloc_get_type_abort_const
#define talloc_strdup(_ctx, _str)
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define fr_strerror_const_push(_msg)
#define fr_strerror_const(_msg)
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
#define fr_box_strvalue(_val)