2 * version.c Print version number and exit.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 1999-2014 The FreeRADIUS server project
21 * Copyright 2012 Alan DeKok <aland@ox.org>
22 * Copyright 2000 Chris Parker <cparker@starnetusa.com>
27 #include <freeradius-devel/radiusd.h>
28 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
30 static uint64_t libmagic = RADIUSD_MAGIC_NUMBER;
31 char const *radiusd_version_short = RADIUSD_VERSION_STRING;
33 #ifdef HAVE_OPENSSL_CRYPTO_H
34 # include <openssl/crypto.h>
35 # include <openssl/opensslv.h>
37 static long ssl_built = OPENSSL_VERSION_NUMBER;
39 /** Check built and linked versions of OpenSSL match
41 * OpenSSL version number consists of:
42 * MNNFFPPS: major minor fix patch status
44 * Where status >= 0 && < 10 means beta, and status 10 means release.
46 * Startup check for whether the linked version of OpenSSL matches the
47 * version the server was built against.
49 * @return 0 if ok, else -1
51 int ssl_check_consistency(void)
55 return 0; /* Painless Security customization */
57 ssl_linked = SSLeay();
60 * Status mismatch always triggers error.
62 if ((ssl_linked & 0x0000000f) != (ssl_built & 0x0000000f)) {
64 ERROR("libssl version mismatch. built: %lx linked: %lx",
65 (unsigned long) ssl_built,
66 (unsigned long) ssl_linked);
72 * Use the OpenSSH approach and relax fix checks after version
73 * 1.0.0 and only allow moving backwards within a patch
76 if (ssl_built & 0xf0000000) {
77 if ((ssl_built & 0xfffff000) != (ssl_linked & 0xfffff000) ||
78 (ssl_built & 0x00000ff0) > (ssl_linked & 0x00000ff0)) goto mismatch;
80 * Before 1.0.0 we require the same major minor and fix version
81 * and ignore the patch number.
83 } else if ((ssl_built & 0xfffff000) != (ssl_linked & 0xfffff000)) goto mismatch;
88 /** Convert a version number to a text string
90 * @note Not thread safe.
92 * @param v version to convert.
93 * @return pointer to a static buffer containing the version string.
95 char const *ssl_version_by_num(uint32_t v)
97 /* 2 (%s) + 1 (.) + 2 (%i) + 1 (.) + 2 (%i) + 1 (c) + 8 (%s) + \0 */
98 static char buffer[18];
101 p += sprintf(p, "%u.%u.%u",
102 (0xf0000000 & v) >> 28,
103 (0x0ff00000 & v) >> 20,
104 (0x000ff000 & v) >> 12);
106 if ((0x00000ff0 & v) >> 4) {
107 *p++ = (char) (0x60 + ((0x00000ff0 & v) >> 4));
115 if ((0x0000000f & v) == 0) {
120 } else if ((0x0000000f & v) <= 14) {
121 sprintf(p, "beta %u", 0x0000000f & v);
123 strcpy(p, "release");
129 /** Return the linked SSL version number as a string
131 * @return pointer to a static buffer containing the version string.
133 char const *ssl_version_num(void)
137 ssl_linked = SSLeay();
138 return ssl_version_by_num((uint32_t)ssl_linked);
141 /** Convert two openssl version numbers into a range string
143 * @note Not thread safe.
145 * @param low version to convert.
146 * @param high version to convert.
147 * @return pointer to a static buffer containing the version range string.
149 char const *ssl_version_range(uint32_t low, uint32_t high)
151 /* 12 (version) + 3 ( - ) + 12 (version) */
152 static char buffer[28];
155 p += strlcpy(p, ssl_version_by_num(low), sizeof(buffer));
156 p += strlcpy(p, " - ", sizeof(buffer) - (p - buffer));
157 strlcpy(p, ssl_version_by_num(high), sizeof(buffer) - (p - buffer));
162 /** Print the current linked version of Openssl
164 * Print the currently linked version of the OpenSSL library.
166 * @note Not thread safe.
167 * @return pointer to a static buffer containing libssl version information.
169 char const *ssl_version(void)
171 static char buffer[256];
173 uint32_t v = SSLeay();
175 snprintf(buffer, sizeof(buffer), "%s 0x%.8x (%s)",
176 SSLeay_version(SSLEAY_VERSION), /* Not all builds include a useful version number */
178 ssl_version_by_num(v));
183 int ssl_check_consistency(void) {
187 char const *ssl_version_num(void)
192 char const *ssl_version()
196 #endif /* ifdef HAVE_OPENSSL_CRYPTO_H */
198 /** Check if the application linking to the library has the correct magic number
200 * @param magic number as defined by RADIUSD_MAGIC_NUMBER
201 * @returns 0 on success, -1 on prefix mismatch, -2 on version mismatch -3 on commit mismatch.
203 int rad_check_lib_magic(uint64_t magic)
205 if (MAGIC_PREFIX(magic) != MAGIC_PREFIX(libmagic)) {
206 ERROR("Application and libfreeradius-server magic number (prefix) mismatch."
207 " application: %x library: %x",
208 MAGIC_PREFIX(magic), MAGIC_PREFIX(libmagic));
212 if (MAGIC_VERSION(magic) != MAGIC_VERSION(libmagic)) {
213 ERROR("Application and libfreeradius-server magic number (version) mismatch."
214 " application: %lx library: %lx",
215 (unsigned long) MAGIC_VERSION(magic), (unsigned long) MAGIC_VERSION(libmagic));
219 if (MAGIC_COMMIT(magic) != MAGIC_COMMIT(libmagic)) {
220 ERROR("Application and libfreeradius-server magic number (commit) mismatch."
221 " application: %lx library: %lx",
222 (unsigned long) MAGIC_COMMIT(magic), (unsigned long) MAGIC_COMMIT(libmagic));
229 /** Add a feature flag to the main configuration
231 * Add a feature flag (yes/no) to the 'feature' subsection
232 * off the main config.
234 * This allows the user to create configurations that work with
235 * across multiple environments.
237 * @param cs to add feature pair to.
238 * @param name of feature.
239 * @param enabled Whether the feature is present/enabled.
240 * @return 0 on success else -1.
242 int version_add_feature(CONF_SECTION *cs, char const *name, bool enabled)
246 if (!cf_pair_find(cs, name)) {
249 cp = cf_pair_alloc(cs, name, enabled ? "yes" : "no",
250 T_OP_SET, T_BARE_WORD, T_BARE_WORD);
258 /** Add a library/server version pair to the main configuration
260 * Add a version number to the 'version' subsection off the main
263 * Because of the optimisations in the configuration parser, these
264 * may be checked using regular expressions without a performance
267 * The version pairs are there primarily to work around defects
268 * in libraries or the server.
270 * @param cs to add feature pair to.
271 * @param name of library or feature.
272 * @param version Humanly readable version text.
273 * @return 0 on success else -1.
275 int version_add_number(CONF_SECTION *cs, char const *name, char const *version)
281 old = cf_pair_find(cs, name);
285 cp = cf_pair_alloc(cs, name, version, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING);
290 WARN("Replacing user version.%s (%s) with %s", name, cf_pair_value(old), version);
292 cf_pair_replace(cs, old, version);
299 /** Initialise core feature flags
301 * @param cs Where to add the CONF_PAIRS, if null pairs will be added
302 * to the 'feature' section of the main config.
304 void version_init_features(CONF_SECTION *cs)
306 version_add_feature(cs, "accounting",
307 #ifdef WITH_ACCOUNTING
314 version_add_feature(cs, "authentication", true);
316 version_add_feature(cs, "ascend-binary-attributes",
317 #ifdef WITH_ASCEND_BINARY
324 version_add_feature(cs, "coa",
333 version_add_feature(cs, "control-socket",
334 #ifdef WITH_COMMAND_SOCKET
342 version_add_feature(cs, "detail",
350 version_add_feature(cs, "dhcp",
358 version_add_feature(cs, "dynamic-clients",
359 #ifdef WITH_DYNAMIC_CLIENTS
366 version_add_feature(cs, "osfc2",
374 version_add_feature(cs, "proxy",
382 version_add_feature(cs, "regex-pcre",
390 #if !defined(HAVE_PCRE) && defined(HAVE_REGEX)
391 version_add_feature(cs, "regex-posix", true);
392 version_add_feature(cs, "regex-posix-extended",
393 # ifdef HAVE_REG_EXTENDED
400 version_add_feature(cs, "regex-posix", false);
401 version_add_feature(cs, "regex-posix-extended", false);
404 version_add_feature(cs, "session-management",
405 #ifdef WITH_SESSION_MGMT
412 version_add_feature(cs, "stats",
420 version_add_feature(cs, "tcp",
428 version_add_feature(cs, "threads",
436 version_add_feature(cs, "tls",
444 version_add_feature(cs, "unlang",
452 version_add_feature(cs, "vmps",
460 version_add_feature(cs, "developer",
469 /** Initialise core version flags
471 * @param cs Where to add the CONF_PAIRS, if null pairs will be added
472 * to the 'version' section of the main config.
474 void version_init_numbers(CONF_SECTION *cs)
478 version_add_number(cs, "freeradius-server", radiusd_version_short);
480 snprintf(buffer, sizeof(buffer), "%i.%i.*", talloc_version_major(), talloc_version_minor());
481 version_add_number(cs, "talloc", buffer);
483 version_add_number(cs, "ssl", ssl_version_num());
485 #if defined(HAVE_REGEX) && defined(HAVE_PCRE)
486 version_add_number(cs, "pcre", pcre_version());
490 static char const *spaces = " "; /* 40 */
493 * Display the revision number for this program
495 void version_print(void)
497 CONF_SECTION *features, *versions;
501 if (DEBUG_ENABLED3) {
504 MEM(features = cf_section_alloc(NULL, "feature", NULL));
505 version_init_features(features);
507 MEM(versions = cf_section_alloc(NULL, "version", NULL));
508 version_init_numbers(versions);
510 DEBUG2("Server was built with: ");
512 for (ci = cf_item_find_next(features, NULL);
514 ci = cf_item_find_next(features, ci)) {
515 len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci)));
516 if (max < len) max = len;
519 for (ci = cf_item_find_next(versions, NULL);
521 ci = cf_item_find_next(versions, ci)) {
522 len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci)));
523 if (max < len) max = len;
527 for (ci = cf_item_find_next(features, NULL);
529 ci = cf_item_find_next(features, ci)) {
532 cp = cf_item_to_pair(ci);
533 attr = cf_pair_attr(cp);
535 DEBUG2(" %s%.*s : %s", attr,
536 (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
539 talloc_free(features);
541 DEBUG2("Server core libs:");
543 for (ci = cf_item_find_next(versions, NULL);
545 ci = cf_item_find_next(versions, ci)) {
548 cp = cf_item_to_pair(ci);
549 attr = cf_pair_attr(cp);
551 DEBUG2(" %s%.*s : %s", attr,
552 (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
555 talloc_free(versions);
557 DEBUG2("Endianness:");
558 #if defined(FR_LITTLE_ENDIAN)
560 #elif defined(FR_BIG_ENDIAN)
566 DEBUG2("Compilation flags:");
567 #ifdef BUILT_WITH_CPPFLAGS
568 DEBUG2(" cppflags : " BUILT_WITH_CPPFLAGS);
570 #ifdef BUILT_WITH_CFLAGS
571 DEBUG2(" cflags : " BUILT_WITH_CFLAGS);
573 #ifdef BUILT_WITH_LDFLAGS
574 DEBUG2(" ldflags : " BUILT_WITH_LDFLAGS);
576 #ifdef BUILT_WITH_LIBS
577 DEBUG2(" libs : " BUILT_WITH_LIBS);
581 INFO("FreeRADIUS Version " RADIUSD_VERSION_STRING);
582 INFO("Copyright (C) 1999-2016 The FreeRADIUS server project and contributors");
583 INFO("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A");
584 INFO("PARTICULAR PURPOSE");
585 INFO("You may redistribute copies of FreeRADIUS under the terms of the");
586 INFO("GNU General Public License");
587 INFO("For more information about these matters, see the file named COPYRIGHT");