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