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