# include <systemd/sd-daemon.h>
#endif
-#if defined(WITH_TLS) && OPENSSL_VERSION_NUMBER >= 0x30000000L
-# include <openssl/provider.h>
+#ifdef WITH_TLS
+# include <freeradius-devel/tls/version.h>
#endif
char const *radiusd_version = RADIUSD_VERSION_STRING_BUILD("FreeRADIUS");
* Mismatch between build time OpenSSL and linked SSL, better to die
* here than segfault later.
*/
- if (ssl_check_consistency() < 0) EXIT_WITH_FAILURE;
+ if (fr_openssl_version_consistent() < 0) EXIT_WITH_FAILURE;
/*
* Initialising OpenSSL once, here, is safer than having individual modules do it.
/*
* Check for vulnerabilities in the version of libssl were linked against.
*/
-#if defined(WITH_TLS) && defined(ENABLE_OPENSSL_VERSION_CHECK)
+#ifdef WITH_TLS
+# ifdef ENABLE_OPENSSL_VERSION_CHECK
if (fr_openssl_version_check(config->allow_vulnerable_openssl) < 0) EXIT_WITH_FAILURE;
-#endif
+# endif
-#ifdef WITH_TLS
/*
* Toggle FIPS mode
*/
#include <freeradius-devel/io/listen.h>
#include <freeradius-devel/tls/base.h>
+#include <freeradius-devel/tls/version.h>
#include <freeradius-devel/unlang/base.h>
* Mismatch between build time OpenSSL and linked SSL, better to die
* here than segfault later.
*/
- if (ssl_check_consistency() < 0) EXIT_WITH_FAILURE;
+ if (fr_openssl_version_consistent() < 0) EXIT_WITH_FAILURE;
/*
* Initialising OpenSSL once, here, is safer than having individual modules do it.
#include <freeradius-devel/tls/openssl_user_macros.h>
#ifdef WITH_TLS
-# include <freeradius-devel/tls/openssl_user_macros.h>
+# include <freeradius-devel/tls/version.h>
# include <openssl/crypto.h>
# include <openssl/opensslv.h>
# include <openssl/engine.h>
+#endif
#ifdef HAVE_VALGRIND_H
# include <valgrind.h>
#endif
-static long ssl_built = OPENSSL_VERSION_NUMBER;
-
-/** Check built and linked versions of OpenSSL match
- *
- * OpenSSL version number consists of:
- * MNNFFPPS: major minor fix patch status
- *
- * Where status >= 0 && < 10 means beta, and status 10 means release.
- *
- * https://wiki.openssl.org/index.php/Versioning
- *
- * Startup check for whether the linked version of OpenSSL matches the
- * version the server was built against.
- *
- * @return
- * - 0 if ok.
- * - -1 if not ok.
- */
-int ssl_check_consistency(void)
-{
- unsigned long ssl_linked;
-
-#if OPENSSL_VERSION_NUMBER >= 0x10101000L
- ssl_linked = OpenSSL_version_num();
-#else
- ssl_linked = (unsigned long)SSLeay();
-#endif
-
- /*
- * Major and minor versions mismatch, that's bad.
- */
- if ((ssl_linked & 0xfff00000) != (ssl_built & 0xfff00000)) goto mismatch;
-
- /*
- * 1.1.0 and later export all of the APIs we need, so we
- * don't care about mismatches in fix / patch / status
- * fields. If the major && minor fields match, that's
- * good enough.
- */
- if ((ssl_linked & 0xfff00000) >= 0x10100000) return 0;
-
- /*
- * Before 1.1.0, we need all kinds of stupid checks to
- * see if it might work.
- */
-
- /*
- * Status mismatch always triggers error.
- */
- if ((ssl_linked & 0x0000000f) != (ssl_built & 0x0000000f)) {
- mismatch:
- ERROR("libssl version mismatch. built: %lx linked: %lx",
- (unsigned long) ssl_built,
- (unsigned long) ssl_linked);
-
- return -1;
- }
-
- /*
- * Use the OpenSSH approach and relax fix checks after version
- * 1.0.0 and only allow moving backwards within a patch
- * series.
- */
- if (ssl_built & 0xf0000000) {
- if ((ssl_built & 0xfffff000) != (ssl_linked & 0xfffff000) ||
- (ssl_built & 0x00000ff0) > (ssl_linked & 0x00000ff0)) goto mismatch;
- /*
- * Before 1.0.0 we require the same major minor and fix version
- * and ignore the patch number.
- */
- } else if ((ssl_built & 0xfffff000) != (ssl_linked & 0xfffff000)) goto mismatch;
-
- return 0;
-}
-
-/** Convert a version number to a text string
- *
- * @note Not thread safe.
- *
- * @param v version to convert.
- * @return pointer to a static buffer containing the version string.
- */
-char const *ssl_version_by_num(uint32_t v)
-{
- /* 2 (%s) + 1 (.) + 2 (%i) + 1 (.) + 2 (%i) + 1 (c) + 8 (%s) + \0 */
- static char buffer[18];
- char *p = buffer;
-
- p += sprintf(p, "%u.%u.%u",
- (0xf0000000 & v) >> 28,
- (0x0ff00000 & v) >> 20,
- (0x000ff000 & v) >> 12);
-
- if ((0x00000ff0 & v) >> 4) {
- *p++ = (char) (0x60 + ((0x00000ff0 & v) >> 4));
- }
-
- *p++ = ' ';
-
- /*
- * Development (0)
- */
- if ((0x0000000f & v) == 0) {
- strcpy(p, "dev");
- /*
- * Beta (1-14)
- */
- } else if ((0x0000000f & v) <= 14) {
- sprintf(p, "beta %u", 0x0000000f & v);
- } else {
- strcpy(p, "release");
- }
-
- return buffer;
-}
-
-/** Convert two openssl version numbers into a range string
- *
- * @note Not thread safe.
- *
- * @param low version to convert.
- * @param high version to convert.
- * @return pointer to a static buffer containing the version range string.
- */
-char const *ssl_version_range(uint32_t low, uint32_t high)
-{
- /* 18 (version) + 3 ( - ) + 18 (version) */
- static char buffer[40];
- char *p = buffer;
-
- p += strlcpy(p, ssl_version_by_num(low), sizeof(buffer));
- p += strlcpy(p, " - ", sizeof(buffer) - (p - buffer));
- strlcpy(p, ssl_version_by_num(high), sizeof(buffer) - (p - buffer));
-
- return buffer;
-}
-
-# if OPENSSL_VERSION_NUMBER >= 0x10101000L
-/** Return the linked SSL version number as a string
- *
- * @return pointer to a static buffer containing the version string.
- */
-char const *ssl_version_num(void)
-{
- unsigned long ssl_linked;
-
- ssl_linked = OpenSSL_version_num();
- return ssl_version_by_num((uint32_t)ssl_linked);
-}
-
-/** Print the current linked version of Openssl
- *
- * Print the currently linked version of the OpenSSL library.
- *
- * @note Not thread safe.
- * @return pointer to a static buffer containing libssl version information.
- */
-char const *ssl_version(void)
-{
- static char buffer[256];
-
- unsigned long v = OpenSSL_version_num();
-
- snprintf(buffer, sizeof(buffer), "%s 0x%.8lx (%s)",
- OpenSSL_version(OPENSSL_VERSION), /* Not all builds include a useful version number */
- v,
- ssl_version_by_num(v));
-
- return buffer;
-}
-# else
-/** Return the linked SSL version number as a string
- *
- * @return pointer to a static buffer containing the version string.
- */
-char const *ssl_version_num(void)
-{
- long ssl_linked;
-
- ssl_linked = SSLeay();
- return ssl_version_by_num((uint32_t)ssl_linked);
-}
-
-/** Print the current linked version of Openssl
- *
- * Print the currently linked version of the OpenSSL library.
- *
- * @note Not thread safe.
- * @return pointer to a static buffer containing libssl version information.
- */
-char const *ssl_version(void)
-{
- static char buffer[256];
- long ssl_linked = SSLeay();
-
- snprintf(buffer, sizeof(buffer), "%s 0x%.8x (%s)",
- SSLeay_version(SSLEAY_VERSION), /* Not all builds include a useful version number */
- ssl_linked,
- ssl_version_by_num(v));
-
- return buffer;
-}
-# endif
-#else
-int ssl_check_consistency(void) {
- return 0;
-}
-
-char const *ssl_version_num(void)
-{
- return "not linked";
-}
-
-char const *ssl_version()
-{
- return "not linked";
-}
-#endif /* ifdef WITH_TLS */
-
/** Check if the application linking to the library has the correct magic number
*
* @param magic number as defined by RADIUSD_MAGIC_NUMBER
snprintf(buffer, sizeof(buffer), "%i.%i.*", talloc_version_major(), talloc_version_minor());
dependency_version_number_add(cs, "talloc", buffer);
- dependency_version_number_add(cs, "ssl", ssl_version_num());
+#if WITH_TLS
+ dependency_version_number_add(cs, "ssl", fr_openssl_version_basic());
+#endif
#ifdef HAVE_REGEX
# ifdef HAVE_REGEX_PCRE2
#include <stddef.h>
int rad_check_lib_magic(uint64_t magic);
-int ssl_check_consistency(void);
-char const *ssl_version_by_num(uint32_t version);
-char const *ssl_version_num(void);
-char const *ssl_version_range(uint32_t low, uint32_t high);
-char const *ssl_version(void);
int dependency_feature_add(CONF_SECTION *cs, char const *name, bool enabled);
int dependency_version_number_add(CONF_SECTION *cs, char const *name, char const *version);
void dependency_features_init(CONF_SECTION *cs) CC_HINT(nonnull);
session.c \
utils.c \
verify.c \
+ version.c \
virtual_server.c
TGT_PREREQS := libfreeradius-internal.a libfreeradius-util.a
/*
* tls/base.c
*/
-
-#ifdef ENABLE_OPENSSL_VERSION_CHECK
-int fr_openssl_version_check(char const *acknowledged);
-#endif
-
int fr_openssl_thread_init(size_t async_pool_size_init, size_t async_pool_size_max);
int fr_openssl_init(void);
*/
int fr_tls_max_threads = 1;
-#ifdef ENABLE_OPENSSL_VERSION_CHECK
-typedef struct {
- uint64_t high; //!< The last version number this defect affected.
- uint64_t low; //!< The first version this defect affected.
-
- char const *id; //!< CVE (or other ID)
- char const *name; //!< As known in the media...
- char const *comment; //!< Where to get more information.
-} fr_openssl_defect_t;
-
-#undef VM
-#undef Vm
-#define VM(_a,_b,_c) (((((_a) << 24) | ((_b) << 16) | ((_c) << 8)) << 4) | 0x0f)
-#define Vm(_a,_b,_c,_d) (((((_a) << 24) | ((_b) << 16) | ((_c) << 8) | ((_d) - 'a' + 1)) << 4) | 0x0f)
-
-/* Record critical defects in libssl here, new versions of OpenSSL to older versions of OpenSSL. */
-static fr_openssl_defect_t fr_openssl_defects[] =
-{
- {
- .low = Vm(1,1,0,'a'), /* 1.1.0a */
- .high = Vm(1,1,0,'a'), /* 1.1.0a */
- .id = "CVE-2016-6309",
- .name = "OCSP status request extension",
- .comment = "For more information see https://www.openssl.org/news/secadv/20160926.txt"
- },
- {
- .low = VM(1,1,0), /* 1.1.0 */
- .high = VM(1,1,0), /* 1.1.0 */
- .id = "CVE-2016-6304",
- .name = "OCSP status request extension",
- .comment = "For more information see https://www.openssl.org/news/secadv/20160922.txt"
- }
-};
-#endif /* ENABLE_OPENSSL_VERSION_CHECK */
-
-#ifdef ENABLE_OPENSSL_VERSION_CHECK
-/** Check for vulnerable versions of libssl
- *
- * @param acknowledged The highest CVE number a user has confirmed is not present in the system's
- * libssl.
- * @return 0 if the CVE specified by the user matches the most recent CVE we have, else -1.
- */
-int fr_openssl_version_check(char const *acknowledged)
-{
- bool bad = false;
- size_t i;
- unsigned long ssl_linked;
-
-
- /*
- * Didn't get passed anything, that's an error.
- */
- if (!acknowledged || !*acknowledged) {
- ERROR("Refusing to start until 'allow_vulnerable_openssl' is given a value");
- return -1;
- }
-
- if (strcmp(acknowledged, "yes") == 0) return 0;
-
- /* Check for bad versions */
-
-#if OPENSSL_VERSION_NUMBER >= 0x10101000L
- ssl_linked = OpenSSL_version_num();
-#else
- ssl_linked = (unsigned long)SSLeay();
-#endif
-
- for (i = 0; i < (NUM_ELEMENTS(fr_openssl_defects)); i++) {
- fr_openssl_defect_t *defect = &fr_openssl_defects[i];
-
- if ((ssl_linked >= defect->low) && (ssl_linked <= defect->high)) {
- /*
- * If the CVE is acknowledged, allow it.
- */
- if (!bad && (strcmp(acknowledged, defect->id) == 0)) return 0;
-
- ERROR("Refusing to start with libssl version %s (in range %s)",
- ssl_version(), ssl_version_range(defect->low, defect->high));
- ERROR("Security advisory %s (%s)", defect->id, defect->name);
- ERROR("%s", defect->comment);
-
- /*
- * Only warn about the first one...
- */
- if (!bad) {
- INFO("Once you have verified libssl has been correctly patched, "
- "set security.allow_vulnerable_openssl = '%s'", defect->id);
- bad = true;
- }
- }
- }
-
- if (bad) return -1;
-
- return 0;
-}
-#endif
-
/** Allocate memory for OpenSSL in the NULL context
*
* @param len to alloc.
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ *
+ * @file tls/version.c
+ * @brief Check OpenSSL library/header consistency, and process version information.
+ *
+ * @copyright 2022 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+ */
+#define LOG_PREFIX "tls"
+
+#include "version.h"
+
+#ifdef WITH_TLS
+#include <freeradius-devel/server/log.h>
+
+static long ssl_built = OPENSSL_VERSION_NUMBER;
+
+/** Check built and linked versions of OpenSSL match
+ *
+ * OpenSSL version number consists of:
+ * MNNFFPPS: major minor fix patch status
+ *
+ * Where status >= 0 && < 10 means beta, and status 10 means release.
+ *
+ * https://wiki.openssl.org/index.php/Versioning
+ *
+ * Startup check for whether the linked version of OpenSSL matches the
+ * version the server was built against.
+ *
+ * @return
+ * - 0 if ok.
+ * - -1 if not ok.
+ */
+int fr_openssl_version_consistent(void)
+{
+ unsigned long ssl_linked;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L
+ ssl_linked = OpenSSL_version_num();
+#else
+ ssl_linked = (unsigned long)SSLeay();
+#endif
+
+ /*
+ * Major and minor versions mismatch, that's bad.
+ *
+ * We still allow mismatches between patch versions
+ * as they should be ABI compatible.
+ *
+ * This should work for >= 1.1.0 including 3.0.0
+ */
+ if ((ssl_linked & 0xfff00000) != (ssl_built & 0xfff00000)) {
+ ERROR("libssl version mismatch. built: %lx linked: %lx",
+ (unsigned long) ssl_built,
+ (unsigned long) ssl_linked);
+ return -1;
+ }
+
+ return 0;
+}
+
+/** Convert a version number to a text string
+ *
+ * @note Not thread safe.
+ *
+ * @param v version to convert.
+ * @return pointer to a static buffer containing the version string.
+ */
+char const *fr_openssl_version_str_from_num(uint32_t v)
+{
+ /* 2 (%s) + 1 (.) + 2 (%i) + 1 (.) + 2 (%i) + 1 (c) + 8 (%s) + \0 */
+ static char buffer[18];
+ char *p = buffer;
+
+ /*
+ * If OpenSSL major version is less than three
+ * use the old version number layout.
+ */
+ if ((v & 0xf0000000) < 3) {
+ p += sprintf(p, "%u.%u.%u",
+ (0xf0000000 & v) >> 28,
+ (0x0ff00000 & v) >> 20,
+ (0x000ff000 & v) >> 12);
+
+ if ((0x00000ff0 & v) >> 4) {
+ *p++ = (char) (0x60 + ((0x00000ff0 & v) >> 4));
+ }
+
+ *p++ = ' ';
+
+ /*
+ * Development (0)
+ */
+ if ((0x0000000f & v) == 0) {
+ strcpy(p, "dev");
+ /*
+ * Beta (1-14)
+ */
+ } else if ((0x0000000f & v) <= 14) {
+ sprintf(p, "beta %u", 0x0000000f & v);
+ } else {
+ strcpy(p, "release");
+ }
+
+ return buffer;
+ }
+
+ /*
+ * If OpenSSL major version is >= 3 us the
+ * new version number layout
+ *
+ * OPENSSL_VERSION_NUMBER is a combination of the major, minor
+ * and patch version into a single integer 0xMNN00PP0L, where:
+ *
+ * M is the number from OPENSSL_VERSION_MAJOR, in hexadecimal notation.
+ * NN is the number from OPENSSL_VERSION_MINOR, in hexadecimal notation.
+ * PP is the number from OPENSSL_VERSION_PATCH, in hexadecimal notation.
+ */
+ sprintf(buffer, "%u.%u.%u",
+ (0xf0000000 & v) >> 28,
+ (0x0ff00000 & v) >> 20,
+ (0x00000ff0 & v) >> 4);
+
+ return buffer;
+}
+
+/** Convert two openssl version numbers into a range string
+ *
+ * @param[in] low version to convert.
+ * @param[in] high version to convert.
+ * @return pointer to a static buffer containing the version range string.
+ */
+char const *fr_openssl_version_range(uint32_t low, uint32_t high)
+{
+ /* 18 (version) + 3 ( - ) + 18 (version) */
+ static _Thread_local char buffer[40];
+ char *p = buffer;
+
+ p += strlcpy(p, fr_openssl_version_str_from_num(low), sizeof(buffer));
+ p += strlcpy(p, " - ", sizeof(buffer) - (p - buffer));
+ strlcpy(p, fr_openssl_version_str_from_num(high), sizeof(buffer) - (p - buffer));
+
+ return buffer;
+}
+
+# if OPENSSL_VERSION_NUMBER >= 0x10101000L
+/** Return the linked SSL version number as a string
+ *
+ * @return pointer to a static buffer containing the version string.
+ */
+char const *fr_openssl_version_basic(void)
+{
+ unsigned long ssl_linked;
+
+ ssl_linked = OpenSSL_version_num();
+ return fr_openssl_version_str_from_num((uint32_t)ssl_linked);
+}
+
+/** Print the current linked version of Openssl
+ *
+ * Print the currently linked version of the OpenSSL library.
+ *
+ * @return pointer to a static buffer containing libssl version information.
+ */
+char const *fr_openssl_version_expanded(void)
+{
+ static _Thread_local char buffer[256];
+
+ unsigned long v = OpenSSL_version_num();
+
+ snprintf(buffer, sizeof(buffer), "%s 0x%.8lx (%s)",
+ OpenSSL_version(OPENSSL_VERSION), /* Not all builds include a useful version number */
+ v,
+ fr_openssl_version_str_from_num(v));
+
+ return buffer;
+}
+# else
+/** Return the linked SSL version number as a string
+ *
+ * @return pointer to a static buffer containing the version string.
+ */
+char const *fr_openssl_version_basic(void)
+{
+ long ssl_linked;
+
+ ssl_linked = SSLeay();
+ return fr_openssl_version_str_from_num((uint32_t)ssl_linked);
+}
+
+/** Print the current linked version of Openssl
+ *
+ * Print the currently linked version of the OpenSSL library.
+ *
+ * @note Not thread safe.
+ *
+ * @return pointer to a static buffer containing libssl version information.
+ */
+char const *fr_openssl_version_expanded(void)
+{
+ static _Thread_local char buffer[256];
+ long ssl_linked = SSLeay();
+
+ snprintf(buffer, sizeof(buffer), "%s 0x%.8x (%s)",
+ SSLeay_version(SSLEAY_VERSION), /* Not all builds include a useful version number */
+ ssl_linked,
+ fr_openssl_version_str_from_num(v));
+
+ return buffer;
+}
+# endif
+
+# ifdef ENABLE_OPENSSL_VERSION_CHECK
+typedef struct {
+ uint64_t high; //!< The last version number this defect affected.
+ uint64_t low; //!< The first version this defect affected.
+
+ char const *id; //!< CVE (or other ID)
+ char const *name; //!< As known in the media...
+ char const *comment; //!< Where to get more information.
+} fr_openssl_defect_t;
+
+# undef VM
+# undef Vm
+# define VM(_a,_b,_c) (((((_a) << 24) | ((_b) << 16) | ((_c) << 8)) << 4) | 0x0f)
+# define Vm(_a,_b,_c,_d) (((((_a) << 24) | ((_b) << 16) | ((_c) << 8) | ((_d) - 'a' + 1)) << 4) | 0x0f)
+
+/* Record critical defects in libssl here, new versions of OpenSSL to older versions of OpenSSL. */
+static fr_openssl_defect_t fr_openssl_defects[] =
+{
+ {
+ .low = Vm(1,1,0,'a'), /* 1.1.0a */
+ .high = Vm(1,1,0,'a'), /* 1.1.0a */
+ .id = "CVE-2016-6309",
+ .name = "OCSP status request extension",
+ .comment = "For more information see https://www.openssl.org/news/secadv/20160926.txt"
+ },
+ {
+ .low = VM(1,1,0), /* 1.1.0 */
+ .high = VM(1,1,0), /* 1.1.0 */
+ .id = "CVE-2016-6304",
+ .name = "OCSP status request extension",
+ .comment = "For more information see https://www.openssl.org/news/secadv/20160922.txt"
+ }
+};
+
+/** Check for vulnerable versions of libssl
+ *
+ * @param acknowledged The highest CVE number a user has confirmed is not present in the system's
+ * libssl.
+ * @return 0 if the CVE specified by the user matches the most recent CVE we have, else -1.
+ */
+int fr_openssl_version_check(char const *acknowledged)
+{
+ bool bad = false;
+ size_t i;
+ unsigned long ssl_linked;
+
+
+ /*
+ * Didn't get passed anything, that's an error.
+ */
+ if (!acknowledged || !*acknowledged) {
+ ERROR("Refusing to start until 'allow_vulnerable_openssl' is given a value");
+ return -1;
+ }
+
+ if (strcmp(acknowledged, "yes") == 0) return 0;
+
+ /* Check for bad versions */
+
+# if OPENSSL_VERSION_NUMBER >= 0x10101000L
+ ssl_linked = OpenSSL_version_num();
+# else
+ ssl_linked = (unsigned long)SSLeay();
+# endif
+
+ for (i = 0; i < (NUM_ELEMENTS(fr_openssl_defects)); i++) {
+ fr_openssl_defect_t *defect = &fr_openssl_defects[i];
+
+ if ((ssl_linked >= defect->low) && (ssl_linked <= defect->high)) {
+ /*
+ * If the CVE is acknowledged, allow it.
+ */
+ if (!bad && (strcmp(acknowledged, defect->id) == 0)) return 0;
+
+ ERROR("Refusing to start with libssl version %s (in range %s)",
+ fr_openssl_version_expanded(), fr_openssl_version_range(defect->low, defect->high));
+ ERROR("Security advisory %s (%s)", defect->id, defect->name);
+ ERROR("%s", defect->comment);
+
+ /*
+ * Only warn about the first one...
+ */
+ if (!bad) {
+ INFO("Once you have verified libssl has been correctly patched, "
+ "set security.allow_vulnerable_openssl = '%s'", defect->id);
+ bad = true;
+ }
+ }
+ }
+
+ if (bad) return -1;
+
+ return 0;
+}
+# endif
+#else
+int fr_openssl_version_consistent(void) {
+ return 0;
+}
+
+char const *fr_openssl_version_basic(void)
+{
+ return "not linked";
+}
+
+char const *fr_openssl_version_expanded(void)
+{
+ return "not linked";
+}
+#endif /* ifdef WITH_TLS */
--- /dev/null
+#pragma once
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+/**
+ * $Id$
+ *
+ * @file lib/tls/version.h
+ * @brief Structures for dealing with OpenSSL library versions
+ *
+ * @copyright 2022 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
+ */
+RCSIDH(tls_version_h, "$Id$")
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "openssl_user_macros.h"
+
+#ifdef WITH_TLS
+# include <openssl/ssl.h>
+#endif
+
+/*
+ * If we're not building with TLS, dummy functions will
+ * be provided.
+ */
+int fr_openssl_version_consistent(void);
+char const *fr_openssl_version_str_from_num(uint32_t version);
+char const *fr_openssl_version_basic(void);
+char const *fr_openssl_version_range(uint32_t low, uint32_t high);
+char const *fr_openssl_version_expanded(void);
+
+#ifdef ENABLE_OPENSSL_VERSION_CHECK
+int fr_openssl_version_check(char const *acknowledged);
+#endif
+
+#ifdef __cplusplus
+}
+#endif