The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
dependency.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: b8af05290cd0c48b4a424ac6df6d21077267f668 $
19 * @file src/lib/server/dependency.c
20 * @brief Check version numbers of dependencies.
21 *
22 * @copyright 1999-2014 The FreeRADIUS server project
23 * @copyright 2012 Alan DeKok (aland@freeradius.org)
24 * @copyright 2000 Chris Parker (cparker@starnetusa.com)
25 */
26
27RCSID("$Id: b8af05290cd0c48b4a424ac6df6d21077267f668 $")
28
29#include <freeradius-devel/util/regex.h>
30#include <freeradius-devel/util/syserror.h>
31
32#include <freeradius-devel/server/cf_util.h>
33#include <freeradius-devel/server/dependency.h>
34#include <freeradius-devel/server/log.h>
35
36USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
37
39char const *radiusd_version_short = STRINGIFY(RADIUSD_VERSION_MAJOR) "." STRINGIFY(RADIUSD_VERSION_MINOR) "." STRINGIFY(RADIUSD_VERSION_INCRM);
40
41static CONF_SECTION *default_feature_cs; //!< Default configuration section to add features to.
42static CONF_SECTION *default_version_cs; //!< Default configuration section to add features to.
43
44#include <freeradius-devel/tls/openssl_user_macros.h>
45
46#ifdef WITH_TLS
47# include <freeradius-devel/tls/version.h>
48# include <openssl/crypto.h>
49# include <openssl/opensslv.h>
50#endif
51
52#ifdef HAVE_GPERFTOOLS_PROFILER_H
53# include <gperftools/profiler.h>
54#endif
55
56#ifdef HAVE_VALGRIND_VALGRIND_H
57# include <valgrind/valgrind.h>
58#endif
59
60/** Check if the application linking to the library has the correct magic number
61 *
62 * @param magic number as defined by RADIUSD_MAGIC_NUMBER
63 * @returns
64 * - 0 on success.
65 * - -1 on prefix mismatch.
66 * - -2 on version mismatch.
67 * - -3 on commit mismatch.
68 */
69int rad_check_lib_magic(uint64_t magic)
70{
71 if (MAGIC_PREFIX(magic) != MAGIC_PREFIX(libmagic)) {
72 ERROR("Application and libfreeradius-server magic number (prefix) mismatch."
73 " application: %x library: %x",
75 return -1;
76 }
77
78 if (MAGIC_VERSION(magic) != MAGIC_VERSION(libmagic)) {
79 ERROR("Application and libfreeradius-server magic number (version) mismatch."
80 " application: %lx library: %lx",
81 (unsigned long) MAGIC_VERSION(magic), (unsigned long) MAGIC_VERSION(libmagic));
82 return -2;
83 }
84
85 if (MAGIC_COMMIT(magic) != MAGIC_COMMIT(libmagic)) {
86 ERROR("Application and libfreeradius-server magic number (commit) mismatch."
87 " application: %lx library: %lx",
88 (unsigned long) MAGIC_COMMIT(magic), (unsigned long) MAGIC_COMMIT(libmagic));
89 return -3;
90 }
91
92 return 0;
93}
94
95/** Add a feature flag to the main configuration
96 *
97 * Add a feature flag (yes/no) to the 'feature' subsection
98 * off the main config.
99 *
100 * This allows the user to create configurations that work with
101 * across multiple environments.
102 *
103 * @param[in] cs to add feature pair to. May be NULL
104 * in which case the cs passed to
105 * dependency_feature_init() is used.
106 * @param[in] name of feature.
107 * @param[in] enabled Whether the feature is present/enabled.
108 * @return
109 * - 0 on success.
110 * - -1 on failure.
111 */
112int dependency_feature_add(CONF_SECTION *cs, char const *name, bool enabled)
113{
114 if (!cs) cs = default_feature_cs;
115 if (!fr_cond_assert_msg(cs, "dependency_features_init() must be called before calling %s", __FUNCTION__)) {
116 return -1;
117 }
118
119 if (!cf_pair_find(cs, name)) {
120 CONF_PAIR *cp;
121
122 cp = cf_pair_alloc(cs, name, enabled ? "yes" : "no",
124 if (!cp) return -1;
125 }
126
127 return 0;
128}
129
130/** Add a library/server version pair to the main configuration
131 *
132 * Add a version number to the 'version' subsection off the main
133 * config.
134 *
135 * Because of the optimisations in the configuration parser, these
136 * may be checked using regular expressions without a performance
137 * penalty.
138 *
139 * The version pairs are there primarily to work around defects
140 * in libraries or the server.
141 *
142 * @param[in] cs to add feature pair to. May be NULL
143 * in which case the cs passed to
144 * dependency_feature_init() is used.
145 * @param[in] name of library or feature.
146 * @param[in] version Humanly readable version text.
147 * @return
148 * - 0 on success.
149 * - -1 on failure.
150 */
151int dependency_version_number_add(CONF_SECTION *cs, char const *name, char const *version)
152{
153 CONF_PAIR *old;
154
155 if (!cs) cs = default_version_cs;
156 if (!fr_cond_assert_msg(cs, "dependency_version_numbers_init() must be called before calling %s", __FUNCTION__)) {
157 return -1;
158 }
159
160 old = cf_pair_find(cs, name);
161 if (!old) {
162 CONF_PAIR *cp;
163
165 if (!cp) return -1;
166
167 } else {
168 WARN("Replacing user version.%s (%s) with %s", name, cf_pair_value(old), version);
169
170 cf_pair_replace(cs, old, version);
171 }
172
173 return 0;
174}
175
176
177/** Initialise core feature flags
178 *
179 * @param cs Where to add the CONF_PAIRS, if null pairs will be added
180 * to the 'feature' section of the main config.
181 */
183{
185
186 dependency_feature_add(cs, "cap",
187#ifdef HAVE_CAPABILITY_H
188 true
189#else
190 false
191#endif
192 );
193
194 dependency_feature_add(cs, "regex-pcre2",
195#ifdef HAVE_REGEX_PCRE2
196 true
197#else
198 false
199#endif
200 );
201
202#ifdef HAVE_REGEX_POSIX
203 dependency_feature_add(cs, "regex-posix", true);
204 dependency_feature_add(cs, "regex-posix-extended",
205# ifdef HAVE_REG_EXTENDED
206 true
207# else
208 false
209# endif
210 );
211#else
212 dependency_feature_add(cs, "regex-posix", false);
213 dependency_feature_add(cs, "regex-posix-extended", false);
214#endif
215
216 dependency_feature_add(cs, "regex-binsafe",
217#if defined(HAVE_REGNEXEC) || defined(HAVE_REGEX_PCRE2)
218 true
219#else
220 false
221#endif
222 );
223
224 dependency_feature_add(cs, "stats",
225#ifdef WITH_STATS
226 true
227#else
228 false
229#endif
230 );
231
232 dependency_feature_add(cs, "systemd",
233#ifdef HAVE_SYSTEMD
234 true
235#else
236 false
237#endif
238 );
239
240 dependency_feature_add(cs, "tls",
241#ifdef WITH_TLS
242 true
243#else
244 false
245#endif
246 );
247
248 dependency_feature_add(cs, "socket-timestamps",
249#ifdef SO_TIMESTAMP
250 true
251#else
252 false
253#endif
254 );
255
256 dependency_feature_add(cs, "developer",
257#ifndef NDEBUG
258 true
259#else
260 false
261#endif
262 );
263
264 dependency_feature_add(cs, "address-sanitizer",
265#ifdef __SANITIZE_ADDRESS__
266 true
267#else
268 false
269#endif
270 );
271
272#ifdef HAVE_SANITIZER_COMMON_INTERFACE_DEFS_H
273 /*
274 * Are we running under Leak Sanitizer
275 */
276 dependency_feature_add(cs, "runtime-lsan", (fr_get_lsan_state() == 1));
277#endif
278
279#ifdef HAVE_GPERFTOOLS_PROFILER_H
280 {
281 struct ProfilerState state;
282
283 ProfilerGetCurrentState(&state);
284 /*
285 * Were we build with gperftools support,
286 * and is it currently enabled.
287 */
288 dependency_feature_add(cs, "runtime-gperftools", state.enabled);
289 }
290#endif
291
292#ifdef HAVE_VALGRIND_H
293 /*
294 * Are we running under valgrind
295 */
296 dependency_feature_add(cs, "runtime-valgrind", RUNNING_ON_VALGRIND);
297#endif
298
299 /*
300 * Are we running under a debugger
301 */
302 dependency_feature_add(cs, "runtime-debugger", (fr_get_debug_state() == 1));
303}
304
305#ifdef EVFILT_LIBKQUEUE
306static void dependency_libqueue_version(CONF_SECTION *cs)
307{
308 int kqfd, ret;
309 struct kevent kev, receipt;
310
311 kqfd = kqueue();
312 if (kqfd < 0) {
313 kqueue_error:
314 dependency_version_number_add(cs, "libkqueue", fr_syserror(errno));
315 return;
316 }
317
318 EV_SET(&kev, 0, EVFILT_LIBKQUEUE, EV_ADD, NOTE_VERSION_STR, 0, NULL);
319 ret = kevent(kqfd, &kev, 1, &receipt, 1, &(struct timespec){});
320 close(kqfd);
321 if (ret != 1) goto kqueue_error;
322
323 dependency_version_number_add(cs, "libkqueue", (char *)receipt.udata);
324}
325#endif
326
327/** Initialise core version flags
328 *
329 * @param cs Where to add the CONF_PAIRS, if null pairs will be added
330 * to the 'version' section of the main config.
331 */
333{
334 char buffer[128];
335
337
339
340 snprintf(buffer, sizeof(buffer), "%i.%i.*", talloc_version_major(), talloc_version_minor());
342
343#ifdef WITH_TLS
345#endif
346
347#ifdef HAVE_REGEX
348# ifdef HAVE_REGEX_PCRE2
349 snprintf(buffer, sizeof(buffer), "%i.%i (%s) - retrieved at build time", PCRE2_MAJOR, PCRE2_MINOR, STRINGIFY(PCRE2_DATE));
351# endif
352#endif
353
354#ifdef EVFILT_LIBKQUEUE
355 dependency_libqueue_version(cs);
356#endif
357}
358
359static char const *spaces = " "; /* 40 */
360
361/*
362 * Display the revision number for this program
363 */
365{
366 CONF_SECTION *features, *versions;
367 CONF_ITEM *ci;
368 CONF_PAIR *cp;
369
370 if (DEBUG_ENABLED3) {
371 int max = 0, len;
372
373 MEM(features = cf_section_alloc(NULL, NULL, "feature", NULL));
374 dependency_features_init(features);
375
376 MEM(versions = cf_section_alloc(NULL, NULL, "version", NULL));
378
379 DEBUG2("Server was built with:");
380
381 for (ci = cf_item_next(features, NULL);
382 ci;
383 ci = cf_item_next(features, ci)) {
384 len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci)));
385 if (max < len) max = len;
386 }
387
388 for (ci = cf_item_next(versions, NULL);
389 ci;
390 ci = cf_item_next(versions, ci)) {
391 len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci)));
392 if (max < len) max = len;
393 }
394
395 for (ci = cf_item_next(features, NULL);
396 ci;
397 ci = cf_item_next(features, ci)) {
398 char const *attr;
399
400 cp = cf_item_to_pair(ci);
401 attr = cf_pair_attr(cp);
402
403 DEBUG2(" %s%.*s : %s", attr,
404 (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
405 }
406
407 DEBUG2("Server core libs:");
408
409 for (ci = cf_item_next(versions, NULL);
410 ci;
411 ci = cf_item_next(versions, ci)) {
412 char const *attr;
413
414 cp = cf_item_to_pair(ci);
415 attr = cf_pair_attr(cp);
416
417 DEBUG2(" %s%.*s : %s", attr,
418 (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
419 }
420
421 talloc_free(features);
422 talloc_free(versions);
423
424 DEBUG2("Endianness:");
425#ifdef WORDS_BIGENDIAN
426 DEBUG2(" big");
427#else
428 DEBUG2(" little");
429#endif
430
431 DEBUG2("Compilation flags:");
432#ifdef BUILT_WITH_CPPFLAGS
433 DEBUG2(" cppflags : %s", BUILT_WITH_CPPFLAGS);
434#endif
435#ifdef BUILT_WITH_CFLAGS
436 DEBUG2(" cflags : %s", BUILT_WITH_CFLAGS);
437#endif
438#ifdef BUILT_WITH_LDFLAGS
439 DEBUG2(" ldflags : %s", BUILT_WITH_LDFLAGS);
440#endif
441#ifdef BUILT_WITH_LIBS
442 DEBUG2(" libs : %s", BUILT_WITH_LIBS);
443#endif
444 DEBUG2(" ");
445 }
446#ifdef WITH_VERIFY_PTR
447 WARN(" ");
448 WARN("#######################################################################");
449 WARN("# ");
450 WARN("# The server was built with the 'WITH_VERIFY_PTR' flag set. This is a");
451 WARN("# developer-only build option that DRASTICALLY slows down the server.");
452 WARN("# If you are using the server in a production environment, you will see");
453 WARN("# significantly improved performance (3x-4x) by re-running 'configure'");
454 WARN("# with the flag '--disable-developer', and then re-building and");
455 WARN("# re-installing the server.");
456 WARN("# ");
457 WARN("#######################################################################");
458 WARN(" ");
459#endif
460
461 INFO("Copyright 1999-2026 The FreeRADIUS server project and contributors");
462 INFO("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A");
463 INFO("PARTICULAR PURPOSE");
464 INFO("You may redistribute copies of FreeRADIUS under the terms of the");
465 INFO("GNU General Public License");
466 INFO("For more information about these matters, see the file named COPYRIGHT");
467 INFO(" ");
468 INFO("FreeRADIUS is developed, maintained, and supported by InkBridge Networks.");
469 INFO("For commercial support, please email sales@inkbridgenetworks.com");
470 INFO("https://inkbridgenetworks.com/");
471
472 fflush(NULL);
473}
static int const char char buffer[256]
Definition acutest.h:576
#define USES_APPLE_DEPRECATED_API
Definition build.h:547
#define RCSID(id)
Definition build.h:560
#define STRINGIFY(x)
Definition build.h:216
Common header for all CONF_* types.
Definition cf_priv.h:54
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:77
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
Allocate a CONF_PAIR.
Definition cf_util.c:1444
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1597
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:675
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1756
int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value)
Replace pair value in a given section with the given value.
Definition cf_util.c:1518
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1740
#define cf_item_next(_parent, _curr)
Definition cf_util.h:94
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:201
int fr_get_lsan_state(void)
Definition debug.c:245
int fr_get_debug_state(void)
Definition debug.c:493
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:189
#define MEM(x)
Definition debug.h:38
void dependency_version_print(void)
Definition dependency.c:364
void dependency_features_init(CONF_SECTION *cs)
Initialise core feature flags.
Definition dependency.c:182
int rad_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition dependency.c:69
static USES_APPLE_DEPRECATED_API uint64_t libmagic
Definition dependency.c:38
char const * radiusd_version_short
Definition dependency.c:39
void dependency_version_numbers_init(CONF_SECTION *cs)
Initialise core version flags.
Definition dependency.c:332
int dependency_feature_add(CONF_SECTION *cs, char const *name, bool enabled)
Add a feature flag to the main configuration.
Definition dependency.c:112
int dependency_version_number_add(CONF_SECTION *cs, char const *name, char const *version)
Add a library/server version pair to the main configuration.
Definition dependency.c:151
static CONF_SECTION * default_feature_cs
Default configuration section to add features to.
Definition dependency.c:41
static char const * spaces
Definition dependency.c:359
static CONF_SECTION * default_version_cs
Default configuration section to add features to.
Definition dependency.c:42
#define ERROR(fmt,...)
Definition dhcpclient.c:40
#define RUNNING_ON_VALGRIND
Definition dl.c:40
Definition dwarf.c:424
talloc_free(hp)
#define DEBUG_ENABLED3
True if global debug level 1-3 messages are enabled.
Definition log.h:264
#define DEBUG2(fmt,...)
#define WARN(fmt,...)
#define INFO(fmt,...)
Definition radict.c:63
static char const * name
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
void * state
Definition testlib.c:46
char const * fr_openssl_version_basic(void)
Definition version.c:250
@ T_SINGLE_QUOTED_STRING
Definition token.h:120
@ T_BARE_WORD
Definition token.h:118
@ T_OP_EQ
Definition token.h:81
#define MAGIC_PREFIX(_x)
Definition version.h:82
#define MAGIC_VERSION(_x)
Definition version.h:83
#define MAGIC_COMMIT(_x)
Definition version.h:84
#define RADIUSD_MAGIC_NUMBER
Definition version.h:81