summaryrefslogtreecommitdiffstats
path: root/src/main/version.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/version.c')
-rw-r--r--src/main/version.c625
1 files changed, 625 insertions, 0 deletions
diff --git a/src/main/version.c b/src/main/version.c
new file mode 100644
index 0000000..c7c7659
--- /dev/null
+++ b/src/main/version.c
@@ -0,0 +1,625 @@
+/*
+ * version.c Print version number and exit.
+ *
+ * Version: $Id$
+ *
+ * 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
+ *
+ * Copyright 1999-2019 The FreeRADIUS server project
+ * Copyright 2012 Alan DeKok <aland@ox.org>
+ * Copyright 2000 Chris Parker <cparker@starnetusa.com>
+ */
+
+RCSID("$Id$")
+
+#include <freeradius-devel/radiusd.h>
+USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
+
+static uint64_t libmagic = RADIUSD_MAGIC_NUMBER;
+char const *radiusd_version_short = RADIUSD_VERSION_STRING;
+
+#ifdef HAVE_OPENSSL_CRYPTO_H
+# include <openssl/crypto.h>
+# include <openssl/opensslv.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, else -1
+ */
+int ssl_check_consistency(void)
+{
+ long ssl_linked;
+
+ ssl_linked = SSLeay();
+
+ /*
+ * 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;
+}
+
+/** 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);
+}
+
+/** 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)
+{
+ /* 12 (version) + 3 ( - ) + 12 (version) */
+ static char buffer[28];
+ 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;
+}
+
+/** 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];
+
+ uint32_t v = SSLeay();
+
+ snprintf(buffer, sizeof(buffer), "%s 0x%.8x (%s)",
+ SSLeay_version(SSLEAY_VERSION), /* Not all builds include a useful version number */
+ v,
+ ssl_version_by_num(v));
+
+ return buffer;
+}
+# 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 HAVE_OPENSSL_CRYPTO_H */
+
+/** Check if the application linking to the library has the correct magic number
+ *
+ * @param magic number as defined by RADIUSD_MAGIC_NUMBER
+ * @returns 0 on success, -1 on prefix mismatch, -2 on version mismatch -3 on commit mismatch.
+ */
+int rad_check_lib_magic(uint64_t magic)
+{
+ if (MAGIC_PREFIX(magic) != MAGIC_PREFIX(libmagic)) {
+ ERROR("Application and libfreeradius-server magic number (prefix) mismatch."
+ " application: %x library: %x",
+ MAGIC_PREFIX(magic), MAGIC_PREFIX(libmagic));
+ return -1;
+ }
+
+ if (MAGIC_VERSION(magic) != MAGIC_VERSION(libmagic)) {
+ ERROR("Application and libfreeradius-server magic number (version) mismatch."
+ " application: %lx library: %lx",
+ (unsigned long) MAGIC_VERSION(magic), (unsigned long) MAGIC_VERSION(libmagic));
+ return -2;
+ }
+
+ if (MAGIC_COMMIT(magic) != MAGIC_COMMIT(libmagic)) {
+ ERROR("Application and libfreeradius-server magic number (commit) mismatch."
+ " application: %lx library: %lx",
+ (unsigned long) MAGIC_COMMIT(magic), (unsigned long) MAGIC_COMMIT(libmagic));
+ return -3;
+ }
+
+ return 0;
+}
+
+/** Add a feature flag to the main configuration
+ *
+ * Add a feature flag (yes/no) to the 'feature' subsection
+ * off the main config.
+ *
+ * This allows the user to create configurations that work with
+ * across multiple environments.
+ *
+ * @param cs to add feature pair to.
+ * @param name of feature.
+ * @param enabled Whether the feature is present/enabled.
+ * @return 0 on success else -1.
+ */
+int version_add_feature(CONF_SECTION *cs, char const *name, bool enabled)
+{
+ if (!cs) return -1;
+
+ if (!cf_pair_find(cs, name)) {
+ CONF_PAIR *cp;
+
+ cp = cf_pair_alloc(cs, name, enabled ? "yes" : "no",
+ T_OP_SET, T_BARE_WORD, T_BARE_WORD);
+ if (!cp) return -1;
+ cf_pair_add(cs, cp);
+ }
+
+ return 0;
+}
+
+/** Add a library/server version pair to the main configuration
+ *
+ * Add a version number to the 'version' subsection off the main
+ * config.
+ *
+ * Because of the optimisations in the configuration parser, these
+ * may be checked using regular expressions without a performance
+ * penalty.
+ *
+ * The version pairs are there primarily to work around defects
+ * in libraries or the server.
+ *
+ * @param cs to add feature pair to.
+ * @param name of library or feature.
+ * @param version Humanly readable version text.
+ * @return 0 on success else -1.
+ */
+int version_add_number(CONF_SECTION *cs, char const *name, char const *version)
+{
+ CONF_PAIR *old;
+
+ if (!cs) return -1;
+
+ old = cf_pair_find(cs, name);
+ if (!old) {
+ CONF_PAIR *cp;
+
+ cp = cf_pair_alloc(cs, name, version, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING);
+ if (!cp) return -1;
+
+ cf_pair_add(cs, cp);
+ } else {
+ WARN("Replacing user version.%s (%s) with %s", name, cf_pair_value(old), version);
+
+ cf_pair_replace(cs, old, version);
+ }
+
+ return 0;
+}
+
+
+/** Initialise core feature flags
+ *
+ * @param cs Where to add the CONF_PAIRS, if null pairs will be added
+ * to the 'feature' section of the main config.
+ */
+void version_init_features(CONF_SECTION *cs)
+{
+ version_add_feature(cs, "accounting",
+#ifdef WITH_ACCOUNTING
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "authentication", true);
+
+ version_add_feature(cs, "ascend-binary-attributes",
+#ifdef WITH_ASCEND_BINARY
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "coa",
+#ifdef WITH_COA
+ true
+#else
+ false
+#endif
+ );
+
+
+ version_add_feature(cs, "recv-coa-from-home-server",
+#ifdef WITH_COA_TUNNEL
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "control-socket",
+#ifdef WITH_COMMAND_SOCKET
+ true
+#else
+ false
+#endif
+ );
+
+
+ version_add_feature(cs, "detail",
+#ifdef WITH_DETAIL
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "dhcp",
+#ifdef WITH_DHCP
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "dynamic-clients",
+#ifdef WITH_DYNAMIC_CLIENTS
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "osfc2",
+#ifdef OSFC2
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "proxy",
+#ifdef WITH_PROXY
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "regex-pcre",
+#ifdef HAVE_PCRE
+ true
+#else
+ false
+#endif
+ );
+
+#if !defined(HAVE_PCRE) && defined(HAVE_REGEX)
+ version_add_feature(cs, "regex-posix", true);
+ version_add_feature(cs, "regex-posix-extended",
+# ifdef HAVE_REG_EXTENDED
+ true
+# else
+ false
+# endif
+ );
+#else
+ version_add_feature(cs, "regex-posix", false);
+ version_add_feature(cs, "regex-posix-extended", false);
+#endif
+
+ version_add_feature(cs, "session-management",
+#ifdef WITH_SESSION_MGMT
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "stats",
+#ifdef WITH_STATS
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "systemd",
+#ifdef HAVE_SYSTEMD
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "tcp",
+#ifdef WITH_TCP
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "threads",
+#ifdef WITH_THREADS
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "tls",
+#ifdef WITH_TLS
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "unlang",
+#ifdef WITH_UNLANG
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "vmps",
+#ifdef WITH_VMPS
+ true
+#else
+ false
+#endif
+ );
+
+ version_add_feature(cs, "developer",
+#ifndef NDEBUG
+ true
+#else
+ false
+#endif
+ );
+}
+
+/** Initialise core version flags
+ *
+ * @param cs Where to add the CONF_PAIRS, if null pairs will be added
+ * to the 'version' section of the main config.
+ */
+void version_init_numbers(CONF_SECTION *cs)
+{
+ char buffer[128];
+
+ version_add_number(cs, "freeradius-server", radiusd_version_short);
+
+ snprintf(buffer, sizeof(buffer), "%i.%i.*", talloc_version_major(), talloc_version_minor());
+ version_add_number(cs, "talloc", buffer);
+
+ version_add_number(cs, "ssl", ssl_version_num());
+
+#if defined(HAVE_REGEX) && defined(HAVE_PCRE)
+ version_add_number(cs, "pcre", pcre_version());
+#endif
+}
+
+static char const *spaces = " "; /* 40 */
+
+/*
+ * Display the revision number for this program
+ */
+void version_print(void)
+{
+ CONF_SECTION *features, *versions;
+ CONF_ITEM *ci;
+ CONF_PAIR *cp;
+
+ if (DEBUG_ENABLED3) {
+ int max = 0, len;
+
+ MEM(features = cf_section_alloc(NULL, "feature", NULL));
+ version_init_features(features);
+
+ MEM(versions = cf_section_alloc(NULL, "version", NULL));
+ version_init_numbers(versions);
+
+ DEBUG2("Server was built with: ");
+
+ for (ci = cf_item_find_next(features, NULL);
+ ci;
+ ci = cf_item_find_next(features, ci)) {
+ len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci)));
+ if (max < len) max = len;
+ }
+
+ for (ci = cf_item_find_next(versions, NULL);
+ ci;
+ ci = cf_item_find_next(versions, ci)) {
+ len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci)));
+ if (max < len) max = len;
+ }
+
+
+ for (ci = cf_item_find_next(features, NULL);
+ ci;
+ ci = cf_item_find_next(features, ci)) {
+ char const *attr;
+
+ cp = cf_item_to_pair(ci);
+ attr = cf_pair_attr(cp);
+
+ DEBUG2(" %s%.*s : %s", attr,
+ (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
+ }
+
+ talloc_free(features);
+
+ DEBUG2("Server core libs:");
+
+ for (ci = cf_item_find_next(versions, NULL);
+ ci;
+ ci = cf_item_find_next(versions, ci)) {
+ char const *attr;
+
+ cp = cf_item_to_pair(ci);
+ attr = cf_pair_attr(cp);
+
+ DEBUG2(" %s%.*s : %s", attr,
+ (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
+ }
+
+ talloc_free(versions);
+
+ DEBUG2("Endianness:");
+#if defined(FR_LITTLE_ENDIAN)
+ DEBUG2(" little");
+#elif defined(FR_BIG_ENDIAN)
+ DEBUG2(" big");
+#else
+ DEBUG2(" unknown");
+#endif
+
+ DEBUG2("Compilation flags:");
+#ifdef BUILT_WITH_CPPFLAGS
+ DEBUG2(" cppflags : " BUILT_WITH_CPPFLAGS);
+#endif
+#ifdef BUILT_WITH_CFLAGS
+ DEBUG2(" cflags : " BUILT_WITH_CFLAGS);
+#endif
+#ifdef BUILT_WITH_LDFLAGS
+ DEBUG2(" ldflags : " BUILT_WITH_LDFLAGS);
+#endif
+#ifdef BUILT_WITH_LIBS
+ DEBUG2(" libs : " BUILT_WITH_LIBS);
+#endif
+ DEBUG2(" ");
+ }
+ INFO("FreeRADIUS Version " RADIUSD_VERSION_STRING);
+ INFO("Copyright (C) 1999-2022 The FreeRADIUS server project and contributors");
+ INFO("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A");
+ INFO("PARTICULAR PURPOSE");
+ INFO("You may redistribute copies of FreeRADIUS under the terms of the");
+ INFO("GNU General Public License");
+ INFO("For more information about these matters, see the file named COPYRIGHT");
+
+ fflush(NULL);
+}
+