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: f3b7c61a1d866136f5bb9fe819b2c00a82ed1e54 $
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: f3b7c61a1d866136f5bb9fe819b2c00a82ed1e54 $")
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-pcre",
196#ifdef HAVE_REGEX_PCRE
197 true
198#else
199 false
200#endif
201 );
202
203 dependency_feature_add(cs, "regex-pcre2",
204#ifdef HAVE_REGEX_PCRE2
205 true
206#else
207 false
208#endif
209 );
210
211#ifdef HAVE_REGEX_POSIX
212 dependency_feature_add(cs, "regex-posix", true);
213 dependency_feature_add(cs, "regex-posix-extended",
214# ifdef HAVE_REG_EXTENDED
215 true
216# else
217 false
218# endif
219 );
220#else
221 dependency_feature_add(cs, "regex-posix", false);
222 dependency_feature_add(cs, "regex-posix-extended", false);
223#endif
224
225 dependency_feature_add(cs, "regex-binsafe",
226#if defined(HAVE_REGNEXEC) || defined(HAVE_REGEX_PCRE) || defined(HAVE_REGEX_PCRE2)
227 true
228#else
229 false
230#endif
231 );
232
233 dependency_feature_add(cs, "stats",
234#ifdef WITH_STATS
235 true
236#else
237 false
238#endif
239 );
240
241 dependency_feature_add(cs, "systemd",
242#ifdef HAVE_SYSTEMD
243 true
244#else
245 false
246#endif
247 );
248
249 dependency_feature_add(cs, "tls",
250#ifdef WITH_TLS
251 true
252#else
253 false
254#endif
255 );
256
257 dependency_feature_add(cs, "socket-timestamps",
258#ifdef SO_TIMESTAMP
259 true
260#else
261 false
262#endif
263 );
264
265 dependency_feature_add(cs, "developer",
266#ifndef NDEBUG
267 true
268#else
269 false
270#endif
271 );
272
273 dependency_feature_add(cs, "address-sanitizer",
274#ifdef __SANITIZE_ADDRESS__
275 true
276#else
277 false
278#endif
279 );
280
281#ifdef HAVE_SANITIZER_COMMON_INTERFACE_DEFS_H
282 /*
283 * Are we running under Leak Sanitizer
284 */
285 dependency_feature_add(cs, "runtime-lsan", (fr_get_lsan_state() == 1));
286#endif
287
288#ifdef HAVE_GPERFTOOLS_PROFILER_H
289 {
290 struct ProfilerState state;
291
292 ProfilerGetCurrentState(&state);
293 /*
294 * Were we build with gperftools support,
295 * and is it currently enabled.
296 */
297 dependency_feature_add(cs, "runtime-gperftools", state.enabled);
298 }
299#endif
300
301#ifdef HAVE_VALGRIND_H
302 /*
303 * Are we running under valgrind
304 */
305 dependency_feature_add(cs, "runtime-valgrind", RUNNING_ON_VALGRIND);
306#endif
307
308 /*
309 * Are we running under a debugger
310 */
311 dependency_feature_add(cs, "runtime-debugger", (fr_get_debug_state() == 1));
312}
313
314#ifdef EVFILT_LIBKQUEUE
315static void dependency_libqueue_version(CONF_SECTION *cs)
316{
317 int kqfd, ret;
318 struct kevent kev, receipt;
319
320 kqfd = kqueue();
321 if (kqfd < 0) {
322 kqueue_error:
323 dependency_version_number_add(cs, "libkqueue", fr_syserror(errno));
324 return;
325 }
326
327 EV_SET(&kev, 0, EVFILT_LIBKQUEUE, EV_ADD, NOTE_VERSION_STR, 0, NULL);
328 ret = kevent(kqfd, &kev, 1, &receipt, 1, &(struct timespec){});
329 close(kqfd);
330 if (ret != 1) goto kqueue_error;
331
332 dependency_version_number_add(cs, "libkqueue", (char *)receipt.udata);
333}
334#endif
335
336/** Initialise core version flags
337 *
338 * @param cs Where to add the CONF_PAIRS, if null pairs will be added
339 * to the 'version' section of the main config.
340 */
342{
343 char buffer[128];
344
346
348
349 snprintf(buffer, sizeof(buffer), "%i.%i.*", talloc_version_major(), talloc_version_minor());
351
352#ifdef WITH_TLS
354#endif
355
356#ifdef HAVE_REGEX
357# ifdef HAVE_REGEX_PCRE2
358 snprintf(buffer, sizeof(buffer), "%i.%i (%s) - retrieved at build time", PCRE2_MAJOR, PCRE2_MINOR, STRINGIFY(PCRE2_DATE));
360# elif defined(HAVE_REGEX_PCRE)
361 dependency_version_number_add(cs, "pcre", pcre_version());
362# endif
363#endif
364
365#ifdef EVFILT_LIBKQUEUE
366 dependency_libqueue_version(cs);
367#endif
368}
369
370static char const *spaces = " "; /* 40 */
371
372/*
373 * Display the revision number for this program
374 */
376{
377 CONF_SECTION *features, *versions;
378 CONF_ITEM *ci;
379 CONF_PAIR *cp;
380
381 if (DEBUG_ENABLED3) {
382 int max = 0, len;
383
384 MEM(features = cf_section_alloc(NULL, NULL, "feature", NULL));
385 dependency_features_init(features);
386
387 MEM(versions = cf_section_alloc(NULL, NULL, "version", NULL));
389
390 DEBUG2("Server was built with:");
391
392 for (ci = cf_item_next(features, NULL);
393 ci;
394 ci = cf_item_next(features, ci)) {
395 len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci)));
396 if (max < len) max = len;
397 }
398
399 for (ci = cf_item_next(versions, NULL);
400 ci;
401 ci = cf_item_next(versions, ci)) {
402 len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci)));
403 if (max < len) max = len;
404 }
405
406 for (ci = cf_item_next(features, NULL);
407 ci;
408 ci = cf_item_next(features, ci)) {
409 char const *attr;
410
411 cp = cf_item_to_pair(ci);
412 attr = cf_pair_attr(cp);
413
414 DEBUG2(" %s%.*s : %s", attr,
415 (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
416 }
417
418 DEBUG2("Server core libs:");
419
420 for (ci = cf_item_next(versions, NULL);
421 ci;
422 ci = cf_item_next(versions, ci)) {
423 char const *attr;
424
425 cp = cf_item_to_pair(ci);
426 attr = cf_pair_attr(cp);
427
428 DEBUG2(" %s%.*s : %s", attr,
429 (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
430 }
431
432 talloc_free(features);
433 talloc_free(versions);
434
435 DEBUG2("Endianness:");
436#ifdef WORDS_BIGENDIAN
437 DEBUG2(" big");
438#else
439 DEBUG2(" little");
440#endif
441
442 DEBUG2("Compilation flags:");
443#ifdef BUILT_WITH_CPPFLAGS
444 DEBUG2(" cppflags : " BUILT_WITH_CPPFLAGS);
445#endif
446#ifdef BUILT_WITH_CFLAGS
447 DEBUG2(" cflags : " BUILT_WITH_CFLAGS);
448#endif
449#ifdef BUILT_WITH_LDFLAGS
450 DEBUG2(" ldflags : " BUILT_WITH_LDFLAGS);
451#endif
452#ifdef BUILT_WITH_LIBS
453 DEBUG2(" libs : " BUILT_WITH_LIBS);
454#endif
455 DEBUG2(" ");
456 }
457 INFO("Copyright 1999-2024 The FreeRADIUS server project and contributors");
458 INFO("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A");
459 INFO("PARTICULAR PURPOSE");
460 INFO("You may redistribute copies of FreeRADIUS under the terms of the");
461 INFO("GNU General Public License");
462 INFO("For more information about these matters, see the file named COPYRIGHT");
463
464 fflush(NULL);
465}
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:261
int fr_get_debug_state(void)
Definition debug.c:509
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:156
#define MEM(x)
Definition debug.h:36
void dependency_version_print(void)
Definition dependency.c:375
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:341
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:370
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